Compare commits
4 commits
80b1d49e74
...
0d552d2cb0
Author | SHA1 | Date | |
---|---|---|---|
0d552d2cb0 | |||
e1dde1576a | |||
1cb593e155 | |||
95aef64618 |
2 changed files with 350 additions and 246 deletions
|
@ -1,6 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## Latest Changes
|
## Upcoming Changes
|
||||||
|
|
||||||
|
## Version 1.1
|
||||||
|
|
||||||
|
Some refactoring of code handling parsing the config file.
|
||||||
|
|
||||||
|
Remove buffer-size-limit on config file entries.
|
||||||
|
|
||||||
## Version 1.0
|
## Version 1.0
|
||||||
|
|
||||||
|
|
588
src/config.c
588
src/config.c
|
@ -26,215 +26,16 @@
|
||||||
// Local includes
|
// Local includes
|
||||||
#include "constants.h"
|
#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 {
|
typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredIter {
|
||||||
SDArchiverHashMap *hash_map;
|
SDArchiverHashMap *hash_map;
|
||||||
const char *path;
|
const char *path;
|
||||||
} C_SIMPLE_HTTP_INTERNAL_RequiredIter;
|
} 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) {
|
int c_simple_http_required_iter_fn(void *data, void *ud) {
|
||||||
C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
|
C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud;
|
||||||
uint32_t data_str_length = (uint32_t)strlen(data) + 1;
|
uint32_t data_str_length = (uint32_t)strlen(data) + 1;
|
||||||
|
@ -260,10 +61,224 @@ int c_simple_http_required_iter_fn(void *data, void *ud) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
|
void c_simple_http_hash_map_wrapper_cleanup_hashmap_fn(void *data) {
|
||||||
const SDArchiverHashMap *map_of_paths_and_their_vars;
|
C_SIMPLE_HTTP_HashMapWrapper *wrapper = data;
|
||||||
const SDArchiverLinkedList *required;
|
simple_archiver_hash_map_free(&wrapper->paths);
|
||||||
} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
|
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 internal_single_quote_decrement(uint_fast8_t *single_quote_count,
|
||||||
|
uint32_t *state,
|
||||||
|
char **key_buf,
|
||||||
|
uint32_t *key_capacity,
|
||||||
|
uint32_t *key_idx,
|
||||||
|
char **value_buf,
|
||||||
|
uint32_t *value_capacity,
|
||||||
|
uint32_t *value_idx) {
|
||||||
|
for(; (*single_quote_count) > 0; --(*single_quote_count)) {
|
||||||
|
if (((*state) & 1) == 0) {
|
||||||
|
(*key_buf)[(*key_idx)++] = '\'';
|
||||||
|
if (*key_idx >= *key_capacity) {
|
||||||
|
(*key_capacity) *= 2;
|
||||||
|
(*key_buf) = realloc(*key_buf, *key_capacity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(*value_buf)[(*value_idx)++] = '\'';
|
||||||
|
if ((*value_idx) >= *value_capacity) {
|
||||||
|
(*value_capacity) *= 2;
|
||||||
|
(*value_buf) = realloc(*value_buf, *value_capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void internal_double_quote_decrement(uint_fast8_t *double_quote_count,
|
||||||
|
uint32_t *state,
|
||||||
|
char **key_buf,
|
||||||
|
uint32_t *key_capacity,
|
||||||
|
uint32_t *key_idx,
|
||||||
|
char **value_buf,
|
||||||
|
uint32_t *value_capacity,
|
||||||
|
uint32_t *value_idx) {
|
||||||
|
for(; (*double_quote_count) > 0; --(*double_quote_count)) {
|
||||||
|
if (((*state) & 1) == 0) {
|
||||||
|
(*key_buf)[(*key_idx)++] = '"';
|
||||||
|
if ((*key_idx) >= (*key_capacity)) {
|
||||||
|
(*key_capacity) *= 2;
|
||||||
|
(*key_buf) = realloc(*key_buf, *key_capacity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(*value_buf)[(*value_idx)++] = '"';
|
||||||
|
if ((*value_idx) >= (*value_capacity)) {
|
||||||
|
(*value_capacity) *= 2;
|
||||||
|
(*value_buf) = realloc(*value_buf, *value_capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns non-zero if config should be returned.
|
||||||
|
int internal_check_add_value(uint32_t *state,
|
||||||
|
char **key_buf,
|
||||||
|
uint32_t *key_capacity,
|
||||||
|
uint32_t *key_idx,
|
||||||
|
char **value_buf,
|
||||||
|
uint32_t *value_capacity,
|
||||||
|
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) < (*value_capacity)) {
|
||||||
|
(*value_buf)[(*value_idx)++] = 0;
|
||||||
|
} else {
|
||||||
|
(*value_capacity) *= 2;
|
||||||
|
(*value_buf) = realloc(*value_buf, *value_capacity);
|
||||||
|
(*value_buf)[(*value_idx)++] = 0;
|
||||||
|
}
|
||||||
|
(*state) &= 0xFFFFFFFE;
|
||||||
|
|
||||||
|
/* Check if key is separating_key. */
|
||||||
|
if (strcmp((*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) {
|
int c_simple_http_check_required_iter_fn(void *path_void_str, void *ud) {
|
||||||
C_SIMPLE_HTTP_INTERNAL_RequiredCheck *req = ud;
|
C_SIMPLE_HTTP_INTERNAL_RequiredCheck *req = ud;
|
||||||
|
@ -318,8 +333,12 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
c_simple_http_clean_up_parsed_config(&config);
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
unsigned char key_buf[C_SIMPLE_HTTP_CONFIG_BUF_SIZE];
|
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||||
unsigned char value_buf[C_SIMPLE_HTTP_CONFIG_BUF_SIZE];
|
char *key_buf = malloc(C_SIMPLE_HTTP_CONFIG_BUF_SIZE);
|
||||||
|
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||||
|
char *value_buf = malloc(C_SIMPLE_HTTP_CONFIG_BUF_SIZE);
|
||||||
|
uint32_t key_capacity = C_SIMPLE_HTTP_CONFIG_BUF_SIZE;
|
||||||
|
uint32_t value_capacity = C_SIMPLE_HTTP_CONFIG_BUF_SIZE;
|
||||||
uint32_t key_idx = 0;
|
uint32_t key_idx = 0;
|
||||||
uint32_t value_idx = 0;
|
uint32_t value_idx = 0;
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||||
|
@ -332,8 +351,8 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
// 01xx - reading value is single quoted
|
// 01xx - reading value is single quoted
|
||||||
// 10xx - reading value is double quoted
|
// 10xx - reading value is double quoted
|
||||||
uint32_t state = 0;
|
uint32_t state = 0;
|
||||||
unsigned char single_quote_count = 0;
|
uint_fast8_t single_quote_count = 0;
|
||||||
unsigned char double_quote_count = 0;
|
uint_fast8_t double_quote_count = 0;
|
||||||
int32_t c;
|
int32_t c;
|
||||||
|
|
||||||
while (feof(f) == 0) {
|
while (feof(f) == 0) {
|
||||||
|
@ -342,20 +361,55 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
break;
|
break;
|
||||||
} else if ((state & 0xC) == 0 && (c == ' ' || c == '\t')) {
|
} else if ((state & 0xC) == 0 && (c == ' ' || c == '\t')) {
|
||||||
// Ignore whitespace when not quoted.
|
// Ignore whitespace when not quoted.
|
||||||
SINGLE_QUOTE_DECREMENT();
|
internal_single_quote_decrement(&single_quote_count,
|
||||||
DOUBLE_QUOTE_DECREMENT();
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
|
internal_double_quote_decrement(&double_quote_count,
|
||||||
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
continue;
|
continue;
|
||||||
} else if ((state & 1) == 0
|
} else if ((state & 1) == 0
|
||||||
&& (state & 0xC) == 0
|
&& (state & 0xC) == 0
|
||||||
&& (c == '\r' || c == '\n')) {
|
&& (c == '\r' || c == '\n')) {
|
||||||
// Ignore newlines when parsing for key and when not quoted.
|
// Ignore newlines when parsing for key and when not quoted.
|
||||||
SINGLE_QUOTE_DECREMENT();
|
internal_single_quote_decrement(&single_quote_count,
|
||||||
DOUBLE_QUOTE_DECREMENT();
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
|
internal_double_quote_decrement(&double_quote_count,
|
||||||
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
continue;
|
continue;
|
||||||
} else if ((state & 1) == 1) {
|
} else if ((state & 1) == 1) {
|
||||||
if (c == '\'') {
|
if (c == '\'') {
|
||||||
++single_quote_count;
|
++single_quote_count;
|
||||||
DOUBLE_QUOTE_DECREMENT();
|
internal_double_quote_decrement(&double_quote_count,
|
||||||
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
|
|
||||||
if (((state & 0xC) == 0x4 || (state & 0xC) == 0)
|
if (((state & 0xC) == 0x4 || (state & 0xC) == 0)
|
||||||
&& single_quote_count >= C_SIMPLE_HTTP_QUOTE_COUNT_MAX) {
|
&& single_quote_count >= C_SIMPLE_HTTP_QUOTE_COUNT_MAX) {
|
||||||
|
@ -371,7 +425,14 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
continue;
|
continue;
|
||||||
} else if (c == '"') {
|
} else if (c == '"') {
|
||||||
++double_quote_count;
|
++double_quote_count;
|
||||||
SINGLE_QUOTE_DECREMENT();
|
internal_single_quote_decrement(&single_quote_count,
|
||||||
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
|
|
||||||
if (((state & 0xC) == 0x8 || (state & 0xC) == 0)
|
if (((state & 0xC) == 0x8 || (state & 0xC) == 0)
|
||||||
&& double_quote_count >= C_SIMPLE_HTTP_QUOTE_COUNT_MAX) {
|
&& double_quote_count >= C_SIMPLE_HTTP_QUOTE_COUNT_MAX) {
|
||||||
|
@ -386,47 +447,69 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
SINGLE_QUOTE_DECREMENT();
|
internal_single_quote_decrement(&single_quote_count,
|
||||||
DOUBLE_QUOTE_DECREMENT();
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
|
internal_double_quote_decrement(&double_quote_count,
|
||||||
|
&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((state & 1) == 0) {
|
if ((state & 1) == 0) {
|
||||||
if (c != '=') {
|
if (c != '=') {
|
||||||
key_buf[key_idx++] = (unsigned char)c;
|
key_buf[key_idx++] = (char)c;
|
||||||
if (key_idx >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
|
if (key_idx >= key_capacity) {
|
||||||
fprintf(stderr,
|
key_capacity *= 2;
|
||||||
"ERROR: config file \"key\" is larger than %u bytes!\n",
|
key_buf = realloc(key_buf, key_capacity);
|
||||||
C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (key_idx < C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
|
if (key_idx < key_capacity) {
|
||||||
key_buf[key_idx++] = 0;
|
key_buf[key_idx++] = 0;
|
||||||
|
if (key_idx >= key_capacity) {
|
||||||
|
key_capacity *= 2;
|
||||||
|
key_buf = realloc(key_buf, key_capacity);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
key_capacity *= 2;
|
||||||
"ERROR: config file \"key\" is larger than %u bytes!\n",
|
key_buf = realloc(key_buf, key_capacity);
|
||||||
C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1);
|
key_buf[key_idx++] = 0;
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
state |= 1;
|
state |= 1;
|
||||||
}
|
}
|
||||||
} else if ((state & 1) == 1) {
|
} else if ((state & 1) == 1) {
|
||||||
if ((c != '\n' && c != '\r') || (state & 0xC) != 0) {
|
if ((c != '\n' && c != '\r') || (state & 0xC) != 0) {
|
||||||
value_buf[value_idx++] = (unsigned char)c;
|
value_buf[value_idx++] = (char)c;
|
||||||
if (value_idx >= C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
|
if (value_idx >= value_capacity) {
|
||||||
fprintf(stderr,
|
value_capacity *= 2;
|
||||||
"ERROR: config file \"value\" is larger than %u bytes!\n",
|
value_buf = realloc(value_buf, value_capacity);
|
||||||
C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CHECK_ADD_VALUE()
|
if (internal_check_add_value(&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&value_idx,
|
||||||
|
&config,
|
||||||
|
separating_key,
|
||||||
|
required_names,
|
||||||
|
separating_key_size,
|
||||||
|
paths,
|
||||||
|
¤t_separating_key_value,
|
||||||
|
¤t_separating_key_value_size)) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -435,7 +518,22 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
if ((state & 0x1) == 1 && (state & 0xC) == 0 && value_idx != 0) {
|
if ((state & 0x1) == 1 && (state & 0xC) == 0 && value_idx != 0) {
|
||||||
// Leftover "value" not added yet.
|
// Leftover "value" not added yet.
|
||||||
|
|
||||||
CHECK_ADD_VALUE()
|
if (internal_check_add_value(&state,
|
||||||
|
&key_buf,
|
||||||
|
&key_capacity,
|
||||||
|
&key_idx,
|
||||||
|
&value_buf,
|
||||||
|
&value_capacity,
|
||||||
|
&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) {
|
if (!current_separating_key_value) {
|
||||||
|
|
Loading…
Reference in a new issue