Allow "multi-valued-key-entries" in ParsedConfig
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 25s
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 25s
This commit begins work on adding more templating features.
This commit is contained in:
parent
35aa5fc5a3
commit
2c82b82b06
4 changed files with 114 additions and 56 deletions
60
src/config.c
60
src/config.c
|
@ -36,6 +36,23 @@ typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck {
|
||||||
const SDArchiverLinkedList *required;
|
const SDArchiverLinkedList *required;
|
||||||
} C_SIMPLE_HTTP_INTERNAL_RequiredCheck;
|
} 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) {
|
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;
|
||||||
|
@ -187,13 +204,17 @@ int internal_check_add_value(uint32_t *state,
|
||||||
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
||||||
unsigned char *key = malloc(separating_key_size);
|
unsigned char *key = malloc(separating_key_size);
|
||||||
strncpy((char*)key, separating_key, separating_key_size);
|
strncpy((char*)key, separating_key, separating_key_size);
|
||||||
unsigned char *value = malloc(*value_idx);
|
C_SIMPLE_HTTP_ConfigValue *config_value =
|
||||||
memcpy(value, *value_buf, (*value_idx));
|
malloc(sizeof(C_SIMPLE_HTTP_ConfigValue));
|
||||||
if (simple_archiver_hash_map_insert(hash_map,
|
config_value->value = malloc(*value_idx);
|
||||||
value,
|
config_value->next = NULL;
|
||||||
|
memcpy(config_value->value, *value_buf, (*value_idx));
|
||||||
|
if (simple_archiver_hash_map_insert(
|
||||||
|
hash_map,
|
||||||
|
config_value,
|
||||||
key,
|
key,
|
||||||
separating_key_size,
|
separating_key_size,
|
||||||
NULL,
|
c_simple_http_cleanup_config_value_void_ptr,
|
||||||
NULL) != 0) {
|
NULL) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ERROR: Failed to create hash map for new separating_key "
|
"ERROR: Failed to create hash map for new separating_key "
|
||||||
|
@ -201,7 +222,8 @@ int internal_check_add_value(uint32_t *state,
|
||||||
c_simple_http_clean_up_parsed_config(config);
|
c_simple_http_clean_up_parsed_config(config);
|
||||||
config->hash_map = NULL;
|
config->hash_map = NULL;
|
||||||
free(key);
|
free(key);
|
||||||
free(value);
|
free(config_value->value);
|
||||||
|
free(config_value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +234,7 @@ int internal_check_add_value(uint32_t *state,
|
||||||
if (simple_archiver_hash_map_insert(
|
if (simple_archiver_hash_map_insert(
|
||||||
config->hash_map,
|
config->hash_map,
|
||||||
wrapper,
|
wrapper,
|
||||||
value,
|
config_value->value,
|
||||||
(*value_idx),
|
(*value_idx),
|
||||||
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
||||||
simple_archiver_helper_datastructure_cleanup_nop) != 0) {
|
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);
|
c_simple_http_hash_map_wrapper_cleanup(wrapper);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
simple_archiver_list_add(paths, value,
|
simple_archiver_list_add(paths, config_value->value,
|
||||||
simple_archiver_helper_datastructure_cleanup_nop);
|
simple_archiver_helper_datastructure_cleanup_nop);
|
||||||
} else if (!(*current_separating_key_value)) {
|
} else if (!(*current_separating_key_value)) {
|
||||||
fprintf(
|
fprintf(
|
||||||
|
@ -254,11 +276,26 @@ int internal_check_add_value(uint32_t *state,
|
||||||
unsigned char *value = malloc(*value_idx);
|
unsigned char *value = malloc(*value_idx);
|
||||||
memcpy(value, *value_buf, (*value_idx));
|
memcpy(value, *value_buf, (*value_idx));
|
||||||
|
|
||||||
if (simple_archiver_hash_map_insert(hash_map_wrapper->paths,
|
// Check if key already exists in wrapped hash-map.
|
||||||
value,
|
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,
|
||||||
*key_idx,
|
*key_idx,
|
||||||
NULL,
|
c_simple_http_cleanup_config_value_void_ptr,
|
||||||
NULL) != 0) {
|
NULL) != 0) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"ERROR: Internal error failed to insert into hash map with path "
|
"ERROR: Internal error failed to insert into hash map with path "
|
||||||
|
@ -270,6 +307,7 @@ int internal_check_add_value(uint32_t *state,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
(*key_idx) = 0;
|
(*key_idx) = 0;
|
||||||
(*value_idx) = 0;
|
(*value_idx) = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
12
src/config.h
12
src/config.h
|
@ -30,6 +30,9 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
|
||||||
/// KEY: "/", VALUE: HashMapWrapper struct
|
/// KEY: "/", VALUE: HashMapWrapper struct
|
||||||
/// KEY: "/inner", VALUE: HashMapWrapper struct
|
/// KEY: "/inner", VALUE: HashMapWrapper struct
|
||||||
/// KEY: "/inner/further", 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 {
|
union {
|
||||||
SDArchiverHashMap *paths;
|
SDArchiverHashMap *paths;
|
||||||
SDArchiverHashMap *hash_map;
|
SDArchiverHashMap *hash_map;
|
||||||
|
@ -38,6 +41,15 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig {
|
||||||
|
|
||||||
typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper;
|
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
|
/// 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
|
/// 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
|
/// of a string can be "quoted" if it is surrounded by three single-quotes or
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <SimpleArchiver/src/helpers.h>
|
#include <SimpleArchiver/src/helpers.h>
|
||||||
|
|
||||||
// Local includes.
|
// Local includes.
|
||||||
|
#include "config.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
/// Returns 0 if "c_string" ends with "_FILE".
|
/// 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)))
|
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||||
char *html_buf = NULL;
|
char *html_buf = NULL;
|
||||||
size_t html_buf_size = 0;
|
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);
|
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)))
|
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
|
||||||
FILE *f = fopen(html_filename, "r");
|
FILE *f = fopen(html_file_value->value, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -99,19 +100,19 @@ char *c_simple_http_path_to_generated(
|
||||||
html_buf[html_file_size] = 0;
|
html_buf[html_file_size] = 0;
|
||||||
html_buf_size = (size_t)html_file_size;
|
html_buf_size = (size_t)html_file_size;
|
||||||
if (files_list_out) {
|
if (files_list_out) {
|
||||||
char *html_filename_copy = malloc(strlen(html_filename) + 1);
|
char *html_filename_copy = malloc(strlen(html_file_value->value) + 1);
|
||||||
strcpy(html_filename_copy, html_filename);
|
strcpy(html_filename_copy, html_file_value->value);
|
||||||
simple_archiver_list_add(*files_list_out, html_filename_copy, NULL);
|
simple_archiver_list_add(*files_list_out, html_filename_copy, NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char *stored_html =
|
C_SIMPLE_HTTP_ConfigValue *stored_html_config_value =
|
||||||
simple_archiver_hash_map_get(wrapped_hash_map->hash_map, "HTML", 5);
|
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;
|
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);
|
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;
|
html_buf_size = stored_html_size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,34 +178,34 @@ char *c_simple_http_path_to_generated(
|
||||||
html_buf + last_part->extra,
|
html_buf + last_part->extra,
|
||||||
var_size);
|
var_size);
|
||||||
var[var_size] = 0;
|
var[var_size] = 0;
|
||||||
const char *value_c_str =
|
C_SIMPLE_HTTP_ConfigValue *config_value =
|
||||||
simple_archiver_hash_map_get(
|
simple_archiver_hash_map_get(
|
||||||
wrapped_hash_map->hash_map,
|
wrapped_hash_map->hash_map,
|
||||||
var,
|
var,
|
||||||
(uint32_t)var_size + 1);
|
(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) {
|
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)))
|
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
|
||||||
FILE *f = fopen(value_c_str, "r");
|
FILE *f = fopen(config_value->value, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
fprintf(stderr, "ERROR Failed to open file \"%s\"!\n",
|
fprintf(stderr, "ERROR Failed to open file \"%s\"!\n",
|
||||||
value_c_str);
|
config_value->value);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (fseek(f, 0, SEEK_END) != 0) {
|
} else if (fseek(f, 0, SEEK_END) != 0) {
|
||||||
fprintf(stderr, "ERROR Failed to seek to end of file \"%s\"!\n",
|
fprintf(stderr, "ERROR Failed to seek to end of file \"%s\"!\n",
|
||||||
value_c_str);
|
config_value->value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
long file_size = ftell(f);
|
long file_size = ftell(f);
|
||||||
if (file_size <= 0) {
|
if (file_size <= 0) {
|
||||||
fprintf(stderr, "ERROR Size of file \"%s\" is invalid!\n",
|
fprintf(stderr, "ERROR Size of file \"%s\" is invalid!\n",
|
||||||
value_c_str);
|
config_value->value);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (fseek(f, 0, SEEK_SET) != 0) {
|
} else if (fseek(f, 0, SEEK_SET) != 0) {
|
||||||
fprintf(stderr, "ERROR Failed to seek to start of file "
|
fprintf(stderr, "ERROR Failed to seek to start of file "
|
||||||
"\"%s\"!\n",
|
"\"%s\"!\n",
|
||||||
value_c_str);
|
config_value->value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
string_part.size = (size_t)file_size + 1;
|
string_part.size = (size_t)file_size + 1;
|
||||||
|
@ -217,21 +218,21 @@ char *c_simple_http_path_to_generated(
|
||||||
f)
|
f)
|
||||||
!= 1) {
|
!= 1) {
|
||||||
fprintf(stderr, "ERROR Failed to read from file \"%s\"!\n",
|
fprintf(stderr, "ERROR Failed to read from file \"%s\"!\n",
|
||||||
value_c_str);
|
config_value->value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
string_part.buf[string_part.size - 1] = 0;
|
string_part.buf[string_part.size - 1] = 0;
|
||||||
if (files_list_out) {
|
if (files_list_out) {
|
||||||
char *variable_filename = malloc(strlen(value_c_str) + 1);
|
char *variable_filename = malloc(strlen(config_value->value) + 1);
|
||||||
strcpy(variable_filename, value_c_str);
|
strcpy(variable_filename, config_value->value);
|
||||||
simple_archiver_list_add(
|
simple_archiver_list_add(
|
||||||
*files_list_out, variable_filename, NULL);
|
*files_list_out, variable_filename, NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Variable data is "value_c_str".
|
// Variable data is "config_value->value".
|
||||||
string_part.size = strlen(value_c_str) + 1;
|
string_part.size = strlen(config_value->value) + 1;
|
||||||
string_part.buf = malloc(string_part.size);
|
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.buf[string_part.size - 1] = 0;
|
||||||
string_part.extra = idx + 1;
|
string_part.extra = idx + 1;
|
||||||
}
|
}
|
||||||
|
|
23
src/test.c
23
src/test.c
|
@ -173,46 +173,53 @@ int main(int argc, char **argv) {
|
||||||
simple_archiver_hash_map_get(templates.paths, "/", 2);
|
simple_archiver_hash_map_get(templates.paths, "/", 2);
|
||||||
ASSERT_TRUE(first_path_map_wrapper);
|
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);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
ASSERT_STREQ(value, "/");
|
ASSERT_TRUE(value->value);
|
||||||
|
ASSERT_STREQ(value->value, "/");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " one two three ");
|
ASSERT_STREQ(value->value, " one two three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " \"one two \"three ");
|
ASSERT_STREQ(value->value, " \"one two \"three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, "'\"onetwo\"three''");
|
ASSERT_STREQ(value->value, "'\"onetwo\"three''");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " \"one two \"three ''");
|
ASSERT_STREQ(value->value, " \"one two \"three ''");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " \"\"\"one two \"\"\"three ");
|
ASSERT_STREQ(value->value, " \"\"\"one two \"\"\"three ");
|
||||||
|
|
||||||
value =
|
value =
|
||||||
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
|
simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6);
|
||||||
ASSERT_TRUE(value);
|
ASSERT_TRUE(value);
|
||||||
|
ASSERT_TRUE(value->value);
|
||||||
// printf("%s\n", value);
|
// printf("%s\n", value);
|
||||||
ASSERT_STREQ(value, " '''one two '''three ");
|
ASSERT_STREQ(value->value, " '''one two '''three ");
|
||||||
|
|
||||||
simple_archiver_list_free(&required_names);
|
simple_archiver_list_free(&required_names);
|
||||||
required_names = simple_archiver_list_init();
|
required_names = simple_archiver_list_init();
|
||||||
|
|
Loading…
Reference in a new issue