summaryrefslogtreecommitdiff
path: root/pom.c
diff options
context:
space:
mode:
Diffstat (limited to 'pom.c')
-rw-r--r--pom.c147
1 files changed, 94 insertions, 53 deletions
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);