// Local includes
#include "constants.h"
-#define SINGLE_QUOTE_DECREMENT() \
- for(; single_quote_count > 0; --single_quote_count) { \
- if ((state & 1) == 0) { \
- key_buf[key_idx++] = '\''; \
- if (key_idx >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) { \
- fprintf(stderr, \
- "ERROR: config file \"key\" 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; \
- } \
- } else { \
- value_buf[value_idx++] = '\''; \
- if (value_idx >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) { \
- 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; \
- } \
- } \
- }
-
-#define DOUBLE_QUOTE_DECREMENT() \
- for(; double_quote_count > 0; --double_quote_count) { \
- if ((state & 1) == 0) { \
- key_buf[key_idx++] = '"'; \
- if (key_idx >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) { \
- fprintf(stderr, \
- "ERROR: config file \"key\" 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; \
- } \
- } else { \
- value_buf[value_idx++] = '"'; \
- if (value_idx >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) { \
- 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; \
- } \
- } \
- }
-
-#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);
- free(wrapper);
-}
-
-void c_simple_http_hash_map_wrapper_cleanup(C_SIMPLE_HTTP_HashMapWrapper *wrapper) {
- simple_archiver_hash_map_free(&wrapper->paths);
- free(wrapper);
-}
-
-void c_simple_http_hash_map_cleanup_helper(SDArchiverHashMap *hash_map) {
- simple_archiver_hash_map_free(&hash_map);
-}
-
typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredIter {
SDArchiverHashMap *hash_map;
const char *path;
} C_SIMPLE_HTTP_INTERNAL_RequiredIter;
+typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
+ const SDArchiverHashMap *map_of_paths_and_their_vars;
+ const SDArchiverLinkedList *required;
+} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
+
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;
return 0;
}
-typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
- const SDArchiverHashMap *map_of_paths_and_their_vars;
- const SDArchiverLinkedList *required;
-} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
+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);
+ free(wrapper);
+}
+
+void c_simple_http_hash_map_wrapper_cleanup(
+ C_SIMPLE_HTTP_HashMapWrapper *wrapper) {
+ simple_archiver_hash_map_free(&wrapper->paths);
+ free(wrapper);
+}
+
+/// Returns non-zero if config should be returned.
+int internal_single_quote_decrement(uint_fast8_t *single_quote_count,
+ uint32_t *state,
+ unsigned char *key_buf,
+ uint32_t *key_idx,
+ unsigned char *value_buf,
+ uint32_t *value_idx,
+ C_SIMPLE_HTTP_ParsedConfig *config) {
+ for(; (*single_quote_count) > 0; --(*single_quote_count)) {
+ if (((*state) & 1) == 0) {
+ key_buf[(*key_idx)++] = '\'';
+ if ((*key_idx) >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
+ fprintf(stderr,
+ "ERROR: config file \"key\" 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 1;
+ }
+ } else {
+ value_buf[(*value_idx)++] = '\'';
+ if ((*value_idx) >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
+ 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 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/// Returns non-zero if config should be returned.
+int internal_double_quote_decrement(uint_fast8_t *double_quote_count,
+ uint32_t *state,
+ unsigned char *key_buf,
+ uint32_t *key_idx,
+ unsigned char *value_buf,
+ uint32_t *value_idx,
+ C_SIMPLE_HTTP_ParsedConfig *config) {
+ for(; (*double_quote_count) > 0; --(*double_quote_count)) {
+ if (((*state) & 1) == 0) {
+ key_buf[(*key_idx)++] = '"';
+ if ((*key_idx) >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
+ fprintf(stderr,
+ "ERROR: config file \"key\" 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 1;
+ }
+ } else {
+ value_buf[(*value_idx)++] = '"';
+ if ((*value_idx) >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
+ 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 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/// Returns non-zero if config should be returned.
+int internal_check_add_value(uint32_t *state,
+ unsigned char *key_buf,
+ uint32_t *key_idx,
+ unsigned char *value_buf,
+ uint32_t *value_idx,
+ C_SIMPLE_HTTP_ParsedConfig *config,
+ const char *separating_key,
+ const SDArchiverLinkedList *required_names,
+ const uint32_t separating_key_size,
+ SDArchiverLinkedList *paths,
+ char **current_separating_key_value,
+ uint32_t *current_separating_key_value_size) {
+ 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 1;
+ }
+ (*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 1;
+ }
+ }
+
+ (*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 1;
+ }
+
+ 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 1;
+ }
+ 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 1;
+ } 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 1;
+ }
+
+ 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 1;
+ }
+ }
+ (*key_idx) = 0;
+ (*value_idx) = 0;
+ return 0;
+}
+
+void c_simple_http_hash_map_cleanup_helper(SDArchiverHashMap *hash_map) {
+ simple_archiver_hash_map_free(&hash_map);
+}
int c_simple_http_check_required_iter_fn(void *path_void_str, void *ud) {
C_SIMPLE_HTTP_INTERNAL_RequiredCheck *req = ud;
// 01xx - reading value is single quoted
// 10xx - reading value is double quoted
uint32_t state = 0;
- unsigned char single_quote_count = 0;
- unsigned char double_quote_count = 0;
+ uint_fast8_t single_quote_count = 0;
+ uint_fast8_t double_quote_count = 0;
int32_t c;
while (feof(f) == 0) {
break;
} else if ((state & 0xC) == 0 && (c == ' ' || c == '\t')) {
// Ignore whitespace when not quoted.
- SINGLE_QUOTE_DECREMENT();
- DOUBLE_QUOTE_DECREMENT();
+ if (internal_single_quote_decrement(&single_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
+ if (internal_double_quote_decrement(&double_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
continue;
} else if ((state & 1) == 0
&& (state & 0xC) == 0
&& (c == '\r' || c == '\n')) {
// Ignore newlines when parsing for key and when not quoted.
- SINGLE_QUOTE_DECREMENT();
- DOUBLE_QUOTE_DECREMENT();
+ if (internal_single_quote_decrement(&single_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
+ if (internal_double_quote_decrement(&double_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
continue;
} else if ((state & 1) == 1) {
if (c == '\'') {
++single_quote_count;
- DOUBLE_QUOTE_DECREMENT();
+ if (internal_double_quote_decrement(&double_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
if (((state & 0xC) == 0x4 || (state & 0xC) == 0)
&& single_quote_count >= C_SIMPLE_HTTP_QUOTE_COUNT_MAX) {
continue;
} else if (c == '"') {
++double_quote_count;
- SINGLE_QUOTE_DECREMENT();
+ if (internal_single_quote_decrement(&single_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
if (((state & 0xC) == 0x8 || (state & 0xC) == 0)
&& double_quote_count >= C_SIMPLE_HTTP_QUOTE_COUNT_MAX) {
}
continue;
} else {
- SINGLE_QUOTE_DECREMENT();
- DOUBLE_QUOTE_DECREMENT();
+ if (internal_single_quote_decrement(&single_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
+ if (internal_double_quote_decrement(&double_quote_count,
+ &state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config)) {
+ return config;
+ }
}
}
if ((state & 1) == 0) {
return config;
}
} else {
- CHECK_ADD_VALUE()
+ if (internal_check_add_value(&state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config,
+ separating_key,
+ required_names,
+ separating_key_size,
+ paths,
+ ¤t_separating_key_value,
+ ¤t_separating_key_value_size)) {
+ return config;
+ }
}
}
}
if ((state & 0x1) == 1 && (state & 0xC) == 0 && value_idx != 0) {
// Leftover "value" not added yet.
- CHECK_ADD_VALUE()
+ if (internal_check_add_value(&state,
+ key_buf,
+ &key_idx,
+ value_buf,
+ &value_idx,
+ &config,
+ separating_key,
+ required_names,
+ separating_key_size,
+ paths,
+ ¤t_separating_key_value,
+ ¤t_separating_key_value_size)) {
+ return config;
+ }
}
if (!current_separating_key_value) {