00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "tolua++.h"
00015 #include "tolua_event.h"
00016 #include "lauxlib.h"
00017
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <math.h>
00022
00023
00024
00025
00026
00027 static int tolua_newmetatable (lua_State* L, const char* name)
00028 {
00029 int r = luaL_newmetatable(L,name);
00030
00031 #ifdef LUA_VERSION_NUM
00032 if (r) {
00033 lua_pushvalue(L, -1);
00034 lua_pushstring(L, name);
00035 lua_settable(L, LUA_REGISTRYINDEX);
00036 };
00037 #endif
00038
00039 if (r)
00040 tolua_classevents(L);
00041 lua_pop(L,1);
00042 return r;
00043 }
00044
00045
00046
00047
00048 static void mapsuper (lua_State* L, const char* name, const char* base)
00049 {
00050
00051 lua_pushstring(L,"tolua_super");
00052 lua_rawget(L,LUA_REGISTRYINDEX);
00053 luaL_getmetatable(L,name);
00054 lua_rawget(L,-2);
00055 if (lua_isnil(L,-1))
00056 {
00057
00058 lua_pop(L,1);
00059 lua_newtable(L);
00060 luaL_getmetatable(L,name);
00061 lua_pushvalue(L,-2);
00062 lua_rawset(L,-4);
00063 }
00064
00065
00066 lua_pushstring(L,base);
00067 lua_pushboolean(L,1);
00068 lua_rawset(L,-3);
00069
00070
00071 luaL_getmetatable(L,base);
00072 lua_rawget(L,-3);
00073 if (lua_istable(L,-1))
00074 {
00075
00076 lua_pushnil(L);
00077 while (lua_next(L,-2) != 0)
00078 {
00079
00080 lua_pushvalue(L,-2);
00081 lua_insert(L,-2);
00082 lua_rawset(L,-5);
00083 }
00084 }
00085 lua_pop(L,3);
00086 }
00087
00088
00089
00090 static void set_ubox(lua_State* L) {
00091
00092
00093 if (!lua_isnil(L, -1)) {
00094 lua_pushstring(L, "tolua_ubox");
00095 lua_rawget(L,-2);
00096 } else {
00097 lua_pushnil(L);
00098 };
00099
00100 if (!lua_isnil(L,-1)) {
00101 lua_pushstring(L, "tolua_ubox");
00102 lua_insert(L, -2);
00103
00104 lua_rawset(L,-4);
00105
00106 } else {
00107
00108 lua_pop(L, 1);
00109 lua_pushstring(L,"tolua_ubox"); lua_newtable(L);
00110
00111
00112 lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); lua_rawset(L, -3);
00113 lua_setmetatable(L, -2);
00114 lua_rawset(L,-4);
00115 };
00116
00117 };
00118
00119
00120
00121
00122 static void mapinheritance (lua_State* L, const char* name, const char* base)
00123 {
00124
00125 luaL_getmetatable(L,name);
00126
00127 if (base && *base)
00128 luaL_getmetatable(L,base);
00129 else {
00130
00131 if (lua_getmetatable(L, -1)) {
00132 lua_pop(L, 2);
00133 return;
00134 };
00135 luaL_getmetatable(L,"tolua_commonclass");
00136 };
00137
00138 set_ubox(L);
00139
00140 lua_setmetatable(L,-2);
00141 lua_pop(L,1);
00142 }
00143
00144
00145
00146 static int tolua_bnd_type (lua_State* L)
00147 {
00148 tolua_typename(L,lua_gettop(L));
00149 return 1;
00150 }
00151
00152
00153
00154 static int tolua_bnd_takeownership (lua_State* L)
00155 {
00156 int success = 0;
00157 if (lua_isuserdata(L,1))
00158 {
00159 if (lua_getmetatable(L,1))
00160 {
00161 lua_pop(L,1);
00162
00163 #ifdef LUA_VERSION_NUM
00164 lua_gc(L, LUA_GCCOLLECT, 0);
00165 #else
00166 lua_setgcthreshold(L,0);
00167 #endif
00168
00169 success = tolua_register_gc(L,1);
00170 }
00171 }
00172 lua_pushboolean(L,success!=0);
00173 return 1;
00174 }
00175
00176
00177
00178 static int tolua_bnd_releaseownership (lua_State* L)
00179 {
00180 int done = 0;
00181 if (lua_isuserdata(L,1))
00182 {
00183 void* u = *((void**)lua_touserdata(L,1));
00184
00185 #ifdef LUA_VERSION_NUM
00186 lua_gc(L, LUA_GCCOLLECT, 0);
00187 #else
00188 lua_setgcthreshold(L,0);
00189 #endif
00190 lua_pushstring(L,"tolua_gc");
00191 lua_rawget(L,LUA_REGISTRYINDEX);
00192 lua_pushlightuserdata(L,u);
00193 lua_rawget(L,-2);
00194 lua_getmetatable(L,1);
00195 if (lua_rawequal(L,-1,-2))
00196 {
00197 lua_pushlightuserdata(L,u);
00198 lua_pushnil(L);
00199 lua_rawset(L,-5);
00200 done = 1;
00201 }
00202 }
00203 lua_pushboolean(L,done!=0);
00204 return 1;
00205 }
00206
00207
00208
00209 static int tolua_bnd_cast (lua_State* L)
00210 {
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void* v;
00223 const char* s;
00224 if (lua_islightuserdata(L, 1)) {
00225 v = tolua_touserdata(L, 1, NULL);
00226 } else {
00227 v = tolua_tousertype(L, 1, 0);
00228 };
00229
00230 s = tolua_tostring(L,2,NULL);
00231 if (v && s)
00232 tolua_pushusertype(L,v,s);
00233 else
00234 lua_pushnil(L);
00235 return 1;
00236 }
00237
00238
00239
00240 static int tolua_bnd_inherit (lua_State* L) {
00241
00242
00243 lua_pushstring(L, ".c_instance");
00244 lua_pushvalue(L, -2);
00245 lua_rawset(L, -4);
00246
00247
00248 return 0;
00249 };
00250
00251 #ifdef LUA_VERSION_NUM
00252 static int tolua_bnd_setpeer(lua_State* L) {
00253
00254
00255 if (!lua_isuserdata(L, -2)) {
00256 lua_pushstring(L, "Invalid argument #1 to setpeer: userdata expected.");
00257 lua_error(L);
00258 };
00259
00260 if (lua_isnil(L, -1)) {
00261
00262 lua_pop(L, 1);
00263 lua_pushvalue(L, TOLUA_NOPEER);
00264 };
00265 lua_setfenv(L, -2);
00266
00267 return 0;
00268 };
00269
00270 static int tolua_bnd_getpeer(lua_State* L) {
00271
00272
00273 lua_getfenv(L, -1);
00274 if (lua_rawequal(L, -1, TOLUA_NOPEER)) {
00275 lua_pop(L, 1);
00276 lua_pushnil(L);
00277 };
00278 return 1;
00279 };
00280 #endif
00281
00282
00283
00284 TOLUA_API void tolua_open (lua_State* L)
00285 {
00286 int top = lua_gettop(L);
00287 lua_pushstring(L,"tolua_opened");
00288 lua_rawget(L,LUA_REGISTRYINDEX);
00289 if (!lua_isboolean(L,-1))
00290 {
00291 lua_pushstring(L,"tolua_opened"); lua_pushboolean(L,1); lua_rawset(L,LUA_REGISTRYINDEX);
00292
00293 #ifndef LUA_VERSION_NUM
00294
00295 lua_pushstring(L, "tolua_peers"); lua_newtable(L);
00296
00297 lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "k"); lua_rawset(L, -3);
00298 lua_setmetatable(L, -2);
00299 lua_rawset(L,LUA_REGISTRYINDEX);
00300 #endif
00301
00302
00303 lua_pushstring(L,"tolua_ubox"); lua_newtable(L);
00304
00305
00306 lua_newtable(L); lua_pushliteral(L, "__mode"); lua_pushliteral(L, "v"); lua_rawset(L, -3);
00307 lua_setmetatable(L, -2);
00308 lua_rawset(L,LUA_REGISTRYINDEX);
00309
00310 lua_pushstring(L,"tolua_super"); lua_newtable(L); lua_rawset(L,LUA_REGISTRYINDEX);
00311 lua_pushstring(L,"tolua_gc"); lua_newtable(L);lua_rawset(L,LUA_REGISTRYINDEX);
00312
00313
00314 lua_pushstring(L, "tolua_gc_event");
00315 lua_pushstring(L, "tolua_gc");
00316 lua_rawget(L, LUA_REGISTRYINDEX);
00317 lua_pushstring(L, "tolua_super");
00318 lua_rawget(L, LUA_REGISTRYINDEX);
00319 lua_pushcclosure(L, class_gc_event, 2);
00320 lua_rawset(L, LUA_REGISTRYINDEX);
00321
00322 tolua_newmetatable(L,"tolua_commonclass");
00323
00324 tolua_module(L,NULL,0);
00325 tolua_beginmodule(L,NULL);
00326 tolua_module(L,"tolua",0);
00327 tolua_beginmodule(L,"tolua");
00328 tolua_function(L,"type",tolua_bnd_type);
00329 tolua_function(L,"takeownership",tolua_bnd_takeownership);
00330 tolua_function(L,"releaseownership",tolua_bnd_releaseownership);
00331 tolua_function(L,"cast",tolua_bnd_cast);
00332 tolua_function(L,"inherit", tolua_bnd_inherit);
00333 #ifdef LUA_VERSION_NUM
00334 tolua_function(L, "setpeer", tolua_bnd_setpeer);
00335 tolua_function(L, "getpeer", tolua_bnd_getpeer);
00336 #endif
00337
00338 tolua_endmodule(L);
00339 tolua_endmodule(L);
00340 }
00341 lua_settop(L,top);
00342 }
00343
00344
00345
00346 TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size)
00347 {
00348 void* clone = (void*)malloc(size);
00349 if (clone)
00350 memcpy(clone,value,size);
00351 else
00352 tolua_error(L,"insuficient memory",NULL);
00353 return clone;
00354 }
00355
00356
00357
00358 TOLUA_API int tolua_default_collect (lua_State* tolua_S)
00359 {
00360 void* self = tolua_tousertype(tolua_S,1,0);
00361 free(self);
00362 return 0;
00363 }
00364
00365
00366
00367 TOLUA_API int tolua_register_gc (lua_State* L, int lo)
00368 {
00369 int success = 1;
00370 void *value = *(void **)lua_touserdata(L,lo);
00371 lua_pushstring(L,"tolua_gc");
00372 lua_rawget(L,LUA_REGISTRYINDEX);
00373 lua_pushlightuserdata(L,value);
00374 lua_rawget(L,-2);
00375 if (!lua_isnil(L,-1))
00376 success = 0;
00377 else
00378 {
00379 lua_pushlightuserdata(L,value);
00380 lua_getmetatable(L,lo);
00381 lua_rawset(L,-4);
00382 }
00383 lua_pop(L,2);
00384 return success;
00385 }
00386
00387
00388
00389
00390
00391 TOLUA_API void tolua_usertype (lua_State* L, const char* type)
00392 {
00393 char ctype[128] = "const ";
00394 strncat(ctype,type,120);
00395
00396
00397 if (tolua_newmetatable(L,ctype) && tolua_newmetatable(L,type))
00398 mapsuper(L,type,ctype);
00399 }
00400
00401
00402
00403
00404
00405 TOLUA_API void tolua_beginmodule (lua_State* L, const char* name)
00406 {
00407 if (name)
00408 {
00409 lua_pushstring(L,name);
00410 lua_rawget(L,-2);
00411 }
00412 else
00413 lua_pushvalue(L,LUA_GLOBALSINDEX);
00414 }
00415
00416
00417
00418
00419 TOLUA_API void tolua_endmodule (lua_State* L)
00420 {
00421 lua_pop(L,1);
00422 }
00423
00424
00425
00426
00427 #if 1
00428 TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
00429 {
00430 if (name)
00431 {
00432
00433 lua_pushstring(L,name);
00434 lua_rawget(L,-2);
00435 if (!lua_istable(L,-1))
00436 {
00437 lua_pop(L,1);
00438 lua_newtable(L);
00439 lua_pushstring(L,name);
00440 lua_pushvalue(L,-2);
00441 lua_rawset(L,-4);
00442 }
00443 }
00444 else
00445 {
00446
00447 lua_pushvalue(L,LUA_GLOBALSINDEX);
00448 }
00449 if (hasvar)
00450 {
00451 if (!tolua_ismodulemetatable(L))
00452 {
00453
00454 lua_newtable(L);
00455 tolua_moduleevents(L);
00456 if (lua_getmetatable(L,-2))
00457 lua_setmetatable(L,-2);
00458 lua_setmetatable(L,-2);
00459 }
00460 }
00461 lua_pop(L,1);
00462 }
00463 #else
00464 TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar)
00465 {
00466 if (name)
00467 {
00468
00469 lua_pushstring(L,name);
00470 lua_newtable(L);
00471 }
00472 else
00473 {
00474
00475 lua_pushvalue(L,LUA_GLOBALSINDEX);
00476 }
00477 if (hasvar)
00478 {
00479
00480 lua_newtable(L);
00481 tolua_moduleevents(L);
00482 if (lua_getmetatable(L,-2))
00483 lua_setmetatable(L,-2);
00484 lua_setmetatable(L,-2);
00485 }
00486 if (name)
00487 lua_rawset(L,-3);
00488 else
00489 lua_pop(L,1);
00490 }
00491 #endif
00492
00493 static void push_collector(lua_State* L, const char* type, lua_CFunction col) {
00494
00495
00496
00497 if (!col) return;
00498 luaL_getmetatable(L,type);
00499 lua_pushstring(L,".collector");
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 lua_pushcfunction(L,col);
00512
00513 lua_rawset(L,-3);
00514 lua_pop(L, 1);
00515 };
00516
00517
00518
00519
00520 TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col)
00521 {
00522 char cname[128] = "const ";
00523 char cbase[128] = "const ";
00524 strncat(cname,name,120);
00525 strncat(cbase,base,120);
00526
00527 mapinheritance(L,name,base);
00528 mapinheritance(L,cname,name);
00529
00530 mapsuper(L,cname,cbase);
00531 mapsuper(L,name,base);
00532
00533 lua_pushstring(L,lname);
00534
00535 push_collector(L, name, col);
00536
00537
00538
00539
00540
00541
00542
00543
00544 luaL_getmetatable(L,name);
00545 lua_rawset(L,-3);
00546
00547
00548
00549 push_collector(L, cname, col);
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func)
00580 {
00581 lua_pushstring(L,name);
00582 lua_pushcfunction(L,func);
00583 lua_rawset(L,-3);
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 TOLUA_API void tolua_constant (lua_State* L, const char* name, double value)
00603 {
00604 lua_pushstring(L,name);
00605 tolua_pushnumber(L,value);
00606 lua_rawset(L,-3);
00607 }
00608
00609
00610
00611
00612
00613 TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
00614 {
00615
00616 lua_pushstring(L,".get");
00617 lua_rawget(L,-2);
00618 if (!lua_istable(L,-1))
00619 {
00620
00621 lua_pop(L,1);
00622 lua_newtable(L);
00623 lua_pushstring(L,".get");
00624 lua_pushvalue(L,-2);
00625 lua_rawset(L,-4);
00626 }
00627 lua_pushstring(L,name);
00628 lua_pushcfunction(L,get);
00629 lua_rawset(L,-3);
00630 lua_pop(L,1);
00631
00632
00633 if (set)
00634 {
00635 lua_pushstring(L,".set");
00636 lua_rawget(L,-2);
00637 if (!lua_istable(L,-1))
00638 {
00639
00640 lua_pop(L,1);
00641 lua_newtable(L);
00642 lua_pushstring(L,".set");
00643 lua_pushvalue(L,-2);
00644 lua_rawset(L,-4);
00645 }
00646 lua_pushstring(L,name);
00647 lua_pushcfunction(L,set);
00648 lua_rawset(L,-3);
00649 lua_pop(L,1);
00650 }
00651 }
00652
00653
00654
00655
00656 static int const_array (lua_State* L)
00657 {
00658 luaL_error(L,"value of const array cannot be changed");
00659 return 0;
00660 }
00661
00662
00663
00664
00665 TOLUA_API void tolua_array (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set)
00666 {
00667 lua_pushstring(L,".get");
00668 lua_rawget(L,-2);
00669 if (!lua_istable(L,-1))
00670 {
00671
00672 lua_pop(L,1);
00673 lua_newtable(L);
00674 lua_pushstring(L,".get");
00675 lua_pushvalue(L,-2);
00676 lua_rawset(L,-4);
00677 }
00678 lua_pushstring(L,name);
00679
00680 lua_newtable(L);
00681 lua_pushvalue(L,-1);
00682 lua_setmetatable(L,-2);
00683 lua_pushstring(L,"__index");
00684 lua_pushcfunction(L,get);
00685 lua_rawset(L,-3);
00686 lua_pushstring(L,"__newindex");
00687 lua_pushcfunction(L,set?set:const_array);
00688 lua_rawset(L,-3);
00689
00690 lua_rawset(L,-3);
00691 lua_pop(L,1);
00692 }
00693
00694
00695 TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name) {
00696
00697 #ifdef LUA_VERSION_NUM
00698 luaL_loadbuffer(L, B, size, name) || lua_pcall(L, 0, 0, 0);
00699 #else
00700 lua_dobuffer(L, B, size, name);
00701 #endif
00702 };
00703