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: 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); }
/** * @brief Works more or less like Lua's builtin print. */ static int AIL_print (lua_State *L) { int i; const int n = lua_gettop(L); /* number of arguments */ for (i = 1; i <= n; i++) { const char *s; bool meta = false; lua_pushvalue(L, i); /* value to print */ if (luaL_callmeta(L, 1, "__tostring")) { s = lua_tostring(L, -1); meta = true; } else { switch (lua_type(L, -1)) { case LUA_TNUMBER: case LUA_TSTRING: s = lua_tostring(L, -1); break; case LUA_TBOOLEAN: s = lua_toboolean(L, -1) ? "true" : "false"; break; case LUA_TNIL: s = "nil"; break; default: s = "unknown lua type"; break; } } gi.DPrintf("%s%s", (i > 1) ? "\t" : "", s); lua_pop(L, 1); /* Pop the value */ if (meta) /* Meta creates an additional string. */ lua_pop(L, 1); } gi.DPrintf("\n"); return 0; }
char const * tostring(lua_State * L, int idx) { if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ switch (lua_type(L, idx)) { case LUA_TNUMBER: 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: { std::ostringstream strm; strm << lua_typename(L, idx) << ": " << lua_topointer(L, idx); lua_pushstring(L, strm.str().c_str()); break; }} } return lua_tostring(L, -1); }
static int luaB_tostring (lua_State *L) { luaL_checkany(L, 1); if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ return 1; /* use its value */ switch (lua_type(L, 1)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, 1)); break; case LUA_TSTRING: lua_pushvalue(L, 1); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); break; } return 1; }
int ex_lua_tostring ( lua_State *_l, int _idx ) { luaL_checkany( _l, _idx ); if ( luaL_callmeta(_l, _idx, "__tostring") ) /* is there a metafield? */ return 1; /* use its value */ switch ( lua_type(_l, _idx) ) { case LUA_TNUMBER: lua_pushstring(_l, lua_tostring(_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 1; }
static int luaB_tostring(lua_State * L) { char buff[128]; luaL_checkany(L, 1); if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ return 1; /* use its value */ switch (lua_type(L, 1)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, 1)); return 1; case LUA_TSTRING: lua_pushvalue(L, 1); return 1; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); return 1; case LUA_TTABLE: sprintf(buff, "table: %p", lua_topointer(L, 1)); break; case LUA_TFUNCTION: sprintf(buff, "function: %p", lua_topointer(L, 1)); break; case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); break; case LUA_TTHREAD: sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); break; case LUA_TNIL: lua_pushliteral(L, "nil"); return 1; } lua_pushstring(L, buff); return 1; }
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ if (!lua_isstring(L, -1)) luaL_error(L, "'__tostring' must return a string"); } else { switch (lua_type(L, idx)) { case LUA_TNUMBER: { if (lua_isinteger(L, idx)) lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); else lua_pushfstring(L, "%f", (LUAI_UACNUMBER)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: { int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : luaL_typename(L, idx); lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); if (tt != LUA_TNIL) lua_remove(L, -2); /* remove '__name' */ break; } } } return lua_tolstring(L, -1, len); }
static int traceback(lua_State *L) { if (!lua_isstring(L, 1)) { /* Non-string error object? Try metamethod. */ if (lua_isnoneornil(L, 1) || !luaL_callmeta(L, 1, "__tostring") || !lua_isstring(L, -1)) return 1; /* Return non-string error object. */ lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ } lua_getfield(L, LUA_GLOBALSINDEX, "debug"); if (!lua_istable(L, -1)) { lua_pop(L, 1); return 1; } lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) { lua_pop(L, 2); return 1; } lua_pushvalue(L, 1); /* Push error message. */ lua_pushinteger(L, 2); /* Skip this function and debug.traceback(). */ lua_call(L, 2, 1); /* Call debug.traceback(). */ return 1; }
LUALIB_API int luaL_pushtype (lua_State *L, int narg) { if (!luaL_callmeta(L, narg, "__type")) lua_pushstring (L, luaL_typename(L, narg)); return 1; }
int rb_save(lua_State *L, int index, ringbuffer_t *rb, int oop, int upval) { char type = lua_type(L, index); switch (type) { case LUA_TNIL: { RB_WRITE(L, rb, &type, sizeof(char)); return 0; } case LUA_TBOOLEAN: { RB_WRITE(L, rb, &type, sizeof(char)); type = lua_toboolean(L, index); RB_WRITE(L, rb, &type, sizeof(char)); return 0; } case LUA_TNUMBER: { #if LUA_VERSION_NUM >= 503 if (lua_isinteger(L, index)) { type = EXTRA_LUA_TINTEGER; RB_WRITE(L, rb, &type, sizeof(char)); lua_Integer n = lua_tointeger(L, index); RB_WRITE(L, rb, &n, sizeof(n)); } else #endif { RB_WRITE(L, rb, &type, sizeof(char)); lua_Number n = lua_tonumber(L, index); RB_WRITE(L, rb, &n, sizeof(n)); } return 0; } case LUA_TSTRING: { RB_WRITE(L, rb, &type, sizeof(char)); size_t str_len; const char *str = lua_tolstring(L, index, &str_len); RB_WRITE(L, rb, &str_len, sizeof(str_len)); RB_WRITE(L, rb, str, str_len); return 0; } case LUA_TTABLE: { RB_WRITE(L, rb, &type, sizeof(char)); int top = lua_gettop(L); int ret; lua_pushnil(L); while (lua_next(L, index) != 0) { ret = rb_save(L, top + 1, rb, oop, upval); // key if (ret) { lua_pop(L, 2); return ret; } ret = rb_save(L, top + 2, rb, oop, upval); // value if (ret) { lua_pop(L, 2); return ret; } lua_pop(L, 1); } type = LUA_TNIL; RB_WRITE(L, rb, &type, sizeof(char)); // breaks the read loop // the typename identifies the metatable const char *str = luaT_typename(L, index); if (!str) { if (luaL_callmeta(L, index, "metatablename")) { str = lua_tostring(L, lua_gettop(L)); lua_pop(L, 1); } else { str = ""; } } size_t str_len = strlen(str); RB_WRITE(L, rb, &str_len, sizeof(str_len)); RB_WRITE(L, rb, str, str_len); return 0; } case LUA_TFUNCTION: { RB_WRITE(L, rb, &type, sizeof(char)); if (index != lua_gettop(L)) { lua_pushvalue(L, index); } lua_Debug ar; lua_pushvalue(L, -1); lua_getinfo(L, ">nuS", &ar); if (ar.what[0] != 'L') { luaL_error(L, "attempt to persist a C function '%s'", ar.name); } // this returns different things under LuaJIT vs Lua #if LUA_VERSION_NUM >= 503 lua_dump(L, rb_lua_writer, rb, 0); #else lua_dump(L, rb_lua_writer, rb); #endif size_t str_len = 0; RB_WRITE(L, rb, &str_len, sizeof(size_t)); // zero-terminated // does the serialization accept upvalues? RB_WRITE(L, rb, &upval, sizeof(int)); // upvalues if (upval == 1) { lua_newtable(L); int envIdx = -1; for (int i=1; i <= ar.nups; i++) { const char *name = lua_getupvalue(L, -2, i); if (strcmp(name, "_ENV") != 0) { lua_rawseti(L, -2, i); } else { // ignore _ENV as we assume that this is the global _G variable lua_pop(L, 1); envIdx = i; } } // write upvalue index of _ENV RB_WRITE(L, rb, &envIdx, sizeof(int)); // write upvalue table int ret = rb_save(L, lua_gettop(L), rb, oop, upval); if (ret) { return ret; } lua_pop(L, 1); } else if (ar.nups > 1) { luaL_error(L, "attempt to serialize a funciton with upvalues (i.e. a closure). Use ipc.workqueue.writeup()."); } if (index != lua_gettop(L)) { lua_pop(L, 1); } return 0; } case LUA_TUSERDATA: { if (oop) return -EPERM; const char *str = luaT_typename(L, index); if (!str) { if (luaL_callmeta(L, index, "metatablename")) { str = lua_tostring(L, lua_gettop(L)); lua_pop(L, 1); type = -type; } else { return -EINVAL; } } RB_WRITE(L, rb, &type, sizeof(char)); size_t str_len = strlen(str); RB_WRITE(L, rb, &str_len, sizeof(str_len)); RB_WRITE(L, rb, str, str_len); void *ptr = lua_touserdata(L, index); RB_WRITE(L, rb, ptr, sizeof(void *)); if (luaL_callmeta(L, index, "retain")) { lua_pop(L, 1); } else { return -EINVAL; } return 0; } default: return -EPERM; } }