From: Eugene Blikh <bigbes@gmail.com>
To: tarantool-patches@freelists.org
Cc: Eugine Blikh <bigbes@gmail.com>
Subject: [tarantool-patches] [PATCH tarantool 1/2] Introduce luaT_tolstring
Date: Mon, 6 Aug 2018 10:16:59 +0300 [thread overview]
Message-ID: <bc3d570ba3084d208a5713386ffb4d2eb7340891.1533292738.git.bigbes@gmail.com> (raw)
In-Reply-To: <cover.1533292738.git.bigbes@gmail.com>
In-Reply-To: <cover.1533292738.git.bigbes@gmail.com>
From: Eugine Blikh <bigbes@gmail.com>
`lua_tostring`/`lua_tolstring` ignores metatable/boolean/nil and return NULL,
but sometimes it's needed to have similar behaviour, like lua functions
tostring. Lua 5.1 and LuaJIT ignores it by default, Lua 5.2 introduced
auxilary function luaL_to(l)string with supporting of __tostring. This
function is backport of Lua 5.1 "lauxlib.h"s luaL_tostring in the luaT
namespace.
---
| 1 +
src/lua/init.h | 8 --------
src/lua/utils.c | 31 +++++++++++++++++++++++++++++++
src/lua/utils.h | 6 ++++++
test/app-tap/module_api.c | 39 +++++++++++++++++++++++++++++++++++++++
test/app-tap/module_api.test.lua | 13 +++++++++++--
6 files changed, 88 insertions(+), 10 deletions(-)
--git a/extra/exports b/extra/exports
index 61a2e0a54..a27722910 100644
--- a/extra/exports
+++ b/extra/exports
@@ -130,6 +130,7 @@ luaT_error
luaT_call
luaT_cpcall
luaT_state
+luaT_tolstring
box_txn
box_txn_begin
box_txn_commit
diff --git a/src/lua/init.h b/src/lua/init.h
index ddf3e9195..1257ef510 100644
--- a/src/lua/init.h
+++ b/src/lua/init.h
@@ -59,14 +59,6 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv);
void
tarantool_lua_free();
-/**
- * This function exists because lua_tostring does not use
- * __tostring metamethod, and this metamethod has to be used
- * if we want to print Lua userdata correctly.
- */
-const char *
-tarantool_lua_tostring(struct lua_State *L, int index);
-
/**
* Load and execute start-up file
*
diff --git a/src/lua/utils.c b/src/lua/utils.c
index 2f0f4dcf8..afc44b581 100644
--- a/src/lua/utils.c
+++ b/src/lua/utils.c
@@ -941,6 +941,37 @@ luaT_cpcall(lua_State *L, lua_CFunction func, void *ud)
return 0;
}
+/**
+ * This function exists because lua_tostring does not use
+ * __tostring metamethod, and this metamethod has to be used
+ * if we want to print Lua userdata correctly.
+ */
+const char *
+luaT_tolstring(lua_State *L, int idx, size_t *len)
+{
+ if (!luaL_callmeta(L, idx, "__tostring")) {
+ switch (lua_type(L, idx)) {
+ case LUA_TNUMBER:
+ case LUA_TSTRING:
+ lua_pushvalue(L, idx);
+ break;
+ case LUA_TBOOLEAN: {
+ int val = lua_toboolean(L, idx);
+ lua_pushstring(L, val ? "true" : "false");
+ break;
+ }
+ case LUA_TNIL:
+ lua_pushliteral(L, "nil");
+ break;
+ default:
+ lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
+ lua_topointer(L, idx));
+ }
+ }
+
+ return lua_tolstring(L, -1, len);
+}
+
lua_State *
luaT_state(void)
{
diff --git a/src/lua/utils.h b/src/lua/utils.h
index 6b057af3e..fdfa95805 100644
--- a/src/lua/utils.h
+++ b/src/lua/utils.h
@@ -430,6 +430,12 @@ luaT_cpcall(lua_State *L, lua_CFunction func, void *ud);
LUA_API lua_State *
luaT_state(void);
+/**
+ * Like lua_tolstring, but supports metatables, booleans and nil properly.
+ */
+LUA_API const char *
+luaT_tolstring(lua_State *L, int idx, size_t *ssize);
+
/** \endcond public */
void
diff --git a/test/app-tap/module_api.c b/test/app-tap/module_api.c
index 01c1ee35b..4abe1af48 100644
--- a/test/app-tap/module_api.c
+++ b/test/app-tap/module_api.c
@@ -402,6 +402,44 @@ test_state(lua_State *L)
return 1;
}
+static int table_tostring(lua_State *L) {
+ lua_pushstring(L, "123");
+ return 1;
+}
+
+static int
+test_tostring(lua_State *L)
+{
+ /* original table */
+ lua_createtable(L, 0, 0);
+ /* meta-table */
+ lua_createtable(L, 0, 0);
+ /* pushing __tostring function */
+ lua_pushcfunction(L, table_tostring);
+ lua_setfield(L, -2, "__tostring");
+ /* setting metatable */
+ lua_setmetatable(L, -2);
+ assert(strcmp(luaT_tolstring(L, -1, NULL), "123") == 0);
+
+ lua_pushnumber(L, 1);
+ assert(strcmp(luaT_tolstring(L, -1, NULL), "1") == 0);
+
+ lua_createtable(L, 0, 0);
+ assert(strncmp(luaT_tolstring(L, -1, NULL), "table: ", 7) == 0);
+
+ lua_pushboolean(L, true);
+ assert(strcmp(luaT_tolstring(L, -1, NULL), "true") == 0);
+
+ lua_pushboolean(L, false);
+ assert(strcmp(luaT_tolstring(L, -1, NULL), "false") == 0);
+
+ lua_pushnil(L);
+ assert(strcmp(luaT_tolstring(L, -1, NULL), "nil") == 0);
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
LUA_API int
luaopen_module_api(lua_State *L)
{
@@ -428,6 +466,7 @@ luaopen_module_api(lua_State *L)
{"test_call", test_call},
{"test_cpcall", test_cpcall},
{"test_state", test_state},
+ {"test_tostring", test_tostring},
{NULL, NULL}
};
luaL_register(L, "module_api", lib);
diff --git a/test/app-tap/module_api.test.lua b/test/app-tap/module_api.test.lua
index d55f67c3b..f93257236 100755
--- a/test/app-tap/module_api.test.lua
+++ b/test/app-tap/module_api.test.lua
@@ -1,8 +1,12 @@
#!/usr/bin/env tarantool
+local fio = require('fio')
+
box.cfg{log = "tarantool.log"}
build_path = os.getenv("BUILDDIR")
-package.cpath = build_path .. '/test/app-tap/?.so;' .. build_path .. '/test/app-tap/?.dylib;'
+package.cpath = fio.pathjoin(build_path, 'test/app-tap/?.so' ) .. ';' ..
+ fio.pathjoin(build_path, 'test/app-tap/?.dylib') .. ';' ..
+ package.cpath
local function test_pushcdata(test, module)
test:plan(6)
@@ -33,11 +37,15 @@ local function test_pushcdata(test, module)
end
local test = require('tap').test("module_api", function(test)
- test:plan(22)
+ test:plan(23)
local status, module = pcall(require, 'module_api')
test:is(status, true, "module")
test:ok(status, "module is loaded")
if not status then
+ test:diag("Failed to load library:")
+ for _, line in ipairs(module:split("\n")) do
+ test:diag("%s", line)
+ end
return
end
@@ -57,4 +65,5 @@ local test = require('tap').test("module_api", function(test)
space:drop()
end)
+
os.exit(0)
--
2.16.2
next prev parent reply other threads:[~2018-08-06 7:18 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-08-06 7:16 [tarantool-patches] [PATCH tarantool 0/2] Using luaT_tolstring in error conversion function, instead lua_tostring Eugene Blikh
2018-08-06 7:16 ` Eugene Blikh [this message]
2018-08-06 7:17 ` [tarantool-patches] [PATCH tarantool 2/2] Using luaT_tolstring in " Eugene Blikh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bc3d570ba3084d208a5713386ffb4d2eb7340891.1533292738.git.bigbes@gmail.com \
--to=bigbes@gmail.com \
--cc=tarantool-patches@freelists.org \
--subject='Re: [tarantool-patches] [PATCH tarantool 1/2] Introduce luaT_tolstring' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox