| Previous | 199869 Revisions | Next |
| r31046 Friday 20th June, 2014 at 12:15:24 UTC by Miodrag Milanović |
|---|
| Added LuaBridge and exposed few classes as example (nw) |
| [src/emu] | luaengine.c luaengine.h |
| [src/lib/lua/bridge] | LuaBridge.h* |
| [src/lib/lua/bridge/detail] | CFunctions.h* ClassInfo.h* Constructor.h* FuncTraits.h* Iterator.h* LuaException.h* LuaHelpers.h* LuaRef.h* Namespace.h* Stack.h* TypeList.h* TypeTraits.h* Userdata.h* dump.h* |
| r31045 | r31046 | |
|---|---|---|
| 16 | 16 | #include "lua/lua.hpp" |
| 17 | 17 | #include "lua/lib/lualibs.h" |
| 18 | 18 | #include "web/mongoose.h" |
| 19 | #include "lua/bridge/LuaBridge.h" | |
| 19 | 20 | |
| 20 | 21 | //************************************************************************** |
| 21 | 22 | // LUA ENGINE |
| r31045 | r31046 | |
| 341 | 342 | return 1; |
| 342 | 343 | } |
| 343 | 344 | |
| 344 | //------------------------------------------------- | |
| 345 | // luaopen_emu - connect emu section lib | |
| 346 | //------------------------------------------------- | |
| 347 | ||
| 348 | int lua_engine::luaopen_emu(lua_State *L) | |
| 349 | { | |
| 350 | static const struct luaL_Reg emu_funcs [] = { | |
| 351 | { "gamename", l_emu_gamename }, | |
| 352 | { "keypost", l_emu_keypost }, | |
| 353 | { "hook_output", l_emu_hook_output }, | |
| 354 | { "time", l_emu_time }, | |
| 355 | { "wait", l_emu_wait }, | |
| 356 | { "after", l_emu_after }, | |
| 357 | { "exit", l_emu_exit }, | |
| 358 | { "start", l_emu_start }, | |
| 359 | { NULL, NULL } /* sentinel */ | |
| 360 | }; | |
| 361 | ||
| 362 | luaL_newlib(L, emu_funcs); | |
| 363 | return 1; | |
| 364 | } | |
| 365 | ||
| 366 | 345 | int lua_engine::luaopen_ioport(lua_State *L) |
| 367 | 346 | { |
| 368 | 347 | static const struct luaL_Reg ioport_funcs [] = { |
| r31045 | r31046 | |
| 466 | 445 | luaL_openlibs(m_lua_state); /* open libraries */ |
| 467 | 446 | |
| 468 | 447 | luaopen_lsqlite3(m_lua_state); |
| 469 | luaL_requiref(m_lua_state, "emu", luaopen_emu, 1); | |
| 470 | 448 | |
| 471 | 449 | luaopen_ioport(m_lua_state); |
| 472 | 450 | |
| r31045 | r31046 | |
| 515 | 493 | |
| 516 | 494 | void lua_engine::initialize() |
| 517 | 495 | { |
| 496 | luabridge::getGlobalNamespace (m_lua_state) | |
| 497 | .beginNamespace ("emu") | |
| 498 | .addCFunction ("gamename", l_emu_gamename ) | |
| 499 | .addCFunction ("keypost", l_emu_keypost ) | |
| 500 | .addCFunction ("hook_output", l_emu_hook_output ) | |
| 501 | .addCFunction ("time", l_emu_time ) | |
| 502 | .addCFunction ("wait", l_emu_wait ) | |
| 503 | .addCFunction ("after", l_emu_after ) | |
| 504 | .addCFunction ("exit", l_emu_exit ) | |
| 505 | .addCFunction ("start", l_emu_start ) | |
| 506 | .beginClass <machine_manager> ("manager") | |
| 507 | .addFunction ("machine", &machine_manager::machine) | |
| 508 | .addFunction ("options", &machine_manager::options) | |
| 509 | .endClass () | |
| 510 | .beginClass <running_machine> ("machine") | |
| 511 | .addFunction ("exit", &running_machine::schedule_exit) | |
| 512 | .addFunction ("hard_reset", &running_machine::schedule_hard_reset) | |
| 513 | .addFunction ("soft_reset", &running_machine::schedule_soft_reset) | |
| 514 | .addFunction ("system", &running_machine::system) | |
| 515 | .endClass () | |
| 516 | .beginClass <game_driver> ("game_driver") | |
| 517 | .addData ("name", &game_driver::name) | |
| 518 | .addData ("description", &game_driver::description) | |
| 519 | .addData ("year", &game_driver::year) | |
| 520 | .addData ("manufacturer", &game_driver::manufacturer) | |
| 521 | .endClass () | |
| 522 | .endNamespace (); | |
| 523 | luabridge::push (m_lua_state, machine_manager::instance()); | |
| 524 | lua_setglobal(m_lua_state, "manager"); | |
| 525 | ||
| 518 | 526 | mg_start_thread(::serve_lua, this); |
| 519 | 527 | } |
| 520 | 528 |
| r31045 | r31046 | |
|---|---|---|
| 86 | 86 | void resume(void *L, INT32 param); |
| 87 | 87 | void report_errors(int status); |
| 88 | 88 | void start(); |
| 89 | static int luaopen_emu(lua_State *L); | |
| 90 | 89 | static int luaopen_ioport(lua_State *L); |
| 91 | 90 | void close(); |
| 92 | 91 |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | ||
| 7 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 8 | ||
| 9 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 10 | of this software and associated documentation files (the "Software"), to deal | |
| 11 | in the Software without restriction, including without limitation the rights | |
| 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 13 | copies of the Software, and to permit persons to whom the Software is | |
| 14 | furnished to do so, subject to the following conditions: | |
| 15 | ||
| 16 | The above copyright notice and this permission notice shall be included in all | |
| 17 | copies or substantial portions of the Software. | |
| 18 | ||
| 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 25 | SOFTWARE. | |
| 26 | */ | |
| 27 | //============================================================================== | |
| 28 | ||
| 29 | #ifndef LUABRIDGE_TYPEINFO_HEADER | |
| 30 | #define LUABRIDGE_TYPEINFO_HEADER | |
| 31 | ||
| 32 | //------------------------------------------------------------------------------ | |
| 33 | /** | |
| 34 | Container traits. | |
| 35 | ||
| 36 | Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE. | |
| 37 | All user defined containers must supply an appropriate specialization for | |
| 38 | ContinerTraits (without the typedef isNotContainer). The containers that | |
| 39 | come with LuaBridge also come with the appropriate ContainerTraits | |
| 40 | specialization. See the corresponding declaration for details. | |
| 41 | ||
| 42 | A specialization of ContainerTraits for some generic type ContainerType | |
| 43 | looks like this: | |
| 44 | ||
| 45 | template <class T> | |
| 46 | struct ContainerTraits <ContainerType <T> > | |
| 47 | { | |
| 48 | typedef typename T Type; | |
| 49 | ||
| 50 | static T* get (ContainerType <T> const& c) | |
| 51 | { | |
| 52 | return c.get (); // Implementation-dependent on ContainerType | |
| 53 | } | |
| 54 | }; | |
| 55 | */ | |
| 56 | template <class T> | |
| 57 | struct ContainerTraits | |
| 58 | { | |
| 59 | typedef bool isNotContainer; | |
| 60 | }; | |
| 61 | ||
| 62 | //------------------------------------------------------------------------------ | |
| 63 | /** | |
| 64 | Type traits. | |
| 65 | ||
| 66 | Specializations return information about a type. | |
| 67 | */ | |
| 68 | struct TypeTraits | |
| 69 | { | |
| 70 | /** Determine if type T is a container. | |
| 71 | ||
| 72 | To be considered a container, there must be a specialization of | |
| 73 | ContainerTraits with the required fields. | |
| 74 | */ | |
| 75 | template <typename T> | |
| 76 | class isContainer | |
| 77 | { | |
| 78 | private: | |
| 79 | typedef char yes[1]; // sizeof (yes) == 1 | |
| 80 | typedef char no [2]; // sizeof (no) == 2 | |
| 81 | ||
| 82 | template <typename C> | |
| 83 | static no& test (typename C::isNotContainer*); | |
| 84 | ||
| 85 | template <typename> | |
| 86 | static yes& test (...); | |
| 87 | ||
| 88 | public: | |
| 89 | static const bool value = sizeof (test <ContainerTraits <T> >(0)) == sizeof (yes); | |
| 90 | }; | |
| 91 | ||
| 92 | /** Determine if T is const qualified. | |
| 93 | */ | |
| 94 | /** @{ */ | |
| 95 | template <class T> | |
| 96 | struct isConst | |
| 97 | { | |
| 98 | static bool const value = false; | |
| 99 | }; | |
| 100 | ||
| 101 | template <class T> | |
| 102 | struct isConst <T const> | |
| 103 | { | |
| 104 | static bool const value = true; | |
| 105 | }; | |
| 106 | /** @} */ | |
| 107 | ||
| 108 | /** Remove the const qualifier from T. | |
| 109 | */ | |
| 110 | /** @{ */ | |
| 111 | template <class T> | |
| 112 | struct removeConst | |
| 113 | { | |
| 114 | typedef T Type; | |
| 115 | }; | |
| 116 | ||
| 117 | template <class T> | |
| 118 | struct removeConst <T const> | |
| 119 | { | |
| 120 | typedef T Type; | |
| 121 | }; | |
| 122 | /**@}*/ | |
| 123 | }; | |
| 124 | ||
| 125 | #endif |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | ||
| 7 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 8 | ||
| 9 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 10 | of this software and associated documentation files (the "Software"), to deal | |
| 11 | in the Software without restriction, including without limitation the rights | |
| 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 13 | copies of the Software, and to permit persons to whom the Software is | |
| 14 | furnished to do so, subject to the following conditions: | |
| 15 | ||
| 16 | The above copyright notice and this permission notice shall be included in all | |
| 17 | copies or substantial portions of the Software. | |
| 18 | ||
| 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 25 | SOFTWARE. | |
| 26 | */ | |
| 27 | //============================================================================== | |
| 28 | ||
| 29 | //============================================================================== | |
| 30 | /** | |
| 31 | Return the identity pointer for our lightuserdata tokens. | |
| 32 | ||
| 33 | LuaBridge metatables are tagged with a security "token." The token is a | |
| 34 | lightuserdata created from the identity pointer, used as a key in the | |
| 35 | metatable. The value is a boolean = true, although any value could have been | |
| 36 | used. | |
| 37 | ||
| 38 | Because of Lua's dynamic typing and our improvised system of imposing C++ | |
| 39 | class structure, there is the possibility that executing scripts may | |
| 40 | knowingly or unknowingly cause invalid data to get passed to the C functions | |
| 41 | created by LuaBridge. In particular, our security model addresses the | |
| 42 | following: | |
| 43 | ||
| 44 | Notes: | |
| 45 | 1. Scripts cannot create a userdata (ignoring the debug lib). | |
| 46 | 2. Scripts cannot create a lightuserdata (ignoring the debug lib). | |
| 47 | 3. Scripts cannot set the metatable on a userdata. | |
| 48 | 4. Our identity key is a unique pointer in the process. | |
| 49 | 5. Our metatables have a lightuserdata identity key / value pair. | |
| 50 | 6. Our metatables have "__metatable" set to a boolean = false. | |
| 51 | 7. Our lightuserdata is unique. | |
| 52 | */ | |
| 53 | inline void* getIdentityKey () | |
| 54 | { | |
| 55 | static char value; | |
| 56 | return &value; | |
| 57 | } | |
| 58 | ||
| 59 | /** | |
| 60 | Interface to a class pointer retrievable from a userdata. | |
| 61 | */ | |
| 62 | class Userdata | |
| 63 | { | |
| 64 | protected: | |
| 65 | void* m_p; // subclasses must set this | |
| 66 | ||
| 67 | //-------------------------------------------------------------------------- | |
| 68 | /** | |
| 69 | Get an untyped pointer to the contained class. | |
| 70 | */ | |
| 71 | inline void* const getPointer () | |
| 72 | { | |
| 73 | return m_p; | |
| 74 | } | |
| 75 | ||
| 76 | private: | |
| 77 | //-------------------------------------------------------------------------- | |
| 78 | /** | |
| 79 | Validate and retrieve a Userdata on the stack. | |
| 80 | ||
| 81 | The Userdata must exactly match the corresponding class table or | |
| 82 | const table, or else a Lua error is raised. This is used for the | |
| 83 | __gc metamethod. | |
| 84 | */ | |
| 85 | static Userdata* getExactClass (lua_State* L, | |
| 86 | int narg, | |
| 87 | void const* classKey) | |
| 88 | { | |
| 89 | Userdata* ud = 0; | |
| 90 | int const index = lua_absindex (L, narg); | |
| 91 | ||
| 92 | bool mismatch = false; | |
| 93 | char const* got = 0; | |
| 94 | ||
| 95 | lua_rawgetp (L, LUA_REGISTRYINDEX, classKey); | |
| 96 | assert (lua_istable (L, -1)); | |
| 97 | ||
| 98 | // Make sure we have a userdata. | |
| 99 | if (!lua_isuserdata (L, index)) | |
| 100 | mismatch = true; | |
| 101 | ||
| 102 | // Make sure it's metatable is ours. | |
| 103 | if (!mismatch) | |
| 104 | { | |
| 105 | lua_getmetatable (L, index); | |
| 106 | lua_rawgetp (L, -1, getIdentityKey ()); | |
| 107 | if (lua_isboolean (L, -1)) | |
| 108 | { | |
| 109 | lua_pop (L, 1); | |
| 110 | } | |
| 111 | else | |
| 112 | { | |
| 113 | lua_pop (L, 2); | |
| 114 | mismatch = true; | |
| 115 | } | |
| 116 | } | |
| 117 | ||
| 118 | if (!mismatch) | |
| 119 | { | |
| 120 | if (lua_rawequal (L, -1, -2)) | |
| 121 | { | |
| 122 | // Matches class table. | |
| 123 | lua_pop (L, 2); | |
| 124 | ud = static_cast <Userdata*> (lua_touserdata (L, index)); | |
| 125 | } | |
| 126 | else | |
| 127 | { | |
| 128 | rawgetfield (L, -2, "__const"); | |
| 129 | if (lua_rawequal (L, -1, -2)) | |
| 130 | { | |
| 131 | // Matches const table | |
| 132 | lua_pop (L, 3); | |
| 133 | ud = static_cast <Userdata*> (lua_touserdata (L, index)); | |
| 134 | } | |
| 135 | else | |
| 136 | { | |
| 137 | // Mismatch, but its one of ours so get a type name. | |
| 138 | rawgetfield (L, -2, "__type"); | |
| 139 | lua_insert (L, -4); | |
| 140 | lua_pop (L, 2); | |
| 141 | got = lua_tostring (L, -2); | |
| 142 | mismatch = true; | |
| 143 | } | |
| 144 | } | |
| 145 | } | |
| 146 | ||
| 147 | if (mismatch) | |
| 148 | { | |
| 149 | rawgetfield (L, -1, "__type"); | |
| 150 | assert (lua_type (L, -1) == LUA_TSTRING); | |
| 151 | char const* const expected = lua_tostring (L, -1); | |
| 152 | ||
| 153 | if (got == 0) | |
| 154 | got = lua_typename (L, lua_type (L, index)); | |
| 155 | ||
| 156 | char const* const msg = lua_pushfstring ( | |
| 157 | L, "%s expected, got %s", expected, got); | |
| 158 | ||
| 159 | if (narg > 0) | |
| 160 | luaL_argerror (L, narg, msg); | |
| 161 | else | |
| 162 | lua_error (L); | |
| 163 | } | |
| 164 | ||
| 165 | return ud; | |
| 166 | } | |
| 167 | ||
| 168 | //-------------------------------------------------------------------------- | |
| 169 | /** | |
| 170 | Validate and retrieve a Userdata on the stack. | |
| 171 | ||
| 172 | The Userdata must be derived from or the same as the given base class, | |
| 173 | identified by the key. If canBeConst is false, generates an error if | |
| 174 | the resulting Userdata represents to a const object. We do the type check | |
| 175 | first so that the error message is informative. | |
| 176 | */ | |
| 177 | static Userdata* getClass (lua_State* L, | |
| 178 | int index, | |
| 179 | void const* baseClassKey, | |
| 180 | bool canBeConst) | |
| 181 | { | |
| 182 | assert (index > 0); | |
| 183 | Userdata* ud = 0; | |
| 184 | ||
| 185 | bool mismatch = false; | |
| 186 | char const* got = 0; | |
| 187 | ||
| 188 | lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey); | |
| 189 | assert (lua_istable (L, -1)); | |
| 190 | ||
| 191 | // Make sure we have a userdata. | |
| 192 | if (lua_isuserdata (L, index)) | |
| 193 | { | |
| 194 | // Make sure it's metatable is ours. | |
| 195 | lua_getmetatable (L, index); | |
| 196 | lua_rawgetp (L, -1, getIdentityKey ()); | |
| 197 | if (lua_isboolean (L, -1)) | |
| 198 | { | |
| 199 | lua_pop (L, 1); | |
| 200 | ||
| 201 | // If __const is present, object is NOT const. | |
| 202 | rawgetfield (L, -1, "__const"); | |
| 203 | assert (lua_istable (L, -1) || lua_isnil (L, -1)); | |
| 204 | bool const isConst = lua_isnil (L, -1); | |
| 205 | lua_pop (L, 1); | |
| 206 | ||
| 207 | // Replace the class table with the const table if needed. | |
| 208 | if (isConst) | |
| 209 | { | |
| 210 | rawgetfield (L, -2, "__const"); | |
| 211 | assert (lua_istable (L, -1)); | |
| 212 | lua_replace (L, -3); | |
| 213 | } | |
| 214 | ||
| 215 | for (;;) | |
| 216 | { | |
| 217 | if (lua_rawequal (L, -1, -2)) | |
| 218 | { | |
| 219 | lua_pop (L, 2); | |
| 220 | ||
| 221 | // Match, now check const-ness. | |
| 222 | if (isConst && !canBeConst) | |
| 223 | { | |
| 224 | luaL_argerror (L, index, "cannot be const"); | |
| 225 | } | |
| 226 | else | |
| 227 | { | |
| 228 | ud = static_cast <Userdata*> (lua_touserdata (L, index)); | |
| 229 | break; | |
| 230 | } | |
| 231 | } | |
| 232 | else | |
| 233 | { | |
| 234 | // Replace current metatable with it's base class. | |
| 235 | rawgetfield (L, -1, "__parent"); | |
| 236 | /* | |
| 237 | ud | |
| 238 | class metatable | |
| 239 | ud metatable | |
| 240 | ud __parent (nil) | |
| 241 | */ | |
| 242 | ||
| 243 | if (lua_isnil (L, -1)) | |
| 244 | { | |
| 245 | lua_remove (L, -1); | |
| 246 | // Mismatch, but its one of ours so get a type name. | |
| 247 | rawgetfield (L, -1, "__type"); | |
| 248 | lua_insert (L, -3); | |
| 249 | lua_pop (L, 1); | |
| 250 | got = lua_tostring (L, -2); | |
| 251 | mismatch = true; | |
| 252 | break; | |
| 253 | } | |
| 254 | else | |
| 255 | { | |
| 256 | lua_remove (L, -2); | |
| 257 | } | |
| 258 | } | |
| 259 | } | |
| 260 | } | |
| 261 | else | |
| 262 | { | |
| 263 | lua_pop (L, 2); | |
| 264 | mismatch = true; | |
| 265 | } | |
| 266 | } | |
| 267 | else | |
| 268 | { | |
| 269 | mismatch = true; | |
| 270 | } | |
| 271 | ||
| 272 | if (mismatch) | |
| 273 | { | |
| 274 | assert (lua_type (L, -1) == LUA_TTABLE); | |
| 275 | rawgetfield (L, -1, "__type"); | |
| 276 | assert (lua_type (L, -1) == LUA_TSTRING); | |
| 277 | char const* const expected = lua_tostring (L, -1); | |
| 278 | ||
| 279 | if (got == 0) | |
| 280 | got = lua_typename (L, lua_type (L, index)); | |
| 281 | ||
| 282 | char const* const msg = lua_pushfstring ( | |
| 283 | L, "%s expected, got %s", expected, got); | |
| 284 | ||
| 285 | luaL_argerror (L, index, msg); | |
| 286 | } | |
| 287 | ||
| 288 | return ud; | |
| 289 | } | |
| 290 | ||
| 291 | public: | |
| 292 | virtual ~Userdata () { } | |
| 293 | ||
| 294 | //-------------------------------------------------------------------------- | |
| 295 | /** | |
| 296 | Returns the Userdata* if the class on the Lua stack matches. | |
| 297 | ||
| 298 | If the class does not match, a Lua error is raised. | |
| 299 | */ | |
| 300 | template <class T> | |
| 301 | static inline Userdata* getExact (lua_State* L, int index) | |
| 302 | { | |
| 303 | return getExactClass (L, index, ClassInfo <T>::getClassKey ()); | |
| 304 | } | |
| 305 | ||
| 306 | //-------------------------------------------------------------------------- | |
| 307 | /** | |
| 308 | Get a pointer to the class from the Lua stack. | |
| 309 | ||
| 310 | If the object is not the class or a subclass, or it violates the | |
| 311 | const-ness, a Lua error is raised. | |
| 312 | */ | |
| 313 | template <class T> | |
| 314 | static inline T* get (lua_State* L, int index, bool canBeConst) | |
| 315 | { | |
| 316 | if (lua_isnil (L, index)) | |
| 317 | return 0; | |
| 318 | else | |
| 319 | return static_cast <T*> (getClass (L, index, | |
| 320 | ClassInfo <T>::getClassKey (), canBeConst)->getPointer ()); | |
| 321 | } | |
| 322 | }; | |
| 323 | ||
| 324 | //---------------------------------------------------------------------------- | |
| 325 | /** | |
| 326 | Wraps a class object stored in a Lua userdata. | |
| 327 | ||
| 328 | The lifetime of the object is managed by Lua. The object is constructed | |
| 329 | inside the userdata using placement new. | |
| 330 | */ | |
| 331 | template <class T> | |
| 332 | class UserdataValue : public Userdata | |
| 333 | { | |
| 334 | private: | |
| 335 | UserdataValue <T> (UserdataValue <T> const&); | |
| 336 | UserdataValue <T> operator= (UserdataValue <T> const&); | |
| 337 | ||
| 338 | char m_storage [sizeof (T)]; | |
| 339 | ||
| 340 | inline T* getObject () | |
| 341 | { | |
| 342 | // If this fails to compile it means you forgot to provide | |
| 343 | // a Container specialization for your container! | |
| 344 | // | |
| 345 | return reinterpret_cast <T*> (&m_storage [0]); | |
| 346 | } | |
| 347 | ||
| 348 | private: | |
| 349 | /** | |
| 350 | Used for placement construction. | |
| 351 | */ | |
| 352 | UserdataValue () | |
| 353 | { | |
| 354 | m_p = getObject (); | |
| 355 | } | |
| 356 | ||
| 357 | ~UserdataValue () | |
| 358 | { | |
| 359 | getObject ()->~T (); | |
| 360 | } | |
| 361 | ||
| 362 | public: | |
| 363 | /** | |
| 364 | Push a T via placement new. | |
| 365 | ||
| 366 | The caller is responsible for calling placement new using the | |
| 367 | returned uninitialized storage. | |
| 368 | */ | |
| 369 | static void* place (lua_State* const L) | |
| 370 | { | |
| 371 | UserdataValue <T>* const ud = new ( | |
| 372 | lua_newuserdata (L, sizeof (UserdataValue <T>))) UserdataValue <T> (); | |
| 373 | lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); | |
| 374 | // If this goes off it means you forgot to register the class! | |
| 375 | assert (lua_istable (L, -1)); | |
| 376 | lua_setmetatable (L, -2); | |
| 377 | return ud->getPointer (); | |
| 378 | } | |
| 379 | ||
| 380 | /** | |
| 381 | Push T via copy construction from U. | |
| 382 | */ | |
| 383 | template <class U> | |
| 384 | static inline void push (lua_State* const L, U const& u) | |
| 385 | { | |
| 386 | new (place (L)) U (u); | |
| 387 | } | |
| 388 | }; | |
| 389 | ||
| 390 | //---------------------------------------------------------------------------- | |
| 391 | /** | |
| 392 | Wraps a pointer to a class object inside a Lua userdata. | |
| 393 | ||
| 394 | The lifetime of the object is managed by C++. | |
| 395 | */ | |
| 396 | class UserdataPtr : public Userdata | |
| 397 | { | |
| 398 | private: | |
| 399 | UserdataPtr (UserdataPtr const&); | |
| 400 | UserdataPtr operator= (UserdataPtr const&); | |
| 401 | ||
| 402 | private: | |
| 403 | /** Push non-const pointer to object using metatable key. | |
| 404 | */ | |
| 405 | static void push (lua_State* L, void* const p, void const* const key) | |
| 406 | { | |
| 407 | if (p) | |
| 408 | { | |
| 409 | new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p); | |
| 410 | lua_rawgetp (L, LUA_REGISTRYINDEX, key); | |
| 411 | // If this goes off it means you forgot to register the class! | |
| 412 | assert (lua_istable (L, -1)); | |
| 413 | lua_setmetatable (L, -2); | |
| 414 | } | |
| 415 | else | |
| 416 | { | |
| 417 | lua_pushnil (L); | |
| 418 | } | |
| 419 | } | |
| 420 | ||
| 421 | /** Push const pointer to object using metatable key. | |
| 422 | */ | |
| 423 | static void push (lua_State* L, void const* const p, void const* const key) | |
| 424 | { | |
| 425 | if (p) | |
| 426 | { | |
| 427 | new (lua_newuserdata (L, sizeof (UserdataPtr))) | |
| 428 | UserdataPtr (const_cast <void*> (p)); | |
| 429 | lua_rawgetp (L, LUA_REGISTRYINDEX, key); | |
| 430 | // If this goes off it means you forgot to register the class! | |
| 431 | assert (lua_istable (L, -1)); | |
| 432 | lua_setmetatable (L, -2); | |
| 433 | } | |
| 434 | else | |
| 435 | { | |
| 436 | lua_pushnil (L); | |
| 437 | } | |
| 438 | } | |
| 439 | ||
| 440 | explicit UserdataPtr (void* const p) | |
| 441 | { | |
| 442 | m_p = p; | |
| 443 | ||
| 444 | // Can't construct with a null pointer! | |
| 445 | // | |
| 446 | assert (m_p != 0); | |
| 447 | } | |
| 448 | ||
| 449 | public: | |
| 450 | /** Push non-const pointer to object. | |
| 451 | */ | |
| 452 | template <class T> | |
| 453 | static inline void push (lua_State* const L, T* const p) | |
| 454 | { | |
| 455 | if (p) | |
| 456 | push (L, p, ClassInfo <T>::getClassKey ()); | |
| 457 | else | |
| 458 | lua_pushnil (L); | |
| 459 | } | |
| 460 | ||
| 461 | /** Push const pointer to object. | |
| 462 | */ | |
| 463 | template <class T> | |
| 464 | static inline void push (lua_State* const L, T const* const p) | |
| 465 | { | |
| 466 | if (p) | |
| 467 | push (L, p, ClassInfo <T>::getConstKey ()); | |
| 468 | else | |
| 469 | lua_pushnil (L); | |
| 470 | } | |
| 471 | }; | |
| 472 | ||
| 473 | //============================================================================ | |
| 474 | /** | |
| 475 | Wraps a container thet references a class object. | |
| 476 | ||
| 477 | The template argument C is the container type, ContainerTraits must be | |
| 478 | specialized on C or else a compile error will result. | |
| 479 | */ | |
| 480 | template <class C> | |
| 481 | class UserdataShared : public Userdata | |
| 482 | { | |
| 483 | private: | |
| 484 | UserdataShared (UserdataShared <C> const&); | |
| 485 | UserdataShared <C>& operator= (UserdataShared <C> const&); | |
| 486 | ||
| 487 | typedef typename TypeTraits::removeConst < | |
| 488 | typename ContainerTraits <C>::Type>::Type T; | |
| 489 | ||
| 490 | C m_c; | |
| 491 | ||
| 492 | private: | |
| 493 | ~UserdataShared () | |
| 494 | { | |
| 495 | } | |
| 496 | ||
| 497 | public: | |
| 498 | /** | |
| 499 | Construct from a container to the class or a derived class. | |
| 500 | */ | |
| 501 | template <class U> | |
| 502 | explicit UserdataShared (U const& u) : m_c (u) | |
| 503 | { | |
| 504 | m_p = const_cast <void*> (reinterpret_cast <void const*> ( | |
| 505 | (ContainerTraits <C>::get (m_c)))); | |
| 506 | } | |
| 507 | ||
| 508 | /** | |
| 509 | Construct from a pointer to the class or a derived class. | |
| 510 | */ | |
| 511 | template <class U> | |
| 512 | explicit UserdataShared (U* u) : m_c (u) | |
| 513 | { | |
| 514 | m_p = const_cast <void*> (reinterpret_cast <void const*> ( | |
| 515 | (ContainerTraits <C>::get (m_c)))); | |
| 516 | } | |
| 517 | }; | |
| 518 | ||
| 519 | //---------------------------------------------------------------------------- | |
| 520 | // | |
| 521 | // SFINAE helpers. | |
| 522 | // | |
| 523 | ||
| 524 | // non-const objects | |
| 525 | template <class C, bool makeObjectConst> | |
| 526 | struct UserdataSharedHelper | |
| 527 | { | |
| 528 | typedef typename TypeTraits::removeConst < | |
| 529 | typename ContainerTraits <C>::Type>::Type T; | |
| 530 | ||
| 531 | static void push (lua_State* L, C const& c) | |
| 532 | { | |
| 533 | if (ContainerTraits <C>::get (c) != 0) | |
| 534 | { | |
| 535 | new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c); | |
| 536 | lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); | |
| 537 | // If this goes off it means the class T is unregistered! | |
| 538 | assert (lua_istable (L, -1)); | |
| 539 | lua_setmetatable (L, -2); | |
| 540 | } | |
| 541 | else | |
| 542 | { | |
| 543 | lua_pushnil (L); | |
| 544 | } | |
| 545 | } | |
| 546 | ||
| 547 | static void push (lua_State* L, T* const t) | |
| 548 | { | |
| 549 | if (t) | |
| 550 | { | |
| 551 | new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t); | |
| 552 | lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); | |
| 553 | // If this goes off it means the class T is unregistered! | |
| 554 | assert (lua_istable (L, -1)); | |
| 555 | lua_setmetatable (L, -2); | |
| 556 | } | |
| 557 | else | |
| 558 | { | |
| 559 | lua_pushnil (L); | |
| 560 | } | |
| 561 | } | |
| 562 | }; | |
| 563 | ||
| 564 | // const objects | |
| 565 | template <class C> | |
| 566 | struct UserdataSharedHelper <C, true> | |
| 567 | { | |
| 568 | typedef typename TypeTraits::removeConst < | |
| 569 | typename ContainerTraits <C>::Type>::Type T; | |
| 570 | ||
| 571 | static void push (lua_State* L, C const& c) | |
| 572 | { | |
| 573 | if (ContainerTraits <C>::get (c) != 0) | |
| 574 | { | |
| 575 | new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (c); | |
| 576 | lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); | |
| 577 | // If this goes off it means the class T is unregistered! | |
| 578 | assert (lua_istable (L, -1)); | |
| 579 | lua_setmetatable (L, -2); | |
| 580 | } | |
| 581 | else | |
| 582 | { | |
| 583 | lua_pushnil (L); | |
| 584 | } | |
| 585 | } | |
| 586 | ||
| 587 | static void push (lua_State* L, T* const t) | |
| 588 | { | |
| 589 | if (t) | |
| 590 | { | |
| 591 | new (lua_newuserdata (L, sizeof (UserdataShared <C>))) UserdataShared <C> (t); | |
| 592 | lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); | |
| 593 | // If this goes off it means the class T is unregistered! | |
| 594 | assert (lua_istable (L, -1)); | |
| 595 | lua_setmetatable (L, -2); | |
| 596 | } | |
| 597 | else | |
| 598 | { | |
| 599 | lua_pushnil (L); | |
| 600 | } | |
| 601 | } | |
| 602 | }; | |
| 603 | ||
| 604 | /** | |
| 605 | Pass by container. | |
| 606 | ||
| 607 | The container controls the object lifetime. Typically this will be a | |
| 608 | lifetime shared by C++ and Lua using a reference count. Because of type | |
| 609 | erasure, containers like std::shared_ptr will not work. Containers must | |
| 610 | either be of the intrusive variety, or in the style of the RefCountedPtr | |
| 611 | type provided by LuaBridge (that uses a global hash table). | |
| 612 | */ | |
| 613 | template <class C, bool byContainer> | |
| 614 | struct StackHelper | |
| 615 | { | |
| 616 | static inline void push (lua_State* L, C const& c) | |
| 617 | { | |
| 618 | UserdataSharedHelper <C, | |
| 619 | TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, c); | |
| 620 | } | |
| 621 | ||
| 622 | typedef typename TypeTraits::removeConst < | |
| 623 | typename ContainerTraits <C>::Type>::Type T; | |
| 624 | ||
| 625 | static inline C get (lua_State* L, int index) | |
| 626 | { | |
| 627 | return Userdata::get <T> (L, index, true); | |
| 628 | } | |
| 629 | }; | |
| 630 | ||
| 631 | /** | |
| 632 | Pass by value. | |
| 633 | ||
| 634 | Lifetime is managed by Lua. A C++ function which accesses a pointer or | |
| 635 | reference to an object outside the activation record in which it was | |
| 636 | retrieved may result in undefined behavior if Lua garbage collected it. | |
| 637 | */ | |
| 638 | template <class T> | |
| 639 | struct StackHelper <T, false> | |
| 640 | { | |
| 641 | static inline void push (lua_State* L, T const& t) | |
| 642 | { | |
| 643 | UserdataValue <T>::push (L, t); | |
| 644 | } | |
| 645 | ||
| 646 | static inline T const& get (lua_State* L, int index) | |
| 647 | { | |
| 648 | return *Userdata::get <T> (L, index, true); | |
| 649 | } | |
| 650 | }; | |
| 651 | ||
| 652 | //============================================================================== | |
| 653 | ||
| 654 | /** | |
| 655 | Lua stack conversions for class objects passed by value. | |
| 656 | */ | |
| 657 | template <class T> | |
| 658 | struct Stack | |
| 659 | { | |
| 660 | public: | |
| 661 | static inline void push (lua_State* L, T const& t) | |
| 662 | { | |
| 663 | StackHelper <T, | |
| 664 | TypeTraits::isContainer <T>::value>::push (L, t); | |
| 665 | } | |
| 666 | ||
| 667 | static inline T get (lua_State* L, int index) | |
| 668 | { | |
| 669 | return StackHelper <T, | |
| 670 | TypeTraits::isContainer <T>::value>::get (L, index); | |
| 671 | } | |
| 672 | }; | |
| 673 | ||
| 674 | //------------------------------------------------------------------------------ | |
| 675 | /** | |
| 676 | Lua stack conversions for pointers and references to class objects. | |
| 677 | ||
| 678 | Lifetime is managed by C++. Lua code which remembers a reference to the | |
| 679 | value may result in undefined behavior if C++ destroys the object. The | |
| 680 | handling of the const and volatile qualifiers happens in UserdataPtr. | |
| 681 | */ | |
| 682 | ||
| 683 | // pointer | |
| 684 | template <class T> | |
| 685 | struct Stack <T*> | |
| 686 | { | |
| 687 | static inline void push (lua_State* L, T* const p) | |
| 688 | { | |
| 689 | UserdataPtr::push (L, p); | |
| 690 | } | |
| 691 | ||
| 692 | static inline T* const get (lua_State* L, int index) | |
| 693 | { | |
| 694 | return Userdata::get <T> (L, index, false); | |
| 695 | } | |
| 696 | }; | |
| 697 | ||
| 698 | // Strips the const off the right side of * | |
| 699 | template <class T> | |
| 700 | struct Stack <T* const> | |
| 701 | { | |
| 702 | static inline void push (lua_State* L, T* const p) | |
| 703 | { | |
| 704 | UserdataPtr::push (L, p); | |
| 705 | } | |
| 706 | ||
| 707 | static inline T* const get (lua_State* L, int index) | |
| 708 | { | |
| 709 | return Userdata::get <T> (L, index, false); | |
| 710 | } | |
| 711 | }; | |
| 712 | ||
| 713 | // pointer to const | |
| 714 | template <class T> | |
| 715 | struct Stack <T const*> | |
| 716 | { | |
| 717 | static inline void push (lua_State* L, T const* const p) | |
| 718 | { | |
| 719 | UserdataPtr::push (L, p); | |
| 720 | } | |
| 721 | ||
| 722 | static inline T const* const get (lua_State* L, int index) | |
| 723 | { | |
| 724 | return Userdata::get <T> (L, index, true); | |
| 725 | } | |
| 726 | }; | |
| 727 | ||
| 728 | // Strips the const off the right side of * | |
| 729 | template <class T> | |
| 730 | struct Stack <T const* const> | |
| 731 | { | |
| 732 | static inline void push (lua_State* L, T const* const p) | |
| 733 | { | |
| 734 | UserdataPtr::push (L, p); | |
| 735 | } | |
| 736 | ||
| 737 | static inline T const* const get (lua_State* L, int index) | |
| 738 | { | |
| 739 | return Userdata::get <T> (L, index, true); | |
| 740 | } | |
| 741 | }; | |
| 742 | ||
| 743 | // reference | |
| 744 | template <class T> | |
| 745 | struct Stack <T&> | |
| 746 | { | |
| 747 | static inline void push (lua_State* L, T& t) | |
| 748 | { | |
| 749 | UserdataPtr::push (L, &t); | |
| 750 | } | |
| 751 | ||
| 752 | static T& get (lua_State* L, int index) | |
| 753 | { | |
| 754 | T* const t = Userdata::get <T> (L, index, false); | |
| 755 | if (!t) | |
| 756 | luaL_error (L, "nil passed to reference"); | |
| 757 | return *t; | |
| 758 | } | |
| 759 | }; | |
| 760 | ||
| 761 | template <class C, bool byContainer> | |
| 762 | struct RefStackHelper | |
| 763 | { | |
| 764 | typedef C return_type; | |
| 765 | ||
| 766 | static inline void push (lua_State* L, C const& t) | |
| 767 | { | |
| 768 | UserdataSharedHelper <C, | |
| 769 | TypeTraits::isConst <typename ContainerTraits <C>::Type>::value>::push (L, t); | |
| 770 | } | |
| 771 | ||
| 772 | typedef typename TypeTraits::removeConst < | |
| 773 | typename ContainerTraits <C>::Type>::Type T; | |
| 774 | ||
| 775 | static return_type get (lua_State* L, int index) | |
| 776 | { | |
| 777 | return Userdata::get <T> (L, index, true); | |
| 778 | } | |
| 779 | }; | |
| 780 | ||
| 781 | template <class T> | |
| 782 | struct RefStackHelper <T, false> | |
| 783 | { | |
| 784 | typedef T const& return_type; | |
| 785 | ||
| 786 | static inline void push (lua_State* L, T const& t) | |
| 787 | { | |
| 788 | UserdataPtr::push (L, &t); | |
| 789 | } | |
| 790 | ||
| 791 | static return_type get (lua_State* L, int index) | |
| 792 | { | |
| 793 | T const* const t = Userdata::get <T> (L, index, true); | |
| 794 | ||
| 795 | if (!t) | |
| 796 | luaL_error (L, "nil passed to reference"); | |
| 797 | return *t; | |
| 798 | } | |
| 799 | ||
| 800 | }; | |
| 801 | ||
| 802 | // reference to const | |
| 803 | template <class T> | |
| 804 | struct Stack <T const&> | |
| 805 | { | |
| 806 | typedef RefStackHelper <T, TypeTraits::isContainer <T>::value> helper_t; | |
| 807 | ||
| 808 | static inline void push (lua_State* L, T const& t) | |
| 809 | { | |
| 810 | helper_t::push (L, t); | |
| 811 | } | |
| 812 | ||
| 813 | static typename helper_t::return_type get (lua_State* L, int index) | |
| 814 | { | |
| 815 | return helper_t::get (L, index); | |
| 816 | } | |
| 817 | }; |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | ||
| 7 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 8 | ||
| 9 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 10 | of this software and associated documentation files (the "Software"), to deal | |
| 11 | in the Software without restriction, including without limitation the rights | |
| 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 13 | copies of the Software, and to permit persons to whom the Software is | |
| 14 | furnished to do so, subject to the following conditions: | |
| 15 | ||
| 16 | The above copyright notice and this permission notice shall be included in all | |
| 17 | copies or substantial portions of the Software. | |
| 18 | ||
| 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 25 | SOFTWARE. | |
| 26 | */ | |
| 27 | //============================================================================== | |
| 28 | ||
| 29 | /** Allows table iteration. | |
| 30 | */ | |
| 31 | class Iterator | |
| 32 | { | |
| 33 | private: | |
| 34 | lua_State* m_L; | |
| 35 | LuaRef m_table; | |
| 36 | LuaRef m_key; | |
| 37 | LuaRef m_value; | |
| 38 | ||
| 39 | void next () | |
| 40 | { | |
| 41 | m_table.push(m_L); | |
| 42 | m_key.push (m_L); | |
| 43 | if (lua_next (m_L, -2)) | |
| 44 | { | |
| 45 | m_value.pop (m_L); | |
| 46 | m_key.pop (m_L); | |
| 47 | } | |
| 48 | else | |
| 49 | { | |
| 50 | m_key = Nil(); | |
| 51 | m_value = Nil(); | |
| 52 | } | |
| 53 | lua_pop(m_L, 1); | |
| 54 | } | |
| 55 | ||
| 56 | public: | |
| 57 | explicit Iterator (LuaRef table) | |
| 58 | : m_L (table.state ()) | |
| 59 | , m_table (table) | |
| 60 | , m_key (table.state ()) // m_key is nil | |
| 61 | , m_value (table.state ()) // m_value is nil | |
| 62 | { | |
| 63 | next (); // get the first (key, value) pair from table | |
| 64 | } | |
| 65 | ||
| 66 | lua_State* state () const | |
| 67 | { | |
| 68 | return m_L; | |
| 69 | } | |
| 70 | ||
| 71 | LuaRef operator* () const | |
| 72 | { | |
| 73 | return m_value; | |
| 74 | } | |
| 75 | ||
| 76 | LuaRef operator-> () const | |
| 77 | { | |
| 78 | return m_value; | |
| 79 | } | |
| 80 | ||
| 81 | Iterator& operator++ () | |
| 82 | { | |
| 83 | if (isNil()) | |
| 84 | { | |
| 85 | // if the iterator reaches the end, do nothing | |
| 86 | return *this; | |
| 87 | } | |
| 88 | else | |
| 89 | { | |
| 90 | next(); | |
| 91 | return *this; | |
| 92 | } | |
| 93 | } | |
| 94 | ||
| 95 | inline bool isNil () const | |
| 96 | { | |
| 97 | return m_key.isNil (); | |
| 98 | } | |
| 99 | ||
| 100 | inline LuaRef key () const | |
| 101 | { | |
| 102 | return m_key; | |
| 103 | } | |
| 104 | ||
| 105 | inline LuaRef value () const | |
| 106 | { | |
| 107 | return m_value; | |
| 108 | } | |
| 109 | ||
| 110 | private: | |
| 111 | // Don't use postfix increment, it is less efficient | |
| 112 | Iterator operator++ (int); | |
| 113 | }; | |
| 114 |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | ||
| 7 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 8 | ||
| 9 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 10 | of this software and associated documentation files (the "Software"), to deal | |
| 11 | in the Software without restriction, including without limitation the rights | |
| 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 13 | copies of the Software, and to permit persons to whom the Software is | |
| 14 | furnished to do so, subject to the following conditions: | |
| 15 | ||
| 16 | The above copyright notice and this permission notice shall be included in all | |
| 17 | copies or substantial portions of the Software. | |
| 18 | ||
| 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 25 | SOFTWARE. | |
| 26 | */ | |
| 27 | //============================================================================== | |
| 28 | ||
| 29 | // We use a structure so we can define everything in the header. | |
| 30 | // | |
| 31 | struct CFunc | |
| 32 | { | |
| 33 | //---------------------------------------------------------------------------- | |
| 34 | /** | |
| 35 | __index metamethod for a namespace or class static members. | |
| 36 | ||
| 37 | This handles: | |
| 38 | Retrieving functions and class static methods, stored in the metatable. | |
| 39 | Reading global and class static data, stored in the __propget table. | |
| 40 | Reading global and class properties, stored in the __propget table. | |
| 41 | */ | |
| 42 | static int indexMetaMethod (lua_State* L) | |
| 43 | { | |
| 44 | int result = 0; | |
| 45 | lua_getmetatable (L, 1); // push metatable of arg1 | |
| 46 | for (;;) | |
| 47 | { | |
| 48 | lua_pushvalue (L, 2); // push key arg2 | |
| 49 | lua_rawget (L, -2); // lookup key in metatable | |
| 50 | if (lua_isnil (L, -1)) // not found | |
| 51 | { | |
| 52 | lua_pop (L, 1); // discard nil | |
| 53 | rawgetfield (L, -1, "__propget"); // lookup __propget in metatable | |
| 54 | lua_pushvalue (L, 2); // push key arg2 | |
| 55 | lua_rawget (L, -2); // lookup key in __propget | |
| 56 | lua_remove (L, -2); // discard __propget | |
| 57 | if (lua_iscfunction (L, -1)) | |
| 58 | { | |
| 59 | lua_remove (L, -2); // discard metatable | |
| 60 | lua_pushvalue (L, 1); // push arg1 | |
| 61 | lua_call (L, 1, 1); // call cfunction | |
| 62 | result = 1; | |
| 63 | break; | |
| 64 | } | |
| 65 | else | |
| 66 | { | |
| 67 | assert (lua_isnil (L, -1)); | |
| 68 | lua_pop (L, 1); // discard nil and fall through | |
| 69 | } | |
| 70 | } | |
| 71 | else | |
| 72 | { | |
| 73 | assert (lua_istable (L, -1) || lua_iscfunction (L, -1)); | |
| 74 | lua_remove (L, -2); | |
| 75 | result = 1; | |
| 76 | break; | |
| 77 | } | |
| 78 | ||
| 79 | rawgetfield (L, -1, "__parent"); | |
| 80 | if (lua_istable (L, -1)) | |
| 81 | { | |
| 82 | // Remove metatable and repeat the search in __parent. | |
| 83 | lua_remove (L, -2); | |
| 84 | } | |
| 85 | else | |
| 86 | { | |
| 87 | // Discard metatable and return nil. | |
| 88 | assert (lua_isnil (L, -1)); | |
| 89 | lua_remove (L, -2); | |
| 90 | result = 1; | |
| 91 | break; | |
| 92 | } | |
| 93 | } | |
| 94 | ||
| 95 | return result; | |
| 96 | } | |
| 97 | ||
| 98 | //---------------------------------------------------------------------------- | |
| 99 | /** | |
| 100 | __newindex metamethod for a namespace or class static members. | |
| 101 | ||
| 102 | The __propset table stores proxy functions for assignment to: | |
| 103 | Global and class static data. | |
| 104 | Global and class properties. | |
| 105 | */ | |
| 106 | static int newindexMetaMethod (lua_State* L) | |
| 107 | { | |
| 108 | int result = 0; | |
| 109 | lua_getmetatable (L, 1); // push metatable of arg1 | |
| 110 | for (;;) | |
| 111 | { | |
| 112 | rawgetfield (L, -1, "__propset"); // lookup __propset in metatable | |
| 113 | assert (lua_istable (L, -1)); | |
| 114 | lua_pushvalue (L, 2); // push key arg2 | |
| 115 | lua_rawget (L, -2); // lookup key in __propset | |
| 116 | lua_remove (L, -2); // discard __propset | |
| 117 | if (lua_iscfunction (L, -1)) // ensure value is a cfunction | |
| 118 | { | |
| 119 | lua_remove (L, -2); // discard metatable | |
| 120 | lua_pushvalue (L, 3); // push new value arg3 | |
| 121 | lua_call (L, 1, 0); // call cfunction | |
| 122 | result = 0; | |
| 123 | break; | |
| 124 | } | |
| 125 | else | |
| 126 | { | |
| 127 | assert (lua_isnil (L, -1)); | |
| 128 | lua_pop (L, 1); | |
| 129 | } | |
| 130 | ||
| 131 | rawgetfield (L, -1, "__parent"); | |
| 132 | if (lua_istable (L, -1)) | |
| 133 | { | |
| 134 | // Remove metatable and repeat the search in __parent. | |
| 135 | lua_remove (L, -2); | |
| 136 | } | |
| 137 | else | |
| 138 | { | |
| 139 | assert (lua_isnil (L, -1)); | |
| 140 | lua_pop (L, 2); | |
| 141 | result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2)); | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | return result; | |
| 146 | } | |
| 147 | ||
| 148 | //---------------------------------------------------------------------------- | |
| 149 | /** | |
| 150 | lua_CFunction to report an error writing to a read-only value. | |
| 151 | ||
| 152 | The name of the variable is in the first upvalue. | |
| 153 | */ | |
| 154 | static int readOnlyError (lua_State* L) | |
| 155 | { | |
| 156 | std::string s; | |
| 157 | ||
| 158 | s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only"; | |
| 159 | ||
| 160 | return luaL_error (L, s.c_str ()); | |
| 161 | } | |
| 162 | ||
| 163 | //---------------------------------------------------------------------------- | |
| 164 | /** | |
| 165 | lua_CFunction to get a variable. | |
| 166 | ||
| 167 | This is used for global variables or class static data members. | |
| 168 | ||
| 169 | The pointer to the data is in the first upvalue. | |
| 170 | */ | |
| 171 | template <class T> | |
| 172 | static int getVariable (lua_State* L) | |
| 173 | { | |
| 174 | assert (lua_islightuserdata (L, lua_upvalueindex (1))); | |
| 175 | T const* ptr = static_cast <T const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 176 | assert (ptr != 0); | |
| 177 | Stack <T>::push (L, *ptr); | |
| 178 | return 1; | |
| 179 | } | |
| 180 | ||
| 181 | //---------------------------------------------------------------------------- | |
| 182 | /** | |
| 183 | lua_CFunction to set a variable. | |
| 184 | ||
| 185 | This is used for global variables or class static data members. | |
| 186 | ||
| 187 | The pointer to the data is in the first upvalue. | |
| 188 | */ | |
| 189 | template <class T> | |
| 190 | static int setVariable (lua_State* L) | |
| 191 | { | |
| 192 | assert (lua_islightuserdata (L, lua_upvalueindex (1))); | |
| 193 | T* ptr = static_cast <T*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 194 | assert (ptr != 0); | |
| 195 | *ptr = Stack <T>::get (L, 1); | |
| 196 | return 0; | |
| 197 | } | |
| 198 | ||
| 199 | //---------------------------------------------------------------------------- | |
| 200 | /** | |
| 201 | lua_CFunction to call a function with a return value. | |
| 202 | ||
| 203 | This is used for global functions, global properties, class static methods, | |
| 204 | and class static properties. | |
| 205 | ||
| 206 | The function pointer is in the first upvalue. | |
| 207 | */ | |
| 208 | template <class FnPtr, | |
| 209 | class ReturnType = typename FuncTraits <FnPtr>::ReturnType> | |
| 210 | struct Call | |
| 211 | { | |
| 212 | typedef typename FuncTraits <FnPtr>::Params Params; | |
| 213 | static int f (lua_State* L) | |
| 214 | { | |
| 215 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 216 | FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 217 | assert (fnptr != 0); | |
| 218 | ArgList <Params> args (L); | |
| 219 | Stack <typename FuncTraits <FnPtr>::ReturnType>::push (L, FuncTraits <FnPtr>::call (fnptr, args)); | |
| 220 | return 1; | |
| 221 | } | |
| 222 | }; | |
| 223 | ||
| 224 | //---------------------------------------------------------------------------- | |
| 225 | /** | |
| 226 | lua_CFunction to call a function with no return value. | |
| 227 | ||
| 228 | This is used for global functions, global properties, class static methods, | |
| 229 | and class static properties. | |
| 230 | ||
| 231 | The function pointer is in the first upvalue. | |
| 232 | */ | |
| 233 | template <class FnPtr> | |
| 234 | struct Call <FnPtr, void> | |
| 235 | { | |
| 236 | typedef typename FuncTraits <FnPtr>::Params Params; | |
| 237 | static int f (lua_State* L) | |
| 238 | { | |
| 239 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 240 | FnPtr const& fnptr = *static_cast <FnPtr const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 241 | assert (fnptr != 0); | |
| 242 | ArgList <Params> args (L); | |
| 243 | FuncTraits <FnPtr>::call (fnptr, args); | |
| 244 | return 0; | |
| 245 | } | |
| 246 | }; | |
| 247 | ||
| 248 | //---------------------------------------------------------------------------- | |
| 249 | /** | |
| 250 | lua_CFunction to call a class member function with a return value. | |
| 251 | ||
| 252 | The member function pointer is in the first upvalue. | |
| 253 | The class userdata object is at the top of the Lua stack. | |
| 254 | */ | |
| 255 | template <class MemFnPtr, | |
| 256 | class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType> | |
| 257 | struct CallMember | |
| 258 | { | |
| 259 | typedef typename FuncTraits <MemFnPtr>::ClassType T; | |
| 260 | typedef typename FuncTraits <MemFnPtr>::Params Params; | |
| 261 | ||
| 262 | static int f (lua_State* L) | |
| 263 | { | |
| 264 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 265 | T* const t = Userdata::get <T> (L, 1, false); | |
| 266 | MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 267 | assert (fnptr != 0); | |
| 268 | ArgList <Params, 2> args (L); | |
| 269 | Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args)); | |
| 270 | return 1; | |
| 271 | } | |
| 272 | }; | |
| 273 | ||
| 274 | template <class MemFnPtr, | |
| 275 | class ReturnType = typename FuncTraits <MemFnPtr>::ReturnType> | |
| 276 | struct CallConstMember | |
| 277 | { | |
| 278 | typedef typename FuncTraits <MemFnPtr>::ClassType T; | |
| 279 | typedef typename FuncTraits <MemFnPtr>::Params Params; | |
| 280 | ||
| 281 | static int f (lua_State* L) | |
| 282 | { | |
| 283 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 284 | T const* const t = Userdata::get <T> (L, 1, true); | |
| 285 | MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 286 | assert (fnptr != 0); | |
| 287 | ArgList <Params, 2> args(L); | |
| 288 | Stack <ReturnType>::push (L, FuncTraits <MemFnPtr>::call (t, fnptr, args)); | |
| 289 | return 1; | |
| 290 | } | |
| 291 | }; | |
| 292 | ||
| 293 | //---------------------------------------------------------------------------- | |
| 294 | /** | |
| 295 | lua_CFunction to call a class member function with no return value. | |
| 296 | ||
| 297 | The member function pointer is in the first upvalue. | |
| 298 | The class userdata object is at the top of the Lua stack. | |
| 299 | */ | |
| 300 | template <class MemFnPtr> | |
| 301 | struct CallMember <MemFnPtr, void> | |
| 302 | { | |
| 303 | typedef typename FuncTraits <MemFnPtr>::ClassType T; | |
| 304 | typedef typename FuncTraits <MemFnPtr>::Params Params; | |
| 305 | ||
| 306 | static int f (lua_State* L) | |
| 307 | { | |
| 308 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 309 | T* const t = Userdata::get <T> (L, 1, false); | |
| 310 | MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 311 | assert (fnptr != 0); | |
| 312 | ArgList <Params, 2> args (L); | |
| 313 | FuncTraits <MemFnPtr>::call (t, fnptr, args); | |
| 314 | return 0; | |
| 315 | } | |
| 316 | }; | |
| 317 | ||
| 318 | template <class MemFnPtr> | |
| 319 | struct CallConstMember <MemFnPtr, void> | |
| 320 | { | |
| 321 | typedef typename FuncTraits <MemFnPtr>::ClassType T; | |
| 322 | typedef typename FuncTraits <MemFnPtr>::Params Params; | |
| 323 | ||
| 324 | static int f (lua_State* L) | |
| 325 | { | |
| 326 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 327 | T const* const t = Userdata::get <T> (L, 1, true); | |
| 328 | MemFnPtr const& fnptr = *static_cast <MemFnPtr const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 329 | assert (fnptr != 0); | |
| 330 | ArgList <Params, 2> args (L); | |
| 331 | FuncTraits <MemFnPtr>::call (t, fnptr, args); | |
| 332 | return 0; | |
| 333 | } | |
| 334 | }; | |
| 335 | ||
| 336 | //-------------------------------------------------------------------------- | |
| 337 | /** | |
| 338 | lua_CFunction to call a class member lua_CFunction. | |
| 339 | ||
| 340 | The member function pointer is in the first upvalue. | |
| 341 | The class userdata object is at the top of the Lua stack. | |
| 342 | */ | |
| 343 | template <class T> | |
| 344 | struct CallMemberCFunction | |
| 345 | { | |
| 346 | static int f (lua_State* L) | |
| 347 | { | |
| 348 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 349 | typedef int (T::*MFP)(lua_State* L); | |
| 350 | T* const t = Userdata::get <T> (L, 1, false); | |
| 351 | MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 352 | assert (fnptr != 0); | |
| 353 | return (t->*fnptr) (L); | |
| 354 | } | |
| 355 | }; | |
| 356 | ||
| 357 | template <class T> | |
| 358 | struct CallConstMemberCFunction | |
| 359 | { | |
| 360 | static int f (lua_State* L) | |
| 361 | { | |
| 362 | assert (isfulluserdata (L, lua_upvalueindex (1))); | |
| 363 | typedef int (T::*MFP)(lua_State* L); | |
| 364 | T const* const t = Userdata::get <T> (L, 1, true); | |
| 365 | MFP const& fnptr = *static_cast <MFP const*> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 366 | assert (fnptr != 0); | |
| 367 | return (t->*fnptr) (L); | |
| 368 | } | |
| 369 | }; | |
| 370 | ||
| 371 | //-------------------------------------------------------------------------- | |
| 372 | ||
| 373 | // SFINAE Helpers | |
| 374 | ||
| 375 | template <class MemFnPtr, bool isConst> | |
| 376 | struct CallMemberFunctionHelper | |
| 377 | { | |
| 378 | static void add (lua_State* L, char const* name, MemFnPtr mf) | |
| 379 | { | |
| 380 | new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf); | |
| 381 | lua_pushcclosure (L, &CallConstMember <MemFnPtr>::f, 1); | |
| 382 | lua_pushvalue (L, -1); | |
| 383 | rawsetfield (L, -5, name); // const table | |
| 384 | rawsetfield (L, -3, name); // class table | |
| 385 | } | |
| 386 | }; | |
| 387 | ||
| 388 | template <class MemFnPtr> | |
| 389 | struct CallMemberFunctionHelper <MemFnPtr, false> | |
| 390 | { | |
| 391 | static void add (lua_State* L, char const* name, MemFnPtr mf) | |
| 392 | { | |
| 393 | new (lua_newuserdata (L, sizeof (MemFnPtr))) MemFnPtr (mf); | |
| 394 | lua_pushcclosure (L, &CallMember <MemFnPtr>::f, 1); | |
| 395 | rawsetfield (L, -3, name); // class table | |
| 396 | } | |
| 397 | }; | |
| 398 | ||
| 399 | //-------------------------------------------------------------------------- | |
| 400 | /** | |
| 401 | __gc metamethod for a class. | |
| 402 | */ | |
| 403 | template <class C> | |
| 404 | static int gcMetaMethod (lua_State* L) | |
| 405 | { | |
| 406 | Userdata* const ud = Userdata::getExact <C> (L, 1); | |
| 407 | ud->~Userdata (); | |
| 408 | return 0; | |
| 409 | } | |
| 410 | ||
| 411 | //-------------------------------------------------------------------------- | |
| 412 | /** | |
| 413 | lua_CFunction to get a class data member. | |
| 414 | ||
| 415 | The pointer-to-member is in the first upvalue. | |
| 416 | The class userdata object is at the top of the Lua stack. | |
| 417 | */ | |
| 418 | template <class C, typename T> | |
| 419 | static int getProperty (lua_State* L) | |
| 420 | { | |
| 421 | C const* const c = Userdata::get <C> (L, 1, true); | |
| 422 | T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 423 | Stack <T>::push (L, c->**mp); | |
| 424 | return 1; | |
| 425 | } | |
| 426 | ||
| 427 | //-------------------------------------------------------------------------- | |
| 428 | /** | |
| 429 | lua_CFunction to set a class data member. | |
| 430 | ||
| 431 | The pointer-to-member is in the first upvalue. | |
| 432 | The class userdata object is at the top of the Lua stack. | |
| 433 | */ | |
| 434 | template <class C, typename T> | |
| 435 | static int setProperty (lua_State* L) | |
| 436 | { | |
| 437 | C* const c = Userdata::get <C> (L, 1, false); | |
| 438 | T C::** mp = static_cast <T C::**> (lua_touserdata (L, lua_upvalueindex (1))); | |
| 439 | c->**mp = Stack <T>::get (L, 2); | |
| 440 | return 0; | |
| 441 | } | |
| 442 | }; |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2007, Nathan Reed | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | /** Provides C++ to Lua registration capabilities. | |
| 31 | ||
| 32 | This class is not instantiated directly, call `getGlobalNamespace` to start | |
| 33 | the registration process. | |
| 34 | */ | |
| 35 | class Namespace | |
| 36 | { | |
| 37 | private: | |
| 38 | Namespace& operator= (Namespace const& other); | |
| 39 | ||
| 40 | lua_State* const L; | |
| 41 | int mutable m_stackSize; | |
| 42 | ||
| 43 | private: | |
| 44 | //============================================================================ | |
| 45 | /** | |
| 46 | Error reporting. | |
| 47 | ||
| 48 | VF: This function looks handy, why aren't we using it? | |
| 49 | */ | |
| 50 | #if 0 | |
| 51 | static int luaError (lua_State* L, std::string message) | |
| 52 | { | |
| 53 | assert (lua_isstring (L, lua_upvalueindex (1))); | |
| 54 | std::string s; | |
| 55 | ||
| 56 | // Get information on the caller's caller to format the message, | |
| 57 | // so the error appears to originate from the Lua source. | |
| 58 | lua_Debug ar; | |
| 59 | int result = lua_getstack (L, 2, &ar); | |
| 60 | if (result != 0) | |
| 61 | { | |
| 62 | lua_getinfo (L, "Sl", &ar); | |
| 63 | s = ar.short_src; | |
| 64 | if (ar.currentline != -1) | |
| 65 | { | |
| 66 | // poor mans int to string to avoid <strstrream>. | |
| 67 | lua_pushnumber (L, ar.currentline); | |
| 68 | s = s + ":" + lua_tostring (L, -1) + ": "; | |
| 69 | lua_pop (L, 1); | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | s = s + message; | |
| 74 | ||
| 75 | return luaL_error (L, s.c_str ()); | |
| 76 | } | |
| 77 | #endif | |
| 78 | ||
| 79 | //---------------------------------------------------------------------------- | |
| 80 | /** | |
| 81 | Pop the Lua stack. | |
| 82 | */ | |
| 83 | void pop (int n) const | |
| 84 | { | |
| 85 | if (m_stackSize >= n && lua_gettop (L) >= n) | |
| 86 | { | |
| 87 | lua_pop (L, n); | |
| 88 | m_stackSize -= n; | |
| 89 | } | |
| 90 | else | |
| 91 | { | |
| 92 | throw std::logic_error ("invalid stack"); | |
| 93 | } | |
| 94 | } | |
| 95 | ||
| 96 | private: | |
| 97 | /** | |
| 98 | Factored base to reduce template instantiations. | |
| 99 | */ | |
| 100 | class ClassBase | |
| 101 | { | |
| 102 | private: | |
| 103 | ClassBase& operator= (ClassBase const& other); | |
| 104 | ||
| 105 | protected: | |
| 106 | friend class Namespace; | |
| 107 | ||
| 108 | lua_State* const L; | |
| 109 | int mutable m_stackSize; | |
| 110 | ||
| 111 | protected: | |
| 112 | //-------------------------------------------------------------------------- | |
| 113 | /** | |
| 114 | __index metamethod for a class. | |
| 115 | ||
| 116 | This implements member functions, data members, and property members. | |
| 117 | Functions are stored in the metatable and const metatable. Data members | |
| 118 | and property members are in the __propget table. | |
| 119 | ||
| 120 | If the key is not found, the search proceeds up the hierarchy of base | |
| 121 | classes. | |
| 122 | */ | |
| 123 | static int indexMetaMethod (lua_State* L) | |
| 124 | { | |
| 125 | int result = 0; | |
| 126 | ||
| 127 | assert (lua_isuserdata (L, 1)); // warn on security bypass | |
| 128 | lua_getmetatable (L, 1); // get metatable for object | |
| 129 | for (;;) | |
| 130 | { | |
| 131 | lua_pushvalue (L, 2); // push key arg2 | |
| 132 | lua_rawget (L, -2); // lookup key in metatable | |
| 133 | if (lua_iscfunction (L, -1)) // ensure its a cfunction | |
| 134 | { | |
| 135 | lua_remove (L, -2); // remove metatable | |
| 136 | result = 1; | |
| 137 | break; | |
| 138 | } | |
| 139 | else if (lua_isnil (L, -1)) | |
| 140 | { | |
| 141 | lua_pop (L, 1); | |
| 142 | } | |
| 143 | else | |
| 144 | { | |
| 145 | lua_pop (L, 2); | |
| 146 | throw std::logic_error ("not a cfunction"); | |
| 147 | } | |
| 148 | ||
| 149 | rawgetfield (L, -1, "__propget"); // get __propget table | |
| 150 | if (lua_istable (L, -1)) // ensure it is a table | |
| 151 | { | |
| 152 | lua_pushvalue (L, 2); // push key arg2 | |
| 153 | lua_rawget (L, -2); // lookup key in __propget | |
| 154 | lua_remove (L, -2); // remove __propget | |
| 155 | if (lua_iscfunction (L, -1)) // ensure its a cfunction | |
| 156 | { | |
| 157 | lua_remove (L, -2); // remove metatable | |
| 158 | lua_pushvalue (L, 1); // push class arg1 | |
| 159 | lua_call (L, 1, 1); | |
| 160 | result = 1; | |
| 161 | break; | |
| 162 | } | |
| 163 | else if (lua_isnil (L, -1)) | |
| 164 | { | |
| 165 | lua_pop (L, 1); | |
| 166 | } | |
| 167 | else | |
| 168 | { | |
| 169 | lua_pop (L, 2); | |
| 170 | ||
| 171 | // We only put cfunctions into __propget. | |
| 172 | throw std::logic_error ("not a cfunction"); | |
| 173 | } | |
| 174 | } | |
| 175 | else | |
| 176 | { | |
| 177 | lua_pop (L, 2); | |
| 178 | ||
| 179 | // __propget is missing, or not a table. | |
| 180 | throw std::logic_error ("missing __propget table"); | |
| 181 | } | |
| 182 | ||
| 183 | // Repeat the lookup in the __parent metafield, | |
| 184 | // or return nil if the field doesn't exist. | |
| 185 | rawgetfield (L, -1, "__parent"); | |
| 186 | if (lua_istable (L, -1)) | |
| 187 | { | |
| 188 | // Remove metatable and repeat the search in __parent. | |
| 189 | lua_remove (L, -2); | |
| 190 | } | |
| 191 | else if (lua_isnil (L, -1)) | |
| 192 | { | |
| 193 | result = 1; | |
| 194 | break; | |
| 195 | } | |
| 196 | else | |
| 197 | { | |
| 198 | lua_pop (L, 2); | |
| 199 | ||
| 200 | throw std::logic_error ("__parent is not a table"); | |
| 201 | } | |
| 202 | } | |
| 203 | ||
| 204 | return result; | |
| 205 | } | |
| 206 | ||
| 207 | //-------------------------------------------------------------------------- | |
| 208 | /** | |
| 209 | __newindex metamethod for classes. | |
| 210 | ||
| 211 | This supports writable variables and properties on class objects. The | |
| 212 | corresponding object is passed in the first parameter to the set function. | |
| 213 | */ | |
| 214 | static int newindexMetaMethod (lua_State* L) | |
| 215 | { | |
| 216 | int result = 0; | |
| 217 | ||
| 218 | lua_getmetatable (L, 1); | |
| 219 | ||
| 220 | for (;;) | |
| 221 | { | |
| 222 | // Check __propset | |
| 223 | rawgetfield (L, -1, "__propset"); | |
| 224 | if (!lua_isnil (L, -1)) | |
| 225 | { | |
| 226 | lua_pushvalue (L, 2); | |
| 227 | lua_rawget (L, -2); | |
| 228 | if (!lua_isnil (L, -1)) | |
| 229 | { | |
| 230 | // found it, call the setFunction. | |
| 231 | assert (lua_isfunction (L, -1)); | |
| 232 | lua_pushvalue (L, 1); | |
| 233 | lua_pushvalue (L, 3); | |
| 234 | lua_call (L, 2, 0); | |
| 235 | result = 0; | |
| 236 | break; | |
| 237 | } | |
| 238 | lua_pop (L, 1); | |
| 239 | } | |
| 240 | lua_pop (L, 1); | |
| 241 | ||
| 242 | // Repeat the lookup in the __parent metafield. | |
| 243 | rawgetfield (L, -1, "__parent"); | |
| 244 | if (lua_isnil (L, -1)) | |
| 245 | { | |
| 246 | // Either the property or __parent must exist. | |
| 247 | result = luaL_error (L, | |
| 248 | "no member named '%s'", lua_tostring (L, 2)); | |
| 249 | } | |
| 250 | lua_remove (L, -2); | |
| 251 | } | |
| 252 | ||
| 253 | return result; | |
| 254 | } | |
| 255 | ||
| 256 | //-------------------------------------------------------------------------- | |
| 257 | /** | |
| 258 | Create the const table. | |
| 259 | */ | |
| 260 | void createConstTable (char const* name) | |
| 261 | { | |
| 262 | lua_newtable (L); | |
| 263 | lua_pushvalue (L, -1); | |
| 264 | lua_setmetatable (L, -2); | |
| 265 | lua_pushboolean (L, 1); | |
| 266 | lua_rawsetp (L, -2, getIdentityKey ()); | |
| 267 | lua_pushstring (L, (std::string ("const ") + name).c_str ()); | |
| 268 | rawsetfield (L, -2, "__type"); | |
| 269 | lua_pushcfunction (L, &indexMetaMethod); | |
| 270 | rawsetfield (L, -2, "__index"); | |
| 271 | lua_pushcfunction (L, &newindexMetaMethod); | |
| 272 | rawsetfield (L, -2, "__newindex"); | |
| 273 | lua_newtable (L); | |
| 274 | rawsetfield (L, -2, "__propget"); | |
| 275 | ||
| 276 | if (Security::hideMetatables ()) | |
| 277 | { | |
| 278 | lua_pushnil (L); | |
| 279 | rawsetfield (L, -2, "__metatable"); | |
| 280 | } | |
| 281 | } | |
| 282 | ||
| 283 | //-------------------------------------------------------------------------- | |
| 284 | /** | |
| 285 | Create the class table. | |
| 286 | ||
| 287 | The Lua stack should have the const table on top. | |
| 288 | */ | |
| 289 | void createClassTable (char const* name) | |
| 290 | { | |
| 291 | lua_newtable (L); | |
| 292 | lua_pushvalue (L, -1); | |
| 293 | lua_setmetatable (L, -2); | |
| 294 | lua_pushboolean (L, 1); | |
| 295 | lua_rawsetp (L, -2, getIdentityKey ()); | |
| 296 | lua_pushstring (L, name); | |
| 297 | rawsetfield (L, -2, "__type"); | |
| 298 | lua_pushcfunction (L, &indexMetaMethod); | |
| 299 | rawsetfield (L, -2, "__index"); | |
| 300 | lua_pushcfunction (L, &newindexMetaMethod); | |
| 301 | rawsetfield (L, -2, "__newindex"); | |
| 302 | lua_newtable (L); | |
| 303 | rawsetfield (L, -2, "__propget"); | |
| 304 | lua_newtable (L); | |
| 305 | rawsetfield (L, -2, "__propset"); | |
| 306 | ||
| 307 | lua_pushvalue (L, -2); | |
| 308 | rawsetfield (L, -2, "__const"); // point to const table | |
| 309 | ||
| 310 | lua_pushvalue (L, -1); | |
| 311 | rawsetfield (L, -3, "__class"); // point const table to class table | |
| 312 | ||
| 313 | if (Security::hideMetatables ()) | |
| 314 | { | |
| 315 | lua_pushnil (L); | |
| 316 | rawsetfield (L, -2, "__metatable"); | |
| 317 | } | |
| 318 | } | |
| 319 | ||
| 320 | //-------------------------------------------------------------------------- | |
| 321 | /** | |
| 322 | Create the static table. | |
| 323 | ||
| 324 | The Lua stack should have: | |
| 325 | -1 class table | |
| 326 | -2 const table | |
| 327 | -3 enclosing namespace | |
| 328 | */ | |
| 329 | void createStaticTable (char const* name) | |
| 330 | { | |
| 331 | lua_newtable (L); | |
| 332 | lua_newtable (L); | |
| 333 | lua_pushvalue (L, -1); | |
| 334 | lua_setmetatable (L, -3); | |
| 335 | lua_insert (L, -2); | |
| 336 | rawsetfield (L, -5, name); | |
| 337 | ||
| 338 | #if 0 | |
| 339 | lua_pushlightuserdata (L, this); | |
| 340 | lua_pushcclosure (L, &tostringMetaMethod, 1); | |
| 341 | rawsetfield (L, -2, "__tostring"); | |
| 342 | #endif | |
| 343 | lua_pushcfunction (L, &CFunc::indexMetaMethod); | |
| 344 | rawsetfield (L, -2, "__index"); | |
| 345 | lua_pushcfunction (L, &CFunc::newindexMetaMethod); | |
| 346 | rawsetfield (L, -2, "__newindex"); | |
| 347 | lua_newtable (L); | |
| 348 | rawsetfield (L, -2, "__propget"); | |
| 349 | lua_newtable (L); | |
| 350 | rawsetfield (L, -2, "__propset"); | |
| 351 | ||
| 352 | lua_pushvalue (L, -2); | |
| 353 | rawsetfield (L, -2, "__class"); // point to class table | |
| 354 | ||
| 355 | if (Security::hideMetatables ()) | |
| 356 | { | |
| 357 | lua_pushnil (L); | |
| 358 | rawsetfield (L, -2, "__metatable"); | |
| 359 | } | |
| 360 | } | |
| 361 | ||
| 362 | //========================================================================== | |
| 363 | /** | |
| 364 | lua_CFunction to construct a class object wrapped in a container. | |
| 365 | */ | |
| 366 | template <class Params, class C> | |
| 367 | static int ctorContainerProxy (lua_State* L) | |
| 368 | { | |
| 369 | typedef typename ContainerTraits <C>::Type T; | |
| 370 | ArgList <Params, 2> args (L); | |
| 371 | T* const p = Constructor <T, Params>::call (args); | |
| 372 | UserdataSharedHelper <C, false>::push (L, p); | |
| 373 | return 1; | |
| 374 | } | |
| 375 | ||
| 376 | //-------------------------------------------------------------------------- | |
| 377 | /** | |
| 378 | lua_CFunction to construct a class object in-place in the userdata. | |
| 379 | */ | |
| 380 | template <class Params, class T> | |
| 381 | static int ctorPlacementProxy (lua_State* L) | |
| 382 | { | |
| 383 | ArgList <Params, 2> args (L); | |
| 384 | Constructor <T, Params>::call (UserdataValue <T>::place (L), args); | |
| 385 | return 1; | |
| 386 | } | |
| 387 | ||
| 388 | //-------------------------------------------------------------------------- | |
| 389 | /** | |
| 390 | Pop the Lua stack. | |
| 391 | */ | |
| 392 | void pop (int n) const | |
| 393 | { | |
| 394 | if (m_stackSize >= n && lua_gettop (L) >= n) | |
| 395 | { | |
| 396 | lua_pop (L, n); | |
| 397 | m_stackSize -= n; | |
| 398 | } | |
| 399 | else | |
| 400 | { | |
| 401 | throw std::logic_error ("invalid stack"); | |
| 402 | } | |
| 403 | } | |
| 404 | ||
| 405 | public: | |
| 406 | //-------------------------------------------------------------------------- | |
| 407 | explicit ClassBase (lua_State* L_) | |
| 408 | : L (L_) | |
| 409 | , m_stackSize (0) | |
| 410 | { | |
| 411 | } | |
| 412 | ||
| 413 | //-------------------------------------------------------------------------- | |
| 414 | /** | |
| 415 | Copy Constructor. | |
| 416 | */ | |
| 417 | ClassBase (ClassBase const& other) | |
| 418 | : L (other.L) | |
| 419 | , m_stackSize (0) | |
| 420 | { | |
| 421 | m_stackSize = other.m_stackSize; | |
| 422 | other.m_stackSize = 0; | |
| 423 | } | |
| 424 | ||
| 425 | ~ClassBase () | |
| 426 | { | |
| 427 | pop (m_stackSize); | |
| 428 | } | |
| 429 | }; | |
| 430 | ||
| 431 | //============================================================================ | |
| 432 | // | |
| 433 | // Class | |
| 434 | // | |
| 435 | //============================================================================ | |
| 436 | /** | |
| 437 | Provides a class registration in a lua_State. | |
| 438 | ||
| 439 | After contstruction the Lua stack holds these objects: | |
| 440 | -1 static table | |
| 441 | -2 class table | |
| 442 | -3 const table | |
| 443 | -4 (enclosing namespace) | |
| 444 | */ | |
| 445 | template <class T> | |
| 446 | class Class : public ClassBase | |
| 447 | { | |
| 448 | public: | |
| 449 | //========================================================================== | |
| 450 | /** | |
| 451 | Register a new class or add to an existing class registration. | |
| 452 | */ | |
| 453 | Class (char const* name, Namespace const* parent) : ClassBase (parent->L) | |
| 454 | { | |
| 455 | m_stackSize = parent->m_stackSize + 3; | |
| 456 | parent->m_stackSize = 0; | |
| 457 | ||
| 458 | assert (lua_istable (L, -1)); | |
| 459 | rawgetfield (L, -1, name); | |
| 460 | ||
| 461 | if (lua_isnil (L, -1)) | |
| 462 | { | |
| 463 | lua_pop (L, 1); | |
| 464 | ||
| 465 | createConstTable (name); | |
| 466 | lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); | |
| 467 | rawsetfield (L, -2, "__gc"); | |
| 468 | ||
| 469 | createClassTable (name); | |
| 470 | lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); | |
| 471 | rawsetfield (L, -2, "__gc"); | |
| 472 | ||
| 473 | createStaticTable (name); | |
| 474 | ||
| 475 | // Map T back to its tables. | |
| 476 | lua_pushvalue (L, -1); | |
| 477 | lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); | |
| 478 | lua_pushvalue (L, -2); | |
| 479 | lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); | |
| 480 | lua_pushvalue (L, -3); | |
| 481 | lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); | |
| 482 | } | |
| 483 | else | |
| 484 | { | |
| 485 | rawgetfield (L, -1, "__class"); | |
| 486 | rawgetfield (L, -1, "__const"); | |
| 487 | ||
| 488 | // Reverse the top 3 stack elements | |
| 489 | lua_insert (L, -3); | |
| 490 | lua_insert (L, -2); | |
| 491 | } | |
| 492 | } | |
| 493 | ||
| 494 | //========================================================================== | |
| 495 | /** | |
| 496 | Derive a new class. | |
| 497 | */ | |
| 498 | Class (char const* name, Namespace const* parent, void const* const staticKey) | |
| 499 | : ClassBase (parent->L) | |
| 500 | { | |
| 501 | m_stackSize = parent->m_stackSize + 3; | |
| 502 | parent->m_stackSize = 0; | |
| 503 | ||
| 504 | assert (lua_istable (L, -1)); | |
| 505 | ||
| 506 | createConstTable (name); | |
| 507 | lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); | |
| 508 | rawsetfield (L, -2, "__gc"); | |
| 509 | ||
| 510 | createClassTable (name); | |
| 511 | lua_pushcfunction (L, &CFunc::gcMetaMethod <T>); | |
| 512 | rawsetfield (L, -2, "__gc"); | |
| 513 | ||
| 514 | createStaticTable (name); | |
| 515 | ||
| 516 | lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey); | |
| 517 | assert (lua_istable (L, -1)); | |
| 518 | rawgetfield (L, -1, "__class"); | |
| 519 | assert (lua_istable (L, -1)); | |
| 520 | rawgetfield (L, -1, "__const"); | |
| 521 | assert (lua_istable (L, -1)); | |
| 522 | ||
| 523 | rawsetfield (L, -6, "__parent"); | |
| 524 | rawsetfield (L, -4, "__parent"); | |
| 525 | rawsetfield (L, -2, "__parent"); | |
| 526 | ||
| 527 | lua_pushvalue (L, -1); | |
| 528 | lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getStaticKey ()); | |
| 529 | lua_pushvalue (L, -2); | |
| 530 | lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getClassKey ()); | |
| 531 | lua_pushvalue (L, -3); | |
| 532 | lua_rawsetp (L, LUA_REGISTRYINDEX, ClassInfo <T>::getConstKey ()); | |
| 533 | } | |
| 534 | ||
| 535 | //-------------------------------------------------------------------------- | |
| 536 | /** | |
| 537 | Continue registration in the enclosing namespace. | |
| 538 | */ | |
| 539 | Namespace endClass () | |
| 540 | { | |
| 541 | return Namespace (this); | |
| 542 | } | |
| 543 | ||
| 544 | //-------------------------------------------------------------------------- | |
| 545 | /** | |
| 546 | Add or replace a static data member. | |
| 547 | */ | |
| 548 | template <class U> | |
| 549 | Class <T>& addStaticData (char const* name, U* pu, bool isWritable = true) | |
| 550 | { | |
| 551 | assert (lua_istable (L, -1)); | |
| 552 | ||
| 553 | rawgetfield (L, -1, "__propget"); | |
| 554 | assert (lua_istable (L, -1)); | |
| 555 | lua_pushlightuserdata (L, pu); | |
| 556 | lua_pushcclosure (L, &CFunc::getVariable <U>, 1); | |
| 557 | rawsetfield (L, -2, name); | |
| 558 | lua_pop (L, 1); | |
| 559 | ||
| 560 | rawgetfield (L, -1, "__propset"); | |
| 561 | assert (lua_istable (L, -1)); | |
| 562 | if (isWritable) | |
| 563 | { | |
| 564 | lua_pushlightuserdata (L, pu); | |
| 565 | lua_pushcclosure (L, &CFunc::setVariable <U>, 1); | |
| 566 | } | |
| 567 | else | |
| 568 | { | |
| 569 | lua_pushstring (L, name); | |
| 570 | lua_pushcclosure (L, &CFunc::readOnlyError, 1); | |
| 571 | } | |
| 572 | rawsetfield (L, -2, name); | |
| 573 | lua_pop (L, 1); | |
| 574 | ||
| 575 | return *this; | |
| 576 | } | |
| 577 | ||
| 578 | //-------------------------------------------------------------------------- | |
| 579 | /** | |
| 580 | Add or replace a static property member. | |
| 581 | ||
| 582 | If the set function is null, the property is read-only. | |
| 583 | */ | |
| 584 | template <class U> | |
| 585 | Class <T>& addStaticProperty (char const* name, U (*get)(), void (*set)(U) = 0) | |
| 586 | { | |
| 587 | typedef U (*get_t)(); | |
| 588 | typedef void (*set_t)(U); | |
| 589 | ||
| 590 | assert (lua_istable (L, -1)); | |
| 591 | ||
| 592 | rawgetfield (L, -1, "__propget"); | |
| 593 | assert (lua_istable (L, -1)); | |
| 594 | new (lua_newuserdata (L, sizeof (get))) get_t (get); | |
| 595 | lua_pushcclosure (L, &CFunc::Call <U (*) (void)>::f, 1); | |
| 596 | rawsetfield (L, -2, name); | |
| 597 | lua_pop (L, 1); | |
| 598 | ||
| 599 | rawgetfield (L, -1, "__propset"); | |
| 600 | assert (lua_istable (L, -1)); | |
| 601 | if (set != 0) | |
| 602 | { | |
| 603 | new (lua_newuserdata (L, sizeof (set))) set_t (set); | |
| 604 | lua_pushcclosure (L, &CFunc::Call <void (*) (U)>::f, 1); | |
| 605 | } | |
| 606 | else | |
| 607 | { | |
| 608 | lua_pushstring (L, name); | |
| 609 | lua_pushcclosure (L, &CFunc::readOnlyError, 1); | |
| 610 | } | |
| 611 | rawsetfield (L, -2, name); | |
| 612 | lua_pop (L, 1); | |
| 613 | ||
| 614 | return *this; | |
| 615 | } | |
| 616 | ||
| 617 | //-------------------------------------------------------------------------- | |
| 618 | /** | |
| 619 | Add or replace a static member function. | |
| 620 | */ | |
| 621 | template <class FP> | |
| 622 | Class <T>& addStaticFunction (char const* name, FP const fp) | |
| 623 | { | |
| 624 | new (lua_newuserdata (L, sizeof (fp))) FP (fp); | |
| 625 | lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); | |
| 626 | rawsetfield (L, -2, name); | |
| 627 | ||
| 628 | return *this; | |
| 629 | } | |
| 630 | ||
| 631 | //-------------------------------------------------------------------------- | |
| 632 | /** | |
| 633 | Add or replace a lua_CFunction. | |
| 634 | */ | |
| 635 | Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*)) | |
| 636 | { | |
| 637 | lua_pushcfunction (L, fp); | |
| 638 | rawsetfield (L, -2, name); | |
| 639 | return *this; | |
| 640 | } | |
| 641 | ||
| 642 | //-------------------------------------------------------------------------- | |
| 643 | /** | |
| 644 | Add or replace a data member. | |
| 645 | */ | |
| 646 | template <class U> | |
| 647 | Class <T>& addData (char const* name, const U T::* mp, bool isWritable = true) | |
| 648 | { | |
| 649 | typedef const U T::*mp_t; | |
| 650 | ||
| 651 | // Add to __propget in class and const tables. | |
| 652 | { | |
| 653 | rawgetfield (L, -2, "__propget"); | |
| 654 | rawgetfield (L, -4, "__propget"); | |
| 655 | new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); | |
| 656 | lua_pushcclosure (L, &CFunc::getProperty <T,U>, 1); | |
| 657 | lua_pushvalue (L, -1); | |
| 658 | rawsetfield (L, -4, name); | |
| 659 | rawsetfield (L, -2, name); | |
| 660 | lua_pop (L, 2); | |
| 661 | } | |
| 662 | ||
| 663 | if (isWritable) | |
| 664 | { | |
| 665 | // Add to __propset in class table. | |
| 666 | rawgetfield (L, -2, "__propset"); | |
| 667 | assert (lua_istable (L, -1)); | |
| 668 | new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); | |
| 669 | lua_pushcclosure (L, &CFunc::setProperty <T,U>, 1); | |
| 670 | rawsetfield (L, -2, name); | |
| 671 | lua_pop (L, 1); | |
| 672 | } | |
| 673 | ||
| 674 | return *this; | |
| 675 | } | |
| 676 | ||
| 677 | //-------------------------------------------------------------------------- | |
| 678 | /** | |
| 679 | Add or replace a property member. | |
| 680 | */ | |
| 681 | template <class TG, class TS> | |
| 682 | Class <T>& addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS)) | |
| 683 | { | |
| 684 | // Add to __propget in class and const tables. | |
| 685 | { | |
| 686 | rawgetfield (L, -2, "__propget"); | |
| 687 | rawgetfield (L, -4, "__propget"); | |
| 688 | typedef TG (T::*get_t) () const; | |
| 689 | new (lua_newuserdata (L, sizeof (get_t))) get_t (get); | |
| 690 | lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); | |
| 691 | lua_pushvalue (L, -1); | |
| 692 | rawsetfield (L, -4, name); | |
| 693 | rawsetfield (L, -2, name); | |
| 694 | lua_pop (L, 2); | |
| 695 | } | |
| 696 | ||
| 697 | { | |
| 698 | // Add to __propset in class table. | |
| 699 | rawgetfield (L, -2, "__propset"); | |
| 700 | assert (lua_istable (L, -1)); | |
| 701 | typedef void (T::* set_t) (TS); | |
| 702 | new (lua_newuserdata (L, sizeof (set_t))) set_t (set); | |
| 703 | lua_pushcclosure (L, &CFunc::CallMember <set_t>::f, 1); | |
| 704 | rawsetfield (L, -2, name); | |
| 705 | lua_pop (L, 1); | |
| 706 | } | |
| 707 | ||
| 708 | return *this; | |
| 709 | } | |
| 710 | ||
| 711 | // read-only | |
| 712 | template <class TG> | |
| 713 | Class <T>& addProperty (char const* name, TG (T::* get) () const) | |
| 714 | { | |
| 715 | // Add to __propget in class and const tables. | |
| 716 | rawgetfield (L, -2, "__propget"); | |
| 717 | rawgetfield (L, -4, "__propget"); | |
| 718 | typedef TG (T::*get_t) () const; | |
| 719 | new (lua_newuserdata (L, sizeof (get_t))) get_t (get); | |
| 720 | lua_pushcclosure (L, &CFunc::CallConstMember <get_t>::f, 1); | |
| 721 | lua_pushvalue (L, -1); | |
| 722 | rawsetfield (L, -4, name); | |
| 723 | rawsetfield (L, -2, name); | |
| 724 | lua_pop (L, 2); | |
| 725 | ||
| 726 | return *this; | |
| 727 | } | |
| 728 | ||
| 729 | //-------------------------------------------------------------------------- | |
| 730 | /** | |
| 731 | Add or replace a property member, by proxy. | |
| 732 | ||
| 733 | When a class is closed for modification and does not provide (or cannot | |
| 734 | provide) the function signatures necessary to implement get or set for | |
| 735 | a property, this will allow non-member functions act as proxies. | |
| 736 | ||
| 737 | Both the get and the set functions require a T const* and T* in the first | |
| 738 | argument respectively. | |
| 739 | */ | |
| 740 | template <class TG, class TS> | |
| 741 | Class <T>& addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS)) | |
| 742 | { | |
| 743 | // Add to __propget in class and const tables. | |
| 744 | { | |
| 745 | rawgetfield (L, -2, "__propget"); | |
| 746 | rawgetfield (L, -4, "__propget"); | |
| 747 | typedef TG (*get_t) (T const*); | |
| 748 | new (lua_newuserdata (L, sizeof (get_t))) get_t (get); | |
| 749 | lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1); | |
| 750 | lua_pushvalue (L, -1); | |
| 751 | rawsetfield (L, -4, name); | |
| 752 | rawsetfield (L, -2, name); | |
| 753 | lua_pop (L, 2); | |
| 754 | } | |
| 755 | ||
| 756 | if (set != 0) | |
| 757 | { | |
| 758 | // Add to __propset in class table. | |
| 759 | rawgetfield (L, -2, "__propset"); | |
| 760 | assert (lua_istable (L, -1)); | |
| 761 | typedef void (*set_t) (T*, TS); | |
| 762 | new (lua_newuserdata (L, sizeof (set_t))) set_t (set); | |
| 763 | lua_pushcclosure (L, &CFunc::Call <set_t>::f, 1); | |
| 764 | rawsetfield (L, -2, name); | |
| 765 | lua_pop (L, 1); | |
| 766 | } | |
| 767 | ||
| 768 | return *this; | |
| 769 | } | |
| 770 | ||
| 771 | // read-only | |
| 772 | template <class TG, class TS> | |
| 773 | Class <T>& addProperty (char const* name, TG (*get) (T const*)) | |
| 774 | { | |
| 775 | // Add to __propget in class and const tables. | |
| 776 | rawgetfield (L, -2, "__propget"); | |
| 777 | rawgetfield (L, -4, "__propget"); | |
| 778 | typedef TG (*get_t) (T const*); | |
| 779 | new (lua_newuserdata (L, sizeof (get_t))) get_t (get); | |
| 780 | lua_pushcclosure (L, &CFunc::Call <get_t>::f, 1); | |
| 781 | lua_pushvalue (L, -1); | |
| 782 | rawsetfield (L, -4, name); | |
| 783 | rawsetfield (L, -2, name); | |
| 784 | lua_pop (L, 2); | |
| 785 | ||
| 786 | return *this; | |
| 787 | } | |
| 788 | ||
| 789 | //-------------------------------------------------------------------------- | |
| 790 | /** | |
| 791 | Add or replace a member function. | |
| 792 | */ | |
| 793 | template <class MemFn> | |
| 794 | Class <T>& addFunction (char const* name, MemFn mf) | |
| 795 | { | |
| 796 | CFunc::CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf); | |
| 797 | return *this; | |
| 798 | } | |
| 799 | ||
| 800 | //-------------------------------------------------------------------------- | |
| 801 | /** | |
| 802 | Add or replace a member lua_CFunction. | |
| 803 | */ | |
| 804 | Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*)) | |
| 805 | { | |
| 806 | typedef int (T::*MFP)(lua_State*); | |
| 807 | assert (lua_istable (L, -1)); | |
| 808 | new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); | |
| 809 | lua_pushcclosure (L, &CFunc::CallMemberCFunction <T>::f, 1); | |
| 810 | rawsetfield (L, -3, name); // class table | |
| 811 | ||
| 812 | return *this; | |
| 813 | } | |
| 814 | ||
| 815 | //-------------------------------------------------------------------------- | |
| 816 | /** | |
| 817 | Add or replace a const member lua_CFunction. | |
| 818 | */ | |
| 819 | Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const) | |
| 820 | { | |
| 821 | typedef int (T::*MFP)(lua_State*) const; | |
| 822 | assert (lua_istable (L, -1)); | |
| 823 | new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); | |
| 824 | lua_pushcclosure (L, &CFunc::CallConstMemberCFunction <T>::f, 1); | |
| 825 | lua_pushvalue (L, -1); | |
| 826 | rawsetfield (L, -5, name); // const table | |
| 827 | rawsetfield (L, -3, name); // class table | |
| 828 | ||
| 829 | return *this; | |
| 830 | } | |
| 831 | ||
| 832 | //-------------------------------------------------------------------------- | |
| 833 | /** | |
| 834 | Add or replace a primary Constructor. | |
| 835 | ||
| 836 | The primary Constructor is invoked when calling the class type table | |
| 837 | like a function. | |
| 838 | ||
| 839 | The template parameter should be a function pointer type that matches | |
| 840 | the desired Constructor (since you can't take the address of a Constructor | |
| 841 | and pass it as an argument). | |
| 842 | */ | |
| 843 | template <class MemFn, class C> | |
| 844 | Class <T>& addConstructor () | |
| 845 | { | |
| 846 | lua_pushcclosure (L, | |
| 847 | &ctorContainerProxy <typename FuncTraits <MemFn>::Params, C>, 0); | |
| 848 | rawsetfield(L, -2, "__call"); | |
| 849 | ||
| 850 | return *this; | |
| 851 | } | |
| 852 | ||
| 853 | template <class MemFn> | |
| 854 | Class <T>& addConstructor () | |
| 855 | { | |
| 856 | lua_pushcclosure (L, | |
| 857 | &ctorPlacementProxy <typename FuncTraits <MemFn>::Params, T>, 0); | |
| 858 | rawsetfield(L, -2, "__call"); | |
| 859 | ||
| 860 | return *this; | |
| 861 | } | |
| 862 | }; | |
| 863 | ||
| 864 | private: | |
| 865 | //---------------------------------------------------------------------------- | |
| 866 | /** | |
| 867 | Open the global namespace for registrations. | |
| 868 | */ | |
| 869 | explicit Namespace (lua_State* L_) | |
| 870 | : L (L_) | |
| 871 | , m_stackSize (0) | |
| 872 | { | |
| 873 | lua_getglobal (L, "_G"); | |
| 874 | ++m_stackSize; | |
| 875 | } | |
| 876 | ||
| 877 | //---------------------------------------------------------------------------- | |
| 878 | /** | |
| 879 | Open a namespace for registrations. | |
| 880 | ||
| 881 | The namespace is created if it doesn't already exist. | |
| 882 | The parent namespace is at the top of the Lua stack. | |
| 883 | */ | |
| 884 | Namespace (char const* name, Namespace const* parent) | |
| 885 | : L (parent->L) | |
| 886 | , m_stackSize (0) | |
| 887 | { | |
| 888 | m_stackSize = parent->m_stackSize + 1; | |
| 889 | parent->m_stackSize = 0; | |
| 890 | ||
| 891 | assert (lua_istable (L, -1)); | |
| 892 | rawgetfield (L, -1, name); | |
| 893 | if (lua_isnil (L, -1)) | |
| 894 | { | |
| 895 | lua_pop (L, 1); | |
| 896 | ||
| 897 | lua_newtable (L); | |
| 898 | lua_pushvalue (L, -1); | |
| 899 | lua_setmetatable (L, -2); | |
| 900 | lua_pushcfunction (L, &CFunc::indexMetaMethod); | |
| 901 | rawsetfield (L, -2, "__index"); | |
| 902 | lua_pushcfunction (L, &CFunc::newindexMetaMethod); | |
| 903 | rawsetfield (L, -2, "__newindex"); | |
| 904 | lua_newtable (L); | |
| 905 | rawsetfield (L, -2, "__propget"); | |
| 906 | lua_newtable (L); | |
| 907 | rawsetfield (L, -2, "__propset"); | |
| 908 | lua_pushvalue (L, -1); | |
| 909 | rawsetfield (L, -3, name); | |
| 910 | #if 0 | |
| 911 | lua_pushcfunction (L, &tostringMetaMethod); | |
| 912 | rawsetfield (L, -2, "__tostring"); | |
| 913 | #endif | |
| 914 | } | |
| 915 | } | |
| 916 | ||
| 917 | //---------------------------------------------------------------------------- | |
| 918 | /** | |
| 919 | Creates a continued registration from a child namespace. | |
| 920 | */ | |
| 921 | explicit Namespace (Namespace const* child) | |
| 922 | : L (child->L) | |
| 923 | , m_stackSize (0) | |
| 924 | { | |
| 925 | m_stackSize = child->m_stackSize - 1; | |
| 926 | child->m_stackSize = 1; | |
| 927 | child->pop (1); | |
| 928 | ||
| 929 | // It is not necessary or valid to call | |
| 930 | // endNamespace() for the global namespace! | |
| 931 | // | |
| 932 | assert (m_stackSize != 0); | |
| 933 | } | |
| 934 | ||
| 935 | //---------------------------------------------------------------------------- | |
| 936 | /** | |
| 937 | Creates a continued registration from a child class. | |
| 938 | */ | |
| 939 | explicit Namespace (ClassBase const* child) | |
| 940 | : L (child->L) | |
| 941 | , m_stackSize (0) | |
| 942 | { | |
| 943 | m_stackSize = child->m_stackSize - 3; | |
| 944 | child->m_stackSize = 3; | |
| 945 | child->pop (3); | |
| 946 | } | |
| 947 | ||
| 948 | public: | |
| 949 | //---------------------------------------------------------------------------- | |
| 950 | /** | |
| 951 | Copy Constructor. | |
| 952 | ||
| 953 | Ownership of the stack is transferred to the new object. This happens | |
| 954 | when the compiler emits temporaries to hold these objects while chaining | |
| 955 | registrations across namespaces. | |
| 956 | */ | |
| 957 | Namespace (Namespace const& other) : L (other.L) | |
| 958 | { | |
| 959 | m_stackSize = other.m_stackSize; | |
| 960 | other.m_stackSize = 0; | |
| 961 | } | |
| 962 | ||
| 963 | //---------------------------------------------------------------------------- | |
| 964 | /** | |
| 965 | Closes this namespace registration. | |
| 966 | */ | |
| 967 | ~Namespace () | |
| 968 | { | |
| 969 | pop (m_stackSize); | |
| 970 | } | |
| 971 | ||
| 972 | //---------------------------------------------------------------------------- | |
| 973 | /** | |
| 974 | Open the global namespace. | |
| 975 | */ | |
| 976 | static Namespace getGlobalNamespace (lua_State* L) | |
| 977 | { | |
| 978 | return Namespace (L); | |
| 979 | } | |
| 980 | ||
| 981 | //---------------------------------------------------------------------------- | |
| 982 | /** | |
| 983 | Open a new or existing namespace for registrations. | |
| 984 | */ | |
| 985 | Namespace beginNamespace (char const* name) | |
| 986 | { | |
| 987 | return Namespace (name, this); | |
| 988 | } | |
| 989 | ||
| 990 | //---------------------------------------------------------------------------- | |
| 991 | /** | |
| 992 | Continue namespace registration in the parent. | |
| 993 | ||
| 994 | Do not use this on the global namespace. | |
| 995 | */ | |
| 996 | Namespace endNamespace () | |
| 997 | { | |
| 998 | return Namespace (this); | |
| 999 | } | |
| 1000 | ||
| 1001 | //---------------------------------------------------------------------------- | |
| 1002 | /** | |
| 1003 | Add or replace a variable. | |
| 1004 | */ | |
| 1005 | template <class T> | |
| 1006 | Namespace& addVariable (char const* name, T* pt, bool isWritable = true) | |
| 1007 | { | |
| 1008 | assert (lua_istable (L, -1)); | |
| 1009 | ||
| 1010 | rawgetfield (L, -1, "__propget"); | |
| 1011 | assert (lua_istable (L, -1)); | |
| 1012 | lua_pushlightuserdata (L, pt); | |
| 1013 | lua_pushcclosure (L, &CFunc::getVariable <T>, 1); | |
| 1014 | rawsetfield (L, -2, name); | |
| 1015 | lua_pop (L, 1); | |
| 1016 | ||
| 1017 | rawgetfield (L, -1, "__propset"); | |
| 1018 | assert (lua_istable (L, -1)); | |
| 1019 | if (isWritable) | |
| 1020 | { | |
| 1021 | lua_pushlightuserdata (L, pt); | |
| 1022 | lua_pushcclosure (L, &CFunc::setVariable <T>, 1); | |
| 1023 | } | |
| 1024 | else | |
| 1025 | { | |
| 1026 | lua_pushstring (L, name); | |
| 1027 | lua_pushcclosure (L, &CFunc::readOnlyError, 1); | |
| 1028 | } | |
| 1029 | rawsetfield (L, -2, name); | |
| 1030 | lua_pop (L, 1); | |
| 1031 | ||
| 1032 | return *this; | |
| 1033 | } | |
| 1034 | ||
| 1035 | //---------------------------------------------------------------------------- | |
| 1036 | /** | |
| 1037 | Add or replace a property. | |
| 1038 | ||
| 1039 | If the set function is omitted or null, the property is read-only. | |
| 1040 | */ | |
| 1041 | template <class TG, class TS> | |
| 1042 | Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0) | |
| 1043 | { | |
| 1044 | assert (lua_istable (L, -1)); | |
| 1045 | ||
| 1046 | rawgetfield (L, -1, "__propget"); | |
| 1047 | assert (lua_istable (L, -1)); | |
| 1048 | typedef TG (*get_t) (); | |
| 1049 | new (lua_newuserdata (L, sizeof (get_t))) get_t (get); | |
| 1050 | lua_pushcclosure (L, &CFunc::Call <TG (*) (void)>::f, 1); | |
| 1051 | rawsetfield (L, -2, name); | |
| 1052 | lua_pop (L, 1); | |
| 1053 | ||
| 1054 | rawgetfield (L, -1, "__propset"); | |
| 1055 | assert (lua_istable (L, -1)); | |
| 1056 | if (set != 0) | |
| 1057 | { | |
| 1058 | typedef void (*set_t) (TS); | |
| 1059 | new (lua_newuserdata (L, sizeof (set_t))) set_t (set); | |
| 1060 | lua_pushcclosure (L, &CFunc::Call <void (*) (TS)>::f, 1); | |
| 1061 | } | |
| 1062 | else | |
| 1063 | { | |
| 1064 | lua_pushstring (L, name); | |
| 1065 | lua_pushcclosure (L, &CFunc::readOnlyError, 1); | |
| 1066 | } | |
| 1067 | rawsetfield (L, -2, name); | |
| 1068 | lua_pop (L, 1); | |
| 1069 | ||
| 1070 | return *this; | |
| 1071 | } | |
| 1072 | ||
| 1073 | //---------------------------------------------------------------------------- | |
| 1074 | /** | |
| 1075 | Add or replace a free function. | |
| 1076 | */ | |
| 1077 | template <class FP> | |
| 1078 | Namespace& addFunction (char const* name, FP const fp) | |
| 1079 | { | |
| 1080 | assert (lua_istable (L, -1)); | |
| 1081 | ||
| 1082 | new (lua_newuserdata (L, sizeof (fp))) FP (fp); | |
| 1083 | lua_pushcclosure (L, &CFunc::Call <FP>::f, 1); | |
| 1084 | rawsetfield (L, -2, name); | |
| 1085 | ||
| 1086 | return *this; | |
| 1087 | } | |
| 1088 | ||
| 1089 | //---------------------------------------------------------------------------- | |
| 1090 | /** | |
| 1091 | Add or replace a lua_CFunction. | |
| 1092 | */ | |
| 1093 | Namespace& addCFunction (char const* name, int (*const fp)(lua_State*)) | |
| 1094 | { | |
| 1095 | lua_pushcfunction (L, fp); | |
| 1096 | rawsetfield (L, -2, name); | |
| 1097 | ||
| 1098 | return *this; | |
| 1099 | } | |
| 1100 | ||
| 1101 | //---------------------------------------------------------------------------- | |
| 1102 | /** | |
| 1103 | Open a new or existing class for registrations. | |
| 1104 | */ | |
| 1105 | template <class T> | |
| 1106 | Class <T> beginClass (char const* name) | |
| 1107 | { | |
| 1108 | return Class <T> (name, this); | |
| 1109 | } | |
| 1110 | ||
| 1111 | //---------------------------------------------------------------------------- | |
| 1112 | /** | |
| 1113 | Derive a new class for registrations. | |
| 1114 | ||
| 1115 | To continue registrations for the class later, use beginClass(). | |
| 1116 | Do not call deriveClass() again. | |
| 1117 | */ | |
| 1118 | template <class T, class U> | |
| 1119 | Class <T> deriveClass (char const* name) | |
| 1120 | { | |
| 1121 | return Class <T> (name, this, ClassInfo <U>::getStaticKey ()); | |
| 1122 | } | |
| 1123 | }; | |
| 1124 | ||
| 1125 | //------------------------------------------------------------------------------ | |
| 1126 | /** | |
| 1127 | Retrieve the global namespace. | |
| 1128 | ||
| 1129 | It is recommended to put your namespace inside the global namespace, and | |
| 1130 | then add your classes and functions to it, rather than adding many classes | |
| 1131 | and functions directly to the global namespace. | |
| 1132 | */ | |
| 1133 | inline Namespace getGlobalNamespace (lua_State* L) | |
| 1134 | { | |
| 1135 | return Namespace::getGlobalNamespace (L); | |
| 1136 | } |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2007, Nathan Reed | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | ||
| 28 | This file incorporates work covered by the following copyright and | |
| 29 | permission notice: | |
| 30 | ||
| 31 | The Loki Library | |
| 32 | Copyright (c) 2001 by Andrei Alexandrescu | |
| 33 | This code accompanies the book: | |
| 34 | Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design | |
| 35 | Patterns Applied". Copyright (c) 2001. Addison-Wesley. | |
| 36 | Permission to use, copy, modify, distribute and sell this software for any | |
| 37 | purpose is hereby granted without fee, provided that the above copyright | |
| 38 | notice appear in all copies and that both that copyright notice and this | |
| 39 | permission notice appear in supporting documentation. | |
| 40 | The author or Addison-Welsey Longman make no representations about the | |
| 41 | suitability of this software for any purpose. It is provided "as is" | |
| 42 | without express or implied warranty. | |
| 43 | */ | |
| 44 | //============================================================================== | |
| 45 | ||
| 46 | /** | |
| 47 | None type means void parameters or return value. | |
| 48 | */ | |
| 49 | typedef void None; | |
| 50 | ||
| 51 | template <typename Head, typename Tail = None> | |
| 52 | struct TypeList | |
| 53 | { | |
| 54 | }; | |
| 55 | ||
| 56 | /** | |
| 57 | A TypeList with actual values. | |
| 58 | */ | |
| 59 | template <typename List> | |
| 60 | struct TypeListValues | |
| 61 | { | |
| 62 | static std::string const tostring (bool) | |
| 63 | { | |
| 64 | return ""; | |
| 65 | } | |
| 66 | }; | |
| 67 | ||
| 68 | /** | |
| 69 | TypeListValues recursive template definition. | |
| 70 | */ | |
| 71 | template <typename Head, typename Tail> | |
| 72 | struct TypeListValues <TypeList <Head, Tail> > | |
| 73 | { | |
| 74 | Head hd; | |
| 75 | TypeListValues <Tail> tl; | |
| 76 | ||
| 77 | TypeListValues (Head hd_, TypeListValues <Tail> const& tl_) | |
| 78 | : hd (hd_), tl (tl_) | |
| 79 | { | |
| 80 | } | |
| 81 | ||
| 82 | static std::string const tostring (bool comma = false) | |
| 83 | { | |
| 84 | std::string s; | |
| 85 | ||
| 86 | if (comma) | |
| 87 | s = ", "; | |
| 88 | ||
| 89 | s = s + typeid (Head).name (); | |
| 90 | ||
| 91 | return s + TypeListValues <Tail>::tostring (true); | |
| 92 | } | |
| 93 | }; | |
| 94 | ||
| 95 | // Specializations of type/value list for head types that are references and | |
| 96 | // const-references. We need to handle these specially since we can't count | |
| 97 | // on the referenced object hanging around for the lifetime of the list. | |
| 98 | ||
| 99 | template <typename Head, typename Tail> | |
| 100 | struct TypeListValues <TypeList <Head&, Tail> > | |
| 101 | { | |
| 102 | Head hd; | |
| 103 | TypeListValues <Tail> tl; | |
| 104 | ||
| 105 | TypeListValues (Head& hd_, TypeListValues <Tail> const& tl_) | |
| 106 | : hd (hd_), tl (tl_) | |
| 107 | { | |
| 108 | } | |
| 109 | ||
| 110 | static std::string const tostring (bool comma = false) | |
| 111 | { | |
| 112 | std::string s; | |
| 113 | ||
| 114 | if (comma) | |
| 115 | s = ", "; | |
| 116 | ||
| 117 | s = s + typeid (Head).name () + "&"; | |
| 118 | ||
| 119 | return s + TypeListValues <Tail>::tostring (true); | |
| 120 | } | |
| 121 | }; | |
| 122 | ||
| 123 | template <typename Head, typename Tail> | |
| 124 | struct TypeListValues <TypeList <Head const&, Tail> > | |
| 125 | { | |
| 126 | Head hd; | |
| 127 | TypeListValues <Tail> tl; | |
| 128 | ||
| 129 | TypeListValues (Head const& hd_, const TypeListValues <Tail>& tl_) | |
| 130 | : hd (hd_), tl (tl_) | |
| 131 | { | |
| 132 | } | |
| 133 | ||
| 134 | static std::string const tostring (bool comma = false) | |
| 135 | { | |
| 136 | std::string s; | |
| 137 | ||
| 138 | if (comma) | |
| 139 | s = ", "; | |
| 140 | ||
| 141 | s = s + typeid (Head).name () + " const&"; | |
| 142 | ||
| 143 | return s + TypeListValues <Tail>::tostring (true); | |
| 144 | } | |
| 145 | }; | |
| 146 | ||
| 147 | //============================================================================== | |
| 148 | /** | |
| 149 | Subclass of a TypeListValues constructable from the Lua stack. | |
| 150 | */ | |
| 151 | ||
| 152 | template <typename List, int Start = 1> | |
| 153 | struct ArgList | |
| 154 | { | |
| 155 | }; | |
| 156 | ||
| 157 | template <int Start> | |
| 158 | struct ArgList <None, Start> : public TypeListValues <None> | |
| 159 | { | |
| 160 | ArgList (lua_State*) | |
| 161 | { | |
| 162 | } | |
| 163 | }; | |
| 164 | ||
| 165 | template <typename Head, typename Tail, int Start> | |
| 166 | struct ArgList <TypeList <Head, Tail>, Start> | |
| 167 | : public TypeListValues <TypeList <Head, Tail> > | |
| 168 | { | |
| 169 | ArgList (lua_State* L) | |
| 170 | : TypeListValues <TypeList <Head, Tail> > (Stack <Head>::get (L, Start), | |
| 171 | ArgList <Tail, Start + 1> (L)) | |
| 172 | { | |
| 173 | } | |
| 174 | }; |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com> | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | //------------------------------------------------------------------------------ | |
| 31 | /** | |
| 32 | Type tag for representing LUA_TNIL. | |
| 33 | ||
| 34 | Construct one of these using `Nil()` to represent a Lua nil. This is faster | |
| 35 | than creating a reference in the registry to nil. Example: | |
| 36 | ||
| 37 | LuaRef t (LuaRef::createTable (L)); | |
| 38 | ... | |
| 39 | t ["k"] = Nil(); // assign nil | |
| 40 | */ | |
| 41 | struct Nil | |
| 42 | { | |
| 43 | }; | |
| 44 | ||
| 45 | //------------------------------------------------------------------------------ | |
| 46 | /** | |
| 47 | Lightweight reference to a Lua object. | |
| 48 | ||
| 49 | The reference is maintained for the lifetime of the C++ object. | |
| 50 | */ | |
| 51 | class LuaRef | |
| 52 | { | |
| 53 | private: | |
| 54 | class Proxy; | |
| 55 | friend struct Stack <Proxy>; | |
| 56 | ||
| 57 | //---------------------------------------------------------------------------- | |
| 58 | /** | |
| 59 | Pop the Lua stack. | |
| 60 | ||
| 61 | Pops the specified number of stack items on destruction. We use this | |
| 62 | when returning objects, to avoid an explicit temporary variable, since | |
| 63 | the destructor executes after the return statement. For example: | |
| 64 | ||
| 65 | template <class U> | |
| 66 | U cast (lua_State* L) | |
| 67 | { | |
| 68 | StackPop p (L, 1); | |
| 69 | ... | |
| 70 | return U (); // dtor called after this line | |
| 71 | } | |
| 72 | ||
| 73 | @note The `StackPop` object must always be a named local variable. | |
| 74 | */ | |
| 75 | class StackPop | |
| 76 | { | |
| 77 | public: | |
| 78 | /** Create a StackPop object. | |
| 79 | ||
| 80 | @param count The number of stack entries to pop on destruction. | |
| 81 | */ | |
| 82 | StackPop (lua_State* L, int count) | |
| 83 | : m_L (L) | |
| 84 | , m_count (count) | |
| 85 | { | |
| 86 | } | |
| 87 | ||
| 88 | ~StackPop () | |
| 89 | { | |
| 90 | lua_pop (m_L, m_count); | |
| 91 | } | |
| 92 | ||
| 93 | private: | |
| 94 | lua_State* m_L; | |
| 95 | int m_count; | |
| 96 | }; | |
| 97 | ||
| 98 | //---------------------------------------------------------------------------- | |
| 99 | /** | |
| 100 | A proxy for representing table values. | |
| 101 | */ | |
| 102 | class Proxy | |
| 103 | { | |
| 104 | private: | |
| 105 | lua_State* m_L; | |
| 106 | int m_tableRef; | |
| 107 | int m_keyRef; | |
| 108 | ||
| 109 | public: | |
| 110 | //-------------------------------------------------------------------------- | |
| 111 | /** | |
| 112 | Construct a Proxy from a table value. | |
| 113 | ||
| 114 | The table is in the registry, and the key is at the top of the stack. | |
| 115 | The key is popped off the stack. | |
| 116 | */ | |
| 117 | Proxy (lua_State* L, int tableRef) | |
| 118 | : m_L (L) | |
| 119 | , m_tableRef (tableRef) | |
| 120 | , m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX)) | |
| 121 | { | |
| 122 | } | |
| 123 | ||
| 124 | //-------------------------------------------------------------------------- | |
| 125 | /** | |
| 126 | Create a Proxy via copy constructor. | |
| 127 | ||
| 128 | It is best to avoid code paths that invoke this, because it creates | |
| 129 | an extra temporary Lua reference. Typically this is done by passing | |
| 130 | the Proxy parameter as a `const` reference. | |
| 131 | */ | |
| 132 | Proxy (Proxy const& other) | |
| 133 | : m_L (other.m_L) | |
| 134 | , m_tableRef (other.m_tableRef) | |
| 135 | { | |
| 136 | // If this assert goes off it means code is taking this path, | |
| 137 | // which is better avoided. | |
| 138 | // | |
| 139 | assert (0); | |
| 140 | ||
| 141 | lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef); | |
| 142 | m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 143 | } | |
| 144 | ||
| 145 | //-------------------------------------------------------------------------- | |
| 146 | /** | |
| 147 | Destroy the proxy. | |
| 148 | ||
| 149 | This does not destroy the table value. | |
| 150 | */ | |
| 151 | ~Proxy () | |
| 152 | { | |
| 153 | luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef); | |
| 154 | } | |
| 155 | ||
| 156 | //-------------------------------------------------------------------------- | |
| 157 | /** | |
| 158 | Return a reference to the table value. | |
| 159 | */ | |
| 160 | int createRef () const | |
| 161 | { | |
| 162 | push (m_L); | |
| 163 | return luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 164 | } | |
| 165 | ||
| 166 | //-------------------------------------------------------------------------- | |
| 167 | /** | |
| 168 | Assign a new value to this table key. | |
| 169 | ||
| 170 | This may invoke metamethods. | |
| 171 | */ | |
| 172 | template <class T> | |
| 173 | Proxy& operator= (T v) | |
| 174 | { | |
| 175 | StackPop p (m_L, 1); | |
| 176 | lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); | |
| 177 | lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); | |
| 178 | Stack <T>::push (m_L, v); | |
| 179 | lua_rawset (m_L, -3); | |
| 180 | return *this; | |
| 181 | } | |
| 182 | ||
| 183 | //-------------------------------------------------------------------------- | |
| 184 | /** | |
| 185 | Assign a new value to this table key. | |
| 186 | ||
| 187 | The assignment is raw, no metamethods are invoked. | |
| 188 | */ | |
| 189 | template <class T> | |
| 190 | Proxy& rawset (T v) | |
| 191 | { | |
| 192 | StackPop p (m_L, 1); | |
| 193 | lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); | |
| 194 | lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); | |
| 195 | Stack <T>::push (m_L, v); | |
| 196 | lua_settable (m_L, -3); | |
| 197 | return *this; | |
| 198 | } | |
| 199 | ||
| 200 | //========================================================================== | |
| 201 | // | |
| 202 | // This group of member functions mirrors the member functions in LuaRef. | |
| 203 | ||
| 204 | /** Retrieve the lua_State associated with the table value. | |
| 205 | */ | |
| 206 | lua_State* state () const | |
| 207 | { | |
| 208 | return m_L; | |
| 209 | } | |
| 210 | ||
| 211 | //-------------------------------------------------------------------------- | |
| 212 | /** | |
| 213 | Push the value onto the Lua stack. | |
| 214 | */ | |
| 215 | void push (lua_State* L) const | |
| 216 | { | |
| 217 | assert (equalstates (L, m_L)); | |
| 218 | lua_rawgeti (L, LUA_REGISTRYINDEX, m_tableRef); | |
| 219 | lua_rawgeti (L, LUA_REGISTRYINDEX, m_keyRef); | |
| 220 | lua_gettable (L, -2); | |
| 221 | lua_remove (L, -2); // remove the table | |
| 222 | } | |
| 223 | ||
| 224 | //-------------------------------------------------------------------------- | |
| 225 | /** | |
| 226 | Determine the object type. | |
| 227 | ||
| 228 | The return values are the same as for `lua_type`. | |
| 229 | */ | |
| 230 | int type () const | |
| 231 | { | |
| 232 | int result; | |
| 233 | push (m_L); | |
| 234 | result = lua_type (m_L, -1); | |
| 235 | lua_pop (m_L, 1); | |
| 236 | return result; | |
| 237 | } | |
| 238 | ||
| 239 | inline bool isNil () const { return type () == LUA_TNIL; } | |
| 240 | inline bool isNumber () const { return type () == LUA_TNUMBER; } | |
| 241 | inline bool isString () const { return type () == LUA_TSTRING; } | |
| 242 | inline bool isTable () const { return type () == LUA_TTABLE; } | |
| 243 | inline bool isFunction () const { return type () == LUA_TFUNCTION; } | |
| 244 | inline bool isUserdata () const { return type () == LUA_TUSERDATA; } | |
| 245 | inline bool isThread () const { return type () == LUA_TTHREAD; } | |
| 246 | inline bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; } | |
| 247 | ||
| 248 | //-------------------------------------------------------------------------- | |
| 249 | /** | |
| 250 | Perform an explicit conversion. | |
| 251 | */ | |
| 252 | template <class T> | |
| 253 | T cast () const | |
| 254 | { | |
| 255 | StackPop p (m_L, 1); | |
| 256 | push (m_L); | |
| 257 | ||
| 258 | // lua_gettop is used because Userdata::getClass() doesn't handle | |
| 259 | // negative stack indexes. | |
| 260 | // | |
| 261 | return Stack <T>::get (m_L, lua_gettop (m_L)); | |
| 262 | } | |
| 263 | ||
| 264 | //-------------------------------------------------------------------------- | |
| 265 | /** | |
| 266 | Universal implicit conversion operator. | |
| 267 | ||
| 268 | NOTE: Visual Studio 2010 and 2012 have a bug where this function | |
| 269 | is not used. See: | |
| 270 | ||
| 271 | http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014 | |
| 272 | https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile | |
| 273 | ||
| 274 | // This code snippet fails to compile in vs2010,vs2012 | |
| 275 | struct S { | |
| 276 | template <class T> inline operator T () const { return T (); } | |
| 277 | }; | |
| 278 | int main () { | |
| 279 | S () || false; | |
| 280 | return 0; | |
| 281 | } | |
| 282 | */ | |
| 283 | template <class T> | |
| 284 | inline operator T () const | |
| 285 | { | |
| 286 | return cast <T> (); | |
| 287 | } | |
| 288 | ||
| 289 | //-------------------------------------------------------------------------- | |
| 290 | /** | |
| 291 | Universal comparison operators. | |
| 292 | */ | |
| 293 | /** @{ */ | |
| 294 | template <class T> | |
| 295 | bool operator== (T rhs) const | |
| 296 | { | |
| 297 | StackPop p (m_L, 2); | |
| 298 | push (m_L); | |
| 299 | Stack <T>::push (m_L, rhs); | |
| 300 | return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; | |
| 301 | } | |
| 302 | ||
| 303 | template <class T> | |
| 304 | bool operator< (T rhs) const | |
| 305 | { | |
| 306 | StackPop p (m_L, 2); | |
| 307 | push (m_L); | |
| 308 | Stack <T>::push (m_L, rhs); | |
| 309 | return lua_compare (m_L, -2, -1, LUA_OPLT) == 1; | |
| 310 | } | |
| 311 | ||
| 312 | template <class T> | |
| 313 | bool operator<= (T rhs) const | |
| 314 | { | |
| 315 | StackPop p (m_L, 2); | |
| 316 | push (m_L); | |
| 317 | Stack <T>::push (m_L, rhs); | |
| 318 | return lua_compare (m_L, -2, -1, LUA_OPLE) == 1; | |
| 319 | } | |
| 320 | ||
| 321 | template <class T> | |
| 322 | bool operator> (T rhs) const | |
| 323 | { | |
| 324 | StackPop p (m_L, 2); | |
| 325 | push (m_L); | |
| 326 | Stack <T>::push (m_L, rhs); | |
| 327 | return lua_compare (m_L, -1, -2, LUA_OPLT) == 1; | |
| 328 | } | |
| 329 | ||
| 330 | template <class T> | |
| 331 | bool operator>= (T rhs) const | |
| 332 | { | |
| 333 | StackPop p (m_L, 2); | |
| 334 | push (m_L); | |
| 335 | Stack <T>::push (m_L, rhs); | |
| 336 | return lua_compare (m_L, -1, -2, LUA_OPLE) == 1; | |
| 337 | } | |
| 338 | ||
| 339 | template <class T> | |
| 340 | bool rawequal (T rhs) const | |
| 341 | { | |
| 342 | StackPop p (m_L, 2); | |
| 343 | push (m_L); | |
| 344 | Stack <T>::push (m_L, rhs); | |
| 345 | return lua_rawequal (m_L, -1, -2) == 1; | |
| 346 | } | |
| 347 | /** @} */ | |
| 348 | ||
| 349 | //-------------------------------------------------------------------------- | |
| 350 | /** | |
| 351 | Access a table value using a key. | |
| 352 | ||
| 353 | This invokes metamethods. | |
| 354 | */ | |
| 355 | template <class T> | |
| 356 | Proxy operator[] (T key) const | |
| 357 | { | |
| 358 | return LuaRef (*this) [key]; | |
| 359 | } | |
| 360 | ||
| 361 | //-------------------------------------------------------------------------- | |
| 362 | /** | |
| 363 | Access a table value using a key. | |
| 364 | ||
| 365 | The operation is raw, metamethods are not invoked. The result is | |
| 366 | passed by value and may not be modified. | |
| 367 | */ | |
| 368 | template <class T> | |
| 369 | LuaRef rawget (T key) const | |
| 370 | { | |
| 371 | StackPop (m_L, 1); | |
| 372 | push (m_L); | |
| 373 | Stack <T>::push (m_L, key); | |
| 374 | lua_rawget (m_L, -2); | |
| 375 | return LuaRef (m_L, FromStack ()); | |
| 376 | } | |
| 377 | ||
| 378 | //-------------------------------------------------------------------------- | |
| 379 | /** | |
| 380 | Append a value to the table. | |
| 381 | ||
| 382 | If the table is a sequence this will add another element to it. | |
| 383 | */ | |
| 384 | template <class T> | |
| 385 | void append (T v) const | |
| 386 | { | |
| 387 | push (m_L); | |
| 388 | Stack <T>::push (m_L, v); | |
| 389 | luaL_ref (m_L, -2); | |
| 390 | lua_pop (m_L, 1); | |
| 391 | } | |
| 392 | ||
| 393 | //-------------------------------------------------------------------------- | |
| 394 | /** | |
| 395 | Call the length operator. | |
| 396 | ||
| 397 | This is identical to applying the Lua # operator. | |
| 398 | */ | |
| 399 | int length () const | |
| 400 | { | |
| 401 | StackPop p (m_L, 1); | |
| 402 | push (m_L); | |
| 403 | return get_length (m_L, -1); | |
| 404 | } | |
| 405 | ||
| 406 | //-------------------------------------------------------------------------- | |
| 407 | /** | |
| 408 | Call Lua code. | |
| 409 | ||
| 410 | These overloads allow Lua code to be called with up to 8 parameters. | |
| 411 | The return value is provided as a LuaRef (which may be LUA_REFNIL). | |
| 412 | If an error occurs, a LuaException is thrown. | |
| 413 | */ | |
| 414 | /** @{ */ | |
| 415 | LuaRef const operator() () const | |
| 416 | { | |
| 417 | push (m_L); | |
| 418 | LuaException::pcall (m_L, 0, 1); | |
| 419 | return LuaRef (m_L, FromStack ()); | |
| 420 | } | |
| 421 | ||
| 422 | template <class P1> | |
| 423 | LuaRef const operator() (P1 p1) const | |
| 424 | { | |
| 425 | push (m_L); | |
| 426 | Stack <P1>::push (m_L, p1); | |
| 427 | LuaException::pcall (m_L, 1, 1); | |
| 428 | return LuaRef (m_L, FromStack ()); | |
| 429 | } | |
| 430 | ||
| 431 | template <class P1, class P2> | |
| 432 | LuaRef const operator() (P1 p1, P2 p2) const | |
| 433 | { | |
| 434 | push (m_L); | |
| 435 | Stack <P1>::push (m_L, p1); | |
| 436 | Stack <P2>::push (m_L, p2); | |
| 437 | LuaException::pcall (m_L, 2, 1); | |
| 438 | return LuaRef (m_L, FromStack ()); | |
| 439 | } | |
| 440 | ||
| 441 | template <class P1, class P2, class P3> | |
| 442 | LuaRef const operator() (P1 p1, P2 p2, P3 p3) const | |
| 443 | { | |
| 444 | push (m_L); | |
| 445 | Stack <P1>::push (m_L, p1); | |
| 446 | Stack <P2>::push (m_L, p2); | |
| 447 | Stack <P3>::push (m_L, p3); | |
| 448 | LuaException::pcall (m_L, 3, 1); | |
| 449 | return LuaRef (m_L, FromStack ()); | |
| 450 | } | |
| 451 | ||
| 452 | template <class P1, class P2, class P3, class P4> | |
| 453 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4) const | |
| 454 | { | |
| 455 | push (m_L); | |
| 456 | Stack <P1>::push (m_L, p1); | |
| 457 | Stack <P2>::push (m_L, p2); | |
| 458 | Stack <P3>::push (m_L, p3); | |
| 459 | Stack <P4>::push (m_L, p4); | |
| 460 | LuaException::pcall (m_L, 4, 1); | |
| 461 | return LuaRef (m_L, FromStack ()); | |
| 462 | } | |
| 463 | ||
| 464 | template <class P1, class P2, class P3, class P4, class P5> | |
| 465 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const | |
| 466 | { | |
| 467 | push (m_L); | |
| 468 | Stack <P1>::push (m_L, p1); | |
| 469 | Stack <P2>::push (m_L, p2); | |
| 470 | Stack <P3>::push (m_L, p3); | |
| 471 | Stack <P4>::push (m_L, p4); | |
| 472 | Stack <P5>::push (m_L, p5); | |
| 473 | LuaException::pcall (m_L, 5, 1); | |
| 474 | return LuaRef (m_L, FromStack ()); | |
| 475 | } | |
| 476 | ||
| 477 | template <class P1, class P2, class P3, class P4, class P5, class P6> | |
| 478 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const | |
| 479 | { | |
| 480 | push (m_L); | |
| 481 | Stack <P1>::push (m_L, p1); | |
| 482 | Stack <P2>::push (m_L, p2); | |
| 483 | Stack <P3>::push (m_L, p3); | |
| 484 | Stack <P4>::push (m_L, p4); | |
| 485 | Stack <P5>::push (m_L, p5); | |
| 486 | Stack <P6>::push (m_L, p6); | |
| 487 | LuaException::pcall (m_L, 6, 1); | |
| 488 | return LuaRef (m_L, FromStack ()); | |
| 489 | } | |
| 490 | ||
| 491 | template <class P1, class P2, class P3, class P4, class P5, class P6, class P7> | |
| 492 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const | |
| 493 | { | |
| 494 | push (m_L); | |
| 495 | Stack <P1>::push (m_L, p1); | |
| 496 | Stack <P2>::push (m_L, p2); | |
| 497 | Stack <P3>::push (m_L, p3); | |
| 498 | Stack <P4>::push (m_L, p4); | |
| 499 | Stack <P5>::push (m_L, p5); | |
| 500 | Stack <P6>::push (m_L, p6); | |
| 501 | Stack <P7>::push (m_L, p7); | |
| 502 | LuaException::pcall (m_L, 7, 1); | |
| 503 | return LuaRef (m_L, FromStack ()); | |
| 504 | } | |
| 505 | ||
| 506 | template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> | |
| 507 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const | |
| 508 | { | |
| 509 | push (m_L); | |
| 510 | Stack <P1>::push (m_L, p1); | |
| 511 | Stack <P2>::push (m_L, p2); | |
| 512 | Stack <P3>::push (m_L, p3); | |
| 513 | Stack <P4>::push (m_L, p4); | |
| 514 | Stack <P5>::push (m_L, p5); | |
| 515 | Stack <P6>::push (m_L, p6); | |
| 516 | Stack <P7>::push (m_L, p7); | |
| 517 | Stack <P8>::push (m_L, p8); | |
| 518 | LuaException::pcall (m_L, 8, 1); | |
| 519 | return LuaRef (m_L, FromStack ()); | |
| 520 | } | |
| 521 | /** @} */ | |
| 522 | ||
| 523 | //========================================================================== | |
| 524 | }; | |
| 525 | ||
| 526 | private: | |
| 527 | friend struct Stack <LuaRef>; | |
| 528 | ||
| 529 | //---------------------------------------------------------------------------- | |
| 530 | /** | |
| 531 | Type tag for stack construction. | |
| 532 | */ | |
| 533 | struct FromStack { }; | |
| 534 | ||
| 535 | //---------------------------------------------------------------------------- | |
| 536 | /** | |
| 537 | Create a reference to an object at the top of the Lua stack and pop it. | |
| 538 | ||
| 539 | This constructor is private and not invoked directly. | |
| 540 | Instead, use the `fromStack` function. | |
| 541 | ||
| 542 | @note The object is popped. | |
| 543 | */ | |
| 544 | LuaRef (lua_State* L, FromStack) | |
| 545 | : m_L (L) | |
| 546 | { | |
| 547 | m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 548 | } | |
| 549 | ||
| 550 | //---------------------------------------------------------------------------- | |
| 551 | /** | |
| 552 | Create a reference to an object on the Lua stack. | |
| 553 | ||
| 554 | This constructor is private and not invoked directly. | |
| 555 | Instead, use the `fromStack` function. | |
| 556 | ||
| 557 | @note The object is not popped. | |
| 558 | */ | |
| 559 | LuaRef (lua_State* L, int index, FromStack) | |
| 560 | : m_L (L) | |
| 561 | { | |
| 562 | lua_pushvalue (m_L, index); | |
| 563 | m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 564 | } | |
| 565 | ||
| 566 | //---------------------------------------------------------------------------- | |
| 567 | ||
| 568 | // This type of construction is disallowed, since we don't have a `lua_State`. | |
| 569 | // | |
| 570 | template <class T> | |
| 571 | LuaRef (T) | |
| 572 | { | |
| 573 | } | |
| 574 | ||
| 575 | //---------------------------------------------------------------------------- | |
| 576 | /** | |
| 577 | Create a reference to this ref. | |
| 578 | ||
| 579 | This is used internally. | |
| 580 | */ | |
| 581 | int createRef () const | |
| 582 | { | |
| 583 | if (m_ref != LUA_REFNIL) | |
| 584 | { | |
| 585 | push (m_L); | |
| 586 | return luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 587 | } | |
| 588 | else | |
| 589 | { | |
| 590 | return LUA_REFNIL; | |
| 591 | } | |
| 592 | } | |
| 593 | ||
| 594 | public: | |
| 595 | //---------------------------------------------------------------------------- | |
| 596 | /** | |
| 597 | Create a nil reference. | |
| 598 | ||
| 599 | The LuaRef may be assigned later. | |
| 600 | */ | |
| 601 | LuaRef (lua_State* L) | |
| 602 | : m_L (L) | |
| 603 | , m_ref (LUA_REFNIL) | |
| 604 | { | |
| 605 | } | |
| 606 | ||
| 607 | //---------------------------------------------------------------------------- | |
| 608 | /** | |
| 609 | Create a reference to a value. | |
| 610 | */ | |
| 611 | template <class T> | |
| 612 | LuaRef (lua_State* L, T v) | |
| 613 | : m_L (L) | |
| 614 | { | |
| 615 | Stack <T>::push (m_L, v); | |
| 616 | m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 617 | } | |
| 618 | ||
| 619 | //---------------------------------------------------------------------------- | |
| 620 | /** | |
| 621 | Create a reference to a table value. | |
| 622 | */ | |
| 623 | LuaRef (Proxy const& v) | |
| 624 | : m_L (v.state ()) | |
| 625 | , m_ref (v.createRef ()) | |
| 626 | { | |
| 627 | } | |
| 628 | ||
| 629 | //---------------------------------------------------------------------------- | |
| 630 | /** | |
| 631 | Create a new reference to an existing reference. | |
| 632 | */ | |
| 633 | LuaRef (LuaRef const& other) | |
| 634 | : m_L (other.m_L) | |
| 635 | , m_ref (other.createRef ()) | |
| 636 | { | |
| 637 | } | |
| 638 | ||
| 639 | //---------------------------------------------------------------------------- | |
| 640 | /** | |
| 641 | Destroy a reference. | |
| 642 | ||
| 643 | The corresponding Lua registry reference will be released. | |
| 644 | ||
| 645 | @note If the state refers to a thread, it is the responsibility of the | |
| 646 | caller to ensure that the thread still exists when the LuaRef | |
| 647 | is destroyed. | |
| 648 | */ | |
| 649 | ~LuaRef () | |
| 650 | { | |
| 651 | luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); | |
| 652 | } | |
| 653 | ||
| 654 | //---------------------------------------------------------------------------- | |
| 655 | /** | |
| 656 | Return a LuaRef from a stack item. | |
| 657 | ||
| 658 | The stack item is not popped. | |
| 659 | */ | |
| 660 | static LuaRef fromStack (lua_State* L, int index) | |
| 661 | { | |
| 662 | lua_pushvalue (L, index); | |
| 663 | return LuaRef (L, FromStack ()); | |
| 664 | } | |
| 665 | ||
| 666 | //---------------------------------------------------------------------------- | |
| 667 | /** | |
| 668 | Create a new empty table and return a reference to it. | |
| 669 | ||
| 670 | It is also possible to use the free function `newTable`. | |
| 671 | ||
| 672 | @see ::getGlobal | |
| 673 | */ | |
| 674 | static LuaRef newTable (lua_State* L) | |
| 675 | { | |
| 676 | lua_newtable (L); | |
| 677 | return LuaRef (L, FromStack ()); | |
| 678 | } | |
| 679 | ||
| 680 | //---------------------------------------------------------------------------- | |
| 681 | /** | |
| 682 | Return a reference to a named global. | |
| 683 | ||
| 684 | It is also possible to use the free function `getGlobal`. | |
| 685 | ||
| 686 | @see ::getGlobal | |
| 687 | */ | |
| 688 | static LuaRef getGlobal (lua_State *L, char const* name) | |
| 689 | { | |
| 690 | lua_getglobal (L, name); | |
| 691 | return LuaRef (L, FromStack ()); | |
| 692 | } | |
| 693 | ||
| 694 | //---------------------------------------------------------------------------- | |
| 695 | /** | |
| 696 | Assign a different value to this LuaRef. | |
| 697 | */ | |
| 698 | template <class T> | |
| 699 | LuaRef& operator= (T rhs) | |
| 700 | { | |
| 701 | luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); | |
| 702 | Stack <T>::push (m_L, rhs); | |
| 703 | m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 704 | return *this; | |
| 705 | } | |
| 706 | ||
| 707 | //---------------------------------------------------------------------------- | |
| 708 | /** | |
| 709 | Assign another LuaRef to this LuaRef. | |
| 710 | */ | |
| 711 | LuaRef& operator= (LuaRef const& rhs) | |
| 712 | { | |
| 713 | luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); | |
| 714 | rhs.push (m_L); | |
| 715 | m_L = rhs.state (); | |
| 716 | m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 717 | return *this; | |
| 718 | } | |
| 719 | ||
| 720 | //---------------------------------------------------------------------------- | |
| 721 | /** | |
| 722 | converts to a string using luas tostring function | |
| 723 | */ | |
| 724 | std::string tostring() const | |
| 725 | { | |
| 726 | lua_getglobal (m_L, "tostring"); | |
| 727 | push (m_L); | |
| 728 | lua_call (m_L, 1, 1); | |
| 729 | const char* str = lua_tostring(m_L, 1); | |
| 730 | lua_pop(m_L, 1); | |
| 731 | return std::string(str); | |
| 732 | } | |
| 733 | ||
| 734 | //---------------------------------------------------------------------------- | |
| 735 | /** | |
| 736 | Print a text description of the value to a stream. | |
| 737 | ||
| 738 | This is used for diagnostics. | |
| 739 | */ | |
| 740 | void print (std::ostream& os) const | |
| 741 | { | |
| 742 | switch (type ()) | |
| 743 | { | |
| 744 | case LUA_TNIL: | |
| 745 | os << "nil"; | |
| 746 | break; | |
| 747 | ||
| 748 | case LUA_TNUMBER: | |
| 749 | os << cast <lua_Number> (); | |
| 750 | break; | |
| 751 | ||
| 752 | case LUA_TBOOLEAN: | |
| 753 | os << (cast <bool> () ? "true" : "false"); | |
| 754 | break; | |
| 755 | ||
| 756 | case LUA_TSTRING: | |
| 757 | os << '"' << cast <std::string> () << '"'; | |
| 758 | break; | |
| 759 | ||
| 760 | case LUA_TTABLE: | |
| 761 | os << "table: " << tostring(); | |
| 762 | break; | |
| 763 | ||
| 764 | case LUA_TFUNCTION: | |
| 765 | os << "function: " << tostring(); | |
| 766 | break; | |
| 767 | ||
| 768 | case LUA_TUSERDATA: | |
| 769 | os << "userdata: " << tostring(); | |
| 770 | break; | |
| 771 | ||
| 772 | case LUA_TTHREAD: | |
| 773 | os << "thread: " << tostring(); | |
| 774 | break; | |
| 775 | ||
| 776 | case LUA_TLIGHTUSERDATA: | |
| 777 | os << "lightuserdata: " << tostring(); | |
| 778 | break; | |
| 779 | ||
| 780 | default: | |
| 781 | os << "unknown"; | |
| 782 | break; | |
| 783 | } | |
| 784 | } | |
| 785 | ||
| 786 | //============================================================================ | |
| 787 | // | |
| 788 | // This group of member functions is mirrored in Proxy | |
| 789 | // | |
| 790 | ||
| 791 | /** Retrieve the lua_State associated with the reference. | |
| 792 | */ | |
| 793 | lua_State* state () const | |
| 794 | { | |
| 795 | return m_L; | |
| 796 | } | |
| 797 | ||
| 798 | //---------------------------------------------------------------------------- | |
| 799 | /** | |
| 800 | Place the object onto the Lua stack. | |
| 801 | */ | |
| 802 | void push (lua_State* L) const | |
| 803 | { | |
| 804 | assert (equalstates (L, m_L)); | |
| 805 | lua_rawgeti (L, LUA_REGISTRYINDEX, m_ref); | |
| 806 | } | |
| 807 | ||
| 808 | //---------------------------------------------------------------------------- | |
| 809 | /** | |
| 810 | Pop the top of Lua stack and assign the ref to m_ref | |
| 811 | */ | |
| 812 | void pop (lua_State* L) | |
| 813 | { | |
| 814 | assert (equalstates (L, m_L)); | |
| 815 | luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); | |
| 816 | m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); | |
| 817 | } | |
| 818 | ||
| 819 | //---------------------------------------------------------------------------- | |
| 820 | /** | |
| 821 | Determine the object type. | |
| 822 | ||
| 823 | The return values are the same as for `lua_type`. | |
| 824 | */ | |
| 825 | /** @{ */ | |
| 826 | int type () const | |
| 827 | { | |
| 828 | int result; | |
| 829 | if (m_ref != LUA_REFNIL) | |
| 830 | { | |
| 831 | push (m_L); | |
| 832 | result = lua_type (m_L, -1); | |
| 833 | lua_pop (m_L, 1); | |
| 834 | } | |
| 835 | else | |
| 836 | { | |
| 837 | result = LUA_TNIL; | |
| 838 | } | |
| 839 | ||
| 840 | return result; | |
| 841 | } | |
| 842 | ||
| 843 | // should never happen | |
| 844 | //inline bool isNone () const { return m_ref == LUA_NOREF; } | |
| 845 | ||
| 846 | inline bool isNil () const { return type () == LUA_TNIL; } | |
| 847 | inline bool isNumber () const { return type () == LUA_TNUMBER; } | |
| 848 | inline bool isString () const { return type () == LUA_TSTRING; } | |
| 849 | inline bool isTable () const { return type () == LUA_TTABLE; } | |
| 850 | inline bool isFunction () const { return type () == LUA_TFUNCTION; } | |
| 851 | inline bool isUserdata () const { return type () == LUA_TUSERDATA; } | |
| 852 | inline bool isThread () const { return type () == LUA_TTHREAD; } | |
| 853 | inline bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; } | |
| 854 | /** @} */ | |
| 855 | ||
| 856 | //---------------------------------------------------------------------------- | |
| 857 | /** | |
| 858 | Perform an explicit conversion. | |
| 859 | */ | |
| 860 | template <class T> | |
| 861 | T cast () const | |
| 862 | { | |
| 863 | StackPop p (m_L, 1); | |
| 864 | push (m_L); | |
| 865 | ||
| 866 | // lua_gettop is used because Userdata::getClass() doesn't handle | |
| 867 | // negative stack indexes. | |
| 868 | // | |
| 869 | return Stack <T>::get (m_L, lua_gettop (m_L)); | |
| 870 | } | |
| 871 | ||
| 872 | //---------------------------------------------------------------------------- | |
| 873 | /** | |
| 874 | Universal implicit conversion operator. | |
| 875 | ||
| 876 | NOTE: Visual Studio 2010 and 2012 have a bug where this function | |
| 877 | is not used. See: | |
| 878 | ||
| 879 | http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014 | |
| 880 | https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile | |
| 881 | ||
| 882 | // This code snippet fails to compile in vs2010,vs2012 | |
| 883 | struct S { | |
| 884 | template <class T> inline operator T () const { return T (); } | |
| 885 | }; | |
| 886 | int main () { | |
| 887 | S () || false; | |
| 888 | return 0; | |
| 889 | } | |
| 890 | */ | |
| 891 | template <class T> | |
| 892 | inline operator T () const | |
| 893 | { | |
| 894 | return cast <T> (); | |
| 895 | } | |
| 896 | ||
| 897 | //---------------------------------------------------------------------------- | |
| 898 | /** | |
| 899 | Universal comparison operators. | |
| 900 | */ | |
| 901 | /** @{ */ | |
| 902 | template <class T> | |
| 903 | bool operator== (T rhs) const | |
| 904 | { | |
| 905 | StackPop p (m_L, 2); | |
| 906 | push (m_L); | |
| 907 | Stack <T>::push (m_L, rhs); | |
| 908 | return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; | |
| 909 | } | |
| 910 | ||
| 911 | template <class T> | |
| 912 | bool operator< (T rhs) const | |
| 913 | { | |
| 914 | StackPop p (m_L, 2); | |
| 915 | push (m_L); | |
| 916 | Stack <T>::push (m_L, rhs); | |
| 917 | return lua_compare (m_L, -2, -1, LUA_OPLT) == 1; | |
| 918 | } | |
| 919 | ||
| 920 | template <class T> | |
| 921 | bool operator<= (T rhs) const | |
| 922 | { | |
| 923 | StackPop p (m_L, 2); | |
| 924 | push (m_L); | |
| 925 | Stack <T>::push (m_L, rhs); | |
| 926 | return lua_compare (m_L, -2, -1, LUA_OPLE) == 1; | |
| 927 | } | |
| 928 | ||
| 929 | template <class T> | |
| 930 | bool operator> (T rhs) const | |
| 931 | { | |
| 932 | StackPop p (m_L, 2); | |
| 933 | push (m_L); | |
| 934 | Stack <T>::push (m_L, rhs); | |
| 935 | return lua_compare (m_L, -1, -2, LUA_OPLT) == 1; | |
| 936 | } | |
| 937 | ||
| 938 | template <class T> | |
| 939 | bool operator>= (T rhs) const | |
| 940 | { | |
| 941 | StackPop p (m_L, 2); | |
| 942 | push (m_L); | |
| 943 | Stack <T>::push (m_L, rhs); | |
| 944 | return lua_compare (m_L, -1, -2, LUA_OPLE) == 1; | |
| 945 | } | |
| 946 | ||
| 947 | template <class T> | |
| 948 | bool rawequal (T rhs) const | |
| 949 | { | |
| 950 | StackPop p (m_L, 2); | |
| 951 | push (m_L); | |
| 952 | Stack <T>::push (m_L, rhs); | |
| 953 | return lua_rawequal (m_L, -1, -2) == 1; | |
| 954 | } | |
| 955 | /** @} */ | |
| 956 | ||
| 957 | //---------------------------------------------------------------------------- | |
| 958 | /** | |
| 959 | Append a value to the table. | |
| 960 | ||
| 961 | If the table is a sequence this will add another element to it. | |
| 962 | */ | |
| 963 | template <class T> | |
| 964 | void append (T v) const | |
| 965 | { | |
| 966 | push (m_L); | |
| 967 | Stack <T>::push (m_L, v); | |
| 968 | luaL_ref (m_L, -2); | |
| 969 | lua_pop (m_L, 1); | |
| 970 | } | |
| 971 | ||
| 972 | //---------------------------------------------------------------------------- | |
| 973 | /** | |
| 974 | Call the length operator. | |
| 975 | ||
| 976 | This is identical to applying the Lua # operator. | |
| 977 | */ | |
| 978 | int length () const | |
| 979 | { | |
| 980 | StackPop p (m_L, 1); | |
| 981 | push (m_L); | |
| 982 | return get_length (m_L, -1); | |
| 983 | } | |
| 984 | ||
| 985 | //---------------------------------------------------------------------------- | |
| 986 | /** | |
| 987 | Access a table value using a key. | |
| 988 | ||
| 989 | This invokes metamethods. | |
| 990 | */ | |
| 991 | template <class T> | |
| 992 | Proxy operator[] (T key) const | |
| 993 | { | |
| 994 | Stack <T>::push (m_L, key); | |
| 995 | return Proxy (m_L, m_ref); | |
| 996 | } | |
| 997 | ||
| 998 | //---------------------------------------------------------------------------- | |
| 999 | /** | |
| 1000 | Call Lua code. | |
| 1001 | ||
| 1002 | These overloads allow Lua code to be called with up to 8 parameters. | |
| 1003 | The return value is provided as a LuaRef (which may be LUA_REFNIL). | |
| 1004 | If an error occurs, a LuaException is thrown. | |
| 1005 | */ | |
| 1006 | /** @{ */ | |
| 1007 | LuaRef const operator() () const | |
| 1008 | { | |
| 1009 | push (m_L); | |
| 1010 | LuaException::pcall (m_L, 0, 1); | |
| 1011 | return LuaRef (m_L, FromStack ()); | |
| 1012 | } | |
| 1013 | ||
| 1014 | template <class P1> | |
| 1015 | LuaRef const operator() (P1 p1) const | |
| 1016 | { | |
| 1017 | push (m_L); | |
| 1018 | Stack <P1>::push (m_L, p1); | |
| 1019 | LuaException::pcall (m_L, 1, 1); | |
| 1020 | return LuaRef (m_L, FromStack ()); | |
| 1021 | } | |
| 1022 | ||
| 1023 | template <class P1, class P2> | |
| 1024 | LuaRef const operator() (P1 p1, P2 p2) const | |
| 1025 | { | |
| 1026 | push (m_L); | |
| 1027 | Stack <P1>::push (m_L, p1); | |
| 1028 | Stack <P2>::push (m_L, p2); | |
| 1029 | LuaException::pcall (m_L, 2, 1); | |
| 1030 | return LuaRef (m_L, FromStack ()); | |
| 1031 | } | |
| 1032 | ||
| 1033 | template <class P1, class P2, class P3> | |
| 1034 | LuaRef const operator() (P1 p1, P2 p2, P3 p3) const | |
| 1035 | { | |
| 1036 | push (m_L); | |
| 1037 | Stack <P1>::push (m_L, p1); | |
| 1038 | Stack <P2>::push (m_L, p2); | |
| 1039 | Stack <P3>::push (m_L, p3); | |
| 1040 | LuaException::pcall (m_L, 3, 1); | |
| 1041 | return LuaRef (m_L, FromStack ()); | |
| 1042 | } | |
| 1043 | ||
| 1044 | template <class P1, class P2, class P3, class P4> | |
| 1045 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4) const | |
| 1046 | { | |
| 1047 | push (m_L); | |
| 1048 | Stack <P1>::push (m_L, p1); | |
| 1049 | Stack <P2>::push (m_L, p2); | |
| 1050 | Stack <P3>::push (m_L, p3); | |
| 1051 | Stack <P4>::push (m_L, p4); | |
| 1052 | LuaException::pcall (m_L, 4, 1); | |
| 1053 | return LuaRef (m_L, FromStack ()); | |
| 1054 | } | |
| 1055 | ||
| 1056 | template <class P1, class P2, class P3, class P4, class P5> | |
| 1057 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const | |
| 1058 | { | |
| 1059 | push (m_L); | |
| 1060 | Stack <P1>::push (m_L, p1); | |
| 1061 | Stack <P2>::push (m_L, p2); | |
| 1062 | Stack <P3>::push (m_L, p3); | |
| 1063 | Stack <P4>::push (m_L, p4); | |
| 1064 | Stack <P5>::push (m_L, p5); | |
| 1065 | LuaException::pcall (m_L, 5, 1); | |
| 1066 | return LuaRef (m_L, FromStack ()); | |
| 1067 | } | |
| 1068 | ||
| 1069 | template <class P1, class P2, class P3, class P4, class P5, class P6> | |
| 1070 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const | |
| 1071 | { | |
| 1072 | push (m_L); | |
| 1073 | Stack <P1>::push (m_L, p1); | |
| 1074 | Stack <P2>::push (m_L, p2); | |
| 1075 | Stack <P3>::push (m_L, p3); | |
| 1076 | Stack <P4>::push (m_L, p4); | |
| 1077 | Stack <P5>::push (m_L, p5); | |
| 1078 | Stack <P6>::push (m_L, p6); | |
| 1079 | LuaException::pcall (m_L, 6, 1); | |
| 1080 | return LuaRef (m_L, FromStack ()); | |
| 1081 | } | |
| 1082 | ||
| 1083 | template <class P1, class P2, class P3, class P4, class P5, class P6, class P7> | |
| 1084 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const | |
| 1085 | { | |
| 1086 | push (m_L); | |
| 1087 | Stack <P1>::push (m_L, p1); | |
| 1088 | Stack <P2>::push (m_L, p2); | |
| 1089 | Stack <P3>::push (m_L, p3); | |
| 1090 | Stack <P4>::push (m_L, p4); | |
| 1091 | Stack <P5>::push (m_L, p5); | |
| 1092 | Stack <P6>::push (m_L, p6); | |
| 1093 | Stack <P7>::push (m_L, p7); | |
| 1094 | LuaException::pcall (m_L, 7, 1); | |
| 1095 | return LuaRef (m_L, FromStack ()); | |
| 1096 | } | |
| 1097 | ||
| 1098 | template <class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> | |
| 1099 | LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const | |
| 1100 | { | |
| 1101 | push (m_L); | |
| 1102 | Stack <P1>::push (m_L, p1); | |
| 1103 | Stack <P2>::push (m_L, p2); | |
| 1104 | Stack <P3>::push (m_L, p3); | |
| 1105 | Stack <P4>::push (m_L, p4); | |
| 1106 | Stack <P5>::push (m_L, p5); | |
| 1107 | Stack <P6>::push (m_L, p6); | |
| 1108 | Stack <P7>::push (m_L, p7); | |
| 1109 | Stack <P8>::push (m_L, p8); | |
| 1110 | LuaException::pcall (m_L, 8, 1); | |
| 1111 | return LuaRef (m_L, FromStack ()); | |
| 1112 | } | |
| 1113 | /** @} */ | |
| 1114 | ||
| 1115 | //============================================================================ | |
| 1116 | ||
| 1117 | private: | |
| 1118 | lua_State* m_L; | |
| 1119 | int m_ref; | |
| 1120 | }; | |
| 1121 | ||
| 1122 | //------------------------------------------------------------------------------ | |
| 1123 | /** | |
| 1124 | Stack specialization for Nil | |
| 1125 | */ | |
| 1126 | template <> | |
| 1127 | struct Stack <Nil> | |
| 1128 | { | |
| 1129 | public: | |
| 1130 | static inline void push (lua_State* L, Nil) | |
| 1131 | { | |
| 1132 | lua_pushnil (L); | |
| 1133 | } | |
| 1134 | }; | |
| 1135 | ||
| 1136 | //------------------------------------------------------------------------------ | |
| 1137 | /** | |
| 1138 | Stack specialization for LuaRef. | |
| 1139 | */ | |
| 1140 | template <> | |
| 1141 | struct Stack <LuaRef> | |
| 1142 | { | |
| 1143 | public: | |
| 1144 | // The value is const& to prevent a copy construction. | |
| 1145 | // | |
| 1146 | static inline void push (lua_State* L, LuaRef const& v) | |
| 1147 | { | |
| 1148 | v.push (L); | |
| 1149 | } | |
| 1150 | ||
| 1151 | static inline LuaRef get (lua_State* L, int index) | |
| 1152 | { | |
| 1153 | return LuaRef (L, index, LuaRef::FromStack ()); | |
| 1154 | } | |
| 1155 | }; | |
| 1156 | ||
| 1157 | //------------------------------------------------------------------------------ | |
| 1158 | /** | |
| 1159 | Stack specialization for Proxy. | |
| 1160 | */ | |
| 1161 | template <> | |
| 1162 | struct Stack <LuaRef::Proxy> | |
| 1163 | { | |
| 1164 | public: | |
| 1165 | // The value is const& to prevent a copy construction. | |
| 1166 | // | |
| 1167 | static inline void push (lua_State* L, LuaRef::Proxy const& v) | |
| 1168 | { | |
| 1169 | v.push (L); | |
| 1170 | } | |
| 1171 | }; | |
| 1172 | ||
| 1173 | //------------------------------------------------------------------------------ | |
| 1174 | /** | |
| 1175 | Create a reference to a new, empty table. | |
| 1176 | ||
| 1177 | This is a syntactic abbreviation for LuaRef::newTable(). | |
| 1178 | */ | |
| 1179 | inline LuaRef newTable (lua_State* L) | |
| 1180 | { | |
| 1181 | return LuaRef::newTable (L); | |
| 1182 | } | |
| 1183 | ||
| 1184 | //------------------------------------------------------------------------------ | |
| 1185 | /** | |
| 1186 | Create a reference to a value in the global table. | |
| 1187 | ||
| 1188 | This is a syntactic abbreviation for LuaRef::getGlobal(). | |
| 1189 | */ | |
| 1190 | inline LuaRef getGlobal (lua_State *L, char const* name) | |
| 1191 | { | |
| 1192 | return LuaRef::getGlobal (L, name); | |
| 1193 | } | |
| 1194 | ||
| 1195 | //------------------------------------------------------------------------------ | |
| 1196 | /** | |
| 1197 | Write a LuaRef to a stream. | |
| 1198 | ||
| 1199 | This allows LuaRef and table proxies to work with streams. | |
| 1200 | */ | |
| 1201 | inline std::ostream& operator<< (std::ostream& os, LuaRef const& ref) | |
| 1202 | { | |
| 1203 | ref.print (os); | |
| 1204 | return os; | |
| 1205 | } | |
| 1206 | ||
| 1207 | //------------------------------------------------------------------------------ | |
| 1208 | ||
| 1209 | // more C++-like cast syntax | |
| 1210 | // | |
| 1211 | template<class T> | |
| 1212 | inline T LuaRef_cast(LuaRef const& lr) | |
| 1213 | { | |
| 1214 | return lr.cast<T>(); | |
| 1215 | } |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2008, Nigel Atkinson <suprapilot+LuaCode@gmail.com> | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | class LuaException : public std::exception | |
| 31 | { | |
| 32 | private: | |
| 33 | lua_State* m_L; | |
| 34 | std::string m_what; | |
| 35 | ||
| 36 | public: | |
| 37 | //---------------------------------------------------------------------------- | |
| 38 | /** | |
| 39 | Construct a LuaException after a lua_pcall(). | |
| 40 | */ | |
| 41 | LuaException (lua_State* L, int /*code*/) | |
| 42 | : m_L (L) | |
| 43 | { | |
| 44 | whatFromStack (); | |
| 45 | } | |
| 46 | ||
| 47 | //---------------------------------------------------------------------------- | |
| 48 | ||
| 49 | LuaException (lua_State *L, | |
| 50 | char const*, | |
| 51 | char const*, | |
| 52 | long) | |
| 53 | : m_L (L) | |
| 54 | { | |
| 55 | whatFromStack (); | |
| 56 | } | |
| 57 | ||
| 58 | //---------------------------------------------------------------------------- | |
| 59 | ||
| 60 | ~LuaException() throw () | |
| 61 | { | |
| 62 | } | |
| 63 | ||
| 64 | //---------------------------------------------------------------------------- | |
| 65 | ||
| 66 | char const* what() const throw () | |
| 67 | { | |
| 68 | return m_what.c_str(); | |
| 69 | } | |
| 70 | ||
| 71 | //============================================================================ | |
| 72 | /** | |
| 73 | Throw an exception. | |
| 74 | ||
| 75 | This centralizes all the exceptions thrown, so that we can set | |
| 76 | breakpoints before the stack is unwound, or otherwise customize the | |
| 77 | behavior. | |
| 78 | */ | |
| 79 | template <class Exception> | |
| 80 | static void Throw (Exception e) | |
| 81 | { | |
| 82 | throw e; | |
| 83 | } | |
| 84 | ||
| 85 | //---------------------------------------------------------------------------- | |
| 86 | /** | |
| 87 | Wrapper for lua_pcall that throws. | |
| 88 | */ | |
| 89 | static void pcall (lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0) | |
| 90 | { | |
| 91 | int code = lua_pcall (L, nargs, nresults, msgh); | |
| 92 | ||
| 93 | if (code != LUABRIDGE_LUA_OK) | |
| 94 | Throw (LuaException (L, code)); | |
| 95 | } | |
| 96 | ||
| 97 | //---------------------------------------------------------------------------- | |
| 98 | ||
| 99 | protected: | |
| 100 | void whatFromStack () | |
| 101 | { | |
| 102 | if (lua_gettop (m_L) > 0) | |
| 103 | { | |
| 104 | char const* s = lua_tostring (m_L, -1); | |
| 105 | m_what = s ? s : ""; | |
| 106 | } | |
| 107 | else | |
| 108 | { | |
| 109 | // stack is empty | |
| 110 | m_what = "missing error"; | |
| 111 | } | |
| 112 | } | |
| 113 | }; |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | ||
| 7 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 8 | ||
| 9 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 10 | of this software and associated documentation files (the "Software"), to deal | |
| 11 | in the Software without restriction, including without limitation the rights | |
| 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 13 | copies of the Software, and to permit persons to whom the Software is | |
| 14 | furnished to do so, subject to the following conditions: | |
| 15 | ||
| 16 | The above copyright notice and this permission notice shall be included in all | |
| 17 | copies or substantial portions of the Software. | |
| 18 | ||
| 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 25 | SOFTWARE. | |
| 26 | */ | |
| 27 | //============================================================================== | |
| 28 | ||
| 29 | /** Unique Lua registry keys for a class. | |
| 30 | ||
| 31 | Each registered class inserts three keys into the registry, whose | |
| 32 | values are the corresponding static, class, and const metatables. This | |
| 33 | allows a quick and reliable lookup for a metatable from a template type. | |
| 34 | */ | |
| 35 | template <class T> | |
| 36 | class ClassInfo | |
| 37 | { | |
| 38 | public: | |
| 39 | /** Get the key for the static table. | |
| 40 | ||
| 41 | The static table holds the static data members, static properties, and | |
| 42 | static member functions for a class. | |
| 43 | */ | |
| 44 | static void const* getStaticKey () | |
| 45 | { | |
| 46 | static char value; | |
| 47 | return &value; | |
| 48 | } | |
| 49 | ||
| 50 | /** Get the key for the class table. | |
| 51 | ||
| 52 | The class table holds the data members, properties, and member functions | |
| 53 | of a class. Read-only data and properties, and const member functions are | |
| 54 | also placed here (to save a lookup in the const table). | |
| 55 | */ | |
| 56 | static void const* getClassKey () | |
| 57 | { | |
| 58 | static char value; | |
| 59 | return &value; | |
| 60 | } | |
| 61 | ||
| 62 | /** Get the key for the const table. | |
| 63 | ||
| 64 | The const table holds read-only data members and properties, and const | |
| 65 | member functions of a class. | |
| 66 | */ | |
| 67 | static void const* getConstKey () | |
| 68 | { | |
| 69 | static char value; | |
| 70 | return &value; | |
| 71 | } | |
| 72 | }; | |
| 73 |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | ||
| 7 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 8 | ||
| 9 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 10 | of this software and associated documentation files (the "Software"), to deal | |
| 11 | in the Software without restriction, including without limitation the rights | |
| 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 13 | copies of the Software, and to permit persons to whom the Software is | |
| 14 | furnished to do so, subject to the following conditions: | |
| 15 | ||
| 16 | The above copyright notice and this permission notice shall be included in all | |
| 17 | copies or substantial portions of the Software. | |
| 18 | ||
| 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 25 | SOFTWARE. | |
| 26 | */ | |
| 27 | //============================================================================== | |
| 28 | ||
| 29 | /** | |
| 30 | Since the throw specification is part of a function signature, the FuncTraits | |
| 31 | family of templates needs to be specialized for both types. The | |
| 32 | LUABRIDGE_THROWSPEC macro controls whether we use the 'throw ()' form, or | |
| 33 | 'noexcept' (if C++11 is available) to distinguish the functions. | |
| 34 | */ | |
| 35 | #if defined (__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__clang__) || defined(__GNUC__) || \ | |
| 36 | (defined (_MSC_VER) && (_MSC_VER >= 1700)) | |
| 37 | // Do not define LUABRIDGE_THROWSPEC since the Xcode and gcc compilers do not | |
| 38 | // distinguish the throw specification in the function signature. | |
| 39 | #else | |
| 40 | // Visual Studio 10 and earlier pay too much mind to useless throw() spec. | |
| 41 | // | |
| 42 | # define LUABRIDGE_THROWSPEC throw() | |
| 43 | #endif | |
| 44 | ||
| 45 | //============================================================================== | |
| 46 | /** | |
| 47 | Traits for function pointers. | |
| 48 | ||
| 49 | There are three types of functions: global, non-const member, and const | |
| 50 | member. These templates determine the type of function, which class type it | |
| 51 | belongs to if it is a class member, the const-ness if it is a member | |
| 52 | function, and the type information for the return value and argument list. | |
| 53 | ||
| 54 | Expansions are provided for functions with up to 8 parameters. This can be | |
| 55 | manually extended, or expanded to an arbitrary amount using C++11 features. | |
| 56 | */ | |
| 57 | template <class MemFn, class D = MemFn> | |
| 58 | struct FuncTraits | |
| 59 | { | |
| 60 | }; | |
| 61 | ||
| 62 | /* Ordinary function pointers. */ | |
| 63 | ||
| 64 | template <class R, class D> | |
| 65 | struct FuncTraits <R (*) (), D> | |
| 66 | { | |
| 67 | static bool const isMemberFunction = false; | |
| 68 | typedef D DeclType; | |
| 69 | typedef R ReturnType; | |
| 70 | typedef None Params; | |
| 71 | static R call (D fp, TypeListValues <Params>) | |
| 72 | { | |
| 73 | return fp (); | |
| 74 | } | |
| 75 | }; | |
| 76 | ||
| 77 | template <class R, class P1, class D> | |
| 78 | struct FuncTraits <R (*) (P1), D> | |
| 79 | { | |
| 80 | static bool const isMemberFunction = false; | |
| 81 | typedef D DeclType; | |
| 82 | typedef R ReturnType; | |
| 83 | typedef TypeList <P1> Params; | |
| 84 | static R call (D fp, TypeListValues <Params> tvl) | |
| 85 | { | |
| 86 | return fp (tvl.hd); | |
| 87 | } | |
| 88 | }; | |
| 89 | ||
| 90 | template <class R, class P1, class P2, class D> | |
| 91 | struct FuncTraits <R (*) (P1, P2), D> | |
| 92 | { | |
| 93 | static bool const isMemberFunction = false; | |
| 94 | typedef D DeclType; | |
| 95 | typedef R ReturnType; | |
| 96 | typedef TypeList <P1, TypeList <P2> > Params; | |
| 97 | static R call (D fp, TypeListValues <Params> tvl) | |
| 98 | { | |
| 99 | return fp (tvl.hd, tvl.tl.hd); | |
| 100 | } | |
| 101 | }; | |
| 102 | ||
| 103 | template <class R, class P1, class P2, class P3, class D> | |
| 104 | struct FuncTraits <R (*) (P1, P2, P3), D> | |
| 105 | { | |
| 106 | static bool const isMemberFunction = false; | |
| 107 | typedef D DeclType; | |
| 108 | typedef R ReturnType; | |
| 109 | typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params; | |
| 110 | static R call (D fp, TypeListValues <Params> tvl) | |
| 111 | { | |
| 112 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 113 | } | |
| 114 | }; | |
| 115 | ||
| 116 | template <class R, class P1, class P2, class P3, class P4, class D> | |
| 117 | struct FuncTraits <R (*) (P1, P2, P3, P4), D> | |
| 118 | { | |
| 119 | static bool const isMemberFunction = false; | |
| 120 | typedef D DeclType; | |
| 121 | typedef R ReturnType; | |
| 122 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params; | |
| 123 | static R call (D fp, TypeListValues <Params> tvl) | |
| 124 | { | |
| 125 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 126 | } | |
| 127 | }; | |
| 128 | ||
| 129 | template <class R, class P1, class P2, class P3, class P4, class P5, class D> | |
| 130 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5), D> | |
| 131 | { | |
| 132 | static bool const isMemberFunction = false; | |
| 133 | typedef D DeclType; | |
| 134 | typedef R ReturnType; | |
| 135 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params; | |
| 136 | static R call (D fp, TypeListValues <Params> tvl) | |
| 137 | { | |
| 138 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); | |
| 139 | } | |
| 140 | }; | |
| 141 | ||
| 142 | template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D> | |
| 143 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6), D> | |
| 144 | { | |
| 145 | static bool const isMemberFunction = false; | |
| 146 | typedef D DeclType; | |
| 147 | typedef R ReturnType; | |
| 148 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params; | |
| 149 | static R call (D fp, TypeListValues <Params> tvl) | |
| 150 | { | |
| 151 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 152 | } | |
| 153 | }; | |
| 154 | ||
| 155 | template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D> | |
| 156 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7), D> | |
| 157 | { | |
| 158 | static bool const isMemberFunction = false; | |
| 159 | typedef D DeclType; | |
| 160 | typedef R ReturnType; | |
| 161 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params; | |
| 162 | static R call (D fp, TypeListValues <Params> tvl) | |
| 163 | { | |
| 164 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 165 | } | |
| 166 | }; | |
| 167 | ||
| 168 | template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D> | |
| 169 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8), D> | |
| 170 | { | |
| 171 | static bool const isMemberFunction = false; | |
| 172 | typedef D DeclType; | |
| 173 | typedef R ReturnType; | |
| 174 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params; | |
| 175 | static R call (D fp, TypeListValues <Params> tvl) | |
| 176 | { | |
| 177 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 178 | } | |
| 179 | }; | |
| 180 | ||
| 181 | /* Non-const member function pointers. */ | |
| 182 | ||
| 183 | template <class T, class R, class D> | |
| 184 | struct FuncTraits <R (T::*) (), D> | |
| 185 | { | |
| 186 | static bool const isMemberFunction = true; | |
| 187 | static bool const isConstMemberFunction = false; | |
| 188 | typedef D DeclType; | |
| 189 | typedef T ClassType; | |
| 190 | typedef R ReturnType; | |
| 191 | typedef None Params; | |
| 192 | static R call (T* obj, D fp, TypeListValues <Params>) | |
| 193 | { | |
| 194 | return (obj->*fp)(); | |
| 195 | } | |
| 196 | }; | |
| 197 | ||
| 198 | template <class T, class R, class P1, class D> | |
| 199 | struct FuncTraits <R (T::*) (P1), D> | |
| 200 | { | |
| 201 | static bool const isMemberFunction = true; | |
| 202 | static bool const isConstMemberFunction = false; | |
| 203 | typedef D DeclType; | |
| 204 | typedef T ClassType; | |
| 205 | typedef R ReturnType; | |
| 206 | typedef TypeList <P1> Params; | |
| 207 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 208 | { | |
| 209 | return (obj->*fp)(tvl.hd); | |
| 210 | } | |
| 211 | }; | |
| 212 | ||
| 213 | template <class T, class R, class P1, class P2, class D> | |
| 214 | struct FuncTraits <R (T::*) (P1, P2), D> | |
| 215 | { | |
| 216 | static bool const isMemberFunction = true; | |
| 217 | static bool const isConstMemberFunction = false; | |
| 218 | typedef D DeclType; | |
| 219 | typedef T ClassType; | |
| 220 | typedef R ReturnType; | |
| 221 | typedef TypeList <P1, TypeList <P2> > Params; | |
| 222 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 223 | { | |
| 224 | return (obj->*fp)(tvl.hd, tvl.tl.hd); | |
| 225 | } | |
| 226 | }; | |
| 227 | ||
| 228 | template <class T, class R, class P1, class P2, class P3, class D> | |
| 229 | struct FuncTraits <R (T::*) (P1, P2, P3), D> | |
| 230 | { | |
| 231 | static bool const isMemberFunction = true; | |
| 232 | static bool const isConstMemberFunction = false; | |
| 233 | typedef D DeclType; | |
| 234 | typedef T ClassType; | |
| 235 | typedef R ReturnType; | |
| 236 | typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params; | |
| 237 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 238 | { | |
| 239 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 240 | } | |
| 241 | }; | |
| 242 | ||
| 243 | template <class T, class R, class P1, class P2, class P3, class P4, class D> | |
| 244 | struct FuncTraits <R (T::*) (P1, P2, P3, P4), D> | |
| 245 | { | |
| 246 | static bool const isMemberFunction = true; | |
| 247 | static bool const isConstMemberFunction = false; | |
| 248 | typedef D DeclType; | |
| 249 | typedef T ClassType; | |
| 250 | typedef R ReturnType; | |
| 251 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params; | |
| 252 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 253 | { | |
| 254 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 255 | } | |
| 256 | }; | |
| 257 | ||
| 258 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D> | |
| 259 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5), D> | |
| 260 | { | |
| 261 | static bool const isMemberFunction = true; | |
| 262 | static bool const isConstMemberFunction = false; | |
| 263 | typedef D DeclType; | |
| 264 | typedef T ClassType; | |
| 265 | typedef R ReturnType; | |
| 266 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params; | |
| 267 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 268 | { | |
| 269 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); | |
| 270 | } | |
| 271 | }; | |
| 272 | ||
| 273 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D> | |
| 274 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6), D> | |
| 275 | { | |
| 276 | static bool const isMemberFunction = true; | |
| 277 | static bool const isConstMemberFunction = false; | |
| 278 | typedef D DeclType; | |
| 279 | typedef T ClassType; | |
| 280 | typedef R ReturnType; | |
| 281 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params; | |
| 282 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 283 | { | |
| 284 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 285 | } | |
| 286 | }; | |
| 287 | ||
| 288 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D> | |
| 289 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7), D> | |
| 290 | { | |
| 291 | static bool const isMemberFunction = true; | |
| 292 | static bool const isConstMemberFunction = false; | |
| 293 | typedef D DeclType; | |
| 294 | typedef T ClassType; | |
| 295 | typedef R ReturnType; | |
| 296 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params; | |
| 297 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 298 | { | |
| 299 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 300 | } | |
| 301 | }; | |
| 302 | ||
| 303 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D> | |
| 304 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8), D> | |
| 305 | { | |
| 306 | static bool const isMemberFunction = true; | |
| 307 | static bool const isConstMemberFunction = false; | |
| 308 | typedef D DeclType; | |
| 309 | typedef T ClassType; | |
| 310 | typedef R ReturnType; | |
| 311 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params; | |
| 312 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 313 | { | |
| 314 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 315 | } | |
| 316 | }; | |
| 317 | ||
| 318 | /* Const member function pointers. */ | |
| 319 | ||
| 320 | template <class T, class R, class D> | |
| 321 | struct FuncTraits <R (T::*) () const, D> | |
| 322 | { | |
| 323 | static bool const isMemberFunction = true; | |
| 324 | static bool const isConstMemberFunction = true; | |
| 325 | typedef D DeclType; | |
| 326 | typedef T ClassType; | |
| 327 | typedef R ReturnType; | |
| 328 | typedef None Params; | |
| 329 | static R call (T const* obj, D fp, TypeListValues <Params>) | |
| 330 | { | |
| 331 | return (obj->*fp)(); | |
| 332 | } | |
| 333 | }; | |
| 334 | ||
| 335 | template <class T, class R, class P1, class D> | |
| 336 | struct FuncTraits <R (T::*) (P1) const, D> | |
| 337 | { | |
| 338 | static bool const isMemberFunction = true; | |
| 339 | static bool const isConstMemberFunction = true; | |
| 340 | typedef D DeclType; | |
| 341 | typedef T ClassType; | |
| 342 | typedef R ReturnType; | |
| 343 | typedef TypeList <P1> Params; | |
| 344 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 345 | { | |
| 346 | return (obj->*fp)(tvl.hd); | |
| 347 | } | |
| 348 | }; | |
| 349 | ||
| 350 | template <class T, class R, class P1, class P2, class D> | |
| 351 | struct FuncTraits <R (T::*) (P1, P2) const, D> | |
| 352 | { | |
| 353 | static bool const isMemberFunction = true; | |
| 354 | static bool const isConstMemberFunction = true; | |
| 355 | typedef D DeclType; | |
| 356 | typedef T ClassType; | |
| 357 | typedef R ReturnType; | |
| 358 | typedef TypeList <P1, TypeList <P2> > Params; | |
| 359 | static R call (T const* obj, R (T::*fp) (P1, P2) const, | |
| 360 | TypeListValues <Params> tvl) | |
| 361 | { | |
| 362 | return (obj->*fp)(tvl.hd, tvl.tl.hd); | |
| 363 | } | |
| 364 | }; | |
| 365 | ||
| 366 | template <class T, class R, class P1, class P2, class P3, class D> | |
| 367 | struct FuncTraits <R (T::*) (P1, P2, P3) const, D> | |
| 368 | { | |
| 369 | static bool const isMemberFunction = true; | |
| 370 | static bool const isConstMemberFunction = true; | |
| 371 | typedef D DeclType; | |
| 372 | typedef T ClassType; | |
| 373 | typedef R ReturnType; | |
| 374 | typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params; | |
| 375 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 376 | { | |
| 377 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 378 | } | |
| 379 | }; | |
| 380 | ||
| 381 | template <class T, class R, class P1, class P2, class P3, class P4, class D> | |
| 382 | struct FuncTraits <R (T::*) (P1, P2, P3, P4) const, D> | |
| 383 | { | |
| 384 | static bool const isMemberFunction = true; | |
| 385 | static bool const isConstMemberFunction = true; | |
| 386 | typedef D DeclType; | |
| 387 | typedef T ClassType; | |
| 388 | typedef R ReturnType; | |
| 389 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params; | |
| 390 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 391 | { | |
| 392 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 393 | } | |
| 394 | }; | |
| 395 | ||
| 396 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D> | |
| 397 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const, D> | |
| 398 | { | |
| 399 | static bool const isMemberFunction = true; | |
| 400 | static bool const isConstMemberFunction = true; | |
| 401 | typedef D DeclType; | |
| 402 | typedef T ClassType; | |
| 403 | typedef R ReturnType; | |
| 404 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params; | |
| 405 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 406 | { | |
| 407 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); | |
| 408 | } | |
| 409 | }; | |
| 410 | ||
| 411 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D> | |
| 412 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const, D> | |
| 413 | { | |
| 414 | static bool const isMemberFunction = true; | |
| 415 | static bool const isConstMemberFunction = true; | |
| 416 | typedef D DeclType; | |
| 417 | typedef T ClassType; | |
| 418 | typedef R ReturnType; | |
| 419 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params; | |
| 420 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 421 | { | |
| 422 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 423 | } | |
| 424 | }; | |
| 425 | ||
| 426 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D> | |
| 427 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const, D> | |
| 428 | { | |
| 429 | static bool const isMemberFunction = true; | |
| 430 | static bool const isConstMemberFunction = true; | |
| 431 | typedef D DeclType; | |
| 432 | typedef T ClassType; | |
| 433 | typedef R ReturnType; | |
| 434 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params; | |
| 435 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 436 | { | |
| 437 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 438 | } | |
| 439 | }; | |
| 440 | ||
| 441 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D> | |
| 442 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const, D> | |
| 443 | { | |
| 444 | static bool const isMemberFunction = true; | |
| 445 | static bool const isConstMemberFunction = true; | |
| 446 | typedef D DeclType; | |
| 447 | typedef T ClassType; | |
| 448 | typedef R ReturnType; | |
| 449 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params; | |
| 450 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 451 | { | |
| 452 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 453 | } | |
| 454 | }; | |
| 455 | ||
| 456 | #if defined (LUABRIDGE_THROWSPEC) | |
| 457 | ||
| 458 | /* Ordinary function pointers. */ | |
| 459 | ||
| 460 | template <class R, class D> | |
| 461 | struct FuncTraits <R (*) () LUABRIDGE_THROWSPEC, D> | |
| 462 | { | |
| 463 | static bool const isMemberFunction = false; | |
| 464 | typedef D DeclType; | |
| 465 | typedef R ReturnType; | |
| 466 | typedef None Params; | |
| 467 | static R call (D fp, TypeListValues <Params> const&) | |
| 468 | { | |
| 469 | return fp (); | |
| 470 | } | |
| 471 | }; | |
| 472 | ||
| 473 | template <class R, class P1, class D> | |
| 474 | struct FuncTraits <R (*) (P1) LUABRIDGE_THROWSPEC, D> | |
| 475 | { | |
| 476 | static bool const isMemberFunction = false; | |
| 477 | typedef D DeclType; | |
| 478 | typedef R ReturnType; | |
| 479 | typedef TypeList <P1> Params; | |
| 480 | static R call (D fp, TypeListValues <Params> tvl) | |
| 481 | { | |
| 482 | return fp (tvl.hd); | |
| 483 | } | |
| 484 | }; | |
| 485 | ||
| 486 | template <class R, class P1, class P2, class D> | |
| 487 | struct FuncTraits <R (*) (P1, P2) LUABRIDGE_THROWSPEC, D> | |
| 488 | { | |
| 489 | static bool const isMemberFunction = false; | |
| 490 | typedef D DeclType; | |
| 491 | typedef R ReturnType; | |
| 492 | typedef TypeList <P1, TypeList <P2> > Params; | |
| 493 | static R call (D fp, TypeListValues <Params> tvl) | |
| 494 | { | |
| 495 | return fp (tvl.hd, tvl.tl.hd); | |
| 496 | } | |
| 497 | }; | |
| 498 | ||
| 499 | template <class R, class P1, class P2, class P3, class D> | |
| 500 | struct FuncTraits <R (*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D> | |
| 501 | { | |
| 502 | static bool const isMemberFunction = false; | |
| 503 | typedef D DeclType; | |
| 504 | typedef R ReturnType; | |
| 505 | typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params; | |
| 506 | static R call (D fp, TypeListValues <Params> tvl) | |
| 507 | { | |
| 508 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 509 | } | |
| 510 | }; | |
| 511 | ||
| 512 | template <class R, class P1, class P2, class P3, class P4, class D> | |
| 513 | struct FuncTraits <R (*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D> | |
| 514 | { | |
| 515 | static bool const isMemberFunction = false; | |
| 516 | typedef D DeclType; | |
| 517 | typedef R ReturnType; | |
| 518 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params; | |
| 519 | static R call (D fp, TypeListValues <Params> tvl) | |
| 520 | { | |
| 521 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 522 | } | |
| 523 | }; | |
| 524 | ||
| 525 | template <class R, class P1, class P2, class P3, class P4, class P5, class D> | |
| 526 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D> | |
| 527 | { | |
| 528 | static bool const isMemberFunction = false; | |
| 529 | typedef D DeclType; | |
| 530 | typedef R ReturnType; | |
| 531 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params; | |
| 532 | static R call (D fp, TypeListValues <Params> tvl) | |
| 533 | { | |
| 534 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); | |
| 535 | } | |
| 536 | }; | |
| 537 | ||
| 538 | template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class D> | |
| 539 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D> | |
| 540 | { | |
| 541 | static bool const isMemberFunction = false; | |
| 542 | typedef D DeclType; | |
| 543 | typedef R ReturnType; | |
| 544 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params; | |
| 545 | static R call (D fp, TypeListValues <Params> tvl) | |
| 546 | { | |
| 547 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 548 | } | |
| 549 | }; | |
| 550 | ||
| 551 | template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D> | |
| 552 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D> | |
| 553 | { | |
| 554 | static bool const isMemberFunction = false; | |
| 555 | typedef D DeclType; | |
| 556 | typedef R ReturnType; | |
| 557 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params; | |
| 558 | static R call (D fp, TypeListValues <Params> tvl) | |
| 559 | { | |
| 560 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 561 | } | |
| 562 | }; | |
| 563 | ||
| 564 | template <class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D> | |
| 565 | struct FuncTraits <R (*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D> | |
| 566 | { | |
| 567 | static bool const isMemberFunction = false; | |
| 568 | typedef D DeclType; | |
| 569 | typedef R ReturnType; | |
| 570 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params; | |
| 571 | static R call (D fp, TypeListValues <Params> tvl) | |
| 572 | { | |
| 573 | return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 574 | } | |
| 575 | }; | |
| 576 | ||
| 577 | /* Non-const member function pointers with THROWSPEC. */ | |
| 578 | ||
| 579 | template <class T, class R, class D> | |
| 580 | struct FuncTraits <R (T::*) () LUABRIDGE_THROWSPEC, D> | |
| 581 | { | |
| 582 | static bool const isMemberFunction = true; | |
| 583 | static bool const isConstMemberFunction = false; | |
| 584 | typedef D DeclType; | |
| 585 | typedef T ClassType; | |
| 586 | typedef R ReturnType; | |
| 587 | typedef None Params; | |
| 588 | static R call (T* obj, D fp, TypeListValues <Params> const&) | |
| 589 | { | |
| 590 | return (obj->*fp)(); | |
| 591 | } | |
| 592 | }; | |
| 593 | ||
| 594 | template <class T, class R, class P1, class D> | |
| 595 | struct FuncTraits <R (T::*) (P1) LUABRIDGE_THROWSPEC, D> | |
| 596 | { | |
| 597 | static bool const isMemberFunction = true; | |
| 598 | static bool const isConstMemberFunction = false; | |
| 599 | typedef D DeclType; | |
| 600 | typedef T ClassType; | |
| 601 | typedef R ReturnType; | |
| 602 | typedef TypeList <P1> Params; | |
| 603 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 604 | { | |
| 605 | return (obj->*fp)(tvl.hd); | |
| 606 | } | |
| 607 | }; | |
| 608 | ||
| 609 | template <class T, class R, class P1, class P2, class D> | |
| 610 | struct FuncTraits <R (T::*) (P1, P2) LUABRIDGE_THROWSPEC, D> | |
| 611 | { | |
| 612 | static bool const isMemberFunction = true; | |
| 613 | static bool const isConstMemberFunction = false; | |
| 614 | typedef D DeclType; | |
| 615 | typedef T ClassType; | |
| 616 | typedef R ReturnType; | |
| 617 | typedef TypeList <P1, TypeList <P2> > Params; | |
| 618 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 619 | { | |
| 620 | return (obj->*fp)(tvl.hd, tvl.tl.hd); | |
| 621 | } | |
| 622 | }; | |
| 623 | ||
| 624 | template <class T, class R, class P1, class P2, class P3, class D> | |
| 625 | struct FuncTraits <R (T::*) (P1, P2, P3) LUABRIDGE_THROWSPEC, D> | |
| 626 | { | |
| 627 | static bool const isMemberFunction = true; | |
| 628 | static bool const isConstMemberFunction = false; | |
| 629 | typedef D DeclType; | |
| 630 | typedef T ClassType; | |
| 631 | typedef R ReturnType; | |
| 632 | typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params; | |
| 633 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 634 | { | |
| 635 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 636 | } | |
| 637 | }; | |
| 638 | ||
| 639 | template <class T, class R, class P1, class P2, class P3, class P4, class D> | |
| 640 | struct FuncTraits <R (T::*) (P1, P2, P3, P4) LUABRIDGE_THROWSPEC, D> | |
| 641 | { | |
| 642 | static bool const isMemberFunction = true; | |
| 643 | static bool const isConstMemberFunction = false; | |
| 644 | typedef D DeclType; | |
| 645 | typedef T ClassType; | |
| 646 | typedef R ReturnType; | |
| 647 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params; | |
| 648 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 649 | { | |
| 650 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 651 | } | |
| 652 | }; | |
| 653 | ||
| 654 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D> | |
| 655 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) LUABRIDGE_THROWSPEC, D> | |
| 656 | { | |
| 657 | static bool const isMemberFunction = true; | |
| 658 | static bool const isConstMemberFunction = false; | |
| 659 | typedef D DeclType; | |
| 660 | typedef T ClassType; | |
| 661 | typedef R ReturnType; | |
| 662 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params; | |
| 663 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 664 | { | |
| 665 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd); | |
| 666 | } | |
| 667 | }; | |
| 668 | ||
| 669 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D> | |
| 670 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) LUABRIDGE_THROWSPEC, D> | |
| 671 | { | |
| 672 | static bool const isMemberFunction = true; | |
| 673 | static bool const isConstMemberFunction = false; | |
| 674 | typedef D DeclType; | |
| 675 | typedef T ClassType; | |
| 676 | typedef R ReturnType; | |
| 677 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params; | |
| 678 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 679 | { | |
| 680 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 681 | } | |
| 682 | }; | |
| 683 | ||
| 684 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D> | |
| 685 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) LUABRIDGE_THROWSPEC, D> | |
| 686 | { | |
| 687 | static bool const isMemberFunction = true; | |
| 688 | static bool const isConstMemberFunction = false; | |
| 689 | typedef D DeclType; | |
| 690 | typedef T ClassType; | |
| 691 | typedef R ReturnType; | |
| 692 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params; | |
| 693 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 694 | { | |
| 695 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 696 | } | |
| 697 | }; | |
| 698 | ||
| 699 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D> | |
| 700 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) LUABRIDGE_THROWSPEC, D> | |
| 701 | { | |
| 702 | static bool const isMemberFunction = true; | |
| 703 | static bool const isConstMemberFunction = false; | |
| 704 | typedef D DeclType; | |
| 705 | typedef T ClassType; | |
| 706 | typedef R ReturnType; | |
| 707 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params; | |
| 708 | static R call (T* obj, D fp, TypeListValues <Params> tvl) | |
| 709 | { | |
| 710 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 711 | } | |
| 712 | }; | |
| 713 | ||
| 714 | /* Const member function pointers with THROWSPEC. */ | |
| 715 | ||
| 716 | template <class T, class R, class D> | |
| 717 | struct FuncTraits <R (T::*) () const LUABRIDGE_THROWSPEC, D> | |
| 718 | { | |
| 719 | static bool const isMemberFunction = true; | |
| 720 | static bool const isConstMemberFunction = true; | |
| 721 | typedef D DeclType; | |
| 722 | typedef T ClassType; | |
| 723 | typedef R ReturnType; | |
| 724 | typedef None Params; | |
| 725 | static R call (T const* obj, D fp, TypeListValues <Params>) | |
| 726 | { | |
| 727 | return (obj->*fp)(); | |
| 728 | } | |
| 729 | }; | |
| 730 | ||
| 731 | template <class T, class R, class P1, class D> | |
| 732 | struct FuncTraits <R (T::*) (P1) const LUABRIDGE_THROWSPEC, D> | |
| 733 | { | |
| 734 | static bool const isMemberFunction = true; | |
| 735 | static bool const isConstMemberFunction = true; | |
| 736 | typedef D DeclType; | |
| 737 | typedef T ClassType; | |
| 738 | typedef R ReturnType; | |
| 739 | typedef TypeList <P1> Params; | |
| 740 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 741 | { | |
| 742 | return (obj->*fp)(tvl.hd); | |
| 743 | } | |
| 744 | }; | |
| 745 | ||
| 746 | template <class T, class R, class P1, class P2, class D> | |
| 747 | struct FuncTraits <R (T::*) (P1, P2) const LUABRIDGE_THROWSPEC, D> | |
| 748 | { | |
| 749 | static bool const isMemberFunction = true; | |
| 750 | static bool const isConstMemberFunction = true; | |
| 751 | typedef D DeclType; | |
| 752 | typedef T ClassType; | |
| 753 | typedef R ReturnType; | |
| 754 | typedef TypeList <P1, TypeList <P2> > Params; | |
| 755 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 756 | { | |
| 757 | return (obj->*fp)(tvl.hd, tvl.tl.hd); | |
| 758 | } | |
| 759 | }; | |
| 760 | ||
| 761 | template <class T, class R, class P1, class P2, class P3, class D> | |
| 762 | struct FuncTraits <R (T::*) (P1, P2, P3) const LUABRIDGE_THROWSPEC, D> | |
| 763 | { | |
| 764 | static bool const isMemberFunction = true; | |
| 765 | static bool const isConstMemberFunction = true; | |
| 766 | typedef D DeclType; | |
| 767 | typedef T ClassType; | |
| 768 | typedef R ReturnType; | |
| 769 | typedef TypeList <P1, TypeList <P2, TypeList <P3> > > Params; | |
| 770 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 771 | { | |
| 772 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 773 | } | |
| 774 | }; | |
| 775 | ||
| 776 | template <class T, class R, class P1, class P2, class P3, class P4, class D> | |
| 777 | struct FuncTraits <R (T::*) (P1, P2, P3, P4) const LUABRIDGE_THROWSPEC, D> | |
| 778 | { | |
| 779 | static bool const isMemberFunction = true; | |
| 780 | static bool const isConstMemberFunction = true; | |
| 781 | typedef D DeclType; | |
| 782 | typedef T ClassType; | |
| 783 | typedef R ReturnType; | |
| 784 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4> > > > Params; | |
| 785 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 786 | { | |
| 787 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 788 | } | |
| 789 | }; | |
| 790 | ||
| 791 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class D> | |
| 792 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5) const LUABRIDGE_THROWSPEC, D> | |
| 793 | { | |
| 794 | static bool const isMemberFunction = true; | |
| 795 | static bool const isConstMemberFunction = true; | |
| 796 | typedef D DeclType; | |
| 797 | typedef T ClassType; | |
| 798 | typedef R ReturnType; | |
| 799 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5> > > > > Params; | |
| 800 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 801 | { | |
| 802 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 803 | tvl.tl.tl.tl.tl.hd); | |
| 804 | } | |
| 805 | }; | |
| 806 | ||
| 807 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class D> | |
| 808 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6) const LUABRIDGE_THROWSPEC, D> | |
| 809 | { | |
| 810 | static bool const isMemberFunction = true; | |
| 811 | static bool const isConstMemberFunction = true; | |
| 812 | typedef D DeclType; | |
| 813 | typedef T ClassType; | |
| 814 | typedef R ReturnType; | |
| 815 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > Params; | |
| 816 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 817 | { | |
| 818 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 819 | } | |
| 820 | }; | |
| 821 | ||
| 822 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class D> | |
| 823 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7) const LUABRIDGE_THROWSPEC, D> | |
| 824 | { | |
| 825 | static bool const isMemberFunction = true; | |
| 826 | static bool const isConstMemberFunction = true; | |
| 827 | typedef D DeclType; | |
| 828 | typedef T ClassType; | |
| 829 | typedef R ReturnType; | |
| 830 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > Params; | |
| 831 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 832 | { | |
| 833 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 834 | } | |
| 835 | }; | |
| 836 | ||
| 837 | template <class T, class R, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class D> | |
| 838 | struct FuncTraits <R (T::*) (P1, P2, P3, P4, P5, P6, P7, P8) const LUABRIDGE_THROWSPEC, D> | |
| 839 | { | |
| 840 | static bool const isMemberFunction = true; | |
| 841 | static bool const isConstMemberFunction = true; | |
| 842 | typedef D DeclType; | |
| 843 | typedef T ClassType; | |
| 844 | typedef R ReturnType; | |
| 845 | typedef TypeList <P1, TypeList <P2, TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, TypeList <P8> > > > > > > > Params; | |
| 846 | static R call (T const* obj, D fp, TypeListValues <Params> tvl) | |
| 847 | { | |
| 848 | return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 849 | } | |
| 850 | }; | |
| 851 | ||
| 852 | #endif |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2007, Nathan Reed | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | // These are for Lua versions prior to 5.2.0. | |
| 31 | // | |
| 32 | #if LUA_VERSION_NUM < 502 | |
| 33 | inline int lua_absindex (lua_State* L, int idx) | |
| 34 | { | |
| 35 | if (idx > LUA_REGISTRYINDEX && idx < 0) | |
| 36 | return lua_gettop (L) + idx + 1; | |
| 37 | else | |
| 38 | return idx; | |
| 39 | } | |
| 40 | ||
| 41 | inline void lua_rawgetp (lua_State* L, int idx, void const* p) | |
| 42 | { | |
| 43 | idx = lua_absindex (L, idx); | |
| 44 | lua_pushlightuserdata (L, const_cast <void*> (p)); | |
| 45 | lua_rawget (L,idx); | |
| 46 | } | |
| 47 | ||
| 48 | inline void lua_rawsetp (lua_State* L, int idx, void const* p) | |
| 49 | { | |
| 50 | idx = lua_absindex (L, idx); | |
| 51 | lua_pushlightuserdata (L, const_cast <void*> (p)); | |
| 52 | // put key behind value | |
| 53 | lua_insert (L, -2); | |
| 54 | lua_rawset (L, idx); | |
| 55 | } | |
| 56 | ||
| 57 | #define LUA_OPEQ 1 | |
| 58 | #define LUA_OPLT 2 | |
| 59 | #define LUA_OPLE 3 | |
| 60 | ||
| 61 | inline int lua_compare (lua_State* L, int idx1, int idx2, int op) | |
| 62 | { | |
| 63 | switch (op) | |
| 64 | { | |
| 65 | case LUA_OPEQ: | |
| 66 | return lua_equal (L, idx1, idx2); | |
| 67 | break; | |
| 68 | ||
| 69 | case LUA_OPLT: | |
| 70 | return lua_lessthan (L, idx1, idx2); | |
| 71 | break; | |
| 72 | ||
| 73 | case LUA_OPLE: | |
| 74 | return lua_equal (L, idx1, idx2) || lua_lessthan (L, idx1, idx2); | |
| 75 | break; | |
| 76 | ||
| 77 | default: | |
| 78 | return 0; | |
| 79 | }; | |
| 80 | } | |
| 81 | ||
| 82 | inline int get_length (lua_State* L, int idx) | |
| 83 | { | |
| 84 | return int (lua_objlen (L, idx)); | |
| 85 | } | |
| 86 | ||
| 87 | #else | |
| 88 | inline int get_length (lua_State* L, int idx) | |
| 89 | { | |
| 90 | lua_len (L, idx); | |
| 91 | int len = int (luaL_checknumber (L, -1)); | |
| 92 | lua_pop (L, 1); | |
| 93 | return len; | |
| 94 | } | |
| 95 | ||
| 96 | #endif | |
| 97 | ||
| 98 | #ifndef LUA_OK | |
| 99 | # define LUABRIDGE_LUA_OK 0 | |
| 100 | #else | |
| 101 | # define LUABRIDGE_LUA_OK LUA_OK | |
| 102 | #endif | |
| 103 | ||
| 104 | /** Get a table value, bypassing metamethods. | |
| 105 | */ | |
| 106 | inline void rawgetfield (lua_State* L, int index, char const* key) | |
| 107 | { | |
| 108 | assert (lua_istable (L, index)); | |
| 109 | index = lua_absindex (L, index); | |
| 110 | lua_pushstring (L, key); | |
| 111 | lua_rawget (L, index); | |
| 112 | } | |
| 113 | ||
| 114 | /** Set a table value, bypassing metamethods. | |
| 115 | */ | |
| 116 | inline void rawsetfield (lua_State* L, int index, char const* key) | |
| 117 | { | |
| 118 | assert (lua_istable (L, index)); | |
| 119 | index = lua_absindex (L, index); | |
| 120 | lua_pushstring (L, key); | |
| 121 | lua_insert (L, -2); | |
| 122 | lua_rawset (L, index); | |
| 123 | } | |
| 124 | ||
| 125 | /** Returns true if the value is a full userdata (not light). | |
| 126 | */ | |
| 127 | inline bool isfulluserdata (lua_State* L, int index) | |
| 128 | { | |
| 129 | return lua_isuserdata (L, index) && !lua_islightuserdata (L, index); | |
| 130 | } | |
| 131 | ||
| 132 | /** Test lua_State objects for global equality. | |
| 133 | ||
| 134 | This can determine if two different lua_State objects really point | |
| 135 | to the same global state, such as when using coroutines. | |
| 136 | ||
| 137 | @note This is used for assertions. | |
| 138 | */ | |
| 139 | inline bool equalstates (lua_State* L1, lua_State* L2) | |
| 140 | { | |
| 141 | return lua_topointer (L1, LUA_REGISTRYINDEX) == | |
| 142 | lua_topointer (L2, LUA_REGISTRYINDEX); | |
| 143 | } |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2007, Nathan Reed | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | #ifndef LUABRIDGE_CONSTRUCTOR_HEADER | |
| 31 | #define LUABRIDGE_CONSTRUCTOR_HEADER | |
| 32 | ||
| 33 | /* | |
| 34 | * Constructor generators. These templates allow you to call operator new and | |
| 35 | * pass the contents of a type/value list to the Constructor. Like the | |
| 36 | * function pointer containers, these are only defined up to 8 parameters. | |
| 37 | */ | |
| 38 | ||
| 39 | /** Constructor generators. | |
| 40 | ||
| 41 | These templates call operator new with the contents of a type/value | |
| 42 | list passed to the Constructor with up to 8 parameters. Two versions | |
| 43 | of call() are provided. One performs a regular new, the other performs | |
| 44 | a placement new. | |
| 45 | */ | |
| 46 | template <class T, typename List> | |
| 47 | struct Constructor {}; | |
| 48 | ||
| 49 | template <class T> | |
| 50 | struct Constructor <T, None> | |
| 51 | { | |
| 52 | static T* call (TypeListValues <None> const&) | |
| 53 | { | |
| 54 | return new T; | |
| 55 | } | |
| 56 | static T* call (void* mem, TypeListValues <None> const&) | |
| 57 | { | |
| 58 | return new (mem) T; | |
| 59 | } | |
| 60 | }; | |
| 61 | ||
| 62 | template <class T, class P1> | |
| 63 | struct Constructor <T, TypeList <P1> > | |
| 64 | { | |
| 65 | static T* call (const TypeListValues<TypeList <P1> > &tvl) | |
| 66 | { | |
| 67 | return new T(tvl.hd); | |
| 68 | } | |
| 69 | static T* call (void* mem, const TypeListValues<TypeList <P1> > &tvl) | |
| 70 | { | |
| 71 | return new (mem) T(tvl.hd); | |
| 72 | } | |
| 73 | }; | |
| 74 | ||
| 75 | template <class T, class P1, class P2> | |
| 76 | struct Constructor <T, TypeList <P1, TypeList <P2> > > | |
| 77 | { | |
| 78 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl) | |
| 79 | { | |
| 80 | return new T(tvl.hd, tvl.tl.hd); | |
| 81 | } | |
| 82 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2> > > &tvl) | |
| 83 | { | |
| 84 | return new (mem) T(tvl.hd, tvl.tl.hd); | |
| 85 | } | |
| 86 | }; | |
| 87 | ||
| 88 | template <class T, class P1, class P2, class P3> | |
| 89 | struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3> > > > | |
| 90 | { | |
| 91 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2, | |
| 92 | TypeList <P3> > > > &tvl) | |
| 93 | { | |
| 94 | return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 95 | } | |
| 96 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2, | |
| 97 | TypeList <P3> > > > &tvl) | |
| 98 | { | |
| 99 | return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); | |
| 100 | } | |
| 101 | }; | |
| 102 | ||
| 103 | template <class T, class P1, class P2, class P3, class P4> | |
| 104 | struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3, | |
| 105 | TypeList <P4> > > > > | |
| 106 | { | |
| 107 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2, | |
| 108 | TypeList <P3, TypeList <P4> > > > > &tvl) | |
| 109 | { | |
| 110 | return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 111 | } | |
| 112 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2, | |
| 113 | TypeList <P3, TypeList <P4> > > > > &tvl) | |
| 114 | { | |
| 115 | return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); | |
| 116 | } | |
| 117 | }; | |
| 118 | ||
| 119 | template <class T, class P1, class P2, class P3, class P4, | |
| 120 | class P5> | |
| 121 | struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3, | |
| 122 | TypeList <P4, TypeList <P5> > > > > > | |
| 123 | { | |
| 124 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2, | |
| 125 | TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl) | |
| 126 | { | |
| 127 | return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 128 | tvl.tl.tl.tl.tl.hd); | |
| 129 | } | |
| 130 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2, | |
| 131 | TypeList <P3, TypeList <P4, TypeList <P5> > > > > > &tvl) | |
| 132 | { | |
| 133 | return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 134 | tvl.tl.tl.tl.tl.hd); | |
| 135 | } | |
| 136 | }; | |
| 137 | ||
| 138 | template <class T, class P1, class P2, class P3, class P4, | |
| 139 | class P5, class P6> | |
| 140 | struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3, | |
| 141 | TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > | |
| 142 | { | |
| 143 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2, | |
| 144 | TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl) | |
| 145 | { | |
| 146 | return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 147 | tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 148 | } | |
| 149 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2, | |
| 150 | TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6> > > > > > > &tvl) | |
| 151 | { | |
| 152 | return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 153 | tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd); | |
| 154 | } | |
| 155 | }; | |
| 156 | ||
| 157 | template <class T, class P1, class P2, class P3, class P4, | |
| 158 | class P5, class P6, class P7> | |
| 159 | struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3, | |
| 160 | TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7> > > > > > > > | |
| 161 | { | |
| 162 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2, | |
| 163 | TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, | |
| 164 | TypeList <P7> > > > > > > > &tvl) | |
| 165 | { | |
| 166 | return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 167 | tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, | |
| 168 | tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 169 | } | |
| 170 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2, | |
| 171 | TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, | |
| 172 | TypeList <P7> > > > > > > > &tvl) | |
| 173 | { | |
| 174 | return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 175 | tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, | |
| 176 | tvl.tl.tl.tl.tl.tl.tl.hd); | |
| 177 | } | |
| 178 | }; | |
| 179 | ||
| 180 | template <class T, class P1, class P2, class P3, class P4, | |
| 181 | class P5, class P6, class P7, class P8> | |
| 182 | struct Constructor <T, TypeList <P1, TypeList <P2, TypeList <P3, | |
| 183 | TypeList <P4, TypeList <P5, TypeList <P6, TypeList <P7, | |
| 184 | TypeList <P8> > > > > > > > > | |
| 185 | { | |
| 186 | static T* call (const TypeListValues<TypeList <P1, TypeList <P2, | |
| 187 | TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, | |
| 188 | TypeList <P7, TypeList <P8> > > > > > > > > &tvl) | |
| 189 | { | |
| 190 | return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 191 | tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, | |
| 192 | tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 193 | } | |
| 194 | static T* call (void* mem, const TypeListValues<TypeList <P1, TypeList <P2, | |
| 195 | TypeList <P3, TypeList <P4, TypeList <P5, TypeList <P6, | |
| 196 | TypeList <P7, TypeList <P8> > > > > > > > > &tvl) | |
| 197 | { | |
| 198 | return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, | |
| 199 | tvl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.hd, | |
| 200 | tvl.tl.tl.tl.tl.tl.tl.hd, tvl.tl.tl.tl.tl.tl.tl.tl.hd); | |
| 201 | } | |
| 202 | }; | |
| 203 | ||
| 204 | #endif |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2007, Nathan Reed | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | //------------------------------------------------------------------------------ | |
| 31 | /** | |
| 32 | Receive the lua_State* as an argument. | |
| 33 | */ | |
| 34 | template <> | |
| 35 | struct Stack <lua_State*> | |
| 36 | { | |
| 37 | static lua_State* get (lua_State* L, int) | |
| 38 | { | |
| 39 | return L; | |
| 40 | } | |
| 41 | }; | |
| 42 | ||
| 43 | //------------------------------------------------------------------------------ | |
| 44 | /** | |
| 45 | Push a lua_CFunction. | |
| 46 | */ | |
| 47 | template <> | |
| 48 | struct Stack <lua_CFunction> | |
| 49 | { | |
| 50 | static void push (lua_State* L, lua_CFunction f) | |
| 51 | { | |
| 52 | lua_pushcfunction (L, f); | |
| 53 | } | |
| 54 | ||
| 55 | static lua_CFunction get (lua_State* L, int index) | |
| 56 | { | |
| 57 | return lua_tocfunction (L, index); | |
| 58 | } | |
| 59 | }; | |
| 60 | ||
| 61 | //------------------------------------------------------------------------------ | |
| 62 | /** | |
| 63 | Stack specialization for `int`. | |
| 64 | */ | |
| 65 | template <> | |
| 66 | struct Stack <int> | |
| 67 | { | |
| 68 | static inline void push (lua_State* L, int value) | |
| 69 | { | |
| 70 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 71 | } | |
| 72 | ||
| 73 | static inline int get (lua_State* L, int index) | |
| 74 | { | |
| 75 | return static_cast <int> (luaL_checkinteger (L, index)); | |
| 76 | } | |
| 77 | }; | |
| 78 | ||
| 79 | template <> | |
| 80 | struct Stack <int const&> | |
| 81 | { | |
| 82 | static inline void push (lua_State* L, int value) | |
| 83 | { | |
| 84 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 85 | } | |
| 86 | ||
| 87 | static inline int get (lua_State* L, int index) | |
| 88 | { | |
| 89 | return static_cast <int > (luaL_checknumber (L, index)); | |
| 90 | } | |
| 91 | }; | |
| 92 | //------------------------------------------------------------------------------ | |
| 93 | /** | |
| 94 | Stack specialization for `unsigned int`. | |
| 95 | */ | |
| 96 | template <> | |
| 97 | struct Stack <unsigned int> | |
| 98 | { | |
| 99 | static inline void push (lua_State* L, unsigned int value) | |
| 100 | { | |
| 101 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 102 | } | |
| 103 | ||
| 104 | static inline unsigned int get (lua_State* L, int index) | |
| 105 | { | |
| 106 | return static_cast <unsigned int> (luaL_checkinteger (L, index)); | |
| 107 | } | |
| 108 | }; | |
| 109 | ||
| 110 | template <> | |
| 111 | struct Stack <unsigned int const&> | |
| 112 | { | |
| 113 | static inline void push (lua_State* L, unsigned int value) | |
| 114 | { | |
| 115 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 116 | } | |
| 117 | ||
| 118 | static inline unsigned int get (lua_State* L, int index) | |
| 119 | { | |
| 120 | return static_cast <unsigned int > (luaL_checknumber (L, index)); | |
| 121 | } | |
| 122 | }; | |
| 123 | ||
| 124 | //------------------------------------------------------------------------------ | |
| 125 | /** | |
| 126 | Stack specialization for `unsigned char`. | |
| 127 | */ | |
| 128 | template <> | |
| 129 | struct Stack <unsigned char> | |
| 130 | { | |
| 131 | static inline void push (lua_State* L, unsigned char value) | |
| 132 | { | |
| 133 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 134 | } | |
| 135 | ||
| 136 | static inline unsigned char get (lua_State* L, int index) | |
| 137 | { | |
| 138 | return static_cast <unsigned char> (luaL_checkinteger (L, index)); | |
| 139 | } | |
| 140 | }; | |
| 141 | ||
| 142 | template <> | |
| 143 | struct Stack <unsigned char const&> | |
| 144 | { | |
| 145 | static inline void push (lua_State* L, unsigned char value) | |
| 146 | { | |
| 147 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 148 | } | |
| 149 | ||
| 150 | static inline unsigned char get (lua_State* L, int index) | |
| 151 | { | |
| 152 | return static_cast <unsigned char> (luaL_checknumber (L, index)); | |
| 153 | } | |
| 154 | }; | |
| 155 | ||
| 156 | //------------------------------------------------------------------------------ | |
| 157 | /** | |
| 158 | Stack specialization for `short`. | |
| 159 | */ | |
| 160 | template <> | |
| 161 | struct Stack <short> | |
| 162 | { | |
| 163 | static inline void push (lua_State* L, short value) | |
| 164 | { | |
| 165 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 166 | } | |
| 167 | ||
| 168 | static inline short get (lua_State* L, int index) | |
| 169 | { | |
| 170 | return static_cast <short> (luaL_checkinteger (L, index)); | |
| 171 | } | |
| 172 | }; | |
| 173 | ||
| 174 | template <> | |
| 175 | struct Stack <short const&> | |
| 176 | { | |
| 177 | static inline void push (lua_State* L, short value) | |
| 178 | { | |
| 179 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 180 | } | |
| 181 | ||
| 182 | static inline short get (lua_State* L, int index) | |
| 183 | { | |
| 184 | return static_cast <short> (luaL_checknumber (L, index)); | |
| 185 | } | |
| 186 | }; | |
| 187 | ||
| 188 | //------------------------------------------------------------------------------ | |
| 189 | /** | |
| 190 | Stack specialization for `unsigned short`. | |
| 191 | */ | |
| 192 | template <> | |
| 193 | struct Stack <unsigned short> | |
| 194 | { | |
| 195 | static inline void push (lua_State* L, unsigned short value) | |
| 196 | { | |
| 197 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 198 | } | |
| 199 | ||
| 200 | static inline unsigned short get (lua_State* L, int index) | |
| 201 | { | |
| 202 | return static_cast <unsigned short> (luaL_checkinteger (L, index)); | |
| 203 | } | |
| 204 | }; | |
| 205 | ||
| 206 | template <> | |
| 207 | struct Stack <unsigned short const&> | |
| 208 | { | |
| 209 | static inline void push (lua_State* L, unsigned short value) | |
| 210 | { | |
| 211 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 212 | } | |
| 213 | ||
| 214 | static inline unsigned short get (lua_State* L, int index) | |
| 215 | { | |
| 216 | return static_cast <unsigned short> (luaL_checknumber (L, index)); | |
| 217 | } | |
| 218 | }; | |
| 219 | ||
| 220 | //------------------------------------------------------------------------------ | |
| 221 | /** | |
| 222 | Stack specialization for `long`. | |
| 223 | */ | |
| 224 | template <> | |
| 225 | struct Stack <long> | |
| 226 | { | |
| 227 | static inline void push (lua_State* L, long value) | |
| 228 | { | |
| 229 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 230 | } | |
| 231 | ||
| 232 | static inline long get (lua_State* L, int index) | |
| 233 | { | |
| 234 | return static_cast <long> (luaL_checkinteger (L, index)); | |
| 235 | } | |
| 236 | }; | |
| 237 | ||
| 238 | template <> | |
| 239 | struct Stack <long const&> | |
| 240 | { | |
| 241 | static inline void push (lua_State* L, long value) | |
| 242 | { | |
| 243 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 244 | } | |
| 245 | ||
| 246 | static inline long get (lua_State* L, int index) | |
| 247 | { | |
| 248 | return static_cast <long> (luaL_checknumber (L, index)); | |
| 249 | } | |
| 250 | }; | |
| 251 | ||
| 252 | //------------------------------------------------------------------------------ | |
| 253 | /** | |
| 254 | Stack specialization for `unsigned long`. | |
| 255 | */ | |
| 256 | template <> | |
| 257 | struct Stack <unsigned long> | |
| 258 | { | |
| 259 | static inline void push (lua_State* L, unsigned long value) | |
| 260 | { | |
| 261 | lua_pushinteger (L, static_cast <lua_Integer> (value)); | |
| 262 | } | |
| 263 | ||
| 264 | static inline unsigned long get (lua_State* L, int index) | |
| 265 | { | |
| 266 | return static_cast <unsigned long> (luaL_checkinteger (L, index)); | |
| 267 | } | |
| 268 | }; | |
| 269 | ||
| 270 | template <> | |
| 271 | struct Stack <unsigned long const&> | |
| 272 | { | |
| 273 | static inline void push (lua_State* L, unsigned long value) | |
| 274 | { | |
| 275 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 276 | } | |
| 277 | ||
| 278 | static inline unsigned long get (lua_State* L, int index) | |
| 279 | { | |
| 280 | return static_cast <unsigned long> (luaL_checknumber (L, index)); | |
| 281 | } | |
| 282 | }; | |
| 283 | ||
| 284 | //------------------------------------------------------------------------------ | |
| 285 | /** | |
| 286 | Stack specialization for `float`. | |
| 287 | */ | |
| 288 | template <> | |
| 289 | struct Stack <float> | |
| 290 | { | |
| 291 | static inline void push (lua_State* L, float value) | |
| 292 | { | |
| 293 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 294 | } | |
| 295 | ||
| 296 | static inline float get (lua_State* L, int index) | |
| 297 | { | |
| 298 | return static_cast <float> (luaL_checknumber (L, index)); | |
| 299 | } | |
| 300 | }; | |
| 301 | ||
| 302 | template <> | |
| 303 | struct Stack <float const&> | |
| 304 | { | |
| 305 | static inline void push (lua_State* L, float value) | |
| 306 | { | |
| 307 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 308 | } | |
| 309 | ||
| 310 | static inline float get (lua_State* L, int index) | |
| 311 | { | |
| 312 | return static_cast <float> (luaL_checknumber (L, index)); | |
| 313 | } | |
| 314 | }; | |
| 315 | ||
| 316 | //------------------------------------------------------------------------------ | |
| 317 | /** | |
| 318 | Stack specialization for `double`. | |
| 319 | */ | |
| 320 | template <> struct Stack <double> | |
| 321 | { | |
| 322 | static inline void push (lua_State* L, double value) | |
| 323 | { | |
| 324 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 325 | } | |
| 326 | ||
| 327 | static inline double get (lua_State* L, int index) | |
| 328 | { | |
| 329 | return static_cast <double> (luaL_checknumber (L, index)); | |
| 330 | } | |
| 331 | }; | |
| 332 | ||
| 333 | template <> struct Stack <double const&> | |
| 334 | { | |
| 335 | static inline void push (lua_State* L, double value) | |
| 336 | { | |
| 337 | lua_pushnumber (L, static_cast <lua_Number> (value)); | |
| 338 | } | |
| 339 | ||
| 340 | static inline double get (lua_State* L, int index) | |
| 341 | { | |
| 342 | return static_cast <double> (luaL_checknumber (L, index)); | |
| 343 | } | |
| 344 | }; | |
| 345 | ||
| 346 | //------------------------------------------------------------------------------ | |
| 347 | /** | |
| 348 | Stack specialization for `bool`. | |
| 349 | */ | |
| 350 | template <> | |
| 351 | struct Stack <bool> { | |
| 352 | static inline void push (lua_State* L, bool value) | |
| 353 | { | |
| 354 | lua_pushboolean (L, value ? 1 : 0); | |
| 355 | } | |
| 356 | ||
| 357 | static inline bool get (lua_State* L, int index) | |
| 358 | { | |
| 359 | return lua_toboolean (L, index) ? true : false; | |
| 360 | } | |
| 361 | }; | |
| 362 | ||
| 363 | template <> | |
| 364 | struct Stack <bool const&> { | |
| 365 | static inline void push (lua_State* L, bool value) | |
| 366 | { | |
| 367 | lua_pushboolean (L, value ? 1 : 0); | |
| 368 | } | |
| 369 | ||
| 370 | static inline bool get (lua_State* L, int index) | |
| 371 | { | |
| 372 | return lua_toboolean (L, index) ? true : false; | |
| 373 | } | |
| 374 | }; | |
| 375 | ||
| 376 | //------------------------------------------------------------------------------ | |
| 377 | /** | |
| 378 | Stack specialization for `char`. | |
| 379 | */ | |
| 380 | template <> | |
| 381 | struct Stack <char> | |
| 382 | { | |
| 383 | static inline void push (lua_State* L, char value) | |
| 384 | { | |
| 385 | char str [2] = { value, 0 }; | |
| 386 | lua_pushstring (L, str); | |
| 387 | } | |
| 388 | ||
| 389 | static inline char get (lua_State* L, int index) | |
| 390 | { | |
| 391 | return luaL_checkstring (L, index) [0]; | |
| 392 | } | |
| 393 | }; | |
| 394 | ||
| 395 | template <> | |
| 396 | struct Stack <char const&> | |
| 397 | { | |
| 398 | static inline void push (lua_State* L, char value) | |
| 399 | { | |
| 400 | char str [2] = { value, 0 }; | |
| 401 | lua_pushstring (L, str); | |
| 402 | } | |
| 403 | ||
| 404 | static inline char get (lua_State* L, int index) | |
| 405 | { | |
| 406 | return luaL_checkstring (L, index) [0]; | |
| 407 | } | |
| 408 | }; | |
| 409 | ||
| 410 | //------------------------------------------------------------------------------ | |
| 411 | /** | |
| 412 | Stack specialization for `float`. | |
| 413 | */ | |
| 414 | template <> | |
| 415 | struct Stack <char const*> | |
| 416 | { | |
| 417 | static inline void push (lua_State* L, char const* str) | |
| 418 | { | |
| 419 | if (str != 0) | |
| 420 | lua_pushstring (L, str); | |
| 421 | else | |
| 422 | lua_pushnil (L); | |
| 423 | } | |
| 424 | ||
| 425 | static inline char const* get (lua_State* L, int index) | |
| 426 | { | |
| 427 | return lua_isnil (L, index) ? 0 : luaL_checkstring (L, index); | |
| 428 | } | |
| 429 | }; | |
| 430 | ||
| 431 | //------------------------------------------------------------------------------ | |
| 432 | /** | |
| 433 | Stack specialization for `std::string`. | |
| 434 | */ | |
| 435 | template <> | |
| 436 | struct Stack <std::string> | |
| 437 | { | |
| 438 | static inline void push (lua_State* L, std::string const& str) | |
| 439 | { | |
| 440 | lua_pushlstring (L, str.c_str (), str.size()); | |
| 441 | } | |
| 442 | ||
| 443 | static inline std::string get (lua_State* L, int index) | |
| 444 | { | |
| 445 | size_t len; | |
| 446 | const char *str = luaL_checklstring(L, index, &len); | |
| 447 | return std::string (str, len); | |
| 448 | } | |
| 449 | }; | |
| 450 | ||
| 451 | //------------------------------------------------------------------------------ | |
| 452 | /** | |
| 453 | Stack specialization for `std::string const&`. | |
| 454 | */ | |
| 455 | template <> | |
| 456 | struct Stack <std::string const&> | |
| 457 | { | |
| 458 | static inline void push (lua_State* L, std::string const& str) | |
| 459 | { | |
| 460 | lua_pushstring (L, str.c_str()); | |
| 461 | } | |
| 462 | ||
| 463 | static inline std::string get (lua_State* L, int index) | |
| 464 | { | |
| 465 | size_t len; | |
| 466 | const char *str = luaL_checklstring(L, index, &len); | |
| 467 | return std::string (str, len); | |
| 468 | } | |
| 469 | }; |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | #include <sstream> | |
| 2 | #include <string> | |
| 3 | ||
| 4 | std::string dumpLuaState(lua_State *L) { | |
| 5 | std::stringstream ostr; | |
| 6 | int i; | |
| 7 | int top = lua_gettop(L); | |
| 8 | ostr << "top=" << top << ":\n"; | |
| 9 | for (i = 1; i <= top; ++i) { | |
| 10 | int t = lua_type(L, i); | |
| 11 | switch(t) { | |
| 12 | case LUA_TSTRING: | |
| 13 | ostr << " " << i << ": '" << lua_tostring(L, i) << "'\n"; | |
| 14 | break; | |
| 15 | case LUA_TBOOLEAN: | |
| 16 | ostr << " " << i << ": " << | |
| 17 | (lua_toboolean(L, i) ? "true" : "false") << "\n"; | |
| 18 | break; | |
| 19 | case LUA_TNUMBER: | |
| 20 | ostr << " " << i << ": " << lua_tonumber(L, i) << "\n"; | |
| 21 | break; | |
| 22 | default: | |
| 23 | ostr << " " << i << ": TYPE=" << lua_typename(L, t) << "\n"; | |
| 24 | break; | |
| 25 | } | |
| 26 | } | |
| 27 | return ostr.str(); | |
| 28 | } |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| r0 | r31046 | |
|---|---|---|
| 1 | //------------------------------------------------------------------------------ | |
| 2 | /* | |
| 3 | https://github.com/vinniefalco/LuaBridge | |
| 4 | ||
| 5 | Copyright 2012, Vinnie Falco <vinnie.falco@gmail.com> | |
| 6 | Copyright 2007, Nathan Reed | |
| 7 | ||
| 8 | License: The MIT License (http://www.opensource.org/licenses/mit-license.php) | |
| 9 | ||
| 10 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
| 11 | of this software and associated documentation files (the "Software"), to deal | |
| 12 | in the Software without restriction, including without limitation the rights | |
| 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| 14 | copies of the Software, and to permit persons to whom the Software is | |
| 15 | furnished to do so, subject to the following conditions: | |
| 16 | ||
| 17 | The above copyright notice and this permission notice shall be included in all | |
| 18 | copies or substantial portions of the Software. | |
| 19 | ||
| 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| 26 | SOFTWARE. | |
| 27 | */ | |
| 28 | //============================================================================== | |
| 29 | ||
| 30 | #ifndef LUABRIDGE_LUABRIDGE_HEADER | |
| 31 | #define LUABRIDGE_LUABRIDGE_HEADER | |
| 32 | ||
| 33 | // All #include dependencies are listed here | |
| 34 | // instead of in the individual header files. | |
| 35 | // | |
| 36 | #include <cassert> | |
| 37 | #include <sstream> | |
| 38 | #include <stdexcept> | |
| 39 | #include <string> | |
| 40 | #include <typeinfo> | |
| 41 | ||
| 42 | #define LUABRIDGE_MAJOR_VERSION 2 | |
| 43 | #define LUABRIDGE_MINOR_VERSION 0 | |
| 44 | #define LUABRIDGE_VERSION 200 | |
| 45 | ||
| 46 | namespace luabridge | |
| 47 | { | |
| 48 | ||
| 49 | // Forward declaration | |
| 50 | // | |
| 51 | template <class T> | |
| 52 | struct Stack; | |
| 53 | ||
| 54 | #include "detail/LuaHelpers.h" | |
| 55 | ||
| 56 | #include "detail/TypeTraits.h" | |
| 57 | #include "detail/TypeList.h" | |
| 58 | #include "detail/FuncTraits.h" | |
| 59 | #include "detail/Constructor.h" | |
| 60 | #include "detail/Stack.h" | |
| 61 | #include "detail/ClassInfo.h" | |
| 62 | ||
| 63 | class LuaRef; | |
| 64 | ||
| 65 | #include "detail/LuaException.h" | |
| 66 | #include "detail/LuaRef.h" | |
| 67 | #include "detail/Iterator.h" | |
| 68 | ||
| 69 | //------------------------------------------------------------------------------ | |
| 70 | /** | |
| 71 | security options. | |
| 72 | */ | |
| 73 | class Security | |
| 74 | { | |
| 75 | public: | |
| 76 | static bool hideMetatables () | |
| 77 | { | |
| 78 | return getSettings().hideMetatables; | |
| 79 | } | |
| 80 | ||
| 81 | static void setHideMetatables (bool shouldHide) | |
| 82 | { | |
| 83 | getSettings().hideMetatables = shouldHide; | |
| 84 | } | |
| 85 | ||
| 86 | private: | |
| 87 | struct Settings | |
| 88 | { | |
| 89 | Settings () : hideMetatables (true) | |
| 90 | { | |
| 91 | } | |
| 92 | ||
| 93 | bool hideMetatables; | |
| 94 | }; | |
| 95 | ||
| 96 | static Settings& getSettings () | |
| 97 | { | |
| 98 | static Settings settings; | |
| 99 | return settings; | |
| 100 | } | |
| 101 | }; | |
| 102 | ||
| 103 | #include "detail/Userdata.h" | |
| 104 | #include "detail/CFunctions.h" | |
| 105 | #include "detail/Namespace.h" | |
| 106 | ||
| 107 | //------------------------------------------------------------------------------ | |
| 108 | /** | |
| 109 | Push an object onto the Lua stack. | |
| 110 | */ | |
| 111 | template <class T> | |
| 112 | inline void push (lua_State* L, T t) | |
| 113 | { | |
| 114 | Stack <T>::push (L, t); | |
| 115 | } | |
| 116 | ||
| 117 | //------------------------------------------------------------------------------ | |
| 118 | /** | |
| 119 | Set a global value in the lua_State. | |
| 120 | ||
| 121 | @note This works on any type specialized by `Stack`, including `LuaRef` and | |
| 122 | its table proxies. | |
| 123 | */ | |
| 124 | template <class T> | |
| 125 | inline void setGlobal (lua_State* L, T t, char const* name) | |
| 126 | { | |
| 127 | push (L, t); | |
| 128 | lua_setglobal (L, name); | |
| 129 | } | |
| 130 | ||
| 131 | //------------------------------------------------------------------------------ | |
| 132 | /** | |
| 133 | Change whether or not metatables are hidden (on by default). | |
| 134 | */ | |
| 135 | inline void setHideMetatables (bool shouldHide) | |
| 136 | { | |
| 137 | Security::setHideMetatables (shouldHide); | |
| 138 | } | |
| 139 | ||
| 140 | } | |
| 141 | ||
| 142 | #endif |
| Added: svn:mime-type + text/plain Added: svn:eol-style + native |
| Previous | 199869 Revisions | Next |