Add lua_setlightuserdataname and lua_getlightuserdataname

This commit is contained in:
Petri Häkkinen 2023-11-02 11:58:13 +02:00
parent 002aaf8dcf
commit 1491dc64c9
7 changed files with 42 additions and 0 deletions

View file

@ -325,6 +325,9 @@ typedef void (*lua_Destructor)(lua_State* L, void* userdata);
LUA_API void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor);
LUA_API lua_Destructor lua_getuserdatadtor(lua_State* L, int tag);
LUA_API void lua_setlightuserdataname(lua_State* L, int tag, const char* name);
LUA_API const char* lua_getlightuserdataname(lua_State* L, int tag);
LUA_API void lua_clonefunction(lua_State* L, int idx);
LUA_API void lua_cleartable(lua_State* L, int idx);

View file

@ -101,6 +101,11 @@
#define LUA_UTAG_LIMIT 128
#endif
// number of valid Lua lightuserdata tags
#ifndef LUA_LUTAG_LIMIT
#define LUA_LUTAG_LIMIT 128
#endif
// upper bound for number of size classes used by page allocator
#ifndef LUA_SIZECLASSES
#define LUA_SIZECLASSES 32

View file

@ -681,6 +681,7 @@ void lua_pushboolean(lua_State* L, int b)
void lua_pushlightuserdatatagged(lua_State* L, void* p, int tag)
{
api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT);
setpvalue(L->top, p);
L->top->extra[0] = tag;
api_incr_top(L);
@ -1427,6 +1428,24 @@ lua_Destructor lua_getuserdatadtor(lua_State* L, int tag)
return L->global->udatagc[tag];
}
void lua_setlightuserdataname(lua_State* L, int tag, const char* name)
{
api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT);
api_check(L, !L->global->lightuserdataname[tag]); // renaming not supported
if (!L->global->lightuserdataname[tag])
{
L->global->lightuserdataname[tag] = luaS_new(L, name);
luaS_fix(L->global->lightuserdataname[tag]); // never collect these names
}
}
const char* lua_getlightuserdataname(lua_State* L, int tag)
{
api_check(L, unsigned(tag) < LUA_LUTAG_LIMIT);
const TString* name = L->global->lightuserdataname[tag];
return name ? getstr(name) : nullptr;
}
void lua_clonefunction(lua_State* L, int idx)
{
luaC_checkGC(L);

View file

@ -210,6 +210,8 @@ lua_State* lua_newstate(lua_Alloc f, void* ud)
g->mt[i] = NULL;
for (i = 0; i < LUA_UTAG_LIMIT; i++)
g->udatagc[i] = NULL;
for (i = 0; i < LUA_LUTAG_LIMIT; i++)
g->lightuserdataname[i] = NULL;
for (i = 0; i < LUA_MEMORY_CATEGORIES; i++)
g->memcatbytes[i] = 0;

View file

@ -197,6 +197,7 @@ typedef struct global_State
struct Table* mt[LUA_T_COUNT]; // metatables for basic types
TString* ttname[LUA_T_COUNT]; // names for basic types
TString* tmname[TM_N]; // array with tag-method names
TString* lightuserdataname[LUA_LUTAG_LIMIT]; // names for tagged lightuserdata
TValue pseudotemp; // storage for temporary values used in pseudo2addr

View file

@ -129,6 +129,13 @@ const TString* luaT_objtypenamestr(lua_State* L, const TValue* o)
if (ttisstring(type))
return tsvalue(type);
}
if (ttislightuserdata(o) && o->extra[0] != 0)
{
const TString* name = L->global->lightuserdataname[o->extra[0]];
if (name)
return name;
}
else if (Table* mt = L->global->mt[ttype(o)])
{
const TValue* type = luaH_getstr(mt, L->global->tmname[TM_TYPE]);

View file

@ -1684,6 +1684,11 @@ TEST_CASE("LightuserdataApi")
CHECK(lua_tolightuserdatatagged(L, -1, 0) == nullptr);
CHECK(lua_tolightuserdatatagged(L, -1, 1) == value);
lua_setlightuserdataname(L, 1, "id");
CHECK(!lua_getlightuserdataname(L, 0));
CHECK(strcmp(lua_getlightuserdataname(L, 1), "id") == 0);
CHECK(strcmp(luaL_typename(L, -1), "id") == 0);
globalState.reset();
}