1 // Copyright (c) 2003 Daniel Wallin and Arvid Norberg 2 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the "Software"), 5 // to deal in the Software without restriction, including without limitation 6 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 // and/or sell copies of the Software, and to permit persons to whom the 8 // Software is furnished to do so, subject to the following conditions: 9 10 // The above copyright notice and this permission notice shall be included 11 // in all copies or substantial portions of the Software. 12 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 21 // OR OTHER DEALINGS IN THE SOFTWARE. 22 23 #define LUABIND_BUILDING 24 25 #include <luabind/luabind.hpp> 26 27 #include <luabind/lua_include.hpp> 28 29 namespace luabind { namespace detail 30 { 31 namespace 32 { 33 // expects two tables on the lua stack: 34 // 1: destination 35 // 2: source copy_member_table(lua_State * L)36 void copy_member_table(lua_State* L) 37 { 38 lua_pushnil(L); 39 40 while (lua_next(L, -2)) 41 { 42 lua_pushliteral(L, "__init"); 43 if (lua_compare(L, -1, -3, LUA_OPEQ)) 44 { 45 lua_pop(L, 2); 46 continue; 47 } 48 else lua_pop(L, 1); // __init string 49 50 lua_pushliteral(L, "__finalize"); 51 if (lua_compare(L, -1, -3, LUA_OPEQ)) 52 { 53 lua_pop(L, 2); 54 continue; 55 } 56 else lua_pop(L, 1); // __finalize string 57 58 lua_pushvalue(L, -2); // copy key 59 lua_insert(L, -2); 60 lua_settable(L, -5); 61 } 62 } 63 } 64 65 stage2(lua_State * L)66 int create_class::stage2(lua_State* L) 67 { 68 class_rep* crep = static_cast<class_rep*>(lua_touserdata(L, lua_upvalueindex(1))); 69 assert((crep != 0) && "internal error, please report"); 70 assert((is_class_rep(L, lua_upvalueindex(1))) && "internal error, please report"); 71 72 #ifndef LUABIND_NO_ERROR_CHECKING 73 74 if (!is_class_rep(L, 1)) 75 { 76 lua_pushliteral(L, "expected class to derive from or a newline"); 77 lua_error(L); 78 } 79 80 #endif 81 82 class_rep* base = static_cast<class_rep*>(lua_touserdata(L, 1)); 83 crep->add_base_class(base); 84 85 // copy base class members 86 87 crep->get_table(L); 88 base->get_table(L); 89 copy_member_table(L); 90 91 crep->get_default_table(L); 92 base->get_default_table(L); 93 copy_member_table(L); 94 95 crep->set_type(base->type()); 96 97 return 0; 98 } 99 stage1(lua_State * L)100 int create_class::stage1(lua_State* L) 101 { 102 103 #ifndef LUABIND_NO_ERROR_CHECKING 104 105 if (lua_gettop(L) != 1 || lua_type(L, 1) != LUA_TSTRING || lua_isnumber(L, 1)) 106 { 107 lua_pushliteral(L, "invalid construct, expected class name"); 108 lua_error(L); 109 } 110 111 if (std::strlen(lua_tostring(L, 1)) != lua_rawlen(L, 1)) 112 { 113 lua_pushliteral(L, "luabind does not support class names with extra nulls"); 114 lua_error(L); 115 } 116 117 #endif 118 119 const char* name = lua_tostring(L, 1); 120 121 void* c = lua_newuserdata(L, sizeof(class_rep)); 122 new(c) class_rep(L, name); 123 124 // make the class globally available 125 lua_pushvalue(L, -1); 126 lua_setglobal(L, name); 127 128 // also add it to the closure as return value 129 lua_pushcclosure(L, &stage2, 1); 130 131 return 1; 132 } 133 134 }} 135