Skip to content

Commit

Permalink
feat(rotable): add metatable support to rotable
Browse files Browse the repository at this point in the history
Use userdata's uservalue as a place to store metatable.

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
  • Loading branch information
XuNeo committed Jul 22, 2024
1 parent e7bb0a9 commit 48c08f0
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
30 changes: 26 additions & 4 deletions src/rotable.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,26 @@ static int rotable_udata_index( lua_State* L ) {
p = find_key( p, t->n, s );
if( p )
rotable_pushvalue( L, p );
else
else {
int type = lua_getuservalue( L, 1 );
if( type == LUA_TTABLE ) {
type = lua_getfield( L, -1, "__index" );
if( type == LUA_TTABLE ) {
lua_pushvalue( L, 2 );
lua_gettable( L, -2 );
return 1;
}
else if( type == LUA_TFUNCTION ){
lua_pushvalue( L, -2 );
lua_pushvalue( L, 2 );
lua_call( L, 2, 1 );
return 1;
}
}

/* Otherwise, not found.*/
lua_pushnil( L );
}
return 1;
}

Expand Down Expand Up @@ -185,7 +203,7 @@ static int rotable_udata_pairs( lua_State* L ) {

ROTABLE_EXPORT void rotable_newlib( lua_State* L, void const* v ) {
rotable_Reg const* reg = (rotable_Reg const*)v;
rotable* t = (rotable*)lua_newuserdata( L, sizeof( *t ) );
rotable* t = (rotable*)lua_newuserdata( L, sizeof( *t ));
lua_pushlightuserdata( L, (void*)unique_address );
lua_rawget( L, LUA_REGISTRYINDEX );
if( !lua_istable( L, -1 ) ) {
Expand Down Expand Up @@ -218,12 +236,16 @@ ROTABLE_EXPORT void rotable_newlib( lua_State* L, void const* v ) {
}
}

ROTABLE_EXPORT void rotable_setmetatable( lua_State* L, int idx) {
/* Store a table to uservalue as rotable's "metatable" */
lua_setuservalue( L, idx );
}

ROTABLE_EXPORT void rotable_newidx( lua_State* L, void const* v ) {
rotable_Reg const* reg = (rotable_Reg const*)v;
int i = 0;
int i = 1;
lua_pushlightuserdata( L, (void*)v);
for( ; reg[ i ].func; ++i ) {
for( ; reg[ i ].name; ++i ) {
if( lv_strcmp( reg[ i-1 ].name, reg[ i ].name ) >= 0 ) {
i = 0;
break;
Expand Down
8 changes: 8 additions & 0 deletions src/rotable.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,12 @@ ROTABLE_EXPORT void rotable_newlib( lua_State* L, void const* reg );
* `rotable_Reg` array. */
ROTABLE_EXPORT void rotable_newidx( lua_State* L, void const* reg );

/**
* Since the rodata's metatable is used to simulate the table itself,
* we use userdata's uservalue to store an optional table as a
* metatable. It's used in the __index method when no match is found
* in the rotable.
*/
ROTABLE_EXPORT void rotable_setmetatable( lua_State* L, int idx);

#endif /* ROTABLE_H_ */

0 comments on commit 48c08f0

Please sign in to comment.