aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2024-08-16 13:21:28 +0100
committerVsevolod Stakhov <vsevolod@rspamd.com>2024-08-16 13:21:28 +0100
commit05ea03c3b2cd36a35996e8dc0c59a6b1d0659df4 (patch)
tree99a8458d1c1587977f95e4a4493bdfd9ae85f8a3 /contrib
parente88ab8ee93e49b9f2ebc7d2026f5c5ad642ff808 (diff)
downloadrspamd-05ea03c3b2cd36a35996e8dc0c59a6b1d0659df4.tar.gz
rspamd-05ea03c3b2cd36a35996e8dc0c59a6b1d0659df4.zip
[Minor] Add some hacks to convert lua table into either object or an array
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libucl/lua_ucl.c161
1 files changed, 118 insertions, 43 deletions
diff --git a/contrib/libucl/lua_ucl.c b/contrib/libucl/lua_ucl.c
index c2b37b14c..19ac9cb12 100644
--- a/contrib/libucl/lua_ucl.c
+++ b/contrib/libucl/lua_ucl.c
@@ -44,6 +44,7 @@
#include "ucl.h"
#include "ucl_internal.h"
#include "lua_ucl.h"
+#include "kvec.h"
#include <strings.h>
/***
@@ -1423,67 +1424,141 @@ lua_ucl_newindex(lua_State *L)
obj = lua_ucl_object_get(L, 1);
int key_type = lua_type(L, 2);
- if (ucl_object_type(obj) == UCL_OBJECT && (key_type == LUA_TSTRING)) {
- lua_Integer keylen;
- const char *key = lua_tolstring(L, 2, &keylen);
+ if (ucl_object_type(obj) == UCL_OBJECT) {
+ if (key_type == LUA_TSTRING) {
+ lua_Integer keylen;
+ const char *key = lua_tolstring(L, 2, &keylen);
- ucl_object_t *value_obj = lua_ucl_object_get(L, 3);
- if (value_obj) {
- value_obj = ucl_object_ref(value_obj);
- }
- else {
- value_obj = ucl_object_lua_import(L, 3);
+ ucl_object_t *value_obj = lua_ucl_object_get(L, 3);
+ if (value_obj) {
+ value_obj = ucl_object_ref(value_obj);
+ }
+ else {
+ value_obj = ucl_object_lua_import(L, 3);
+ }
+
+ if (ucl_object_lookup_len(obj, key, keylen) != NULL) {
+ if (value_obj != NULL) {
+ ucl_object_replace_key(obj, value_obj, key, keylen, true);
+ }
+ else {
+ /* Delete key */
+ ucl_object_delete_keyl(obj, key, keylen);
+ }
+ }
+ else {
+ if (value_obj != NULL) {
+ ucl_object_insert_key(obj, value_obj, key, keylen, true);
+ }
+ /* Do nothing if value_obj is null, like Lua does */
+ }
}
+ else if (key_type == LUA_TNUMBER) {
+ /*
+ * We have some object but wanted it to be an array
+ * In Lua, this is allowed but UCL has distinction between array and object
+ * Here, we allow one thing: if an object is empty, and we want a numeric index, we convert it to an array
+ */
+ lua_Integer idx = lua_tointeger(L, 2);
+ if (idx == 1 && obj->len == 0 && obj->value.ov == NULL) {
+ /* UCL preallocate arrays, but it is not a requirement once av is NULL */
+ obj->type = UCL_ARRAY;
+ ucl_object_t *value_obj = lua_ucl_object_get(L, 3);
+ if (value_obj) {
+ value_obj = ucl_object_ref(value_obj);
+ }
+ else {
+ value_obj = ucl_object_lua_import(L, 3);
+ }
- if (ucl_object_lookup_len(obj, key, keylen) != NULL) {
- if (value_obj != NULL) {
- ucl_object_replace_key(obj, value_obj, key, keylen, true);
+ if (value_obj == NULL) {
+ return luaL_error(L, "invalid value type: %s", lua_typename(L, lua_type(L, 3)));
+ }
+ ucl_array_append(obj, value_obj);
}
else {
- /* Delete key */
- ucl_object_delete_keyl(obj, key, keylen);
+ return luaL_error(L, "invalid index type for an object: %s", lua_typename(L, key_type));
}
}
else {
- if (value_obj != NULL) {
- ucl_object_insert_key(obj, value_obj, key, keylen, true);
- }
- /* Do nothing if value_obj is null, like Lua does */
+ return luaL_error(L, "invalid index type for an object: %s", lua_typename(L, key_type));
}
return 0;
}
- else if (ucl_object_type(obj) == UCL_ARRAY && (key_type == LUA_TNUMBER)) {
- lua_Integer idx = lua_tointeger(L, 2);
+ else if (ucl_object_type(obj) == UCL_ARRAY) {
+ if (key_type == LUA_TNUMBER) {
+ lua_Integer idx = lua_tointeger(L, 2);
- ucl_object_t *value_obj = lua_ucl_object_get(L, 3);
- if (value_obj) {
- value_obj = ucl_object_ref(value_obj);
- }
- else {
- value_obj = ucl_object_lua_import(L, 3);
- }
+ ucl_object_t *value_obj = lua_ucl_object_get(L, 3);
+ if (value_obj) {
+ value_obj = ucl_object_ref(value_obj);
+ }
+ else {
+ value_obj = ucl_object_lua_import(L, 3);
+ }
- if (value_obj == NULL) {
- return luaL_error(L, "invalid value type: %s", lua_typename(L, lua_type(L, 3)));
- }
+ if (value_obj == NULL) {
+ return luaL_error(L, "invalid value type: %s", lua_typename(L, lua_type(L, 3)));
+ }
- /* Lua allows sparse arrays and ucl does not
- * So we have 3 options:
- * 1) Idx is some existing index, so we need to replace it
- * 3) Idx is #len, so we append it
- * Everything else is an error
- */
- if (idx == ucl_array_size(obj) + 1) {
- ucl_array_append(obj, value_obj);
+ /* Lua allows sparse arrays and ucl does not
+ * So we have 2 options:
+ * 1) Idx is some existing index, so we need to replace it
+ * 3) Idx is #len, so we append it
+ * Everything else is an error
+ */
+ if (idx == ucl_array_size(obj) + 1) {
+ ucl_array_append(obj, value_obj);
+ }
+ else if (idx >= 1 && idx <= ucl_array_size(obj)) {
+ ucl_array_replace_index(obj, value_obj, idx - 1);
+ }
+ else {
+ ucl_object_unref(value_obj);
+
+ return luaL_error(L, "invalid index for array: %d", (int) idx);
+ }
}
- else if (idx >= 1 && idx <= ucl_array_size(obj)) {
- ucl_array_replace_index(obj, value_obj, idx - 1);
+ else if (key_type == LUA_TSTRING) {
+ /*
+ * We have some array but wanted it to be an object
+ * In Lua, this is allowed but UCL has distinction between array and object
+ * Here, we allow one thing: if an array is empty, and we want a string index, we convert it to an object
+ * The biggest issue is that ucl array is preallocated in general, so we need to free it somehow
+ */
+ /*
+ * Dirty hacks are here
+ */
+ kvec_t(ucl_object_t *) *real_ar = obj->value.av;
+
+ if (real_ar) {
+ kv_destroy(*real_ar);
+ }
+ UCL_FREE(sizeof(*real_ar), real_ar);
+ obj->value.av = NULL;
+ obj->type = UCL_OBJECT;
+
+ lua_Integer keylen;
+ const char *key = lua_tolstring(L, 2, &keylen);
+
+ ucl_object_t *value_obj = lua_ucl_object_get(L, 3);
+ if (value_obj) {
+ value_obj = ucl_object_ref(value_obj);
+ }
+ else {
+ value_obj = ucl_object_lua_import(L, 3);
+ }
+
+ if (value_obj) {
+ ucl_object_insert_key(obj, value_obj, key, keylen, true);
+ }
+ else {
+ return luaL_error(L, "invalid value type: %s", lua_typename(L, lua_type(L, 3)));
+ }
}
else {
- ucl_object_unref(value_obj);
-
- return luaL_error(L, "invalid index for array: %d", (int) idx);
+ return luaL_error(L, "invalid index type for an array: %s", lua_typename(L, key_type));
}
return 0;