diff options
author | pommicket <pommicket@gmail.com> | 2025-09-12 14:44:41 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-09-12 14:45:26 -0400 |
commit | 45393c79ab36bb64b933b44983a1cd8dffc0ebac (patch) | |
tree | 3efcdfd61a60ce02d08f4ff5d5ca0b445c1964a4 /pom.c | |
parent | 81c1cecf40b0733446fb0d945505155d87bf74c6 (diff) |
Implement pom_conf_next_key, pom_conf_next_unread_key
Diffstat (limited to 'pom.c')
-rw-r--r-- | pom.c | 87 |
1 files changed, 78 insertions, 9 deletions
@@ -46,9 +46,6 @@ struct to_free { struct pom_conf { struct main_conf *main; - // this is checked vs main->version_number - // to detect when a section is used after a merge - uint64_t version_number; size_t prefix_len; struct conf_item *items; size_t items_count; @@ -60,6 +57,17 @@ struct pom_item_iter { pom_item item; }; +struct pom_unread_key_iter { + const pom_conf *conf; + const struct conf_item *conf_item; +}; + +struct pom_key_iter { + const pom_conf *conf; + char *prev_key; + const struct conf_item *conf_item; +}; + struct conf_item { const char *key, *value, *file; uint64_t line; @@ -700,7 +708,7 @@ parser_finish(struct parser *parser) { conf_item->key = ((char*)string_data->data) + (parser_item->key - sizeof(struct to_free)); conf_item->value = ((char*)string_data->data) + (parser_item->value - sizeof(struct to_free)); #if HAVE_ATOMICS - conf_item->read = ATOMIC_VAR_INIT(false); + atomic_init(&conf_item->read, false); #else conf_item->read = false; #endif @@ -853,10 +861,6 @@ static void check_conf_(const pom_conf *conf, const char *func) { if (!conf) fatal_error("NULL configuration passed to %s", func); - if (conf->version_number != conf->main->version_number) - fatal_error("Section obtained via pom_conf_section is being used\n" - "(in %s) after pom_conf_merge was called.\n" - "This is not allowed.", func); } #define check_conf(conf) check_conf_(conf, __func__) @@ -886,6 +890,71 @@ pom_conf_next_item(const pom_conf *conf, pom_item_iter **p_iter) { return &iter->item; } +const char * +pom_conf_next_unread_key(const pom_conf *conf, pom_unread_key_iter **p_iter) { + check_conf(conf); + if (!p_iter) fatal_error("NULL iter passed to %s", __func__); + if (!*p_iter) { + *p_iter = malloc(sizeof **p_iter); + if (!*p_iter) return NULL; + (*p_iter)->conf = conf; + (*p_iter)->conf_item = conf->items; + } + pom_unread_key_iter *iter = *p_iter; + if (iter->conf != conf) + fatal_error("%s being called with inconsistent configurations for a single iterator", __func__); + for (; iter->conf_item < conf->items + conf->items_count; iter->conf_item++) { + if (!( + #if HAVE_ATOMICS + atomic_load_explicit(&iter->conf_item->read, memory_order_relaxed) + #else + iter->conf_item->read + #endif + )) { + const char *key = iter->conf_item->key + conf->prefix_len; + iter->conf_item++; + return key; + } + } + free(iter); + *p_iter = NULL; + return NULL; +} + +const char * +pom_conf_next_key(const pom_conf *conf, pom_key_iter **p_iter) { + check_conf(conf); + if (!p_iter) fatal_error("NULL iter passed to %s", __func__); + if (!*p_iter) { + *p_iter = malloc(sizeof **p_iter); + if (!*p_iter) return NULL; + (*p_iter)->conf = conf; + (*p_iter)->conf_item = conf->items; + (*p_iter)->prev_key = NULL; + } + pom_key_iter *iter = *p_iter; + if (iter->conf != conf) + fatal_error("%s being called with inconsistent configurations for a single iterator", __func__); + for (; iter->conf_item < conf->items + conf->items_count; iter->conf_item++) { + const char *key = iter->conf_item->key + conf->prefix_len; + size_t first_component_len = strcspn(key, "."); + if (!iter->prev_key || strncmp(iter->prev_key, key, first_component_len) != 0) { + // new first component + char *first_component = realloc(iter->prev_key, first_component_len + 1); + if (!first_component) return NULL; + iter->prev_key = first_component; + memcpy(first_component, key, first_component_len); + first_component[first_component_len] = 0; + iter->conf_item++; + return first_component; + } + } + free(iter->prev_key); + free(iter); + *p_iter = NULL; + return NULL; +} + static size_t conf_binary_search(const pom_conf *conf, const char *key, char nxt_char, bool *found) { size_t lo = 0; @@ -929,7 +998,7 @@ pom_conf_get(const pom_conf *conf, const char *key) { struct conf_item *item = conf_get_item(conf, key); if (item) { #if HAVE_ATOMICS - atomic_store(&item->read, true); + atomic_store_explicit(&item->read, true, memory_order_relaxed); #else item->read = true; #endif |