]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Add helpers to work with boxed int64 numbers
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 20 Oct 2021 09:38:55 +0000 (10:38 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 20 Oct 2021 09:38:55 +0000 (10:38 +0100)
src/lua/lua_util.c

index fd3db07749afaab2474e7c6f002e6fa445b681c7..8d8a6db5e57cd6b2dd78e52616efaeb7b237ab0e 100644 (file)
@@ -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)
 {