diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-11-05 14:28:41 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-11-05 14:28:41 +0000 |
commit | e57950d1f51e5ee77e185adb459f8d66f05ce82d (patch) | |
tree | 2f7e486fd9692dd11f1a655a8dc45be9a88035e8 /src/ucl | |
parent | d75ece11c02ecd3b05ad3ded2270055dc812a2f7 (diff) | |
download | rspamd-e57950d1f51e5ee77e185adb459f8d66f05ce82d.tar.gz rspamd-e57950d1f51e5ee77e185adb459f8d66f05ce82d.zip |
Fix load of ucl config.
Diffstat (limited to 'src/ucl')
-rw-r--r-- | src/ucl/include/ucl.h | 13 | ||||
-rw-r--r-- | src/ucl/src/ucl_hash.c | 14 | ||||
-rw-r--r-- | src/ucl/src/ucl_hash.h | 5 | ||||
-rw-r--r-- | src/ucl/src/ucl_util.c | 61 |
4 files changed, 82 insertions, 11 deletions
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 @@ -307,6 +307,19 @@ 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) * @param eltelement to append (must NOT be 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 @@ -65,6 +65,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. */ ucl_object_t* ucl_hash_search (ucl_hash_t* hashlin, const char *key, unsigned keylen); 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,22 +893,62 @@ 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) { ucl_object_t *ret, srch; |