]> git.seodisparate.com - c_simple_http/commitdiff
config parsing: Handle when config has no endline
authorStephen Seo <seo.disparate@gmail.com>
Wed, 4 Sep 2024 08:32:09 +0000 (17:32 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Wed, 4 Sep 2024 08:37:16 +0000 (17:37 +0900)
Put duplicate code into a macro/defines function.

src/config.c
src/test.c

index 81c756cc86805c5b1c913ec1ac76cc901cc0fb24..ebead223bf27905e3fe70720c2a9c4d58852b4b9 100644 (file)
     } \
   }
 
+#define CHECK_ADD_VALUE() \
+  if (value_idx < C_SIMPLE_HTTP_CONFIG_BUF_SIZE) { \
+    value_buf[value_idx++] = 0; \
+  } else { \
+    fprintf(stderr, \
+            "ERROR: config file \"value\" is larger than %u bytes!\n", \
+            C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1); \
+    c_simple_http_clean_up_parsed_config(&config); \
+    config.hash_map = NULL; \
+    return config; \
+  } \
+  state &= 0xFFFFFFFE; \
+ \
+  /* Check if key is separating_key. */ \
+  if (strcmp((char*)key_buf, separating_key) == 0) { \
+    if (current_separating_key_value) { \
+      if (required_names) { \
+        C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper = \
+          simple_archiver_hash_map_get( \
+            config.hash_map, \
+            current_separating_key_value, \
+            current_separating_key_value_size); \
+        C_SIMPLE_HTTP_INTERNAL_RequiredIter req_iter_struct; \
+        req_iter_struct.hash_map = hash_map_wrapper->hash_map; \
+        if (paths->count != 0) { \
+          req_iter_struct.path = paths->tail->prev->data; \
+        } else { \
+          req_iter_struct.path = NULL; \
+        } \
+        const char *missing_key = simple_archiver_list_get( \
+          required_names, \
+          c_simple_http_required_iter_fn, \
+          &req_iter_struct); \
+        if (missing_key) { \
+          fprintf(stderr, \
+                  "WARNING: config file did not have required key \"%s\"!" \
+                  " Returning NULL map!\n", \
+                  missing_key); \
+          c_simple_http_clean_up_parsed_config(&config); \
+          config.hash_map = NULL; \
+          return config; \
+        } \
+      } \
+ \
+      state &= 0xFFFFFFFD; \
+      free(current_separating_key_value); \
+    } \
+    current_separating_key_value = malloc(value_idx); \
+    memcpy(current_separating_key_value, value_buf, value_idx); \
+    current_separating_key_value_size = value_idx; \
+    /* At this point, key is separating_key. */ \
+    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) { \
+      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); \
+      return config; \
+    } \
+ \
+    C_SIMPLE_HTTP_HashMapWrapper *wrapper = malloc(sizeof(C_SIMPLE_HTTP_HashMapWrapper)); \
+    wrapper->paths = hash_map; \
+ \
+    if (simple_archiver_hash_map_insert( \
+        &config.hash_map, \
+        wrapper, \
+        value, \
+        value_idx, \
+        c_simple_http_hash_map_wrapper_cleanup_hashmap_fn, \
+        simple_archiver_helper_datastructure_cleanup_nop) != 0) { \
+      fprintf(stderr, \
+          "ERROR: Failed to insert new hash map for new PATH block!\n"); \
+      c_simple_http_clean_up_parsed_config(&config); \
+      config.hash_map = NULL; \
+      c_simple_http_hash_map_wrapper_cleanup(wrapper); \
+      return config; \
+    } \
+    simple_archiver_list_add(paths, value, \
+        simple_archiver_helper_datastructure_cleanup_nop); \
+  } else if (!current_separating_key_value) { \
+    fprintf( \
+        stderr, \
+        "ERROR: config file has invalid key: No preceding \"%s\" " \
+        "key!\n", separating_key); \
+    c_simple_http_clean_up_parsed_config(&config); \
+    config.hash_map = NULL; \
+    return config; \
+  } else { \
+    /* Non-separating_key key. */ \
+    C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper = \
+      simple_archiver_hash_map_get( \
+        config.hash_map, \
+        current_separating_key_value, \
+        current_separating_key_value_size); \
+    if (!hash_map_wrapper) { \
+      fprintf(stderr, \
+        "ERROR: Internal error failed to get existing hash map with path " \
+        "\"%s\"!", current_separating_key_value); \
+      c_simple_http_clean_up_parsed_config(&config); \
+      config.hash_map = NULL; \
+      return config; \
+    } \
+ \
+    unsigned char *key = malloc(key_idx); \
+    memcpy(key, key_buf, key_idx); \
+    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 config; \
+    } \
+  } \
+  key_idx = 0; \
+  value_idx = 0;
+
 void c_simple_http_hash_map_wrapper_cleanup_hashmap_fn(void *data) {
   C_SIMPLE_HTTP_HashMapWrapper *wrapper = data;
   simple_archiver_hash_map_free(&wrapper->paths);
@@ -279,148 +418,18 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
           return config;
         }
       } else {
-        if (value_idx < C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
-          value_buf[value_idx++] = 0;
-        } else {
-          fprintf(stderr,
-                  "ERROR: config file \"value\" is larger than %u bytes!\n",
-                  C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1);
-          c_simple_http_clean_up_parsed_config(&config);
-          config.hash_map = NULL;
-          return config;
-        }
-        state &= 0xFFFFFFFE;
-
-        // Check if key is separating_key.
-        if (strcmp((char*)key_buf, separating_key) == 0) {
-          if (current_separating_key_value) {
-            if (required_names) {
-              C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper =
-                simple_archiver_hash_map_get(
-                  config.hash_map,
-                  current_separating_key_value,
-                  current_separating_key_value_size);
-              C_SIMPLE_HTTP_INTERNAL_RequiredIter req_iter_struct;
-              req_iter_struct.hash_map = hash_map_wrapper->hash_map;
-              if (paths->count != 0) {
-                req_iter_struct.path = paths->tail->prev->data;
-              } else {
-                req_iter_struct.path = NULL;
-              }
-              const char *missing_key = simple_archiver_list_get(
-                required_names,
-                c_simple_http_required_iter_fn,
-                &req_iter_struct);
-              if (missing_key) {
-                fprintf(stderr,
-                        "WARNING: config file did not have required key \"%s\"!"
-                        " Returning NULL map!\n",
-                        missing_key);
-                c_simple_http_clean_up_parsed_config(&config);
-                config.hash_map = NULL;
-                return config;
-              }
-            }
-
-            state &= 0xFFFFFFFD;
-            free(current_separating_key_value);
-          }
-          current_separating_key_value = malloc(value_idx);
-          memcpy(current_separating_key_value, value_buf, value_idx);
-          current_separating_key_value_size = value_idx;
-          // At this point, key is separating_key.
-          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) {
-            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);
-            return config;
-          }
-
-          C_SIMPLE_HTTP_HashMapWrapper *wrapper = malloc(sizeof(C_SIMPLE_HTTP_HashMapWrapper));
-          wrapper->paths = hash_map;
-
-          if (simple_archiver_hash_map_insert(
-              &config.hash_map,
-              wrapper,
-              value,
-              value_idx,
-              c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
-              simple_archiver_helper_datastructure_cleanup_nop) != 0) {
-            fprintf(stderr,
-                "ERROR: Failed to insert new hash map for new PATH block!\n");
-            c_simple_http_clean_up_parsed_config(&config);
-            config.hash_map = NULL;
-            c_simple_http_hash_map_wrapper_cleanup(wrapper);
-            return config;
-          }
-          simple_archiver_list_add(paths, value,
-              simple_archiver_helper_datastructure_cleanup_nop);
-        } else if (!current_separating_key_value) {
-          fprintf(
-              stderr,
-              "ERROR: config file has invalid key: No preceding \"%s\" "
-              "key!\n", separating_key);
-          c_simple_http_clean_up_parsed_config(&config);
-          config.hash_map = NULL;
-          return config;
-        } else {
-          // Non-separating_key key.
-          C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper =
-            simple_archiver_hash_map_get(
-              config.hash_map,
-              current_separating_key_value,
-              current_separating_key_value_size);
-          if (!hash_map_wrapper) {
-            fprintf(stderr,
-              "ERROR: Internal error failed to get existing hash map with path "
-              "\"%s\"!", current_separating_key_value);
-            c_simple_http_clean_up_parsed_config(&config);
-            config.hash_map = NULL;
-            return config;
-          }
-
-          unsigned char *key = malloc(key_idx);
-          memcpy(key, key_buf, key_idx);
-          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 config;
-          }
-        }
-        key_idx = 0;
-        value_idx = 0;
+        CHECK_ADD_VALUE()
       }
     }
   }
   simple_archiver_helper_cleanup_FILE(&f);
 
+  if ((state & 0x1) == 1 && (state & 0xC) == 0 && value_idx != 0) {
+    // Leftover "value" not added yet.
+
+    CHECK_ADD_VALUE()
+  }
+
   if (!current_separating_key_value) {
     fprintf(stderr, "ERROR: Never got \"PATH\" key in config!\n");
     c_simple_http_clean_up_parsed_config(&config);
index d75f25d12daefd181a714ad04482628c6f42e306..661540e4b78e79d430a4c5a02ede4a96cd45554c 100644 (file)
@@ -120,9 +120,11 @@ int main(void) {
     ASSERT_TRUE(
         fwrite("TEST3=something\n", 1, 16, test_file)
         == 16);
+    // No endline at the end of file to check for case where the config file
+    // has no endline.
     ASSERT_TRUE(
-        fwrite("TEST2=' \"one two \"three ''\n", 1, 27, test_file)
-        == 27);
+        fwrite("TEST2=' \"one two \"three ''", 1, 26, test_file)
+        == 26);
     simple_archiver_helper_cleanup_FILE(&test_file);
 
     __attribute__((cleanup(simple_archiver_list_free)))