]> git.seodisparate.com - c_simple_http/commitdiff
Allow "multi-valued-key-entries" in ParsedConfig
authorStephen Seo <seo.disparate@gmail.com>
Fri, 15 Nov 2024 07:28:31 +0000 (16:28 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 15 Nov 2024 07:28:31 +0000 (16:28 +0900)
This commit begins work on adding more templating features.

src/config.c
src/config.h
src/http_template.c
src/test.c

index 46e19ed6c7b99187e1f0acfcee00304d0b2629d4..14e61065f77c2e26ca58dd946a6b32cec59f174f 100644 (file)
@@ -36,6 +36,23 @@ typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
   const SDArchiverLinkedList *required;
 } C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
 
+void c_simple_http_cleanup_config_value(
+    C_SIMPLE_HTTP_ConfigValue *config_value) {
+  if (config_value) {
+    if (config_value->next) {
+      c_simple_http_cleanup_config_value(config_value->next);
+    }
+    if(config_value->value) {
+      free(config_value->value);
+    }
+    free(config_value);
+  }
+}
+
+void c_simple_http_cleanup_config_value_void_ptr(void *config_value) {
+  c_simple_http_cleanup_config_value(config_value);
+}
+
 int c_simple_http_required_iter_fn(void *data, void *ud) {
   C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
   uint32_t data_str_length = (uint32_t)strlen(data) + 1;
@@ -187,21 +204,26 @@ int internal_check_add_value(uint32_t *state,
     SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
     unsigned char *key = malloc(separating_key_size);
     strncpy((char*)key, separating_key, separating_key_size);
-    unsigned char *value = malloc(*value_idx);
-    memcpy(value, *value_buf, (*value_idx));
-    if (simple_archiver_hash_map_insert(hash_map,
-                                        value,
-                                        key,
-                                        separating_key_size,
-                                        NULL,
-                                        NULL) != 0) {
+    C_SIMPLE_HTTP_ConfigValue *config_value =
+      malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
+    config_value->value = malloc(*value_idx);
+    config_value->next = NULL;
+    memcpy(config_value->value, *value_buf, (*value_idx));
+    if (simple_archiver_hash_map_insert(
+        hash_map,
+        config_value,
+        key,
+        separating_key_size,
+        c_simple_http_cleanup_config_value_void_ptr,
+        NULL) != 0) {
       fprintf(stderr,
         "ERROR: Failed to create hash map for new separating_key "
         "block!\n");
       c_simple_http_clean_up_parsed_config(config);
       config->hash_map = NULL;
       free(key);
-      free(value);
+      free(config_value->value);
+      free(config_value);
       return 1;
     }
 
@@ -212,7 +234,7 @@ int internal_check_add_value(uint32_t *state,
     if (simple_archiver_hash_map_insert(
         config->hash_map,
         wrapper,
-        value,
+        config_value->value,
         (*value_idx),
         c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
         simple_archiver_helper_datastructure_cleanup_nop) != 0) {
@@ -223,7 +245,7 @@ int internal_check_add_value(uint32_t *state,
       c_simple_http_hash_map_wrapper_cleanup(wrapper);
       return 1;
     }
-    simple_archiver_list_add(paths, value,
+    simple_archiver_list_add(paths, config_value->value,
         simple_archiver_helper_datastructure_cleanup_nop);
   } else if (!(*current_separating_key_value)) {
     fprintf(
@@ -254,20 +276,36 @@ int internal_check_add_value(uint32_t *state,
     unsigned char *value = malloc(*value_idx);
     memcpy(value, *value_buf, (*value_idx));
 
-    if (simple_archiver_hash_map_insert(hash_map_wrapper->paths,
-                                        value,
-                                        key,
-                                        *key_idx,
-                                        NULL,
-                                        NULL) != 0) {
-      fprintf(stderr,
-        "ERROR: Internal error failed to insert into hash map with path "
-        "\"%s\"!", (*current_separating_key_value));
-      c_simple_http_clean_up_parsed_config(config);
-      config->hash_map = NULL;
-      free(key);
-      free(value);
-      return 1;
+    // Check if key already exists in wrapped hash-map.
+    C_SIMPLE_HTTP_ConfigValue *config_value =
+      simple_archiver_hash_map_get(hash_map_wrapper->paths, key, *key_idx);
+    if (config_value) {
+      while(config_value->next) {
+        config_value = config_value->next;
+      }
+      config_value->next = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
+      config_value->next->value = (char*)value;
+      config_value->next->next = NULL;
+    } else {
+      config_value = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
+      config_value->value = (char*)value;
+      config_value->next = NULL;
+      if (simple_archiver_hash_map_insert(
+          hash_map_wrapper->paths,
+          config_value,
+          key,
+          *key_idx,
+          c_simple_http_cleanup_config_value_void_ptr,
+          NULL) != 0) {
+        fprintf(stderr,
+          "ERROR: Internal error failed to insert into hash map with path "
+          "\"%s\"!", (*current_separating_key_value));
+        c_simple_http_clean_up_parsed_config(config);
+        config->hash_map = NULL;
+        free(key);
+        free(value);
+        return 1;
+      }
     }
   }
   (*key_idx) = 0;
index 9d7c9e61a81646e237b04d89a4c856a0b6690943..0857b217df018bb7f8c475759dd2ec7c095fc569 100644 (file)
@@ -30,6 +30,9 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
   /// KEY: "/", VALUE: HashMapWrapper struct
   /// KEY: "/inner", VALUE: HashMapWrapper struct
   /// KEY: "/inner/further", VALUE: HashMapWrapper struct
+  ///
+  /// Each HashMapWrapper struct's hash-map has the following:
+  /// KEY: VAR_NAME, VALUE: ConfigValue struct
   union {
     SDArchiverHashMap *paths;
     SDArchiverHashMap *hash_map;
@@ -38,6 +41,15 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
 
 typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper;
 
+typedef struct C_SIMPLE_HTTP_ConfigValue {
+  char *value;
+  struct C_SIMPLE_HTTP_ConfigValue *next;
+} C_SIMPLE_HTTP_ConfigValue;
+
+void c_simple_http_cleanup_config_value(
+  C_SIMPLE_HTTP_ConfigValue *config_value);
+void c_simple_http_cleanup_config_value_void_ptr(void *config_value);
+
 /// Each line in the config should be a key-value pair separated by an equals
 /// sign "=". All whitespace is ignored unless if the value is "quoted". A part
 /// of a string can be "quoted" if it is surrounded by three single-quotes or
index b6510181d0dbb8db8bead1e0ce5cd8e7d5ba0a5f..d91c7f027be8960767f9b78823e7eb486ee2d440 100644 (file)
@@ -26,6 +26,7 @@
 #include <SimpleArchiver/src/helpers.h>
 
 // Local includes.
+#include "config.h"
 #include "helpers.h"
 
 /// Returns 0 if "c_string" ends with "_FILE".
@@ -73,11 +74,11 @@ char *c_simple_http_path_to_generated(
   __attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
   char *html_buf = NULL;
   size_t html_buf_size = 0;
-  const char *html_filename =
+  C_SIMPLE_HTTP_ConfigValue *html_file_value =
     simple_archiver_hash_map_get(wrapped_hash_map->hash_map, "HTML_FILE", 10);
-  if (html_filename) {
+  if (html_file_value && html_file_value->value) {
     __attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
-    FILE *f = fopen(html_filename, "r");
+    FILE *f = fopen(html_file_value->value, "r");
     if (!f) {
       return NULL;
     }
@@ -99,19 +100,19 @@ char *c_simple_http_path_to_generated(
     html_buf[html_file_size] = 0;
     html_buf_size = (size_t)html_file_size;
     if (files_list_out) {
-      char *html_filename_copy = malloc(strlen(html_filename) + 1);
-      strcpy(html_filename_copy, html_filename);
+      char *html_filename_copy = malloc(strlen(html_file_value->value) + 1);
+      strcpy(html_filename_copy, html_file_value->value);
       simple_archiver_list_add(*files_list_out, html_filename_copy, NULL);
     }
   } else {
-    char *stored_html =
+    C_SIMPLE_HTTP_ConfigValue *stored_html_config_value =
       simple_archiver_hash_map_get(wrapped_hash_map->hash_map, "HTML", 5);
-    if (!stored_html) {
+    if (!stored_html_config_value || !stored_html_config_value->value) {
       return NULL;
     }
-    size_t stored_html_size = strlen(stored_html) + 1;
+    size_t stored_html_size = strlen(stored_html_config_value->value) + 1;
     html_buf = malloc(stored_html_size);
-    memcpy(html_buf, stored_html, stored_html_size);
+    memcpy(html_buf, stored_html_config_value->value, stored_html_size);
     html_buf_size = stored_html_size - 1;
   }
 
@@ -177,34 +178,34 @@ char *c_simple_http_path_to_generated(
             html_buf + last_part->extra,
             var_size);
           var[var_size] = 0;
-          const char *value_c_str =
+          C_SIMPLE_HTTP_ConfigValue *config_value =
             simple_archiver_hash_map_get(
               wrapped_hash_map->hash_map,
               var,
               (uint32_t)var_size + 1);
-          if (value_c_str) {
+          if (config_value && config_value->value) {
             if (c_simple_http_internal_ends_with_FILE(var) == 0) {
-              // Load from file specified by "value_c_str".
+              // Load from file specified by "config_value->value".
               __attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
-              FILE *f = fopen(value_c_str, "r");
+              FILE *f = fopen(config_value->value, "r");
               if (!f) {
                 fprintf(stderr, "ERROR Failed to open file \"%s\"!\n",
-                        value_c_str);
+                        config_value->value);
                 return NULL;
               } else if (fseek(f, 0, SEEK_END) != 0) {
                 fprintf(stderr, "ERROR Failed to seek to end of file \"%s\"!\n",
-                        value_c_str);
+                        config_value->value);
                 return NULL;
               }
               long file_size = ftell(f);
               if (file_size <= 0) {
                 fprintf(stderr, "ERROR Size of file \"%s\" is invalid!\n",
-                        value_c_str);
+                        config_value->value);
                 return NULL;
               } else if (fseek(f, 0, SEEK_SET) != 0) {
                 fprintf(stderr, "ERROR Failed to seek to start of file "
                         "\"%s\"!\n",
-                        value_c_str);
+                        config_value->value);
                 return NULL;
               }
               string_part.size = (size_t)file_size + 1;
@@ -217,21 +218,21 @@ char *c_simple_http_path_to_generated(
                         f)
                     != 1) {
                 fprintf(stderr, "ERROR Failed to read from file \"%s\"!\n",
-                        value_c_str);
+                        config_value->value);
                 return NULL;
               }
               string_part.buf[string_part.size - 1] = 0;
               if (files_list_out) {
-                char *variable_filename = malloc(strlen(value_c_str) + 1);
-                strcpy(variable_filename, value_c_str);
+                char *variable_filename = malloc(strlen(config_value->value) + 1);
+                strcpy(variable_filename, config_value->value);
                 simple_archiver_list_add(
                     *files_list_out, variable_filename, NULL);
               }
             } else {
-              // Variable data is "value_c_str".
-              string_part.size = strlen(value_c_str) + 1;
+              // Variable data is "config_value->value".
+              string_part.size = strlen(config_value->value) + 1;
               string_part.buf = malloc(string_part.size);
-              memcpy(string_part.buf, value_c_str, string_part.size);
+              memcpy(string_part.buf, config_value->value, string_part.size);
               string_part.buf[string_part.size - 1] = 0;
               string_part.extra = idx + 1;
             }
index b2382b43a8fa97d9ff1c65c27d97a08a30584568..0699574d46bee2385a282180d39483d56d3cc4d1 100644 (file)
@@ -173,46 +173,53 @@ int main(int argc, char **argv) {
       simple_archiver_hash_map_get(templates.paths, "/", 2);
     ASSERT_TRUE(first_path_map_wrapper);
 
-    const char *value =
+    C_SIMPLE_HTTP_ConfigValue *value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5);
     ASSERT_TRUE(value);
-    ASSERT_STREQ(value, "/");
+    ASSERT_TRUE(value->value);
+    ASSERT_STREQ(value->value, "/");
 
     value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
     ASSERT_TRUE(value);
+    ASSERT_TRUE(value->value);
     // printf("%s\n", value);
-    ASSERT_STREQ(value, " one two three ");
+    ASSERT_STREQ(value->value, " one two three ");
 
     value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
     ASSERT_TRUE(value);
+    ASSERT_TRUE(value->value);
     // printf("%s\n", value);
-    ASSERT_STREQ(value, " \"one two \"three ");
+    ASSERT_STREQ(value->value, " \"one two \"three ");
 
     value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
     ASSERT_TRUE(value);
+    ASSERT_TRUE(value->value);
     // printf("%s\n", value);
-    ASSERT_STREQ(value, "'\"onetwo\"three''");
+    ASSERT_STREQ(value->value, "'\"onetwo\"three''");
 
     value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
     ASSERT_TRUE(value);
+    ASSERT_TRUE(value->value);
     // printf("%s\n", value);
-    ASSERT_STREQ(value, " \"one two \"three ''");
+    ASSERT_STREQ(value->value, " \"one two \"three ''");
 
     value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
     ASSERT_TRUE(value);
+    ASSERT_TRUE(value->value);
     // printf("%s\n", value);
-    ASSERT_STREQ(value, " \"\"\"one two \"\"\"three ");
+    ASSERT_STREQ(value->value, " \"\"\"one two \"\"\"three ");
 
     value =
       simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
     ASSERT_TRUE(value);
+    ASSERT_TRUE(value->value);
     // printf("%s\n", value);
-    ASSERT_STREQ(value, " '''one two '''three ");
+    ASSERT_STREQ(value->value, " '''one two '''three ");
 
     simple_archiver_list_free(&required_names);
     required_names = simple_archiver_list_init();