From 802f11352a1f8ab25a222111d2ba254ed9f7113f Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 12 Sep 2025 15:06:47 -0400 Subject: Simplify pom_conf --- examples/conf.pom | 2 + pom.c | 147 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 96 insertions(+), 53 deletions(-) diff --git a/examples/conf.pom b/examples/conf.pom index 8df17e7..cc8404f 100644 --- a/examples/conf.pom +++ b/examples/conf.pom @@ -10,5 +10,7 @@ Hello = 5 [number] one = 1 + two = 2 + three = 3 [] thing=yup diff --git a/pom.c b/pom.c index 6aed7e8..5bb8c74 100644 --- a/pom.c +++ b/pom.c @@ -32,7 +32,16 @@ struct pom_error { const char *message; }; -struct main_conf; +struct conf_item { + const char *key, *value, *file; + uint64_t line; +#if HAVE_ATOMICS + atomic_bool read; +#else + bool read; +#endif +}; + struct to_free { struct to_free *next; @@ -49,6 +58,18 @@ struct pom_conf { size_t prefix_len; struct conf_item *items; size_t items_count; + struct conf_section *sections; + size_t sections_count; +}; + +struct conf_section { + const char *key; + struct pom_conf section; +}; + +struct main_conf { + struct to_free *to_free_head, *to_free_tail; + struct pom_conf empty_section; }; struct pom_item_iter { @@ -68,25 +89,6 @@ struct pom_key_iter { const struct conf_item *conf_item; }; -struct conf_item { - const char *key, *value, *file; - uint64_t line; - const struct pom_conf *section; -#if HAVE_ATOMICS - atomic_bool read; -#else - bool read; -#endif -}; - -struct main_conf { - struct conf_item *items; - struct to_free *to_free_head, *to_free_tail; - size_t items_count; - // increases when merged - uint64_t version_number; -}; - // temporary error that is eventually converted to a pom_error struct parser_error { uint64_t line; @@ -676,6 +678,40 @@ conf_item_cmp_qsort(const void *va, const void *vb) { return strcmp(item_a->key, item_b->key); } +/* +// Returns true if `descendant` starts with `ancestor.`. +static bool +is_descendant(const char *ancestor, const char *descendant) { + size_t ancestor_len = strlen(ancestor); + return memcmp(ancestor, descendant, ancestor_len) == 0 + && descendant[ancestor_len] == '.'; +} +*/ + +static size_t +conf_binary_search(const pom_conf *conf, const char *key, char nxt_char, bool *found) { + size_t lo = 0; + size_t hi = conf->items_count; + size_t key_len = strlen(key); + while (lo < hi) { + size_t mid = (lo + hi) / 2; + const char *mid_key = conf->items[mid].key + conf->prefix_len; + int cmp = memcmp(key, mid_key, key_len); + if (cmp == 0) + cmp = nxt_char - mid_key[key_len]; + if (cmp < 0) { + hi = mid; + } else if (cmp > 0) { + lo = mid + 1; + } else { + if (found) *found = true; + return mid; + } + } + if (found) *found = false; + return lo; +} + pom_conf * parser_finish(struct parser *parser) { if (parser->out_of_memory || parser->errors.count) { @@ -686,11 +722,14 @@ parser_finish(struct parser *parser) { parser_out_of_memory(parser); return NULL; } - conf->items_count = parser->items.count; - conf->items = conf_calloc(conf, conf->items_count, sizeof(struct conf_item)); + conf->empty_section.main = conf; + size_t items_count = parser->items.count; + struct conf_item *items = conf_calloc(conf, items_count, sizeof(struct conf_item)); char *filename = conf_calloc(conf, strlen(parser->filename) + 1, 1); - if (!conf->items || !filename) { + if (!items || !filename) { + out_of_memory: parser_out_of_memory(parser); + conf_free(conf); return NULL; } strcpy(filename, parser->filename); @@ -700,9 +739,9 @@ parser_finish(struct parser *parser) { parser->string_data.array = NULL; conf_free_list_append(conf, string_data); - for (size_t i = 0; i < conf->items_count; i++) { + for (size_t i = 0; i < items_count; i++) { const struct parser_item *parser_item = &parser->items.array[i]; - struct conf_item *conf_item = &conf->items[i]; + struct conf_item *conf_item = &items[i]; conf_item->file = filename; conf_item->line = parser_item->line; conf_item->key = ((char*)string_data->data) + (parser_item->key - sizeof(struct to_free)); @@ -712,14 +751,40 @@ parser_finish(struct parser *parser) { #else conf_item->read = false; #endif - conf_item->section = NULL; // TODO } - qsort(conf->items, conf->items_count, sizeof *conf->items, conf_item_cmp_qsort); + qsort(items, items_count, sizeof *items, conf_item_cmp_qsort); + // TODO: check for duplicates + pom_conf *root = conf_calloc(conf, 1, sizeof *root); - root->items = conf->items; - root->items_count = conf->items_count; + if (!root) goto out_of_memory; root->main = conf; root->prefix_len = 0; + root->items = items; + root->items_count = items_count; + #if 0 + size_t section_count = 0; + for (size_t i = 0; i + 1 < conf->items_count; i++) { + struct conf_item *item = &items[i]; + struct conf_item *next = &items[i+1]; + section_count += is_descendant(item->key, next->key); + } + pom_conf *sections = conf_calloc(conf, section_count, sizeof *section); + if (!sections) goto out_of_memory; + for (size_t i = 0; i + 1 < conf->items_count; i++) { + struct conf_item *item = &conf->items[i]; + struct conf_item *next = &conf->items[i+1]; + if (is_descendant(item->key, next->key)) { + // create section + size_t i_start = i + 1; + size_t i_end = conf_binary_search(root, item->key, '.' + 1, NULL); + section->items = conf->items + i_start; + section->items_count = i_end - i_start; + section->prefix_len = strlen(item->key) + 1/* dot */; + section->main = conf; + section++; + } + } + #endif return root; } @@ -955,30 +1020,6 @@ pom_conf_next_key(const pom_conf *conf, pom_key_iter **p_iter) { return NULL; } -static size_t -conf_binary_search(const pom_conf *conf, const char *key, char nxt_char, bool *found) { - size_t lo = 0; - size_t hi = conf->items_count; - size_t key_len = strlen(key); - while (lo < hi) { - size_t mid = (lo + hi) / 2; - const char *mid_key = conf->items[mid].key + conf->prefix_len; - int cmp = memcmp(key, mid_key, key_len); - if (cmp == 0) - cmp = nxt_char - mid_key[key_len]; - if (cmp < 0) { - hi = mid; - } else if (cmp > 0) { - lo = mid + 1; - } else { - if (found) *found = true; - return mid; - } - } - if (found) *found = false; - return lo; -} - struct conf_item * conf_get_item(const pom_conf *conf, const char *key, const char *func) { check_conf_(conf, func); -- cgit v1.2.3