aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libucl
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-06-02 14:41:51 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-06-02 14:42:10 +0100
commitc1184c7823b41ee51750d7551403bbd9499a71ff (patch)
tree7a6d54c4b6993ffc5d2ad70f6ea69b9bafd4664b /contrib/libucl
parenteda600d5632e65b3a97b2faa794dc1aeb6689f96 (diff)
downloadrspamd-c1184c7823b41ee51750d7551403bbd9499a71ff.tar.gz
rspamd-c1184c7823b41ee51750d7551403bbd9499a71ff.zip
[Fix] Fix objects merging in UCL
Diffstat (limited to 'contrib/libucl')
-rw-r--r--contrib/libucl/ucl_util.c98
1 files changed, 83 insertions, 15 deletions
diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c
index 07af232d9..812655d2e 100644
--- a/contrib/libucl/ucl_util.c
+++ b/contrib/libucl/ucl_util.c
@@ -2195,7 +2195,7 @@ ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
while ((cur = ucl_object_iterate (elt, &it, true)) != NULL) {
tmp = ucl_object_ref (cur);
ucl_object_insert_key_common (found, tmp, cur->key,
- cur->keylen, copy_key, false, false);
+ cur->keylen, copy_key, true, false);
}
ucl_object_unref (elt);
}
@@ -2292,30 +2292,98 @@ ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
ucl_object_t *cur = NULL, *cp = NULL, *found = NULL;
ucl_object_iter_t iter = NULL;
- if (top == NULL || top->type != UCL_OBJECT || elt == NULL || elt->type != UCL_OBJECT) {
+ if (top == NULL || elt == NULL) {
return false;
}
- /* Mix two hashes */
- while ((cur = (ucl_object_t*)ucl_hash_iterate (elt->value.ov, &iter))) {
- if (copy) {
- cp = ucl_object_copy (cur);
+ if (top->type == UCL_ARRAY) {
+ if (elt->type == UCL_ARRAY) {
+ /* Merge two arrays */
+ return ucl_array_merge (top, elt, copy);
}
else {
- cp = ucl_object_ref (cur);
+ if (copy) {
+ ucl_array_append (top, ucl_object_copy (elt));
+
+ return true;
+ }
+ else {
+ ucl_array_append (top, ucl_object_ref (elt));
+
+ return true;
+ }
}
- found = __DECONST(ucl_object_t *, ucl_hash_search (top->value.ov, cp->key, cp->keylen));
- if (found == NULL) {
- /* The key does not exist */
- top->value.ov = ucl_hash_insert_object (top->value.ov, cp, false);
- top->len ++;
+ }
+ else if (top->type == UCL_OBJECT) {
+ if (elt->type == UCL_OBJECT) {
+ /* Mix two hashes */
+ while ((cur = (ucl_object_t *) ucl_hash_iterate (elt->value.ov,
+ &iter))) {
+
+ if (copy) {
+ cp = ucl_object_copy (cur);
+ } else {
+ cp = ucl_object_ref (cur);
+ }
+
+ found = __DECONST(ucl_object_t *,
+ ucl_hash_search (top->value.ov, cp->key, cp->keylen));
+
+ if (found == NULL) {
+ /* The key does not exist */
+ top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
+ false);
+ top->len++;
+ }
+ else {
+ /* The key already exists, merge it recursively */
+ if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
+ if (!ucl_object_merge (found, cp, copy)) {
+ return false;
+ }
+ }
+ else {
+ ucl_hash_replace (top->value.ov, found, cp);
+ ucl_object_unref (found);
+ }
+ }
+ }
}
else {
- /* The key already exists, replace it */
- ucl_hash_replace (top->value.ov, found, cp);
- ucl_object_unref (found);
+ if (copy) {
+ cp = ucl_object_copy (elt);
+ }
+ else {
+ cp = ucl_object_ref (elt);
+ }
+
+ found = __DECONST(ucl_object_t *,
+ ucl_hash_search (top->value.ov, cp->key, cp->keylen));
+
+ if (found == NULL) {
+ /* The key does not exist */
+ top->value.ov = ucl_hash_insert_object (top->value.ov, cp,
+ false);
+ top->len++;
+ }
+ else {
+ /* The key already exists, merge it recursively */
+ if (found->type == UCL_OBJECT || found->type == UCL_ARRAY) {
+ if (!ucl_object_merge (found, cp, copy)) {
+ return false;
+ }
+ }
+ else {
+ ucl_hash_replace (top->value.ov, found, cp);
+ ucl_object_unref (found);
+ }
+ }
}
}
+ else {
+ /* Cannot merge trivial objects */
+ return false;
+ }
return true;
}