From ace2682dec1b27039db5571d656b538831fee4b9 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Mon, 25 Jul 2022 21:31:09 -0400 Subject: [PATCH] Rework HashMapIterate to be more flexible. We now get the keys, and we don't have to operate within the confines of a callback function. --- src/Config.c | 33 +++++++++++++++++++++----------- src/HashMap.c | 44 +++++++++++++++++++++++++++++++++++-------- src/Telodendria.c | 4 ++++ src/include/HashMap.h | 6 +++--- src/include/Json.h | 23 ++++++++-------------- 5 files changed, 73 insertions(+), 37 deletions(-) diff --git a/src/Config.c b/src/Config.c index 00a936a..3536a5b 100644 --- a/src/Config.c +++ b/src/Config.c @@ -91,15 +91,9 @@ ConfigChildrenGet(ConfigDirective * directive) return directive ? directive->children : NULL; } -/* - * Takes a void pointer because it is only used with - * HashMapIterate(), which requires a pointer to a function - * that takes a void pointer. - */ static void -ConfigDirectiveFree(void *ptr) +ConfigDirectiveFree(ConfigDirective * directive) { - ConfigDirective *directive = ptr; size_t i; if (!directive) @@ -113,6 +107,7 @@ ConfigDirectiveFree(void *ptr) } ArrayFree(directive->values); + ConfigFree(directive->children); free(directive); @@ -121,7 +116,15 @@ ConfigDirectiveFree(void *ptr) void ConfigFree(HashMap * conf) { - HashMapIterate(conf, ConfigDirectiveFree); + char *key; + void *value; + + while (HashMapIterate(conf, &key, &value)) + { + ConfigDirectiveFree((ConfigDirective *) value); + free(key); + } + HashMapFree(conf); } @@ -156,14 +159,23 @@ ConfigParserStateCreate(FILE * stream) static void ConfigParserStateFree(ConfigParserState * state) { + char *key; + void *value; + if (!state) { return; } + free(state->token); - HashMapIterate(state->macroMap, free); + while (HashMapIterate(state->macroMap, &key, &value)) + { + free(key); + free(value); + } + HashMapFree(state->macroMap); free(state); @@ -432,7 +444,6 @@ ConfigParseBlock(ConfigParserState * state, int level) * NULL is sent to ConfigDirectiveFree(), making it a no-op. */ ConfigDirectiveFree(HashMapSet(block, name, directive)); - } else if (ConfigExpect(state, TOKEN_MACRO_ASSIGNMENT)) { @@ -442,7 +453,7 @@ ConfigParseBlock(ConfigParserState * state, int level) char *valueCopy = malloc(strlen(state->token) + 1); strcpy(valueCopy, state->token); - free(HashMapSet(state->macroMap, name, state->token)); + free(HashMapSet(state->macroMap, name, valueCopy)); ConfigTokenSeek(state); } else diff --git a/src/HashMap.c b/src/HashMap.c index 62c47ba..e2eb954 100644 --- a/src/HashMap.c +++ b/src/HashMap.c @@ -18,6 +18,7 @@ struct HashMap HashMapBucket **entries; float maxLoad; + size_t iterator; }; static uint32_t @@ -112,6 +113,7 @@ HashMapCreate(void) map->maxLoad = 0.75; map->count = 0; map->capacity = 16; + map->iterator = 0; map->entries = calloc(map->capacity, sizeof(HashMapBucket *)); if (!map->entries) @@ -211,25 +213,37 @@ HashMapGet(HashMap * map, const char *key) return NULL; } -void -HashMapIterate(HashMap * map, void (*iteratorFunc) (char *, void *)) +int +HashMapIterate(HashMap * map, char **key, void **value) { - size_t i; - if (!map) { - return; + return 0; } - for (i = 0; i < map->capacity; i++) + if (map->iterator >= map->capacity) { - HashMapBucket *bucket = map->entries[i]; + map->iterator = 0; + *key = NULL; + *value = NULL; + return 0; + } + + while (map->iterator < map->capacity) + { + HashMapBucket *bucket = map->entries[map->iterator]; + + map->iterator++; if (bucket) { - iteratorFunc(bucket->key, bucket->value); + *key = bucket->key; + *value = bucket->value; + return 1; } } + + return 0; } void @@ -304,3 +318,17 @@ HashMapSet(HashMap * map, char *key, void *value) return NULL; } + +void +HashMapIterateFree(char *key, void *value) +{ + if (key) + { + free(key); + } + + if (value) + { + free(value); + } +} diff --git a/src/Telodendria.c b/src/Telodendria.c index 610ba9a..783ca2d 100644 --- a/src/Telodendria.c +++ b/src/Telodendria.c @@ -127,9 +127,13 @@ main(int argc, char **argv) Log(lc, LOG_MESSAGE, "Using configuration file '%s'.", configArg); + Log(lc, LOG_DEBUG, "Executing ConfigParse()"); + /* Read config here */ configParseResult = ConfigParse(configFile); + Log(lc, LOG_DEBUG, "Exitting ConfigParse()"); + if (!ConfigParseResultOk(configParseResult)) { Log(lc, LOG_ERROR, "Syntax error on line %d.", diff --git a/src/include/HashMap.h b/src/include/HashMap.h index ad23363..4d7aa1e 100644 --- a/src/include/HashMap.h +++ b/src/include/HashMap.h @@ -69,8 +69,8 @@ extern void * extern void * HashMapDelete(HashMap * map, const char *key); -extern void - HashMapIterate(HashMap * map, void (*iteratorFunc) (char *, void *)); +extern int + HashMapIterate(HashMap * map, char **key, void **value); /* * HashMapFree: Free the hash map, returning its memory to the operating @@ -80,6 +80,6 @@ extern void * free the values using your own algorithm. */ extern void - HashMapFree(HashMap * map); + HashMapFree(HashMap *); #endif /* TELODENDRIA_HASHMAP_H */ diff --git a/src/include/Json.h b/src/include/Json.h index ec1124a..a6d50df 100644 --- a/src/include/Json.h +++ b/src/include/Json.h @@ -4,6 +4,9 @@ #include #include +#include +#include + typedef enum JsonType { JSON_OBJECT, @@ -15,20 +18,7 @@ typedef enum JsonType JSON_NULL } JsonType; -typedef struct JsonValue -{ - JsonType type; - union as - { - HashMap *object; - Array *array; - char *string; - int64_t integer; - double floating; - int boolean:1; - }; -} JsonValue; - +typedef struct JsonValue JsonValue; extern JsonType JsonValueType(JsonValue * value); @@ -60,9 +50,12 @@ extern JsonValue * extern JsonValue * JsonValueNull(void); -extern void * +extern void JsonValueFree(JsonValue * value); +extern void + JsonFree(HashMap * object); + extern int JsonEncode(HashMap * object, FILE * out);