@@ -130,6 +130,40 @@ static int module_newindex_event (lua_State* L)
130130 return 0 ;
131131}
132132
133+ static int class_table_get_index (lua_State * L )
134+ {
135+ // stack: obj key ... obj
136+
137+ while (lua_getmetatable (L ,-1 )) { /* stack: obj key obj mt */
138+ lua_remove (L ,-2 ); /* stack: ... mt */
139+
140+ lua_pushvalue (L ,2 ); /* stack: ... mt key */
141+ lua_rawget (L ,-2 ); /* stack: ... mt value */
142+ if (!lua_isnil (L ,-1 )) {
143+ return 1 ;
144+ } else {
145+ lua_pop (L ,1 );
146+ }
147+
148+ /* try C/C++ variable */
149+ lua_pushstring (L ,".get" );
150+ lua_rawget (L ,-2 ); /* stack: obj key ... mt tget */
151+ if (lua_istable (L ,-1 )) {
152+ lua_pushvalue (L ,2 ); /* stack: obj key ... mt tget key */
153+ lua_rawget (L ,-2 ); /* stack: obj key ... mt tget value */
154+ if (lua_iscfunction (L ,-1 )) {
155+ lua_call (L ,0 ,1 );
156+ return 1 ;
157+ } else if (lua_istable (L ,-1 )) {
158+ return 1 ;
159+ }
160+ lua_pop (L , 2 );
161+ }
162+ }
163+ lua_pushnil (L );
164+ return 1 ;
165+ }
166+
133167/* Class index function
134168 * If the object is a userdata (ie, an object), it searches the field in
135169 * the alternative table stored in the corresponding "ubox" table.
@@ -227,13 +261,65 @@ static int class_index_event (lua_State* L)
227261 }
228262 else if (t == LUA_TTABLE )
229263 {
230- module_index_event (L );
264+ lua_pushvalue (L ,1 );
265+ class_table_get_index (L );
231266 return 1 ;
232267 }
233268 lua_pushnil (L );
234269 return 1 ;
235270}
236271
272+ static int class_backup_before_newindex (lua_State * L )
273+ {
274+ /* stack: t k v */
275+ int m ;
276+
277+ lua_pushvalue (L , 1 );
278+ m = lua_getmetatable (L ,-1 ); /* stack: t k v t mt */
279+ while (m > 0 && lua_istable (L ,-1 )) {
280+ lua_remove (L , -2 ); /* stack: t k v mt */
281+ //Check if key had been backup
282+ lua_pushstring (L , ".backup" );
283+ lua_rawget (L , -2 ); /* stack: t k v mt mt[".backup"] */
284+ if (!lua_isnil (L , -1 )) {
285+ lua_pushvalue (L , 2 ); /* stack: t k v mt mt[".backup"] k */
286+ lua_rawget (L , -2 );
287+ if (!lua_isnil (L , -1 )) {
288+ // key had been backup
289+ return 0 ;
290+ }
291+ lua_pop (L , 1 );
292+ }
293+ lua_pop (L , 1 ); /* stack: t k v mt */
294+
295+ //Check if key is exist in mt
296+ lua_pushvalue (L , 2 );
297+ lua_rawget (L , -2 ); /* stack: t k v mt mt[k] */
298+ if (!lua_isnil (L , -1 )) {
299+ lua_pushvalue (L , -2 ); /* stack: t k v mt mt[k] mt */
300+ lua_pushstring (L , ".backup" );
301+ lua_rawget (L , -2 ); /* stack: t k v mt mt[k] mt mt[".backup"] */
302+ if (lua_isnil (L , -1 )) {
303+ //Create a table and set to mt[".backup"]
304+ lua_pop (L , 1 ); /* stack: t k v mt mt[k] mt */
305+ lua_pushstring (L , ".backup" );
306+ lua_newtable (L );
307+ lua_rawset (L , -3 );
308+ lua_pushstring (L , ".backup" );
309+ lua_rawget (L , -2 ); /* stack: t k v mt mt[k] mt mt[".backup"] */
310+ }
311+ lua_pushvalue (L , 2 ); /* stack: t k v mt mt[k] mt mt[".backup"] k */
312+ lua_pushvalue (L , -4 ); /* stack: t k v mt mt[k] mt mt[".backup"] k mt[k] */
313+ lua_rawset (L , -3 );
314+ return 0 ;
315+ }
316+ lua_pop (L , 1 ); /* stack: t k v mt */
317+ m = lua_getmetatable (L ,-1 ); /* stack: t k v mt base_mt */
318+ }
319+
320+ return 0 ;
321+ }
322+
237323/* Newindex function
238324 * It first searches for a C/C++ varaible to be set.
239325 * Then, it either stores it in the alternative ubox table (in the case it is
@@ -292,24 +378,46 @@ static int class_newindex_event (lua_State* L)
292378 }
293379 else if (t == LUA_TTABLE )
294380 {
295- module_newindex_event (L );
381+ lua_getmetatable (L ,1 ); /* stack: t k v mt */
382+ lua_pushstring (L ,".set" );
383+ lua_rawget (L ,-2 ); /* stack: t k v mt tset */
384+ if (lua_istable (L ,-1 )) {
385+ lua_pushvalue (L ,2 ); /* stack: t k v mt tset k */
386+ lua_rawget (L ,-2 );
387+ if (lua_iscfunction (L ,-1 )) { /* ... func */
388+ lua_pushvalue (L ,1 ); /* ... func t */
389+ lua_pushvalue (L ,3 ); /* ... func t v */
390+ lua_call (L ,2 ,0 );
391+ return 0 ;
392+ }
393+ }
394+ lua_settop (L ,3 );
395+ class_backup_before_newindex (L );
396+ lua_settop (L ,3 );
397+ lua_getmetatable (L ,1 ); /* stack: t k v mt */
398+ lua_replace (L , 1 ); /* stack: mt k v */
399+ lua_rawset (L ,1 );
296400 }
297401 return 0 ;
298402}
299403
300404static int class_call_event (lua_State * L ) {
301405
302406 if (lua_istable (L , 1 )) {
303- lua_pushstring (L , ".call" );
304- lua_rawget (L , 1 );
305- if (lua_isfunction (L , -1 )) {
306-
307- lua_insert (L , 1 );
308- lua_call (L , lua_gettop (L )- 1 , 1 );
309-
310- return 1 ;
311- };
312- };
407+ //class is not a metatable now, so must get it's metatable to access ".call" function. 2014.6.5 by SunLightJuly
408+ if (lua_getmetatable (L , 1 )) {
409+ lua_replace (L , 1 );
410+ lua_pushstring (L , ".call" );
411+ lua_rawget (L , 1 );
412+ if (lua_isfunction (L , -1 )) {
413+
414+ lua_insert (L , 1 );
415+ lua_call (L , lua_gettop (L )- 1 , 1 );
416+
417+ return 1 ;
418+ }
419+ }
420+ }
313421 tolua_error (L ,"Attempt to call a non-callable object." ,NULL );
314422 return 0 ;
315423};
0 commit comments