diff options
Diffstat (limited to 'common.c')
-rw-r--r-- | common.c | 39 |
1 files changed, 37 insertions, 2 deletions
@@ -488,6 +488,18 @@ toupper_ascii (int c) return c >= 'A' && c <= 'Z' ? c : c - ('a' - 'A'); } +static void +split_str (const char *s, char delimiter, struct str_vector *out) +{ + const char *begin = s, *end; + while ((end = strchr (begin, delimiter))) + { + str_vector_add_owned (out, xstrndup (begin, end - begin)); + begin = ++end; + } + str_vector_add (out, begin); +} + // --- Advanced configuration -------------------------------------------------- // This is a new configuration format, superseding the one currently present @@ -718,10 +730,33 @@ config_item_set_from (struct config_item_ *self, struct config_item_ *source, } static struct config_item_ * -config_item_get (struct config_item_ *self, const char *path) +config_item_get (struct config_item_ *self, const char *path, struct error **e) { hard_assert (self->type == CONFIG_ITEM_OBJECT); - // TODO + + struct str_vector v; + str_vector_init (&v); + split_str (path, '.', &v); + + struct config_item_ *result = NULL; + size_t i = 0; + while (true) + { + const char *key = v.vector[i]; + if (!*key) + error_set (e, "empty path element"); + else if (!(self = str_map_find (&self->value.object, key))) + error_set (e, "`%s' not found in object", key); + else if (++i == v.len) + result = self; + else if (self->type != CONFIG_ITEM_OBJECT) + error_set (e, "`%s' is not an object", key); + else + continue; + break; + } + str_vector_free (&v); + return result; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |