summaryrefslogtreecommitdiff
path: root/pom.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-09-12 14:44:41 -0400
committerpommicket <pommicket@gmail.com>2025-09-12 14:45:26 -0400
commit45393c79ab36bb64b933b44983a1cd8dffc0ebac (patch)
tree3efcdfd61a60ce02d08f4ff5d5ca0b445c1964a4 /pom.c
parent81c1cecf40b0733446fb0d945505155d87bf74c6 (diff)
Implement pom_conf_next_key, pom_conf_next_unread_key
Diffstat (limited to 'pom.c')
-rw-r--r--pom.c87
1 files changed, 78 insertions, 9 deletions
diff --git a/pom.c b/pom.c
index b795f3b..6aed7e8 100644
--- a/pom.c
+++ b/pom.c
@@ -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