Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH v1 1/1] lua: replace tonumber64() with misc.tonumber64()
@ 2020-11-16  9:34 imeevma
  2020-11-25 19:16 ` Sergey Kaplun
  0 siblings, 1 reply; 2+ messages in thread
From: imeevma @ 2020-11-16  9:34 UTC (permalink / raw)
  To: imun; +Cc: tarantool-patches

This patch replaces tonumber64() with misc.tonumber(), which works in a
similar way, but always returns 64-bit integer cdata.

Closes #4738
---
https://github.com/tarantool/tarantool/issues/4738
https://github.com/tarantool/tarantool/tree/imeevma/gh-4738-move-tonumber64-to-luajit

@ChangeLog
 - Now tonumber64() always returns 64-bit integer cdata (gh-4738).

 src/box/lua/schema.lua |   3 +
 src/lua/init.c         | 121 -----------------------------------------
 test/box/misc.result   |  10 ++--
 test/box/misc.test.lua |   8 +--
 4 files changed, 12 insertions(+), 130 deletions(-)

diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index b77c07bc8..eb72b12a5 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1,6 +1,7 @@
 -- schema.lua (internal file)
 --
 local ffi = require('ffi')
+local misc = require('misc')
 local msgpack = require('msgpack')
 local fun = require('fun')
 local log = require('log')
@@ -11,6 +12,8 @@ local function setmap(table)
     return setmetatable(table, { __serialize = 'map' })
 end
 
+tonumber64 = misc.tonumber64
+
 local builtin = ffi.C
 
 -- performance fixup for hot functions
diff --git a/src/lua/init.c b/src/lua/init.c
index a0b2fc775..a46dc6136 100644
--- a/src/lua/init.c
+++ b/src/lua/init.c
@@ -174,126 +174,6 @@ static const char *lua_modules[] = {
  * {{{ box Lua library: common functions
  */
 
-/**
- * Convert lua number or string to lua cdata 64bit number.
- */
-static int
-lbox_tonumber64(struct lua_State *L)
-{
-	luaL_checkany(L, 1);
-	int base = luaL_optint(L, 2, -1);
-	luaL_argcheck(L, (2 <= base && base <= 36) || base == -1, 2,
-		      "base out of range");
-	switch (lua_type(L, 1)) {
-	case LUA_TNUMBER:
-		base = (base == -1 ? 10 : base);
-		if (base != 10)
-			return luaL_argerror(L, 1, "string expected");
-		lua_settop(L, 1); /* return original value as is */
-		return 1;
-	case LUA_TSTRING:
-	{
-		size_t argl = 0;
-		const char *arg = luaL_checklstring(L, 1, &argl);
-		/* Trim whitespaces at begin/end */
-		while (argl > 0 && isspace(arg[argl - 1])) {
-			argl--;
-		}
-		while (isspace(*arg)) {
-			arg++; argl--;
-		}
-
-		/*
-		 * Check if we're parsing custom format:
-		 * 1) '0x' or '0X' trim in case of base == 16 or base == -1
-		 * 2) '0b' or '0B' trim in case of base == 2  or base == -1
-		 * 3) '-' for negative numbers
-		 * 4) LL, ULL, LLU - trim, but only for base == 2 or
-		 *    base == 16 or base == -1. For consistency do not bother
-		 *    with any non-common bases, since user may have specified
-		 *    base >= 22, in which case 'L' will be a digit.
-		 */
-		char negative = 0;
-		if (arg[0] == '-') {
-			arg++; argl--;
-			negative = 1;
-		}
-		if (argl > 2 && arg[0] == '0') {
-			if ((arg[1] == 'x' || arg[1] == 'X') &&
-			    (base == 16 || base == -1)) {
-				base = 16; arg += 2; argl -= 2;
-			} else if ((arg[1] == 'b' || arg[1] == 'B') &&
-			           (base == 2 || base == -1)) {
-				base = 2;  arg += 2; argl -= 2;
-			}
-		}
-		bool ull = false;
-		if (argl > 2 && (base == 2 || base == 16 || base == -1)) {
-			if (arg[argl - 1] == 'u' || arg[argl - 1] == 'U') {
-				ull = true;
-				--argl;
-			}
-			if ((arg[argl - 1] == 'l' || arg[argl - 1] == 'L') &&
-			    (arg[argl - 2] == 'l' || arg[argl - 2] == 'L'))
-				argl -= 2;
-			else {
-				ull = false;
-				goto skip;
-			}
-			if (!ull && (arg[argl - 1] == 'u' ||
-				     arg[argl - 1] == 'U')) {
-				ull = true;
-				--argl;
-			}
-		}
-skip:		base = (base == -1 ? 10 : base);
-		errno = 0;
-		char *arge;
-		unsigned long long result = strtoull(arg, &arge, base);
-		if (errno == 0 && arge == arg + argl) {
-			if (argl == 0) {
-				lua_pushnil(L);
-			} else if (negative) {
-				/*
-				 * To test overflow, consider
-				 *  result > -INT64_MIN;
-				 *  result - 1 > -INT64_MIN - 1;
-				 * Assumption:
-				 *  INT64_MAX == -(INT64_MIN + 1);
-				 * Finally,
-				 *  result - 1 > INT64_MAX;
-				 */
-				if (ull)
-					luaL_pushuint64(L, (UINT64_MAX - result) + 1);
-				else if (result != 0 && result - 1 > INT64_MAX)
-					lua_pushnil(L);
-				else
-					luaL_pushint64(L, -result);
-			} else {
-				luaL_pushuint64(L, result);
-			}
-			return 1;
-		}
-		break;
-	} /* LUA_TSTRING */
-	case LUA_TCDATA:
-	{
-		base = (base == -1 ? 10 : base);
-		if (base != 10)
-			return luaL_argerror(L, 1, "string expected");
-		uint32_t ctypeid = 0;
-		luaL_checkcdata(L, 1, &ctypeid);
-		if (ctypeid >= CTID_INT8 && ctypeid <= CTID_DOUBLE) {
-			lua_pushvalue(L, 1);
-			return 1;
-		}
-		break;
-	} /* LUA_TCDATA */
-	}
-	lua_pushnil(L);
-	return 1;
-}
-
 /* }}} */
 
 /**
@@ -446,7 +326,6 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv)
 	/* Initialize ffi to enable luaL_pushcdata/luaL_checkcdata functions */
 	luaL_loadstring(L, "return require('ffi')");
 	lua_call(L, 0, 0);
-	lua_register(L, "tonumber64", lbox_tonumber64);
 
 	tarantool_lua_utf8_init(L);
 	tarantool_lua_utils_init(L);
diff --git a/test/box/misc.result b/test/box/misc.result
index 714d5ee79..f6b72ccee 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -290,7 +290,7 @@ tonumber64('123')
 ---
 - 123
 ...
-type(tonumber64('4294967296')) == 'number'
+type(tonumber64('4294967296')) == 'cdata'
 ---
 - true
 ...
@@ -329,7 +329,7 @@ tonumber64(tonumber64(2))
 ...
 tostring(tonumber64(tonumber64(3)))
 ---
-- '3'
+- 3ULL
 ...
 --  A test case for Bug#1131108 'tonumber64 from negative int inconsistency'
 tonumber64(-1)
@@ -364,11 +364,11 @@ tonumber64(-1.0)
 ---
 - -1
 ...
-tostring(tonumber64('1234567890123')) == '1234567890123'
+tostring(tonumber64('1234567890123')) == '1234567890123ULL'
 ---
 - true
 ...
-tostring(tonumber64('12345678901234')) == '12345678901234'
+tostring(tonumber64('12345678901234')) == '12345678901234ULL'
 ---
 - true
 ...
@@ -403,7 +403,7 @@ tonumber64('-9223372036854775809') == nil
 ---
 - true
 ...
-tostring(tonumber64('0')) == '0'
+tostring(tonumber64('0')) == '0ULL'
 ---
 - true
 ...
diff --git a/test/box/misc.test.lua b/test/box/misc.test.lua
index 63cbe2bc5..c642cf95f 100644
--- a/test/box/misc.test.lua
+++ b/test/box/misc.test.lua
@@ -105,7 +105,7 @@ tonumber64()
 tonumber64('invalid number')
 tonumber64(123)
 tonumber64('123')
-type(tonumber64('4294967296')) == 'number'
+type(tonumber64('4294967296')) == 'cdata'
 tonumber64('9223372036854775807') == tonumber64('9223372036854775807')
 tonumber64('9223372036854775807') - tonumber64('9223372036854775800')
 tonumber64('18446744073709551615') == tonumber64('18446744073709551615')
@@ -125,8 +125,8 @@ tonumber64(-1ULL)
 -1ULL
 tonumber64(-1.0)
 6LL - 7LL
-tostring(tonumber64('1234567890123')) == '1234567890123'
-tostring(tonumber64('12345678901234')) == '12345678901234'
+tostring(tonumber64('1234567890123')) == '1234567890123ULL'
+tostring(tonumber64('12345678901234')) == '12345678901234ULL'
 tostring(tonumber64('123456789012345')) == '123456789012345ULL'
 tostring(tonumber64('1234567890123456')) == '1234567890123456ULL'
 
@@ -138,7 +138,7 @@ tostring(tonumber64('18446744073709551615')) == '18446744073709551615ULL'
 tonumber64('18446744073709551616') == nil
 tostring(tonumber64('-9223372036854775808')) == '-9223372036854775808LL'
 tonumber64('-9223372036854775809') == nil
-tostring(tonumber64('0')) == '0'
+tostring(tonumber64('0')) == '0ULL'
 
 --
 -- gh-3431: tonumber of strings with ULL.
-- 
2.25.1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-11-25 19:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-16  9:34 [Tarantool-patches] [PATCH v1 1/1] lua: replace tonumber64() with misc.tonumber64() imeevma
2020-11-25 19:16 ` Sergey Kaplun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox