]> source.dussan.org Git - rspamd.git/commitdiff
Fix load of ucl config.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 5 Nov 2013 14:28:41 +0000 (14:28 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 5 Nov 2013 14:28:41 +0000 (14:28 +0000)
src/lua/lua_cfg_file.c
src/ucl/include/ucl.h
src/ucl/src/ucl_hash.c
src/ucl/src/ucl_hash.h
src/ucl/src/ucl_util.c

index 0e22ec8f2e9ae46ec923a4ce1059852fd6b25a5f..6d50153f46b7f96892ef1016f0886816c7d5270b 100644 (file)
@@ -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);
                                }
                        }
                }
index aaad4a9a99cf07fa8693493038f514491ec8c5c7..7647ff3b1b2ee23cefa884856a875e3ea4acc484 100644 (file)
@@ -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)
index a2d047088ffcc40ad6d6ac86dd5dbc5a1233409d..d644da4f49a89cfa8032805b0fadac144acf47df 100644 (file)
@@ -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);
+       }
+}
index 8c193821a7804c0b66e5a3922b22e0e0a36d7227..5c9b851b9f2937a480b7197f7181c78b285742bb 100644 (file)
@@ -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.
  */
index 6f235aee6599f2537422ddb30d31c4c8a9511992..422b2ea753bc046d65a4dc8357820c2b357016a0 100644 (file)
@@ -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)
 {