diff options
author | chai <chaifix@163.com> | 2021-11-08 10:53:42 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-11-08 10:53:42 +0800 |
commit | 5f46b4102c179680d613b6b9e0e6d392318030d2 (patch) | |
tree | 16527828dc89133f7af41acf6f5c13c23743e7ef /ThirdParty/tolua-5.2.4/src/lib/tolua_map.c | |
parent | 138d3f4d3d6e2aaf5ba34f89af15ef85ea074357 (diff) |
+ tolua
Diffstat (limited to 'ThirdParty/tolua-5.2.4/src/lib/tolua_map.c')
-rw-r--r-- | ThirdParty/tolua-5.2.4/src/lib/tolua_map.c | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/ThirdParty/tolua-5.2.4/src/lib/tolua_map.c b/ThirdParty/tolua-5.2.4/src/lib/tolua_map.c new file mode 100644 index 0000000..767e8f6 --- /dev/null +++ b/ThirdParty/tolua-5.2.4/src/lib/tolua_map.c @@ -0,0 +1,554 @@ +/* tolua: functions to map features + ** Support code for Lua bindings. + ** Written by Waldemar Celes + ** TeCGraf/PUC-Rio + ** Apr 2003 + ** $Id: tolua_map.c,v 1.10 2011/01/13 13:43:46 fabraham Exp $ + */ + +/* This code is free software; you can redistribute it and/or modify it. + ** The software provided hereunder is on an "as is" basis, and + ** the author has no obligation to provide maintenance, support, updates, + ** enhancements, or modifications. + */ + +#include "tolua.h" +#include "tolua_event.h" +#include "lauxlib.h" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + + +static char toluaname[128] = "tolua."; +static const char* TOLUANAME (const char* n) +{ + sprintf(&toluaname[6],"%.120s",n); + return toluaname; +} + +/* Create metatable + * Create and register new metatable + */ +void tolua_newmetatable (lua_State* L, const char* name) +{ + if (luaL_newmetatable(L,TOLUANAME(name))) + { + lua_pushvalue(L,-1); + lua_pushstring(L,name); + lua_rawset(L,LUA_REGISTRYINDEX); + } + + /* set meta events */ + tolua_classevents(L); + lua_pop(L,1); +} + +/* Get metatable + * Access already created metatable + */ +void tolua_getmetatable (lua_State* L, const char* name) +{ + luaL_getmetatable(L,TOLUANAME(name)); +} + +/* Map super classes + * It sets 'name' as being also a 'base', mapping all super classes of 'base' in 'name' + */ +static void mapsuper (lua_State* L, const char* name, const char* base) +{ + /* push registry.super */ + lua_pushstring(L,"tolua_super"); + lua_rawget(L,LUA_REGISTRYINDEX); /* stack: super */ + tolua_getmetatable(L,name); /* stack: super mt */ + lua_rawget(L,-2); /* stack: super table */ + if (lua_isnil(L,-1)) + { + /* create table */ + lua_pop(L,1); + lua_newtable(L); /* stack: super table */ + tolua_getmetatable(L,name); /* stack: super table mt */ + lua_pushvalue(L,-2); /* stack: super table mt table */ + lua_rawset(L,-4); /* stack: super table */ + } + + /* set base as super class */ + lua_pushstring(L,base); + lua_pushboolean(L,1); + lua_rawset(L,-3); /* stack: super table */ + + /* set all super class of base as super class of name */ + tolua_getmetatable(L,base); /* stack: super table base_mt */ + lua_rawget(L,-3); /* stack: super table base_table */ + if (lua_istable(L,-1)) + { + /* traverse base table */ + lua_pushnil(L); /* first key */ + while (lua_next(L,-2) != 0) + { + /* stack: ... base_table key value */ + lua_pushvalue(L,-2); /* stack: ... base_table key value key */ + lua_insert(L,-2); /* stack: ... base_table key key value */ + lua_rawset(L,-5); /* stack: ... base_table key */ + } + } + lua_pop(L,3); /* stack: <empty> */ +} + + +/* Map inheritance + * It sets 'name' as derived from 'base' by setting 'base' as metatable of 'name' + */ +static void mapinheritance (lua_State* L, const char* name, const char* base) +{ + /* set metatable inheritance */ + tolua_getmetatable(L,name); + if (base && *base) + tolua_getmetatable(L,base); + else + tolua_getmetatable(L,"tolua_commonclass"); + lua_setmetatable(L,-2); + lua_pop(L,1); +} + +/* Object type + */ +static int tolua_bnd_type (lua_State* L) +{ + tolua_typename(L,lua_gettop(L)); + return 1; +} + +/* Take ownership + */ +int tolua_bnd_takeownership (lua_State* L) +{ + lua_CFunction func = 0; + if (lua_isuserdata(L,1)) + { + if (lua_getmetatable(L,1)) /* if metatable? */ + { + void* u; + lua_pushstring(L,".collector"); + lua_rawget(L,-2); + func = lua_iscfunction(L,-1) ? lua_tocfunction(L,-1) : NULL; + lua_pop(L,2); + u = *((void**)lua_touserdata(L,1)); + tolua_clone(L,u,func); + } + } + lua_pushboolean(L,func!=0); + return 1; +} + +/* Release ownership + */ +static int tolua_bnd_releaseownership (lua_State* L) +{ + int done = 0; + if (lua_isuserdata(L,1)) + { + void* u = *((void**)lua_touserdata(L,1)); + lua_pushstring(L,"tolua_gc"); + lua_rawget(L,LUA_REGISTRYINDEX); + lua_pushlightuserdata(L,u); + lua_rawget(L,-2); + lua_pushlightuserdata(L,u); + lua_pushnil(L); + lua_rawset(L,-4); + done = 1; + } + lua_pushboolean(L,done!=0); + return 1; +} + +/* Type casting + */ +static int tolua_bnd_cast (lua_State* L) +{ + void* v = tolua_tousertype(L,1,NULL); + const char* s = tolua_tostring(L,2,NULL); + if (!v) + lua_pushnil(L); + else if (v && s) { + tolua_getmetatable(L,s); /* stack: ubox[u] super super[mt] flag mt */ + if (lua_isnil(L,-1)) { + tolua_error(L,"Unknown 'type' for 'tolua.cast' function",NULL); + } + tolua_pushusertype(L,v,s); + } + else { + tolua_error(L,"Invalid arguments for 'tolua.cast' function",NULL); + } + return 1; +} + +/* Release +** Function to be called by a Lua code that uses a function to explicitly +** release a mapped object. This function is automatically called by all +** destructors bound by tolua and by all collected objects. +*/ +static int tolua_bnd_release (lua_State* L) +{ + void* value = tolua_tousertype(L,1,NULL); + if (value) + tolua_release(L,value); + return 1; +} + +/* +** Function to return peer table associated to a given object +*/ +static int tolua_bnd_getpeertable (lua_State* L) +{ + lua_pushstring(L,"tolua_peer"); + lua_rawget(L,LUA_REGISTRYINDEX); /* stack: k v peer */ + lua_pushvalue(L,1); + lua_rawget(L,-2); /* stack: k v peer peer[u] */ + if (!lua_istable(L,-1)) + { + lua_pop(L,1); /* stack: k v peer */ + lua_newtable(L); /* stack: k v peer table */ + lua_pushvalue(L,1); + lua_pushvalue(L,-2); /* stack: k v peer table u table */ + lua_rawset(L,-4); /* stack: k v peer peer[u]=table */ + } + return 1; +} + +static void tolua_push_globals_table (lua_State* L) +{ +#if defined (LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 /* after lua 5.2 */ + lua_pushvalue(L,LUA_REGISTRYINDEX); /* registry */ + lua_pushnumber(L,LUA_RIDX_GLOBALS); /* registry globalsindex */ + lua_rawget(L, -2); /* registry registry[globalsindex] */ + lua_remove(L, -2); /* registry[globalsindex] */ +#else + lua_pushvalue(L,LUA_GLOBALSINDEX); +#endif +} + +TOLUA_API void tolua_open (lua_State* L) +{ + int top = lua_gettop(L); + lua_pushstring(L,"tolua_opened"); + lua_rawget(L,LUA_REGISTRYINDEX); + if (!lua_isboolean(L,-1)) + { + lua_pushstring(L,"tolua_opened"); lua_pushboolean(L,1); lua_rawset(L,LUA_REGISTRYINDEX); + lua_pushstring(L,"tolua_ubox"); + lua_newtable(L); + lua_pushvalue(L, -1); /* metatable: for weak table */ + lua_pushstring(L, "__mode"); + lua_pushstring(L, "v"); + lua_rawset(L, -3); + lua_setmetatable(L, -2); + lua_rawset(L,LUA_REGISTRYINDEX); + lua_pushstring(L,"tolua_peer"); + lua_newtable(L); + lua_pushvalue(L, -1); /* metatable: for weak table */ + lua_pushstring(L, "__mode"); + lua_pushstring(L, "k"); + lua_rawset(L, -3); + lua_setmetatable(L, -2); + lua_rawset(L,LUA_REGISTRYINDEX); + lua_pushstring(L,"tolua_super"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX); + lua_pushstring(L,"tolua_gc"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX); + + tolua_newmetatable(L,"tolua_commonclass"); + + tolua_module(L,NULL,0); + tolua_beginmodule(L,NULL); + tolua_module(L,"tolua",0); + tolua_beginmodule(L,"tolua"); + tolua_function(L,"type",tolua_bnd_type); + tolua_function(L,"takeownership",tolua_bnd_takeownership); + tolua_function(L,"releaseownership",tolua_bnd_releaseownership); + tolua_function(L,"cast",tolua_bnd_cast); + tolua_function(L,"release",tolua_bnd_release); + tolua_function(L,"getpeertable",tolua_bnd_getpeertable); + tolua_endmodule(L); + tolua_endmodule(L); + } + lua_settop(L,top); +} + +/* Copy a C object + */ +TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size) +{ + void* clone = (void*)malloc(size); + if (clone) + memcpy(clone,value,size); + else + tolua_error(L,"insuficient memory",NULL); + return clone; +} + + +/* Release userdata from tolua + */ +TOLUA_API void tolua_release (lua_State* L, void* value) +{ + void** p; + lua_pushstring(L,"tolua_ubox"); + lua_rawget(L,LUA_REGISTRYINDEX); /* stack: ubox */ + lua_pushlightuserdata(L,value); /* stack: ubox u */ + /* set userdata pointer to NULL: this pointer might be reused by C/C++ */ + lua_rawget(L,-2); /* stack: ubox ud */ + p = (void**)lua_touserdata(L,-1); + if (p) *p = NULL; + /* fixed bug: thanks to Ulrik Sverdrup -- it was 1 instead of -1 */ + lua_pop(L,1); /* stack: ubox */ + /* remove value from ubox */ + lua_pushlightuserdata(L,value); /* stack: ubox u */ + lua_pushnil(L); + lua_rawset(L,-3); + lua_pop(L,1); +} + +/* Do clone + */ +TOLUA_API void* tolua_clone (lua_State* L, void* value, lua_CFunction func) +{ + lua_pushstring(L,"tolua_gc"); + lua_rawget(L,LUA_REGISTRYINDEX); + lua_pushlightuserdata(L,value); + lua_pushcfunction(L,func); + lua_rawset(L,-3); + lua_pop(L,1); + return value; +} + +/* Register a usertype + * It creates the correspoding metatable in the registry, for both 'type' and 'const type'. + * It maps 'const type' as being also a 'type' + */ +TOLUA_API void tolua_usertype (lua_State* L, const char* type) +{ + char ctype[128] = "const "; + strncat(ctype,type,120); + + tolua_newmetatable(L,ctype); /* create both metatables */ + tolua_newmetatable(L,type); + + mapsuper(L,type,ctype); /* 'type' is also a 'const type' */ +} + + +/* Begin module + * It pushes the module (or class) table on the stack + */ +TOLUA_API void tolua_beginmodule (lua_State* L, const char* name) +{ + if (name) + { + lua_pushstring(L,name); + lua_rawget(L,-2); + } + else + tolua_push_globals_table(L); +} + +/* End module + * It pops the module (or class) from the stack + */ +TOLUA_API void tolua_endmodule (lua_State* L) +{ + lua_pop(L,1); +} + +/* Map module + * It creates a new module + */ +#if 1 +TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar) +{ + if (name) + { + /* tolua module */ + lua_pushstring(L,name); + lua_rawget(L,-2); + if (!lua_istable(L,-1)) /* check if module already exists */ + { + lua_pop(L,1); + lua_newtable(L); + lua_pushstring(L,name); + lua_pushvalue(L,-2); + lua_rawset(L,-4); /* assing module into module */ + } + } + else + tolua_push_globals_table(L); + if (hasvar) + { + if (!tolua_ismodulemetatable(L)) /* check if it already has a module metatable */ + { + /* create metatable to get/set C/C++ variable */ + lua_newtable(L); + tolua_moduleevents(L); + if (lua_getmetatable(L,-2)) + lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */ + lua_setmetatable(L,-2); + } + } + lua_pop(L,1); /* pop module */ +} +#else +TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar) +{ + if (name) + { + /* tolua module */ + lua_pushstring(L,name); + lua_newtable(L); + } + else + tolua_push_globals_table(L); + if (hasvar) + { + /* create metatable to get/set C/C++ variable */ + lua_newtable(L); + tolua_moduleevents(L); + if (lua_getmetatable(L,-2)) + lua_setmetatable(L,-2); /* set old metatable as metatable of metatable */ + lua_setmetatable(L,-2); + } + if (name) + lua_rawset(L,-3); /* assing module into module */ + else + lua_pop(L,1); /* pop global table */ +} +#endif + +/* Map C class + * It maps a C class, setting the appropriate inheritance and super classes. + */ +TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col) +{ + char cname[128] = "const "; + char cbase[128] = "const "; + strncat(cname,name,120); + strncat(cbase,base,120); + + mapinheritance(L,name,base); + mapinheritance(L,cname,name); + + mapsuper(L,cname,cbase); + mapsuper(L,name,base); + + lua_pushstring(L,lname); + tolua_getmetatable(L,name); + lua_pushstring(L,".collector"); + lua_pushcfunction(L,col); + lua_rawset(L,-3); /* store collector function into metatable */ + lua_rawset(L,-3); /* assign class metatable to module */ +} + +/* Map function + * It assigns a function into the current module (or class) + */ +TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func) +{ + lua_pushstring(L,name); + lua_pushcfunction(L,func); + lua_rawset(L,-3); +} + +/* Map constant number + * It assigns a constant number into the current module (or class) + */ +TOLUA_API void tolua_constant (lua_State* L, const char* name, double value) +{ + lua_pushstring(L,name); + tolua_pushnumber(L,value); + lua_rawset(L,-3); +} + + +/* Map variable + * It assigns a variable into the current module (or class) + */ +TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set) +{ + /* get func */ + lua_pushstring(L,".get"); + lua_rawget(L,-2); + if (!lua_istable(L,-1)) + { + /* create .get table, leaving it at the top */ + lua_pop(L,1); + lua_newtable(L); + lua_pushstring(L,".get"); + lua_pushvalue(L,-2); + lua_rawset(L,-4); + } + lua_pushstring(L,name); + lua_pushcfunction(L,get); + lua_rawset(L,-3); /* store variable */ + lua_pop(L,1); /* pop .get table */ + + /* set func */ + if (set) + { + lua_pushstring(L,".set"); + lua_rawget(L,-2); + if (!lua_istable(L,-1)) + { + /* create .set table, leaving it at the top */ + lua_pop(L,1); + lua_newtable(L); + lua_pushstring(L,".set"); + lua_pushvalue(L,-2); + lua_rawset(L,-4); + } + lua_pushstring(L,name); + lua_pushcfunction(L,set); + lua_rawset(L,-3); /* store variable */ + lua_pop(L,1); /* pop .set table */ + } +} + +/* Access const array + * It reports an error when trying to write into a const array + */ +static int const_array (lua_State* L) +{ + luaL_error(L,"value of const array cannot be changed"); + return 0; +} + +/* Map an array + * It assigns an array into the current module (or class) + */ +TOLUA_API void tolua_array (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set) +{ + lua_pushstring(L,".get"); + lua_rawget(L,-2); + if (!lua_istable(L,-1)) + { + /* create .get table, leaving it at the top */ + lua_pop(L,1); + lua_newtable(L); + lua_pushstring(L,".get"); + lua_pushvalue(L,-2); + lua_rawset(L,-4); + } + lua_pushstring(L,name); + + lua_newtable(L); /* create array metatable */ + lua_pushvalue(L,-1); + lua_setmetatable(L,-2); /* set the own table as metatable (for modules) */ + lua_pushstring(L,"__index"); + lua_pushcfunction(L,get); + lua_rawset(L,-3); + lua_pushstring(L,"__newindex"); + lua_pushcfunction(L,set?set:const_array); + lua_rawset(L,-3); + + lua_rawset(L,-3); /* store variable */ + lua_pop(L,1); /* pop .get table */ +} + |