From c325be435c64be57cf2210fa6936af0d425d0ce0 Mon Sep 17 00:00:00 2001 From: Philipp Janda Date: Fri, 27 Jul 2018 07:35:24 +0200 Subject: Add an implementation of `lua_getextraspace()`. --- README.md | 2 +- c-api/compat-5.3.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ c-api/compat-5.3.h | 4 +++- tests/test.lua | 19 ++++++++++++++---- tests/testmod.c | 16 +++++++++++++++ 5 files changed, 92 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b986584..ea2f079 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,7 @@ For Lua 5.1 additionally: * `lua_KContext` (see [here][14]) * `lua_KFunction` (see [here][14]) * `lua_dump` (extra `strip` parameter, ignored, see [here][15]) +* `lua_getextraspace` (limited compatibilitiy, may throw out-of-memory errors) * `lua_getfield` (return value) * `lua_geti` and `lua_seti` * `lua_getglobal` (return value) @@ -186,7 +187,6 @@ For Lua 5.1 additionally: [`lua-compat-5.2`][2] for a detailed list. * the following C API functions/macros: * `lua_isyieldable` - * `lua_getextraspace` * `lua_arith` (new operators missing) * `lua_push(v)fstring` (new formats missing) * `lua_upvalueid` (5.1) diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index bf81673..590e3c8 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c @@ -720,6 +720,63 @@ COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) { } +#ifndef LUA_EXTRASPACE +#define LUA_EXTRASPACE (sizeof(void*)) +#endif + +COMPAT53_API void *lua_getextraspace (lua_State *L) { + int is_main = 0; + void *ptr = NULL; + luaL_checkstack(L, 4, "not enough stack slots available"); + lua_pushliteral(L, "__compat53_extraspace"); + lua_pushvalue(L, -1); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_createtable(L, 0, 2); + lua_createtable(L, 0, 1); + lua_pushliteral(L, "k"); + lua_setfield(L, -2, "__mode"); + lua_setmetatable(L, -2); + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + lua_replace(L, -2); + is_main = lua_pushthread(L); + lua_rawget(L, -2); + ptr = lua_touserdata(L, -1); + if (!ptr) { + lua_pop(L, 1); + ptr = lua_newuserdata(L, LUA_EXTRASPACE); + if (is_main) { + memset(ptr, '\0', LUA_EXTRASPACE); + lua_pushthread(L); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + lua_pushboolean(L, 1); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } else { + void* mptr = NULL; + lua_pushboolean(L, 1); + lua_rawget(L, -3); + mptr = lua_touserdata(L, -1); + if (mptr) + memcpy(ptr, mptr, LUA_EXTRASPACE); + else + memset(ptr, '\0', LUA_EXTRASPACE); + lua_pop(L, 1); + lua_pushthread(L); + lua_pushvalue(L, -2); + lua_rawset(L, -4); + } + } + lua_pop(L, 2); + return ptr; +} + + COMPAT53_API int lua_isinteger (lua_State *L, int index) { if (lua_type(L, index) == LUA_TNUMBER) { lua_Number n = lua_tonumber(L, index); diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h index 8e10893..082a6a0 100644 --- a/c-api/compat-5.3.h +++ b/c-api/compat-5.3.h @@ -293,6 +293,9 @@ typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i); +#define lua_getextraspace COMPAT53_CONCAT(COMPAT53_PREFIX, _getextraspace) +COMPAT53_API void *lua_getextraspace (lua_State *L); + #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) COMPAT53_API int lua_isinteger (lua_State *L, int index); @@ -339,7 +342,6 @@ COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, /* XXX not implemented: * lua_isyieldable - * lua_getextraspace * lua_arith (new operators) * lua_pushfstring (new formats) */ diff --git a/tests/test.lua b/tests/test.lua index c2c0abf..9bb08da 100755 --- a/tests/test.lua +++ b/tests/test.lua @@ -664,14 +664,12 @@ print("isinteger", mod.isinteger(12.3)) print("isinteger", mod.isinteger(math.huge)) print("isinteger", mod.isinteger(math.sqrt(-1))) - ___'' print("rotate", mod.rotate(1, 1, 2, 3, 4, 5, 6)) print("rotate", mod.rotate(-1, 1, 2, 3, 4, 5, 6)) print("rotate", mod.rotate(4, 1, 2, 3, 4, 5, 6)) print("rotate", mod.rotate(-4, 1, 2, 3, 4, 5, 6)) - ___'' print("strtonum", mod.strtonum("+123")) print("strtonum", mod.strtonum(" 123 ")) @@ -679,13 +677,26 @@ print("strtonum", mod.strtonum("-1.23")) print("strtonum", mod.strtonum(" 123 abc")) print("strtonum", mod.strtonum("jkl")) - ___'' local a, b, c = mod.requiref() print("requiref", type(a), type(b), type(c), a.boolean, b.boolean, c.boolean, type(requiref1), type(requiref2), type(requiref3)) +___'' +mod.extraspace("abc") +print("getextraspace", mod.extraspace("xyz")) +local c = coroutine.wrap(function() + print("getextraspace", mod.extraspace("uvw")) + print("getextraspace", mod.extraspace("123")) + coroutine.yield() + print("getextraspace", mod.extraspace("asd")) +end) +c() +print("getextraspace", mod.extraspace("456")) +c() +print("getextraspace", mod.extraspace("789")) + ___'' local proxy, backend = {}, {} setmetatable(proxy, { __index = backend, __newindex = backend }) @@ -705,7 +716,7 @@ print("tonumber", mod.tonumber("error")) ___'' print("tointeger", mod.tointeger(12)) -print("tointeger", mod.tointeger(-12)) +print("tointeger", mod.tointeger(12)) print("tointeger", mod.tointeger(12.1)) print("tointeger", mod.tointeger(12.9)) print("tointeger", mod.tointeger(-12.1)) diff --git a/tests/testmod.c b/tests/testmod.c index cd56e76..345a8c9 100644 --- a/tests/testmod.c +++ b/tests/testmod.c @@ -63,6 +63,21 @@ static int test_getseti (lua_State *L) { } +#ifndef LUA_EXTRASPACE +#define LUA_EXTRASPACE (sizeof(void*)) +#endif + +static int test_getextraspace (lua_State *L) { + size_t len = 0; + char const* s = luaL_optlstring(L, 1, NULL, &len); + void* p = lua_getextraspace(L); + lua_pushstring(L, p); + if (s) + memcpy(p, s, len > LUA_EXTRASPACE-1 ? LUA_EXTRASPACE-1 : len+1); + return 1; +} + + /* additional tests for Lua5.1 */ #define NUP 3 @@ -307,6 +322,7 @@ static const luaL_Reg funcs[] = { { "strtonum", test_str2num }, { "requiref", test_requiref }, { "getseti", test_getseti }, + { "extraspace", test_getextraspace }, { "newproxy", test_newproxy }, { "arith", test_arith }, { "compare", test_compare }, -- cgit v1.2.3-55-g6feb