From f06a9c54c61d9b562b8b21984a398bdc95f2b995 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 20 Oct 2021 10:38:55 +0100 Subject: [PATCH] [Minor] Add helpers to work with boxed int64 numbers --- src/lua/lua_util.c | 74 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/src/lua/lua_util.c b/src/lua/lua_util.c index fd3db0774..8d8a6db5e 100644 --- a/src/lua/lua_util.c +++ b/src/lua/lua_util.c @@ -716,9 +716,14 @@ static const struct luaL_reg utillib_f[] = { }; LUA_FUNCTION_DEF (int64, tostring); +LUA_FUNCTION_DEF (int64, fromstring); LUA_FUNCTION_DEF (int64, tonumber); LUA_FUNCTION_DEF (int64, hex); +static const struct luaL_reg int64lib_f[] = { + LUA_INTERFACE_DEF (int64, fromstring), + {NULL, NULL} +}; static const struct luaL_reg int64lib_m[] = { LUA_INTERFACE_DEF (int64, tostring), LUA_INTERFACE_DEF (int64, tonumber), @@ -3435,6 +3440,16 @@ lua_load_util (lua_State * L) return 1; } +static gint +lua_load_int64 (lua_State * L) +{ + lua_newtable (L); + luaL_register (L, NULL, int64lib_f); + + return 1; +} + + void luaopen_util (lua_State * L) { @@ -3443,6 +3458,7 @@ luaopen_util (lua_State * L) rspamd_lua_new_class (L, "rspamd{int64}", int64lib_m); lua_pop (L, 1); rspamd_lua_add_preload (L, "rspamd_util", lua_load_util); + rspamd_lua_add_preload (L, "rspamd_int64", lua_load_int64); } static int @@ -3450,13 +3466,69 @@ lua_int64_tostring (lua_State *L) { gint64 n = lua_check_int64 (L, 1); gchar buf[32]; + bool is_signed = false; + + if (lua_isboolean (L, 2)) { + is_signed = lua_toboolean (L, 2); + } - rspamd_snprintf (buf, sizeof (buf), "%uL", n); + if (is_signed) { + rspamd_snprintf(buf, sizeof(buf), "%L", n); + } + else { + rspamd_snprintf(buf, sizeof(buf), "%uL", n); + } lua_pushstring (L, buf); return 1; } +static int +lua_int64_fromstring (lua_State *L) +{ + struct rspamd_lua_text *t = lua_check_text_or_string (L, 1); + + if (t && t->len > 0) { + guint64 u64; + const char *p = t->start; + gsize len = t->len; + bool neg = false; + + /* + * We use complicated negation to allow both signed and unsinged values to + * fit into result. + * So we read int64 as unsigned and copy it to signed number. + * If we wanted u64 this allows to have the same memory representation of + * signed and unsigned. + * If we wanted signed i64 we still can use -1000500 and it will be parsed + * properly + */ + if (*p == '-') { + neg = true; + p ++; + len --; + } + if (!rspamd_strtou64(p, len, &u64)) { + lua_pushnil (L); + lua_pushstring (L, "invalid number"); + return 2; + } + + gint64* i64_p = lua_newuserdata (L, sizeof (gint64)); + rspamd_lua_setclass (L, "rspamd{int64}", -1); + memcpy (i64_p, &u64, sizeof(u64)); + + if (neg) { + *i64_p = -(*i64_p); + } + } + else { + + } + + return 1; +} + static int lua_int64_tonumber (lua_State *L) { -- 2.39.5