[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: luaL_rawtostring needed (Was: Proposal: debug.topointer)
- From: Dirk Laurie <dirk.laurie@...>
- Date: Tue, 28 Jul 2015 12:54:29 +0200
2015-07-28 5:45 GMT+02:00 Daurnimator <quae@daurnimator.com>:
> - __tostring metamethods that have previously needed a `rawtostring`
I thought implementing `rawtostring` would be trivial. However, there
is no `lua_rawtostring` or `luaL_rawtostring`.
`LuaB_tostring` is very short, though:
static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1);
luaL_tolstring(L, 1, NULL);
return 1;
}
The manual says this of `luaL_tolstring`:
If the value has a metatable with a "__tostring" field, then
luaL_tolstring calls the corresponding metamethod with the value as
argument, and uses the result of the call as its result.
It says nothing of the kind at `lua_tostring`. Instead, it says:
The Lua value must be a string or a number; otherwise, the function
returns NULL.
Therefore the functionality that represents tables, etc sits inside
luaL_tolstring, bundled in with the metatable test.
It would be more flexible to unbundle that functionality, i.e. to have
a function luaL_rawtostring that would be called if there is no
metamethod, but could also be called by itself.
diff -ru lua-5.3.1/src/lauxlib.c lua-5.3.1-patched/src/lauxlib.c
--- lua-5.3.1/src/lauxlib.c 2015-02-03 19:38:24.000000000 +0200
+++ lua-5.3.1-patched/src/lauxlib.c 2015-07-28 12:27:52.559150119 +0200
@@ -744,35 +744,39 @@
return l;
}
-
-LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
- if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
- switch (lua_type(L, idx)) {
- case LUA_TNUMBER: {
- if (lua_isinteger(L, idx))
- lua_pushfstring(L, "%I", lua_tointeger(L, idx));
- else
- lua_pushfstring(L, "%f", lua_tonumber(L, idx));
- break;
- }
- case LUA_TSTRING:
- lua_pushvalue(L, idx);
- break;
- case LUA_TBOOLEAN:
- lua_pushstring(L, (lua_toboolean(L, idx) ? "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));
- break;
+LUALIB_API const char *luaL_rawtolstring (lua_State *L, int idx, size_t *len) { switch (lua_type(L, idx)) {
+ case LUA_TNUMBER: {
+ if (lua_isinteger(L, idx))
+ lua_pushfstring(L, "%I", lua_tointeger(L, idx));
+ else
+ lua_pushfstring(L, "%f", lua_tonumber(L, idx));
+ break;
}
+ case LUA_TSTRING:
+ lua_pushvalue(L, idx);
+ break;
+ case LUA_TBOOLEAN:
+ lua_pushstring(L, (lua_toboolean(L, idx) ? "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));
+ break;
}
return lua_tolstring(L, -1, len);
}
+LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
+ idx = lua_absindex(L, idx);
+ int has_meta = luaL_getmetafield(L, idx, "__tostring");
+ if (has_meta == LUA_TNIL) return luaL_rawtolstring(L, idx, len);
+ lua_pushvalue(L, idx);
+ lua_call(L, 1, 1);
+ return lua_tolstring(L, -1, len);
+}
/*
** {======================================================
diff -ru lua-5.3.1/src/lauxlib.h lua-5.3.1-patched/src/lauxlib.h
--- lua-5.3.1/src/lauxlib.h 2014-10-29 18:11:17.000000000 +0200
+++ lua-5.3.1-patched/src/lauxlib.h 2015-07-28 12:07:09.831182752 +0200
@@ -34,6 +34,7 @@
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
+LUALIB_API const char *(luaL_rawtolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
diff -ru lua-5.3.1/src/lbaselib.c lua-5.3.1-patched/src/lbaselib.c
--- lua-5.3.1/src/lbaselib.c 2015-03-28 21:14:47.000000000 +0200
+++ lua-5.3.1-patched/src/lbaselib.c 2015-07-28 12:06:03.447184495 +0200
@@ -458,13 +458,18 @@
return finishpcall(L, status, 2);
}
-
static int luaB_tostring (lua_State *L) {
luaL_checkany(L, 1);
luaL_tolstring(L, 1, NULL);
return 1;
}
+/* DPL 2015-07-28 */
+static int luaB_rawtostring (lua_State *L) {
+ luaL_checkany(L, 1);
+ luaL_rawtolstring(L, 1, NULL);
+ return 1;
+}
static const luaL_Reg base_funcs[] = {
{"assert", luaB_assert},
@@ -486,6 +491,7 @@
{"rawlen", luaB_rawlen},
{"rawget", luaB_rawget},
{"rawset", luaB_rawset},
+ {"rawtostring", luaB_rawtostring}, /* DPL 2015-07-28 */
{"select", luaB_select},
{"setmetatable", luaB_setmetatable},
{"tonumber", luaB_tonumber},
@@ -509,6 +515,8 @@
lua_setfield(L, -2, "_G");
/* set global _VERSION */
lua_pushliteral(L, LUA_VERSION);
+ lua_pushliteral(L, " patched by DPL");
+ lua_concat(L,2);
lua_setfield(L, -2, "_VERSION");
/* set function 'type' with proper upvalues */
for (i = 0; i < LUA_NUMTAGS; i++) /* push all type names as upvalues */