Browse Source

[Feature] Libucl: Allow to sort keys in ucl objects

tags/2.0
Vsevolod Stakhov 4 years ago
parent
commit
9b74e57ad3
5 changed files with 90 additions and 0 deletions
  1. 13
    0
      contrib/libucl/lua_ucl.c
  2. 13
    0
      contrib/libucl/ucl.h
  3. 49
    0
      contrib/libucl/ucl_hash.c
  4. 7
    0
      contrib/libucl/ucl_hash.h
  5. 8
    0
      contrib/libucl/ucl_util.c

+ 13
- 0
contrib/libucl/lua_ucl.c View 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);
}

+ 13
- 0
contrib/libucl/ucl.h View 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

+ 49
- 0
contrib/libucl/ucl_hash.c View 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);
}
}
}
}

+ 7
- 0
contrib/libucl/ucl_hash.h View 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

+ 8
- 0
contrib/libucl/ucl_util.c View 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

Loading…
Cancel
Save