diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-07-08 13:01:08 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2019-07-08 13:01:08 +0100 |
commit | 9b74e57ad3fb694741fdcf5e27a046fbe99a40f7 (patch) | |
tree | 3080fb43edac872ca98c4fe3c5953e59d02ceef9 /contrib/libucl | |
parent | 3d8f5c5e7f4ee08aa033805313fe9b5585a2d4fa (diff) | |
download | rspamd-9b74e57ad3fb694741fdcf5e27a046fbe99a40f7.tar.gz rspamd-9b74e57ad3fb694741fdcf5e27a046fbe99a40f7.zip |
[Feature] Libucl: Allow to sort keys in ucl objects
Diffstat (limited to 'contrib/libucl')
-rw-r--r-- | contrib/libucl/lua_ucl.c | 13 | ||||
-rw-r--r-- | contrib/libucl/ucl.h | 13 | ||||
-rw-r--r-- | contrib/libucl/ucl_hash.c | 49 | ||||
-rw-r--r-- | contrib/libucl/ucl_hash.h | 7 | ||||
-rw-r--r-- | contrib/libucl/ucl_util.c | 8 |
5 files changed, 90 insertions, 0 deletions
diff --git a/contrib/libucl/lua_ucl.c b/contrib/libucl/lua_ucl.c index b97387d9e..049b1d08c 100644 --- a/contrib/libucl/lua_ucl.c +++ b/contrib/libucl/lua_ucl.c @@ -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); } diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h index 01542d3c7..b6b9f44c0 100644 --- a/contrib/libucl/ucl.h +++ b/contrib/libucl/ucl.h @@ -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 diff --git a/contrib/libucl/ucl_hash.c b/contrib/libucl/ucl_hash.c index 6594b2557..a8e735d13 100644 --- a/contrib/libucl/ucl_hash.c +++ b/contrib/libucl/ucl_hash.c @@ -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 diff --git a/contrib/libucl/ucl_hash.h b/contrib/libucl/ucl_hash.h index 805c8efb2..c2d5517bb 100644 --- a/contrib/libucl/ucl_hash.h +++ b/contrib/libucl/ucl_hash.h @@ -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 diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c index 0996caa77..5ef83e31b 100644 --- a/contrib/libucl/ucl_util.c +++ b/contrib/libucl/ucl_util.c @@ -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 |