aboutsummaryrefslogtreecommitdiffstats
path: root/src/ucl
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2013-11-05 14:28:41 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2013-11-05 14:28:41 +0000
commite57950d1f51e5ee77e185adb459f8d66f05ce82d (patch)
tree2f7e486fd9692dd11f1a655a8dc45be9a88035e8 /src/ucl
parentd75ece11c02ecd3b05ad3ded2270055dc812a2f7 (diff)
downloadrspamd-e57950d1f51e5ee77e185adb459f8d66f05ce82d.tar.gz
rspamd-e57950d1f51e5ee77e185adb459f8d66f05ce82d.zip
Fix load of ucl config.
Diffstat (limited to 'src/ucl')
-rw-r--r--src/ucl/include/ucl.h13
-rw-r--r--src/ucl/src/ucl_hash.c14
-rw-r--r--src/ucl/src/ucl_hash.h5
-rw-r--r--src/ucl/src/ucl_util.c61
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;