diff --git a/src/config.c b/src/config.c index 81c756c..ebead22 100644 --- a/src/config.c +++ b/src/config.c @@ -76,6 +76,145 @@ } \ } +#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); diff --git a/src/test.c b/src/test.c index d75f25d..661540e 100644 --- a/src/test.c +++ b/src/test.c @@ -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)))