From: Vsevolod Stakhov Date: Tue, 5 Nov 2013 14:28:41 +0000 (+0000) Subject: Fix load of ucl config. X-Git-Tag: 0.6.0~92 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e57950d1f51e5ee77e185adb459f8d66f05ce82d;p=rspamd.git Fix load of ucl config. --- diff --git a/src/lua/lua_cfg_file.c b/src/lua/lua_cfg_file.c index 0e22ec8f2..6d50153f4 100644 --- a/src/lua/lua_cfg_file.c +++ b/src/lua/lua_cfg_file.c @@ -140,7 +140,7 @@ lua_post_load_config (struct config_file *cfg) if (name != NULL && lua_istable (L, -1)) { obj = lua_rcl_obj_get (L, -1); if (obj != NULL) { - cfg->rcl_obj = ucl_object_insert_key (cfg->rcl_obj, obj, name, keylen, true); + cfg->rcl_obj = ucl_object_insert_key_merged (cfg->rcl_obj, obj, name, keylen, true); } } } diff --git a/src/ucl/include/ucl.h b/src/ucl/include/ucl.h index aaad4a9a9..7647ff3b1 100644 --- a/src/ucl/include/ucl.h +++ b/src/ucl/include/ucl.h @@ -306,6 +306,19 @@ ucl_object_frombool (bool bv) ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; +/** + * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, + * try to merge its content + * @param top destination object (will be created automatically if top is NULL) + * @param elt element to insert (must NOT be NULL) + * @param key key to associate with this object (either const or preallocated) + * @param keylen length of the key (or 0 for NULL terminated keys) + * @param copy_key make an internal copy of key + * @return new value of top object + */ +ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; + /** * Append an element to the array object * @param top destination object (will be created automatically if top is NULL) diff --git a/src/ucl/src/ucl_hash.c b/src/ucl/src/ucl_hash.c index a2d047088..d644da4f4 100644 --- a/src/ucl/src/ucl_hash.c +++ b/src/ucl/src/ucl_hash.c @@ -66,7 +66,7 @@ ucl_hash_iterate (ucl_hash_t *hashlin, ucl_hash_iter_t *iter) ucl_hash_node_t *elt = *iter; if (elt == NULL) { - if (hashlin->buckets == NULL) { + if (hashlin == NULL || hashlin->buckets == NULL) { return NULL; } elt = hashlin->buckets; @@ -103,3 +103,15 @@ ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen) } return NULL; } + +void +ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj) +{ + ucl_hash_node_t *found; + + HASH_FIND (hh, hashlin->buckets, obj->key, obj->keylen, found); + + if (found) { + HASH_DELETE (hh, hashlin->buckets, found); + } +} diff --git a/src/ucl/src/ucl_hash.h b/src/ucl/src/ucl_hash.h index 8c193821a..5c9b851b9 100644 --- a/src/ucl/src/ucl_hash.h +++ b/src/ucl/src/ucl_hash.h @@ -64,6 +64,11 @@ void ucl_hash_destroy (ucl_hash_t* hashlin, ucl_hash_free_func *func); */ void ucl_hash_insert (ucl_hash_t* hashlin, ucl_object_t *obj, const char *key, unsigned keylen); +/** + * Delete an element from the the hashtable. + */ +void ucl_hash_delete (ucl_hash_t* hashlin, ucl_object_t *obj); + /** * Searches an element in the hashtable. */ diff --git a/src/ucl/src/ucl_util.c b/src/ucl/src/ucl_util.c index 6f235aee6..422b2ea75 100644 --- a/src/ucl/src/ucl_util.c +++ b/src/ucl/src/ucl_util.c @@ -62,7 +62,7 @@ ucl_object_free_internal (ucl_object_t *obj, bool allow_rec) } else if (obj->type == UCL_OBJECT) { if (obj->value.ov != NULL) { - ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_obj_free); + ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)ucl_object_unref); } } tmp = obj->next; @@ -858,11 +858,12 @@ ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags return obj; } -ucl_object_t * -ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, - const char *key, size_t keylen, bool copy_key) +static ucl_object_t * +ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key, bool merge) { - ucl_object_t *found; + ucl_object_t *found, *cur; + ucl_object_iter_t it = NULL; const char *p; if (elt == NULL || key == NULL) { @@ -892,21 +893,61 @@ ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, elt->key = key; elt->keylen = keylen; + if (copy_key) { + ucl_copy_key_trash (elt); + } + found = ucl_hash_search_obj (top->value.ov, elt); if (!found) { top->value.ov = ucl_hash_insert_object (top->value.ov, elt); + DL_APPEND (found, elt); } - - DL_APPEND (found, elt); - - if (copy_key) { - ucl_copy_key_trash (elt); + else if (!merge) { + DL_APPEND (found, elt); + } + else { + if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) { + /* Insert old elt to new one */ + elt = ucl_object_insert_key_common (elt, found, found->key, found->keylen, copy_key, false); + ucl_hash_delete (top->value.ov, found); + top->value.ov = ucl_hash_insert_object (top->value.ov, elt); + } + else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) { + /* Insert new to old */ + found = ucl_object_insert_key_common (found, elt, elt->key, elt->keylen, copy_key, false); + } + else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) { + /* Mix two hashes */ + while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) { + ucl_object_ref (cur); + found = ucl_object_insert_key_common (found, cur, cur->key, cur->keylen, copy_key, false); + } + ucl_object_unref (elt); + } + else { + /* Just make a list of scalars */ + DL_APPEND (found, elt); + } } return top; } +ucl_object_t * +ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) +{ + return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false); +} + +ucl_object_t * +ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, + const char *key, size_t keylen, bool copy_key) +{ + return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true); +} + ucl_object_t * ucl_obj_get_keyl (ucl_object_t *obj, const char *key, size_t klen) {