diff options
author | pommicket <pommicket@gmail.com> | 2025-09-12 13:10:53 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-09-12 13:10:53 -0400 |
commit | 81c1cecf40b0733446fb0d945505155d87bf74c6 (patch) | |
tree | 2649bf5e70359c24e8c906438efe48304fa1be9c /pom.c | |
parent | 9865b70c855500ea3cae76fb8c9986bdf6f249ca (diff) |
Getting items
Diffstat (limited to 'pom.c')
-rw-r--r-- | pom.c | 109 |
1 files changed, 106 insertions, 3 deletions
@@ -13,12 +13,18 @@ #else #define ATTRIBUTE_PRINTF(fmt, args) #endif + #if _MSC_VER >= 1600 #define PRINTF_FORMAT_STRING _Printf_format_string_ #else #define PRINTF_FORMAT_STRING #endif +#if __STDC_VERSION__ >= 201112 && !defined(__STDC_NO_ATOMICS__) +#define HAVE_ATOMICS 1 +#include <stdatomic.h> +#endif + struct pom_error { const pom_error *next; const char *file; @@ -44,7 +50,7 @@ struct pom_conf { // to detect when a section is used after a merge uint64_t version_number; size_t prefix_len; - const struct conf_item *items; + struct conf_item *items; size_t items_count; }; @@ -58,6 +64,11 @@ 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 { @@ -650,6 +661,13 @@ static void conf_free(struct main_conf *conf) { free(conf); } +static int +conf_item_cmp_qsort(const void *va, const void *vb) { + const struct conf_item *item_a = va; + const struct conf_item *item_b = vb; + return strcmp(item_a->key, item_b->key); +} + pom_conf * parser_finish(struct parser *parser) { if (parser->out_of_memory || parser->errors.count) { @@ -667,6 +685,7 @@ parser_finish(struct parser *parser) { parser_out_of_memory(parser); return NULL; } + strcpy(filename, parser->filename); // we made room for the to_free header in pom_load. struct to_free *string_data = (struct to_free *)parser->string_data.array; // stop this from getting freed @@ -680,8 +699,14 @@ parser_finish(struct parser *parser) { conf_item->line = parser_item->line; 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); +#else + conf_item->read = false; +#endif conf_item->section = NULL; // TODO } + qsort(conf->items, conf->items_count, sizeof *conf->items, conf_item_cmp_qsort); pom_conf *root = conf_calloc(conf, 1, sizeof *root); root->items = conf->items; root->items_count = conf->items_count; @@ -825,7 +850,7 @@ pom_conf_free(pom_conf *conf) { } static void -check_conf(const pom_conf *conf, const char *func) { +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) @@ -833,7 +858,7 @@ check_conf(const pom_conf *conf, const char *func) { "(in %s) after pom_conf_merge was called.\n" "This is not allowed.", func); } -#define check_conf(conf) check_conf(conf, __func__) +#define check_conf(conf) check_conf_(conf, __func__) const pom_item * pom_conf_next_item(const pom_conf *conf, pom_item_iter **p_iter) { @@ -860,3 +885,81 @@ pom_conf_next_item(const pom_conf *conf, pom_item_iter **p_iter) { iter->conf_item++; return &iter->item; } + +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); + if (!key) + fatal_error("%s called with key = NULL", func); + bool found; + size_t i = conf_binary_search(conf, key, 0, &found); + if (found) + return &conf->items[i]; + else + return NULL; +} +#define conf_get_item(conf, key) conf_get_item(conf, key, __func__) + +const char * +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); + #else + item->read = true; + #endif + return item->value; + } else { + return NULL; + } +} + +const char * +pom_conf_get_or_default(const pom_conf *conf, const char *key, const char *dflt) { + const char *value = pom_conf_get(conf, key); + return value ? value : dflt; +} + +bool +pom_conf_has(const pom_conf *conf, const char *key) { + return conf_get_item(conf, key) != NULL; +} + +bool +pom_conf_location(const pom_conf *conf, const char *key, const char **file, uint64_t *line) { + struct conf_item *item = conf_get_item(conf, key); + if (item) { + if (file) *file = item->file; + if (line) *line = item->line; + return true; + } else { + if (file) *file = NULL; + if (line) *line = 0; + return false; + } +} |