]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Feature] Libucl: Allow to sort keys in ucl objects
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 8 Jul 2019 12:01:08 +0000 (13:01 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 8 Jul 2019 12:01:08 +0000 (13:01 +0100)
contrib/libucl/lua_ucl.c
contrib/libucl/ucl.h
contrib/libucl/ucl_hash.c
contrib/libucl/ucl_hash.h
contrib/libucl/ucl_util.c

index b97387d9eb42459473454ffab28adc549b426b7c..049b1d08c7342de13d7a8096eb25a5700a0336ed 100644 (file)
@@ -1368,6 +1368,7 @@ lua_ucl_to_format (lua_State *L)
 {
        ucl_object_t *obj;
        int format = UCL_EMIT_JSON;
+       bool sort = false;
 
        if (lua_gettop (L) > 1) {
                if (lua_type (L, 2) == LUA_TNUMBER) {
@@ -1397,10 +1398,22 @@ lua_ucl_to_format (lua_State *L)
                                format = UCL_EMIT_MSGPACK;
                        }
                }
+
+               if (lua_isboolean (L, 3)) {
+                       sort = lua_toboolean (L, 3);
+               }
        }
 
        obj = ucl_object_lua_import (L, 1);
+
        if (obj != NULL) {
+
+               if (sort) {
+                       if (ucl_object_type (obj) == UCL_OBJECT) {
+                               ucl_object_sort_keys (obj, UCL_SORT_KEYS_RECURSIVE);
+                       }
+               }
+
                lua_ucl_to_string (L, obj, format);
                ucl_object_unref (obj);
        }
index 01542d3c79c00267848813779f462674328baa4d..b6b9f44c010736f5817561f23f1bc7f673fa676b 100644 (file)
@@ -800,6 +800,19 @@ UCL_EXTERN int ucl_object_compare_qsort (const ucl_object_t **o1,
 UCL_EXTERN void ucl_object_array_sort (ucl_object_t *ar,
                int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2));
 
+enum ucl_object_keys_sort_flags {
+       UCL_SORT_KEYS_DEFAULT = 0,
+       UCL_SORT_KEYS_ICASE = (1u << 0u),
+       UCL_SORT_KEYS_RECURSIVE = (1u << 1u),
+};
+/***
+ * Sorts keys in object in place
+ * @param obj
+ * @param how
+ */
+UCL_EXTERN void ucl_object_sort_keys (ucl_object_t *obj,
+               enum ucl_object_keys_sort_flags how);
+
 /**
  * Get the priority for specific UCL object
  * @param obj any ucl object
index 6594b2557023f39cfa0f2be109101747698ef275..a8e735d133e3ef989f290de996d37423abf40203 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "cryptobox.h"
 #include "libutil/str_util.h"
+#include "ucl.h"
 
 #include <time.h>
 #include <limits.h>
@@ -453,4 +454,52 @@ ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz)
        return true;
        e0:
        return false;
+}
+
+static int
+ucl_hash_cmp_icase (const void *a, const void *b)
+{
+       const ucl_object_t *oa = *(const ucl_object_t **)a,
+               *ob = *(const ucl_object_t **)b;
+
+       if (oa->keylen == ob->keylen) {
+               return rspamd_lc_cmp (oa->key, ob->key, oa->keylen);
+       }
+
+       return ((int)(oa->keylen)) - ob->keylen;
+}
+
+static int
+ucl_hash_cmp_case_sens (const void *a, const void *b)
+{
+       const ucl_object_t *oa = *(const ucl_object_t **)a,
+                       *ob = *(const ucl_object_t **)b;
+
+       if (oa->keylen == ob->keylen) {
+               return memcmp (oa->key, ob->key, oa->keylen);
+       }
+
+       return ((int)(oa->keylen)) - ob->keylen;
+}
+
+void
+ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl)
+{
+
+       if (fl & UCL_SORT_KEYS_ICASE) {
+               qsort (hashlin->ar.a, hashlin->ar.n, sizeof (ucl_object_t *),
+                               ucl_hash_cmp_icase);
+       }
+       else {
+               qsort (hashlin->ar.a, hashlin->ar.n, sizeof (ucl_object_t *),
+                               ucl_hash_cmp_case_sens);
+       }
+
+       if (fl & UCL_SORT_KEYS_RECURSIVE) {
+               for (size_t i = 0; i < hashlin->ar.n; i ++) {
+                       if (ucl_object_type (hashlin->ar.a[i]) == UCL_OBJECT) {
+                               ucl_hash_sort (hashlin->ar.a[i]->value.ov, fl);
+                       }
+               }
+       }
 }
\ No newline at end of file
index 805c8efb2d6768cb8f257b9a5975b69f6ad47cc5..c2d5517bbb86c3dfad5441a4bd69ecea39e9ce68 100644 (file)
@@ -104,4 +104,11 @@ bool ucl_hash_iter_has_next (ucl_hash_t *hashlin, ucl_hash_iter_t iter);
  */
 bool ucl_hash_reserve (ucl_hash_t *hashlin, size_t sz);
 
+/**
+ * Sorts keys in a hash
+ * @param hashlin
+ * @param fl
+ */
+void ucl_hash_sort (ucl_hash_t *hashlin, enum ucl_object_keys_sort_flags fl);
+
 #endif
index 0996caa776eb74d5a10b101ae9841920dc0d9228..5ef83e31b1ee8350eb78a3b7057ab56a4a691735 100644 (file)
@@ -3746,6 +3746,14 @@ ucl_object_array_sort (ucl_object_t *ar,
                        (int (*)(const void *, const void *))cmp);
 }
 
+void ucl_object_sort_keys (ucl_object_t *obj,
+               enum ucl_object_keys_sort_flags how)
+{
+       if (obj != NULL && obj->type == UCL_OBJECT) {
+               ucl_hash_sort (obj->value.ov, how);
+       }
+}
+
 #define PRIOBITS 4
 
 unsigned int