From d1f7935ee29e2063e92374917c84c78538922afd Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 11 May 2013 01:29:58 -0700 Subject: [PATCH] ...trying out boost with luabind --- CMakeLists.txt | 12 +- common/luabridge/LuaBridge.h | 4759 ----------------- common/luabridge/RefCountedObject.h | 348 -- common/luabridge/RefCountedPtr.h | 248 - luabind/CMakeLists.txt | 34 + luabind/luabind/adopt_policy.hpp | 142 + luabind/luabind/back_reference.hpp | 112 + luabind/luabind/back_reference_fwd.hpp | 37 + luabind/luabind/class.hpp | 879 +++ luabind/luabind/class_info.hpp | 50 + luabind/luabind/config.hpp | 128 + luabind/luabind/container_policy.hpp | 143 + luabind/luabind/copy_policy.hpp | 61 + luabind/luabind/dependency_policy.hpp | 119 + luabind/luabind/detail/calc_arity.hpp | 61 + luabind/luabind/detail/call.hpp | 323 ++ luabind/luabind/detail/call_function.hpp | 443 ++ luabind/luabind/detail/call_member.hpp | 363 ++ .../luabind/detail/call_operator_iterate.hpp | 66 + luabind/luabind/detail/class_cache.hpp | 89 + luabind/luabind/detail/class_registry.hpp | 85 + luabind/luabind/detail/class_rep.hpp | 213 + luabind/luabind/detail/compute_score.hpp | 73 + luabind/luabind/detail/constructor.hpp | 111 + luabind/luabind/detail/conversion_storage.hpp | 41 + luabind/luabind/detail/convert_to_lua.hpp | 92 + luabind/luabind/detail/debug.hpp | 55 + luabind/luabind/detail/decorate_type.hpp | 266 + luabind/luabind/detail/deduce_signature.hpp | 118 + luabind/luabind/detail/enum_maker.hpp | 123 + luabind/luabind/detail/format_signature.hpp | 148 + luabind/luabind/detail/garbage_collector.hpp | 53 + luabind/luabind/detail/has_get_pointer.hpp | 107 + luabind/luabind/detail/inheritance.hpp | 168 + luabind/luabind/detail/instance_holder.hpp | 131 + luabind/luabind/detail/is_indirect_const.hpp | 70 + luabind/luabind/detail/link_compatibility.hpp | 60 + luabind/luabind/detail/make_instance.hpp | 105 + luabind/luabind/detail/most_derived.hpp | 44 + luabind/luabind/detail/object_call.hpp | 52 + luabind/luabind/detail/object_funs.hpp | 224 + luabind/luabind/detail/object_rep.hpp | 132 + luabind/luabind/detail/open.hpp | 45 + luabind/luabind/detail/operator_id.hpp | 79 + luabind/luabind/detail/other.hpp | 119 + luabind/luabind/detail/pcall.hpp | 36 + luabind/luabind/detail/pointee_sizeof.hpp | 54 + luabind/luabind/detail/pointee_typeid.hpp | 40 + luabind/luabind/detail/policy.hpp | 1021 ++++ luabind/luabind/detail/primitives.hpp | 85 + luabind/luabind/detail/property.hpp | 33 + luabind/luabind/detail/ref.hpp | 112 + luabind/luabind/detail/signature_match.hpp | 61 + luabind/luabind/detail/stack_utils.hpp | 52 + luabind/luabind/detail/typetraits.hpp | 190 + luabind/luabind/detail/yes_no.hpp | 34 + luabind/luabind/discard_result_policy.hpp | 72 + luabind/luabind/error.hpp | 93 + luabind/luabind/exception_handler.hpp | 110 + luabind/luabind/from_stack.hpp | 42 + luabind/luabind/function.hpp | 62 + luabind/luabind/get_main_thread.hpp | 16 + luabind/luabind/get_pointer.hpp | 39 + luabind/luabind/handle.hpp | 144 + luabind/luabind/iterator_policy.hpp | 112 + luabind/luabind/lua_include.hpp | 39 + luabind/luabind/luabind.hpp | 32 + luabind/luabind/make_function.hpp | 123 + luabind/luabind/nil.hpp | 40 + luabind/luabind/object.hpp | 1410 +++++ luabind/luabind/open.hpp | 36 + luabind/luabind/operator.hpp | 355 ++ luabind/luabind/out_value_policy.hpp | 280 + luabind/luabind/prefix.hpp | 31 + luabind/luabind/raw_policy.hpp | 85 + .../luabind/return_reference_to_policy.hpp | 73 + luabind/luabind/scope.hpp | 103 + luabind/luabind/shared_ptr_converter.hpp | 83 + luabind/luabind/tag_function.hpp | 88 + luabind/luabind/typeid.hpp | 65 + luabind/luabind/value_wrapper.hpp | 168 + luabind/luabind/version.hpp | 16 + luabind/luabind/weak_ref.hpp | 59 + luabind/luabind/wrapper_base.hpp | 190 + luabind/luabind/yield_policy.hpp | 67 + luabind/src/class.cpp | 337 ++ luabind/src/class_info.cpp | 120 + luabind/src/class_registry.cpp | 166 + luabind/src/class_rep.cpp | 395 ++ luabind/src/create_class.cpp | 140 + luabind/src/error.cpp | 78 + luabind/src/exception_handler.cpp | 87 + luabind/src/function.cpp | 136 + luabind/src/inheritance.cpp | 258 + luabind/src/link_compatibility.cpp | 43 + luabind/src/object_rep.cpp | 272 + luabind/src/open.cpp | 199 + luabind/src/pcall.cpp | 60 + luabind/src/scope.cpp | 209 + luabind/src/stack_content_by_name.cpp | 59 + luabind/src/weak_ref.cpp | 157 + luabind/src/wrapper_base.cpp | 55 + zone/CMakeLists.txt | 5 + zone/lua_entity.cpp | 11 - zone/lua_mob.cpp | 9 + zone/lua_mob.h | 3 + zone/lua_parser.cpp | 66 +- 107 files changed, 14352 insertions(+), 5395 deletions(-) delete mode 100644 common/luabridge/LuaBridge.h delete mode 100644 common/luabridge/RefCountedObject.h delete mode 100644 common/luabridge/RefCountedPtr.h create mode 100644 luabind/CMakeLists.txt create mode 100644 luabind/luabind/adopt_policy.hpp create mode 100644 luabind/luabind/back_reference.hpp create mode 100644 luabind/luabind/back_reference_fwd.hpp create mode 100644 luabind/luabind/class.hpp create mode 100644 luabind/luabind/class_info.hpp create mode 100644 luabind/luabind/config.hpp create mode 100644 luabind/luabind/container_policy.hpp create mode 100644 luabind/luabind/copy_policy.hpp create mode 100644 luabind/luabind/dependency_policy.hpp create mode 100644 luabind/luabind/detail/calc_arity.hpp create mode 100644 luabind/luabind/detail/call.hpp create mode 100644 luabind/luabind/detail/call_function.hpp create mode 100644 luabind/luabind/detail/call_member.hpp create mode 100644 luabind/luabind/detail/call_operator_iterate.hpp create mode 100644 luabind/luabind/detail/class_cache.hpp create mode 100644 luabind/luabind/detail/class_registry.hpp create mode 100644 luabind/luabind/detail/class_rep.hpp create mode 100644 luabind/luabind/detail/compute_score.hpp create mode 100644 luabind/luabind/detail/constructor.hpp create mode 100644 luabind/luabind/detail/conversion_storage.hpp create mode 100644 luabind/luabind/detail/convert_to_lua.hpp create mode 100644 luabind/luabind/detail/debug.hpp create mode 100644 luabind/luabind/detail/decorate_type.hpp create mode 100644 luabind/luabind/detail/deduce_signature.hpp create mode 100644 luabind/luabind/detail/enum_maker.hpp create mode 100644 luabind/luabind/detail/format_signature.hpp create mode 100644 luabind/luabind/detail/garbage_collector.hpp create mode 100644 luabind/luabind/detail/has_get_pointer.hpp create mode 100644 luabind/luabind/detail/inheritance.hpp create mode 100644 luabind/luabind/detail/instance_holder.hpp create mode 100644 luabind/luabind/detail/is_indirect_const.hpp create mode 100644 luabind/luabind/detail/link_compatibility.hpp create mode 100644 luabind/luabind/detail/make_instance.hpp create mode 100644 luabind/luabind/detail/most_derived.hpp create mode 100644 luabind/luabind/detail/object_call.hpp create mode 100644 luabind/luabind/detail/object_funs.hpp create mode 100644 luabind/luabind/detail/object_rep.hpp create mode 100644 luabind/luabind/detail/open.hpp create mode 100644 luabind/luabind/detail/operator_id.hpp create mode 100644 luabind/luabind/detail/other.hpp create mode 100644 luabind/luabind/detail/pcall.hpp create mode 100644 luabind/luabind/detail/pointee_sizeof.hpp create mode 100644 luabind/luabind/detail/pointee_typeid.hpp create mode 100644 luabind/luabind/detail/policy.hpp create mode 100644 luabind/luabind/detail/primitives.hpp create mode 100644 luabind/luabind/detail/property.hpp create mode 100644 luabind/luabind/detail/ref.hpp create mode 100644 luabind/luabind/detail/signature_match.hpp create mode 100644 luabind/luabind/detail/stack_utils.hpp create mode 100644 luabind/luabind/detail/typetraits.hpp create mode 100644 luabind/luabind/detail/yes_no.hpp create mode 100644 luabind/luabind/discard_result_policy.hpp create mode 100644 luabind/luabind/error.hpp create mode 100644 luabind/luabind/exception_handler.hpp create mode 100644 luabind/luabind/from_stack.hpp create mode 100644 luabind/luabind/function.hpp create mode 100644 luabind/luabind/get_main_thread.hpp create mode 100644 luabind/luabind/get_pointer.hpp create mode 100644 luabind/luabind/handle.hpp create mode 100644 luabind/luabind/iterator_policy.hpp create mode 100644 luabind/luabind/lua_include.hpp create mode 100644 luabind/luabind/luabind.hpp create mode 100644 luabind/luabind/make_function.hpp create mode 100644 luabind/luabind/nil.hpp create mode 100644 luabind/luabind/object.hpp create mode 100644 luabind/luabind/open.hpp create mode 100644 luabind/luabind/operator.hpp create mode 100644 luabind/luabind/out_value_policy.hpp create mode 100644 luabind/luabind/prefix.hpp create mode 100644 luabind/luabind/raw_policy.hpp create mode 100644 luabind/luabind/return_reference_to_policy.hpp create mode 100644 luabind/luabind/scope.hpp create mode 100644 luabind/luabind/shared_ptr_converter.hpp create mode 100644 luabind/luabind/tag_function.hpp create mode 100644 luabind/luabind/typeid.hpp create mode 100644 luabind/luabind/value_wrapper.hpp create mode 100644 luabind/luabind/version.hpp create mode 100644 luabind/luabind/weak_ref.hpp create mode 100644 luabind/luabind/wrapper_base.hpp create mode 100644 luabind/luabind/yield_policy.hpp create mode 100644 luabind/src/class.cpp create mode 100644 luabind/src/class_info.cpp create mode 100644 luabind/src/class_registry.cpp create mode 100644 luabind/src/class_rep.cpp create mode 100644 luabind/src/create_class.cpp create mode 100644 luabind/src/error.cpp create mode 100644 luabind/src/exception_handler.cpp create mode 100644 luabind/src/function.cpp create mode 100644 luabind/src/inheritance.cpp create mode 100644 luabind/src/link_compatibility.cpp create mode 100644 luabind/src/object_rep.cpp create mode 100644 luabind/src/open.cpp create mode 100644 luabind/src/pcall.cpp create mode 100644 luabind/src/scope.cpp create mode 100644 luabind/src/stack_content_by_name.cpp create mode 100644 luabind/src/weak_ref.cpp create mode 100644 luabind/src/wrapper_base.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 41649f4ec..ef14a40d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,11 +144,21 @@ ENDIF(EQEMU_BUILD_PERL) IF(EQEMU_BUILD_LUA) FIND_PACKAGE(Lua51 REQUIRED) - INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}" "common/luabridge") + SET(Boost_USE_STATIC_LIBS OFF) + SET(Boost_USE_MULTITHREADED ON) + SET(Boost_USE_STATIC_RUNTIME OFF) + SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost") + + FIND_PACKAGE(Boost REQUIRED) + INCLUDE_DIRECTORIES("${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "luabind") ENDIF(EQEMU_BUILD_LUA) INCLUDE_DIRECTORIES("${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}") +IF(EQEMU_BUILD_LUA) + ADD_SUBDIRECTORY(luabind) +ENDIF(EQEMU_BUILD_LUA) + IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS) ADD_SUBDIRECTORY(common) ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS) diff --git a/common/luabridge/LuaBridge.h b/common/luabridge/LuaBridge.h deleted file mode 100644 index 3ebf9783a..000000000 --- a/common/luabridge/LuaBridge.h +++ /dev/null @@ -1,4759 +0,0 @@ -//============================================================================== -/* - https://github.com/vinniefalco/LuaBridge - https://github.com/vinniefalco/LuaBridgeDemo - - Copyright (C) 2012, Vinnie Falco - Copyright (C) 2007, Nathan Reed - - License: The MIT License (http://www.opensource.org/licenses/mit-license.php) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - - This file incorporates work covered by the following copyright and - permission notice: - - The Loki Library - Copyright (c) 2001 by Andrei Alexandrescu - This code accompanies the book: - Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design - Patterns Applied". Copyright (c) 2001. Addison-Wesley. - Permission to use, copy, modify, distribute and sell this software for any - purpose is hereby granted without fee, provided that the above copyright - notice appear in all copies and that both that copyright notice and this - permission notice appear in supporting documentation. - The author or Addison-Welsey Longman make no representations about the - suitability of this software for any purpose. It is provided "as is" - without express or implied warranty. -*/ -//============================================================================== - -#ifndef LUABRIDGE_LUABRIDGE_HEADER -#define LUABRIDGE_LUABRIDGE_HEADER - -#include -#include -#include - -//============================================================================== -/** - @mainpage LuaBridge: Simple C++ to Lua bindings. - - @details - - - -
- - # LuaBridge 1.0.2 - - [LuaBridge][3] is a lightweight, dependency-free library for making C++ data, - functions, and classes available to [Lua][5]: A powerful, fast, lightweight, - embeddable scripting language. LuaBridge has been tested and works with Lua - revisions starting from 5.1.5., although it should work in any version of Lua - from 5.1.0 and later. - - LuaBridge offers the following features: - - - Nothing to compile, just include one header file! - - - Simple, light, and nothing else needed (like Boost). - - - Supports different object lifetime management models. - - - Convenient, type-safe access to the Lua stack. - - - Automatic function parameter type binding. - - - Does not require C++11. - - LuaBridge is distributed as a single header file. You simply add - `#include "LuaBridge.h"` where you want to bind your functions, classes, and - variables. There are no additional source files, no compilation settings, and - no Makefiles or IDE-specific project files. LuaBridge is easy to integrate. - A few additional header files provide optional features. Like the main header - file, these are simply used via `#include`. No additional source files need - to be compiled. - - C++ concepts like variables and classes are made available to Lua through a - process called _registration_. Because Lua is weakly typed, the resulting - structure is not rigid. The API is based on C++ template metaprogramming. It - contains template code to automatically generate at compile-time the various - Lua C API calls necessary to export your program's classes and functions to - the Lua environment. - - ### Version - - LuaBridge repository branches are as follows: - - - **[master][7]**: Tagged, stable release versions. - - - **[release][8]**: Tagged candidates for imminent release. - - - **[develop][9]**: Work in progress. - - ## LuaBridge Demo and Tests - - LuaBridge provides both a command line program and a stand-alone graphical - program for compiling and running the test suite. The graphical program brings - up an interactive window where you can enter execute Lua statements in a - persistent environment. This application is cross platform and works on - Windows, Mac OS, iOS, Android, and GNU/Linux systems with X11. The stand-alone - program should work anywhere. Both of these applications include LuaBridge, - Lua version 5.2, and the code necessary to produce a cross platform graphic - application. They are all together in a separate repository, with no - additional dependencies, available on Github at [LuaBridge Demo and Tests][4]. - This is what the GUI application looks like, along with the C++ code snippet - for registering the two classes: - - - -
- - ## Registration - - There are five types of objects that LuaBridge can register: - - - **Data**: Global variables, data members, and static data members. - - - **Functions**: Global functions, member functions, and static member - functions. - - - **CFunctions**: A regular function, member function, or static member - function that uses the `lua_CFunction` calling convention. - - - **Namespaces**: A namespace is simply a table containing registrations of - functions, data, properties, and other namespaces. - - - **Properties**: Global properties, property members, and static property - members. These appear like data to Lua, but are implemented - using get and set functions on the C++ side. - - Both data and properties can be marked as _read-only_ at the time of - registration. This is different from `const`; the values of these objects can - be modified on the C++ side, but Lua scripts cannot change them. Code samples - that follow are in C++ or Lua, depending on context. For brevity of exposition - code samples in C++ assume the traditional variable `lua_State* L` is defined, - and that a `using namespace luabridge` using-directive is in effect. - - ### Namespaces - - All LuaBridge registrations take place in a _namespace_. When we refer to a - _namespace_ we are always talking about a namespace in the Lua sense, which is - implemented using tables. The namespace need not correspond to a C++ namespace; - in fact no C++ namespaces need to exist at all unless you want them to. - LuaBridge namespaces are visible only to Lua scripts; they are used as a - logical grouping tool. To obtain access to the global namespace we write: - - getGlobalNamespace (L); - - This returns an object on which further registrations can be performed. The - subsequent registrations will go into the global namespace, a practice which - is not recommended. Instead, we can add our own namespace by writing: - - getGlobalNamespace (L) - .beginNamespace ("test"); - - This creates a table in `_G` called "test". Since we have not performed any - registrations, this table will be empty except for some bookkeeping key/value - pairs. LuaBridge reserves all identifiers that start with a double underscore. - So `__test` would be an invalid name (although LuaBridge will silently accept - it). Functions like `beginNamespace` return the corresponding object on which - we can make more registrations. Given: - - getGlobalNamespace (L) - .beginNamespace ("test") - .beginNamespace ("detail") - .endNamespace () - .beginNamespace ("utility") - .endNamespace () - .endNamespace (); - - The results are accessible to Lua as `test`, `test.detail`, and - `test.utility`. Here we introduce the `endNamespace` function; it returns an - object representing the original enclosing namespace. All LuaBridge functions - which create registrations return an object upon which subsequent - registrations can be made, allowing for an unlimited number of registrations - to be chained together using the dot operator `.`. Adding two objects with the - same name, in the same namespace, results in undefined behavior (although - LuaBridge will silently accept it). - - A namespace can be re-opened later to add more functions. This lets you split - up the registration between different source files. These are equivalent: - - getGlobalNamespace (L) - .beginNamespace ("test") - .addFunction ("foo", foo) - .endNamespace (); - - getGlobalNamespace (L) - .beginNamespace ("test") - .addFunction ("bar", bar) - .endNamespace (); - - and - - getGlobalNamespace (L) - .beginNamespace ("test") - .addFunction ("foo", foo) - .addFunction ("bar", bar) - .endNamespace (); - - - ### Data, Properties, Functions, and CFunctions. - - These are registered into a namespace using `addVariable`, `addProperty`, - `addFunction`, and `addCFunction`. When registered functions are called by - scripts, LuaBridge automatically takes care of the conversion of arguments - into the appropriate data type when doing so is possible. This automated - system works for the function's return value, and up to 8 parameters although - more can be added by extending the templates. Pointers, references, and - objects of class type as parameters are treated specially, and explained - later. If we have: - - int globalVar; - static float staticVar; - - std::string stringProperty; - std::string getString () { return stringProperty; } - void setString (std::string s) { return s; } - - int foo () { return 42; } - void bar (char const*) { } - int cFunc (lua_State* L) { return 0; } - - These are registered with: - - getGlobalNamespace (L) - .beginNamespace ("test") - .addVariable ("var1", &globalVar) - .addVariable ("var2", &staticVar, false) // read-only - .addProperty ("prop1", getString, setString) - .addProperty ("prop2", getString) // read only - .addFunction ("foo", foo) - .addFunction ("bar", bar) - .addCFunction ("cfunc", cFunc) - .endNamespace (); - - Variables can be marked _read-only_ by passing `false` in the second optional - parameter. If the parameter is omitted, `true` is used making the variable - read/write. Properties are marked read-only by omitting the set function. - After the registrations above, the following Lua identifiers are valid: - - test -- a namespace - test.var1 -- a lua_Number variable - test.var2 -- a read-only lua_Number variable - test.prop1 -- a lua_String property - test.prop2 -- a read-only lua_String property - test.foo -- a function returning a lua_Number - test.bar -- a function taking a lua_String as a parameter - test.cfunc -- a function with a variable argument list and multi-return - - Note that `test.prop1` and `test.prop2` both refer to the same value. However, - since `test.prop2` is read-only, assignment does not work. These Lua - statements have the stated effects: - - test.var1 = 5 -- okay - test.var2 = 6 -- error: var2 is not writable - test.prop1 = "Hello" -- okay - test.prop1 = 68 -- okay, Lua converts the number to a string. - test.prop2 = "bar" -- error: prop2 is not writable - - test.foo () -- calls foo and discards the return value - test.var1 = foo () -- calls foo and stores the result in var1 - test.bar ("Employee") -- calls bar with a string - test.bar (test) -- error: bar expects a string not a table - - LuaBridge does not support overloaded functions nor is it likely to in the - future. Since Lua is dynamically typed, any system that tries to resolve a set - of parameters passed from a script will face considerable ambiguity when - trying to choose an appropriately matching C++ function signature. - - ### Classes - - A class registration is opened using either `beginClass` or `deriveClass` and - ended using `endClass`. Once registered, a class can later be re-opened for - more registrations using `beginClass`. However, `deriveClass` should only be - used once. To add more registrations to an already registered derived class, - use `beginClass`. These declarations: - - struct A { - static int staticData; - static float staticProperty; - - static float getStaticProperty () { return staticProperty; } - static void setStaticProperty (float f) { staticProperty = f; } - static void staticFunc () { } - - static int staticCFunc () { return 0; } - - std::string dataMember; - - char dataProperty; - char getProperty () const { return dataProperty; } - void setProperty (char v) { dataProperty = v; } - - void func1 () { } - virtual void virtualFunc () { } - - int cfunc (lua_State* L) { return 0; } - }; - - struct B : public A { - double dataMember2; - - void func1 () { } - void func2 () { } - void virtualFunc () { } - }; - - int A::staticData; - float A::staticProperty; - - Are registered using: - - getGlobalNamespace (L) - .beginNamespace ("test") - .beginClass ("A") - .addStaticData ("staticData", &A::staticData) - .addStaticProperty ("staticProperty", &A::staticProperty) - .addStaticFunction ("staticFunc", &A::staticFunc) - .addStaticCFunction ("staticCFunc", &A::staticCFunc) - .addData ("data", &A::dataMember) - .addProperty ("prop", &A::getProperty, &A::setProperty) - .addFunction ("func1", &A::func1) - .addFunction ("virtualFunc", &A::virtualFunc) - .addCFunction ("cfunc", &A::cfunc) - .endClass () - .deriveClass ("B") - .addData ("data", &B::dataMember2) - .addFunction ("func1", &B::func1) - .addFunction ("func2", &B::func2) - .endClass () - .endClass (); - - Method registration works just like function registration. Virtual methods - work normally; no special syntax is needed. const methods are detected and - const-correctness is enforced, so if a function returns a const object (or - a container holding to a const object) to Lua, that reference to the object - will be considered const and only const methods can be called on it. - Destructors are registered automatically for each class. - - As with regular variables and properties, class data and properties can be - marked read-only by passing false in the second parameter, or omitting the set - set function respectively. The `deriveClass` takes two template arguments: the - class to be registered, and its base class. Inherited methods do not have to - be re-declared and will function normally in Lua. If a class has a base class - that is **not** registered with Lua, there is no need to declare it as a - subclass. - - ### Property Member Proxies - - Sometimes when registering a class which comes from a third party library, the - data is not exposed in a way that can be expressed as a pointer to member, - there are no get or set functions, or the get and set functons do not have the - right function signature. Since the class declaration is closed for changes, - LuaBridge provides allows a _property member proxy_. This is a pair of get - and set flat functions which take as their first parameter a pointer to - the object. This is easily understood with the following example: - - // Third party declaration, can't be changed - struct Vec - { - float coord [3]; - }; - - Taking the address of an array element, e.g. `&Vec::coord [0]` results in an - error instead of a pointer-to-member. The class is closed for modifications, - but we want to export Vec objects to Lua using the familiar object notation. - To do this, first we add a "helper" class: - - struct VecHelper - { - template - static float get (Vec const* vec) - { - return vec->coord [index]; - } - - template - static void set (Vec* vec, float value) - { - vec->coord [index] = value; - } - }; - - This helper class is only used to provide property member proxies. `Vec` - continues to be used in the C++ code as it was before. Now we can register - the `Vec` class with property member proxies for `x`, `y`, and `z`: - - getGlobalNamespace (L) - .beginNamespace ("test") - .beginClass ("Vec") - .addProperty ("x", &VecHelper::get <0>, &VecHelper::set <0>) - .addProperty ("y", &VecHelper::get <1>, &VecHelper::set <1>) - .addProperty ("z", &VecHelper::get <2>, &VecHelper::set <2>) - .endClass () - .endNamespace (); - - ### Constructors - - A single constructor may be added for a class using `addConstructor`. - LuaBridge cannot automatically determine the number and types of constructor - parameters like it can for functions and methods, so you must provide them. - This is done by specifying the signature of the desired constructor function - as the first template parameter to `addConstructor`. The parameter types will - be extracted from this (the return type is ignored). For example, these - statements register constructors for the given classes: - - struct A { - A (); - }; - - struct B { - explicit B (char const* s, int nChars); - }; - - getGlobalNamespace (L) - .beginNamespace ("test") - .beginClass ("A") - .addConstructor () - .endClass () - .beginClass ("B") - .addConstructor () - .endClass (); - .endNamespace () - - Constructors added in this fashion are called from Lua using the fully - qualified name of the class. This Lua code will create instances of `A` and - `B` - - a = test.A () -- Create a new A. - b = test.B ("hello", 5) -- Create a new B. - b = test.B () -- Error: expected string in argument 1 - - ## The Lua Stack - - In the Lua C API, all operations on the `lua_State` are performed through the - Lua stack. In order to pass parameters back and forth between C++ and Lua, - LuaBridge uses specializations of this template class concept: - - template - struct Stack - { - static void push (lua_State* L, T t); - static T get (lua_State* L, int index); - }; - - The Stack template class specializations are used automatically for variables, - properties, data members, property members, function arguments and return - values. These basic types are supported: - - - `bool` - - `char`, converted to a string of length one. - - `char const*` and `std::string` strings. - - Integers, `float`, and `double`, converted to `Lua_number`. - - User-defined types which are convertible to one of the basic types are - possible, simply provide a `Stack <>` specialization in the `luabridge` - namespace for your user-defined type, modeled after the existing types. - For example, here is a specialization for a [juce::String][6]: - - template <> - struct Stack - { - static void push (lua_State* L, juce::String s) - { - lua_pushstring (L, s.toUTF8 ()); - } - - static juce::String get (lua_State* L, int index) - { - return juce::String (luaL_checkstring (L, index)); - } - }; - - ### The `lua_State*` - - Sometimes it is convenient from within a bound function or member function - to gain access to the `lua_State*` normally available to a `lua_CFunction`. - With LuaBridge, all you need to do is add a `lua_State*` as the last - parameter of your bound function: - - void useState (lua_State* L); - - getGlobalNamespace (L).addFunction ("useState", &useState); - - You can still include regular arguments while receiving the state: - - void useStateAndArgs (int i, std::string s, lua_State* L); - - getGlobalNamespace (L).addFunction ("useStateAndArgs", &useStateAndArgs); - - When a script calls `useStateAndArgs`, it passes only the integer and string - parameters. LuaBridge takes care of inserting the `lua_State*` into the - argument list for the corresponding C++ function. This will work correctly - even for the state created by coroutines. Undefined behavior results if - the `lua_State*` is not the last parameter. - - ### Class Object Types - - An object of a registered class `T` may be passed to Lua as: - - - `T*` or `T&`: Passed by reference, with _C++ lifetime_. - - `T const*` or `T const&`: Passed by const reference, with _C++ lifetime_. - - `T` or `T const`: Passed by value (a copy), with _Lua lifetime_. - - ### C++ Lifetime - - The creation and deletion of objects with _C++ lifetime_ is controlled by - the C++ code. Lua does nothing when it garbage collects a reference to such an - object. Specifically, the object's destructor is not called (since C++ owns - it). Care must be taken to ensure that objects with C++ lifetime are not - deleted while still being referenced by a `lua_State*`, or else undefined - behavior results. In the previous examples, an instance of `A` can be passed - to Lua with C++ lifetime, like this: - - A a; - - push (L, &a); // pointer to 'a', C++ lifetime - lua_setglobal (L, "a"); - - push (L, (A const*)&a); // pointer to 'a const', C++ lifetime - lua_setglobal (L, "ac"); - - push (L, &a); // equivalent to push (L, (A const*)&a) - lua_setglobal (L, "ac2"); - - push (L, new A); // compiles, but will leak memory - lua_setglobal (L, "ap"); - - ### Lua Lifetime - - When an object of a registered class is passed by value to Lua, it will have - _Lua lifetime_. A copy of the passed object is constructed inside the - userdata. When Lua has no more references to the object, it becomes eligible - for garbage collection. When the userdata is collected, the destructor for - the class will be called on the object. Care must be taken to ensure that - objects with Lua lifetime are not accessed by C++ after they are garbage - collected, or else undefined behavior results. An instance of `B` can be - passed to Lua with Lua lifetime this way: - - B b; - - push (L, b); // Copy of b passed, Lua lifetime. - lua_setglobal (L, "b"); - - Given the previous code segments, these Lua statements are applicable: - - print (test.A.staticData) -- Prints the static data member. - print (test.A.staticProperty) -- Prints the static property member. - test.A.staticFunc () -- Calls the static method. - - print (a.data) -- Prints the data member. - print (a.prop) -- Prints the property member. - a:func1 () -- Calls A::func1 (). - test.A.func1 (a) -- Equivalent to a:func1 (). - test.A.func1 ("hello") -- Error: "hello" is not a class A. - a:virtualFunc () -- Calls A::virtualFunc (). - - print (b.data) -- Prints B::dataMember. - print (b.prop) -- Prints inherited property member. - b:func1 () -- Calls B::func1 (). - b:func2 () -- Calls B::func2 (). - test.B.func2 (a) -- Error: a is not a class B. - test.A.func1 (b) -- Calls A::func1 (). - b:virtualFunc () -- Calls B::virtualFunc (). - test.B.virtualFunc (b) -- Calls B::virtualFunc (). - test.A.virtualFunc (b) -- Calls B::virtualFunc (). - test.B.virtualFunc (a) -- Error: a is not a class B. - - a = nil; collectgarbage () -- 'a' still exists in C++. - b = nil; collectgarbage () -- Lua calls ~B() on the copy of b. - - When Lua script creates an object of class type using a registered - constructor, the resulting value will have Lua lifetime. After Lua no longer - references the object, it becomes eligible for garbage collection. You can - still pass these to C++, either by reference or by value. If passed by - reference, the usual warnings apply about accessing the reference later, - after it has been garbage collected. - - ### Pointers, References, and Pass by Value - - When C++ objects are passed from Lua back to C++ as arguments to functions, - or set as data members, LuaBridge does its best to automate the conversion. - Using the previous definitions, the following functions may be registered - to Lua: - - void func0 (A a); - void func1 (A* a); - void func2 (A const* a); - void func3 (A& a); - void func4 (A const& a); - - Executing this Lua code will have the prescribed effect: - - func0 (a) -- Passes a copy of a, using A's copy constructor. - func1 (a) -- Passes a pointer to a. - func2 (a) -- Passes a pointer to a const a. - func3 (a) -- Passes a reference to a. - func4 (a) -- Passes a reference to a const a. - - In the example above, all functions can read the data members and property - members of `a`, or call const member functions of `a`. Only `func0`, `func1` - and `func3` can modify the data members and data properties, or call - non-const member functions of `a`. - - The usual C++ inheritance and pointer assignment rules apply. Given: - - void func5 (B b); - void func6 (B* b); - - These Lua statements hold: - - func5 (b) - Passes a copy of b, using B's copy constructor. - func6 (b) - Passes a pointer to b. - func6 (a) - Error: Pointer to B expected. - func1 (b) - Okay, b is a subclass of a. - - When a pointer or pointer to const is passed to Lua and the pointer is null - (zero), LuaBridge will pass Lua a `nil` instead. When Lua passes a `nil` - to C++ where a pointer is expected, a null (zero) is passed instead. - Attempting to pass a null pointer to a C++ function expecting a reference - results in `lua_error` being called. - - ## Shared Lifetime - - LuaBridge supports a "shared lifetime" model: dynamically allocated and - reference counted objects whose ownership is shared by both Lua and C++. - The object remains in existence until there are no remaining C++ or Lua - references, and Lua performs its usual garbage collection cycle. A container - is recognized by a specialization of the `ContainerTraits` template class. - LuaBridge will automatically recognize when a data type is a container when - the correspoding specialization is present. Two styles of containers come with - LuaBridge, including the necessary specializations: - - ### The `RefCountedObjectPtr` Container - - This is an intrusive style container. Your existing class declaration must be - changed to be also derived from `RefCountedObject`. Given `class T`, derived - from `RefCountedObject`, the container `RefCountedObjectPtr ` may be used. - In order for reference counts to be maintained properly, all C++ code must - store a container instead of the pointer. This is similar in style to - `std::shared_ptr` although there are slight differences. For example: - - // A is reference counted. - struct A : public RefCountedObject - { - void foo () { } - }; - - struct B - { - RefCountedObjectPtr a; // holds a reference to A - }; - - void bar (RefCountedObjectPtr a) - { - a->foo (); - } - - ### The `RefCountedPtr` Container - - This is a non intrusive reference counted pointer. The reference counts are - kept in a global hash table, which does incur a small performance penalty. - However, it does not require changing any already existing class declarations. - This is especially useful when the classes to be registered come from a third - party library and cannot be modified. To use it, simply wrap all pointers - to class objects with the container instead: - - struct A - { - void foo () { } - }; - - struct B - { - RefCountedPtr a; - }; - - RefCountedPtr createA () - { - return new A; - } - - void bar (RefCountedPtr a) - { - a->foo (); - } - - void callFoo () - { - bar (createA ()); - - // The created A will be destroyed - // when we leave this scope - } - - ### Custom Containers - - If you have your own container, you must provide a specialization of - `ContainerTraits` in the `luabridge` namespace for your type before it will be - recognized by LuaBridge (or else the code will not compile): - - template - struct ContainerTraits > - { - typedef typename T Type; - - static T* get (CustomContainer const& c) - { - return c.getPointerToObject (); - } - }; - - Standard containers like `std::shared_ptr` or `boost::shared_ptr` **will not - work**. This is because of type erasure; when the object goes from C++ to - Lua and back to C++, there is no way to associate the object with the - original container. The new container is constructed from a pointer to the - object instead of an existing container. The result is undefined behavior - since there are now two sets of reference counts. - - ### Container Construction - - When a constructor is registered for a class, there is an additional - optional second template parameter describing the type of container to use. - If this parameter is specified, calls to the constructor will create the - object dynamically, via operator new, and place it a container of that - type. The container must have been previously specialized in - `ContainerTraits`, or else a compile error will result. This code will - register two objects, each using a constructor that creates an object - with Lua lifetime using the specified container: - - class C : public RefCountedObject - { - C () { } - }; - - class D - { - D () { } - }; - - getGlobalNamespace (L) - .beginNamespace ("test") - .beginClass ("C") - .addConstructor > () - .endClass () - .beginClass ("D") - .addConstructor > () - .endClass (); - .endNamespace () - - ### Mixing Lifetimes - - Mixing object lifetime models is entirely possible, subject to the usual - caveats of holding references to objects which could get deleted. For - example, C++ can be called from Lua with a pointer to an object of class - type; the function can modify the object or call non-const data members. - These modifications are visible to Lua (since they both refer to the same - object). An object store in a container can be passed to a function expecting - a pointer. These conversion work seamlessly. - - ## Security - - The metatables and userdata that LuaBridge creates in the `lua_State*` are - protected using a security system, to eliminate the possibility of undefined - behavior resulting from scripted manipulation of the environment. The - security system has these components: - - - Class and const class tables use the 'table proxy' technique. The - corresponding metatables have `__index` and `__newindex` metamethods, - so these class tables are immutable from Lua. - - - Metatables have `__metatable` set to a boolean value. Scripts cannot - obtain the metatable from a LuaBridge object. - - - Classes are mapped to metatables through the registry, which Lua scripts - cannot access. The global environment does not expose metatables - - - Metatables created by LuaBridge are tagged with a lightuserdata key which - is unique in the process. Other libraries cannot forge a LuaBridge - metatable. - - This security system can be easily bypassed if scripts are given access to - the debug library (or functionality similar to it, i.e. a raw `getmetatable`). - The security system can also be defeated by C code in the host, either by - revealing the unique lightuserdata key to another module or by putting a - LuaBridge metatable in a place that can be accessed by scripts. - - When a class member function is called, or class property member accessed, - the `this` pointer is type-checked. This is because member functions exposed - to Lua are just plain functions that usually get called with the Lua colon - notation, which passes the object in question as the first parameter. Lua's - dynamic typing makes this type-checking mandatory to prevent undefined - behavior resulting from improper use. - - If a type check error occurs, LuaBridge uses the `lua_error` mechanism to - trigger a failure. A host program can always recover from an error through - the use of `lua_pcall`; proper usage of LuaBridge will never result in - undefined behavior. - - ## Limitations - - LuaBridge does not support: - - - Enumerated constants - - More than 8 parameters on a function or method (although this can be - increased by adding more `TypeListValues` specializations). - - Overloaded functions, methods, or constructors. - - Global variables (variables must be wrapped in a named scope). - - Automatic conversion between STL container types and Lua tables. - - Inheriting Lua classes from C++ classes. - - Passing nil to a C++ function that expects a pointer or reference. - - Standard containers like `std::shared_ptr`. - - ## Development - - [Github][3] is the new official home for LuaBridge. The old SVN repository is - deprecated since it is no longer used, or maintained. The original author has - graciously passed the reins to Vinnie Falco for maintaining and improving the - project. To obtain the older official releases, checkout the tags from 0.2.1 - and earlier. - - If you are an existing LuaBridge user, a new LuaBridge user, or a potential - LuaBridge user, we welcome your input, feedback, and contributions. Feel - free to open Issues, or fork the repository. All questions, comments, - suggestions, and/or proposed changes will be handled by the new maintainer. - - ## License - - Copyright (C) 2012, [Vinnie Falco][1] ([e-mail][0])
- Copyright (C) 2007, Nathan Reed
- - Portions from The Loki Library:
- Copyright (C) 2001 by Andrei Alexandrescu - - License: The [MIT License][2] - - Older versions of LuaBridge up to and including 0.2 are distributed under the - BSD 3-Clause License. See the corresponding license file in those versions - for more details. - - [0]: mailto:vinnie.falco@gmail.com "Vinnie Falco (Email)" - [1]: http://www.vinniefalco.com "Vinnie Falco" - [2]: http://www.opensource.org/licenses/mit-license.html "The MIT License" - [3]: https://github.com/vinniefalco/LuaBridge "LuaBridge" - [4]: https://github.com/vinniefalco/LuaBridgeDemo "LuaBridge Demo" - [5]: http://lua.org "The Lua Programming Language" - [6]: http://www.rawmaterialsoftware.com/juce/api/classString.html "juce::String" - [7]: https://github.com/vinniefalco/LuaBridge "LuaBridge master branch" - [8]: https://github.com/vinniefalco/LuaBridge/tree/release "LuaBridge release branch" - [9]: https://github.com/vinniefalco/LuaBridge/tree/develop "LuaBridge develop branch" -*/ - -#include -#include - -namespace luabridge -{ - -/** - Since the throw specification is part of a function signature, the FuncTraits - family of templates needs to be specialized for both types. The THROWSPEC - macro controls whether we use the 'throw ()' form, or 'noexcept' (if C++11 - is available) to distinguish the functions. -*/ -#if defined (__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__clang__) || defined(__GNUC__) -// Do not define THROWSPEC since the Xcode and gcc compilers do not -// distinguish the throw specification in the function signature. -#else -#define THROWSPEC throw() -#endif - -//============================================================================== -/** - Templates for extracting type information. - - These templates are used for extracting information about types used in - various ways. -*/ - -//============================================================================== - -template -struct TypeInfo -{ - typedef T Type; - static bool const is_const = false; - static bool const is_pointer = false; - static bool const is_reference = false; -}; - -template -struct TypeInfo -{ - typedef T Type; - static bool const is_const = true; - static bool const is_pointer = false; - static bool const is_reference = false; -}; - -template -struct TypeInfo -{ - typedef T Type; - static bool const is_const = false; - static bool const is_pointer = true; - static bool const is_reference = false; -}; - -template -struct TypeInfo -{ - typedef T Type; - static bool const is_const = true; - static bool const is_pointer = true; - static bool const is_reference = false; -}; - -template -struct TypeInfo -{ - typedef T Type; - static bool const is_const = false; - static bool const is_pointer = false; - static bool const is_reference = true; -}; - -template -struct TypeInfo -{ - typedef T Type; - static bool const is_const = true; - static bool const is_pointer = false; - static bool const is_reference = true; -}; - -//============================================================================== -// -// TypeList -// -//============================================================================== - -/** - None type means void parameters or return value. -*/ -typedef void None; - -template -struct TypeList -{ -}; - -/** - A TypeList with actual values. -*/ -template -struct TypeListValues -{ - static std::string const tostring (bool) - { - return ""; - } -}; - -/** - TypeListValues recursive template definition. -*/ -template -struct TypeListValues > -{ - Head hd; - TypeListValues tl; - - TypeListValues (Head hd_, TypeListValues const& tl_) - : hd (hd_), tl (tl_) - { - } - - static std::string const tostring (bool comma = false) - { - std::string s; - - if (comma) - s = ", "; - - s = s + typeid (Head).name (); - - return s + TypeListValues ::tostring (true); - } -}; - -// Specializations of type/value list for head types that are references and -// const-references. We need to handle these specially since we can't count -// on the referenced object hanging around for the lifetime of the list. - -template -struct TypeListValues > -{ - Head hd; - TypeListValues tl; - - TypeListValues (Head& hd_, TypeListValues const& tl_) - : hd (hd_), tl (tl_) - { - } - - static std::string const tostring (bool comma = false) - { - std::string s; - - if (comma) - s = ", "; - - s = s + typeid (Head).name () + "&"; - - return s + TypeListValues ::tostring (true); - } -}; - -template -struct TypeListValues > -{ - Head hd; - TypeListValues tl; - - TypeListValues (Head const& hd_, const TypeListValues & tl_) - : hd (hd_), tl (tl_) - { - } - - static std::string const tostring (bool comma = false) - { - std::string s; - - if (comma) - s = ", "; - - s = s + typeid (Head).name () + " const&"; - - return s + TypeListValues ::tostring (true); - } -}; - -//============================================================================== -/** - Traits for function pointers. - - There are three types of functions: global, non-const member, and const member. - These templates determine the type of function, which class type it belongs to - if it is a class member, the const-ness if it is a member function, and the - type information for the return value and argument list. - - Expansions are provided for functions with up to 8 parameters. This can be - manually extended, or expanded to an arbitrary amount using C++11 features. -*/ -template -struct FuncTraits -{ -}; - -/* Ordinary function pointers. */ - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef None Params; - static R call (DeclType fp, TypeListValues ) - { - return fp (); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -/* Non-const member function pointers. */ - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef None Params; - static R call (T* const obj, DeclType fp, TypeListValues const&) - { - return (obj->*fp)(); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -/* Const member function pointers. */ - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef None Params; - static R call (T const* const obj, DeclType fp, TypeListValues const&) - { - return (obj->*fp)(); - } -}; - -#if !defined(_MSC_VER) || (_MSC_VER < 1700) -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > Params; - static R call (T const* const obj, R (T::*fp) (P1, P2) const, - TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; -#endif - -#if defined (THROWSPEC) - -/* Ordinary function pointers. */ - -#if !defined(_MSC_VER) || (_MSC_VER < 1700) -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef None Params; - static R call (DeclType fp, TypeListValues const&) - { - return fp (); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - return fp (tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = false; - typedef D DeclType; - typedef R ReturnType; - typedef TypeList > > > > > > > Params; - static R call (DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -/* Non-const member function pointers. */ - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef None Params; - static R call (T* const obj, DeclType fp, TypeListValues const&) - { - return (obj->*fp)(); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = false; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > > Params; - static R call (T* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -/* Const member function pointers. */ - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef None Params; - static R call (T const* const obj, DeclType fp, TypeListValues const&) - { - (void)tvl; - return (obj->*fp)(); - } -}; -#endif - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - return (obj->*fp)(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -template -struct FuncTraits -{ - static bool const isMemberFunction = true; - static bool const isConstMemberFunction = true; - typedef D DeclType; - typedef T ClassType; - typedef R ReturnType; - typedef TypeList > > > > > > > Params; - static R call (T const* const obj, DeclType fp, TypeListValues tvl) - { - 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); - } -}; - -#endif - -/* -* Constructor generators. These templates allow you to call operator new and -* pass the contents of a type/value list to the Constructor. Like the -* function pointer containers, these are only defined up to 8 parameters. -*/ - -/** Constructor generators. - - These templates call operator new with the contents of a type/value - list passed to the Constructor with up to 8 parameters. Two versions - of call() are provided. One performs a regular new, the other performs - a placement new. -*/ -template -struct Constructor {}; - -template -struct Constructor -{ - static T* call (TypeListValues const&) - { - return new T; - } - static T* call (void* mem, TypeListValues const&) - { - return new (mem) T; - } -}; - -template -struct Constructor > -{ - static T* call (const TypeListValues > &tvl) - { - return new T(tvl.hd); - } - static T* call (void* mem, const TypeListValues > &tvl) - { - return new (mem) T(tvl.hd); - } -}; - -template -struct Constructor > > -{ - static T* call (const TypeListValues > > &tvl) - { - return new T(tvl.hd, tvl.tl.hd); - } - static T* call (void* mem, const TypeListValues > > &tvl) - { - return new (mem) T(tvl.hd, tvl.tl.hd); - } -}; - -template -struct Constructor > > > -{ - static T* call (const TypeListValues > > > &tvl) - { - return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } - static T* call (void* mem, const TypeListValues > > > &tvl) - { - return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd); - } -}; - -template -struct Constructor > > > > -{ - static T* call (const TypeListValues > > > > &tvl) - { - return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } - static T* call (void* mem, const TypeListValues > > > > &tvl) - { - return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd); - } -}; - -template -struct Constructor > > > > > -{ - static T* call (const TypeListValues > > > > > &tvl) - { - return new T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } - static T* call (void* mem, const TypeListValues > > > > > &tvl) - { - return new (mem) T(tvl.hd, tvl.tl.hd, tvl.tl.tl.hd, tvl.tl.tl.tl.hd, - tvl.tl.tl.tl.tl.hd); - } -}; - -template -struct Constructor > > > > > > -{ - static T* call (const TypeListValues > > > > > > &tvl) - { - return new T(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); - } - static T* call (void* mem, const TypeListValues > > > > > > &tvl) - { - return new (mem) T(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); - } -}; - -template -struct Constructor > > > > > > > -{ - static T* call (const TypeListValues > > > > > > > &tvl) - { - return new T(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); - } - static T* call (void* mem, const TypeListValues > > > > > > > &tvl) - { - return new (mem) T(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); - } -}; - -template -struct Constructor > > > > > > > > -{ - static T* call (const TypeListValues > > > > > > > > &tvl) - { - return new T(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); - } - static T* call (void* mem, const TypeListValues > > > > > > > > &tvl) - { - return new (mem) T(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); - } -}; - -//============================================================================== - -// Forward declaration required. -template -struct Stack; - -//------------------------------------------------------------------------------ -/** - Container traits. - - Unspecialized ContainerTraits has the isNotContainer typedef for SFINAE. All - user defined containers must supply an appropriate specialization for - ContinerTraits (without the typedef isNotContainer). The containers that come - with LuaBridge also come with the appropriate ContainerTraits specialization. - See the corresponding declaration for details. - - A specialization of ContainerTraits for some generic type ContainerType - looks like this: - - template - struct ContainerTraits > - { - typedef typename T Type; - - static T* get (ContainerType const& c) - { - return c.get (); // Implementation-dependent on ContainerType - } - }; -*/ -template -struct ContainerTraits -{ - typedef bool isNotContainer; -}; - -//============================================================================== - -#if LUA_VERSION_NUM < 502 -/** - Helpers for Lua versions prior to 5.2.0. -*/ - -inline int lua_absindex (lua_State *L, int idx) -{ - if (idx > LUA_REGISTRYINDEX && idx < 0) - return lua_gettop (L) + idx + 1; - else - return idx; -} - -inline void lua_rawgetp (lua_State *L, int idx, void const* p) -{ - idx = lua_absindex (L, idx); - lua_pushlightuserdata (L, const_cast (p)); - lua_rawget (L,idx); -} - -inline void lua_rawsetp (lua_State *L, int idx, void const* p) -{ - idx = lua_absindex (L, idx); - lua_pushlightuserdata (L, const_cast (p)); - // put key behind value - lua_insert (L, -2); - lua_rawset (L, idx); -} -#endif - -//------------------------------------------------------------------------------ -/** - Get a table value, bypassing metamethods. -*/ -inline void rawgetfield (lua_State* const L, int index, char const* const key) -{ - assert (lua_istable (L, index)); - index = lua_absindex (L, index); - lua_pushstring (L, key); - lua_rawget (L, index); -} - -//------------------------------------------------------------------------------ -/** - Set a table value, bypassing metamethods. -*/ -inline void rawsetfield (lua_State* const L, int index, char const* const key) -{ - assert (lua_istable (L, index)); - index = lua_absindex (L, index); - lua_pushstring (L, key); - lua_insert (L, -2); - lua_rawset (L, index); -} - -//============================================================================== - -namespace Detail -{ - //---------------------------------------------------------------------------- - /** - Control security options. - */ - class Security - { - public: - static bool hideMetatables () - { - return getSettings().hideMetatables; - } - - static void setHideMetatables (bool shouldHide) - { - getSettings().hideMetatables = shouldHide; - } - - private: - struct Settings - { - Settings () - : hideMetatables (true) - { - } - - bool hideMetatables; - }; - - static Settings& getSettings () - { - static Settings settings; - return settings; - } - }; - - //---------------------------------------------------------------------------- - struct TypeTraits - { - //-------------------------------------------------------------------------- - /** - Determine if type T is a container. - - To be considered a container, there must be a specialization of - ContainerTraits with the required fields. - */ - template - class isContainer - { - typedef char yes[1]; // sizeof (yes) == 1 - typedef char no [2]; // sizeof (no) == 2 - - template - static no& test (typename C::isNotContainer*); - - template - static yes& test (...); - - public: - static const bool value = sizeof (test >(0)) == sizeof (yes); - }; - - //-------------------------------------------------------------------------- - /** - Determine if T is const qualified. - */ - template - struct isConst - { - static bool const value = false; - }; - - template - struct isConst - { - static bool const value = true; - }; - - //-------------------------------------------------------------------------- - /** - Strip the const qualifier from T. - */ - template - struct removeConst - { - typedef T Type; - }; - - template - struct removeConst - { - typedef T Type; - }; - }; - - //============================================================================ - /** - Return the identity pointer for our lightuserdata tokens. - - LuaBridge metatables are tagged with a security "token." The token is a - lightuserdata created from the identity pointer, used as a key in the - metatable. The value is a boolean = true, although any value could have been - used. - - Because of Lua's dynamic typing and our improvised system of imposing C++ - class structure, there is the possibility that executing scripts may - knowingly or unknowingly cause invalid data to get passed to the C functions - created by LuaBridge. In particular, our security model addresses the - following: - - Problem: - - Prove that a userdata passed to a LuaBridge C function was created by us. - - An attempt to access the memory of a foreign userdata through a pointer - of our own type will result in undefined behavior. Our verification - strategy is based on the security of the token used to tag our metatables. - We will now reason about the security model. - - Axioms: - - 1. Scripts cannot create a userdata (ignoring the debug lib). - 2. Scripts cannot create a lightuserdata (ignoring the debug lib). - 3. Scripts cannot set the metatable on a userdata. - 4. Our identity key is a unique pointer in the process. - 5. Our metatables have a lightuserdata identity key / value pair. - 6. Our metatables have "__metatable" set to a boolean = false. - - Lemma: - - 7. Our lightuserdata is unique. - - This follows from #4. - - Lemma: - - - Lua scripts cannot read or write metatables created by LuaBridge. - They cannot gain access to a lightuserdata - - Therefore, it is certain that if a Lua value is a userdata, the userdata - has a metatable, and the metatable has a value for a lightuserdata key - with this identity pointer address, that LuaBridge created the userdata. - */ - inline void* const getIdentityKey () - { - static char value; - return &value; - } - - //---------------------------------------------------------------------------- - /** - Unique registry keys for a class. - - Each registered class inserts three keys into the registry, whose - values are the corresponding static, class, and const metatables. This - allows a quick and reliable lookup for a metatable from a template type. - */ - template - class ClassInfo - { - public: - /** - Get the key for the static table. - - The static table holds the static data members, static properties, and - static member functions for a class. - */ - static void const* const getStaticKey () - { - static char value; - return &value; - } - - /** - Get the key for the class table. - - The class table holds the data members, properties, and member functions - of a class. Read-only data and properties, and const member functions are - also placed here (to save a lookup in the const table). - */ - static void const* const getClassKey () - { - static char value; - return &value; - } - - /** - Get the key for the const table. - - The const table holds read-only data members and properties, and const - member functions of a class. - */ - static void const* const getConstKey () - { - static char value; - return &value; - } - }; - - //============================================================================ - /** - Interface to a class poiner retrievable from a userdata. - */ - class Userdata - { - protected: - void* m_p; // subclasses must set this - - //-------------------------------------------------------------------------- - /** - Get an untyped pointer to the contained class. - */ - inline void* const getPointer () - { - return m_p; - } - - private: - //-------------------------------------------------------------------------- - /** - Validate and retrieve a Userdata on the stack. - - The Userdata must exactly match the corresponding class table or - const table, or else a Lua error is raised. This is used for the - __gc metamethod. - */ - static Userdata* const getExactClass (lua_State* L, int narg, void const* const classKey) - { - Userdata* ud = 0; - int const index = lua_absindex (L, narg); - - bool mismatch = false; - char const* got = 0; - - lua_rawgetp (L, LUA_REGISTRYINDEX, classKey); - assert (lua_istable (L, -1)); - - // Make sure we have a userdata. - if (!mismatch && !lua_isuserdata (L, index)) - mismatch = true; - - // Make sure it's metatable is ours. - if (!mismatch) - { - lua_getmetatable (L, index); - lua_rawgetp (L, -1, getIdentityKey ()); - if (lua_isboolean (L, -1)) - { - lua_pop (L, 1); - } - else - { - lua_pop (L, 2); - mismatch = true; - } - } - - if (!mismatch) - { - if (lua_rawequal (L, -1, -2)) - { - // Matches class table. - lua_pop (L, 2); - ud = static_cast (lua_touserdata (L, index)); - } - else - { - rawgetfield (L, -2, "__const"); - if (lua_rawequal (L, -1, -2)) - { - // Matches const table - lua_pop (L, 3); - ud = static_cast (lua_touserdata (L, index)); - } - else - { - // Mismatch, but its one of ours so get a type name. - rawgetfield (L, -2, "__type"); - lua_insert (L, -4); - lua_pop (L, 2); - got = lua_tostring (L, -2); - mismatch = true; - } - } - } - - if (mismatch) - { - rawgetfield (L, -1, "__type"); - assert (lua_type (L, -1) == LUA_TSTRING); - char const* const expected = lua_tostring (L, -1); - - if (got == 0) - got = lua_typename (L, lua_type (L, index)); - - char const* const msg = lua_pushfstring ( - L, "%s expected, got %s", expected, got); - - if (narg > 0) - luaL_argerror (L, narg, msg); - else - lua_error (L); - } - - return ud; - } - - //-------------------------------------------------------------------------- - /** - Validate and retrieve a Userdata on the stack. - - The Userdata must be derived from or the same as the given base class, - identified by the key. If canBeConst is false, generates an error if - the resulting Userdata represents to a const object. We do the type check - first so that the error message is informative. - */ - static Userdata* const getClass ( - lua_State* L, int const index, void const* const baseClassKey, bool const canBeConst) - { - assert (index > 0); - Userdata* ud = 0; - - bool mismatch = false; - char const* got = 0; - - lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey); - assert (lua_istable (L, -1)); - - // Make sure we have a userdata. - if (lua_isuserdata (L, index)) - { - // Make sure it's metatable is ours. - lua_getmetatable (L, index); - lua_rawgetp (L, -1, getIdentityKey ()); - if (lua_isboolean (L, -1)) - { - lua_pop (L, 1); - - // If __const is present, object is NOT const. - rawgetfield (L, -1, "__const"); - assert (lua_istable (L, -1) || lua_isnil (L, -1)); - bool const isConst = lua_isnil (L, -1); - lua_pop (L, 1); - - // Replace the class table with the const table if needed. - if (isConst) - { - rawgetfield (L, -2, "__const"); - assert (lua_istable (L, -1)); - lua_replace (L, -3); - } - - for (;;) - { - if (lua_rawequal (L, -1, -2)) - { - lua_pop (L, 2); - - // Match, now check const-ness. - if (isConst && !canBeConst) - { - luaL_argerror (L, index, "cannot be const"); - } - else - { - ud = static_cast (lua_touserdata (L, index)); - break; - } - } - else - { - // Replace current metatable with it's base class. - rawgetfield (L, -1, "__parent"); - lua_remove (L, -2); - - if (lua_isnil (L, -1)) - { - // Mismatch, but its one of ours so get a type name. - rawgetfield (L, -2, "__type"); - lua_insert (L, -4); - lua_pop (L, 2); - got = lua_tostring (L, -2); - mismatch = true; - break; - } - } - } - } - else - { - lua_pop (L, 2); - mismatch = true; - } - } - else - { - mismatch = true; - } - - if (mismatch) - { - rawgetfield (L, -1, "__type"); - assert (lua_type (L, -1) == LUA_TSTRING); - char const* const expected = lua_tostring (L, -1); - - if (got == 0) - got = lua_typename (L, lua_type (L, index)); - - char const* const msg = lua_pushfstring ( - L, "%s expected, got %s", expected, got); - - luaL_argerror (L, index, msg); - } - - return ud; - } - - public: - virtual ~Userdata () { } - - //-------------------------------------------------------------------------- - /** - Returns the Userdata* if the class on the Lua stack matches. - - If the class does not match, a Lua error is raised. - */ - template - static inline Userdata* getExact (lua_State* L, int index) - { - return getExactClass (L, index, ClassInfo ::getClassKey ()); - } - - //-------------------------------------------------------------------------- - /** - Get a pointer to the class from the Lua stack. - - If the object is not the class or a subclass, or it violates the - const-ness, a Lua error is raised. - */ - template - static inline T* get (lua_State* L, int index, bool canBeConst) - { - if (lua_isnil (L, index)) - return 0; - else - return static_cast (getClass (L, index, - ClassInfo ::getClassKey (), canBeConst)->getPointer ()); - } - }; - - //---------------------------------------------------------------------------- - /** - Wraps a class object stored in a Lua userdata. - - The lifetime of the object is managed by Lua. The object is constructed - inside the userdata using placement new. - */ - template - class UserdataValue : public Userdata - { - private: - UserdataValue (UserdataValue const&); - UserdataValue operator= (UserdataValue const&); - - char m_storage [sizeof (T)]; - - inline T* getObject () - { - // If this fails to compile it means you forgot to provide - // a Container specialization for your container! - // - return reinterpret_cast (&m_storage [0]); - } - - private: - /** - Used for placement construction. - */ - UserdataValue () - { - m_p = getObject (); - } - - ~UserdataValue () - { - getObject ()->~T (); - } - - public: - /** - Push a T via placement new. - - The caller is responsible for calling placement new using the - returned uninitialized storage. - */ - static void* place (lua_State* const L) - { - UserdataValue * const ud = new ( - lua_newuserdata (L, sizeof (UserdataValue ))) UserdataValue (); - lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::getClassKey ()); - // If this goes off it means you forgot to register the class! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - return ud->getPointer (); - } - - /** - Push T via copy construction from U. - */ - template - static inline void push (lua_State* const L, U const& u) - { - new (place (L)) U (u); - } - }; - - //---------------------------------------------------------------------------- - /** - Wraps a pointer to a class object inside a Lua userdata. - - The lifetime of the object is managed by C++. - */ - class UserdataPtr : public Userdata - { - private: - UserdataPtr (UserdataPtr const&); - UserdataPtr operator= (UserdataPtr const&); - - private: - /** Push non-const pointer to object using metatable key. - */ - static void push (lua_State* L, void* const p, void const* const key) - { - if (p) - { - new (lua_newuserdata (L, sizeof (UserdataPtr))) UserdataPtr (p); - lua_rawgetp (L, LUA_REGISTRYINDEX, key); - // If this goes off it means you forgot to register the class! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - } - else - { - lua_pushnil (L); - } - } - - /** Push const pointer to object using metatable key. - */ - static void push (lua_State* L, void const* const p, void const* const key) - { - if (p) - { - new (lua_newuserdata (L, sizeof (UserdataPtr))) - UserdataPtr (const_cast (p)); - lua_rawgetp (L, LUA_REGISTRYINDEX, key); - // If this goes off it means you forgot to register the class! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - } - else - { - lua_pushnil (L); - } - } - - explicit UserdataPtr (void* const p) - { - m_p = p; - - // Can't construct with a null pointer! - // - assert (m_p != 0); - } - - public: - /** Push non-const pointer to object. - */ - template - static inline void push (lua_State* const L, T* const p) - { - if (p) - push (L, p, ClassInfo ::getClassKey ()); - else - lua_pushnil (L); - } - - /** Push const pointer to object. - */ - template - static inline void push (lua_State* const L, T const* const p) - { - if (p) - push (L, p, ClassInfo ::getConstKey ()); - else - lua_pushnil (L); - } - }; - - //============================================================================ - /** - Wraps a container thet references a class object. - - The template argument C is the container type, ContainerTraits must be - specialized on C or else a compile error will result. - */ - template - class UserdataShared : public Userdata - { - private: - UserdataShared (UserdataShared const&); - UserdataShared & operator= (UserdataShared const&); - - typedef typename TypeTraits::removeConst < - typename ContainerTraits ::Type>::Type T; - - C m_c; - - private: - ~UserdataShared () - { - } - - public: - /** - Construct from a container to the class or a derived class. - */ - template - explicit UserdataShared (U const& u) : m_c (u) - { - m_p = const_cast (reinterpret_cast ( - (ContainerTraits ::get (m_c)))); - } - - /** - Construct from a pointer to the class or a derived class. - */ - template - explicit UserdataShared (U* u) : m_c (u) - { - m_p = const_cast (reinterpret_cast ( - (ContainerTraits ::get (m_c)))); - } - }; - - //---------------------------------------------------------------------------- - // - // SFINAE helpers. - // - - // non-const objects - template - struct UserdataSharedHelper - { - typedef typename TypeTraits::removeConst < - typename ContainerTraits ::Type>::Type T; - - static void push (lua_State* L, C const& c) - { - new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (c); - lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::getClassKey ()); - // If this goes off it means the class T is unregistered! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - } - - static void push (lua_State* L, T* const t) - { - new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (t); - lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::getClassKey ()); - // If this goes off it means the class T is unregistered! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - } - }; - - // const objects - template - struct UserdataSharedHelper - { - typedef typename TypeTraits::removeConst < - typename ContainerTraits ::Type>::Type T; - - static void push (lua_State* L, C const& c) - { - new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (c); - lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::getConstKey ()); - // If this goes off it means the class T is unregistered! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - } - - static void push (lua_State* L, T* const t) - { - new (lua_newuserdata (L, sizeof (UserdataShared ))) UserdataShared (t); - lua_rawgetp (L, LUA_REGISTRYINDEX, ClassInfo ::getConstKey ()); - // If this goes off it means the class T is unregistered! - assert (lua_istable (L, -1)); - lua_setmetatable (L, -2); - } - }; - - /** - Pass by container. - - The container controls the object lifetime. Typically this will be a - lifetime shared by C++ and Lua using a reference count. Because of type - erasure, containers like std::shared_ptr will not work. Containers must - either be of the intrusive variety, or in the style of the RefCountedPtr - type provided by LuaBridge (that uses a global hash table). - */ - template - struct StackHelper - { - static inline void push (lua_State* L, C const& c) - { - UserdataSharedHelper ::Type>::value>::push (L, c); - } - - typedef typename TypeTraits::removeConst < - typename ContainerTraits ::Type>::Type T; - - static inline C get (lua_State* L, int index) - { - return Detail::Userdata::get (L, index, true); - } - }; - - /** - Pass by value. - - Lifetime is managed by Lua. A C++ function which accesses a pointer or - reference to an object outside the activation record in which it was - retrieved may result in undefined behavior if Lua garbage collected it. - */ - template - struct StackHelper - { - static inline void push (lua_State* L, T const& t) - { - Detail::UserdataValue ::push (L, t); - } - - static inline T const& get (lua_State* L, int index) - { - return *Detail::Userdata::get (L, index, true); - } - }; -} - -//============================================================================== - -/** - Lua stack conversions for class objects passed by value. -*/ -template -struct Stack -{ -public: - static inline void push (lua_State* L, T const& t) - { - Detail::StackHelper ::value>::push (L, t); - } - - static inline T get (lua_State* L, int index) - { - return Detail::StackHelper ::value>::get (L, index); - } -}; - -//------------------------------------------------------------------------------ -/** - Lua stack conversions for pointers and references to class objects. - - Lifetime is managed by C++. Lua code which remembers a reference to the - value may result in undefined behavior if C++ destroys the object. The - handling of the const and volatile qualifiers happens in UserdataPtr. -*/ - -// pointer -template -struct Stack -{ - static inline void push (lua_State* L, T* const p) - { - Detail::UserdataPtr::push (L, p); - } - - static inline T* const get (lua_State* L, int index) - { - return Detail::Userdata::get (L, index, false); - } -}; - -// Strips the const off the right side of * -template -struct Stack -{ - static inline void push (lua_State* L, T* const p) - { - Detail::UserdataPtr::push (L, p); - } - - static inline T* const get (lua_State* L, int index) - { - return Detail::Userdata::get (L, index, false); - } -}; - -// pointer to const -template -struct Stack -{ - static inline void push (lua_State* L, T const* const p) - { - Detail::UserdataPtr::push (L, p); - } - - static inline T const* const get (lua_State* L, int index) - { - return Detail::Userdata::get (L, index, true); - } -}; - -// Strips the const off the right side of * -template -struct Stack -{ - static inline void push (lua_State* L, T const* const p) - { - Detail::UserdataPtr::push (L, p); - } - - static inline T const* const get (lua_State* L, int index) - { - return Detail::Userdata::get (L, index, true); - } -}; - -// reference -template -struct Stack -{ - static inline void push (lua_State* L, T& t) - { - Detail::UserdataPtr::push (L, &t); - } - - static T& get (lua_State* L, int index) - { - T* const t = Detail::Userdata::get (L, index, false); - if (!t) - luaL_error (L, "nil passed to reference"); - return *t; - } -}; - -// reference to const -template -struct Stack -{ - static inline void push (lua_State* L, T const& t) - { - Detail::UserdataPtr::push (L, &t); - } - - static T const& get (lua_State* L, int index) - { - T const* const t = Detail::Userdata::get (L, index, true); - if (!t) - luaL_error (L, "nil passed to reference"); - return *t; - } -}; - -//------------------------------------------------------------------------------ -/** - Receive the lua_State* as an argument. -*/ -template <> -struct Stack -{ - static lua_State* get (lua_State* L, int) - { - return L; - } -}; - -//------------------------------------------------------------------------------ -/** - Lua stack conversions for basic types. -*/ - -// int -template <> struct Stack < - int > { static inline void push (lua_State* L, - int value) { lua_pushnumber (L, static_cast (value)); } static inline - int get (lua_State* L, int index) { return static_cast < - int > (luaL_checknumber (L, index)); } }; - -// unsigned int -template <> struct Stack < - unsigned int > { static inline void push (lua_State* L, - unsigned int value) { lua_pushnumber (L, static_cast (value)); } static inline - unsigned int get (lua_State* L, int index) { return static_cast < - unsigned int > (luaL_checknumber (L, index)); } }; - -// unsigned char -template <> struct Stack < - unsigned char > { static inline void push (lua_State* L, - unsigned char value) { lua_pushnumber (L, static_cast (value)); } static inline - unsigned char get (lua_State* L, int index) { return static_cast < - unsigned char > (luaL_checknumber (L, index)); } }; - -// short -template <> struct Stack < - short > { static inline void push (lua_State* L, - short value) { lua_pushnumber (L, static_cast (value)); } static inline - short get (lua_State* L, int index) { return static_cast < - short > (luaL_checknumber (L, index)); } }; - -// unsigned short -template <> struct Stack < - unsigned short > { static inline void push (lua_State* L, - unsigned short value) { lua_pushnumber (L, static_cast (value)); } static inline - unsigned short get (lua_State* L, int index) { return static_cast < - unsigned short > (luaL_checknumber (L, index)); } }; - -// long -template <> struct Stack < - long > { static inline void push (lua_State* L, - long value) { lua_pushnumber (L, static_cast (value)); } static inline - long get (lua_State* L, int index) { return static_cast < - long > (luaL_checknumber (L, index)); } }; - -// unsigned long -template <> struct Stack < - unsigned long > { static inline void push (lua_State* L, - unsigned long value) { lua_pushnumber (L, static_cast (value)); } static inline - unsigned long get (lua_State* L, int index) { return static_cast < - unsigned long > (luaL_checknumber (L, index)); } }; - -// float -template <> struct Stack < - float > { static inline void push (lua_State* L, - float value) { lua_pushnumber (L, static_cast (value)); } static inline - float get (lua_State* L, int index) { return static_cast < - float > (luaL_checknumber (L, index)); } }; - -// double -template <> struct Stack < - double > { static inline void push (lua_State* L, - double value) { lua_pushnumber (L, static_cast (value)); } static inline - double get (lua_State* L, int index) { return static_cast < - double > (luaL_checknumber (L, index)); } }; - -// bool -template <> -struct Stack -{ - static inline void push (lua_State* L, bool value) - { - lua_pushboolean (L, value ? 1 : 0); - } - - static inline bool get (lua_State* L, int index) - { - luaL_checktype (L, index, LUA_TBOOLEAN); - - return lua_toboolean (L, index) ? true : false; - } -}; - -// char -template <> -struct Stack -{ - static inline void push (lua_State* L, char value) - { - char str [2] = { value, 0 }; - lua_pushstring (L, str); - } - - static inline char get (lua_State* L, int index) - { - return luaL_checkstring (L, index) [0]; - } -}; - -// null terminated string -template <> -struct Stack -{ - static inline void push (lua_State* L, char const* str) - { - if (str) - lua_pushstring (L, str); - else - lua_pushnil (L); - } - - static inline char const* get (lua_State* L, int index) - { - if (lua_isnil (L, index)) - return 0; - else - return luaL_checkstring (L, index); - } -}; - -// std::string -template <> -struct Stack -{ - static inline void push (lua_State* L, std::string const& str) - { - lua_pushstring (L, str.c_str ()); - } - - static inline std::string get (lua_State* L, int index) - { - return std::string (luaL_checkstring (L, index)); - } -}; - -// std::string const& -template <> -struct Stack -{ - static inline void push (lua_State* L, std::string const& str) - { - lua_pushstring (L, str.c_str()); - } - - static inline std::string get (lua_State* L, int index) - { - return std::string (luaL_checkstring (L, index)); - } -}; - -//============================================================================== -/** - Subclass of a TypeListValues constructable from the Lua stack. -*/ - -template -struct ArgList -{ -}; - -template -struct ArgList : public TypeListValues -{ - ArgList (lua_State*) - { - } -}; - -template -struct ArgList , Start> - : public TypeListValues > -{ - ArgList (lua_State* L) - : TypeListValues > (Stack ::get (L, Start), - ArgList (L)) - { - } -}; - -//============================================================================= - -/** - Provides a namespace registration in a lua_State. -*/ -class Namespace -{ -private: - Namespace& operator= (Namespace const& other); - - lua_State* const L; - int mutable m_stackSize; - -private: - //============================================================================ - /** - Error reporting. - */ - static int luaError (lua_State* L, std::string message) - { - assert (lua_isstring (L, lua_upvalueindex (1))); - std::string s; - - // Get information on the caller's caller to format the message, - // so the error appears to originate from the Lua source. - lua_Debug ar; - int result = lua_getstack (L, 2, &ar); - if (result != 0) - { - lua_getinfo (L, "Sl", &ar); - s = ar.short_src; - if (ar.currentline != -1) - { - // poor mans int to string to avoid . - lua_pushnumber (L, ar.currentline); - s = s + ":" + lua_tostring (L, -1) + ": "; - lua_pop (L, 1); - } - } - - s = s + message; - - return luaL_error (L, s.c_str ()); - } - - //---------------------------------------------------------------------------- - /** - lua_CFunction to report an error writing to a read-only value. - - The name of the variable is in the first upvalue. - */ - static int readOnlyError (lua_State* L) - { - std::string s; - - s = s + "'" + lua_tostring (L, lua_upvalueindex (1)) + "' is read-only"; - - return luaL_error (L, s.c_str ()); - } - - //============================================================================ - /** - __index metamethod for a namespace or class static members. - - This handles: - - Retrieving functions and class static methods, stored in the metatable. - - Reading global and class static data, stored in the __propget table. - - Reading global and class properties, stored in the __propget table. - */ - static int indexMetaMethod (lua_State* L) - { - int result = 0; - lua_getmetatable (L, 1); // push metatable of arg1 - for (;;) - { - lua_pushvalue (L, 2); // push key arg2 - lua_rawget (L, -2); // lookup key in metatable - if (lua_isnil (L, -1)) // not found - { - lua_pop (L, 1); // discard nil - rawgetfield (L, -1, "__propget"); // lookup __propget in metatable - lua_pushvalue (L, 2); // push key arg2 - lua_rawget (L, -2); // lookup key in __propget - lua_remove (L, -2); // discard __propget - if (lua_iscfunction (L, -1)) - { - lua_remove (L, -2); // discard metatable - lua_pushvalue (L, 1); // push arg1 - lua_call (L, 1, 1); // call cfunction - result = 1; - break; - } - else - { - assert (lua_isnil (L, -1)); - lua_pop (L, 1); // discard nil and fall through - } - } - else - { - assert (lua_istable (L, -1) || lua_iscfunction (L, -1)); - lua_remove (L, -2); - result = 1; - break; - } - - rawgetfield (L, -1, "__parent"); - if (lua_istable (L, -1)) - { - // Remove metatable and repeat the search in __parent. - lua_remove (L, -2); - } - else - { - // Discard metatable and return nil. - assert (lua_isnil (L, -1)); - lua_remove (L, -2); - result = 1; - break; - } - } - - return result; - } - - //---------------------------------------------------------------------------- - /** - __newindex metamethod for a namespace or class static members. - - The __propset table stores proxy functions for assignment to: - - Global and class static data. - - Global and class properties. - */ - static int newindexMetaMethod (lua_State* L) - { - int result = 0; - lua_getmetatable (L, 1); // push metatable of arg1 - for (;;) - { - rawgetfield (L, -1, "__propset"); // lookup __propset in metatable - assert (lua_istable (L, -1)); - lua_pushvalue (L, 2); // push key arg2 - lua_rawget (L, -2); // lookup key in __propset - lua_remove (L, -2); // discard __propset - if (lua_iscfunction (L, -1)) // ensure value is a cfunction - { - lua_remove (L, -2); // discard metatable - lua_pushvalue (L, 3); // push new value arg3 - lua_call (L, 1, 0); // call cfunction - result = 0; - break; - } - else - { - assert (lua_isnil (L, -1)); - lua_pop (L, 1); - } - - rawgetfield (L, -1, "__parent"); - if (lua_istable (L, -1)) - { - // Remove metatable and repeat the search in __parent. - lua_remove (L, -2); - } - else - { - assert (lua_isnil (L, -1)); - lua_pop (L, 2); - result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2)); - } - } - - return result; - } - - //---------------------------------------------------------------------------- - /** - lua_CFunction to get a variable. - - This is used for global variables or class static data members. - */ - template - static int getVariable (lua_State* L) - { - assert (lua_islightuserdata (L, lua_upvalueindex (1))); - T const* const data = static_cast (lua_touserdata (L, lua_upvalueindex (1))); - assert (data != 0); - Stack ::push (L, *data); - return 1; - } - - //---------------------------------------------------------------------------- - /** - lua_CFunction to set a variable. - - This is used for global variables or class static data members. - */ - template - static int setVariable (lua_State* L) - { - assert (lua_islightuserdata (L, lua_upvalueindex (1))); - T* const data = static_cast (lua_touserdata (L, lua_upvalueindex (1))); - assert (data != 0); - *data = Stack ::get (L, 1); - return 0; - } - - //---------------------------------------------------------------------------- - /** - lua_CFunction to call a function with a return value. - - This is used for global functions, global properties, class static methods, - and class static properties. - */ - template ::ReturnType> - struct CallFunction - { - typedef typename FuncTraits ::Params Params; - static int call (lua_State* L) - { - assert (lua_isuserdata (L, lua_upvalueindex (1))); - Func const& fp = *static_cast ( - lua_touserdata (L, lua_upvalueindex (1))); - assert (fp != 0); - ArgList args (L); - Stack ::ReturnType>::push ( - L, FuncTraits ::call (fp, args)); - return 1; - } - }; - - //---------------------------------------------------------------------------- - /** - lua_CFunction to call a function with no return value. - - This is used for global functions, global properties, class static methods, - and class static properties. - */ - template - struct CallFunction - { - typedef typename FuncTraits ::Params Params; - static int call (lua_State* L) - { - assert (lua_isuserdata (L, lua_upvalueindex (1))); - Func const& fp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - assert (fp != 0); - ArgList args (L); - FuncTraits ::call (fp, args); - return 0; - } - }; - - //============================================================================ - /** - lua_CFunction to call a class member function with a return value. - */ - template ::ReturnType> - struct CallMemberFunction - { - typedef typename FuncTraits ::ClassType T; - typedef typename FuncTraits ::Params Params; - - static int call (lua_State* L) - { - assert (lua_isuserdata (L, lua_upvalueindex (1))); - T* const t = Detail::Userdata::get (L, 1, false); - MemFn fp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - ArgList args (L); - Stack ::push (L, FuncTraits ::call (t, fp, args)); - return 1; - } - - static int callConst (lua_State* L) - { - assert (lua_isuserdata (L, lua_upvalueindex (1))); - T const* const t = Detail::Userdata::get (L, 1, true); - MemFn fp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - ArgList args(L); - Stack ::push (L, FuncTraits ::call (t, fp, args)); - return 1; - } - }; - - //---------------------------------------------------------------------------- - /** - lua_CFunction to call a class member function with no return value. - */ - template - struct CallMemberFunction - { - typedef typename FuncTraits ::ClassType T; - typedef typename FuncTraits ::Params Params; - - static int call (lua_State* L) - { - T* const t = Detail::Userdata::get (L, 1, false); - MemFn const fp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - ArgList args (L); - FuncTraits ::call (t, fp, args); - return 0; - } - - static int callConst (lua_State* L) - { - T const* const t = Detail::Userdata::get (L, 1, true); - MemFn const fp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - ArgList args (L); - FuncTraits ::call (t, fp, args); - return 0; - } - }; - - //---------------------------------------------------------------------------- - /** - lua_CFunction to call a class member lua_CFunction - */ - template - struct CallMemberCFunction - { - static int call (lua_State* L) - { - typedef int (T::*MFP)(lua_State* L); - T* const t = Detail::Userdata::get (L, 1, false); - MFP const mfp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - return (t->*mfp) (L); - } - - static int callConst (lua_State* L) - { - typedef int (T::*MFP)(lua_State* L); - T const* const t = Detail::Userdata::get (L, 1, true); - MFP const mfp = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); - return (t->*mfp) (L); - } - }; - - //---------------------------------------------------------------------------- - - // SFINAE Helpers - - template - struct CallMemberFunctionHelper - { - static void add (lua_State* L, char const* name, MemFn mf) - { - new (lua_newuserdata (L, sizeof (MemFn))) MemFn (mf); - lua_pushcclosure (L, &CallMemberFunction ::callConst, 1); - lua_pushvalue (L, -1); - rawsetfield (L, -5, name); // const table - rawsetfield (L, -3, name); // class table - } - }; - - template - struct CallMemberFunctionHelper - { - static void add (lua_State* L, char const* name, MemFn mf) - { - new (lua_newuserdata (L, sizeof (MemFn))) MemFn (mf); - lua_pushcclosure (L, &CallMemberFunction ::call, 1); - rawsetfield (L, -3, name); // class table - } - }; - - //---------------------------------------------------------------------------- - /** - Pop the Lua stack. - */ - void pop (int n) const - { - if (m_stackSize >= n && lua_gettop (L) >= n) - { - lua_pop (L, n); - m_stackSize -= n; - } - else - { - throw std::logic_error ("invalid stack"); - } - } - -private: - //============================================================================ - // - // ClassBase - // - //============================================================================ - /** - Factored base to reduce template instantiations. - */ - class ClassBase - { - private: - ClassBase& operator= (ClassBase const& other); - - protected: - friend class Namespace; - - lua_State* const L; - int mutable m_stackSize; - - protected: - //-------------------------------------------------------------------------- - /** - __index metamethod for a class. - - This implements member functions, data members, and property members. - Functions are stored in the metatable and const metatable. Data members - and property members are in the __propget table. - - If the key is not found, the search proceeds up the hierarchy of base - classes. - */ - static int indexMetaMethod (lua_State* L) - { - int result = 0; - - assert (lua_isuserdata (L, 1)); // warn on security bypass - lua_getmetatable (L, 1); // get metatable for object - for (;;) - { - lua_pushvalue (L, 2); // push key arg2 - lua_rawget (L, -2); // lookup key in metatable - if (lua_iscfunction (L, -1)) // ensure its a cfunction - { - lua_remove (L, -2); // remove metatable - result = 1; - break; - } - else if (lua_isnil (L, -1)) - { - lua_pop (L, 1); - } - else - { - lua_pop (L, 2); - throw std::logic_error ("not a cfunction"); - } - - rawgetfield (L, -1, "__propget"); // get __propget table - if (lua_istable (L, -1)) // ensure it is a table - { - lua_pushvalue (L, 2); // push key arg2 - lua_rawget (L, -2); // lookup key in __propget - lua_remove (L, -2); // remove __propget - if (lua_iscfunction (L, -1)) // ensure its a cfunction - { - lua_remove (L, -2); // remove metatable - lua_pushvalue (L, 1); // push class arg1 - lua_call (L, 1, 1); - result = 1; - break; - } - else if (lua_isnil (L, -1)) - { - lua_pop (L, 1); - } - else - { - lua_pop (L, 2); - - // We only put cfunctions into __propget. - throw std::logic_error ("not a cfunction"); - } - } - else - { - lua_pop (L, 2); - - // __propget is missing, or not a table. - throw std::logic_error ("missing __propget table"); - } - - // Repeat the lookup in the __parent metafield, - // or return nil if the field doesn't exist. - rawgetfield (L, -1, "__parent"); - if (lua_istable (L, -1)) - { - // Remove metatable and repeat the search in __parent. - lua_remove (L, -2); - } - else if (lua_isnil (L, -1)) - { - result = 1; - break; - } - else - { - lua_pop (L, 2); - - throw std::logic_error ("__parent is not a table"); - } - } - - return result; - } - - //-------------------------------------------------------------------------- - /** - __newindex metamethod for classes. - - This supports writable variables and properties on class objects. The - corresponding object is passed in the first parameter to the set function. - */ - static int newindexMetaMethod (lua_State* L) - { - int result = 0; - - lua_getmetatable (L, 1); - - for (;;) - { - // Check __propset - rawgetfield (L, -1, "__propset"); - if (!lua_isnil (L, -1)) - { - lua_pushvalue (L, 2); - lua_rawget (L, -2); - if (!lua_isnil (L, -1)) - { - // found it, call the setFunction. - assert (lua_isfunction (L, -1)); - lua_pushvalue (L, 1); - lua_pushvalue (L, 3); - lua_call (L, 2, 0); - result = 0; - break; - } - lua_pop (L, 1); - } - lua_pop (L, 1); - - // Repeat the lookup in the __parent metafield. - rawgetfield (L, -1, "__parent"); - if (lua_isnil (L, -1)) - { - // Either the property or __parent must exist. - result = luaL_error (L, - "no member named '%s'", lua_tostring (L, 2)); - } - lua_remove (L, -2); - } - - return result; - } - - //-------------------------------------------------------------------------- - /** - Create the const table. - */ - void createConstTable (char const* name) - { - lua_newtable (L); - lua_pushvalue (L, -1); - lua_setmetatable (L, -2); - lua_pushboolean (L, 1); - lua_rawsetp (L, -2, Detail::getIdentityKey ()); - lua_pushstring (L, (std::string ("const ") + name).c_str ()); - rawsetfield (L, -2, "__type"); - lua_pushcfunction (L, &indexMetaMethod); - rawsetfield (L, -2, "__index"); - lua_pushcfunction (L, &newindexMetaMethod); - rawsetfield (L, -2, "__newindex"); - lua_newtable (L); - rawsetfield (L, -2, "__propget"); - - if (Detail::Security::hideMetatables ()) - { - lua_pushnil (L); - rawsetfield (L, -2, "__metatable"); - } - } - - //-------------------------------------------------------------------------- - /** - Create the class table. - - The Lua stack should have the const table on top. - */ - void createClassTable (char const* name) - { - lua_newtable (L); - lua_pushvalue (L, -1); - lua_setmetatable (L, -2); - lua_pushboolean (L, 1); - lua_rawsetp (L, -2, Detail::getIdentityKey ()); - lua_pushstring (L, name); - rawsetfield (L, -2, "__type"); - lua_pushcfunction (L, &indexMetaMethod); - rawsetfield (L, -2, "__index"); - lua_pushcfunction (L, &newindexMetaMethod); - rawsetfield (L, -2, "__newindex"); - lua_newtable (L); - rawsetfield (L, -2, "__propget"); - lua_newtable (L); - rawsetfield (L, -2, "__propset"); - - lua_pushvalue (L, -2); - rawsetfield (L, -2, "__const"); // point to const table - - lua_pushvalue (L, -1); - rawsetfield (L, -3, "__class"); // point const table to class table - - if (Detail::Security::hideMetatables ()) - { - lua_pushnil (L); - rawsetfield (L, -2, "__metatable"); - } - } - - //-------------------------------------------------------------------------- - /** - Create the static table. - - The Lua stack should have: - -1 class table - -2 const table - -3 enclosing namespace - */ - void createStaticTable (char const* name) - { - lua_newtable (L); - lua_newtable (L); - lua_pushvalue (L, -1); - lua_setmetatable (L, -3); - lua_insert (L, -2); - rawsetfield (L, -5, name); - -#if 0 - lua_pushlightuserdata (L, this); - lua_pushcclosure (L, &tostringMetaMethod, 1); - rawsetfield (L, -2, "__tostring"); -#endif - lua_pushcfunction (L, &Namespace::indexMetaMethod); - rawsetfield (L, -2, "__index"); - lua_pushcfunction (L, &Namespace::newindexMetaMethod); - rawsetfield (L, -2, "__newindex"); - lua_newtable (L); - rawsetfield (L, -2, "__propget"); - lua_newtable (L); - rawsetfield (L, -2, "__propset"); - - lua_pushvalue (L, -2); - rawsetfield (L, -2, "__class"); // point to class table - - if (Detail::Security::hideMetatables ()) - { - lua_pushnil (L); - rawsetfield (L, -2, "__metatable"); - } - } - - //========================================================================== - /** - lua_CFunction to construct a class object wrapped in a container. - */ - template - static int ctorContainerProxy (lua_State* L) - { - typedef typename ContainerTraits ::Type T; - ArgList args (L); - T* const p = Constructor ::call (args); - Detail::UserdataSharedHelper ::push (L, p); - return 1; - } - - //-------------------------------------------------------------------------- - /** - lua_CFunction to construct a class object in-place in the userdata. - */ - template - static int ctorPlacementProxy (lua_State* L) - { - ArgList args (L); - Constructor ::call (Detail::UserdataValue ::place (L), args); - return 1; - } - - //-------------------------------------------------------------------------- - /** - Pop the Lua stack. - */ - void pop (int n) const - { - if (m_stackSize >= n && lua_gettop (L) >= n) - { - lua_pop (L, n); - m_stackSize -= n; - } - else - { - throw std::logic_error ("invalid stack"); - } - } - - public: - //-------------------------------------------------------------------------- - explicit ClassBase (lua_State* L_) - : L (L_) - , m_stackSize (0) - { - } - - //-------------------------------------------------------------------------- - /** - Copy Constructor. - */ - ClassBase (ClassBase const& other) - : L (other.L) - , m_stackSize (0) - { - m_stackSize = other.m_stackSize; - other.m_stackSize = 0; - } - - ~ClassBase () - { - pop (m_stackSize); - } - }; - - //============================================================================ - // - // Class - // - //============================================================================ - /** - Provides a class registration in a lua_State. - - After contstruction the Lua stack holds these objects: - -1 static table - -2 class table - -3 const table - -4 (enclosing namespace) - */ - template - class Class : public ClassBase - { - private: - //-------------------------------------------------------------------------- - /** - __gc metamethod for a class. - */ - static int gcMetaMethod (lua_State* L) - { - Detail::Userdata* ud = Detail::Userdata::getExact (L, 1); - ud->~Userdata (); - return 0; - } - - //-------------------------------------------------------------------------- - /** - lua_CFunction to get a class data member. - */ - template - static int getProperty (lua_State* L) - { - T const* const t = Detail::Userdata::get (L, 1, true); - U T::** mp = static_cast (lua_touserdata (L, lua_upvalueindex (1))); - Stack ::push (L, t->**mp); - return 1; - } - - //-------------------------------------------------------------------------- - /** - lua_CFunction to set a class data member. - - @note The expected class name is in upvalue 1, and the pointer to the - data member is in upvalue 2. - */ - template - static int setProperty (lua_State* L) - { - T* const t = Detail::Userdata::get (L, 1, false); - U T::** mp = static_cast (lua_touserdata (L, lua_upvalueindex (1))); - t->**mp = Stack ::get (L, 2); - return 0; - } - - public: - //========================================================================== - /** - Register a new class or add to an existing class registration. - */ - Class (char const* name, Namespace const* parent) : ClassBase (parent->L) - { - m_stackSize = parent->m_stackSize + 3; - parent->m_stackSize = 0; - - assert (lua_istable (L, -1)); - rawgetfield (L, -1, name); - - if (lua_isnil (L, -1)) - { - lua_pop (L, 1); - - createConstTable (name); - lua_pushcfunction (L, &gcMetaMethod); - rawsetfield (L, -2, "__gc"); - - createClassTable (name); - lua_pushcfunction (L, &gcMetaMethod); - rawsetfield (L, -2, "__gc"); - - createStaticTable (name); - - // Map T back to its tables. - lua_pushvalue (L, -1); - lua_rawsetp (L, LUA_REGISTRYINDEX, Detail::ClassInfo ::getStaticKey ()); - lua_pushvalue (L, -2); - lua_rawsetp (L, LUA_REGISTRYINDEX, Detail::ClassInfo ::getClassKey ()); - lua_pushvalue (L, -3); - lua_rawsetp (L, LUA_REGISTRYINDEX, Detail::ClassInfo ::getConstKey ()); - } - else - { - rawgetfield (L, -1, "__class"); - rawgetfield (L, -1, "__const"); - - // Reverse the top 3 stack elements - lua_insert (L, -3); - lua_insert (L, -2); - } - } - - //========================================================================== - /** - Derive a new class. - */ - Class (char const* name, Namespace const* parent, void const* const staticKey) - : ClassBase (parent->L) - { - m_stackSize = parent->m_stackSize + 3; - parent->m_stackSize = 0; - - assert (lua_istable (L, -1)); - - createConstTable (name); - lua_pushcfunction (L, &gcMetaMethod); - rawsetfield (L, -2, "__gc"); - - createClassTable (name); - lua_pushcfunction (L, &gcMetaMethod); - rawsetfield (L, -2, "__gc"); - - createStaticTable (name); - - lua_rawgetp (L, LUA_REGISTRYINDEX, staticKey); - assert (lua_istable (L, -1)); - rawgetfield (L, -1, "__class"); - assert (lua_istable (L, -1)); - rawgetfield (L, -1, "__const"); - assert (lua_istable (L, -1)); - - rawsetfield (L, -6, "__parent"); - rawsetfield (L, -4, "__parent"); - rawsetfield (L, -2, "__parent"); - - lua_pushvalue (L, -1); - lua_rawsetp (L, LUA_REGISTRYINDEX, Detail::ClassInfo ::getStaticKey ()); - lua_pushvalue (L, -2); - lua_rawsetp (L, LUA_REGISTRYINDEX, Detail::ClassInfo ::getClassKey ()); - lua_pushvalue (L, -3); - lua_rawsetp (L, LUA_REGISTRYINDEX, Detail::ClassInfo ::getConstKey ()); - } - - //-------------------------------------------------------------------------- - /** - Continue registration in the enclosing namespace. - */ - Namespace endClass () - { - return Namespace (this); - } - - //-------------------------------------------------------------------------- - /** - Add or replace a static data member. - */ - template - Class & addStaticData (char const* name, U* pu, bool isWritable = true) - { - assert (lua_istable (L, -1)); - - rawgetfield (L, -1, "__propget"); - assert (lua_istable (L, -1)); - lua_pushlightuserdata (L, pu); - lua_pushcclosure (L, &getVariable , 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - - rawgetfield (L, -1, "__propset"); - assert (lua_istable (L, -1)); - if (isWritable) - { - lua_pushlightuserdata (L, pu); - lua_pushcclosure (L, &setVariable , 1); - } - else - { - lua_pushstring (L, name); - lua_pushcclosure (L, &readOnlyError, 1); - } - rawsetfield (L, -2, name); - lua_pop (L, 1); - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a static property member. - - If the set function is null, the property is read-only. - */ - template - Class & addStaticProperty (char const* name, U (*get)(), void (*set)(U) = 0) - { - typedef U (*get_t)(); - typedef void (*set_t)(U); - - assert (lua_istable (L, -1)); - - rawgetfield (L, -1, "__propget"); - assert (lua_istable (L, -1)); - new (lua_newuserdata (L, sizeof (get))) get_t (get); - lua_pushcclosure (L, &CallFunction ::call, 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - - rawgetfield (L, -1, "__propset"); - assert (lua_istable (L, -1)); - if (set != 0) - { - new (lua_newuserdata (L, sizeof (set))) set_t (set); - lua_pushcclosure (L, &CallFunction ::call, 1); - } - else - { - lua_pushstring (L, name); - lua_pushcclosure (L, &readOnlyError, 1); - } - rawsetfield (L, -2, name); - lua_pop (L, 1); - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a static member function. - */ - template - Class & addStaticFunction (char const* name, FP const fp) - { - new (lua_newuserdata (L, sizeof (fp))) FP (fp); - lua_pushcclosure (L, &CallFunction ::call, 1); - rawsetfield (L, -2, name); - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a lua_CFunction. - */ - Class & addStaticCFunction (char const* name, int (*const fp)(lua_State*)) - { - lua_pushcfunction (L, fp); - rawsetfield (L, -2, name); - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a data member. - */ - template - Class & addData (char const* name, const U T::* mp, bool isWritable = true) - { - typedef const U T::*mp_t; - - // Add to __propget in class and const tables. - { - rawgetfield (L, -2, "__propget"); - rawgetfield (L, -4, "__propget"); - new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); - lua_pushcclosure (L, &getProperty , 1); - lua_pushvalue (L, -1); - rawsetfield (L, -4, name); - rawsetfield (L, -2, name); - lua_pop (L, 2); - } - - if (isWritable) - { - // Add to __propset in class table. - rawgetfield (L, -2, "__propset"); - assert (lua_istable (L, -1)); - new (lua_newuserdata (L, sizeof (mp_t))) mp_t (mp); - lua_pushcclosure (L, &setProperty , 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - } - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a property member. - */ - template - Class & addProperty (char const* name, TG (T::* get) () const, void (T::* set) (TS)) - { - // Add to __propget in class and const tables. - { - rawgetfield (L, -2, "__propget"); - rawgetfield (L, -4, "__propget"); - typedef TG (T::*get_t) () const; - new (lua_newuserdata (L, sizeof (get_t))) get_t (get); - lua_pushcclosure (L, &CallMemberFunction ::callConst, 1); - lua_pushvalue (L, -1); - rawsetfield (L, -4, name); - rawsetfield (L, -2, name); - lua_pop (L, 2); - } - - { - // Add to __propset in class table. - rawgetfield (L, -2, "__propset"); - assert (lua_istable (L, -1)); - typedef void (T::* set_t) (TS); - new (lua_newuserdata (L, sizeof (set_t))) set_t (set); - lua_pushcclosure (L, &CallMemberFunction ::call, 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - } - - return *this; - } - - // read-only - template - Class & addProperty (char const* name, TG (T::* get) () const) - { - // Add to __propget in class and const tables. - rawgetfield (L, -2, "__propget"); - rawgetfield (L, -4, "__propget"); - typedef TG (T::*get_t) () const; - new (lua_newuserdata (L, sizeof (get_t))) get_t (get); - lua_pushcclosure (L, &CallMemberFunction ::callConst, 1); - lua_pushvalue (L, -1); - rawsetfield (L, -4, name); - rawsetfield (L, -2, name); - lua_pop (L, 2); - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a property member, by proxy. - - When a class is closed for modification and does not provide (or cannot - provide) the function signatures necessary to implement get or set for - a property, this will allow non-member functions act as proxies. - - Both the get and the set functions require a T const* and T* in the first - argument respectively. - */ - template - Class & addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS)) - { - // Add to __propget in class and const tables. - { - rawgetfield (L, -2, "__propget"); - rawgetfield (L, -4, "__propget"); - typedef TG (*get_t) (T const*); - new (lua_newuserdata (L, sizeof (get_t))) get_t (get); - lua_pushcclosure (L, &CallFunction ::call, 1); - lua_pushvalue (L, -1); - rawsetfield (L, -4, name); - rawsetfield (L, -2, name); - lua_pop (L, 2); - } - - if (set != 0) - { - // Add to __propset in class table. - rawgetfield (L, -2, "__propset"); - assert (lua_istable (L, -1)); - typedef void (*set_t) (T*, TS); - new (lua_newuserdata (L, sizeof (set_t))) set_t (set); - lua_pushcclosure (L, &CallFunction ::call, 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - } - - return *this; - } - - // read-only - template - Class & addProperty (char const* name, TG (*get) (T const*)) - { - // Add to __propget in class and const tables. - rawgetfield (L, -2, "__propget"); - rawgetfield (L, -4, "__propget"); - typedef TG (*get_t) (T const*); - new (lua_newuserdata (L, sizeof (get_t))) get_t (get); - lua_pushcclosure (L, &CallFunction ::call, 1); - lua_pushvalue (L, -1); - rawsetfield (L, -4, name); - rawsetfield (L, -2, name); - lua_pop (L, 2); - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a member function. - */ - template - Class & addFunction (char const* name, MemFn mf) - { - CallMemberFunctionHelper ::isConstMemberFunction>::add (L, name, mf); - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a member lua_CFunction. - */ - Class & addCFunction (char const* name, int (T::*mfp)(lua_State*)) - { - typedef int (T::*MFP)(lua_State*); - assert (lua_istable (L, -1)); - new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); - lua_pushcclosure (L, &CallMemberCFunction ::call, 1); - rawsetfield (L, -3, name); // class table - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a const member lua_CFunction. - */ - Class & addCFunction (char const* name, int (T::*mfp)(lua_State*) const) - { - typedef int (T::*MFP)(lua_State*) const; - assert (lua_istable (L, -1)); - new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp); - lua_pushcclosure (L, &CallMemberCFunction ::callConst, 1); - lua_pushvalue (L, -1); - rawsetfield (L, -5, name); // const table - rawsetfield (L, -3, name); // class table - - return *this; - } - - //-------------------------------------------------------------------------- - /** - Add or replace a primary Constructor. - - The primary Constructor is invoked when calling the class type table - like a function. - - The template parameter should be a function pointer type that matches - the desired Constructor (since you can't take the address of a Constructor - and pass it as an argument). - */ - template - Class & addConstructor () - { - lua_pushcclosure (L, - &ctorContainerProxy ::Params, C>, 0); - rawsetfield(L, -2, "__call"); - - return *this; - } - - template - Class & addConstructor () - { - lua_pushcclosure (L, - &ctorPlacementProxy ::Params, T>, 0); - rawsetfield(L, -2, "__call"); - - return *this; - } - }; - -private: - //============================================================================ - // - // Namespace (Cont.) - // - //============================================================================ - - //---------------------------------------------------------------------------- - /** - Opens the global namespace. - */ - explicit Namespace (lua_State* L_) - : L (L_) - , m_stackSize (0) - { - lua_getglobal (L, "_G"); - ++m_stackSize; - } - - //---------------------------------------------------------------------------- - /** - Opens a namespace for registrations. - - The namespace is created if it doesn't already exist. The parent - namespace is at the top of the Lua stack. - */ - Namespace (char const* name, Namespace const* parent) - : L (parent->L) - , m_stackSize (0) - { - m_stackSize = parent->m_stackSize + 1; - parent->m_stackSize = 0; - - assert (lua_istable (L, -1)); - rawgetfield (L, -1, name); - if (lua_isnil (L, -1)) - { - lua_pop (L, 1); - - lua_newtable (L); - lua_pushvalue (L, -1); - lua_setmetatable (L, -2); - lua_pushcfunction (L, &indexMetaMethod); - rawsetfield (L, -2, "__index"); - lua_pushcfunction (L, &newindexMetaMethod); - rawsetfield (L, -2, "__newindex"); - lua_newtable (L); - rawsetfield (L, -2, "__propget"); - lua_newtable (L); - rawsetfield (L, -2, "__propset"); - lua_pushvalue (L, -1); - rawsetfield (L, -3, name); -#if 0 - lua_pushcfunction (L, &tostringMetaMethod); - rawsetfield (L, -2, "__tostring"); -#endif - } - } - - //---------------------------------------------------------------------------- - /** - Creates a continued registration from a child namespace. - */ - explicit Namespace (Namespace const* child) - : L (child->L) - , m_stackSize (0) - { - m_stackSize = child->m_stackSize - 1; - child->m_stackSize = 1; - child->pop (1); - - // It is not necessary or valid to call - // endNamespace() for the global namespace! - // - assert (m_stackSize != 0); - } - - //---------------------------------------------------------------------------- - /** - Creates a continued registration from a child class. - */ - explicit Namespace (ClassBase const* child) - : L (child->L) - , m_stackSize (0) - { - m_stackSize = child->m_stackSize - 3; - child->m_stackSize = 3; - child->pop (3); - } - -public: - //---------------------------------------------------------------------------- - /** - Copy Constructor. - - Ownership of the stack is transferred to the new object. This happens when - the compiler emits temporaries to hold these objects while chaining - registrations across namespaces. - */ - Namespace (Namespace const& other) : L (other.L) - { - m_stackSize = other.m_stackSize; - other.m_stackSize = 0; - } - - //---------------------------------------------------------------------------- - /** - Closes this namespace registration. - */ - ~Namespace () - { - pop (m_stackSize); - } - - //---------------------------------------------------------------------------- - /** - Open the global namespace. - */ - static Namespace getGlobalNamespace (lua_State* L) - { - return Namespace (L); - } - - //---------------------------------------------------------------------------- - /** - Open a new or existing namespace for registrations. - */ - Namespace beginNamespace (char const* name) - { - return Namespace (name, this); - } - - //---------------------------------------------------------------------------- - /** - Continue namespace registration in the parent. - - Do not use this on the global namespace. - */ - Namespace endNamespace () - { - return Namespace (this); - } - - //---------------------------------------------------------------------------- - /** - Add or replace a variable. - */ - template - Namespace& addVariable (char const* const name, T* const pt, bool const isWritable = true) - { - assert (lua_istable (L, -1)); - - rawgetfield (L, -1, "__propget"); - assert (lua_istable (L, -1)); - lua_pushlightuserdata (L, pt); - lua_pushcclosure (L, &getVariable , 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - - rawgetfield (L, -1, "__propset"); - assert (lua_istable (L, -1)); - if (isWritable) - { - lua_pushlightuserdata (L, pt); - lua_pushcclosure (L, &setVariable , 1); - } - else - { - lua_pushstring (L, name); - lua_pushcclosure (L, &readOnlyError, 1); - } - rawsetfield (L, -2, name); - lua_pop (L, 1); - - return *this; - } - - //---------------------------------------------------------------------------- - /** - Add or replace a property. - - If the set function is omitted or null, the property is read-only. - */ - template - Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0) - { - assert (lua_istable (L, -1)); - - rawgetfield (L, -1, "__propget"); - assert (lua_istable (L, -1)); - lua_pushlightuserdata (L, get); - lua_pushcclosure (L, &CallFunction ::call, 1); - rawsetfield (L, -2, name); - lua_pop (L, 1); - - rawgetfield (L, -1, "__propset"); - assert (lua_istable (L, -1)); - if (set != 0) - { - lua_pushlightuserdata (L, set); - lua_pushcclosure (L, &CallFunction ::call, 1); - } - else - { - lua_pushstring (L, name); - lua_pushcclosure (L, &readOnlyError, 1); - } - rawsetfield (L, -2, name); - lua_pop (L, 1); - - return *this; - } - - //---------------------------------------------------------------------------- - /** - Add or replace a function. - */ - template - Namespace& addFunction (char const* name, FP const fp) - { - assert (lua_istable (L, -1)); - - new (lua_newuserdata (L, sizeof (fp))) FP (fp); - lua_pushcclosure (L, &CallFunction ::call, 1); - rawsetfield (L, -2, name); - - return *this; - } - - //---------------------------------------------------------------------------- - /** - Add or replace a lua_CFunction. - */ - Namespace& addCFunction (char const* name, int (*const fp)(lua_State*)) - { - lua_pushcfunction (L, fp); - rawsetfield (L, -2, name); - - return *this; - } - - //---------------------------------------------------------------------------- - /** - Open a new or existing class for registrations. - */ - template - Class beginClass (char const* name) - { - return Class (name, this); - } - - //---------------------------------------------------------------------------- - /** - Derive a new class for registrations. - - To continue registrations for the class later, use beginClass(). - Do not call deriveClass() again. - */ - template - Class deriveClass (char const* name) - { - return Class (name, this, Detail::ClassInfo ::getStaticKey ()); - } -}; - -//============================================================================== -/** - Retrieve the global namespace. - - It is recommended to put your namespace inside the global namespace, and then - add your classes and functions to it, rather than adding many classes and - functions directly to the global namespace. -*/ -inline Namespace getGlobalNamespace (lua_State* L) -{ - return Namespace::getGlobalNamespace (L); -} - -//------------------------------------------------------------------------------ -/** - Push objects onto the Lua stack. -*/ -template -inline void push (lua_State* L, T t) -{ - Stack ::push (L, t); -} - -//------------------------------------------------------------------------------ -/** - Set a global value in the lua_State. -*/ -template -inline void setglobal (lua_State* L, T t, char const* name) -{ - push (L, t); - lua_setglobal (L, name); -} - -//------------------------------------------------------------------------------ -/** - Change whether or not metatables are hidden (on by default). -*/ -inline void setHideMetatables (bool shouldHide) -{ - Detail::Security::setHideMetatables (shouldHide); -} - -} - -//============================================================================== - -#endif diff --git a/common/luabridge/RefCountedObject.h b/common/luabridge/RefCountedObject.h deleted file mode 100644 index 2d4cfbaab..000000000 --- a/common/luabridge/RefCountedObject.h +++ /dev/null @@ -1,348 +0,0 @@ -//============================================================================== -/* - https://github.com/vinniefalco/LuaBridge - https://github.com/vinniefalco/LuaBridgeDemo - - Copyright (C) 2012, Vinnie Falco - Copyright 2004-11 by Raw Material Software Ltd. - - This is a derivative work used by permission from part of - JUCE, available at http://www.rawaterialsoftware.com - - License: The MIT License (http://www.opensource.org/licenses/mit-license.php) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - - This file incorporates work covered by the following copyright and - permission notice: - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-11 by Raw Material Software Ltd. -*/ -//============================================================================== - -#ifndef LUABRIDGE_REFCOUNTEDOBJECT_HEADER -#define LUABRIDGE_REFCOUNTEDOBJECT_HEADER - -#if !defined (LUABRIDGE_LUABRIDGE_HEADER) -#error LuaBridge.h must be included before including this file -#endif - -//#define LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 - -//============================================================================== -/** - Adds reference-counting to an object. - - To add reference-counting to a class, derive it from this class, and - use the RefCountedObjectPtr class to point to it. - - e.g. @code - class MyClass : public RefCountedObjectType - { - void foo(); - - // This is a neat way of declaring a typedef for a pointer class, - // rather than typing out the full templated name each time.. - typedef RefCountedObjectPtr Ptr; - }; - - MyClass::Ptr p = new MyClass(); - MyClass::Ptr p2 = p; - p = 0; - p2->foo(); - @endcode - - Once a new RefCountedObjectType has been assigned to a pointer, be - careful not to delete the object manually. -*/ -template -class RefCountedObjectType -{ -public: - //============================================================================== - /** Increments the object's reference count. - - This is done automatically by the smart pointer, but is public just - in case it's needed for nefarious purposes. - */ - inline void incReferenceCount() const - { - ++refCount; - } - - /** Decreases the object's reference count. - - If the count gets to zero, the object will be deleted. - */ - inline void decReferenceCount() const - { - assert (getReferenceCount() > 0); - - if (--refCount == 0) - delete this; - } - - /** Returns the object's current reference count. */ - inline int getReferenceCount() const - { - return static_cast (refCount); - } - -protected: - //============================================================================== - /** Creates the reference-counted object (with an initial ref count of zero). */ - RefCountedObjectType() : refCount () - { - } - - /** Destructor. */ - virtual ~RefCountedObjectType() - { - // it's dangerous to delete an object that's still referenced by something else! - assert (getReferenceCount() == 0); - } - -private: - //============================================================================== - CounterType mutable refCount; -}; - -//============================================================================== -/** - A smart-pointer class which points to a reference-counted object. - - The template parameter specifies the class of the object you want to point to - the easiest - way to make a class reference-countable is to simply make it inherit from RefCountedObjectType, - but if you need to, you could roll your own reference-countable class by implementing a pair of - mathods called incReferenceCount() and decReferenceCount(). - - When using this class, you'll probably want to create a typedef to abbreviate the full - templated name - e.g. - - @code typedef RefCountedObjectPtr MyClassPtr;@endcode -*/ -template -class RefCountedObjectPtr -{ -public: - /** The class being referenced by this pointer. */ - typedef ReferenceCountedObjectClass ReferencedType; - - //============================================================================== - /** Creates a pointer to a null object. */ - inline RefCountedObjectPtr() : referencedObject (0) - { - } - - /** Creates a pointer to an object. - - This will increment the object's reference-count if it is non-null. - */ - inline RefCountedObjectPtr (ReferenceCountedObjectClass* const refCountedObject) - : referencedObject (refCountedObject) - { - if (refCountedObject != 0) - refCountedObject->incReferenceCount(); - } - - /** Copies another pointer. - This will increment the object's reference-count (if it is non-null). - */ - inline RefCountedObjectPtr (const RefCountedObjectPtr& other) - : referencedObject (other.referencedObject) - { - if (referencedObject != 0) - referencedObject->incReferenceCount(); - } - -#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS - /** Takes-over the object from another pointer. */ - inline RefCountedObjectPtr (RefCountedObjectPtr&& other) - : referencedObject (other.referencedObject) - { - other.referencedObject = 0; - } -#endif - - /** Copies another pointer. - This will increment the object's reference-count (if it is non-null). - */ - template - inline RefCountedObjectPtr (const RefCountedObjectPtr& other) - : referencedObject (static_cast (other.getObject())) - { - if (referencedObject != 0) - referencedObject->incReferenceCount(); - } - - /** Changes this pointer to point at a different object. - - The reference count of the old object is decremented, and it might be - deleted if it hits zero. The new object's count is incremented. - */ - RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other) - { - return operator= (other.referencedObject); - } - - /** Changes this pointer to point at a different object. - - The reference count of the old object is decremented, and it might be - deleted if it hits zero. The new object's count is incremented. - */ - template - RefCountedObjectPtr& operator= (const RefCountedObjectPtr& other) - { - return operator= (static_cast (other.getObject())); - } - -#if LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS - /** Takes-over the object from another pointer. */ - RefCountedObjectPtr& operator= (RefCountedObjectPtr&& other) - { - std::swap (referencedObject, other.referencedObject); - return *this; - } -#endif - - /** Changes this pointer to point at a different object. - - The reference count of the old object is decremented, and it might be - deleted if it hits zero. The new object's count is incremented. - */ - RefCountedObjectPtr& operator= (ReferenceCountedObjectClass* const newObject) - { - if (referencedObject != newObject) - { - if (newObject != 0) - newObject->incReferenceCount(); - - ReferenceCountedObjectClass* const oldObject = referencedObject; - referencedObject = newObject; - - if (oldObject != 0) - oldObject->decReferenceCount(); - } - - return *this; - } - - /** Destructor. - - This will decrement the object's reference-count, and may delete it if it - gets to zero. - */ - inline ~RefCountedObjectPtr() - { - if (referencedObject != 0) - referencedObject->decReferenceCount(); - } - - /** Returns the object that this pointer references. - The pointer returned may be zero, of course. - */ - inline operator ReferenceCountedObjectClass*() const - { - return referencedObject; - } - - // the -> operator is called on the referenced object - inline ReferenceCountedObjectClass* operator->() const - { - return referencedObject; - } - - /** Returns the object that this pointer references. - The pointer returned may be zero, of course. - */ - inline ReferenceCountedObjectClass* getObject() const - { - return referencedObject; - } - -private: - //============================================================================== - ReferenceCountedObjectClass* referencedObject; -}; - -/** Compares two ReferenceCountedObjectPointers. */ -template -bool operator== (const RefCountedObjectPtr& object1, ReferenceCountedObjectClass* const object2) -{ - return object1.getObject() == object2; -} - -/** Compares two ReferenceCountedObjectPointers. */ -template -bool operator== (const RefCountedObjectPtr& object1, const RefCountedObjectPtr& object2) -{ - return object1.getObject() == object2.getObject(); -} - -/** Compares two ReferenceCountedObjectPointers. */ -template -bool operator== (ReferenceCountedObjectClass* object1, RefCountedObjectPtr& object2) -{ - return object1 == object2.getObject(); -} - -/** Compares two ReferenceCountedObjectPointers. */ -template -bool operator!= (const RefCountedObjectPtr& object1, const ReferenceCountedObjectClass* object2) -{ - return object1.getObject() != object2; -} - -/** Compares two ReferenceCountedObjectPointers. */ -template -bool operator!= (const RefCountedObjectPtr& object1, RefCountedObjectPtr& object2) -{ - return object1.getObject() != object2.getObject(); -} - -/** Compares two ReferenceCountedObjectPointers. */ -template -bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr& object2) -{ - return object1 != object2.getObject(); -} - -//============================================================================== - -namespace luabridge -{ - -template -struct ContainerTraits > -{ - typedef T Type; - - static T* get (RefCountedObjectPtr const& c) - { - return c.getObject (); - } -}; - -} - -//============================================================================== - -#endif - diff --git a/common/luabridge/RefCountedPtr.h b/common/luabridge/RefCountedPtr.h deleted file mode 100644 index 9f9217054..000000000 --- a/common/luabridge/RefCountedPtr.h +++ /dev/null @@ -1,248 +0,0 @@ -//============================================================================== -/* - https://github.com/vinniefalco/LuaBridge - https://github.com/vinniefalco/LuaBridgeDemo - - Copyright (C) 2012, Vinnie Falco - Copyright (C) 2007, Nathan Reed - - License: The MIT License (http://www.opensource.org/licenses/mit-license.php) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -//============================================================================== - -#ifndef LUABRIDGE_REFCOUNTEDPTR_HEADER -#define LUABRIDGE_REFCOUNTEDPTR_HEADER - -#ifdef _MSC_VER -# include -#else -# include -# include -#endif - -//============================================================================== -/** - Support for our RefCountedPtr. -*/ -struct RefCountedPtrBase -{ - // Declaration of container for the refcounts -#ifdef _MSC_VER - typedef stdext::hash_map RefCountsType; -#else - struct ptr_hash - { - size_t operator () (const void * const v) const - { - static __gnu_cxx::hash H; - return H(uintptr_t(v)); - } - }; - typedef __gnu_cxx::hash_map RefCountsType; -#endif - -protected: - inline RefCountsType& getRefCounts () - { - static RefCountsType refcounts; - return refcounts ; - } -}; - -//============================================================================== -/** - A reference counted smart pointer. - - The api is compatible with boost::RefCountedPtr and std::RefCountedPtr, in the - sense that it implements a strict subset of the functionality. - - This implementation uses a hash table to look up the reference count - associated with a particular pointer. - - @tparam T The class type. - - @todo Decompose RefCountedPtr using a policy. At a minimum, the underlying - reference count should be policy based (to support atomic operations) - and the delete behavior should be policy based (to support custom - disposal methods). - - @todo Provide an intrusive version of RefCountedPtr. -*/ -template -class RefCountedPtr : private RefCountedPtrBase -{ -public: - template - struct rebind - { - typedef RefCountedPtr other; - }; - - /** Construct as nullptr or from existing pointer to T. - - @param p The optional, existing pointer to assign from. - */ - RefCountedPtr (T* p = 0) : m_p (p) - { - ++getRefCounts () [m_p]; - } - - /** Construct from another RefCountedPtr. - - @param rhs The RefCountedPtr to assign from. - */ - RefCountedPtr (RefCountedPtr const& rhs) : m_p (rhs.get()) - { - ++getRefCounts () [m_p]; - } - - /** Construct from a RefCountedPtr of a different type. - - @invariant A pointer to U must be convertible to a pointer to T. - - @param rhs The RefCountedPtr to assign from. - @tparam U The other object type. - */ - template - RefCountedPtr (RefCountedPtr const& rhs) : m_p (static_cast (rhs.get())) - { - ++getRefCounts () [m_p]; - } - - /** Release the object. - - If there are no more references then the object is deleted. - */ - ~RefCountedPtr () - { - reset(); - } - - /** Assign from another RefCountedPtr. - - @param rhs The RefCountedPtr to assign from. - @return A reference to the RefCountedPtr. - */ - RefCountedPtr & operator= (RefCountedPtr const& rhs) - { - if (m_p != rhs.m_p) - { - reset (); - m_p = rhs.m_p; - ++getRefCounts () [m_p]; - } - return *this; - } - - /** Assign from another RefCountedPtr of a different type. - - @note A pointer to U must be convertible to a pointer to T. - - @tparam U The other object type. - @param rhs The other RefCountedPtr to assign from. - @return A reference to the RefCountedPtr. - */ - template - RefCountedPtr & operator= (RefCountedPtr const& rhs) - { - reset (); - m_p = static_cast (rhs.get()); - ++getRefCounts () [m_p]; - return *this; - } - - /** Retrieve the raw pointer. - - @return A pointer to the object. - */ - T* get () const - { - return m_p; - } - - /** Retrieve the raw pointer. - - @return A pointer to the object. - */ - T* operator* () const - { - return m_p; - } - - /** Retrieve the raw pointer. - - @return A pointer to the object. - */ - T* operator-> () const - { - return m_p; - } - - /** Determine the number of references. - - @note This is not thread-safe. - - @return The number of active references. - */ - long use_count () const - { - return getRefCounts () [m_p]; - } - - /** Release the pointer. - - The reference count is decremented. If the reference count reaches - zero, the object is deleted. - */ - void reset () - { - if (m_p != 0) - { - if (--getRefCounts () [m_p] <= 0) - delete m_p; - - m_p = 0; - } - } - -private: - T* m_p; -}; - -//============================================================================== - -namespace luabridge -{ - -template -struct ContainerTraits > -{ - typedef T Type; - - static T* get (RefCountedPtr const& c) - { - return c.get (); - } -}; - -} - -#endif diff --git a/luabind/CMakeLists.txt b/luabind/CMakeLists.txt new file mode 100644 index 000000000..19d694203 --- /dev/null +++ b/luabind/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) + +SET(lb_sources + src/class.cpp + src/class_info.cpp + src/class_registry.cpp + src/class_rep.cpp + src/create_class.cpp + src/error.cpp + src/exception_handler.cpp + src/function.cpp + src/inheritance.cpp + src/link_compatibility.cpp + src/object_rep.cpp + src/open.cpp + src/pcall.cpp + src/scope.cpp + src/stack_content_by_name.cpp + src/weak_ref.cpp + src/wrapper_base.cpp +) + +SET(lb_headers + +) + +ADD_LIBRARY(luabind ${lb_sources} ${lb_headers}) + + +IF(UNIX) + ADD_DEFINITIONS(-fPIC) +ENDIF(UNIX) + +SET(LIBRARY_OUTPUT_PATH ../Bin) diff --git a/luabind/luabind/adopt_policy.hpp b/luabind/luabind/adopt_policy.hpp new file mode 100644 index 000000000..5e81b948b --- /dev/null +++ b/luabind/luabind/adopt_policy.hpp @@ -0,0 +1,142 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_ADOPT_POLICY_HPP_INCLUDED +#define LUABIND_ADOPT_POLICY_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace luabind { namespace detail +{ + template + void adjust_backref_ownership(T* ptr, mpl::true_) + { + if (wrap_base* p = dynamic_cast(ptr)) + { + wrapped_self_t& wrapper = wrap_access::ref(*p); + wrapper.get(wrapper.state()); + wrapper.m_strong_ref.set(wrapper.state()); + } + } + + inline void adjust_backref_ownership(void*, mpl::false_) + {} + + template + struct adopt_pointer : pointer_converter + { + typedef adopt_pointer type; + + int const consumed_args(...) + { + return 1; + } + + template + T* apply(lua_State* L, by_pointer, int index) + { + T* ptr = pointer_converter::apply( + L, LUABIND_DECORATE_TYPE(T*), index); + + object_rep* obj = static_cast( + lua_touserdata(L, index)); + obj->release(); + + adjust_backref_ownership(ptr, boost::is_polymorphic()); + + return ptr; + } + + template + int match(lua_State* L, by_pointer, int index) + { + return pointer_converter::match( + L, LUABIND_DECORATE_TYPE(T*), index); + } + + template + void converter_postcall(lua_State*, T, int) {} + }; + + template<> + struct adopt_pointer + { + typedef adopt_pointer type; + + template + void apply(lua_State* L, T* ptr) + { + if (ptr == 0) + { + lua_pushnil(L); + return; + } + + // if there is a back_reference, then the + // ownership will be removed from the + // back reference and put on the lua stack. + if (luabind::move_back_reference(L, ptr)) + return; + + make_instance(L, std::auto_ptr(ptr)); + } + }; + + template +// struct adopt_policy : converter_policy_tag + struct adopt_policy : conversion_policy + { +// BOOST_STATIC_CONSTANT(int, index = N); + + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + + struct only_accepts_nonconst_pointers {}; + + template + struct apply + { + typedef luabind::detail::is_nonconst_pointer is_nonconst_p; + typedef typename boost::mpl::if_, only_accepts_nonconst_pointers>::type type; + }; + }; + +}} + +namespace luabind +{ + template + detail::policy_cons, detail::null_type> + adopt(LUABIND_PLACEHOLDER_ARG(N)) + { + return detail::policy_cons, detail::null_type>(); + } +} + +#endif // LUABIND_ADOPT_POLICY_HPP_INCLUDE + diff --git a/luabind/luabind/back_reference.hpp b/luabind/luabind/back_reference.hpp new file mode 100644 index 000000000..5027618fb --- /dev/null +++ b/luabind/luabind/back_reference.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_BACK_REFERENCE_040510_HPP +#define LUABIND_BACK_REFERENCE_040510_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace luabind { + +namespace detail +{ + namespace mpl = boost::mpl; + + template + wrap_base const* get_back_reference_aux0(T const* p, mpl::true_) + { + return dynamic_cast(p); + } + + template + wrap_base const* get_back_reference_aux0(T const*, mpl::false_) + { + return 0; + } + + template + wrap_base const* get_back_reference_aux1(T const* p) + { + return get_back_reference_aux0(p, boost::is_polymorphic()); + } + + template + wrap_base const* get_back_reference_aux2(T const& x, mpl::true_) + { + return get_back_reference_aux1(get_pointer(x)); + } + + template + wrap_base const* get_back_reference_aux2(T const& x, mpl::false_) + { + return get_back_reference_aux1(&x); + } + + template + wrap_base const* get_back_reference(T const& x) + { + return detail::get_back_reference_aux2( + x + , has_get_pointer() + ); + } + +} // namespace detail + +template +bool get_back_reference(lua_State* L, T const& x) +{ +#ifndef LUABIND_NO_RTTI + if (wrap_base const* w = detail::get_back_reference(x)) + { + detail::wrap_access::ref(*w).get(L); + return true; + } +#endif + return false; +} + +template +bool move_back_reference(lua_State* L, T const& x) +{ +#ifndef LUABIND_NO_RTTI + if (wrap_base* w = const_cast(detail::get_back_reference(x))) + { + assert(detail::wrap_access::ref(*w).m_strong_ref.is_valid()); + detail::wrap_access::ref(*w).get(L); + detail::wrap_access::ref(*w).m_strong_ref.reset(); + return true; + } +#endif + return false; +} + +} // namespace luabind + +#endif // LUABIND_BACK_REFERENCE_040510_HPP + diff --git a/luabind/luabind/back_reference_fwd.hpp b/luabind/luabind/back_reference_fwd.hpp new file mode 100644 index 000000000..ffe141dba --- /dev/null +++ b/luabind/luabind/back_reference_fwd.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_BACK_REFERENCE_FWD_040510_HPP +#define LUABIND_BACK_REFERENCE_FWD_040510_HPP + +namespace luabind { + +template +bool get_back_reference(lua_State* L, T const& x); + +template +bool move_back_reference(lua_State* L, T const& x); + +} // namespace luabind + +#endif // LUABIND_BACK_REFERENCE_FWD_040510_HPP + diff --git a/luabind/luabind/class.hpp b/luabind/luabind/class.hpp new file mode 100644 index 000000000..10fb8e03d --- /dev/null +++ b/luabind/luabind/class.hpp @@ -0,0 +1,879 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CLASS_HPP_INCLUDED +#define LUABIND_CLASS_HPP_INCLUDED + +/* + ISSUES: + ------------------------------------------------------ + + * solved for member functions, not application operator * + if we have a base class that defines a function a derived class must be able to + override that function (not just overload). Right now we just add the other overload + to the overloads list and will probably get an ambiguity. If we want to support this + each method_rep must include a vector of type_info pointers for each parameter. + Operators do not have this problem, since operators always have to have + it's own type as one of the arguments, no ambiguity can occur. Application + operator, on the other hand, would have this problem. + Properties cannot be overloaded, so they should always be overridden. + If this is to work for application operator, we really need to specify if an application + operator is const or not. + + If one class registers two functions with the same name and the same + signature, there's currently no error. The last registered function will + be the one that's used. + How do we know which class registered the function? If the function was + defined by the base class, it is a legal operation, to override it. + we cannot look at the pointer offset, since it always will be zero for one of the bases. + + + + TODO: + ------------------------------------------------------ + + finish smart pointer support + * the adopt policy should not be able to adopt pointers to held_types. This + must be prohibited. + * name_of_type must recognize holder_types and not return "custom" + + document custom policies, custom converters + + store the instance object for policies. + + support the __concat metamethod. This is a bit tricky, since it cannot be + treated as a normal operator. It is a binary operator but we want to use the + __tostring implementation for both arguments. + +*/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// to remove the 'this' used in initialization list-warning +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4355) +#endif + +namespace boost +{ + + template class shared_ptr; + +} // namespace boost + +namespace luabind +{ + namespace detail + { + struct unspecified {}; + + template struct operator_; + + struct you_need_to_define_a_get_const_holder_function_for_your_smart_ptr {}; + } + + template + struct class_; + + // TODO: this function will only be invoked if the user hasn't defined a correct overload + // maybe we should have a static assert in here? + inline detail::you_need_to_define_a_get_const_holder_function_for_your_smart_ptr* + get_const_holder(...) + { + return 0; + } + + template + boost::shared_ptr* get_const_holder(boost::shared_ptr*) + { + return 0; + } + + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + LUABIND_MAX_BASES, class A, detail::null_type) + > + struct bases + {}; + + typedef bases no_bases; + + namespace detail + { + template + struct is_bases + : mpl::false_ + {}; + + template + struct is_bases > + : mpl::true_ + {}; + + template + struct is_unspecified + : mpl::apply1 + {}; + + template + struct is_unspecified + : mpl::true_ + {}; + + template + struct is_unspecified_mfn + { + template + struct apply + : is_unspecified + {}; + }; + + template + struct get_predicate + { + typedef mpl::protect > type; + }; + + template + struct result_or_default + { + typedef Result type; + }; + + template + struct result_or_default + { + typedef Default type; + }; + + template + struct extract_parameter + { + typedef typename get_predicate::type pred; + typedef typename boost::mpl::find_if::type iterator; + typedef typename result_or_default< + typename iterator::type, DefaultValue + >::type type; + }; + + // prints the types of the values on the stack, in the + // range [start_index, lua_gettop()] + + LUABIND_API std::string stack_content_by_name(lua_State* L, int start_index); + + struct LUABIND_API create_class + { + static int stage1(lua_State* L); + static int stage2(lua_State* L); + }; + + } // detail + + namespace detail { + + template + struct static_scope + { + static_scope(T& self_) : self(self_) + { + } + + T& operator[](scope s) const + { + self.add_inner_scope(s); + return self; + } + + private: + template void operator,(U const&) const; + void operator=(static_scope const&); + + T& self; + }; + + struct class_registration; + + struct LUABIND_API class_base : scope + { + public: + class_base(char const* name); + + struct base_desc + { + type_id type; + int ptr_offset; + }; + + void init( + type_id const& type, class_id id + , type_id const& wrapped_type, class_id wrapper_id); + + void add_base(type_id const& base, cast_function cast); + + void add_member(registration* member); + void add_default_member(registration* member); + + const char* name() const; + + void add_static_constant(const char* name, int val); + void add_inner_scope(scope& s); + + void add_cast(class_id src, class_id target, cast_function cast); + + private: + class_registration* m_registration; + }; + +// MSVC complains about member being sensitive to alignment (C4121) +// when F is a pointer to member of a class with virtual bases. +# ifdef BOOST_MSVC +# pragma pack(push) +# pragma pack(16) +# endif + + template + struct memfun_registration : registration + { + memfun_registration(char const* name, F f, Policies const& policies) + : name(name) + , f(f) + , policies(policies) + {} + + void register_(lua_State* L) const + { + object fn = make_function( + L, f, deduce_signature(f, (Class*)0), policies); + + add_overload( + object(from_stack(L, -1)) + , name + , fn + ); + } + + char const* name; + F f; + Policies policies; + }; + +# ifdef BOOST_MSVC +# pragma pack(pop) +# endif + + template + struct default_pointer + { + typedef P type; + }; + + template + struct default_pointer + { + typedef std::auto_ptr type; + }; + + template + struct constructor_registration : registration + { + constructor_registration(Policies const& policies) + : policies(policies) + {} + + void register_(lua_State* L) const + { + typedef typename default_pointer::type pointer; + + object fn = make_function( + L + , construct(), Signature() + , policies + ); + + add_overload( + object(from_stack(L, -1)) + , "__init" + , fn + ); + } + + Policies policies; + }; + + template + struct reference_result + : mpl::if_< + mpl::or_, is_primitive > + , T + , typename boost::add_reference::type + > + {}; + + template + struct inject_dependency_policy + : mpl::if_< + is_primitive + , Policies + , policy_cons, Policies> + > + {}; + + template < + class Class + , class Get, class GetPolicies + , class Set = null_type, class SetPolicies = null_type + > + struct property_registration : registration + { + property_registration( + char const* name + , Get const& get + , GetPolicies const& get_policies + , Set const& set = Set() + , SetPolicies const& set_policies = SetPolicies() + ) + : name(name) + , get(get) + , get_policies(get_policies) + , set(set) + , set_policies(set_policies) + {} + + void register_(lua_State* L) const + { + object context(from_stack(L, -1)); + register_aux( + L + , context + , make_get(L, get, boost::is_member_object_pointer()) + , set + ); + } + + template + object make_get(lua_State* L, F const& f, mpl::false_) const + { + return make_function( + L, f, deduce_signature(f, (Class*)0), get_policies); + } + + template + object make_get(lua_State* L, D T::* mem_ptr, mpl::true_) const + { + typedef typename reference_result::type result_type; + typedef typename inject_dependency_policy< + D, GetPolicies>::type policies; + + return make_function( + L + , access_member_ptr(mem_ptr) + , mpl::vector2() + , policies() + ); + } + + template + object make_set(lua_State* L, F const& f, mpl::false_) const + { + return make_function( + L, f, deduce_signature(f, (Class*)0), set_policies); + } + + template + object make_set(lua_State* L, D T::* mem_ptr, mpl::true_) const + { + return make_function( + L + , access_member_ptr(mem_ptr) + , mpl::vector3() + , set_policies + ); + } + + template + void register_aux( + lua_State* L, object const& context + , object const& get_, S const&) const + { + context[name] = property( + get_ + , make_set(L, set, boost::is_member_object_pointer()) + ); + } + + void register_aux( + lua_State*, object const& context + , object const& get_, null_type) const + { + context[name] = property(get_); + } + + char const* name; + Get get; + GetPolicies get_policies; + Set set; + SetPolicies set_policies; + }; + + } // namespace detail + + // registers a class in the lua environment + template + struct class_: detail::class_base + { + typedef class_ self_t; + + private: + + template + class_(const class_&); + + public: + + typedef boost::mpl::vector4 parameters_type; + + // WrappedType MUST inherit from T + typedef typename detail::extract_parameter< + parameters_type + , boost::is_base_and_derived + , detail::null_type + >::type WrappedType; + + typedef typename detail::extract_parameter< + parameters_type + , boost::mpl::not_< + boost::mpl::or_< + detail::is_bases + , boost::is_base_and_derived + , boost::is_base_and_derived + > + > + , detail::null_type + >::type HeldType; + + template + void add_downcast(Src*, Target*, boost::mpl::true_) + { + add_cast( + detail::registered_class::id + , detail::registered_class::id + , detail::dynamic_cast_::execute + ); + } + + template + void add_downcast(Src*, Target*, boost::mpl::false_) + {} + + // this function generates conversion information + // in the given class_rep structure. It will be able + // to implicitly cast to the given template type + template + void gen_base_info(detail::type_) + { + add_base(typeid(To), detail::static_cast_::execute); + add_cast( + detail::registered_class::id + , detail::registered_class::id + , detail::static_cast_::execute + ); + + add_downcast((To*)0, (T*)0, boost::is_polymorphic()); + } + + void gen_base_info(detail::type_) + {} + +#define LUABIND_GEN_BASE_INFO(z, n, text) gen_base_info(detail::type_()); + + template + void generate_baseclass_list(detail::type_ >) + { + BOOST_PP_REPEAT(LUABIND_MAX_BASES, LUABIND_GEN_BASE_INFO, _) + } + +#undef LUABIND_GEN_BASE_INFO + + class_(const char* name): class_base(name), scope(*this) + { +#ifndef NDEBUG + detail::check_link_compatibility(); +#endif + init(); + } + + template + class_& def(const char* name, F f) + { + return this->virtual_def( + name, f, detail::null_type() + , detail::null_type(), boost::mpl::true_()); + } + + // virtual functions + template + class_& def(char const* name, F fn, DefaultOrPolicies default_or_policies) + { + return this->virtual_def( + name, fn, default_or_policies, detail::null_type() + , LUABIND_MSVC_TYPENAME detail::is_policy_cons::type()); + } + + template + class_& def(char const* name, F fn + , Default default_, Policies const& policies) + { + return this->virtual_def( + name, fn, default_ + , policies, boost::mpl::false_()); + } + + template + class_& def(constructor sig) + { + return this->def_constructor(&sig, detail::null_type()); + } + + template + class_& def(constructor sig, const Policies& policies) + { + return this->def_constructor(&sig, policies); + } + + template + class_& property(const char* name, Getter g) + { + this->add_member( + new detail::property_registration( + name, g, detail::null_type())); + return *this; + } + + template + class_& property(const char* name, Getter g, MaybeSetter s) + { + return property_impl( + name, g, s + , boost::mpl::bool_::value>() + ); + } + + template + class_& property(const char* name, Getter g, Setter s, const GetPolicies& get_policies) + { + typedef detail::property_registration< + T, Getter, GetPolicies, Setter, detail::null_type + > registration_type; + + this->add_member( + new registration_type(name, g, get_policies, s)); + return *this; + } + + template + class_& property( + const char* name + , Getter g, Setter s + , GetPolicies const& get_policies + , SetPolicies const& set_policies) + { + typedef detail::property_registration< + T, Getter, GetPolicies, Setter, SetPolicies + > registration_type; + + this->add_member( + new registration_type(name, g, get_policies, s, set_policies)); + return *this; + } + + template + class_& def_readonly(const char* name, D C::*mem_ptr) + { + typedef detail::property_registration + registration_type; + + this->add_member( + new registration_type(name, mem_ptr, detail::null_type())); + return *this; + } + + template + class_& def_readonly(const char* name, D C::*mem_ptr, Policies const& policies) + { + typedef detail::property_registration + registration_type; + + this->add_member( + new registration_type(name, mem_ptr, policies)); + return *this; + } + + template + class_& def_readwrite(const char* name, D C::*mem_ptr) + { + typedef detail::property_registration< + T, D C::*, detail::null_type, D C::* + > registration_type; + + this->add_member( + new registration_type( + name, mem_ptr, detail::null_type(), mem_ptr)); + return *this; + } + + template + class_& def_readwrite( + const char* name, D C::*mem_ptr, GetPolicies const& get_policies) + { + typedef detail::property_registration< + T, D C::*, GetPolicies, D C::* + > registration_type; + + this->add_member( + new registration_type( + name, mem_ptr, get_policies, mem_ptr)); + return *this; + } + + template + class_& def_readwrite( + const char* name + , D C::*mem_ptr + , GetPolicies const& get_policies + , SetPolicies const& set_policies + ) + { + typedef detail::property_registration< + T, D C::*, GetPolicies, D C::*, SetPolicies + > registration_type; + + this->add_member( + new registration_type( + name, mem_ptr, get_policies, mem_ptr, set_policies)); + return *this; + } + + template + class_& def(detail::operator_, Policies const& policies) + { + return this->def( + Derived::name() + , &Derived::template apply::execute + , policies + ); + } + + template + class_& def(detail::operator_) + { + return this->def( + Derived::name() + , &Derived::template apply::execute + ); + } + + detail::enum_maker enum_(const char*) + { + return detail::enum_maker(*this); + } + + detail::static_scope scope; + + private: + void operator=(class_ const&); + + void add_wrapper_cast(detail::null_type*) + {} + + template + void add_wrapper_cast(U*) + { + add_cast( + detail::registered_class::id + , detail::registered_class::id + , detail::static_cast_::execute + ); + + add_downcast((T*)0, (U*)0, boost::is_polymorphic()); + } + + void init() + { + typedef typename detail::extract_parameter< + parameters_type + , boost::mpl::or_< + detail::is_bases + , boost::is_base_and_derived + > + , no_bases + >::type bases_t; + + typedef typename + boost::mpl::if_ + , bases_t + , bases + >::type Base; + + class_base::init( + typeid(T) + , detail::registered_class::id + , typeid(WrappedType) + , detail::registered_class::id + ); + + add_wrapper_cast((WrappedType*)0); + + generate_baseclass_list(detail::type_()); + } + + template + class_& property_impl(const char* name, + Getter g, + GetPolicies policies, + boost::mpl::bool_) + { + this->add_member( + new detail::property_registration( + name, g, policies)); + return *this; + } + + template + class_& property_impl(const char* name, + Getter g, + Setter s, + boost::mpl::bool_) + { + typedef detail::property_registration< + T, Getter, detail::null_type, Setter, detail::null_type + > registration_type; + + this->add_member( + new registration_type(name, g, detail::null_type(), s)); + return *this; + } + + // these handle default implementation of virtual functions + template + class_& virtual_def(char const* name, F const& fn + , Policies const&, detail::null_type, boost::mpl::true_) + { + this->add_member( + new detail::memfun_registration( + name, fn, Policies())); + return *this; + } + + template + class_& virtual_def(char const* name, F const& fn + , Default const& default_, Policies const&, boost::mpl::false_) + { + this->add_member( + new detail::memfun_registration( + name, fn, Policies())); + + this->add_default_member( + new detail::memfun_registration( + name, default_, Policies())); + + return *this; + } + + template + class_& def_constructor(Signature*, Policies const&) + { + typedef typename Signature::signature signature; + + typedef typename boost::mpl::if_< + boost::is_same + , T + , WrappedType + >::type construct_type; + + this->add_member( + new detail::constructor_registration< + construct_type, HeldType, signature, Policies>( + Policies())); + + this->add_default_member( + new detail::constructor_registration< + construct_type, HeldType, signature, Policies>( + Policies())); + + return *this; + } + }; + +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif // LUABIND_CLASS_HPP_INCLUDED + diff --git a/luabind/luabind/class_info.hpp b/luabind/luabind/class_info.hpp new file mode 100644 index 000000000..a4f18a8cc --- /dev/null +++ b/luabind/luabind/class_info.hpp @@ -0,0 +1,50 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CLASS_INFO_HPP_INCLUDED +#define LUABIND_CLASS_INFO_HPP_INCLUDED + +#include +#include +#include +#include + +namespace luabind +{ + struct LUABIND_API class_info + { + std::string name; + object methods; + object attributes; + }; + + LUABIND_API class_info get_class_info(argument const&); + + // returns a table of bound class names + LUABIND_API object get_class_names(lua_State* L); + + LUABIND_API void bind_class_info(lua_State*); +} + +#endif + diff --git a/luabind/luabind/config.hpp b/luabind/luabind/config.hpp new file mode 100644 index 000000000..e8eea875c --- /dev/null +++ b/luabind/luabind/config.hpp @@ -0,0 +1,128 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CONFIG_HPP_INCLUDED +#define LUABIND_CONFIG_HPP_INCLUDED + +#include + +#ifdef BOOST_MSVC + #define LUABIND_ANONYMOUS_FIX static +#else + #define LUABIND_ANONYMOUS_FIX +#endif + +#if defined (BOOST_MSVC) && (BOOST_MSVC <= 1200) + +#define for if (false) {} else for + +#include + +namespace std +{ + using ::strlen; + using ::strcmp; + using ::type_info; +} + +#endif + + +#if defined (BOOST_MSVC) && (BOOST_MSVC <= 1300) + #define LUABIND_MSVC_TYPENAME +#else + #define LUABIND_MSVC_TYPENAME typename +#endif + +// the maximum number of arguments of functions that's +// registered. Must at least be 2 +#ifndef LUABIND_MAX_ARITY + #define LUABIND_MAX_ARITY 10 +#elif LUABIND_MAX_ARITY <= 1 + #undef LUABIND_MAX_ARITY + #define LUABIND_MAX_ARITY 2 +#endif + +// the maximum number of classes one class +// can derive from +// max bases must at least be 1 +#ifndef LUABIND_MAX_BASES + #define LUABIND_MAX_BASES 4 +#elif LUABIND_MAX_BASES <= 0 + #undef LUABIND_MAX_BASES + #define LUABIND_MAX_BASES 1 +#endif + +// LUABIND_NO_ERROR_CHECKING +// define this to remove all error checks +// this will improve performance and memory +// footprint. +// if it is defined matchers will only be called on +// overloaded functions, functions that's +// not overloaded will be called directly. The +// parameters on the lua stack are assumed +// to match those of the function. +// exceptions will still be catched when there's +// no error checking. + +// LUABIND_NOT_THREADSAFE +// this define will make luabind non-thread safe. That is, +// it will rely on a static variable. You can still have +// multiple lua states and use coroutines, but only +// one of your real threads may run lua code. + +// LUABIND_NO_EXCEPTIONS +// this define will disable all usage of try, catch and throw in +// luabind. This will in many cases disable runtime-errors, such +// as invalid casts, when calling lua-functions that fails or +// returns values that cannot be converted by the given policy. +// Luabind requires that no function called directly or indirectly +// by luabind throws an exception (throwing exceptions through +// C code has undefined behavior, lua is written in C). + +#ifdef LUABIND_DYNAMIC_LINK +# ifdef BOOST_WINDOWS +# ifdef LUABIND_BUILDING +# define LUABIND_API __declspec(dllexport) +# else +# define LUABIND_API __declspec(dllimport) +# endif +# else +# if defined(_GNUC_) && _GNUC_ >=4 +# define LUABIND_API __attribute__ ((visibility("default"))) +# endif +# endif +#endif + +#ifndef LUABIND_API +# define LUABIND_API +#endif + +namespace luabind { + +LUABIND_API void disable_super_deprecation(); + +} // namespace luabind + +#endif // LUABIND_CONFIG_HPP_INCLUDED + diff --git a/luabind/luabind/container_policy.hpp b/luabind/luabind/container_policy.hpp new file mode 100644 index 000000000..68ad0a90f --- /dev/null +++ b/luabind/luabind/container_policy.hpp @@ -0,0 +1,143 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CONTAINER_POLICY_HPP_INCLUDED +#define LUABIND_CONTAINER_POLICY_HPP_INCLUDED + +#include +#include +#include + +namespace luabind { namespace detail { + + namespace mpl = boost::mpl; + + template + struct container_converter_lua_to_cpp + { + int const consumed_args(...) + { + return 1; + } + + template + T apply(lua_State* L, by_const_reference, int index) + { + typedef typename T::value_type value_type; + + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + + T container; + + lua_pushnil(L); + while (lua_next(L, index)) + { + container.push_back(converter.apply(L, LUABIND_DECORATE_TYPE(value_type), -1)); + lua_pop(L, 1); // pop value + } + + return container; + } + + template + T apply(lua_State* L, by_value, int index) + { + return apply(L, by_const_reference(), index); + } + + template + static int match(lua_State* L, by_const_reference, int index) + { + if (lua_istable(L, index)) return 0; else return -1; + } + + template + void converter_postcall(lua_State*, T, int) {} + }; + + template + struct container_converter_cpp_to_lua + { + template + void apply(lua_State* L, const T& container) + { + typedef typename T::value_type value_type; + + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + + lua_newtable(L); + + int index = 1; + + for (typename T::const_iterator i = container.begin(); i != container.end(); ++i) + { + converter.apply(L, *i); + lua_rawseti(L, -2, index); + ++index; + } + } + }; + + template +// struct container_policy : converter_policy_tag + struct container_policy : conversion_policy + { +// BOOST_STATIC_CONSTANT(int, index = N); + + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + + struct only_accepts_nonconst_pointers {}; + + template + struct apply + { + typedef typename boost::mpl::if_ + , container_converter_lua_to_cpp + , container_converter_cpp_to_lua + >::type type; + }; + }; + +}} + +namespace luabind +{ + template + detail::policy_cons, detail::null_type> + container(LUABIND_PLACEHOLDER_ARG(N)) + { + return detail::policy_cons, detail::null_type>(); + } + + template + detail::policy_cons, detail::null_type> + container(LUABIND_PLACEHOLDER_ARG(N), const Policies&) + { + return detail::policy_cons, detail::null_type>(); + } +} + +#endif // LUABIND_CONTAINER_POLICY_HPP_INCLUDED diff --git a/luabind/luabind/copy_policy.hpp b/luabind/luabind/copy_policy.hpp new file mode 100644 index 000000000..1a18b729b --- /dev/null +++ b/luabind/luabind/copy_policy.hpp @@ -0,0 +1,61 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_COPY_POLICY_081021_HPP +# define LUABIND_COPY_POLICY_081021_HPP + +# include + +namespace luabind { + +namespace detail +{ + + struct copy_converter + { + template + void apply(lua_State* L, T const& x) + { + value_converter().apply(L, x); + } + + template + void apply(lua_State* L, T* x) + { + if (!x) + lua_pushnil(L); + else + apply(L, *x); + } + }; + + template + struct copy_policy : conversion_policy + { + static void precall(lua_State*, index_map const&) + {} + + static void postcall(lua_State*, index_map const&) + {} + + template + struct apply + { + typedef copy_converter type; + }; + }; + +} // namespace detail + +template +detail::policy_cons, detail::null_type> +copy(LUABIND_PLACEHOLDER_ARG(N)) +{ + return detail::policy_cons, detail::null_type>(); +} + +} // namespace luabind + +#endif // LUABIND_COPY_POLICY_081021_HPP + diff --git a/luabind/luabind/dependency_policy.hpp b/luabind/luabind/dependency_policy.hpp new file mode 100644 index 000000000..cafa49aa1 --- /dev/null +++ b/luabind/luabind/dependency_policy.hpp @@ -0,0 +1,119 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_DEPENDENCY_POLICY_HPP_INCLUDED +#define LUABIND_DEPENDENCY_POLICY_HPP_INCLUDED + +#include +#include + +namespace luabind { namespace detail +{ + // makes A dependent on B, meaning B will outlive A. + // internally A stores a reference to B + template + struct dependency_policy + { + static void postcall(lua_State* L, const index_map& indices) + { + int nurse_index = indices[A]; + int patient = indices[B]; + + object_rep* nurse = static_cast(lua_touserdata(L, nurse_index)); + + // If the nurse isn't an object_rep, just make this a nop. + if (nurse == 0) + return; + + nurse->add_dependency(L, patient); + } + }; + +}} + +#if defined (BOOST_MSVC) && (BOOST_MSVC <= 1200) + +namespace luabind +{ + // most absurd workaround of all time? + namespace detail + { + template + struct size_char_array + { + char storage[N + 2]; + }; + + template + size_char_array deduce_size(LUABIND_PLACEHOLDER_ARG(N)); + + template + struct get_index_workaround + { + static T t; + BOOST_STATIC_CONSTANT(int, value = sizeof(deduce_size(t)) - 2); + }; + } + + template + detail::policy_cons::value + , detail::get_index_workaround::value>, detail::null_type> dependency(A,B) + { + return detail::policy_cons::value, detail::get_index_workaround::value> + , detail::null_type>(); + } + + template + detail::policy_cons::value>, detail::null_type> + return_internal_reference(A) + { + return detail::policy_cons::value>, detail::null_type>(); + } +} + +#else + +namespace luabind +{ + template + detail::policy_cons, detail::null_type> + dependency(LUABIND_PLACEHOLDER_ARG(A), LUABIND_PLACEHOLDER_ARG(B)) + { + return detail::policy_cons, detail::null_type>(); + } + + template + detail::policy_cons, detail::null_type> + return_internal_reference(LUABIND_PLACEHOLDER_ARG(A)) + { + return detail::policy_cons, detail::null_type>(); + } +} + +#endif + +#endif // LUABIND_DEPENDENCY_POLICY_HPP_INCLUDED + diff --git a/luabind/luabind/detail/calc_arity.hpp b/luabind/luabind/detail/calc_arity.hpp new file mode 100644 index 000000000..c2e0aad91 --- /dev/null +++ b/luabind/luabind/detail/calc_arity.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#if !BOOST_PP_IS_ITERATING + +# include + +#ifndef LUABIND_CALC_ARITY_HPP_INCLUDED +#define LUABIND_CALC_ARITY_HPP_INCLUDED + +#define LUABIND_FIND_CONV(z,n,text) typedef typename find_conversion_policy::type p##n; +#define LUABIND_CALC_ARITY(z,n,text) + BOOST_PP_CAT(p,n)::has_arg + +namespace luabind { namespace detail +{ + template struct calc_arity; + + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) + #include BOOST_PP_ITERATE() +}} + +#undef LUABIND_CALC_ARITY +#undef LUABIND_FIND_CONV + + +#endif // LUABIND_CALC_ARITY_HPP_INCLUDED + +#else // BOOST_PP_ITERATE + + template<> + struct calc_arity + { + template + static int apply(constructor, Policies*) + { + BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_FIND_CONV, _) + return 0 BOOST_PP_REPEAT(BOOST_PP_ITERATION(), LUABIND_CALC_ARITY, _); + } + }; + +#endif + diff --git a/luabind/luabind/detail/call.hpp b/luabind/luabind/detail/call.hpp new file mode 100644 index 000000000..cd9402ef3 --- /dev/null +++ b/luabind/luabind/detail/call.hpp @@ -0,0 +1,323 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !BOOST_PP_IS_ITERATING + +# ifndef LUABIND_CALL2_080911_HPP +# define LUABIND_CALL2_080911_HPP + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include +# include + +namespace luabind { namespace detail { + +struct invoke_context; + +struct LUABIND_API function_object +{ + function_object(lua_CFunction entry) + : entry(entry) + , next(0) + {} + + virtual ~function_object() + {} + + virtual int call( + lua_State* L, invoke_context& ctx) const = 0; + virtual void format_signature(lua_State* L, char const* function) const = 0; + + lua_CFunction entry; + std::string name; + function_object* next; + object keepalive; +}; + +struct LUABIND_API invoke_context +{ + invoke_context() + : best_score((std::numeric_limits::max)()) + , candidate_index(0) + {} + + operator bool() const + { + return candidate_index == 1; + } + + void format_error(lua_State* L, function_object const* overloads) const; + + int best_score; + function_object const* candidates[10]; + int candidate_index; +}; + +template +inline int invoke0( + lua_State* L, function_object const& self, invoke_context& ctx + , F const& f, Signature, Policies const& policies, IsVoid, mpl::true_) +{ + return invoke_member( + L, self, ctx, f, Signature(), policies + , mpl::long_::value - 1>(), IsVoid() + ); +} + +template +inline int invoke0( + lua_State* L, function_object const& self, invoke_context& ctx, + F const& f, Signature, Policies const& policies, IsVoid, mpl::false_) +{ + return invoke_normal( + L, self, ctx, f, Signature(), policies + , mpl::long_::value - 1>(), IsVoid() + ); +} + +template +inline int invoke( + lua_State* L, function_object const& self, invoke_context& ctx + , F const& f, Signature, Policies const& policies) +{ + return invoke0( + L, self, ctx, f, Signature(), policies + , boost::is_void::type>() + , boost::is_member_function_pointer() + ); +} + +inline int maybe_yield_aux(lua_State*, int results, mpl::false_) +{ + return results; +} + +inline int maybe_yield_aux(lua_State* L, int results, mpl::true_) +{ + return lua_yield(L, results); +} + +template +int maybe_yield(lua_State* L, int results, Policies*) +{ + return maybe_yield_aux( + L, results, mpl::bool_::value>()); +} + +inline int sum_scores(int const* first, int const* last) +{ + int result = 0; + + for (; first != last; ++first) + { + if (*first < 0) + return *first; + result += *first; + } + + return result; +} + +# define LUABIND_INVOKE_NEXT_ITER(n) \ + typename mpl::next< \ + BOOST_PP_IF( \ + n, BOOST_PP_CAT(iter,BOOST_PP_DEC(n)), first) \ + >::type + +# define LUABIND_INVOKE_NEXT_INDEX(n) \ + BOOST_PP_IF( \ + n \ + , BOOST_PP_CAT(index,BOOST_PP_DEC(n)) + \ + BOOST_PP_CAT(c,BOOST_PP_DEC(n)).consumed_args() \ + , 1 \ + ) + +# define LUABIND_INVOKE_COMPUTE_ARITY(n) + BOOST_PP_CAT(c,n).consumed_args() + +# define LUABIND_INVOKE_DECLARE_CONVERTER(n) \ + typedef LUABIND_INVOKE_NEXT_ITER(n) BOOST_PP_CAT(iter,n); \ + typedef typename mpl::deref::type \ + BOOST_PP_CAT(a,n); \ + typedef typename find_conversion_policy::type \ + BOOST_PP_CAT(p,n); \ + typename mpl::apply_wrap2< \ + BOOST_PP_CAT(p,n), BOOST_PP_CAT(a,n), lua_to_cpp>::type BOOST_PP_CAT(c,n); \ + int const BOOST_PP_CAT(index,n) = LUABIND_INVOKE_NEXT_INDEX(n); + +# define LUABIND_INVOKE_COMPUTE_SCORE(n) \ + , BOOST_PP_CAT(c,n).match( \ + L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,n)), BOOST_PP_CAT(index,n)) + +# define LUABIND_INVOKE_ARG(z, n, base) \ + BOOST_PP_CAT(c,base(n)).apply( \ + L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,base(n))), BOOST_PP_CAT(index,base(n))) + +# define LUABIND_INVOKE_CONVERTER_POSTCALL(n) \ + BOOST_PP_CAT(c,n).converter_postcall( \ + L, LUABIND_DECORATE_TYPE(BOOST_PP_CAT(a,n)), BOOST_PP_CAT(index,n)); + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# define LUABIND_INVOKE_VOID +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# undef LUABIND_INVOKE_VOID +# define LUABIND_INVOKE_MEMBER +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +# define LUABIND_INVOKE_VOID +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +}} // namespace luabind::detail + +# endif // LUABIND_CALL2_080911_HPP + +#else // BOOST_PP_IS_ITERATING + +# ifdef LUABIND_INVOKE_MEMBER +# define N BOOST_PP_INC(BOOST_PP_ITERATION()) +# else +# define N BOOST_PP_ITERATION() +# endif + +template +inline int +# ifdef LUABIND_INVOKE_MEMBER +invoke_member +# else +invoke_normal +# endif +( + lua_State* L, function_object const& self, invoke_context& ctx + , F const& f, Signature, Policies const&, mpl::long_ +# ifdef LUABIND_INVOKE_VOID + , mpl::true_ +# else + , mpl::false_ +# endif +) +{ + typedef typename mpl::begin::type first; +# ifndef LUABIND_INVOKE_VOID + typedef typename mpl::deref::type result_type; + typedef typename find_conversion_policy<0, Policies>::type result_policy; + typename mpl::apply_wrap2< + result_policy, result_type, cpp_to_lua>::type result_converter; +# endif + +# if N > 0 +# define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_DECLARE_CONVERTER(n) +# define BOOST_PP_LOCAL_LIMITS (0,N-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + + int const arity = 0 +# if N > 0 +# define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_COMPUTE_ARITY(n) +# define BOOST_PP_LOCAL_LIMITS (0,N-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + ; + + int const arguments = lua_gettop(L); + + int score = -1; + + if (arity == arguments) + { + int const scores[] = { + 0 +# if N > 0 +# define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_COMPUTE_SCORE(n) +# define BOOST_PP_LOCAL_LIMITS (0,N-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + }; + + score = sum_scores(scores + 1, scores + 1 + N); + } + + if (score >= 0 && score < ctx.best_score) + { + ctx.best_score = score; + ctx.candidates[0] = &self; + ctx.candidate_index = 1; + } + else if (score == ctx.best_score) + { + ctx.candidates[ctx.candidate_index++] = &self; + } + + int results = 0; + + if (self.next) + { + results = self.next->call(L, ctx); + } + + if (score == ctx.best_score && ctx.candidate_index == 1) + { +# ifndef LUABIND_INVOKE_VOID + result_converter.apply( + L, +# endif +# ifdef LUABIND_INVOKE_MEMBER + (c0.apply(L, LUABIND_DECORATE_TYPE(a0), index0).*f)( + BOOST_PP_ENUM(BOOST_PP_DEC(N), LUABIND_INVOKE_ARG, BOOST_PP_INC) + ) +# else +# define LUABIND_INVOKE_IDENTITY(x) x + f( + BOOST_PP_ENUM(N, LUABIND_INVOKE_ARG, LUABIND_INVOKE_IDENTITY) + ) +# undef LUABIND_INVOKE_IDENTITY +# endif +# ifndef LUABIND_INVOKE_VOID + ) +# endif + ; + +# if N > 0 +# define BOOST_PP_LOCAL_MACRO(n) LUABIND_INVOKE_CONVERTER_POSTCALL(n) +# define BOOST_PP_LOCAL_LIMITS (0,N-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + + results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0); + + int const indices[] = { + arguments + results BOOST_PP_ENUM_TRAILING_PARAMS(N, index) + }; + + policy_list_postcall::apply(L, indices); + } + + return results; +} + +# undef N + +#endif + diff --git a/luabind/luabind/detail/call_function.hpp b/luabind/luabind/detail/call_function.hpp new file mode 100644 index 000000000..1b45ec157 --- /dev/null +++ b/luabind/luabind/detail/call_function.hpp @@ -0,0 +1,443 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#if !BOOST_PP_IS_ITERATING + +#ifndef LUABIND_CALL_FUNCTION_HPP_INCLUDED +#define LUABIND_CALL_FUNCTION_HPP_INCLUDED + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace luabind +{ + namespace detail + { + + // if the proxy_function_caller returns non-void + template + class proxy_function_caller + { +// friend class luabind::object; + public: + + typedef int(*function_t)(lua_State*, int, int); + + proxy_function_caller( + lua_State* L + , int params + , function_t fun + , const Tuple args) + : m_state(L) + , m_params(params) + , m_fun(fun) + , m_args(args) + , m_called(false) + { + } + + proxy_function_caller(const proxy_function_caller& rhs) + : m_state(rhs.m_state) + , m_params(rhs.m_params) + , m_fun(rhs.m_fun) + , m_args(rhs.m_args) + , m_called(rhs.m_called) + { + rhs.m_called = true; + } + + ~proxy_function_caller() + { + if (m_called) return; + + m_called = true; + lua_State* L = m_state; + + int top = lua_gettop(L); + + push_args_from_tuple<1>::apply(L, m_args); + if (m_fun(L, boost::tuples::length::value, 0)) + { + assert(lua_gettop(L) == top - m_params + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); + +#endif + } + + // pops the return values from the function call + stack_pop pop(L, lua_gettop(L) - top + m_params); + } + + operator Ret() + { + typename mpl::apply_wrap2::type converter; + + m_called = true; + lua_State* L = m_state; + + int top = lua_gettop(L); + + push_args_from_tuple<1>::apply(L, m_args); + if (m_fun(L, boost::tuples::length::value, 1)) + { + assert(lua_gettop(L) == top - m_params + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); +#endif + } + + // pops the return values from the function call + stack_pop pop(L, lua_gettop(L) - top + m_params); + +#ifndef LUABIND_NO_ERROR_CHECKING + + if (converter.match(L, LUABIND_DECORATE_TYPE(Ret), -1) < 0) + { +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(L, typeid(Ret)); +#else + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(L, typeid(Ret)); + + assert(0 && "the lua function's return value could not be converted." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); + +#endif + } +#endif + return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1); + } + + template + Ret operator[](const Policies& p) + { + typedef typename detail::find_conversion_policy<0, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + + m_called = true; + lua_State* L = m_state; + + int top = lua_gettop(L); + + detail::push_args_from_tuple<1>::apply(L, m_args, p); + if (m_fun(L, boost::tuples::length::value, 1)) + { + assert(lua_gettop(L) == top - m_params + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); +#endif + } + + // pops the return values from the function call + stack_pop pop(L, lua_gettop(L) - top + m_params); + +#ifndef LUABIND_NO_ERROR_CHECKING + + if (converter.match(L, LUABIND_DECORATE_TYPE(Ret), -1) < 0) + { +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(L, typeid(Ret)); +#else + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(L, typeid(Ret)); + + assert(0 && "the lua function's return value could not be converted." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); + +#endif + } +#endif + return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1); + } + + private: + + lua_State* m_state; + int m_params; + function_t m_fun; + Tuple m_args; + mutable bool m_called; + + }; + + // if the proxy_member_caller returns void + template + class proxy_function_void_caller + { + friend class luabind::object; + public: + + typedef int(*function_t)(lua_State*, int, int); + + proxy_function_void_caller( + lua_State* L + , int params + , function_t fun + , const Tuple args) + : m_state(L) + , m_params(params) + , m_fun(fun) + , m_args(args) + , m_called(false) + { + } + + proxy_function_void_caller(const proxy_function_void_caller& rhs) + : m_state(rhs.m_state) + , m_params(rhs.m_params) + , m_fun(rhs.m_fun) + , m_args(rhs.m_args) + , m_called(rhs.m_called) + { + rhs.m_called = true; + } + + ~proxy_function_void_caller() + { + if (m_called) return; + + m_called = true; + lua_State* L = m_state; + + int top = lua_gettop(L); + + push_args_from_tuple<1>::apply(L, m_args); + if (m_fun(L, boost::tuples::length::value, 0)) + { + assert(lua_gettop(L) == top - m_params + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); +#endif + } + // pops the return values from the function call + stack_pop pop(L, lua_gettop(L) - top + m_params); + } + + template + void operator[](const Policies& p) + { + m_called = true; + lua_State* L = m_state; + + int top = lua_gettop(L); + + detail::push_args_from_tuple<1>::apply(L, m_args, p); + if (m_fun(L, boost::tuples::length::value, 0)) + { + assert(lua_gettop(L) == top - m_params + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + " If you want to handle the error you can use luabind::set_error_callback()"); + std::terminate(); +#endif + } + // pops the return values from the function call + stack_pop pop(L, lua_gettop(L) - top + m_params); + } + + private: + + lua_State* m_state; + int m_params; + function_t m_fun; + Tuple m_args; + mutable bool m_called; + + }; + + } + + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) + #include BOOST_PP_ITERATE() + +} + +#endif // LUABIND_CALL_FUNCTION_HPP_INCLUDED + +#elif BOOST_PP_ITERATION_FLAGS() == 1 + +#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * +#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n + + + template + typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type + call_function(lua_State* L, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _) ) + { + assert(name && "luabind::call_function() expects a function name"); + typedef boost::tuples::tuple tuple_t; +#if BOOST_PP_ITERATION() == 0 + tuple_t args; +#else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); +#endif + typedef typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type proxy_type; + + lua_pushstring(L, name); + lua_gettable(L, LUA_GLOBALSINDEX); + + return proxy_type(L, 1, &detail::pcall, args); + } + + template + typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type + call_function(luabind::object const& obj BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _) ) + { + typedef boost::tuples::tuple tuple_t; +#if BOOST_PP_ITERATION() == 0 + tuple_t args; +#else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); +#endif + typedef typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type proxy_type; + + obj.push(obj.interpreter()); + return proxy_type(obj.interpreter(), 1, &detail::pcall, args); + } + + template + typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type + resume_function(lua_State* L, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _) ) + { + assert(name && "luabind::resume_function() expects a function name"); + typedef boost::tuples::tuple tuple_t; +#if BOOST_PP_ITERATION() == 0 + tuple_t args; +#else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); +#endif + typedef typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type proxy_type; + + lua_pushstring(L, name); + lua_gettable(L, LUA_GLOBALSINDEX); + + return proxy_type(L, 1, &detail::resume_impl, args); + } + + template + typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type + resume_function(luabind::object const& obj BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _) ) + { + typedef boost::tuples::tuple tuple_t; +#if BOOST_PP_ITERATION() == 0 + tuple_t args; +#else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); +#endif + typedef typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type proxy_type; + + obj.push(obj.interpreter()); + return proxy_type(obj.interpreter(), 1, &detail::resume_impl, args); + } + + template + typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type + resume(lua_State* L BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _) ) + { + typedef boost::tuples::tuple tuple_t; +#if BOOST_PP_ITERATION() == 0 + tuple_t args; +#else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); +#endif + typedef typename boost::mpl::if_ + , luabind::detail::proxy_function_void_caller > + , luabind::detail::proxy_function_caller > >::type proxy_type; + + return proxy_type(L, 0, &detail::resume_impl, args); + } + + +#undef LUABIND_OPERATOR_PARAMS +#undef LUABIND_TUPLE_PARAMS + + +#endif + diff --git a/luabind/luabind/detail/call_member.hpp b/luabind/luabind/detail/call_member.hpp new file mode 100644 index 000000000..de8d56372 --- /dev/null +++ b/luabind/luabind/detail/call_member.hpp @@ -0,0 +1,363 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#if !BOOST_PP_IS_ITERATING + +#ifndef LUABIND_CALL_MEMBER_HPP_INCLUDED +#define LUABIND_CALL_MEMBER_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include // TODO: REMOVE DEPENDENCY + +#include + +#include +#include +#include + +#include + +namespace luabind +{ + namespace detail + { + + namespace mpl = boost::mpl; + + // if the proxy_member_caller returns non-void + template + class proxy_member_caller + { +// friend class luabind::object; + public: + + proxy_member_caller(lua_State* L_, const Tuple args) + : L(L_) + , m_args(args) + , m_called(false) + { + } + + proxy_member_caller(const proxy_member_caller& rhs) + : L(rhs.L) + , m_args(rhs.m_args) + , m_called(rhs.m_called) + { + rhs.m_called = true; + } + + ~proxy_member_caller() + { + if (m_called) return; + + m_called = true; + + // don't count the function and self-reference + // since those will be popped by pcall + int top = lua_gettop(L) - 2; + + // pcall will pop the function and self reference + // and all the parameters + + push_args_from_tuple<1>::apply(L, m_args); + if (pcall(L, boost::tuples::length::value + 1, 0)) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + // pops the return values from the function + stack_pop pop(L, lua_gettop(L) - top); + } + + operator Ret() + { + typename mpl::apply_wrap2::type converter; + + m_called = true; + + // don't count the function and self-reference + // since those will be popped by pcall + int top = lua_gettop(L) - 2; + + // pcall will pop the function and self reference + // and all the parameters + push_args_from_tuple<1>::apply(L, m_args); + if (pcall(L, boost::tuples::length::value + 1, 1)) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + + // pops the return values from the function + stack_pop pop(L, lua_gettop(L) - top); + +#ifndef LUABIND_NO_ERROR_CHECKING + + if (converter.match(L, LUABIND_DECORATE_TYPE(Ret), -1) < 0) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(L, typeid(Ret)); +#else + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(L, typeid(Ret)); + + assert(0 && "the lua function's return value could not be converted." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } +#endif + return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1); + } + + template + Ret operator[](const Policies& p) + { + typedef typename find_conversion_policy<0, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + + m_called = true; + + // don't count the function and self-reference + // since those will be popped by pcall + int top = lua_gettop(L) - 2; + + // pcall will pop the function and self reference + // and all the parameters + + detail::push_args_from_tuple<1>::apply(L, m_args, p); + if (pcall(L, boost::tuples::length::value + 1, 1)) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + + // pops the return values from the function + stack_pop pop(L, lua_gettop(L) - top); + +#ifndef LUABIND_NO_ERROR_CHECKING + + if (converter.match(L, LUABIND_DECORATE_TYPE(Ret), -1) < 0) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(L, typeid(Ret)); +#else + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(L, typeid(Ret)); + + assert(0 && "the lua function's return value could not be converted." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } +#endif + return converter.apply(L, LUABIND_DECORATE_TYPE(Ret), -1); + } + + private: + + lua_State* L; + Tuple m_args; + mutable bool m_called; + + }; + + // if the proxy_member_caller returns void + template + class proxy_member_void_caller + { + friend class luabind::object; + public: + + proxy_member_void_caller(lua_State* L_, const Tuple args) + : L(L_) + , m_args(args) + , m_called(false) + { + } + + proxy_member_void_caller(const proxy_member_void_caller& rhs) + : L(rhs.L) + , m_args(rhs.m_args) + , m_called(rhs.m_called) + { + rhs.m_called = true; + } + + ~proxy_member_void_caller() + { + if (m_called) return; + + m_called = true; + + // don't count the function and self-reference + // since those will be popped by pcall + int top = lua_gettop(L) - 2; + + // pcall will pop the function and self reference + // and all the parameters + + push_args_from_tuple<1>::apply(L, m_args); + if (pcall(L, boost::tuples::length::value + 1, 0)) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + // pops the return values from the function + stack_pop pop(L, lua_gettop(L) - top); + } + + template + void operator[](const Policies& p) + { + m_called = true; + + // don't count the function and self-reference + // since those will be popped by pcall + int top = lua_gettop(L) - 2; + + // pcall will pop the function and self reference + // and all the parameters + + detail::push_args_from_tuple<1>::apply(L, m_args, p); + if (pcall(L, boost::tuples::length::value + 1, 0)) + { + assert(lua_gettop(L) == top + 1); +#ifndef LUABIND_NO_EXCEPTIONS + throw error(L); +#else + error_callback_fun e = get_error_callback(); + if (e) e(L); + + assert(0 && "the lua function threw an error and exceptions are disabled." + "If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + // pops the return values from the function + stack_pop pop(L, lua_gettop(L) - top); + } + + private: + lua_State* L; + Tuple m_args; + mutable bool m_called; + + }; + + } // detail + + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) + #include BOOST_PP_ITERATE() + +} + +#endif // LUABIND_CALL_MEMBER_HPP_INCLUDED + +#elif BOOST_PP_ITERATION_FLAGS() == 1 + +#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * +#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n + + template + typename boost::mpl::if_ + , luabind::detail::proxy_member_void_caller > + , luabind::detail::proxy_member_caller > >::type + call_member(object const& obj, const char* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _)) + { + typedef boost::tuples::tuple tuple_t; +#if BOOST_PP_ITERATION() == 0 + tuple_t args; +#else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); +#endif + + typedef typename boost::mpl::if_ + , luabind::detail::proxy_member_void_caller > + , luabind::detail::proxy_member_caller > >::type proxy_type; + + // this will be cleaned up by the proxy object + // once the call has been made + + // get the function + obj.push(obj.interpreter()); + lua_pushstring(obj.interpreter(), name); + lua_gettable(obj.interpreter(), -2); + // duplicate the self-object + lua_pushvalue(obj.interpreter(), -2); + // remove the bottom self-object + lua_remove(obj.interpreter(), -3); + + // now the function and self objects + // are on the stack. These will both + // be popped by pcall + return proxy_type(obj.interpreter(), args); + } + +#undef LUABIND_OPERATOR_PARAMS +#undef LUABIND_TUPLE_PARAMS + +#endif + diff --git a/luabind/luabind/detail/call_operator_iterate.hpp b/luabind/luabind/detail/call_operator_iterate.hpp new file mode 100644 index 000000000..c6f95a10c --- /dev/null +++ b/luabind/luabind/detail/call_operator_iterate.hpp @@ -0,0 +1,66 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define N BOOST_PP_ITERATION() + +#define LUABIND_UNWRAP_PARAMETER(z, n, _) \ + typename detail::unwrap_parameter_type::type \ + BOOST_PP_CAT(_, n) + +template +struct BOOST_PP_CAT(call_operator, N) + : detail::operator_< + BOOST_PP_CAT(call_operator, N)< + Self BOOST_PP_ENUM_TRAILING_PARAMS(N, A) + > + > +{ + BOOST_PP_CAT(call_operator, N)(int) {} + + template + struct apply + { + static void execute( + lua_State* L + , typename detail::unwrap_parameter_type::type self + BOOST_PP_ENUM_TRAILING(N, LUABIND_UNWRAP_PARAMETER, _) + ) + { + using namespace detail; + operator_result( + L +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + , self(BOOST_PP_ENUM_PARAMS(N, _)) +#else + , (self(BOOST_PP_ENUM_PARAMS(N, _)), detail::operator_void_return()) +#endif + , (Policies*)0 + ); + } + }; + + static char const* name() { return "__call"; } +}; + +#undef LUABIND_UNWRAP_PARAMETER +#undef N + diff --git a/luabind/luabind/detail/class_cache.hpp b/luabind/luabind/detail/class_cache.hpp new file mode 100644 index 000000000..f49687c30 --- /dev/null +++ b/luabind/luabind/detail/class_cache.hpp @@ -0,0 +1,89 @@ +// Copyright (c) 2004 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef CLASS_CACHE_040218_HPP +#define CLASS_CACHE_040218_HPP + +#include +#include +#include + +namespace luabind { namespace detail { + +#ifdef LUABIND_NOT_THREADSAFE + + class class_rep; + + template + struct class_cache_impl + { + static lua_State* state; + static class_rep* class_; + }; + + template + lua_State* class_cache_impl::state = 0; + + template + class_rep* class_cache_impl::class_ = 0; + + template + struct class_cache + : class_cache_impl< + typename boost::add_reference< + typename boost::add_const< + T + >::type + >::type + > + { + }; + + template + class_rep* get_class_rep(lua_State* L, void(*)(T*) = 0) + { + if (class_cache::state != L) + { + class_cache::state = L; + + class_registry* registry = class_registry::get_registry(L); + class_cache::class_ = registry->find_class(typeid(T)); + } + + return class_cache::class_; + } + +#else + + template + class_rep* get_class_rep(lua_State* L, void(*)(T*) = 0) + { + class_registry* registry = class_registry::get_registry(L); + return registry->find_class(typeid(T)); + } + +#endif + +}} // namespace luabind::detail + +#endif // CLASS_CACHE_040218_HPP + diff --git a/luabind/luabind/detail/class_registry.hpp b/luabind/luabind/detail/class_registry.hpp new file mode 100644 index 000000000..12ed03cfe --- /dev/null +++ b/luabind/luabind/detail/class_registry.hpp @@ -0,0 +1,85 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CLASS_REGISTRY_HPP_INCLUDED +#define LUABIND_CLASS_REGISTRY_HPP_INCLUDED + +#include + +#include +#include +#include + +namespace luabind { namespace detail +{ + class class_rep; + + struct LUABIND_API class_registry + { + class_registry(lua_State* L); + + static class_registry* get_registry(lua_State* L); + + int cpp_instance() const { return m_instance_metatable; } + int cpp_class() const { return m_cpp_class_metatable; } + + int lua_instance() const { return m_instance_metatable; } + int lua_class() const { return m_lua_class_metatable; } + int lua_function() const { return m_lua_function_metatable; } + + void add_class(type_id const& info, class_rep* crep); + + class_rep* find_class(type_id const& info) const; + + std::map const& get_classes() const + { + return m_classes; + } + + private: + + std::map m_classes; + + // this is a lua reference that points to the lua table + // that is to be used as meta table for all C++ class + // instances. It is a kind of v-table. + int m_instance_metatable; + + // this is a lua reference to the metatable to be used + // for all classes defined in C++. + int m_cpp_class_metatable; + + // this is a lua reference to the metatable to be used + // for all classes defined in lua + int m_lua_class_metatable; + + // this metatable only contains a destructor + // for luabind::Detail::free_functions::function_rep + int m_lua_function_metatable; + + }; + +}} + +#endif // LUABIND_CLASS_REGISTRY_HPP_INCLUDED + diff --git a/luabind/luabind/detail/class_rep.hpp b/luabind/luabind/detail/class_rep.hpp new file mode 100644 index 000000000..aa5e866d3 --- /dev/null +++ b/luabind/luabind/detail/class_rep.hpp @@ -0,0 +1,213 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CLASS_REP_HPP_INCLUDED +#define LUABIND_CLASS_REP_HPP_INCLUDED + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace luabind { namespace detail +{ + + LUABIND_API std::string stack_content_by_name(lua_State* L, int start_index); + + struct class_registration; + + struct conversion_storage; + + // This function is used as a tag to identify "properties". + LUABIND_API int property_tag(lua_State*); + + // this is class-specific information, poor man's vtable + // this is allocated statically (removed by the compiler) + // a pointer to this structure is stored in the lua tables' + // metatable with the name __classrep + // it is used when matching parameters to function calls + // to determine possible implicit casts + // it is also used when finding the best match for overloaded + // methods + + class cast_graph; + class class_id_map; + + class LUABIND_API class_rep + { + friend struct class_registration; + friend int super_callback(lua_State*); +//TODO: avoid the lua-prefix + friend int lua_class_gettable(lua_State*); + friend int lua_class_settable(lua_State*); + friend int static_class_gettable(lua_State*); + public: + + enum class_type + { + cpp_class = 0, + lua_class = 1 + }; + + // EXPECTS THE TOP VALUE ON THE LUA STACK TO + // BE THE USER DATA WHERE THIS CLASS IS BEING + // INSTANTIATED! + class_rep(type_id const& type + , const char* name + , lua_State* L + ); + + // used when creating a lua class + // EXPECTS THE TOP VALUE ON THE LUA STACK TO + // BE THE USER DATA WHERE THIS CLASS IS BEING + // INSTANTIATED! + class_rep(lua_State* L, const char* name); + + ~class_rep(); + + std::pair allocate(lua_State* L) const; + + // this is called as metamethod __call on the class_rep. + static int constructor_dispatcher(lua_State* L); + + struct base_info + { + int pointer_offset; // the offset added to the pointer to obtain a basepointer (due to multiple-inheritance) + class_rep* base; + }; + + void add_base_class(const base_info& binfo); + + const std::vector& bases() const throw() { return m_bases; } + + void set_type(type_id const& t) { m_type = t; } + type_id const& type() const throw() { return m_type; } + + const char* name() const throw() { return m_name; } + + // the lua reference to the metatable for this class' instances + int metatable_ref() const throw() { return m_instance_metatable; } + + void get_table(lua_State* L) const { m_table.push(L); } + void get_default_table(lua_State* L) const { m_default_table.push(L); } + + class_type get_class_type() const { return m_class_type; } + + void add_static_constant(const char* name, int val); + + static int super_callback(lua_State* L); + + static int lua_settable_dispatcher(lua_State* L); + + // called from the metamethod for __index + // obj is the object pointer + static int static_class_gettable(lua_State* L); + + bool has_operator_in_lua(lua_State*, int id); + + cast_graph const& casts() const + { + return *m_casts; + } + + class_id_map const& classes() const + { + return *m_classes; + } + + private: + + void cache_operators(lua_State*); + + // this is a pointer to the type_info structure for + // this type + // warning: this may be a problem when using dll:s, since + // typeid() may actually return different pointers for the same + // type. + type_id m_type; + + // a list of info for every class this class derives from + // the information stored here is sufficient to do + // type casts to the base classes + std::vector m_bases; + + // the class' name (as given when registered to lua with class_) + const char* m_name; + + // a reference to this structure itself. Since this struct + // is kept inside lua (to let lua collect it when lua_close() + // is called) we need to lock it to prevent collection. + // the actual reference is not currently used. + detail::lua_reference m_self_ref; + + // this should always be used when accessing + // members in instances of a class. + // this table contains c closures for all + // member functions in this class, they + // may point to both static and virtual functions + handle m_table; + + // this table contains default implementations of the + // virtual functions in m_table. + handle m_default_table; + + // the type of this class.. determines if it's written in c++ or lua + class_type m_class_type; + + // this is a lua reference that points to the lua table + // that is to be used as meta table for all instances + // of this class. + int m_instance_metatable; + + std::map m_static_constants; + + // the first time an operator is invoked + // we check the associated lua table + // and cache the result + int m_operator_cache; + + cast_graph* m_casts; + class_id_map* m_classes; + }; + + bool is_class_rep(lua_State* L, int index); + +}} + +//#include + +#endif // LUABIND_CLASS_REP_HPP_INCLUDED diff --git a/luabind/luabind/detail/compute_score.hpp b/luabind/luabind/detail/compute_score.hpp new file mode 100644 index 000000000..c9a7e9ea1 --- /dev/null +++ b/luabind/luabind/detail/compute_score.hpp @@ -0,0 +1,73 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_COMPUTE_RANK_081006_HPP +# define LUABIND_COMPUTE_RANK_081006_HPP + +# include +# include +# include +# include +# include +# include + +namespace luabind { namespace detail { + +namespace mpl = boost::mpl; + +template +int compute_score_aux( + lua_State*L, int index, Idx, Iter, End end, Policies const& policies) +{ + typedef typename Iter::type arg_type; + typedef typename find_conversion_policy::type + conversion_policy; + typedef typename mpl::apply_wrap2< + conversion_policy, arg_type, lua_to_cpp>::type converter; + + int score = converter::match(L, LUABIND_DECORATE_TYPE(arg_type), index); + + if (score < 0) + return score; + + if (conversion_policy::has_arg) + ++index; + + int next = compute_score_aux( + L + , index + , typename mpl::next::type() + , typename mpl::next::type() + , end + , policies + ); + + if (next < 0) + return next; + + return score + next; +} + +template +int compute_score_aux(lua_State*, int, Idx, End, End, Policies const&) +{ + return 0; +} + +template +int compute_score(lua_State* L, Signature, Policies const& policies) +{ + return compute_score_aux( + L + , 1 + , mpl::int_<1>() + , typename mpl::next::type>::type() + , typename mpl::end::type() + , policies + ); +} + +}} // namespace luabind::detail + +#endif // LUABIND_COMPUTE_RANK_081006_HPP diff --git a/luabind/luabind/detail/constructor.hpp b/luabind/luabind/detail/constructor.hpp new file mode 100644 index 000000000..1cbceb789 --- /dev/null +++ b/luabind/luabind/detail/constructor.hpp @@ -0,0 +1,111 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !BOOST_PP_IS_ITERATING + +# ifndef LUABIND_DETAIL_CONSTRUCTOR_081018_HPP +# define LUABIND_DETAIL_CONSTRUCTOR_081018_HPP + +# include +# include +# include +# include + +# include +# include +# include +# include + +namespace luabind { namespace detail { + +inline void inject_backref(lua_State*, void*, void*) +{} + +template +void inject_backref(lua_State* L, T* p, wrap_base*) +{ + weak_ref(get_main_thread(L), L, 1).swap(wrap_access::ref(*p)); +} + +template +struct construct_aux; + +template +struct construct + : construct_aux::value - 2, T, Pointer, Signature> +{}; + +template +struct construct_aux<0, T, Pointer, Signature> +{ + typedef pointer_holder holder_type; + + void operator()(argument const& self_) const + { + object_rep* self = touserdata(self_); + class_rep* cls = self->crep(); + + std::auto_ptr instance(new T); + inject_backref(self_.interpreter(), instance.get(), instance.get()); + + void* naked_ptr = instance.get(); + Pointer ptr(instance.release()); + + void* storage = self->allocate(sizeof(holder_type)); + + self->set_instance(new (storage) holder_type( + ptr, registered_class::id, naked_ptr, cls)); + } +}; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (1, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +}} // namespace luabind::detail + +# endif // LUABIND_DETAIL_CONSTRUCTOR_081018_HPP + +#else // !BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() + +template +struct construct_aux +{ + typedef typename mpl::begin::type first; + typedef typename mpl::next::type iter0; + +# define BOOST_PP_LOCAL_MACRO(n) \ + typedef typename mpl::next< \ + BOOST_PP_CAT(iter,BOOST_PP_DEC(n))>::type BOOST_PP_CAT(iter,n); \ + typedef typename BOOST_PP_CAT(iter,n)::type BOOST_PP_CAT(a,BOOST_PP_DEC(n)); + +# define BOOST_PP_LOCAL_LIMITS (1,N) +# include BOOST_PP_LOCAL_ITERATE() + + typedef pointer_holder holder_type; + + void operator()(argument const& self_, BOOST_PP_ENUM_BINARY_PARAMS(N,a,_)) const + { + object_rep* self = touserdata(self_); + class_rep* cls = self->crep(); + + std::auto_ptr instance(new T(BOOST_PP_ENUM_PARAMS(N,_))); + inject_backref(self_.interpreter(), instance.get(), instance.get()); + + void* naked_ptr = instance.get(); + Pointer ptr(instance.release()); + + void* storage = self->allocate(sizeof(holder_type)); + + self->set_instance(new (storage) holder_type( + ptr, registered_class::id, naked_ptr, cls)); + } +}; + +# undef N + +#endif + diff --git a/luabind/luabind/detail/conversion_storage.hpp b/luabind/luabind/detail/conversion_storage.hpp new file mode 100644 index 000000000..153112d62 --- /dev/null +++ b/luabind/luabind/detail/conversion_storage.hpp @@ -0,0 +1,41 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_CONVERSION_STORAGE_080930_HPP +# define LUABIND_CONVERSION_STORAGE_080930_HPP + +# include +# include + +namespace luabind { namespace detail { + +typedef void(*destruction_function)(void*); + +// This is used by the converters in policy.hpp, and +// class_rep::convert_to as temporary storage when constructing +// holders. + +struct conversion_storage +{ + conversion_storage() + : destructor(0) + {} + + ~conversion_storage() + { + if (destructor) + destructor(&data); + } + + // Unfortunately the converters currently doesn't have access to + // the actual type being converted when this is instantiated, so + // we have to guess a max size. + boost::aligned_storage<128> data; + destruction_function destructor; +}; + +}} // namespace luabind::detail + +#endif // LUABIND_CONVERSION_STORAGE_080930_HPP + diff --git a/luabind/luabind/detail/convert_to_lua.hpp b/luabind/luabind/detail/convert_to_lua.hpp new file mode 100644 index 000000000..f5aa89aea --- /dev/null +++ b/luabind/luabind/detail/convert_to_lua.hpp @@ -0,0 +1,92 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_CONVERT_TO_LUA_HPP_INCLUDED +#define LUABIND_CONVERT_TO_LUA_HPP_INCLUDED + +#include +#include +#include + +#include + +namespace luabind { namespace detail +{ + template + struct unwrap_ref + { + template + static const T& get(const T& r) { return r; } + + template + struct apply + { + typedef T type; + }; + }; + + template<> + struct unwrap_ref + { + template + static T& get(const boost::reference_wrapper& r) { return r.get(); } + + template + struct apply + { + typedef typename T::type& type; + }; + }; + + namespace mpl = boost::mpl; + + template + void convert_to_lua(lua_State* L, const T& v) + { + typedef typename mpl::apply_wrap1< + unwrap_ref::value> + , T + >::type value_type; + + typename mpl::apply_wrap2::type converter; + + converter.apply(L, unwrap_ref::value>::get(v)); + } + + template + void convert_to_lua_p(lua_State* L, const T& v, const Policies&) + { + typedef typename mpl::apply_wrap1< + unwrap_ref::value> + , T + >::type value_type; + + typedef typename find_conversion_policy::type converter_policy; + typename mpl::apply_wrap2::type converter; + + converter.apply(L, unwrap_ref::value>::get(v)); + } +}} + +#endif + diff --git a/luabind/luabind/detail/debug.hpp b/luabind/luabind/detail/debug.hpp new file mode 100644 index 000000000..ef13bc886 --- /dev/null +++ b/luabind/luabind/detail/debug.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_DEBUG_HPP_INCLUDED +#define LUABIND_DEBUG_HPP_INCLUDED + +#ifndef NDEBUG + +#include +#include + +namespace luabind { namespace detail +{ + struct stack_checker_type + { + stack_checker_type(lua_State* L) + : m_L(L) + , m_stack(lua_gettop(m_L)) + {} + + ~stack_checker_type() + { + assert(m_stack == lua_gettop(m_L)); + } + + lua_State* m_L; + int m_stack; + }; + +}} +#define LUABIND_CHECK_STACK(L) luabind::detail::stack_checker_type stack_checker_object(L) +#else +#define LUABIND_CHECK_STACK(L) do {} while (0) +#endif + +#endif // LUABIND_DEBUG_HPP_INCLUDED diff --git a/luabind/luabind/detail/decorate_type.hpp b/luabind/luabind/detail/decorate_type.hpp new file mode 100644 index 000000000..bb144c463 --- /dev/null +++ b/luabind/luabind/detail/decorate_type.hpp @@ -0,0 +1,266 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_DECORATE_TYPE_HPP_INCLUDED +#define LUABIND_DECORATE_TYPE_HPP_INCLUDED + +#include +#include + +namespace luabind { namespace detail +{ + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct decorated_type + { + static by_value t; + static inline by_value& get() { return /*by_value()*/t; } + }; + + template + by_value decorated_type::t; + + template + struct decorated_type + { + static by_pointer t; + static inline by_pointer& get() { return /*by_pointer()*/t; } + }; + + template + by_pointer decorated_type::t; + + template + struct decorated_type + { + static by_const_pointer t; + static inline by_const_pointer get() { return /*by_const_pointer()*/t; } + }; + + template + by_const_pointer decorated_type::t; + + template + struct decorated_type + { + static by_const_pointer t; + static inline by_const_pointer& get() { return /*by_const_pointer()*/t; } + }; + + template + by_const_pointer decorated_type::t; + + template + struct decorated_type + { + static by_reference t; + static inline by_reference& get() { return /*by_reference()*/t; } + }; + + template + by_reference decorated_type::t; + + template + struct decorated_type + { + static by_const_reference t; + static inline by_const_reference& get() { return /*by_const_reference()*/t; } + }; + + template + by_const_reference decorated_type::t; + + #define LUABIND_DECORATE_TYPE(t) luabind::detail::decorated_type::get() + +#else + +#include + + namespace + { + LUABIND_ANONYMOUS_FIX char decorated_type_array[64]; + } + + template + struct decorated_type_cref_impl + { +#if defined(BOOST_MSVC) && BOOST_MSVC == 1200 + template + static by_const_reference get(const U&) + { + return by_const_reference(); + } + static T data() { return reinterpret_cast(decorated_type_array); } +#else + + static void(*data())(T) + { return (void(*)(T))0; } + + template + static by_const_reference get(void(*f)(const U&)) + { return by_const_reference(); } +#endif + }; + + template + struct decorated_type_ref_impl + { +#if defined(BOOST_MSVC) && BOOST_MSVC == 1200 + template + static by_reference get(U&) + { + return by_reference(); + } + static T data() { return reinterpret_cast(decorated_type_array); } +#else + static void(*data())(T) + { return (void(*)(T))0; } + + template + static by_reference get(void(*)(U&)) + { return by_reference(); } +#endif + }; + + template + struct decorated_type_cptr_impl + { +#if defined(BOOST_MSVC) && BOOST_MSVC == 1200 + template + static by_const_pointer get(const U*) + { + return by_const_pointer(); + } + static T& data() { return reinterpret_cast(decorated_type_array); } +#else + static void(*data())(T) + { return (void(*)(T))0; } + + template + static by_const_pointer get(void(*)(const U*)) + { return by_const_pointer(); } +#endif + }; + + template + struct decorated_type_ptr_impl + { +#if defined(BOOST_MSVC) && BOOST_MSVC == 1200 + template + static by_pointer get(U*) + { + return by_pointer(); + } + static T& data() { return reinterpret_cast(decorated_type_array); } +#else + static void(*data())(T) + { return (void(*)(T))0; } + + template + static by_pointer get(void(*)(U*)) + { return by_pointer(); } +#endif + }; + + template + struct decorated_type_value_impl + { +#if defined(BOOST_MSVC) && BOOST_MSVC == 1200 + template + static by_value get(U&) + { + return by_value(); + } + static T& data() { return reinterpret_cast(decorated_type_array); } +#else + static void(*data())(T&) + { return (void(*)(T&))0; } + + template + static by_value get(void(*)(U&)) + { return by_value(); } +#endif + }; + + template<> + struct decorated_type_value_impl + { + static by_value get(int) + { + return by_value(); + } + static int data() { return 0; } + }; + + template + struct decorated_type_array_impl + { + template + static by_pointer get(U*) + { + return by_pointer(); + } + + template + static by_pointer get(void(*)(U)) + { return by_pointer(); } + + static T& data() { return reinterpret_cast(decorated_type_array); } + }; + + template + struct decorated_type +// : boost::mpl::if_ +// , decorated_type_array_impl + : boost::mpl::if_ + , decorated_type_cref_impl + , typename boost::mpl::if_ + , decorated_type_ref_impl + , typename boost::mpl::if_ + , decorated_type_ptr_impl + , typename boost::mpl::if_ + , decorated_type_cptr_impl + , decorated_type_value_impl + >::type + >::type + >::type + >::type +// >::type + { + }; + +#if defined(BOOST_MSVC) && BOOST_MSVC == 1200 + #define LUABIND_DECORATE_TYPE(t) luabind::detail::decorated_type::get(luabind::detail::decorated_type::data()) +#else +// #define LUABIND_DECORATE_TYPE(t) luabind::detail::decorated_type::get((void(*)(type))0) + #define LUABIND_DECORATE_TYPE(t) luabind::detail::decorated_type::get(luabind::detail::decorated_type::data()) + //#define LUABIND_DECORATE_TYPE(t) luabind::detail::decorated_type::get(type()) +#endif + +#endif + +}} + +#endif // LUABIND_DECORATE_TYPE_HPP_INCLUDED diff --git a/luabind/luabind/detail/deduce_signature.hpp b/luabind/luabind/detail/deduce_signature.hpp new file mode 100644 index 000000000..e47e22f4e --- /dev/null +++ b/luabind/luabind/detail/deduce_signature.hpp @@ -0,0 +1,118 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !BOOST_PP_IS_ITERATING + +# ifndef LUABIND_DEDUCE_SIGNATURE_080911_HPP +# define LUABIND_DEDUCE_SIGNATURE_080911_HPP + +# include + +# if LUABIND_MAX_ARITY <= 8 +# include +# else +# include +# endif +# include +# include +# include + +namespace luabind { namespace detail { + +namespace mpl = boost::mpl; + +template +mpl::vector1 deduce_signature(R(*)(), ...) +{ + return mpl::vector1(); +} + +template +mpl::vector2 deduce_signature(R(T::*)()) +{ + return mpl::vector2(); +} + +template +mpl::vector2::type&> +deduce_signature(R(T::*)(), Wrapped*) +{ + return mpl::vector2::type&>(); +} + +template +mpl::vector2 deduce_signature(R(T::*)() const) +{ + return mpl::vector2(); +} + +template +mpl::vector2::type const&> +deduce_signature(R(T::*)() const, Wrapped*) +{ + return mpl::vector2::type const&>(); +} + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (1, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +}} // namespace luabind::detail + +# endif // LUABIND_DEDUCE_SIGNATURE_080911_HPP + +#else // BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() +# define NPLUS1 BOOST_PP_INC(N) + +template +BOOST_PP_CAT(mpl::vector,NPLUS1) +deduce_signature(R(*)(BOOST_PP_ENUM_PARAMS(N,A)), ...) +{ + return BOOST_PP_CAT(mpl::vector,NPLUS1)(); +} + +# define NPLUS2 BOOST_PP_INC(NPLUS1) + +template +BOOST_PP_CAT(mpl::vector,NPLUS2) +deduce_signature(R(T::*)(BOOST_PP_ENUM_PARAMS(N,A))) +{ + return BOOST_PP_CAT(mpl::vector,NPLUS2)(); +} + +template +BOOST_PP_CAT(mpl::vector,NPLUS2)< + R, typename most_derived::type&, BOOST_PP_ENUM_PARAMS(N,A) +> +deduce_signature(R(T::*)(BOOST_PP_ENUM_PARAMS(N,A)), Wrapped*) +{ + return BOOST_PP_CAT(mpl::vector,NPLUS2)< + R,typename most_derived::type&,BOOST_PP_ENUM_PARAMS(N,A)>(); +} + +template +BOOST_PP_CAT(mpl::vector,NPLUS2) +deduce_signature(R(T::*)(BOOST_PP_ENUM_PARAMS(N,A)) const) +{ + return BOOST_PP_CAT(mpl::vector,NPLUS2)(); +} + +template +BOOST_PP_CAT(mpl::vector,NPLUS2)< + R, typename most_derived::type const&, BOOST_PP_ENUM_PARAMS(N,A) +> +deduce_signature(R(T::*)(BOOST_PP_ENUM_PARAMS(N,A)) const, Wrapped*) +{ + return BOOST_PP_CAT(mpl::vector,NPLUS2)< + R,typename most_derived::type const&,BOOST_PP_ENUM_PARAMS(N,A)>(); +} + +# undef NPLUS2 +# undef NPLUS1 +# undef N + +#endif // BOOST_PP_IS_ITERATING + diff --git a/luabind/luabind/detail/enum_maker.hpp b/luabind/luabind/detail/enum_maker.hpp new file mode 100644 index 000000000..fadbe3e52 --- /dev/null +++ b/luabind/luabind/detail/enum_maker.hpp @@ -0,0 +1,123 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_ENUM_MAKER_HPP_INCLUDED +#define LUABIND_ENUM_MAKER_HPP_INCLUDED + +#include +#include + +#include +#include + +namespace luabind +{ + struct value; + + struct value_vector : public std::vector + { + // a bug in intel's compiler forces us to declare these constructors explicitly. + value_vector(); + virtual ~value_vector(); + value_vector(const value_vector& v); + value_vector& operator,(const value& rhs); + }; + + struct value + { + friend class std::vector; + template + value(const char* name, T v) + : name_(name) + , val_(v) + {} + + const char* name_; + int val_; + + value_vector operator,(const value& rhs) const + { + value_vector v; + + v.push_back(*this); + v.push_back(rhs); + + return v; + } + + private: + + value() {} + }; + + inline value_vector::value_vector() + : std::vector() + { + } + + inline value_vector::~value_vector() {} + + inline value_vector::value_vector(const value_vector& rhs) + : std::vector(rhs) + { + } + + inline value_vector& value_vector::operator,(const value& rhs) + { + push_back(rhs); + return *this; + } + + namespace detail + { + template + struct enum_maker + { + explicit enum_maker(From& from): from_(from) {} + + From& operator[](const value& val) + { + from_.add_static_constant(val.name_, val.val_); + return from_; + } + + From& operator[](const value_vector& values) + { + for (value_vector::const_iterator i = values.begin(); i != values.end(); ++i) + { + from_.add_static_constant(i->name_, i->val_); + } + + return from_; + } + + From& from_; + + private: + void operator=(enum_maker const&); // C4512, assignment operator could not be generated + template void operator,(T const&) const; + }; + } +} + +#endif // LUABIND_ENUM_MAKER_HPP_INCLUDED diff --git a/luabind/luabind/detail/format_signature.hpp b/luabind/luabind/detail/format_signature.hpp new file mode 100644 index 000000000..56e796363 --- /dev/null +++ b/luabind/luabind/detail/format_signature.hpp @@ -0,0 +1,148 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_FORMAT_SIGNATURE_081014_HPP +# define LUABIND_FORMAT_SIGNATURE_081014_HPP + +# include +# include +# include + +# include +# include +# include + +namespace luabind { + +class object; +class argument; +template +struct table; + +} // namespace luabind + +namespace luabind { namespace detail { + +LUABIND_API std::string get_class_name(lua_State* L, type_id const& i); + +template +struct type_to_string +{ + static void get(lua_State* L) + { + lua_pushstring(L, get_class_name(L, typeid(T)).c_str()); + } +}; + +template +struct type_to_string +{ + static void get(lua_State* L) + { + type_to_string::get(L); + lua_pushstring(L, "*"); + lua_concat(L, 2); + } +}; + +template +struct type_to_string +{ + static void get(lua_State* L) + { + type_to_string::get(L); + lua_pushstring(L, "&"); + lua_concat(L, 2); + } +}; + +template +struct type_to_string +{ + static void get(lua_State* L) + { + type_to_string::get(L); + lua_pushstring(L, " const"); + lua_concat(L, 2); + } +}; + +# define LUABIND_TYPE_TO_STRING(x) \ + template <> \ + struct type_to_string \ + { \ + static void get(lua_State* L) \ + { \ + lua_pushstring(L, #x); \ + } \ + }; + +# define LUABIND_INTEGRAL_TYPE_TO_STRING(x) \ + LUABIND_TYPE_TO_STRING(x) \ + LUABIND_TYPE_TO_STRING(unsigned x) + +LUABIND_INTEGRAL_TYPE_TO_STRING(char) +LUABIND_INTEGRAL_TYPE_TO_STRING(short) +LUABIND_INTEGRAL_TYPE_TO_STRING(int) +LUABIND_INTEGRAL_TYPE_TO_STRING(long) + +LUABIND_TYPE_TO_STRING(void) +LUABIND_TYPE_TO_STRING(bool) +LUABIND_TYPE_TO_STRING(std::string) +LUABIND_TYPE_TO_STRING(lua_State) + +LUABIND_TYPE_TO_STRING(luabind::object) +LUABIND_TYPE_TO_STRING(luabind::argument) + +# undef LUABIND_INTEGRAL_TYPE_TO_STRING +# undef LUABIND_TYPE_TO_STRING + +template +struct type_to_string > +{ + static void get(lua_State* L) + { + lua_pushstring(L, "table"); + } +}; + +template +void format_signature_aux(lua_State*, bool, End, End) +{} + +template +void format_signature_aux(lua_State* L, bool first, Iter, End end) +{ + if (!first) + lua_pushstring(L, ","); + type_to_string::get(L); + format_signature_aux(L, false, typename mpl::next::type(), end); +} + +template +void format_signature(lua_State* L, char const* function, Signature) +{ + typedef typename mpl::begin::type first; + + type_to_string::get(L); + + lua_pushstring(L, " "); + lua_pushstring(L, function); + + lua_pushstring(L, "("); + format_signature_aux( + L + , true + , typename mpl::next::type() + , typename mpl::end::type() + ); + lua_pushstring(L, ")"); + + lua_concat(L, static_cast(mpl::size()) * 2 + 2); +} + +}} // namespace luabind::detail + +#endif // LUABIND_FORMAT_SIGNATURE_081014_HPP + diff --git a/luabind/luabind/detail/garbage_collector.hpp b/luabind/luabind/detail/garbage_collector.hpp new file mode 100644 index 000000000..c0d68aa36 --- /dev/null +++ b/luabind/luabind/detail/garbage_collector.hpp @@ -0,0 +1,53 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_GARBAGE_COLLECTOR_HPP_INCLUDED +#define LUABIND_GARBAGE_COLLECTOR_HPP_INCLUDED + +#include + +namespace luabind { namespace detail +{ + // function that is used as __gc metafunction on several objects + template + inline int garbage_collector(lua_State* L) + { + T* obj = static_cast(lua_touserdata(L, -1)); + obj->~T(); + return 0; + } + + template + struct garbage_collector_s + { + static int apply(lua_State* L) + { + T* obj = static_cast(lua_touserdata(L, -1)); + obj->~T(); + return 0; + } + }; + +}} + +#endif // LUABIND_GARBAGE_COLLECTOR_HPP_INCLUDED diff --git a/luabind/luabind/detail/has_get_pointer.hpp b/luabind/luabind/detail/has_get_pointer.hpp new file mode 100644 index 000000000..8a001ddda --- /dev/null +++ b/luabind/luabind/detail/has_get_pointer.hpp @@ -0,0 +1,107 @@ +// Copyright (c) 2005 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_HAS_GET_POINTER_051022_HPP +# define LUABIND_HAS_GET_POINTER_051022_HPP + +# include + +# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# include +# endif + +namespace luabind { namespace detail { + +namespace has_get_pointer_ +{ + + struct any + { + template any(T const&); + }; + + struct no_overload_tag + {}; + + typedef char (&yes)[1]; + typedef char (&no)[2]; + + no_overload_tag operator,(no_overload_tag, int); + +// +// On compilers with ADL, we need these generic overloads in this +// namespace as well as in luabind::. Otherwise get_pointer(any) +// will be found before them. +// +# ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + + template + T* get_pointer(T const volatile*); + + template + T* get_pointer(std::auto_ptr const&); + +# endif + +// +// On compilers that doesn't support ADL, the overload below has to +// live in luabind::. +// +# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +}} // namespace detail::has_get_pointer_ +# endif + +detail::has_get_pointer_::no_overload_tag + get_pointer(detail::has_get_pointer_::any); + +# ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +namespace detail { namespace has_get_pointer_ +{ +# endif + + template + yes check(T const&); + no check(no_overload_tag); + + template + struct impl + { + static typename boost::add_reference::type x; + + BOOST_STATIC_CONSTANT(bool, + value = sizeof(has_get_pointer_::check( (get_pointer(x),0) )) == 1 + ); + + typedef boost::mpl::bool_ type; + }; + +} // namespace has_get_pointer_ + +template +struct has_get_pointer + : has_get_pointer_::impl::type +{}; + +}} // namespace luabind::detail + +#endif // LUABIND_HAS_GET_POINTER_051022_HPP + diff --git a/luabind/luabind/detail/inheritance.hpp b/luabind/luabind/detail/inheritance.hpp new file mode 100644 index 000000000..a7afe0156 --- /dev/null +++ b/luabind/luabind/detail/inheritance.hpp @@ -0,0 +1,168 @@ +// Copyright Daniel Wallin 2009. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_INHERITANCE_090217_HPP +# define LUABIND_INHERITANCE_090217_HPP + +# include +# include +# include +# include +# include +# include +# include + +namespace luabind { namespace detail { + +typedef void*(*cast_function)(void*); +typedef std::size_t class_id; + +class_id const unknown_class = (std::numeric_limits::max)(); + +class class_rep; + +class LUABIND_API cast_graph +{ +public: + cast_graph(); + ~cast_graph(); + + // `src` and `p` here describe the *most derived* object. This means that + // for a polymorphic type, the pointer must be cast with + // dynamic_cast before being passed in here, and `src` has to + // match typeid(*p). + std::pair cast( + void* p, class_id src, class_id target + , class_id dynamic_id, void const* dynamic_ptr) const; + void insert(class_id src, class_id target, cast_function cast); + +private: + class impl; + boost::scoped_ptr m_impl; +}; + +// Maps a type_id to a class_id. Note that this actually partitions the +// id-space into two, using one half for "local" ids; ids that are used only as +// keys into the conversion cache. This is needed because we need a unique key +// even for types that hasn't been registered explicitly. +class LUABIND_API class_id_map +{ +public: + class_id_map(); + + class_id get(type_id const& type) const; + class_id get_local(type_id const& type); + void put(class_id id, type_id const& type); + +private: + typedef std::map map_type; + map_type m_classes; + class_id m_local_id; + + static class_id const local_id_base; +}; + +inline class_id_map::class_id_map() + : m_local_id(local_id_base) +{} + +inline class_id class_id_map::get(type_id const& type) const +{ + map_type::const_iterator i = m_classes.find(type); + if (i == m_classes.end() || i->second >= local_id_base) + return unknown_class; + return i->second; +} + +inline class_id class_id_map::get_local(type_id const& type) +{ + std::pair result = m_classes.insert( + std::make_pair(type, 0)); + + if (result.second) + result.first->second = m_local_id++; + + assert(m_local_id >= local_id_base); + + return result.first->second; +} + +inline void class_id_map::put(class_id id, type_id const& type) +{ + assert(id < local_id_base); + + std::pair result = m_classes.insert( + std::make_pair(type, 0)); + + assert( + result.second + || result.first->second == id + || result.first->second >= local_id_base + ); + + result.first->second = id; +} + +class class_map +{ +public: + class_rep* get(class_id id) const; + void put(class_id id, class_rep* cls); + +private: + std::vector m_classes; +}; + +inline class_rep* class_map::get(class_id id) const +{ + if (id >= m_classes.size()) + return 0; + return m_classes[id]; +} + +inline void class_map::put(class_id id, class_rep* cls) +{ + if (id >= m_classes.size()) + m_classes.resize(id + 1); + m_classes[id] = cls; +} + +template +struct static_cast_ +{ + static void* execute(void* p) + { + return static_cast(static_cast(p)); + } +}; + +template +struct dynamic_cast_ +{ + static void* execute(void* p) + { + return dynamic_cast(static_cast(p)); + } +}; + +// Thread safe class_id allocation. +LUABIND_API class_id allocate_class_id(type_id const& cls); + +template +struct registered_class +{ + static class_id const id; +}; + +template +class_id const registered_class::id = allocate_class_id(typeid(T)); + +template +struct registered_class + : registered_class +{}; + +}} // namespace luabind::detail + +#endif // LUABIND_INHERITANCE_090217_HPP diff --git a/luabind/luabind/detail/instance_holder.hpp b/luabind/luabind/detail/instance_holder.hpp new file mode 100644 index 000000000..456e13e6b --- /dev/null +++ b/luabind/luabind/detail/instance_holder.hpp @@ -0,0 +1,131 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_INSTANCE_HOLDER_081024_HPP +# define LUABIND_INSTANCE_HOLDER_081024_HPP + +# include +# include // TODO +# include +# include +# include +# include + +namespace luabind { namespace detail { + +class instance_holder +{ +public: + instance_holder(class_rep* cls, bool pointee_const) + : m_cls(cls) + , m_pointee_const(pointee_const) + {} + + virtual ~instance_holder() + {} + + virtual std::pair get(class_id target) const = 0; + + virtual void release() = 0; + + class_rep* get_class() const + { + return m_cls; + } + + bool pointee_const() const + { + return m_pointee_const; + } + +private: + class_rep* m_cls; + bool m_pointee_const; +}; + +namespace mpl = boost::mpl; + +inline mpl::false_ check_const_pointer(void*) +{ + return mpl::false_(); +} + +inline mpl::true_ check_const_pointer(void const*) +{ + return mpl::true_(); +} + +template +void release_ownership(std::auto_ptr& p) +{ + p.release(); +} + +template +void release_ownership(P const&) +{ + throw std::runtime_error( + "luabind: smart pointer does not allow ownership transfer"); +} + +template +class_id static_class_id(T*) +{ + return registered_class::id; +} + +template +class pointer_holder : public instance_holder +{ +public: + pointer_holder( + P p, class_id dynamic_id, void* dynamic_ptr, class_rep* cls + ) + : instance_holder(cls, check_const_pointer(false ? get_pointer(p) : 0)) + , p(p) + , weak(0) + , dynamic_id(dynamic_id) + , dynamic_ptr(dynamic_ptr) + {} + + std::pair get(class_id target) const + { + if (target == registered_class

::id) + return std::pair(&this->p, 0); + + void* naked_ptr = const_cast(static_cast( + weak ? weak : get_pointer(p))); + + if (!naked_ptr) + return std::pair((void*)0, 0); + + return get_class()->casts().cast( + naked_ptr + , static_class_id(false ? get_pointer(p) : 0) + , target + , dynamic_id + , dynamic_ptr + ); + } + + void release() + { + weak = const_cast(static_cast( + get_pointer(p))); + release_ownership(p); + } + +private: + mutable P p; + // weak will hold a possibly stale pointer to the object owned + // by p once p has released it's owership. This is a workaround + // to make adopt() work with virtual function wrapper classes. + void* weak; + class_id dynamic_id; + void* dynamic_ptr; +}; + +}} // namespace luabind::detail + +#endif // LUABIND_INSTANCE_HOLDER_081024_HPP diff --git a/luabind/luabind/detail/is_indirect_const.hpp b/luabind/luabind/detail/is_indirect_const.hpp new file mode 100644 index 000000000..b6c1282fb --- /dev/null +++ b/luabind/luabind/detail/is_indirect_const.hpp @@ -0,0 +1,70 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef IS_INDIRECT_CONST_040211_HPP +#define IS_INDIRECT_CONST_040211_HPP + +#include +#include +#include + +namespace luabind { + + namespace detail { + + template + typename boost::is_const::type + is_indirect_const_check(T(*)(), int); + + template + typename boost::is_const::type + is_indirect_const_check(T*(*)(), long); + + template + typename boost::is_const::type + is_indirect_const_check(T&(*)(), long); + + yes_t to_yes_no(boost::mpl::true_); + no_t to_yes_no(boost::mpl::false_); + + } // namespace detail + + // returns true for: + // T = U* is_const + // T = U& is_const + // T = U is_const + template + struct is_indirect_const + { + BOOST_STATIC_CONSTANT(int, value = ( + sizeof( + detail::to_yes_no( + detail::is_indirect_const_check((T(*)())0, 0L) + )) + == sizeof(detail::yes_t) + )); + }; + +} // namespace luabind + +#endif // IS_INDIRECT_CONST_040211_HPP + diff --git a/luabind/luabind/detail/link_compatibility.hpp b/luabind/luabind/detail/link_compatibility.hpp new file mode 100644 index 000000000..6f0006afa --- /dev/null +++ b/luabind/luabind/detail/link_compatibility.hpp @@ -0,0 +1,60 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_LINK_COMPATIBILITY_HPP_INCLUDED +#define LUABIND_LINK_COMPATIBILITY_HPP_INCLUDED + +#include + +namespace luabind { namespace detail +{ + +#ifdef LUABIND_NOT_THREADSAFE + LUABIND_API void not_threadsafe_defined_conflict(); +#else + LUABIND_API void not_threadsafe_not_defined_conflict(); +#endif + +#ifdef LUABIND_NO_ERROR_CHECKING + LUABIND_API void no_error_checking_defined_conflict(); +#else + LUABIND_API void no_error_checking_not_defined_conflict(); +#endif + + inline void check_link_compatibility() + { + #ifdef LUABIND_NOT_THREADSAFE + not_threadsafe_defined_conflict(); + #else + not_threadsafe_not_defined_conflict(); + #endif + + #ifdef LUABIND_NO_ERROR_CHECKING + no_error_checking_defined_conflict(); + #else + no_error_checking_not_defined_conflict(); + #endif + } + +}} + +#endif diff --git a/luabind/luabind/detail/make_instance.hpp b/luabind/luabind/detail/make_instance.hpp new file mode 100644 index 000000000..3150cf048 --- /dev/null +++ b/luabind/luabind/detail/make_instance.hpp @@ -0,0 +1,105 @@ +// Copyright Daniel Wallin 2009. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP +# define LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP + +# include +# include +# include + +namespace luabind { namespace detail { + +template +std::pair get_dynamic_class_aux( + lua_State* L, T const* p, mpl::true_) +{ + lua_pushliteral(L, "__luabind_class_id_map"); + lua_rawget(L, LUA_REGISTRYINDEX); + + class_id_map& class_ids = *static_cast( + lua_touserdata(L, -1)); + + lua_pop(L, 1); + + return std::make_pair( + class_ids.get_local(typeid(*p)) + , dynamic_cast(const_cast(p)) + ); +} + +template +std::pair get_dynamic_class_aux( + lua_State*, T const* p, mpl::false_) +{ + return std::make_pair(registered_class::id, (void*)p); +} + +template +std::pair get_dynamic_class(lua_State* L, T* p) +{ + return get_dynamic_class_aux(L, p, boost::is_polymorphic()); +} + +template +class_rep* get_pointee_class(class_map const& classes, T*) +{ + return classes.get(registered_class::id); +} + +template +class_rep* get_pointee_class(lua_State* L, P const& p, class_id dynamic_id) +{ + lua_pushliteral(L, "__luabind_class_map"); + lua_rawget(L, LUA_REGISTRYINDEX); + + class_map const& classes = *static_cast( + lua_touserdata(L, -1)); + + lua_pop(L, 1); + + class_rep* cls = classes.get(dynamic_id); + + if (!cls) + cls = get_pointee_class(classes, get_pointer(p)); + + return cls; +} + +// Create an appropriate instance holder for the given pointer like object. +template +void make_instance(lua_State* L, P p) +{ + std::pair dynamic = get_dynamic_class(L, get_pointer(p)); + + class_rep* cls = get_pointee_class(L, p, dynamic.first); + + if (!cls) + { + throw std::runtime_error("Trying to use unregistered class"); + } + + object_rep* instance = push_new_instance(L, cls); + + typedef pointer_holder

holder_type; + + void* storage = instance->allocate(sizeof(holder_type)); + + try + { + new (storage) holder_type(p, dynamic.first, dynamic.second, cls); + } + catch (...) + { + instance->deallocate(storage); + lua_pop(L, 1); + throw; + } + + instance->set_instance(static_cast(storage)); +} + +}} // namespace luabind::detail + +#endif // LUABIND_DETAIL_MAKE_INSTANCE_090310_HPP diff --git a/luabind/luabind/detail/most_derived.hpp b/luabind/luabind/detail/most_derived.hpp new file mode 100644 index 000000000..4dd9d9159 --- /dev/null +++ b/luabind/luabind/detail/most_derived.hpp @@ -0,0 +1,44 @@ +// Copyright (c) 2005 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef MOST_DERIVED_051018_HPP +# define MOST_DERIVED_051018_HPP + +# include +# include + +namespace luabind { namespace detail { + +template +struct most_derived +{ + typedef typename boost::mpl::if_< + boost::is_base_and_derived + , WrappedClass + , Class + >::type type; +}; + +}} // namespace luabind::detail + +#endif // MOST_DERIVED_051018_HPP + diff --git a/luabind/luabind/detail/object_call.hpp b/luabind/luabind/detail/object_call.hpp new file mode 100644 index 000000000..46ab0d958 --- /dev/null +++ b/luabind/luabind/detail/object_call.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2005 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#if !BOOST_PP_IS_ITERATING +# error Do not include object_call.hpp directly! +#endif + +#include +#include +#include + +#define N BOOST_PP_ITERATION() + +template +call_proxy< + Derived + , boost::tuples::tuple< + BOOST_PP_ENUM_BINARY_PARAMS(N, A, const* BOOST_PP_INTERCEPT) + > +> operator()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a)) +{ + typedef boost::tuples::tuple< + BOOST_PP_ENUM_BINARY_PARAMS(N, A, const* BOOST_PP_INTERCEPT) + > arguments; + + return call_proxy( + derived() + , arguments(BOOST_PP_ENUM_PARAMS(N, &a)) + ); +} + +#undef N + diff --git a/luabind/luabind/detail/object_funs.hpp b/luabind/luabind/detail/object_funs.hpp new file mode 100644 index 000000000..2600238d9 --- /dev/null +++ b/luabind/luabind/detail/object_funs.hpp @@ -0,0 +1,224 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_OBJECT_PROXY_HPP_INCLUDED +#define LUABIND_OBJECT_PROXY_HPP_INCLUDED + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace luabind +{ + + namespace detail + { + + namespace mpl = boost::mpl; + + template + inline T object_cast_impl(const Obj& obj, const Policies&) + { + if (obj.lua_state() == 0) + { +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(0, typeid(T)); +#else + lua_State* L = obj.lua_state(); + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(L, typeid(T)); + + assert(0 && "object_cast failed. If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + + LUABIND_CHECK_STACK(obj.lua_state()); + + typedef typename detail::find_conversion_policy<0, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + + obj.pushvalue(); + + lua_State* L = obj.lua_state(); + detail::stack_pop p(L, 1); + +#ifndef LUABIND_NO_ERROR_CHECKING + + if (converter.match(L, LUABIND_DECORATE_TYPE(T), -1) < 0) + { +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(L, typeid(T)); +#else + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(L, typeid(T)); + + assert(0 && "object_cast failed. If you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } +#endif + + return converter.apply(L, LUABIND_DECORATE_TYPE(T), -1); + } + + template + boost::optional object_cast_nothrow_impl(const Obj& obj, const Policies&) + { + typedef typename detail::find_conversion_policy<0, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + + if (obj.lua_state() == 0) return boost::optional(); + LUABIND_CHECK_STACK(obj.lua_state()); + + obj.pushvalue(); + + lua_State* L = obj.lua_state(); + detail::stack_pop p(L, 1); + +#ifndef LUABIND_NO_ERROR_CHECKING + + if (converter.match(L, LUABIND_DECORATE_TYPE(T), -1) < 0) + return boost::optional(); +#endif + + return boost::optional(converter.apply(L, LUABIND_DECORATE_TYPE(T), -1)); + } + } + + template + T object_cast(const object& obj) + { return detail::object_cast_impl(obj, detail::null_type()); } + + template + T object_cast(const object& obj, const Policies& p) + { return detail::object_cast_impl(obj, p); } + + template + boost::optional object_cast_nothrow(const object& obj) + { return detail::object_cast_nothrow_impl(obj, detail::null_type()); } + + template + boost::optional object_cast_nothrow(const object& obj, const Policies& p) + { return detail::object_cast_nothrow_impl(obj, p); } + + + template + T object_cast(const detail::proxy_object& obj) + { return detail::object_cast_impl(obj, detail::null_type()); } + + template + T object_cast(const detail::proxy_object& obj, const Policies& p) + { return detail::object_cast_impl(obj, p); } + + template + boost::optional object_cast_nothrow(const detail::proxy_object& obj) + { return detail::object_cast_nothrow_impl(obj, detail::null_type()); } + + template + boost::optional object_cast_nothrow(const detail::proxy_object& obj, const Policies& p) + { return detail::object_cast_nothrow_impl(obj, p); } + + + template + T object_cast(const detail::proxy_raw_object& obj) + { return detail::object_cast_impl(obj, detail::null_type()); } + + template + T object_cast(const detail::proxy_raw_object& obj, const Policies& p) + { return detail::object_cast_impl(obj, p); } + + template + boost::optional object_cast_nothrow(const detail::proxy_raw_object& obj) + { return detail::object_cast_nothrow_impl(obj, detail::null_type()); } + + template + boost::optional object_cast_nothrow(const detail::proxy_raw_object& obj, const Policies& p) + { return detail::object_cast_nothrow_impl(obj, p); } + + + template + T object_cast(const detail::proxy_array_object& obj) + { return detail::object_cast_impl(obj, detail::null_type()); } + + template + T object_cast(const detail::proxy_array_object& obj, const Policies& p) + { return detail::object_cast_impl(obj, p); } + + template + boost::optional object_cast_nothrow(const detail::proxy_array_object& obj) + { return detail::object_cast_nothrow_impl(obj, detail::null_type()); } + + template + boost::optional object_cast_nothrow(const detail::proxy_array_object& obj, const Policies& p) + { return detail::object_cast_nothrow_impl(obj, p); } + + + + + inline object get_globals(lua_State* L) + { + lua_pushvalue(L, LUA_GLOBALSINDEX); + detail::lua_reference ref; + ref.set(L); + return object(L, ref, true/*object::reference()*/); + } + + inline object get_registry(lua_State* L) + { + lua_pushvalue(L, LUA_REGISTRYINDEX); + detail::lua_reference ref; + ref.set(L); + return object(L, ref, true/*object::reference()*/); + } + + inline object newtable(lua_State* L) + { + lua_newtable(L); + detail::lua_reference ref; + ref.set(L); + return object(L, ref, true/*object::reference()*/); + } +} + +/* + +struct A +{ +}; + +object f = class_(); + +A* ptr = object_cast(f(), adopt(_1)); + +delete ptr; + +*/ + +#endif // LUABIND_OBJECT_PROXY_HPP_INCLUDED diff --git a/luabind/luabind/detail/object_rep.hpp b/luabind/luabind/detail/object_rep.hpp new file mode 100644 index 000000000..dafa6532a --- /dev/null +++ b/luabind/luabind/detail/object_rep.hpp @@ -0,0 +1,132 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_OBJECT_REP_HPP_INCLUDED +#define LUABIND_OBJECT_REP_HPP_INCLUDED + +#include +#include +#include +#include + +namespace luabind { namespace detail +{ + class class_rep; + + void finalize(lua_State* L, class_rep* crep); + + // this class is allocated inside lua for each pointer. + // it contains the actual c++ object-pointer. + // it also tells if it is const or not. + class LUABIND_API object_rep + { + public: + object_rep(instance_holder* instance, class_rep* crep); + ~object_rep(); + + const class_rep* crep() const { return m_classrep; } + class_rep* crep() { return m_classrep; } + + void set_instance(instance_holder* instance) { m_instance = instance; } + + void add_dependency(lua_State* L, int index); + void release_dependency_refs(lua_State* L); + + std::pair get_instance(class_id target) const + { + if (m_instance == 0) + return std::pair((void*)0, -1); + return m_instance->get(target); + } + + bool is_const() const + { + return m_instance && m_instance->pointee_const(); + } + + void release() + { + if (m_instance) + m_instance->release(); + } + + void* allocate(std::size_t size) + { + if (size <= 32) + return &m_instance_buffer; + return std::malloc(size); + } + + void deallocate(void* storage) + { + if (storage == &m_instance_buffer) + return; + std::free(storage); + } + + private: + + object_rep(object_rep const&) + {} + + void operator=(object_rep const&) + {} + + instance_holder* m_instance; + boost::aligned_storage<32> m_instance_buffer; + class_rep* m_classrep; // the class information about this object's type + std::size_t m_dependency_cnt; // counts dependencies + }; + + template + struct delete_s + { + static void apply(void* ptr) + { + delete static_cast(ptr); + } + }; + + template + struct destruct_only_s + { + static void apply(void* ptr) + { + // Removes unreferenced formal parameter warning on VC7. + (void)ptr; +#ifndef NDEBUG + int completeness_check[sizeof(T)]; + (void)completeness_check; +#endif + static_cast(ptr)->~T(); + } + }; + + LUABIND_API object_rep* get_instance(lua_State* L, int index); + LUABIND_API void push_instance_metatable(lua_State* L); + LUABIND_API object_rep* push_new_instance(lua_State* L, class_rep* cls); + +}} + +#endif // LUABIND_OBJECT_REP_HPP_INCLUDED + diff --git a/luabind/luabind/detail/open.hpp b/luabind/luabind/detail/open.hpp new file mode 100644 index 000000000..a30faeef8 --- /dev/null +++ b/luabind/luabind/detail/open.hpp @@ -0,0 +1,45 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_OPEN_HPP_INCLUDED +#define LUABIND_OPEN_HPP_INCLUDED + +#include + +namespace luabind +{ + namespace detail + { + LUABIND_API void add_operator_to_metatable(lua_State* L, int op_index); + LUABIND_API int create_cpp_class_metatable(lua_State* L); + LUABIND_API int create_cpp_instance_metatable(lua_State* L); + LUABIND_API int create_lua_class_metatable(lua_State* L); + LUABIND_API int create_lua_instance_metatable(lua_State* L); + LUABIND_API int create_lua_function_metatable(lua_State* L); + } + + LUABIND_API void open(lua_State* L); +} + +#endif // LUABIND_OPEN_HPP_INCLUDED + diff --git a/luabind/luabind/detail/operator_id.hpp b/luabind/luabind/detail/operator_id.hpp new file mode 100644 index 000000000..ed64ba6d5 --- /dev/null +++ b/luabind/luabind/detail/operator_id.hpp @@ -0,0 +1,79 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_OPERATOR_ID_HPP_INCLUDED +#define LUABIND_OPERATOR_ID_HPP_INCLUDED + +#include + +namespace luabind { namespace detail { + + enum operator_id + { + op_add = 0, + op_sub, + op_mul, + op_div, + op_pow, + op_lt, + op_le, + op_eq, + op_call, + op_unm, + op_tostring, + op_concat, + op_len, + + number_of_operators + }; + + inline const char* get_operator_name(int i) + { + static const char* a[number_of_operators] = { + "__add", "__sub", "__mul", "__div", "__pow", + "__lt", "__le", "__eq", "__call", "__unm", + "__tostring", "__concat", "__len" }; + return a[i]; + } + + inline const char* get_operator_symbol(int i) + { + static const char* a[number_of_operators] = { + "+", "-", "*", "/", "^", "<", + "<=", "==", "()", "- (unary)", + "tostring", "..", "#" }; + return a[i]; + } + + inline bool is_unary(int i) + { + // the reason why unary minus is not considered a unary operator here is + // that it always is given two parameters, where the second parameter always + // is nil. + return i == op_tostring; + } + + +}} + +#endif // LUABIND_OPERATOR_ID_HPP_INCLUDED diff --git a/luabind/luabind/detail/other.hpp b/luabind/luabind/detail/other.hpp new file mode 100644 index 000000000..679058c9e --- /dev/null +++ b/luabind/luabind/detail/other.hpp @@ -0,0 +1,119 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_OTHER_HPP_INCLUDED +#define LUABIND_OTHER_HPP_INCLUDED + +// header derived from source code found in Boost.Python + +// Copyright David Abrahams 2002. Permission to copy, use, +// modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. + +#include +#include + +namespace luabind +{ + template + struct other + { + typedef T type; + }; +} + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace luabind { namespace detail +{ + template + class unwrap_other + { + public: + typedef T type; + }; + + template + class unwrap_other > + { + public: + typedef T type; + }; +}} // namespace luabind::detail + +# else // no partial specialization + +#include + +namespace luabind { namespace detail +{ + typedef char (&yes_other_t)[1]; + typedef char (&no_other_t)[2]; + + no_other_t is_other_test(...); + + template + yes_other_t is_other_test(type_< other >); + + template + struct other_unwrapper + { + template + struct apply + { + typedef T type; + }; + }; + + template<> + struct other_unwrapper + { + template + struct apply + { + typedef typename T::type type; + }; + }; + + template + class is_other + { + public: + BOOST_STATIC_CONSTANT( + bool, value = ( + sizeof(detail::is_other_test(type_())) + == sizeof(detail::yes_other_t))); + }; + + template + class unwrap_other + : public detail::other_unwrapper< + is_other::value + >::template apply + {}; + +}} // namespace luabind::detail +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // LUABIND_OTHER_HPP_INCLUDED diff --git a/luabind/luabind/detail/pcall.hpp b/luabind/luabind/detail/pcall.hpp new file mode 100644 index 000000000..f0d72b162 --- /dev/null +++ b/luabind/luabind/detail/pcall.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_PCALL_HPP_INCLUDED +#define LUABIND_PCALL_HPP_INCLUDED + +#include + +struct lua_State; + +namespace luabind { namespace detail +{ + LUABIND_API int pcall(lua_State *L, int nargs, int nresults); + LUABIND_API int resume_impl(lua_State *L, int nargs, int nresults); +}} + +#endif diff --git a/luabind/luabind/detail/pointee_sizeof.hpp b/luabind/luabind/detail/pointee_sizeof.hpp new file mode 100644 index 000000000..3875c09dd --- /dev/null +++ b/luabind/luabind/detail/pointee_sizeof.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef POINTEE_SIZEOF_040211_HPP +#define POINTEE_SIZEOF_040211_HPP + +#include + +namespace luabind { + + namespace detail { + + template T& deref_type(T(*)(), int); + template T& deref_type(T*(*)(), long); + + } // namespace detail + + // returns the indirect sizeof U, as in + // sizeof(T*) = sizeof(T) + // sizeof(T&) = sizeof(T) + // sizeof(T) = sizeof(T) + template + struct pointee_sizeof + { + BOOST_STATIC_CONSTANT(int, value = ( + sizeof(detail::deref_type((T(*)())0), 0L) + )); + + typedef boost::mpl::int_ type; + }; + +} // namespace luabind + +#endif // POINTEE_SIZEOF_040211_HPP + diff --git a/luabind/luabind/detail/pointee_typeid.hpp b/luabind/luabind/detail/pointee_typeid.hpp new file mode 100644 index 000000000..ab4113711 --- /dev/null +++ b/luabind/luabind/detail/pointee_typeid.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2004 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef POINTEE_TYPEID_040211_HPP +#define POINTEE_TYPEID_040211_HPP + +#include +#include + +namespace luabind { namespace detail { + + template + type_id pointee_typeid(T*) + { + return typeid(T); + } + +}} // namespace luabind::detail + +#endif // POINTEE_TYPEID_040211_HPP + diff --git a/luabind/luabind/detail/policy.hpp b/luabind/luabind/detail/policy.hpp new file mode 100644 index 000000000..689c73399 --- /dev/null +++ b/luabind/luabind/detail/policy.hpp @@ -0,0 +1,1021 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_POLICY_HPP_INCLUDED +#define LUABIND_POLICY_HPP_INCLUDED + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +namespace luabind +{ + namespace detail + { + struct conversion_policy_base {}; + } + + template + struct conversion_policy : detail::conversion_policy_base + { + BOOST_STATIC_CONSTANT(int, index = N); + BOOST_STATIC_CONSTANT(bool, has_arg = HasArg); + }; + + class index_map + { + public: + index_map(const int* m): m_map(m) {} + + int operator[](int index) const + { + return m_map[index]; + } + + private: + const int* m_map; + }; + +// template class functor; + class weak_ref; +} + +namespace luabind { namespace detail +{ + template + struct policy_cons + { + typedef H head; + typedef T tail; + + template + policy_cons > operator,(policy_cons) + { + return policy_cons >(); + } + + template + policy_cons > operator+(policy_cons) + { + return policy_cons >(); + } + + template + policy_cons > operator|(policy_cons) + { + return policy_cons >(); + } + }; + + struct indirection_layer + { + template + indirection_layer(const T&); + }; + + yes_t is_policy_cons_test(const null_type&); + template + yes_t is_policy_cons_test(const policy_cons&); + no_t is_policy_cons_test(...); + + template + struct is_policy_cons + { + static const T& t; + + BOOST_STATIC_CONSTANT(bool, value = + sizeof(is_policy_cons_test(t)) == sizeof(yes_t)); + + typedef boost::mpl::bool_ type; + }; + + template + struct is_string_literal + { + static no_t helper(indirection_layer); + static yes_t helper(const char*); + }; + + template<> + struct is_string_literal + { + static no_t helper(indirection_layer); + }; + + + namespace mpl = boost::mpl; + + template + void make_pointee_instance(lua_State* L, T& x, mpl::true_, Clone) + { + if (get_pointer(x)) + { + make_instance(L, x); + } + else + { + lua_pushnil(L); + } + } + + template + void make_pointee_instance(lua_State* L, T& x, mpl::false_, mpl::true_) + { + std::auto_ptr ptr(new T(x)); + make_instance(L, ptr); + } + + template + void make_pointee_instance(lua_State* L, T& x, mpl::false_, mpl::false_) + { + make_instance(L, &x); + } + + template + void make_pointee_instance(lua_State* L, T& x, Clone) + { + make_pointee_instance(L, x, has_get_pointer(), Clone()); + } + +// ********** pointer converter *********** + + struct pointer_converter + { + typedef pointer_converter type; + typedef mpl::false_ is_native; + + pointer_converter() + : result(0) + {} + + void* result; + + int const consumed_args(...) + { + return 1; + } + + template + void apply(lua_State* L, T* ptr) + { + if (ptr == 0) + { + lua_pushnil(L); + return; + } + + if (luabind::get_back_reference(L, ptr)) + return; + + make_instance(L, ptr); + } + + template + T* apply(lua_State*, by_pointer, int) + { + return static_cast(result); + } + + template + int match(lua_State* L, by_pointer, int index) + { + if (lua_isnil(L, index)) return 0; + object_rep* obj = get_instance(L, index); + if (obj == 0) return -1; + + if (obj->is_const()) + return -1; + + std::pair s = obj->get_instance(registered_class::id); + result = s.first; + return s.second; + } + + template + void converter_postcall(lua_State*, by_pointer, int) + {} + }; + +// ******* value converter ******* + + struct value_converter + { + typedef value_converter type; + typedef mpl::false_ is_native; + + int const consumed_args(...) + { + return 1; + } + + value_converter() + : result(0) + {} + + void* result; + + template + void apply(lua_State* L, T x) + { + if (luabind::get_back_reference(L, x)) + return; + + make_pointee_instance(L, x, mpl::true_()); + } + + template + T apply(lua_State*, by_value, int) + { + return *static_cast(result); + } + + template + int match(lua_State* L, by_value, int index) + { + // special case if we get nil in, try to match the holder type + if (lua_isnil(L, index)) + return -1; + + object_rep* obj = get_instance(L, index); + if (obj == 0) return -1; + + std::pair s = obj->get_instance(registered_class::id); + result = s.first; + return s.second; + } + + template + void converter_postcall(lua_State*, T, int) {} + }; + +// ******* const pointer converter ******* + + struct const_pointer_converter + { + typedef const_pointer_converter type; + typedef mpl::false_ is_native; + + int const consumed_args(...) + { + return 1; + } + + const_pointer_converter() + : result(0) + {} + + void* result; + + template + void apply(lua_State* L, const T* ptr) + { + if (ptr == 0) + { + lua_pushnil(L); + return; + } + + if (luabind::get_back_reference(L, ptr)) + return; + + make_instance(L, ptr); + } + + template + T const* apply(lua_State*, by_const_pointer, int) + { + return static_cast(result); + } + + template + int match(lua_State* L, by_const_pointer, int index) + { + if (lua_isnil(L, index)) return 0; + object_rep* obj = get_instance(L, index); + if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match + std::pair s = obj->get_instance(registered_class::id); + if (s.second >= 0 && !obj->is_const()) + s.second += 10; + result = s.first; + return s.second; + } + + template + void converter_postcall(lua_State*, T, int) {} + }; + +// ******* reference converter ******* + + struct ref_converter : pointer_converter + { + typedef ref_converter type; + typedef mpl::false_ is_native; + + int const consumed_args(...) + { + return 1; + } + + template + void apply(lua_State* L, T& ref) + { + if (luabind::get_back_reference(L, ref)) + return; + + make_pointee_instance(L, ref, mpl::false_()); + } + + template + T& apply(lua_State* L, by_reference, int index) + { + assert(!lua_isnil(L, index)); + return *pointer_converter::apply(L, by_pointer(), index); + } + + template + int match(lua_State* L, by_reference, int index) + { + object_rep* obj = get_instance(L, index); + if (obj == 0) return -1; + + if (obj->is_const()) + return -1; + + std::pair s = obj->get_instance(registered_class::id); + result = s.first; + return s.second; + } + + template + void converter_postcall(lua_State*, T, int) {} + }; + +// ******** const reference converter ********* + + struct const_ref_converter + { + typedef const_ref_converter type; + typedef mpl::false_ is_native; + + int const consumed_args(...) + { + return 1; + } + + const_ref_converter() + : result(0) + {} + + void* result; + + template + void apply(lua_State* L, T const& ref) + { + if (luabind::get_back_reference(L, ref)) + return; + + make_pointee_instance(L, ref, mpl::false_()); + } + + template + T const& apply(lua_State*, by_const_reference, int) + { + return *static_cast(result); + } + + template + int match(lua_State* L, by_const_reference, int index) + { + object_rep* obj = get_instance(L, index); + if (obj == 0) return -1; // if the type is not one of our own registered types, classify it as a non-match + + std::pair s = obj->get_instance(registered_class::id); + if (s.second >= 0 && !obj->is_const()) + s.second += 10; + result = s.first; + return s.second; + } + + template + void converter_postcall(lua_State*, by_const_reference, int) + { + } + }; + + // ****** enum converter ******** + + struct enum_converter + { + typedef enum_converter type; + typedef mpl::true_ is_native; + + int const consumed_args(...) + { + return 1; + } + + void apply(lua_State* L, int val) + { + lua_pushnumber(L, val); + } + + template + T apply(lua_State* L, by_value, int index) + { + return static_cast(static_cast(lua_tonumber(L, index))); + } + + template + static int match(lua_State* L, by_value, int index) + { + if (lua_isnumber(L, index)) return 0; else return -1; + } + + template + T apply(lua_State* L, by_const_reference, int index) + { + return static_cast(static_cast(lua_tonumber(L, index))); + } + + template + static int match(lua_State* L, by_const_reference, int index) + { + if (lua_isnumber(L, index)) return 0; else return -1; + } + + template + void converter_postcall(lua_State*, T, int) {} + }; + + template + struct value_wrapper_converter + { + typedef value_wrapper_converter type; + typedef mpl::true_ is_native; + + int const consumed_args(...) + { + return 1; + } + + template + T apply(lua_State* L, by_const_reference, int index) + { + return T(from_stack(L, index)); + } + + template + T apply(lua_State* L, by_value, int index) + { + return apply(L, by_const_reference(), index); + } + + template + static int match(lua_State* L, by_const_reference, int index) + { + return value_wrapper_traits::check(L, index) + ? (std::numeric_limits::max)() / LUABIND_MAX_ARITY + : -1; + } + + template + static int match(lua_State* L, by_value, int index) + { + return match(L, by_const_reference(), index); + } + + void converter_postcall(...) {} + + template + void apply(lua_State* interpreter, T const& value_wrapper) + { + value_wrapper_traits::unwrap(interpreter, value_wrapper); + } + }; + + template + struct default_converter_generator + : mpl::eval_if< + is_value_wrapper_arg + , value_wrapper_converter + , mpl::eval_if< + boost::is_enum::type> + , enum_converter + , mpl::eval_if< + is_nonconst_pointer + , pointer_converter + , mpl::eval_if< + is_const_pointer + , const_pointer_converter + , mpl::eval_if< + is_nonconst_reference + , ref_converter + , mpl::eval_if< + is_const_reference + , const_ref_converter + , value_converter + > + > + > + > + > + > + {}; + +} // namespace detail + +// *********** default_policy ***************** + +template +struct default_converter + : detail::default_converter_generator::type +{}; + +template > +struct native_converter_base +{ + typedef boost::mpl::true_ is_native; + + int const consumed_args(...) + { + return 1; + } + + template + void converter_postcall(lua_State*, U const&, int) + {} + + int match(lua_State* L, detail::by_value, int index) + { + return derived().compute_score(L, index); + } + + int match(lua_State* L, detail::by_value, int index) + { + return derived().compute_score(L, index); + } + + int match(lua_State* L, detail::by_const_reference, int index) + { + return derived().compute_score(L, index); + } + + T apply(lua_State* L, detail::by_value, int index) + { + return derived().from(L, index); + } + + T apply(lua_State* L, detail::by_value, int index) + { + return derived().from(L, index); + } + + T apply(lua_State* L, detail::by_const_reference, int index) + { + return derived().from(L, index); + } + + void apply(lua_State* L, T const& value) + { + derived().to(L, value); + } + + Derived& derived() + { + return static_cast(*this); + } +}; + +template +lua_Integer as_lua_integer(T v) +{ + return static_cast(v); +} + +template +lua_Number as_lua_number(T v) +{ + return static_cast(v); +} + +# define LUABIND_NUMBER_CONVERTER(type, kind) \ + template <> \ +struct default_converter \ + : native_converter_base \ +{ \ + int compute_score(lua_State* L, int index) \ + { \ + return lua_type(L, index) == LUA_TNUMBER ? 0 : -1; \ + }; \ + \ + type from(lua_State* L, int index) \ + { \ + return static_cast(BOOST_PP_CAT(lua_to, kind)(L, index)); \ + } \ + \ + void to(lua_State* L, type const& value) \ + { \ + BOOST_PP_CAT(lua_push, kind)(L, BOOST_PP_CAT(as_lua_, kind)(value)); \ + } \ +}; \ +\ +template <> \ +struct default_converter \ + : default_converter \ +{}; \ +\ +template <> \ +struct default_converter \ + : default_converter \ +{}; + +LUABIND_NUMBER_CONVERTER(char, integer) +LUABIND_NUMBER_CONVERTER(signed char, integer) +LUABIND_NUMBER_CONVERTER(unsigned char, integer) +LUABIND_NUMBER_CONVERTER(signed short, integer) +LUABIND_NUMBER_CONVERTER(unsigned short, integer) +LUABIND_NUMBER_CONVERTER(signed int, integer) + +LUABIND_NUMBER_CONVERTER(unsigned int, number) +LUABIND_NUMBER_CONVERTER(unsigned long, number) + +LUABIND_NUMBER_CONVERTER(signed long, integer) +LUABIND_NUMBER_CONVERTER(float, number) +LUABIND_NUMBER_CONVERTER(double, number) +LUABIND_NUMBER_CONVERTER(long double, number) + +# undef LUABIND_NUMBER_CONVERTER + +template <> +struct default_converter + : native_converter_base +{ + static int compute_score(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TBOOLEAN ? 0 : -1; + } + + bool from(lua_State* L, int index) + { + return lua_toboolean(L, index) == 1; + } + + void to(lua_State* L, bool value) + { + lua_pushboolean(L, value); + } +}; + +template <> +struct default_converter + : default_converter +{}; + +template <> +struct default_converter + : default_converter +{}; + +template <> +struct default_converter + : native_converter_base +{ + static int compute_score(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TSTRING ? 0 : -1; + } + + std::string from(lua_State* L, int index) + { + return std::string(lua_tostring(L, index), lua_strlen(L, index)); + } + + void to(lua_State* L, std::string const& value) + { + lua_pushlstring(L, value.data(), value.size()); + } +}; + +template <> +struct default_converter + : default_converter +{}; + +template <> +struct default_converter + : default_converter +{}; + +template <> +struct default_converter +{ + typedef boost::mpl::true_ is_native; + + int const consumed_args(...) + { + return 1; + } + + template + static int match(lua_State* L, U, int index) + { + int type = lua_type(L, index); + return (type == LUA_TSTRING || type == LUA_TNIL) ? 0 : -1; + } + + template + char const* apply(lua_State* L, U, int index) + { + return lua_tostring(L, index); + } + + void apply(lua_State* L, char const* str) + { + lua_pushstring(L, str); + } + + template + void converter_postcall(lua_State*, U, int) + {} +}; + +template <> +struct default_converter + : default_converter +{}; + +template <> +struct default_converter + : default_converter +{}; + +template +struct default_converter + : default_converter +{}; + +template +struct default_converter + : default_converter +{}; + +template <> +struct default_converter +{ + int const consumed_args(...) + { + return 0; + } + + template + lua_State* apply(lua_State* L, U, int) + { + return L; + } + + template + static int match(lua_State*, U, int) + { + return 0; + } + + template + void converter_postcall(lua_State*, U, int) {} +}; + +namespace detail +{ + + struct default_policy : converter_policy_tag + { + BOOST_STATIC_CONSTANT(bool, has_arg = true); + + template + static void precall(lua_State*, T, int) {} + + template + struct apply + { + typedef default_converter type; + }; + }; + + template + struct is_primitive + : default_converter::is_native + {}; + +// ============== new policy system ================= + + template struct find_conversion_policy; + + template + struct find_conversion_impl + { + template + struct apply + { + typedef typename find_conversion_policy::type type; + }; + }; + + template<> + struct find_conversion_impl + { + template + struct apply + { + typedef typename Policies::head head; + typedef typename Policies::tail tail; + + BOOST_STATIC_CONSTANT(bool, found = (N == head::index)); + + typedef typename + boost::mpl::if_c::type + >::type type; + }; + }; + + template + struct find_conversion_impl2 + { + template + struct apply + : find_conversion_impl< + boost::is_base_and_derived::value + >::template apply + { + }; + }; + + template<> + struct find_conversion_impl2 + { + template + struct apply + { + typedef default_policy type; + }; + }; + + template + struct find_conversion_policy : find_conversion_impl2::template apply + { + }; + + template + struct policy_list_postcall + { + typedef typename List::head head; + typedef typename List::tail tail; + + static void apply(lua_State* L, const index_map& i) + { + head::postcall(L, i); + policy_list_postcall::apply(L, i); + } + }; + + template<> + struct policy_list_postcall + { + static void apply(lua_State*, const index_map&) {} + }; + +// ================================================== + +// ************** precall and postcall on policy_cons ********************* + + + template + struct policy_precall + { + typedef typename List::head head; + typedef typename List::tail tail; + + static void apply(lua_State* L, int index) + { + head::precall(L, index); + policy_precall::apply(L, index); + } + }; + + template<> + struct policy_precall + { + static void apply(lua_State*, int) {} + }; + + template + struct policy_postcall + { + typedef typename List::head head; + typedef typename List::tail tail; + + static void apply(lua_State* L, int index) + { + head::postcall(L, index); + policy_postcall::apply(L, index); + } + }; + + template<> + struct policy_postcall + { + static void apply(lua_State*, int) {} + }; + +}} // namespace luabind::detail + + +namespace luabind { namespace +{ +#if defined(__GNUC__) && ( \ + (BOOST_VERSION < 103500) \ + || (BOOST_VERSION < 103900 && (__GNUC__ * 100 + __GNUC_MINOR__ <= 400)) \ + || (__GNUC__ * 100 + __GNUC_MINOR__ < 400)) + static inline boost::arg<0> return_value() + { + return boost::arg<0>(); + } + + static inline boost::arg<0> result() + { + return boost::arg<0>(); + } +# define LUABIND_PLACEHOLDER_ARG(N) boost::arg(*)() +#elif defined(BOOST_MSVC) || defined(__MWERKS__) \ + || (BOOST_VERSION >= 103900 && defined(__GNUC__) \ + && (__GNUC__ * 100 + __GNUC_MINOR__ == 400)) + static boost::arg<0> return_value; + static boost::arg<0> result; +# define LUABIND_PLACEHOLDER_ARG(N) boost::arg +#else + boost::arg<0> return_value; + boost::arg<0> result; +# define LUABIND_PLACEHOLDER_ARG(N) boost::arg +#endif +}} + +#endif // LUABIND_POLICY_HPP_INCLUDED + diff --git a/luabind/luabind/detail/primitives.hpp b/luabind/luabind/detail/primitives.hpp new file mode 100644 index 000000000..04ce17b87 --- /dev/null +++ b/luabind/luabind/detail/primitives.hpp @@ -0,0 +1,85 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_PRIMITIVES_HPP_INCLUDED +#define LUABIND_PRIMITIVES_HPP_INCLUDED + +#include +#include + +#include +#include + +namespace luabind { namespace detail +{ + template + struct identity + { + typedef T type; + }; + + template + struct type_ {}; + + struct null_type {}; + +/* typedef char yes_t; + typedef double no_t;*/ + + struct lua_to_cpp {}; + struct cpp_to_lua {}; + + template struct by_value {}; + template struct by_reference {}; + template struct by_const_reference {}; + template struct by_pointer {}; + template struct by_const_pointer {}; + + struct converter_policy_tag {}; + + struct ltstr + { + bool operator()(const char* s1, const char* s2) const { return std::strcmp(s1, s2) < 0; } + }; + + template + struct aligned + { + char storage[N]; + }; + + // returns the offset added to a Derived* when cast to a Base* + // TODO: return ptrdiff + template + int ptr_offset(type_, type_) + { + aligned obj; + Derived* ptr = reinterpret_cast(&obj); + + return int(static_cast(static_cast(static_cast(ptr))) + - static_cast(static_cast(ptr))); + } + +}} + +#endif // LUABIND_PRIMITIVES_HPP_INCLUDED diff --git a/luabind/luabind/detail/property.hpp b/luabind/luabind/detail/property.hpp new file mode 100644 index 000000000..2c30ce000 --- /dev/null +++ b/luabind/luabind/detail/property.hpp @@ -0,0 +1,33 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_PROPERTY_081020_HPP +# define LUABIND_PROPERTY_081020_HPP + +namespace luabind { namespace detail { + +template +struct access_member_ptr +{ + access_member_ptr(T Class::* mem_ptr) + : mem_ptr(mem_ptr) + {} + + Result operator()(Class const& x) const + { + return const_cast(x).*mem_ptr; + } + + void operator()(Class& x, T const& value) const + { + x.*mem_ptr = value; + } + + T Class::* mem_ptr; +}; + +}} // namespace luabind::detail + +#endif // LUABIND_PROPERTY_081020_HPP + diff --git a/luabind/luabind/detail/ref.hpp b/luabind/luabind/detail/ref.hpp new file mode 100644 index 000000000..3edbfebfb --- /dev/null +++ b/luabind/luabind/detail/ref.hpp @@ -0,0 +1,112 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_REF_HPP_INCLUDED +#define LUABIND_REF_HPP_INCLUDED + +#include +#include + +#include +#include + +namespace luabind +{ + +namespace detail +{ + + struct lua_reference + { + lua_reference(lua_State* L_ = 0) + : L(L_) + , m_ref(LUA_NOREF) + {} + lua_reference(lua_reference const& r) + : L(r.L) + , m_ref(LUA_NOREF) + { + if (!r.is_valid()) return; + r.get(L); + set(L); + } + ~lua_reference() { reset(); } + + lua_State* state() const { return L; } + + void operator=(lua_reference const& r) + { + // TODO: self assignment problems + reset(); + if (!r.is_valid()) return; + r.get(r.state()); + set(r.state()); + } + + bool is_valid() const + { return m_ref != LUA_NOREF; } + + void set(lua_State* L_) + { + reset(); + L = L_; + m_ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + void replace(lua_State* L_) + { + lua_rawseti(L_, LUA_REGISTRYINDEX, m_ref); + } + + // L may not be the same pointer as + // was used when creating this reference + // since it may be a thread that shares + // the same globals table. + void get(lua_State* L_) const + { + assert(m_ref != LUA_NOREF); + assert(L_); + lua_rawgeti(L_, LUA_REGISTRYINDEX, m_ref); + } + + void reset() + { + if (L && m_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, m_ref); + m_ref = LUA_NOREF; + } + + void swap(lua_reference& r) + { + assert(r.L == L); + std::swap(r.m_ref, m_ref); + } + + private: + lua_State* L; + int m_ref; + }; + +}} + +#endif // LUABIND_REF_HPP_INCLUDED + diff --git a/luabind/luabind/detail/signature_match.hpp b/luabind/luabind/detail/signature_match.hpp new file mode 100644 index 000000000..d76ed6627 --- /dev/null +++ b/luabind/luabind/detail/signature_match.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_SIGNATURE_MATCH_HPP_INCLUDED +#define LUABIND_SIGNATURE_MATCH_HPP_INCLUDED + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace luabind +{ + + namespace adl + { + class argument; + } + + template + struct constructor + { + typedef BOOST_PP_CAT( + boost::mpl::vector, BOOST_PP_INC(BOOST_PP_INC(LUABIND_MAX_ARITY)))< + void, argument const&, BOOST_PP_ENUM_PARAMS(LUABIND_MAX_ARITY, A) + > signature0; + + typedef typename boost::mpl::remove< + signature0, detail::null_type>::type signature; + }; + +} + +#endif // LUABIND_SIGNATURE_MATCH_HPP_INCLUDED + diff --git a/luabind/luabind/detail/stack_utils.hpp b/luabind/luabind/detail/stack_utils.hpp new file mode 100644 index 000000000..15f3a7fce --- /dev/null +++ b/luabind/luabind/detail/stack_utils.hpp @@ -0,0 +1,52 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_STACK_UTILS_HPP_INCLUDED +#define LUABIND_STACK_UTILS_HPP_INCLUDED + +#include + +namespace luabind { namespace detail +{ + + struct stack_pop + { + stack_pop(lua_State* L, int n) + : m_state(L) + , m_n(n) + { + } + + ~stack_pop() + { + lua_pop(m_state, m_n); + } + + private: + + lua_State* m_state; + int m_n; + }; +}} + +#endif // LUABIND_STACK_UTILS_HPP_INCLUDED + diff --git a/luabind/luabind/detail/typetraits.hpp b/luabind/luabind/detail/typetraits.hpp new file mode 100644 index 000000000..f27934e98 --- /dev/null +++ b/luabind/luabind/detail/typetraits.hpp @@ -0,0 +1,190 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_TYPETRAITS_HPP_INCLUDED +#define LUABIND_TYPETRAITS_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace luabind { namespace detail +{ + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct is_const_type + { + typedef typename boost::mpl::if_ + , yes_t + , no_t + >::type type; + }; + + template + struct is_const_reference_helper + { + template + struct apply + { + enum + { + value = false + }; + }; + }; + + template + typename is_const_type::type is_const_reference_tester(T&); + no_t is_const_reference_tester(...); + + template<> + struct is_const_reference_helper + { + template + struct apply + { + static T getT(); + + enum + { + value = sizeof(is_const_reference_tester(getT())) == sizeof(yes_t) + }; + }; + }; + + template + struct is_const_reference + : is_const_reference_helper::value>::template apply + { + typedef boost::mpl::bool_ type; + }; + +#else + + template + struct is_const_reference + { + enum { value = false }; + typedef boost::mpl::bool_ type; + }; + + template + struct is_const_reference + { + enum { value = true }; + typedef boost::mpl::bool_ type; + }; + +#endif + + + template + struct is_nonconst_reference + { + enum + { + value = boost::is_reference::value && !is_const_reference::value + }; + typedef boost::mpl::bool_ type; + }; + + template + yes_t is_const_pointer_helper(void(*)(const A*)); + no_t is_const_pointer_helper(...); + + template + struct is_const_pointer + { + enum { value = sizeof(is_const_pointer_helper((void(*)(T))0)) == sizeof(yes_t) }; + typedef boost::mpl::bool_ type; + }; + + template + yes_t is_nonconst_pointer_helper(void(*)(A*)); + no_t is_nonconst_pointer_helper(...); + + template + struct is_nonconst_pointer + { + enum { value = sizeof(is_nonconst_pointer_helper((void(*)(T))0)) == sizeof(yes_t) && !is_const_pointer::value }; + typedef boost::mpl::bool_ type; + }; +/* + template + struct is_constructable_from_helper + { + static yes_t check(const T&); + static no_t check(...); + }; + + template + struct is_constructable_from + { + static From getFrom(); + + enum + { + value = sizeof(is_constructable_from_helper::check(getFrom())) == sizeof(yes_t) + }; + }; + + template + struct is_const_member_function_helper + { + static no_t test(...); + template + static yes_t test(R(T::*)() const); + template + static yes_t test(R(T::*)(A1) const); + template + static yes_t test(R(T::*)(A1,A2) const); + template + static yes_t test(R(T::*)(A1,A2,A3) const); + }; + + template + struct is_const_member_function + { + static U getU(); + + enum + { + value = sizeof(is_const_member_function_helper::test(getU())) == sizeof(yes_t) + }; + }; +*/ + + template + struct max_c + { + enum { value = (v1>v2)?v1:v2 }; + }; + +}} + +#endif // LUABIND_TYPETRAITS_HPP_INCLUDED + diff --git a/luabind/luabind/detail/yes_no.hpp b/luabind/luabind/detail/yes_no.hpp new file mode 100644 index 000000000..931847c60 --- /dev/null +++ b/luabind/luabind/detail/yes_no.hpp @@ -0,0 +1,34 @@ +// Copyright (c) 2004 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef YES_NO_040211_HPP +#define YES_NO_040211_HPP + +namespace luabind { namespace detail { + + typedef char(&yes_t)[1]; + typedef char(&no_t)[2]; + +}} // namespace luabind::detail + +#endif // YES_NO_040211_HPP + diff --git a/luabind/luabind/discard_result_policy.hpp b/luabind/luabind/discard_result_policy.hpp new file mode 100644 index 000000000..149a7b1bc --- /dev/null +++ b/luabind/luabind/discard_result_policy.hpp @@ -0,0 +1,72 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_DISCARD_RESULT_POLICY_HPP_INCLUDED +#define LUABIND_DISCARD_RESULT_POLICY_HPP_INCLUDED + +#include +#include + +namespace luabind { namespace detail +{ + struct discard_converter + { + template + void apply(lua_State*, T) {} + }; + + struct discard_result_policy : conversion_policy<0> + { + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + + struct can_only_convert_from_cpp_to_lua {}; + + template + struct apply + { + typedef typename boost::mpl::if_ + , discard_converter + , can_only_convert_from_cpp_to_lua + >::type type; + }; + }; + +}} + +namespace luabind +{ + detail::policy_cons< + detail::discard_result_policy, detail::null_type> const discard_result = {}; + + namespace detail + { + inline void ignore_unused_discard_result() + { + (void)discard_result; + } + } +} + +#endif // LUABIND_DISCARD_RESULT_POLICY_HPP_INCLUDED + diff --git a/luabind/luabind/error.hpp b/luabind/luabind/error.hpp new file mode 100644 index 000000000..b282a411a --- /dev/null +++ b/luabind/luabind/error.hpp @@ -0,0 +1,93 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_ERROR_HPP_INCLUDED +#define LUABIND_ERROR_HPP_INCLUDED + +#include +#include +#include +#include + +struct lua_State; + +namespace luabind +{ + +#ifndef LUABIND_NO_EXCEPTIONS + + // this exception usually means that the lua function you called + // from C++ failed with an error code. You will have to + // read the error code from the top of the lua stack + // the reason why this exception class doesn't contain + // the message itself is that std::string's copy constructor + // may throw, if the copy constructor of an exception that is + // being thrown throws another exception, terminate will be called + // and the entire application is killed. + class LUABIND_API error : public std::exception + { + public: + explicit error(lua_State* L): m_L(L) {} + lua_State* state() const throw() { return m_L; } + virtual const char* what() const throw() + { + return "lua runtime error"; + } + private: + lua_State* m_L; + }; + + // if an object_cast<>() fails, this is thrown + // it is also thrown if the return value of + // a lua function cannot be converted + class LUABIND_API cast_failed : public std::exception + { + public: + cast_failed(lua_State* L, type_id const& i): m_L(L), m_info(i) {} + lua_State* state() const throw() { return m_L; } + type_id info() const throw() { return m_info; } + virtual const char* what() const throw() { return "unable to make cast"; } + private: + lua_State* m_L; + type_id m_info; + }; + +#else + + typedef void(*error_callback_fun)(lua_State*); + typedef void(*cast_failed_callback_fun)(lua_State*, type_id const&); + + LUABIND_API void set_error_callback(error_callback_fun e); + LUABIND_API void set_cast_failed_callback(cast_failed_callback_fun c); + LUABIND_API error_callback_fun get_error_callback(); + LUABIND_API cast_failed_callback_fun get_cast_failed_callback(); + +#endif + + typedef int(*pcall_callback_fun)(lua_State*); + LUABIND_API void set_pcall_callback(pcall_callback_fun e); + LUABIND_API pcall_callback_fun get_pcall_callback(); + +} + +#endif // LUABIND_ERROR_HPP_INCLUDED + diff --git a/luabind/luabind/exception_handler.hpp b/luabind/luabind/exception_handler.hpp new file mode 100644 index 000000000..0048563af --- /dev/null +++ b/luabind/luabind/exception_handler.hpp @@ -0,0 +1,110 @@ +// Copyright Daniel Wallin 2005. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_EXCEPTION_HANDLER_050601_HPP +# define LUABIND_EXCEPTION_HANDLER_050601_HPP + +# include +# include +# include +# include + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# include +# include +# endif + +namespace luabind { + +# ifndef LUABIND_NO_EXCEPTIONS + +namespace detail +{ + + struct LUABIND_API exception_handler_base + { + exception_handler_base() + : next(0) + {} + + virtual ~exception_handler_base() {} + virtual void handle(lua_State*) const = 0; + + void try_next(lua_State*) const; + + exception_handler_base* next; + }; + + namespace mpl = boost::mpl; + + template + struct exception_handler : exception_handler_base + { +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename mpl::if_< + boost::is_pointer, E, E const& + >::type argument; +# else + typedef E const& argument; +# endif + + exception_handler(Handler handler) + : handler(handler) + {} + + void handle(lua_State* L) const + { + try + { + try_next(L); + } + catch (argument e) + { + handler(L, e); + } + } + + Handler handler; + }; + + LUABIND_API void handle_exception_aux(lua_State* L); + LUABIND_API void register_exception_handler(exception_handler_base*); + +} // namespace detail + +# endif + +template +void register_exception_handler(Handler handler, boost::type* = 0) +{ +# ifndef LUABIND_NO_EXCEPTIONS + detail::register_exception_handler( + new detail::exception_handler(handler) + ); +# endif +} + +template +boost::optional handle_exceptions(lua_State* L, F fn, boost::type* = 0) +{ +# ifndef LUABIND_NO_EXCEPTIONS + try + { + return fn(); + } + catch (...) + { + detail::handle_exception_aux(L); + } + + return boost::optional(); +# else + return fn(); +# endif +} + +} // namespace luabind + +#endif // LUABIND_EXCEPTION_HANDLER_050601_HPP + diff --git a/luabind/luabind/from_stack.hpp b/luabind/luabind/from_stack.hpp new file mode 100644 index 000000000..56bc268d8 --- /dev/null +++ b/luabind/luabind/from_stack.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2005 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_FROM_STACK_050715_HPP +#define LUABIND_FROM_STACK_050715_HPP + +namespace luabind { + +struct from_stack +{ + from_stack(lua_State* interpreter, int index) + : interpreter(interpreter) + , index(index) + {} + + lua_State* interpreter; + int index; +}; + +} // namespace luabind + +#endif // LUABIND_FROM_STACK_050715_HPP + diff --git a/luabind/luabind/function.hpp b/luabind/luabind/function.hpp new file mode 100644 index 000000000..e156fbfcb --- /dev/null +++ b/luabind/luabind/function.hpp @@ -0,0 +1,62 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_FUNCTION2_081014_HPP +# define LUABIND_FUNCTION2_081014_HPP + +# include +# include +# include + +namespace luabind { + +namespace detail +{ + + template + struct function_registration : registration + { + function_registration(char const* name, F f, Policies const& policies) + : name(name) + , f(f) + , policies(policies) + {} + + void register_(lua_State* L) const + { + object fn = make_function(L, f, deduce_signature(f), policies); + + add_overload( + object(from_stack(L, -1)) + , name + , fn + ); + } + + char const* name; + F f; + Policies policies; + }; + + LUABIND_API bool is_luabind_function(lua_State* L, int index); + +} // namespace detail + +template +scope def(char const* name, F f, Policies const& policies) +{ + return scope(std::auto_ptr( + new detail::function_registration(name, f, policies))); +} + +template +scope def(char const* name, F f) +{ + return def(name, f, detail::null_type()); +} + +} // namespace luabind + +#endif // LUABIND_FUNCTION2_081014_HPP + diff --git a/luabind/luabind/get_main_thread.hpp b/luabind/luabind/get_main_thread.hpp new file mode 100644 index 000000000..f94d6e4bc --- /dev/null +++ b/luabind/luabind/get_main_thread.hpp @@ -0,0 +1,16 @@ +// Copyright Daniel Wallin 2009. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_GET_MAIN_THREAD_090321_HPP +# define LUABIND_GET_MAIN_THREAD_090321_HPP + +# include + +namespace luabind { + +LUABIND_API lua_State* get_main_thread(lua_State* L); + +} // namespace luabind + +#endif // LUABIND_GET_MAIN_THREAD_090321_HPP diff --git a/luabind/luabind/get_pointer.hpp b/luabind/luabind/get_pointer.hpp new file mode 100644 index 000000000..b9aae48a7 --- /dev/null +++ b/luabind/luabind/get_pointer.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2005 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_GET_POINTER_051023_HPP +# define LUABIND_GET_POINTER_051023_HPP + +// +// We need these overloads in the luabind namespace. +// + +# include + +namespace luabind { + +using boost::get_pointer; + +} // namespace luabind + +#endif // LUABIND_GET_POINTER_051023_HPP + diff --git a/luabind/luabind/handle.hpp b/luabind/luabind/handle.hpp new file mode 100644 index 000000000..14adacbae --- /dev/null +++ b/luabind/luabind/handle.hpp @@ -0,0 +1,144 @@ +// Copyright (c) 2005 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_HANDLE_050420_HPP +#define LUABIND_HANDLE_050420_HPP + +#include +#include + +namespace luabind { + +// A reference to a Lua value. Represents an entry in the +// registry table. +class handle +{ +public: + handle(); + handle(lua_State* interpreter, int stack_index); + handle(lua_State* main, lua_State* interpreter, int stack_index); + handle(handle const& other); + ~handle(); + + handle& operator=(handle const& other); + void swap(handle& other); + + void push(lua_State* interpreter) const; + + lua_State* interpreter() const; + + void replace(lua_State* interpreter, int stack_index); + +private: + lua_State* m_interpreter; + int m_index; +}; + +inline handle::handle() + : m_interpreter(0) + , m_index(LUA_NOREF) +{} + +inline handle::handle(handle const& other) + : m_interpreter(other.m_interpreter) + , m_index(LUA_NOREF) +{ + if (m_interpreter == 0) return; + lua_rawgeti(m_interpreter, LUA_REGISTRYINDEX, other.m_index); + m_index = luaL_ref(m_interpreter, LUA_REGISTRYINDEX); +} + +inline handle::handle(lua_State* interpreter, int stack_index) + : m_interpreter(interpreter) + , m_index(LUA_NOREF) +{ + lua_pushvalue(interpreter, stack_index); + m_index = luaL_ref(interpreter, LUA_REGISTRYINDEX); +} + +inline handle::handle(lua_State* main, lua_State* interpreter, int stack_index) + : m_interpreter(main) + , m_index(LUA_NOREF) +{ + lua_pushvalue(interpreter, stack_index); + m_index = luaL_ref(interpreter, LUA_REGISTRYINDEX); +} + +inline handle::~handle() +{ + if (m_interpreter && m_index != LUA_NOREF) + luaL_unref(m_interpreter, LUA_REGISTRYINDEX, m_index); +} + +inline handle& handle::operator=(handle const& other) +{ + handle(other).swap(*this); + return *this; +} + +inline void handle::swap(handle& other) +{ + std::swap(m_interpreter, other.m_interpreter); + std::swap(m_index, other.m_index); +} + +inline void handle::push(lua_State* interpreter) const +{ + lua_rawgeti(interpreter, LUA_REGISTRYINDEX, m_index); +} + +inline lua_State* handle::interpreter() const +{ + return m_interpreter; +} + +inline void handle::replace(lua_State* interpreter, int stack_index) +{ + lua_pushvalue(interpreter, stack_index); + lua_rawseti(interpreter, LUA_REGISTRYINDEX, m_index); +} + +template<> +struct value_wrapper_traits +{ + typedef boost::mpl::true_ is_specialized; + + static lua_State* interpreter(handle const& value) + { + return value.interpreter(); + } + + static void unwrap(lua_State* interpreter, handle const& value) + { + value.push(interpreter); + } + + static bool check(...) + { + return true; + } +}; + +} // namespace luabind + +#endif // LUABIND_HANDLE_050420_HPP + diff --git a/luabind/luabind/iterator_policy.hpp b/luabind/luabind/iterator_policy.hpp new file mode 100644 index 000000000..b1f827fe3 --- /dev/null +++ b/luabind/luabind/iterator_policy.hpp @@ -0,0 +1,112 @@ +// Copyright Daniel Wallin 2007. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_ITERATOR_POLICY__071111_HPP +# define LUABIND_ITERATOR_POLICY__071111_HPP + +# include +# include +# include + +namespace luabind { namespace detail { + +template +struct iterator +{ + static int next(lua_State* L) + { + iterator* self = static_cast( + lua_touserdata(L, lua_upvalueindex(1))); + + if (self->first != self->last) + { + convert_to_lua(L, *self->first); + ++self->first; + } + else + { + lua_pushnil(L); + } + + return 1; + } + + static int destroy(lua_State* L) + { + iterator* self = static_cast(lua_touserdata(L, 1)); + self->~iterator(); + return 0; + } + + iterator(Iterator first, Iterator last) + : first(first) + , last(last) + {} + + Iterator first; + Iterator last; +}; + +template +int make_range(lua_State* L, Iterator first, Iterator last) +{ + void* storage = lua_newuserdata(L, sizeof(iterator)); + lua_newtable(L); + lua_pushcclosure(L, iterator::destroy, 0); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + lua_pushcclosure(L, iterator::next, 1); + new (storage) iterator(first, last); + return 1; +} + +template +int make_range(lua_State* L, Container& container) +{ + return make_range(L, container.begin(), container.end()); +} + +struct iterator_converter +{ + typedef iterator_converter type; + + template + void apply(lua_State* L, Container& container) + { + make_range(L, container); + } + + template + void apply(lua_State* L, Container const& container) + { + make_range(L, container); + } +}; + +struct iterator_policy : conversion_policy<0> +{ + static void precall(lua_State*, index_map const&) + {} + + static void postcall(lua_State*, index_map const&) + {} + + template + struct apply + { + typedef iterator_converter type; + }; +}; + +}} // namespace luabind::detail + +namespace luabind { namespace { + +LUABIND_ANONYMOUS_FIX detail::policy_cons< + detail::iterator_policy, detail::null_type> return_stl_iterator; + +}} // namespace luabind::unnamed + +#endif // LUABIND_ITERATOR_POLICY__071111_HPP + diff --git a/luabind/luabind/lua_include.hpp b/luabind/luabind/lua_include.hpp new file mode 100644 index 000000000..7327b533e --- /dev/null +++ b/luabind/luabind/lua_include.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUA_INCLUDE_HPP_INCLUDED +#define LUA_INCLUDE_HPP_INCLUDED + +#ifndef LUABIND_CPLUSPLUS_LUA +extern "C" +{ +#endif + + #include "lua.h" + #include "lauxlib.h" + +#ifndef LUABIND_CPLUSPLUS_LUA +} +#endif + +#endif + diff --git a/luabind/luabind/luabind.hpp b/luabind/luabind/luabind.hpp new file mode 100644 index 000000000..82298484c --- /dev/null +++ b/luabind/luabind/luabind.hpp @@ -0,0 +1,32 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_BIND_HPP_INCLUDED +#define LUABIND_BIND_HPP_INCLUDED + +#include +#include +#include +#include + +#endif // LUABIND_BIND_HPP_INCLUDED diff --git a/luabind/luabind/make_function.hpp b/luabind/luabind/make_function.hpp new file mode 100644 index 000000000..a1ac8716b --- /dev/null +++ b/luabind/luabind/make_function.hpp @@ -0,0 +1,123 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_MAKE_FUNCTION_081014_HPP +# define LUABIND_MAKE_FUNCTION_081014_HPP + +# include +# include +# include +# include +# include +# include + +namespace luabind { + +namespace detail +{ +# ifndef LUABIND_NO_EXCEPTIONS + LUABIND_API void handle_exception_aux(lua_State* L); +# endif + +// MSVC complains about member being sensitive to alignment (C4121) +// when F is a pointer to member of a class with virtual bases. +# ifdef BOOST_MSVC +# pragma pack(push) +# pragma pack(16) +# endif + + template + struct function_object_impl : function_object + { + function_object_impl(F f, Policies const& policies) + : function_object(&entry_point) + , f(f) + , policies(policies) + {} + + int call(lua_State* L, invoke_context& ctx) const + { + return invoke(L, *this, ctx, f, Signature(), policies); + } + + void format_signature(lua_State* L, char const* function) const + { + detail::format_signature(L, function, Signature()); + } + + static int entry_point(lua_State* L) + { + function_object_impl const* impl = + *(function_object_impl const**)lua_touserdata(L, lua_upvalueindex(1)); + + invoke_context ctx; + + int results = 0; + +# ifndef LUABIND_NO_EXCEPTIONS + bool exception_caught = false; + + try + { + results = invoke( + L, *impl, ctx, impl->f, Signature(), impl->policies); + } + catch (...) + { + exception_caught = true; + handle_exception_aux(L); + } + + if (exception_caught) + lua_error(L); +# else + results = invoke(L, *impl, ctx, impl->f, Signature(), impl->policies); +# endif + + if (!ctx) + { + ctx.format_error(L, impl); + lua_error(L); + } + + return results; + } + + F f; + Policies policies; + }; + +# ifdef BOOST_MSVC +# pragma pack(pop) +# endif + + LUABIND_API object make_function_aux( + lua_State* L, function_object* impl + ); + + LUABIND_API void add_overload(object const&, char const*, object const&); + +} // namespace detail + +template +object make_function(lua_State* L, F f, Signature, Policies) +{ + return detail::make_function_aux( + L + , new detail::function_object_impl( + f, Policies() + ) + ); +} + +template +object make_function(lua_State* L, F f) +{ + return make_function(L, detail::deduce_signature(f), detail::null_type()); +} + +} // namespace luabind + +#endif // LUABIND_MAKE_FUNCTION_081014_HPP + diff --git a/luabind/luabind/nil.hpp b/luabind/luabind/nil.hpp new file mode 100644 index 000000000..5f9ba4db1 --- /dev/null +++ b/luabind/luabind/nil.hpp @@ -0,0 +1,40 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_NIL_HPP +#define LUABIND_NIL_HPP + +#include + +namespace luabind +{ + namespace detail + { + struct nil_type {}; + } + + // defined in class.cpp + extern LUABIND_API detail::nil_type nil; +} + +#endif + diff --git a/luabind/luabind/object.hpp b/luabind/luabind/object.hpp new file mode 100644 index 000000000..f7b7ca50d --- /dev/null +++ b/luabind/luabind/object.hpp @@ -0,0 +1,1410 @@ +// Copyright (c) 2005 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_OBJECT_050419_HPP +#define LUABIND_OBJECT_050419_HPP + +#include // detail::push() +#include // detail::push() +#include // value_wrapper_traits specializations +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include // REFACTOR +#include + +#include // iterator + +#include +#include + +namespace luabind { + +namespace detail +{ + namespace mpl = boost::mpl; + + template + void push_aux(lua_State* interpreter, T& value, ConverterGenerator*) + { + typedef typename boost::mpl::if_< + boost::is_reference_wrapper + , BOOST_DEDUCED_TYPENAME boost::unwrap_reference::type& + , T + >::type unwrapped_type; + + typename mpl::apply_wrap2< + ConverterGenerator,unwrapped_type,cpp_to_lua + >::type cv; + + cv.apply( + interpreter + , boost::implicit_cast< + BOOST_DEDUCED_TYPENAME boost::unwrap_reference::type& + >(value) + ); + } + + template + void push(lua_State* interpreter, T& value, Policies const&) + { + typedef typename find_conversion_policy< + 0 + , Policies + >::type converter_policy; + + push_aux(interpreter, value, (converter_policy*)0); + } + + template + void push(lua_State* interpreter, T& value) + { + push(interpreter, value, null_type()); + } + +} // namespace detail + +namespace adl +{ + namespace mpl = boost::mpl; + + template + class object_interface; + + namespace is_object_interface_aux + { + typedef char (&yes)[1]; + typedef char (&no)[2]; + + template + yes check(object_interface*); + no check(void*); + + template + struct impl + { + BOOST_STATIC_CONSTANT(bool, value = + sizeof(is_object_interface_aux::check((T*)0)) == sizeof(yes) + ); + + typedef mpl::bool_ type; + }; + + } // namespace detail + + template + struct is_object_interface + : is_object_interface_aux::impl::type + {}; + + template + struct enable_binary +# ifndef BOOST_NO_SFINAE + : boost::enable_if< + mpl::or_< + is_object_interface + , is_object_interface + > + , R + > + {}; +# else + { + typedef R type; + }; +# endif + + template + int binary_interpreter(lua_State*& L, T const& lhs, U const& rhs + , boost::mpl::true_, boost::mpl::true_) + { + L = value_wrapper_traits::interpreter(lhs); + lua_State* L2 = value_wrapper_traits::interpreter(rhs); + + // you are comparing objects with different interpreters + // that's not allowed. + assert(L == L2 || L == 0 || L2 == 0); + + // if the two objects we compare have different interpreters + // then they + + if (L != L2) return -1; + if (L == 0) return 1; + return 0; + } + + template + int binary_interpreter(lua_State*& L, T const& x, U const& + , boost::mpl::true_, boost::mpl::false_) + { + L = value_wrapper_traits::interpreter(x); + return 0; + } + + template + int binary_interpreter(lua_State*& L, T const&, U const& x, boost::mpl::false_, boost::mpl::true_) + { + L = value_wrapper_traits::interpreter(x); + return 0; + } + + template + int binary_interpreter(lua_State*& L, T const& x, U const& y) + { + return binary_interpreter( + L + , x + , y + , is_value_wrapper() + , is_value_wrapper() + ); + } + +#define LUABIND_BINARY_OP_DEF(op, fn) \ + template \ + typename enable_binary::type \ + operator op(LHS const& lhs, RHS const& rhs) \ + { \ + lua_State* L = 0; \ + switch (binary_interpreter(L, lhs, rhs)) \ + { \ + case 1: \ + return true; \ + case -1: \ + return false; \ + } \ +\ + assert(L); \ +\ + detail::stack_pop pop1(L, 1); \ + detail::push(L, lhs); \ + detail::stack_pop pop2(L, 1); \ + detail::push(L, rhs); \ +\ + return fn(L, -1, -2) != 0; \ + } + +LUABIND_BINARY_OP_DEF(==, lua_equal) +LUABIND_BINARY_OP_DEF(<, lua_lessthan) + + template + std::ostream& operator<<(std::ostream& os + , object_interface const& v) + { + using namespace luabind; + lua_State* interpreter = value_wrapper_traits::interpreter( + static_cast(v)); + detail::stack_pop pop(interpreter, 1); + value_wrapper_traits::unwrap(interpreter + , static_cast(v)); + char const* p = lua_tostring(interpreter, -1); + std::size_t len = lua_strlen(interpreter, -1); + std::copy(p, p + len, std::ostream_iterator(os)); + return os; + } + +#undef LUABIND_BINARY_OP_DEF + + template + typename enable_binary::type + operator>(LHS const& lhs, RHS const& rhs) + { + return !(lhs < rhs || lhs == rhs); + } + + template + typename enable_binary::type + operator<=(LHS const& lhs, RHS const& rhs) + { + return lhs < rhs || lhs == rhs; + } + + template + typename enable_binary::type + operator>=(LHS const& lhs, RHS const& rhs) + { + return !(lhs < rhs); + } + + template + typename enable_binary::type + operator!=(LHS const& lhs, RHS const& rhs) + { + return !(lhs == rhs); + } + + template + struct call_proxy; + + template + class index_proxy; + + class object; + + template + class object_interface + { + struct safe_bool_type {}; + public: + ~object_interface() {} + + call_proxy > operator()(); + + template + call_proxy< + Derived + , boost::tuples::tuple + > operator()(A0 const& a0) + { + typedef boost::tuples::tuple arguments; + + return call_proxy( + derived() + , arguments(&a0) + ); + } + + template + call_proxy< + Derived + , boost::tuples::tuple + > operator()(A0 const& a0, A1 const& a1) + { + typedef boost::tuples::tuple arguments; + + return call_proxy( + derived() + , arguments(&a0, &a1) + ); + } + + // The rest of the overloads are PP-generated. + #define BOOST_PP_ITERATION_PARAMS_1 (3, \ + (3, LUABIND_MAX_ARITY, )) + #include BOOST_PP_ITERATE() + + operator safe_bool_type*() const + { + lua_State* L = value_wrapper_traits::interpreter(derived()); + + if (!L) + return 0; + + value_wrapper_traits::unwrap(L, derived()); + detail::stack_pop pop(L, 1); + + return lua_toboolean(L, -1) == 1 ? (safe_bool_type*)1 : 0; + } + + private: + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } + }; + +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG + struct iterator_proxy_tag; +#endif + + template + class iterator_proxy + : public object_interface > + { + public: +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG + typedef iterator_proxy_tag value_wrapper_tag; +#endif + + iterator_proxy(lua_State* interpreter, handle const& table, handle const& key) + : m_interpreter(interpreter) + , m_table_index(lua_gettop(interpreter) + 1) + , m_key_index(m_table_index + 1) + { + table.push(m_interpreter); + key.push(m_interpreter); + } + + iterator_proxy(iterator_proxy const& other) + : m_interpreter(other.m_interpreter) + , m_table_index(other.m_table_index) + , m_key_index(other.m_key_index) + { + other.m_interpreter = 0; + } + + ~iterator_proxy() + { + if (m_interpreter) + lua_pop(m_interpreter, 2); + } + + // this will set the value to nil + iterator_proxy & operator=(luabind::detail::nil_type) + { + lua_pushvalue(m_interpreter, m_key_index); + lua_pushnil(m_interpreter); + AccessPolicy::set(m_interpreter, m_table_index); + return *this; + } + + template + iterator_proxy& operator=(T const& value) + { + lua_pushvalue(m_interpreter, m_key_index); + detail::push(m_interpreter, value); + AccessPolicy::set(m_interpreter, m_table_index); + return *this; + } + + template + index_proxy > operator[](Key const& key) + { + return index_proxy >( + *this, m_interpreter, key + ); + } + + // This is non-const to prevent conversion on lvalues. + operator object(); + + lua_State* interpreter() const + { + return m_interpreter; + } + + // TODO: Why is it non-const? + void push(lua_State* interpreter) + { + assert(interpreter == m_interpreter); + lua_pushvalue(m_interpreter, m_key_index); + AccessPolicy::get(m_interpreter, m_table_index); + } + + private: + mutable lua_State* m_interpreter; + int m_table_index; + int m_key_index; + }; + +} // namespace adl + +namespace detail +{ + struct basic_access + { + static void set(lua_State* interpreter, int table) + { + lua_settable(interpreter, table); + } + + static void get(lua_State* interpreter, int table) + { + lua_gettable(interpreter, table); + } + }; + + struct raw_access + { + static void set(lua_State* interpreter, int table) + { + lua_rawset(interpreter, table); + } + + static void get(lua_State* interpreter, int table) + { + lua_rawget(interpreter, table); + } + }; + + template + class basic_iterator + : public boost::iterator_facade< + basic_iterator + , adl::iterator_proxy + , boost::single_pass_traversal_tag + , adl::iterator_proxy + > + { + public: + basic_iterator() + : m_interpreter(0) + {} + + template + explicit basic_iterator(ValueWrapper const& value_wrapper) + : m_interpreter( + value_wrapper_traits::interpreter(value_wrapper) + ) + { + detail::stack_pop pop(m_interpreter, 1); + value_wrapper_traits::unwrap(m_interpreter, value_wrapper); + + lua_pushnil(m_interpreter); + if (lua_next(m_interpreter, -2) != 0) + { + detail::stack_pop pop(m_interpreter, 2); + handle(m_interpreter, -2).swap(m_key); + } + else + { + m_interpreter = 0; + return; + } + + handle(m_interpreter, -1).swap(m_table); + } + + adl::object key() const; + + private: + friend class boost::iterator_core_access; + + void increment() + { + m_table.push(m_interpreter); + m_key.push(m_interpreter); + + detail::stack_pop pop(m_interpreter, 1); + + if (lua_next(m_interpreter, -2) != 0) + { + m_key.replace(m_interpreter, -2); + lua_pop(m_interpreter, 2); + } + else + { + m_interpreter = 0; + handle().swap(m_table); + handle().swap(m_key); + } + } + + bool equal(basic_iterator const& other) const + { + if (m_interpreter == 0 && other.m_interpreter == 0) + return true; + + if (m_interpreter != other.m_interpreter) + return false; + + detail::stack_pop pop(m_interpreter, 2); + m_key.push(m_interpreter); + other.m_key.push(m_interpreter); + return lua_equal(m_interpreter, -2, -1) != 0; + } + + adl::iterator_proxy dereference() const + { + return adl::iterator_proxy(m_interpreter, m_table, m_key); + } + + lua_State* m_interpreter; + handle m_table; + handle m_key; + }; + +// Needed because of some strange ADL issues. + +#define LUABIND_OPERATOR_ADL_WKND(op) \ + inline bool operator op( \ + basic_iterator const& x \ + , basic_iterator const& y) \ + { \ + return boost::operator op(x, y); \ + } \ + \ + inline bool operator op( \ + basic_iterator const& x \ + , basic_iterator const& y) \ + { \ + return boost::operator op(x, y); \ + } + + LUABIND_OPERATOR_ADL_WKND(==) + LUABIND_OPERATOR_ADL_WKND(!=) + +#undef LUABIND_OPERATOR_ADL_WKND + +} // namespace detail + +namespace adl +{ + +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG + struct index_proxy_tag; +#endif + + template + class index_proxy + : public object_interface > + { + public: +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG + typedef index_proxy_tag value_wrapper_tag; +#endif + + typedef index_proxy this_type; + + template + index_proxy(Next const& next, lua_State* interpreter, Key const& key) + : m_interpreter(interpreter) + , m_key_index(lua_gettop(interpreter) + 1) + , m_next(next) + { + detail::push(m_interpreter, key); + } + + index_proxy(index_proxy const& other) + : m_interpreter(other.m_interpreter) + , m_key_index(other.m_key_index) + , m_next(other.m_next) + { + other.m_interpreter = 0; + } + + ~index_proxy() + { + if (m_interpreter) + lua_pop(m_interpreter, 1); + } + + // This is non-const to prevent conversion on lvalues. + operator object(); + + // this will set the value to nil + this_type& operator=(luabind::detail::nil_type) + { + value_wrapper_traits::unwrap(m_interpreter, m_next); + detail::stack_pop pop(m_interpreter, 1); + + lua_pushvalue(m_interpreter, m_key_index); + lua_pushnil(m_interpreter); + lua_settable(m_interpreter, -3); + return *this; + } + + template + this_type& operator=(T const& value) + { + value_wrapper_traits::unwrap(m_interpreter, m_next); + detail::stack_pop pop(m_interpreter, 1); + + lua_pushvalue(m_interpreter, m_key_index); + detail::push(m_interpreter, value); + lua_settable(m_interpreter, -3); + return *this; + } + + this_type& operator=(this_type const& value) + { + value_wrapper_traits::unwrap(m_interpreter, m_next); + detail::stack_pop pop(m_interpreter, 1); + + lua_pushvalue(m_interpreter, m_key_index); + detail::push(m_interpreter, value); + lua_settable(m_interpreter, -3); + return *this; + } + + template + index_proxy operator[](T const& key) + { + return index_proxy(*this, m_interpreter, key); + } + + void push(lua_State* interpreter); + + lua_State* interpreter() const + { + return m_interpreter; + } + + private: + struct hidden_type {}; + +// this_type& operator=(index_proxy const&); + + mutable lua_State* m_interpreter; + int m_key_index; + + Next const& m_next; + }; + +} // namespace adl + +typedef detail::basic_iterator iterator; +typedef detail::basic_iterator raw_iterator; + +#ifndef LUABIND_USE_VALUE_WRAPPER_TAG +template +struct value_wrapper_traits > +#else +template<> +struct value_wrapper_traits +#endif +{ + typedef boost::mpl::true_ is_specialized; + + template + static lua_State* interpreter(adl::index_proxy const& proxy) + { + return proxy.interpreter(); + } + + template + static void unwrap(lua_State* interpreter, adl::index_proxy const& proxy) + { + const_cast&>(proxy).push(interpreter); + } +}; + +#ifndef LUABIND_USE_VALUE_WRAPPER_TAG +template +struct value_wrapper_traits > +#else +template<> +struct value_wrapper_traits +#endif +{ + typedef boost::mpl::true_ is_specialized; + + template + static lua_State* interpreter(Proxy const& p) + { + return p.interpreter(); + } + + template + static void unwrap(lua_State* interpreter, Proxy const& p) + { + // TODO: Why const_cast? + const_cast(p).push(interpreter); + } +}; + +namespace adl +{ + + // An object holds a reference to a Lua value residing + // in the registry. + class object : public object_interface + { + public: + object() + {} + + explicit object(handle const& other) + : m_handle(other) + {} + + explicit object(from_stack const& stack_reference) + : m_handle(stack_reference.interpreter, stack_reference.index) + { + } + + template + object(lua_State* interpreter, T const& value) + { + detail::push(interpreter, value); + detail::stack_pop pop(interpreter, 1); + handle(interpreter, -1).swap(m_handle); + } + + template + object(lua_State* interpreter, T const& value, Policies const&) + { + detail::push(interpreter, value, Policies()); + detail::stack_pop pop(interpreter, 1); + handle(interpreter, -1).swap(m_handle); + } + + void push(lua_State* interpreter) const; + lua_State* interpreter() const; + bool is_valid() const; + + template + index_proxy operator[](T const& key) const + { + return index_proxy( + *this, m_handle.interpreter(), key + ); + } + + void swap(object& other) + { + m_handle.swap(other.m_handle); + } + + private: + handle m_handle; + }; + + inline void object::push(lua_State* interpreter) const + { + m_handle.push(interpreter); + } + + inline lua_State* object::interpreter() const + { + return m_handle.interpreter(); + } + + inline bool object::is_valid() const + { + return m_handle.interpreter() != 0; + } + + class argument : public object_interface + { + public: + argument(from_stack const& stack_reference) + : m_interpreter(stack_reference.interpreter) + , m_index(stack_reference.index) + { + if (m_index < 0) + m_index = lua_gettop(m_interpreter) - m_index + 1; + } + + template + index_proxy operator[](T const& key) const + { + return index_proxy(*this, m_interpreter, key); + } + + void push(lua_State* L) const + { + lua_pushvalue(L, m_index); + } + + lua_State* interpreter() const + { + return m_interpreter; + } + + private: + lua_State* m_interpreter; + int m_index; + }; + +} // namespace adl + +using adl::object; +using adl::argument; + +#ifndef LUABIND_USE_VALUE_WRAPPER_TAG +template +struct value_wrapper_traits > +#else +template<> +struct value_wrapper_traits +#endif +{ + typedef boost::mpl::true_ is_specialized; + + template + static lua_State* interpreter(adl::call_proxy const& proxy) + { + return value_wrapper_traits::interpreter(*proxy.value_wrapper); + } + + template + static void unwrap(lua_State*, adl::call_proxy const& proxy) + { + object result = const_cast&>(proxy); + result.push(result.interpreter()); + } +}; + +template<> +struct value_wrapper_traits +{ + typedef boost::mpl::true_ is_specialized; + + static lua_State* interpreter(object const& value) + { + return value.interpreter(); + } + + static void unwrap(lua_State* interpreter, object const& value) + { + value.push(interpreter); + } + + static bool check(...) + { + return true; + } +}; + +template<> +struct value_wrapper_traits +{ + typedef boost::mpl::true_ is_specialized; + + static lua_State* interpreter(argument const& value) + { + return value.interpreter(); + } + + static void unwrap(lua_State* interpreter, argument const& value) + { + value.push(interpreter); + } + + static bool check(...) + { + return true; + } +}; + +template +inline void adl::index_proxy::push(lua_State* interpreter) +{ + assert(interpreter == m_interpreter); + + value_wrapper_traits::unwrap(m_interpreter, m_next); + + lua_pushvalue(m_interpreter, m_key_index); + lua_gettable(m_interpreter, -2); + lua_remove(m_interpreter, -2); +} + +template +inline adl::index_proxy::operator object() +{ + detail::stack_pop pop(m_interpreter, 1); + push(m_interpreter); + return object(from_stack(m_interpreter, -1)); +} + +template +adl::iterator_proxy::operator object() +{ + lua_pushvalue(m_interpreter, m_key_index); + AccessPolicy::get(m_interpreter, m_table_index); + detail::stack_pop pop(m_interpreter, 1); + return object(from_stack(m_interpreter, -1)); +} + +template +object detail::basic_iterator::key() const +{ + return object(m_key); +} + +namespace detail +{ + + template< + class T + , class ValueWrapper + , class Policies + , class ErrorPolicy + , class ReturnType + > + ReturnType object_cast_aux( + ValueWrapper const& value_wrapper + , T* + , Policies* + , ErrorPolicy* + , ReturnType* + ) + { + lua_State* interpreter = value_wrapper_traits::interpreter( + value_wrapper + ); + +#ifndef LUABIND_NO_ERROR_CHECKING + if (!interpreter) + return ErrorPolicy::handle_error(interpreter, typeid(void)); +#endif + + value_wrapper_traits::unwrap(interpreter, value_wrapper); + + detail::stack_pop pop(interpreter, 1); + + typedef typename detail::find_conversion_policy< + 0 + , Policies + >::type converter_generator; + + typename mpl::apply_wrap2::type cv; + +#ifndef LUABIND_NO_ERROR_CHECKING + if (cv.match(interpreter, LUABIND_DECORATE_TYPE(T), -1) < 0) + { + return ErrorPolicy::handle_error(interpreter, typeid(T)); + } +#endif + + return cv.apply(interpreter, LUABIND_DECORATE_TYPE(T), -1); + } + +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4702) // unreachable code +# endif + + template + struct throw_error_policy + { + static T handle_error(lua_State* interpreter, type_id const& type_info) + { +#ifndef LUABIND_NO_EXCEPTIONS + throw cast_failed(interpreter, type_info); +#else + cast_failed_callback_fun e = get_cast_failed_callback(); + if (e) e(interpreter, type_info); + + assert(0 && "object_cast failed. If you want to handle this error use " + "luabind::set_error_callback()"); + std::terminate(); +#endif + return *(typename boost::remove_reference::type*)0; + } + }; + +# ifdef BOOST_MSVC +# pragma warning(pop) +# endif + + template + struct nothrow_error_policy + { + static boost::optional handle_error(lua_State*, type_id const&) + { + return boost::optional(); + } + }; + +} // namespace detail + +template +T object_cast(ValueWrapper const& value_wrapper) +{ + return detail::object_cast_aux( + value_wrapper + , (T*)0 + , (detail::null_type*)0 + , (detail::throw_error_policy*)0 + , (T*)0 + ); +} + +template +T object_cast(ValueWrapper const& value_wrapper, Policies const&) +{ + return detail::object_cast_aux( + value_wrapper + , (T*)0 + , (Policies*)0 + , (detail::throw_error_policy*)0 + , (T*)0 + ); +} + +template +boost::optional object_cast_nothrow(ValueWrapper const& value_wrapper) +{ + return detail::object_cast_aux( + value_wrapper + , (T*)0 + , (detail::null_type*)0 + , (detail::nothrow_error_policy*)0 + , (boost::optional*)0 + ); +} + +template +boost::optional object_cast_nothrow(ValueWrapper const& value_wrapper, Policies const&) +{ + return detail::object_cast_aux( + value_wrapper + , (T*)0 + , (Policies*)0 + , (detail::nothrow_error_policy*)0 + , (boost::optional*)0 + ); +} + +namespace detail +{ + + template + struct push_args_from_tuple + { + template + inline static void apply(lua_State* L, const boost::tuples::cons& x, const Policies& p) + { + convert_to_lua_p(L, *x.get_head(), p); + push_args_from_tuple::apply(L, x.get_tail(), p); + } + + template + inline static void apply(lua_State* L, const boost::tuples::cons& x) + { + convert_to_lua(L, *x.get_head()); + push_args_from_tuple::apply(L, x.get_tail()); + } + + template + inline static void apply(lua_State*, const boost::tuples::null_type&, const Policies&) {} + + inline static void apply(lua_State*, const boost::tuples::null_type&) {} + }; + +} // namespace detail + +namespace adl +{ + + template + struct call_proxy + { + call_proxy(ValueWrapper& value_wrapper, Arguments arguments) + : value_wrapper(&value_wrapper) + , arguments(arguments) + {} + + call_proxy(call_proxy const& other) + : value_wrapper(other.value_wrapper) + , arguments(other.arguments) + { + other.value_wrapper = 0; + } + + ~call_proxy() + { + if (value_wrapper) + call((detail::null_type*)0); + } + + operator object() + { + return call((detail::null_type*)0); + } + + template + object operator[](Policies const&) + { + return call((Policies*)0); + } + + template + object call(Policies*) + { + lua_State* interpreter = value_wrapper_traits::interpreter( + *value_wrapper + ); + + value_wrapper_traits::unwrap( + interpreter + , *value_wrapper + ); + + value_wrapper = 0; + + detail::push_args_from_tuple<1>::apply(interpreter, arguments, Policies()); + + if (detail::pcall(interpreter, boost::tuples::length::value, 1)) + { +#ifndef LUABIND_NO_EXCEPTIONS + throw luabind::error(interpreter); +#else + error_callback_fun e = get_error_callback(); + if (e) e(interpreter); + + assert(0 && "the lua function threw an error and exceptions are disabled." + "if you want to handle this error use luabind::set_error_callback()"); + std::terminate(); +#endif + } + + detail::stack_pop pop(interpreter, 1); + return object(from_stack(interpreter, -1)); + } + + mutable ValueWrapper* value_wrapper; + Arguments arguments; + }; + + template + call_proxy > + object_interface::operator()() + { + return call_proxy >( + derived() + , boost::tuples::tuple<>() + ); + } + + // Simple value_wrapper adaptor with the sole purpose of helping with + // overload resolution. Use this as a function parameter type instead + // of "object" or "argument" to restrict the parameter to Lua tables. + template + struct table : Base + { + table(from_stack const& stack_reference) + : Base(stack_reference) + {} + }; + +} // namespace adl + +using adl::table; + +template +struct value_wrapper_traits > + : value_wrapper_traits +{ + static bool check(lua_State* L, int idx) + { + return value_wrapper_traits::check(L, idx) && + lua_istable(L, idx); + } +}; + +inline object newtable(lua_State* interpreter) +{ + lua_newtable(interpreter); + detail::stack_pop pop(interpreter, 1); + return object(from_stack(interpreter, -1)); +} + +// this could be optimized by returning a proxy +inline object globals(lua_State* interpreter) +{ + lua_pushvalue(interpreter, LUA_GLOBALSINDEX); + detail::stack_pop pop(interpreter, 1); + return object(from_stack(interpreter, -1)); +} + +// this could be optimized by returning a proxy +inline object registry(lua_State* interpreter) +{ + lua_pushvalue(interpreter, LUA_REGISTRYINDEX); + detail::stack_pop pop(interpreter, 1); + return object(from_stack(interpreter, -1)); +} + +template +inline object gettable(ValueWrapper const& table, K const& key) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + table + ); + + value_wrapper_traits::unwrap(interpreter, table); + detail::stack_pop pop(interpreter, 2); + detail::push(interpreter, key); + lua_gettable(interpreter, -2); + return object(from_stack(interpreter, -1)); +} + +template +inline void settable(ValueWrapper const& table, K const& key, T const& value) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + table + ); + + // TODO: Exception safe? + + value_wrapper_traits::unwrap(interpreter, table); + detail::stack_pop pop(interpreter, 1); + detail::push(interpreter, key); + detail::push(interpreter, value); + lua_settable(interpreter, -3); +} + +template +inline object rawget(ValueWrapper const& table, K const& key) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + table + ); + + value_wrapper_traits::unwrap(interpreter, table); + detail::stack_pop pop(interpreter, 2); + detail::push(interpreter, key); + lua_rawget(interpreter, -2); + return object(from_stack(interpreter, -1)); +} + +template +inline void rawset(ValueWrapper const& table, K const& key, T const& value) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + table + ); + + // TODO: Exception safe? + + value_wrapper_traits::unwrap(interpreter, table); + detail::stack_pop pop(interpreter, 1); + detail::push(interpreter, key); + detail::push(interpreter, value); + lua_rawset(interpreter, -3); +} + +template +inline int type(ValueWrapper const& value) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + value + ); + + value_wrapper_traits::unwrap(interpreter, value); + detail::stack_pop pop(interpreter, 1); + return lua_type(interpreter, -1); +} + +template +inline object getmetatable(ValueWrapper const& obj) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + obj + ); + + value_wrapper_traits::unwrap(interpreter, obj); + detail::stack_pop pop(interpreter, 2); + lua_getmetatable(interpreter, -1); + return object(from_stack(interpreter, -1)); +} + +template +inline void setmetatable( + ValueWrapper1 const& obj, ValueWrapper2 const& metatable) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + obj + ); + + value_wrapper_traits::unwrap(interpreter, obj); + detail::stack_pop pop(interpreter, 1); + value_wrapper_traits::unwrap(interpreter, metatable); + lua_setmetatable(interpreter, -2); +} + +template +inline lua_CFunction tocfunction(ValueWrapper const& value) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + value + ); + + value_wrapper_traits::unwrap(interpreter, value); + detail::stack_pop pop(interpreter, 1); + return lua_tocfunction(interpreter, -1); +} + +template +inline T* touserdata(ValueWrapper const& value) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + value + ); + + value_wrapper_traits::unwrap(interpreter, value); + detail::stack_pop pop(interpreter, 1); + return static_cast(lua_touserdata(interpreter, -1)); +} + +template +inline object getupvalue(ValueWrapper const& value, int index) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + value + ); + + value_wrapper_traits::unwrap(interpreter, value); + detail::stack_pop pop(interpreter, 2); + lua_getupvalue(interpreter, -1, index); + return object(from_stack(interpreter, -1)); +} + +template +inline void setupvalue( + ValueWrapper1 const& function, int index, ValueWrapper2 const& value) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + function + ); + + value_wrapper_traits::unwrap(interpreter, function); + detail::stack_pop pop(interpreter, 1); + value_wrapper_traits::unwrap(interpreter, value); + lua_setupvalue(interpreter, -2, index); +} + +template +object property(GetValueWrapper const& get) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + get + ); + + value_wrapper_traits::unwrap(interpreter, get); + lua_pushnil(interpreter); + + lua_pushcclosure(interpreter, &detail::property_tag, 2); + detail::stack_pop pop(interpreter, 1); + + return object(from_stack(interpreter, -1)); +} + +template +object property(GetValueWrapper const& get, SetValueWrapper const& set) +{ + lua_State* interpreter = value_wrapper_traits::interpreter( + get + ); + + value_wrapper_traits::unwrap(interpreter, get); + value_wrapper_traits::unwrap(interpreter, set); + + lua_pushcclosure(interpreter, &detail::property_tag, 2); + detail::stack_pop pop(interpreter, 1); + + return object(from_stack(interpreter, -1)); + +} + + +} // namespace luabind + +#endif // LUABIND_OBJECT_050419_HPP + diff --git a/luabind/luabind/open.hpp b/luabind/luabind/open.hpp new file mode 100644 index 000000000..cca4c7a52 --- /dev/null +++ b/luabind/luabind/open.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_OPEN_HPP_INCLUDED +#define LUABIND_OPEN_HPP_INCLUDED + +#include + +namespace luabind { + + LUABIND_API void open(lua_State* L); + +} + +#endif // LUABIND_OPEN_HPP_INCLUDED + diff --git a/luabind/luabind/operator.hpp b/luabind/luabind/operator.hpp new file mode 100644 index 000000000..aeb651c03 --- /dev/null +++ b/luabind/luabind/operator.hpp @@ -0,0 +1,355 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef OPERATOR_040729_HPP +#define OPERATOR_040729_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__GNUC__) && __GNUC__ < 3 +# define LUABIND_NO_STRINGSTREAM +#else +# if defined(BOOST_NO_STRINGSTREAM) +# define LUABIND_NO_STRINGSTREAM +# endif +#endif + +#ifdef LUABIND_NO_STRINGSTREAM +#include +#else +#include +#endif + +namespace luabind { namespace detail { + + template struct unwrap_parameter_type; + template struct operator_ {}; + + struct operator_void_return {}; + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + template + inline T const& operator,(T const& x, operator_void_return) + { + return x; + } +#endif + +}} // namespace luabind + +namespace luabind { namespace operators { + + #define BOOST_PP_ITERATION_PARAMS_1 (3, \ + (0, LUABIND_MAX_ARITY, )) + #include BOOST_PP_ITERATE() + +}} // namespace luabind::operators + +#include + +namespace luabind { + + template + struct self_base + { + operators::call_operator0 operator()() const + { + return 0; + } + +#define BOOST_PP_LOCAL_MACRO(n) \ + template \ + BOOST_PP_CAT(operators::call_operator, n)< \ + Derived \ + BOOST_PP_ENUM_TRAILING_PARAMS(n, A) \ + >\ + operator()( \ + BOOST_PP_ENUM_BINARY_PARAMS(n, A, const& BOOST_PP_INTERCEPT) \ + ) const \ + { \ + return 0; \ + } + +#define BOOST_PP_LOCAL_LIMITS (1, LUABIND_MAX_ARITY) +#include BOOST_PP_LOCAL_ITERATE() + + }; + + struct self_type : self_base + { + }; + + struct const_self_type : self_base + { + }; + +namespace detail { + + template + struct unwrap_parameter_type + { + typedef typename boost::mpl::eval_if< + boost::is_same + , boost::mpl::identity + , boost::mpl::eval_if< + boost::is_same + , boost::mpl::identity + , unwrap_other + > + >::type type; + }; + + template + struct binary_operator + : operator_ > + { + binary_operator(int) {} + + template + struct apply + { + typedef typename unwrap_parameter_type::type arg0; + typedef typename unwrap_parameter_type::type arg1; + + static void execute(lua_State* L, arg0 _0, arg1 _1) + { + Derived::template apply::execute( + L, _0, _1); + } + }; + + static char const* name() + { + return Derived::name(); + } + }; + + template + struct unary_operator + : operator_ > + { + unary_operator(int) {} + + template + struct apply + { + typedef typename unwrap_parameter_type::type arg0; + + static void execute(lua_State* L, arg0 _0) + { + Derived::template apply::execute(L, _0); + } + }; + + static char const* name() + { + return Derived::name(); + } + }; + + template + inline void operator_result(lua_State* L, operator_void_return, Policies*) + { + } + + namespace mpl = boost::mpl; + + template + inline void operator_result(lua_State* L, T const& x, Policies*) + { + typedef typename find_conversion_policy< + 0 + , Policies + >::type cv_policy; + + typename mpl::apply_wrap2::type cv; + + cv.apply(L, x); + } + +}} // namespace detail::luabind + +namespace luabind { + +#define LUABIND_BINARY_OPERATOR(name_, op) \ + namespace operators { \ +\ + struct name_ \ + { \ + template \ + struct apply \ + { \ + static void execute(lua_State* L, T0 _0, T1 _1) \ + { \ + detail::operator_result(L, _0 op _1, (Policies*)0); \ + } \ + }; \ +\ + static char const* name() \ + { \ + return "__" # name_; \ + } \ + }; \ +\ + } \ + \ + template \ + detail::binary_operator< \ + operators::name_ \ + , U \ + , T \ + > \ + inline operator op(self_base, T const&) \ + { \ + return 0; \ + } \ + \ + template \ + detail::binary_operator< \ + operators::name_ \ + , T \ + , U \ + > \ + inline operator op(T const&, self_base) \ + { \ + return 0; \ + } \ + \ + detail::binary_operator< \ + operators::name_ \ + , self_type \ + , self_type \ + > \ + inline operator op(self_type, self_type) \ + { \ + return 0; \ + } \ + \ + detail::binary_operator< \ + operators::name_ \ + , self_type \ + , const_self_type \ + > \ + inline operator op(self_type, const_self_type) \ + { \ + return 0; \ + } \ + \ + detail::binary_operator< \ + operators::name_ \ + , const_self_type \ + , self_type \ + > \ + inline operator op(const_self_type, self_type) \ + { \ + return 0; \ + } \ + \ + detail::binary_operator< \ + operators::name_ \ + , const_self_type \ + , const_self_type \ + > \ + inline operator op(const_self_type, const_self_type) \ + { \ + return 0; \ + } + + LUABIND_BINARY_OPERATOR(add, +) + LUABIND_BINARY_OPERATOR(sub, -) + LUABIND_BINARY_OPERATOR(mul, *) + LUABIND_BINARY_OPERATOR(div, /) + LUABIND_BINARY_OPERATOR(pow, ^) + LUABIND_BINARY_OPERATOR(lt, <) + LUABIND_BINARY_OPERATOR(le, <=) + LUABIND_BINARY_OPERATOR(eq, ==) + +#undef LUABIND_UNARY_OPERATOR + +#define LUABIND_UNARY_OPERATOR(name_, op, fn) \ + namespace operators { \ +\ + struct name_ \ + { \ + template \ + struct apply \ + { \ + static void execute(lua_State* L, T x) \ + { \ + detail::operator_result(L, op(x), (Policies*)0); \ + } \ + }; \ +\ + static char const* name() \ + { \ + return "__" # name_; \ + } \ + }; \ +\ + } \ + \ + template \ + detail::unary_operator< \ + operators::name_ \ + , T \ + > \ + inline fn(self_base) \ + { \ + return 0; \ + } + + template + std::string tostring_operator(T const& x) + { +#ifdef LUABIND_NO_STRINGSTREAM + std::strstream s; + s << x << std::ends; +#else + std::stringstream s; + s << x; +#endif + return s.str(); + } + + LUABIND_UNARY_OPERATOR(tostring, tostring_operator, tostring) + LUABIND_UNARY_OPERATOR(unm, -, operator-) + +#undef LUABIND_BINARY_OPERATOR + + namespace { + + LUABIND_ANONYMOUS_FIX self_type self; + LUABIND_ANONYMOUS_FIX const_self_type const_self; + + } // namespace unnamed + +} // namespace luabind + +#endif // OPERATOR_040729_HPP + diff --git a/luabind/luabind/out_value_policy.hpp b/luabind/luabind/out_value_policy.hpp new file mode 100644 index 000000000..ca496b527 --- /dev/null +++ b/luabind/luabind/out_value_policy.hpp @@ -0,0 +1,280 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED +#define LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED + +#include +#include +#include + +namespace luabind { namespace detail +{ + template + struct char_array + { + char storage[N]; + }; + +#if defined(__GNUC__) && ( __GNUC__ == 3 && __GNUC_MINOR__ == 1 ) + + template + char_array indirect_sizeof_test(by_reference); + + template + char_array indirect_sizeof_test(by_const_reference); + + template + char_array indirect_sizeof_test(by_pointer); + + template + char_array indirect_sizeof_test(by_const_pointer); + + template + char_array indirect_sizeof_test(by_value); + +#else + + template + char_array::type)> indirect_sizeof_test(by_reference); + + template + char_array::type)> indirect_sizeof_test(by_const_reference); + + template + char_array::type)> indirect_sizeof_test(by_pointer); + + template + char_array::type)> indirect_sizeof_test(by_const_pointer); + + template + char_array::type)> indirect_sizeof_test(by_value); + +#endif + + template + struct indirect_sizeof + { + BOOST_STATIC_CONSTANT(int, value = sizeof(indirect_sizeof_test(LUABIND_DECORATE_TYPE(T)))); + }; + + namespace mpl = boost::mpl; + + template + struct out_value_converter + { + int const consumed_args(...) + { + return 1; + } + + template + T& apply(lua_State* L, by_reference, int index) + { + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + new (m_storage) T(converter.apply(L, LUABIND_DECORATE_TYPE(T), index)); + return *reinterpret_cast(m_storage); + } + + template + static int match(lua_State* L, by_reference, int index) + { + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typedef typename mpl::apply_wrap2::type converter; + return converter::match(L, LUABIND_DECORATE_TYPE(T), index); + } + + template + void converter_postcall(lua_State* L, by_reference, int) + { + typedef typename find_conversion_policy<2, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + converter.apply(L, *reinterpret_cast(m_storage)); + reinterpret_cast(m_storage)->~T(); + } + + template + T* apply(lua_State* L, by_pointer, int index) + { + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + new (m_storage) T(converter.apply(L, LUABIND_DECORATE_TYPE(T), index)); + return reinterpret_cast(m_storage); + } + + template + static int match(lua_State* L, by_pointer, int index) + { + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typedef typename mpl::apply_wrap2::type converter; + return converter::match(L, LUABIND_DECORATE_TYPE(T), index); + } + + template + void converter_postcall(lua_State* L, by_pointer, int) + { + typedef typename find_conversion_policy<2, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + converter.apply(L, *reinterpret_cast(m_storage)); + reinterpret_cast(m_storage)->~T(); + } + + char m_storage[Size]; + }; + + template + struct out_value_policy : conversion_policy + { + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + + struct only_accepts_nonconst_references_or_pointers {}; + struct can_only_convert_from_lua_to_cpp {}; + + template + struct apply + { + typedef typename boost::mpl::if_ + , typename boost::mpl::if_, is_nonconst_pointer > + , out_value_converter::value, Policies> + , only_accepts_nonconst_references_or_pointers + >::type + , can_only_convert_from_lua_to_cpp + >::type type; + }; + }; + + template + struct pure_out_value_converter + { + int const consumed_args(...) + { + return 0; + } + + template + T& apply(lua_State*, by_reference, int) + { + new (m_storage) T(); + return *reinterpret_cast(m_storage); + } + + template + static int match(lua_State*, by_reference, int) + { + return 0; + } + + template + void converter_postcall(lua_State* L, by_reference, int) + { + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + converter.apply(L, *reinterpret_cast(m_storage)); + reinterpret_cast(m_storage)->~T(); + } + + template + T* apply(lua_State*, by_pointer, int) + { + new (m_storage) T(); + return reinterpret_cast(m_storage); + } + + template + static int match(lua_State*, by_pointer, int) + { + return 0; + } + + template + void converter_postcall(lua_State* L, by_pointer, int) + { + typedef typename find_conversion_policy<1, Policies>::type converter_policy; + typename mpl::apply_wrap2::type converter; + converter.apply(L, *reinterpret_cast(m_storage)); + reinterpret_cast(m_storage)->~T(); + } + + + char m_storage[Size]; + }; + + template + struct pure_out_value_policy : conversion_policy + { + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + + struct only_accepts_nonconst_references_or_pointers {}; + struct can_only_convert_from_lua_to_cpp {}; + + template + struct apply + { + typedef typename boost::mpl::if_ + , typename boost::mpl::if_, is_nonconst_pointer > + , pure_out_value_converter::value, Policies> + , only_accepts_nonconst_references_or_pointers + >::type + , can_only_convert_from_lua_to_cpp + >::type type; + }; + }; + +}} + +namespace luabind +{ + template + detail::policy_cons, detail::null_type> + out_value(LUABIND_PLACEHOLDER_ARG(N)) + { + return detail::policy_cons, detail::null_type>(); + } + + template + detail::policy_cons, detail::null_type> + out_value(LUABIND_PLACEHOLDER_ARG(N), const Policies&) + { + return detail::policy_cons, detail::null_type>(); + } + + template + detail::policy_cons, detail::null_type> + pure_out_value(LUABIND_PLACEHOLDER_ARG(N)) + { + return detail::policy_cons, detail::null_type>(); + } + + template + detail::policy_cons, detail::null_type> + pure_out_value(LUABIND_PLACEHOLDER_ARG(N), const Policies&) + { + return detail::policy_cons, detail::null_type>(); + } +} + +#endif // LUABIND_OUT_VALUE_POLICY_HPP_INCLUDED + diff --git a/luabind/luabind/prefix.hpp b/luabind/luabind/prefix.hpp new file mode 100644 index 000000000..86f2db1b5 --- /dev/null +++ b/luabind/luabind/prefix.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2004 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef PREFIX_040218_HPP +#define PREFIX_040218_HPP + +#ifdef LUABIND_PREFIX_INCLUDE +# include LUABIND_PREFIX_INCLUDE +#endif + +#endif // PREFIX_040218_HPP + diff --git a/luabind/luabind/raw_policy.hpp b/luabind/luabind/raw_policy.hpp new file mode 100644 index 000000000..6d22da246 --- /dev/null +++ b/luabind/luabind/raw_policy.hpp @@ -0,0 +1,85 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_RAW_POLICY_HPP_INCLUDED +#define LUABIND_RAW_POLICY_HPP_INCLUDED + +#include +#include + +namespace luabind { namespace detail { + + struct raw_converter + { + int const consumed_args(...) + { + return 0; + } + + lua_State* apply(lua_State* L, by_pointer, int) + { + return L; + } + + static int match(...) + { + return 0; + } + + void converter_postcall(lua_State*, by_pointer, int) {} + }; + + template + struct raw_policy : conversion_policy + { + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + + template + struct apply + { + typedef raw_converter type; + }; + }; + +}} // namespace luabind::detail + +namespace luabind { + + template + detail::policy_cons< + detail::raw_policy + , detail::null_type + > + inline raw(LUABIND_PLACEHOLDER_ARG(N)) + { + return detail::policy_cons< + detail::raw_policy + , detail::null_type + >(); + } + +} // namespace luabind + +#endif // LUABIND_RAW_POLICY_HPP_INCLUDED + diff --git a/luabind/luabind/return_reference_to_policy.hpp b/luabind/luabind/return_reference_to_policy.hpp new file mode 100644 index 000000000..1432f79e0 --- /dev/null +++ b/luabind/luabind/return_reference_to_policy.hpp @@ -0,0 +1,73 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_RETURN_REFERENCE_TO_POLICY_HPP_INCLUDED +#define LUABIND_RETURN_REFERENCE_TO_POLICY_HPP_INCLUDED + +namespace luabind { namespace detail +{ + template + struct return_reference_to_converter; + + template<> + struct return_reference_to_converter + { + template + void apply(lua_State* L, const T&) + { + lua_pushnil(L); + } + }; + + template + struct return_reference_to_policy : conversion_policy<0> + { + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State* L, const index_map& indices) + { + int result_index = indices[0]; + int ref_to_index = indices[N]; + + lua_pushvalue(L, ref_to_index); + lua_replace(L, result_index); + } + + template + struct apply + { + typedef return_reference_to_converter type; + }; + }; +}} + +namespace luabind +{ + template + detail::policy_cons, detail::null_type> + return_reference_to(LUABIND_PLACEHOLDER_ARG(N)) + { + return detail::policy_cons, detail::null_type>(); + } +} + +#endif // LUABIND_RETURN_REFERENCE_TO_POLICY_HPP_INCLUDED + diff --git a/luabind/luabind/scope.hpp b/luabind/luabind/scope.hpp new file mode 100644 index 000000000..3b5f293bf --- /dev/null +++ b/luabind/luabind/scope.hpp @@ -0,0 +1,103 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef NEW_SCOPE_040211_HPP +#define NEW_SCOPE_040211_HPP + +#include +#include +#include +#include + +namespace luabind { + + struct scope; + +} // namespace luabind + +namespace luabind { namespace detail { + + struct LUABIND_API registration + { + registration(); + virtual ~registration(); + + protected: + virtual void register_(lua_State*) const = 0; + + private: + friend struct ::luabind::scope; + registration* m_next; + }; + +}} // namespace luabind::detail + +namespace luabind { + + struct LUABIND_API scope + { + scope(); + explicit scope(std::auto_ptr reg); + scope(scope const& other_); + ~scope(); + + scope& operator=(scope const& other_); + + scope& operator,(scope s); + + void register_(lua_State* L) const; + + private: + detail::registration* m_chain; + }; + + class LUABIND_API namespace_ : public scope + { + public: + explicit namespace_(char const* name); + namespace_& operator[](scope s); + + private: + struct registration_; + registration_* m_registration; + }; + + class LUABIND_API module_ + { + public: + module_(lua_State* L_, char const* name); + void operator[](scope s); + + private: + lua_State* m_state; + char const* m_name; + }; + + inline module_ module(lua_State* L, char const* name = 0) + { + return module_(L, name); + } + +} // namespace luabind + +#endif // NEW_SCOPE_040211_HPP + diff --git a/luabind/luabind/shared_ptr_converter.hpp b/luabind/luabind/shared_ptr_converter.hpp new file mode 100644 index 000000000..2f61b5cff --- /dev/null +++ b/luabind/luabind/shared_ptr_converter.hpp @@ -0,0 +1,83 @@ +// Copyright Daniel Wallin 2009. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_SHARED_PTR_CONVERTER_090211_HPP +# define LUABIND_SHARED_PTR_CONVERTER_090211_HPP + +# include +# include +# include +# include + +namespace luabind { + +namespace detail +{ + + struct shared_ptr_deleter + { + shared_ptr_deleter(lua_State* L, int index) + : life_support(get_main_thread(L), L, index) + {} + + void operator()(void const*) + { + handle().swap(life_support); + } + + handle life_support; + }; + +} // namespace detail + +template +struct default_converter > + : default_converter +{ + typedef boost::mpl::false_ is_native; + + template + int match(lua_State* L, U, int index) + { + return default_converter::match( + L, LUABIND_DECORATE_TYPE(T*), index); + } + + template + boost::shared_ptr apply(lua_State* L, U, int index) + { + T* raw_ptr = default_converter::apply( + L, LUABIND_DECORATE_TYPE(T*), index); + if (!raw_ptr) + return boost::shared_ptr(); + return boost::shared_ptr( + raw_ptr, detail::shared_ptr_deleter(L, index)); + } + + void apply(lua_State* L, boost::shared_ptr const& p) + { + if (detail::shared_ptr_deleter* d = + boost::get_deleter(p)) + { + d->life_support.push(L); + } + else + { + detail::value_converter().apply(L, p); + } + } + + template + void converter_postcall(lua_State*, U const&, int) + {} +}; + +template +struct default_converter const&> + : default_converter > +{}; + +} // namespace luabind + +#endif // LUABIND_SHARED_PTR_CONVERTER_090211_HPP diff --git a/luabind/luabind/tag_function.hpp b/luabind/luabind/tag_function.hpp new file mode 100644 index 000000000..51fe97b75 --- /dev/null +++ b/luabind/luabind/tag_function.hpp @@ -0,0 +1,88 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !BOOST_PP_IS_ITERATING + +# ifndef LUABIND_TAG_FUNCTION_081129_HPP +# define LUABIND_TAG_FUNCTION_081129_HPP + +# if LUABIND_MAX_ARITY <= 8 +# include +# else +# include +# endif +# include +# include +# include +# include + +namespace luabind { + +namespace detail +{ + + template + struct tagged_function + { + tagged_function(F f) + : f(f) + {} + + F f; + }; + + template + Signature deduce_signature(tagged_function const&, ...) + { + return Signature(); + } + + template + int invoke( + lua_State* L, function_object const& self, invoke_context& ctx + , tagged_function const& tagged + , Signature, Policies const& policies) + { + return invoke(L, self, ctx, tagged.f, Signature(), policies); + } + + template + struct signature_from_function; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, LUABIND_MAX_ARITY, )) +# include BOOST_PP_ITERATE() + +} // namespace detail + +template +detail::tagged_function< + typename detail::signature_from_function::type + , F +> +tag_function(F f) +{ + return f; +} + +} // namespace luabind + +# endif // LUABIND_TAG_FUNCTION_081129_HPP + +#else // BOOST_PP_IS_ITERATING + +# define N BOOST_PP_ITERATION() +# define NPLUS1 BOOST_PP_INC(N) + +template +struct signature_from_function +{ + typedef BOOST_PP_CAT(mpl::vector, NPLUS1)< + R BOOST_PP_ENUM_TRAILING_PARAMS(N, A) + > type; +}; + +#endif // BOOST_PP_IS_ITERATING + + diff --git a/luabind/luabind/typeid.hpp b/luabind/luabind/typeid.hpp new file mode 100644 index 000000000..d92d8fbac --- /dev/null +++ b/luabind/luabind/typeid.hpp @@ -0,0 +1,65 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_TYPEID_081227_HPP +# define LUABIND_TYPEID_081227_HPP + +# include +# include +# include + +namespace luabind { + +# ifdef BOOST_MSVC +# pragma warning(push) +// std::type_info::before() returns int, rather than bool. +// At least on MSVC7.1, this is true for the comparison +// operators as well. +# pragma warning(disable:4800) +# endif + +class type_id + : public boost::less_than_comparable +{ +public: + type_id() + : id(&typeid(detail::null_type)) + {} + + type_id(std::type_info const& id) + : id(&id) + {} + + bool operator!=(type_id const& other) const + { + return *id != *other.id; + } + + bool operator==(type_id const& other) const + { + return *id == *other.id; + } + + bool operator<(type_id const& other) const + { + return id->before(*other.id); + } + + char const* name() const + { + return id->name(); + } + +private: + std::type_info const* id; +}; + +# ifdef BOOST_MSVC +# pragma warning(pop) +# endif + +} // namespace luabind + +#endif // LUABIND_TYPEID_081227_HPP + diff --git a/luabind/luabind/value_wrapper.hpp b/luabind/luabind/value_wrapper.hpp new file mode 100644 index 000000000..8e09395d5 --- /dev/null +++ b/luabind/luabind/value_wrapper.hpp @@ -0,0 +1,168 @@ +// Copyright (c) 2005 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef LUABIND_VALUE_WRAPPER_050419_HPP +#define LUABIND_VALUE_WRAPPER_050419_HPP + +#include +#include +#include + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define LUABIND_USE_VALUE_WRAPPER_TAG +#else +#endif + +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +namespace luabind { + +// +// Concept ``ValueWrapper`` +// + +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG +template +struct value_wrapper_traits; + +namespace detail +{ + + BOOST_MPL_HAS_XXX_TRAIT_DEF(value_wrapper_tag); + + struct unspecialized_value_wrapper_traits + { + typedef boost::mpl::false_ is_specialized; + }; + + template + struct value_wrapper_traits_aux + { + typedef value_wrapper_traits type; + }; + +} // namespace detail +#endif + +template +struct value_wrapper_traits +#ifdef LUABIND_USE_VALUE_WRAPPER_TAG + : boost::mpl::eval_if< + boost::mpl::and_< + boost::mpl::not_< + boost::mpl::or_< + boost::is_reference + , boost::is_pointer + , boost::is_array + > + > + , detail::has_value_wrapper_tag + > + , detail::value_wrapper_traits_aux + , boost::mpl::identity + >::type +{}; +#else +{ + typedef boost::mpl::false_ is_specialized; +}; +#endif + +template +struct is_value_wrapper + : boost::mpl::aux::msvc_eti_base< + typename value_wrapper_traits::is_specialized + >::type +{}; + +} // namespace luabind + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +# include +# include + +namespace luabind { + +template +struct is_value_wrapper_arg + : is_value_wrapper< + typename boost::remove_const< + typename boost::remove_reference::type + >::type + > +{}; + +} // namespace luabind + +#else + +# include +# include + +namespace luabind { + +namespace detail +{ + template + typename is_value_wrapper::type is_value_wrapper_arg_check(T const*); + + yes_t to_yesno(boost::mpl::true_); + no_t to_yesno(boost::mpl::false_); + + template + struct is_value_wrapper_arg_aux + { + static typename boost::add_reference::type x; + + BOOST_STATIC_CONSTANT(bool, value = + sizeof(to_yesno(is_value_wrapper_arg_check(&x))) + == sizeof(yes_t) + ); + + typedef boost::mpl::bool_ type; + }; + +} // namespace detail + +template +struct is_value_wrapper_arg + : detail::is_value_wrapper_arg_aux::type +{ +}; + +} // namespace luabind + +#endif + +#endif // LUABIND_VALUE_WRAPPER_050419_HPP + diff --git a/luabind/luabind/version.hpp b/luabind/luabind/version.hpp new file mode 100644 index 000000000..63acaf765 --- /dev/null +++ b/luabind/luabind/version.hpp @@ -0,0 +1,16 @@ +// Copyright Daniel Wallin 2009. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LUABIND_VERSION_090216_HPP +# define LUABIND_VERSION_090216_HPP + +# define LUABIND_VERSION 900 + +// Each component uses two digits, so: +// +// major = LUABIND_VERSION / 10000 +// minor = LUABIND_VERSION / 100 % 100 +// patch = LUABIND_VERSION % 100 + +#endif // LUABIND_VERSION_090216_HPP diff --git a/luabind/luabind/weak_ref.hpp b/luabind/luabind/weak_ref.hpp new file mode 100644 index 000000000..e08e250dc --- /dev/null +++ b/luabind/luabind/weak_ref.hpp @@ -0,0 +1,59 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef WEAK_REF_040402_HPP +#define WEAK_REF_040402_HPP + +#include + +struct lua_State; + +namespace luabind { + + class LUABIND_API weak_ref + { + public: + weak_ref(); + weak_ref(lua_State* main, lua_State* L, int index); + weak_ref(weak_ref const&); + ~weak_ref(); + + weak_ref& operator=(weak_ref const&); + + void swap(weak_ref&); + + // returns a unique id that no + // other weak ref will return + int id() const; + + lua_State* state() const; + void get(lua_State* L) const; + + private: + struct impl; + impl* m_impl; + }; + +} // namespace luabind + +#endif // WEAK_REF_040402_HPP + diff --git a/luabind/luabind/wrapper_base.hpp b/luabind/luabind/wrapper_base.hpp new file mode 100644 index 000000000..d54c668f3 --- /dev/null +++ b/luabind/luabind/wrapper_base.hpp @@ -0,0 +1,190 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#if !BOOST_PP_IS_ITERATING + +#ifndef LUABIND_WRAPPER_BASE_HPP_INCLUDED +#define LUABIND_WRAPPER_BASE_HPP_INCLUDED + +#include +#include +#include +#include + +#include +#include + +#include + +namespace luabind +{ + namespace detail + { + struct wrap_access; + + // implements the selection between dynamic dispatch + // or default implementation calls from within a virtual + // function wrapper. The input is the self reference on + // the top of the stack. Output is the function to call + // on the top of the stack (the input self reference will + // be popped) + LUABIND_API void do_call_member_selection(lua_State* L, char const* name); + } + + struct wrapped_self_t: weak_ref + { + detail::lua_reference m_strong_ref; + }; + + struct wrap_base + { + friend struct detail::wrap_access; + wrap_base() {} + + #define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 1)) + #include BOOST_PP_ITERATE() + + private: + wrapped_self_t m_self; + }; + +#define BOOST_PP_ITERATION_PARAMS_1 (4, (0, LUABIND_MAX_ARITY, , 2)) +#include BOOST_PP_ITERATE() + + namespace detail + { + struct wrap_access + { + static wrapped_self_t const& ref(wrap_base const& b) + { + return b.m_self; + } + + static wrapped_self_t& ref(wrap_base& b) + { + return b.m_self; + } + }; + } +} + +#endif // LUABIND_WRAPPER_BASE_HPP_INCLUDED + +#elif BOOST_PP_ITERATION_FLAGS() == 1 + +#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * +#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n + + template + typename boost::mpl::if_ + , luabind::detail::proxy_member_void_caller > + , luabind::detail::proxy_member_caller > >::type + call(char const* name BOOST_PP_COMMA_IF(BOOST_PP_ITERATION()) BOOST_PP_ENUM(BOOST_PP_ITERATION(), LUABIND_OPERATOR_PARAMS, _), detail::type_* = 0) const + { + typedef boost::tuples::tuple tuple_t; + #if BOOST_PP_ITERATION() == 0 + tuple_t args; + #else + tuple_t args(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), &a)); + #endif + + typedef typename boost::mpl::if_ + , luabind::detail::proxy_member_void_caller > + , luabind::detail::proxy_member_caller > >::type proxy_type; + + // this will be cleaned up by the proxy object + // once the call has been made + + // TODO: what happens if this virtual function is + // dispatched from a lua thread where the state + // pointer is different? + + // get the function + lua_State* L = m_self.state(); + m_self.get(L); + assert(!lua_isnil(L, -1)); + detail::do_call_member_selection(L, name); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + throw std::runtime_error("Attempt to call nonexistent function"); + } + + // push the self reference as the first parameter + m_self.get(L); + + // now the function and self objects + // are on the stack. These will both + // be popped by pcall + return proxy_type(L, args); + } + +#undef LUABIND_CALL_MEMBER_NAME +#undef LUABIND_OPERATOR_PARAMS +#undef LUABIND_TUPLE_PARAMS + +#else // free call_member forwardarding functions + +#define N BOOST_PP_ITERATION() + +#define LUABIND_TUPLE_PARAMS(z, n, data) const A##n * +#define LUABIND_OPERATOR_PARAMS(z, n, data) const A##n & a##n + + template< + class R + BOOST_PP_ENUM_TRAILING_PARAMS(N, class A) + > + typename boost::mpl::if_< + boost::is_void + , detail::proxy_member_void_caller< + boost::tuples::tuple< + BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _) + > + > + , detail::proxy_member_caller< + R + , boost::tuples::tuple< + BOOST_PP_ENUM(N, LUABIND_TUPLE_PARAMS, _) + > + > + >::type + call_member( + wrap_base const* self + , char const* fn + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(N, A, &a) + , detail::type_* = 0 + ) + { + return self->call( + fn + BOOST_PP_ENUM_TRAILING_PARAMS(N, a) + , (detail::type_*)0 + ); + } + +#undef LUABIND_OPERATOR_PARAMS +#undef LUABIND_TUPLE_PARAMS + +#undef N + +#endif diff --git a/luabind/luabind/yield_policy.hpp b/luabind/luabind/yield_policy.hpp new file mode 100644 index 000000000..9dbbefa29 --- /dev/null +++ b/luabind/luabind/yield_policy.hpp @@ -0,0 +1,67 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + + +#ifndef LUABIND_YIELD_POLICY_HPP_INCLUDED +#define LUABIND_YIELD_POLICY_HPP_INCLUDED + +#include +#include + +namespace luabind { namespace detail +{ + struct yield_policy + { + static void precall(lua_State*, const index_map&) {} + static void postcall(lua_State*, const index_map&) {} + }; + + template + struct has_yield + { + BOOST_STATIC_CONSTANT(bool, + value = (boost::is_same::value || + has_yield::value)); + }; + + template<> + struct has_yield + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +}} + +namespace luabind +{ + detail::policy_cons const yield = {}; + + namespace detail + { + inline void ignore_unused_yield() + { + (void)yield; + } + } +} + +#endif // LUABIND_YIELD_POLICY_HPP_INCLUDED + diff --git a/luabind/src/class.cpp b/luabind/src/class.cpp new file mode 100644 index 000000000..8a67cf6f3 --- /dev/null +++ b/luabind/src/class.cpp @@ -0,0 +1,337 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include + +#include +#include +#include + +#include +#include + +namespace luabind +{ + LUABIND_API detail::nil_type nil; +} + +namespace luabind { namespace detail { + + + namespace + { + struct cast_entry + { + cast_entry(class_id src, class_id target, cast_function cast) + : src(src) + , target(target) + , cast(cast) + {} + + class_id src; + class_id target; + cast_function cast; + }; + + } // namespace unnamed + + struct class_registration : registration + { + class_registration(char const* name); + + void register_(lua_State* L) const; + + const char* m_name; + + mutable std::map m_static_constants; + + typedef std::pair base_desc; + mutable std::vector m_bases; + + type_id m_type; + class_id m_id; + class_id m_wrapper_id; + type_id m_wrapper_type; + std::vector m_casts; + + scope m_scope; + scope m_members; + scope m_default_members; + }; + + class_registration::class_registration(char const* name) + { + m_name = name; + } + + void class_registration::register_(lua_State* L) const + { + LUABIND_CHECK_STACK(L); + + assert(lua_type(L, -1) == LUA_TTABLE); + + lua_pushstring(L, m_name); + + detail::class_rep* crep; + + detail::class_registry* r = detail::class_registry::get_registry(L); + // create a class_rep structure for this class. + // allocate it within lua to let lua collect it on + // lua_close(). This is better than allocating it + // as a static, since it will then be destructed + // when the program exits instead. + // warning: we assume that lua will not + // move the userdata memory. + lua_newuserdata(L, sizeof(detail::class_rep)); + crep = reinterpret_cast(lua_touserdata(L, -1)); + + new(crep) detail::class_rep( + m_type + , m_name + , L + ); + + // register this new type in the class registry + r->add_class(m_type, crep); + + lua_pushstring(L, "__luabind_class_map"); + lua_rawget(L, LUA_REGISTRYINDEX); + class_map& classes = *static_cast( + lua_touserdata(L, -1)); + lua_pop(L, 1); + + classes.put(m_id, crep); + + bool const has_wrapper = m_wrapper_id != registered_class::id; + + if (has_wrapper) + classes.put(m_wrapper_id, crep); + + crep->m_static_constants.swap(m_static_constants); + + detail::class_registry* registry = detail::class_registry::get_registry(L); + + crep->get_default_table(L); + m_scope.register_(L); + m_default_members.register_(L); + lua_pop(L, 1); + + crep->get_table(L); + m_members.register_(L); + lua_pop(L, 1); + + lua_pushstring(L, "__luabind_cast_graph"); + lua_gettable(L, LUA_REGISTRYINDEX); + cast_graph* const casts = static_cast( + lua_touserdata(L, -1)); + lua_pop(L, 1); + + lua_pushstring(L, "__luabind_class_id_map"); + lua_gettable(L, LUA_REGISTRYINDEX); + class_id_map* const class_ids = static_cast( + lua_touserdata(L, -1)); + lua_pop(L, 1); + + class_ids->put(m_id, m_type); + + if (has_wrapper) + class_ids->put(m_wrapper_id, m_wrapper_type); + + BOOST_FOREACH(cast_entry const& e, m_casts) + { + casts->insert(e.src, e.target, e.cast); + } + + for (std::vector::iterator i = m_bases.begin(); + i != m_bases.end(); ++i) + { + LUABIND_CHECK_STACK(L); + + // the baseclass' class_rep structure + detail::class_rep* bcrep = registry->find_class(i->first); + + detail::class_rep::base_info base; + base.pointer_offset = 0; + base.base = bcrep; + + crep->add_base_class(base); + + // copy base class table + crep->get_table(L); + bcrep->get_table(L); + lua_pushnil(L); + + while (lua_next(L, -2)) + { + lua_pushvalue(L, -2); // copy key + lua_gettable(L, -5); + + if (!lua_isnil(L, -1)) + { + lua_pop(L, 2); + continue; + } + + lua_pop(L, 1); + lua_pushvalue(L, -2); // copy key + lua_insert(L, -2); + + lua_settable(L, -5); + } + lua_pop(L, 2); + + // copy base class detaults table + crep->get_default_table(L); + bcrep->get_default_table(L); + lua_pushnil(L); + + while (lua_next(L, -2)) + { + lua_pushvalue(L, -2); // copy key + lua_gettable(L, -5); + + if (!lua_isnil(L, -1)) + { + lua_pop(L, 2); + continue; + } + + lua_pop(L, 1); + lua_pushvalue(L, -2); // copy key + lua_insert(L, -2); + + lua_settable(L, -5); + } + lua_pop(L, 2); + + } + + lua_settable(L, -3); + } + + // -- interface --------------------------------------------------------- + + class_base::class_base(char const* name) + : scope(std::auto_ptr( + m_registration = new class_registration(name)) + ) + { + } + + void class_base::init( + type_id const& type_id_, class_id id + , type_id const& wrapper_type, class_id wrapper_id) + { + m_registration->m_type = type_id_; + m_registration->m_id = id; + m_registration->m_wrapper_type = wrapper_type; + m_registration->m_wrapper_id = wrapper_id; + } + + void class_base::add_base(type_id const& base, cast_function cast) + { + m_registration->m_bases.push_back(std::make_pair(base, cast)); + } + + void class_base::add_member(registration* member) + { + std::auto_ptr ptr(member); + m_registration->m_members.operator,(scope(ptr)); + } + + void class_base::add_default_member(registration* member) + { + std::auto_ptr ptr(member); + m_registration->m_default_members.operator,(scope(ptr)); + } + + const char* class_base::name() const + { + return m_registration->m_name; + } + + void class_base::add_static_constant(const char* name, int val) + { + m_registration->m_static_constants[name] = val; + } + + void class_base::add_inner_scope(scope& s) + { + m_registration->m_scope.operator,(s); + } + + void class_base::add_cast( + class_id src, class_id target, cast_function cast) + { + m_registration->m_casts.push_back(cast_entry(src, target, cast)); + } + + void add_custom_name(type_id const& i, std::string& s) + { + s += " ["; + s += i.name(); + s += "]"; + } + + std::string get_class_name(lua_State* L, type_id const& i) + { + std::string ret; + + assert(L); + + class_registry* r = class_registry::get_registry(L); + class_rep* crep = r->find_class(i); + + if (crep == 0) + { + ret = "custom"; + add_custom_name(i, ret); + } + else + { + /* TODO reimplement this? + if (i == crep->holder_type()) + { + ret += "smart_ptr<"; + ret += crep->name(); + ret += ">"; + } + else if (i == crep->const_holder_type()) + { + ret += "smart_ptrname(); + ret += ">"; + } + else*/ + { + ret += crep->name(); + } + } + return ret; + } + +}} // namespace luabind::detail + diff --git a/luabind/src/class_info.cpp b/luabind/src/class_info.cpp new file mode 100644 index 000000000..531f6e0cc --- /dev/null +++ b/luabind/src/class_info.cpp @@ -0,0 +1,120 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include +#include +#include + +namespace luabind +{ + LUABIND_API class_info get_class_info(argument const& o) + { + lua_State* L = o.interpreter(); + + o.push(L); + detail::object_rep* obj = detail::get_instance(L, -1); + + if (!obj) + { + class_info result; + result.name = lua_typename(L, lua_type(L, -1)); + lua_pop(L, 1); + result.methods = newtable(L); + result.attributes = newtable(L); + return result; + } + + lua_pop(L, 1); + + obj->crep()->get_table(L); + object table(from_stack(L, -1)); + lua_pop(L, 1); + + class_info result; + result.name = obj->crep()->name(); + result.methods = newtable(L); + result.attributes = newtable(L); + + std::size_t index = 1; + + for (iterator i(table), e; i != e; ++i) + { + if (type(*i) != LUA_TFUNCTION) + continue; + + // We have to create a temporary `object` here, otherwise the proxy + // returned by operator->() will mess up the stack. This is a known + // problem that probably doesn't show up in real code very often. + object member(*i); + member.push(L); + detail::stack_pop pop(L, 1); + + if (lua_tocfunction(L, -1) == &detail::property_tag) + { + result.attributes[index++] = i.key(); + } + else + { + result.methods[i.key()] = *i; + } + } + + return result; + } + + LUABIND_API object get_class_names(lua_State* L) + { + detail::class_registry* reg = detail::class_registry::get_registry(L); + + std::map const& classes = reg->get_classes(); + + object result = newtable(L); + std::size_t index = 1; + + for (std::map::const_iterator iter = classes.begin(); + iter != classes.end(); ++iter) + { + result[index++] = iter->second->name(); + } + + return result; + } + + LUABIND_API void bind_class_info(lua_State* L) + { + module(L) + [ + class_("class_info_data") + .def_readonly("name", &class_info::name) + .def_readonly("methods", &class_info::methods) + .def_readonly("attributes", &class_info::attributes), + + def("class_info", &get_class_info), + def("class_names", &get_class_names) + ]; + } +} + diff --git a/luabind/src/class_registry.cpp b/luabind/src/class_registry.cpp new file mode 100644 index 000000000..79df30ade --- /dev/null +++ b/luabind/src/class_registry.cpp @@ -0,0 +1,166 @@ +// Copyright (c) 2004 Daniel Wallin + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include +#include +#include +#include + +namespace luabind { namespace detail { + + LUABIND_API void push_instance_metatable(lua_State* L); + + namespace { + + int create_cpp_class_metatable(lua_State* L) + { + lua_newtable(L); + + // mark the table with our (hopefully) unique tag + // that says that the user data that has this + // metatable is a class_rep + lua_pushstring(L, "__luabind_classrep"); + lua_pushboolean(L, 1); + lua_rawset(L, -3); + + lua_pushstring(L, "__gc"); + lua_pushcclosure( + L + , &garbage_collector_s< + detail::class_rep + >::apply + , 0); + + lua_rawset(L, -3); + + lua_pushstring(L, "__call"); + lua_pushcclosure(L, &class_rep::constructor_dispatcher, 0); + lua_rawset(L, -3); + + lua_pushstring(L, "__index"); + lua_pushcclosure(L, &class_rep::static_class_gettable, 0); + lua_rawset(L, -3); + + lua_pushstring(L, "__newindex"); + lua_pushcclosure(L, &class_rep::lua_settable_dispatcher, 0); + lua_rawset(L, -3); + + return luaL_ref(L, LUA_REGISTRYINDEX); + } + + int create_lua_class_metatable(lua_State* L) + { + lua_newtable(L); + + lua_pushstring(L, "__luabind_classrep"); + lua_pushboolean(L, 1); + lua_rawset(L, -3); + + lua_pushstring(L, "__gc"); + lua_pushcclosure( + L + , &detail::garbage_collector_s< + detail::class_rep + >::apply + , 0); + + lua_rawset(L, -3); + + lua_pushstring(L, "__newindex"); + lua_pushcclosure(L, &class_rep::lua_settable_dispatcher, 0); + lua_rawset(L, -3); + + lua_pushstring(L, "__call"); + lua_pushcclosure(L, &class_rep::constructor_dispatcher, 0); + lua_rawset(L, -3); + + lua_pushstring(L, "__index"); + lua_pushcclosure(L, &class_rep::static_class_gettable, 0); + lua_rawset(L, -3); + + return luaL_ref(L, LUA_REGISTRYINDEX); + } + + } // namespace unnamed + + class class_rep; + + class_registry::class_registry(lua_State* L) + : m_cpp_class_metatable(create_cpp_class_metatable(L)) + , m_lua_class_metatable(create_lua_class_metatable(L)) + { + push_instance_metatable(L); + m_instance_metatable = luaL_ref(L, LUA_REGISTRYINDEX); + } + + class_registry* class_registry::get_registry(lua_State* L) + { + +#ifdef LUABIND_NOT_THREADSAFE + + // if we don't have to be thread safe, we can keep a + // chache of the class_registry pointer without the + // need of a mutex + static lua_State* cache_key = 0; + static class_registry* registry_cache = 0; + if (cache_key == L) return registry_cache; + +#endif + + lua_pushstring(L, "__luabind_classes"); + lua_gettable(L, LUA_REGISTRYINDEX); + class_registry* p = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); + +#ifdef LUABIND_NOT_THREADSAFE + + cache_key = L; + registry_cache = p; + +#endif + + return p; + } + + void class_registry::add_class(type_id const& info, class_rep* crep) + { + // class is already registered + assert((m_classes.find(info) == m_classes.end()) + && "you are trying to register a class twice"); + m_classes[info] = crep; + } + + class_rep* class_registry::find_class(type_id const& info) const + { + std::map::const_iterator i( + m_classes.find(info)); + + if (i == m_classes.end()) return 0; // the type is not registered + return i->second; + } + +}} // namespace luabind::detail + diff --git a/luabind/src/class_rep.cpp b/luabind/src/class_rep.cpp new file mode 100644 index 000000000..70bb6231c --- /dev/null +++ b/luabind/src/class_rep.cpp @@ -0,0 +1,395 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include +#include +#include +#include +#include +#include + +using namespace luabind::detail; + +namespace luabind { namespace detail +{ + LUABIND_API int property_tag(lua_State* L) + { + lua_pushstring(L, "luabind: property_tag function can't be called"); + lua_error(L); + return 0; + } +}} + +luabind::detail::class_rep::class_rep(type_id const& type + , const char* name + , lua_State* L +) + : m_type(type) + , m_name(name) + , m_class_type(cpp_class) + , m_operator_cache(0) +{ + lua_newtable(L); + handle(L, -1).swap(m_table); + lua_newtable(L); + handle(L, -1).swap(m_default_table); + lua_pop(L, 2); + + class_registry* r = class_registry::get_registry(L); + assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()"); + + lua_rawgeti(L, LUA_REGISTRYINDEX, r->cpp_class()); + lua_setmetatable(L, -2); + + lua_pushvalue(L, -1); // duplicate our user data + m_self_ref.set(L); + + m_instance_metatable = r->cpp_instance(); + + lua_pushstring(L, "__luabind_cast_graph"); + lua_gettable(L, LUA_REGISTRYINDEX); + m_casts = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); + + lua_pushstring(L, "__luabind_class_id_map"); + lua_gettable(L, LUA_REGISTRYINDEX); + m_classes = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); +} + +luabind::detail::class_rep::class_rep(lua_State* L, const char* name) + : m_type(typeid(null_type)) + , m_name(name) + , m_class_type(lua_class) + , m_operator_cache(0) +{ + lua_newtable(L); + handle(L, -1).swap(m_table); + lua_newtable(L); + handle(L, -1).swap(m_default_table); + lua_pop(L, 2); + + class_registry* r = class_registry::get_registry(L); + assert((r->cpp_class() != LUA_NOREF) && "you must call luabind::open()"); + + lua_rawgeti(L, LUA_REGISTRYINDEX, r->lua_class()); + lua_setmetatable(L, -2); + lua_pushvalue(L, -1); // duplicate our user data + m_self_ref.set(L); + + m_instance_metatable = r->lua_instance(); + + lua_pushstring(L, "__luabind_cast_graph"); + lua_gettable(L, LUA_REGISTRYINDEX); + m_casts = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); + + lua_pushstring(L, "__luabind_class_id_map"); + lua_gettable(L, LUA_REGISTRYINDEX); + m_classes = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); +} + +luabind::detail::class_rep::~class_rep() +{ +} + +// leaves object on lua stack +std::pair +luabind::detail::class_rep::allocate(lua_State* L) const +{ + const int size = sizeof(object_rep); + char* mem = static_cast(lua_newuserdata(L, size)); + return std::pair(mem, (void*)0); +} + +namespace +{ + + bool super_deprecation_disabled = false; + +} // namespace unnamed + +// this is called as metamethod __call on the class_rep. +int luabind::detail::class_rep::constructor_dispatcher(lua_State* L) +{ + class_rep* cls = static_cast(lua_touserdata(L, 1)); + + int args = lua_gettop(L); + + push_new_instance(L, cls); + + if (super_deprecation_disabled + && cls->get_class_type() == class_rep::lua_class + && !cls->bases().empty()) + { + lua_pushstring(L, "super"); + lua_pushvalue(L, 1); + lua_pushvalue(L, -3); + lua_pushcclosure(L, super_callback, 2); + lua_settable(L, LUA_GLOBALSINDEX); + } + + lua_pushvalue(L, -1); + lua_replace(L, 1); + + cls->get_table(L); + lua_pushliteral(L, "__init"); + lua_gettable(L, -2); + + lua_insert(L, 1); + + lua_pop(L, 1); + lua_insert(L, 1); + + lua_call(L, args, 0); + + if (super_deprecation_disabled) + { + lua_pushstring(L, "super"); + lua_pushnil(L); + lua_settable(L, LUA_GLOBALSINDEX); + } + + return 1; +} + +void luabind::detail::class_rep::add_base_class(const luabind::detail::class_rep::base_info& binfo) +{ + // If you hit this assert you are deriving from a type that is not registered + // in lua. That is, in the class_<> you are giving a baseclass that isn't registered. + // Please note that if you don't need to have access to the base class or the + // conversion from the derived class to the base class, you don't need + // to tell luabind that it derives. + assert(binfo.base && "You cannot derive from an unregistered type"); + + class_rep* bcrep = binfo.base; + + // import all static constants + for (std::map::const_iterator i = bcrep->m_static_constants.begin(); + i != bcrep->m_static_constants.end(); ++i) + { + int& v = m_static_constants[i->first]; + v = i->second; + } + + // also, save the baseclass info to be used for typecasts + m_bases.push_back(binfo); +} + +LUABIND_API void luabind::disable_super_deprecation() +{ + super_deprecation_disabled = true; +} + +int luabind::detail::class_rep::super_callback(lua_State* L) +{ + int args = lua_gettop(L); + + class_rep* crep = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + class_rep* base = crep->bases()[0].base; + + if (base->bases().empty()) + { + lua_pushstring(L, "super"); + lua_pushnil(L); + lua_settable(L, LUA_GLOBALSINDEX); + } + else + { + lua_pushstring(L, "super"); + lua_pushlightuserdata(L, base); + lua_pushvalue(L, lua_upvalueindex(2)); + lua_pushcclosure(L, super_callback, 2); + lua_settable(L, LUA_GLOBALSINDEX); + } + + base->get_table(L); + lua_pushstring(L, "__init"); + lua_gettable(L, -2); + lua_insert(L, 1); + lua_pop(L, 1); + + lua_pushvalue(L, lua_upvalueindex(2)); + lua_insert(L, 2); + + lua_call(L, args + 1, 0); + + // TODO: instead of clearing the global variable "super" + // store it temporarily in the registry. maybe we should + // have some kind of warning if the super global is used? + lua_pushstring(L, "super"); + lua_pushnil(L); + lua_settable(L, LUA_GLOBALSINDEX); + + return 0; +} + + + +int luabind::detail::class_rep::lua_settable_dispatcher(lua_State* L) +{ + class_rep* crep = static_cast(lua_touserdata(L, 1)); + + // get first table + crep->get_table(L); + + // copy key, value + lua_pushvalue(L, -3); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + // pop table + lua_pop(L, 1); + + // get default table + crep->get_default_table(L); + lua_replace(L, 1); + lua_rawset(L, -3); + + crep->m_operator_cache = 0; // invalidate cache + + return 0; +} + +/* + stack: + 1: class_rep + 2: member name +*/ +int luabind::detail::class_rep::static_class_gettable(lua_State* L) +{ + class_rep* crep = static_cast(lua_touserdata(L, 1)); + + // look in the static function table + crep->get_default_table(L); + lua_pushvalue(L, 2); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) return 1; + else lua_pop(L, 2); + + const char* key = lua_tostring(L, 2); + + if (std::strlen(key) != lua_strlen(L, 2)) + { + lua_pushnil(L); + return 1; + } + + std::map::const_iterator j = crep->m_static_constants.find(key); + + if (j != crep->m_static_constants.end()) + { + lua_pushnumber(L, j->second); + return 1; + } + +#ifndef LUABIND_NO_ERROR_CHECKING + + { + std::string msg = "no static '"; + msg += key; + msg += "' in class '"; + msg += crep->name(); + msg += "'"; + lua_pushstring(L, msg.c_str()); + } + lua_error(L); + +#endif + + lua_pushnil(L); + + return 1; +} + +bool luabind::detail::is_class_rep(lua_State* L, int index) +{ + if (lua_getmetatable(L, index) == 0) return false; + + lua_pushstring(L, "__luabind_classrep"); + lua_gettable(L, -2); + if (lua_toboolean(L, -1)) + { + lua_pop(L, 2); + return true; + } + + lua_pop(L, 2); + return false; +} + +void luabind::detail::finalize(lua_State* L, class_rep* crep) +{ + if (crep->get_class_type() != class_rep::lua_class) return; + +// lua_pushvalue(L, -1); // copy the object ref + crep->get_table(L); + lua_pushliteral(L, "__finalize"); + lua_gettable(L, -2); + lua_remove(L, -2); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + } + else + { + lua_pushvalue(L, -2); + lua_call(L, 1, 0); + } + + for (std::vector::const_iterator + i = crep->bases().begin(); i != crep->bases().end(); ++i) + { + if (i->base) finalize(L, i->base); + } +} + +void luabind::detail::class_rep::cache_operators(lua_State* L) +{ + m_operator_cache = 0x1; + + for (int i = 0; i < number_of_operators; ++i) + { + get_table(L); + lua_pushstring(L, get_operator_name(i)); + lua_rawget(L, -2); + + if (lua_isfunction(L, -1)) m_operator_cache |= 1 << (i + 1); + + lua_pop(L, 2); + } +} + +bool luabind::detail::class_rep::has_operator_in_lua(lua_State* L, int id) +{ + if ((m_operator_cache & 0x1) == 0) + cache_operators(L); + + const int mask = 1 << (id + 1); + + return (m_operator_cache & mask) != 0; +} diff --git a/luabind/src/create_class.cpp b/luabind/src/create_class.cpp new file mode 100644 index 000000000..c0eb71938 --- /dev/null +++ b/luabind/src/create_class.cpp @@ -0,0 +1,140 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include + +namespace luabind { namespace detail +{ + namespace + { + // expects two tables on the lua stack: + // 1: destination + // 2: source + void copy_member_table(lua_State* L) + { + lua_pushnil(L); + + while (lua_next(L, -2)) + { + lua_pushstring(L, "__init"); + if (lua_equal(L, -1, -3)) + { + lua_pop(L, 2); + continue; + } + else lua_pop(L, 1); // __init string + + lua_pushstring(L, "__finalize"); + if (lua_equal(L, -1, -3)) + { + lua_pop(L, 2); + continue; + } + else lua_pop(L, 1); // __finalize string + + lua_pushvalue(L, -2); // copy key + lua_insert(L, -2); + lua_settable(L, -5); + } + } + } + + + int create_class::stage2(lua_State* L) + { + class_rep* crep = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + assert((crep != 0) && "internal error, please report"); + assert((is_class_rep(L, lua_upvalueindex(1))) && "internal error, please report"); + + #ifndef LUABIND_NO_ERROR_CHECKING + + if (!is_class_rep(L, 1)) + { + lua_pushstring(L, "expected class to derive from or a newline"); + lua_error(L); + } + + #endif + + class_rep* base = static_cast(lua_touserdata(L, 1)); + class_rep::base_info binfo; + + binfo.pointer_offset = 0; + binfo.base = base; + crep->add_base_class(binfo); + + // copy base class members + + crep->get_table(L); + base->get_table(L); + copy_member_table(L); + + crep->get_default_table(L); + base->get_default_table(L); + copy_member_table(L); + + crep->set_type(base->type()); + + return 0; + } + + int create_class::stage1(lua_State* L) + { + + #ifndef LUABIND_NO_ERROR_CHECKING + + if (lua_gettop(L) != 1 || lua_type(L, 1) != LUA_TSTRING || lua_isnumber(L, 1)) + { + lua_pushstring(L, "invalid construct, expected class name"); + lua_error(L); + } + + if (std::strlen(lua_tostring(L, 1)) != lua_strlen(L, 1)) + { + lua_pushstring(L, "luabind does not support class names with extra nulls"); + lua_error(L); + } + + #endif + + const char* name = lua_tostring(L, 1); + + void* c = lua_newuserdata(L, sizeof(class_rep)); + new(c) class_rep(L, name); + + // make the class globally available + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, LUA_GLOBALSINDEX); + + // also add it to the closure as return value + lua_pushcclosure(L, &stage2, 1); + + return 1; + } + +}} + diff --git a/luabind/src/error.cpp b/luabind/src/error.cpp new file mode 100644 index 000000000..73bbf5c62 --- /dev/null +++ b/luabind/src/error.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + + +namespace luabind +{ + + namespace + { + pcall_callback_fun pcall_callback = 0; +#ifdef LUABIND_NO_EXCEPTIONS + error_callback_fun error_callback = 0; + cast_failed_callback_fun cast_failed_callback = 0; +#endif + } + + +#ifdef LUABIND_NO_EXCEPTIONS + + typedef void(*error_callback_fun)(lua_State*); + typedef void(*cast_failed_callback_fun)(lua_State*, type_id const&); + + void set_error_callback(error_callback_fun e) + { + error_callback = e; + } + + void set_cast_failed_callback(cast_failed_callback_fun c) + { + cast_failed_callback = c; + } + + error_callback_fun get_error_callback() + { + return error_callback; + } + + cast_failed_callback_fun get_cast_failed_callback() + { + return cast_failed_callback; + } + +#endif + + void set_pcall_callback(pcall_callback_fun e) + { + pcall_callback = e; + } + + pcall_callback_fun get_pcall_callback() + { + return pcall_callback; + } + +} diff --git a/luabind/src/exception_handler.cpp b/luabind/src/exception_handler.cpp new file mode 100644 index 000000000..555d3858c --- /dev/null +++ b/luabind/src/exception_handler.cpp @@ -0,0 +1,87 @@ +// Copyright Daniel Wallin 2005. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define LUABIND_BUILDING + +#include +#include +#include +#include + +#ifndef LUABIND_NO_EXCEPTIONS + +namespace luabind { namespace detail { + +namespace +{ + exception_handler_base* handler_chain = 0; + + void push_exception_string(lua_State* L, char const* exception, char const* what) + { + lua_pushstring(L, exception); + lua_pushstring(L, ": '"); + lua_pushstring(L, what); + lua_pushstring(L, "'"); + lua_concat(L, 4); + } +} + +void exception_handler_base::try_next(lua_State* L) const +{ + if (next) + next->handle(L); + else + throw; +} + +LUABIND_API void handle_exception_aux(lua_State* L) +{ + try + { + if (handler_chain) + handler_chain->handle(L); + else + throw; + } + catch (error const&) + {} + catch (std::logic_error const& e) + { + push_exception_string(L, "std::logic_error", e.what()); + } + catch (std::runtime_error const& e) + { + push_exception_string(L, "std::runtime_error", e.what()); + } + catch (std::exception const& e) + { + push_exception_string(L, "std::exception", e.what()); + } + catch (char const* str) + { + push_exception_string(L, "c-string", str); + } + catch (...) + { + lua_pushstring(L, "Unknown C++ exception"); + } +} + +LUABIND_API void register_exception_handler(exception_handler_base* handler) +{ + if (!handler_chain) handler_chain = handler; + else + { + exception_handler_base* p = handler_chain; + + for (; p->next; p = p->next); + + handler->next = 0; + p->next = handler; + } +} + +}} // namespace luabind::detail + +#endif // LUABIND_NO_EXCEPTIONS diff --git a/luabind/src/function.cpp b/luabind/src/function.cpp new file mode 100644 index 000000000..20569b2bd --- /dev/null +++ b/luabind/src/function.cpp @@ -0,0 +1,136 @@ +// Copyright Daniel Wallin 2008. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define LUABIND_BUILDING + +#include + +namespace luabind { namespace detail { + +namespace +{ + + int function_destroy(lua_State* L) + { + function_object* fn = *(function_object**)lua_touserdata(L, 1); + delete fn; + return 0; + } + + void push_function_metatable(lua_State* L) + { + lua_pushstring(L, "luabind.function"); + lua_rawget(L, LUA_REGISTRYINDEX); + + if (lua_istable(L, -1)) + return; + + lua_pop(L, 1); + + lua_newtable(L); + + lua_pushstring(L, "__gc"); + lua_pushcclosure(L, &function_destroy, 0); + lua_rawset(L, -3); + + lua_pushstring(L, "luabind.function"); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + + // A pointer to this is used as a tag value to identify functions exported + // by luabind. + int function_tag = 0; + +} // namespace unnamed + +LUABIND_API bool is_luabind_function(lua_State* L, int index) +{ + if (!lua_getupvalue(L, index, 2)) + return false; + bool result = lua_touserdata(L, -1) == &function_tag; + lua_pop(L, 1); + return result; +} + +namespace +{ + + inline bool is_luabind_function(object const& obj) + { + obj.push(obj.interpreter()); + bool result = detail::is_luabind_function(obj.interpreter(), -1); + lua_pop(obj.interpreter(), 1); + return result; + } + +} // namespace unnamed + +LUABIND_API void add_overload( + object const& context, char const* name, object const& fn) +{ + function_object* f = *touserdata(getupvalue(fn, 1)); + f->name = name; + + if (object overloads = context[name]) + { + if (is_luabind_function(overloads) && is_luabind_function(fn)) + { + f->next = *touserdata(getupvalue(overloads, 1)); + f->keepalive = overloads; + } + } + + context[name] = fn; +} + +LUABIND_API object make_function_aux(lua_State* L, function_object* impl) +{ + void* storage = lua_newuserdata(L, sizeof(function_object*)); + push_function_metatable(L); + *(function_object**)storage = impl; + lua_setmetatable(L, -2); + + lua_pushlightuserdata(L, &function_tag); + lua_pushcclosure(L, impl->entry, 2); + stack_pop pop(L, 1); + + return object(from_stack(L, -1)); +} + +void invoke_context::format_error( + lua_State* L, function_object const* overloads) const +{ + char const* function_name = + overloads->name.empty() ? "" : overloads->name.c_str(); + + if (candidate_index == 0) + { + lua_pushstring(L, "No matching overload found, candidates:\n"); + int count = 0; + for (function_object const* f = overloads; f != 0; f = f->next) + { + if (count != 0) + lua_pushstring(L, "\n"); + f->format_signature(L, function_name); + ++count; + } + lua_concat(L, count * 2); + } + else + { + // Ambiguous + lua_pushstring(L, "Ambiguous, candidates:\n"); + for (int i = 0; i < candidate_index; ++i) + { + if (i != 0) + lua_pushstring(L, "\n"); + candidates[i]->format_signature(L, function_name); + } + lua_concat(L, candidate_index * 2); + } +} + +}} // namespace luabind::detail + diff --git a/luabind/src/inheritance.cpp b/luabind/src/inheritance.cpp new file mode 100644 index 000000000..2e2ec902a --- /dev/null +++ b/luabind/src/inheritance.cpp @@ -0,0 +1,258 @@ +// Copyright Daniel Wallin 2009. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define LUABIND_BUILDING + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace luabind { namespace detail { + +class_id const class_id_map::local_id_base = + std::numeric_limits::max() / 2; + +namespace +{ + + struct edge + { + edge(class_id target, cast_function cast) + : target(target) + , cast(cast) + {} + + class_id target; + cast_function cast; + }; + + bool operator<(edge const& x, edge const& y) + { + return x.target < y.target; + } + + struct vertex + { + vertex(class_id id) + : id(id) + {} + + class_id id; + std::vector edges; + }; + + typedef std::pair cache_entry; + + class cache + { + public: + static std::ptrdiff_t const unknown; + static std::ptrdiff_t const invalid; + + cache_entry get( + class_id src, class_id target, class_id dynamic_id + , std::ptrdiff_t object_offset) const; + + void put( + class_id src, class_id target, class_id dynamic_id + , std::ptrdiff_t object_offset + , std::size_t distance, std::ptrdiff_t offset); + + void invalidate(); + + private: + typedef boost::tuple< + class_id, class_id, class_id, std::ptrdiff_t> key_type; + typedef std::map map_type; + map_type m_cache; + }; + + std::ptrdiff_t const cache::unknown = + std::numeric_limits::max(); + std::ptrdiff_t const cache::invalid = cache::unknown - 1; + + cache_entry cache::get( + class_id src, class_id target, class_id dynamic_id + , std::ptrdiff_t object_offset) const + { + map_type::const_iterator i = m_cache.find( + key_type(src, target, dynamic_id, object_offset)); + return i != m_cache.end() ? i->second : cache_entry(unknown, -1); + } + + void cache::put( + class_id src, class_id target, class_id dynamic_id + , std::ptrdiff_t object_offset, std::size_t distance, std::ptrdiff_t offset) + { + m_cache.insert(std::make_pair( + key_type(src, target, dynamic_id, object_offset) + , cache_entry(offset, distance) + )); + } + + void cache::invalidate() + { + m_cache.clear(); + } + +} // namespace unnamed + +class cast_graph::impl +{ +public: + std::pair cast( + void* p, class_id src, class_id target + , class_id dynamic_id, void const* dynamic_ptr) const; + void insert(class_id src, class_id target, cast_function cast); + +private: + std::vector m_vertices; + mutable cache m_cache; +}; + +namespace +{ + + struct queue_entry + { + queue_entry(void* p, class_id vertex_id, int distance) + : p(p) + , vertex_id(vertex_id) + , distance(distance) + {} + + void* p; + class_id vertex_id; + int distance; + }; + +} // namespace unnamed + +std::pair cast_graph::impl::cast( + void* const p, class_id src, class_id target + , class_id dynamic_id, void const* dynamic_ptr) const +{ + if (src == target) + return std::make_pair(p, 0); + + if (src >= m_vertices.size() || target >= m_vertices.size()) + return std::pair((void*)0, -1); + + std::ptrdiff_t const object_offset = + (char const*)dynamic_ptr - (char const*)p; + + cache_entry cached = m_cache.get(src, target, dynamic_id, object_offset); + + if (cached.first != cache::unknown) + { + if (cached.first == cache::invalid) + return std::pair((void*)0, -1); + return std::make_pair((char*)p + cached.first, cached.second); + } + + std::queue q; + q.push(queue_entry(p, src, 0)); + + boost::dynamic_bitset<> visited(m_vertices.size()); + + while (!q.empty()) + { + queue_entry const qe = q.front(); + q.pop(); + + visited[qe.vertex_id] = true; + vertex const& v = m_vertices[qe.vertex_id]; + + if (v.id == target) + { + m_cache.put( + src, target, dynamic_id, object_offset + , qe.distance, (char*)qe.p - (char*)p + ); + + return std::make_pair(qe.p, qe.distance); + } + + BOOST_FOREACH(edge const& e, v.edges) + { + if (visited[e.target]) + continue; + if (void* casted = e.cast(qe.p)) + q.push(queue_entry(casted, e.target, qe.distance + 1)); + } + } + + m_cache.put(src, target, dynamic_id, object_offset, cache::invalid, -1); + + return std::pair((void*)0, -1); +} + +void cast_graph::impl::insert( + class_id src, class_id target, cast_function cast) +{ + class_id const max_id = std::max(src, target); + + if (max_id >= m_vertices.size()) + { + m_vertices.reserve(max_id + 1); + for (class_id i = m_vertices.size(); i < max_id + 1; ++i) + m_vertices.push_back(vertex(i)); + } + + std::vector& edges = m_vertices[src].edges; + + std::vector::iterator i = std::lower_bound( + edges.begin(), edges.end(), edge(target, 0) + ); + + if (i == edges.end() || i->target != target) + { + edges.insert(i, edge(target, cast)); + m_cache.invalidate(); + } +} + +std::pair cast_graph::cast( + void* p, class_id src, class_id target + , class_id dynamic_id, void const* dynamic_ptr) const +{ + return m_impl->cast(p, src, target, dynamic_id, dynamic_ptr); +} + +void cast_graph::insert(class_id src, class_id target, cast_function cast) +{ + m_impl->insert(src, target, cast); +} + +cast_graph::cast_graph() + : m_impl(new impl) +{} + +cast_graph::~cast_graph() +{} + +LUABIND_API class_id allocate_class_id(type_id const& cls) +{ + typedef std::map map_type; + + static map_type registered; + static class_id id = 0; + + std::pair inserted = registered.insert( + std::make_pair(cls, id)); + + if (inserted.second) + ++id; + + return inserted.first->second; +} + +}} // namespace luabind::detail diff --git a/luabind/src/link_compatibility.cpp b/luabind/src/link_compatibility.cpp new file mode 100644 index 000000000..515e0e392 --- /dev/null +++ b/luabind/src/link_compatibility.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +namespace luabind { namespace detail +{ + +#ifdef LUABIND_NOT_THREADSAFE + void not_threadsafe_defined_conflict() {} +#else + void not_threadsafe_not_defined_conflict() {} +#endif + +#ifdef LUABIND_NO_ERROR_CHECKING + void no_error_checking_defined_conflict() {} +#else + void no_error_checking_not_defined_conflict() {} +#endif + +}} + diff --git a/luabind/src/object_rep.cpp b/luabind/src/object_rep.cpp new file mode 100644 index 000000000..6977beede --- /dev/null +++ b/luabind/src/object_rep.cpp @@ -0,0 +1,272 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include +#include + +namespace luabind { namespace detail +{ + + // dest is a function that is called to delete the c++ object this struct holds + object_rep::object_rep(instance_holder* instance, class_rep* crep) + : m_instance(instance) + , m_classrep(crep) + , m_dependency_cnt(0) + {} + + object_rep::~object_rep() + { + if (!m_instance) + return; + m_instance->~instance_holder(); + deallocate(m_instance); + } + + void object_rep::add_dependency(lua_State* L, int index) + { + assert(m_dependency_cnt < sizeof(object_rep)); + + void* key = (char*)this + m_dependency_cnt; + + lua_pushlightuserdata(L, key); + lua_pushvalue(L, index); + lua_rawset(L, LUA_REGISTRYINDEX); + + ++m_dependency_cnt; + } + + void object_rep::release_dependency_refs(lua_State* L) + { + for (std::size_t i = 0; i < m_dependency_cnt; ++i) + { + void* key = (char*)this + i; + lua_pushlightuserdata(L, key); + lua_pushnil(L); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } + + int destroy_instance(lua_State* L) + { + object_rep* instance = static_cast(lua_touserdata(L, 1)); + + lua_pushstring(L, "__finalize"); + lua_gettable(L, 1); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + } + else + { + lua_pushvalue(L, 1); + lua_call(L, 1, 0); + } + + instance->release_dependency_refs(L); + instance->~object_rep(); + return 0; + } + + namespace + { + + int set_instance_value(lua_State* L) + { + lua_getfenv(L, 1); + lua_pushvalue(L, 2); + lua_rawget(L, -2); + + if (lua_isnil(L, -1) && lua_getmetatable(L, -2)) + { + lua_pushvalue(L, 2); + lua_rawget(L, -2); + lua_replace(L, -3); + lua_pop(L, 1); + } + + if (lua_tocfunction(L, -1) == &property_tag) + { + // this member is a property, extract the "set" function and call it. + lua_getupvalue(L, -1, 2); + + if (lua_isnil(L, -1)) + { + lua_pushfstring(L, "property '%s' is read only", lua_tostring(L, 2)); + lua_error(L); + } + + lua_pushvalue(L, 1); + lua_pushvalue(L, 3); + lua_call(L, 2, 0); + return 0; + } + + lua_pop(L, 1); + + if (!lua_getmetatable(L, 4)) + { + lua_newtable(L); + lua_pushvalue(L, -1); + lua_setfenv(L, 1); + lua_pushvalue(L, 4); + lua_setmetatable(L, -2); + } + else + { + lua_pop(L, 1); + } + + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, -3); + + return 0; + } + + int get_instance_value(lua_State* L) + { + lua_getfenv(L, 1); + lua_pushvalue(L, 2); + lua_rawget(L, -2); + + if (lua_isnil(L, -1) && lua_getmetatable(L, -2)) + { + lua_pushvalue(L, 2); + lua_rawget(L, -2); + } + + if (lua_tocfunction(L, -1) == &property_tag) + { + // this member is a property, extract the "get" function and call it. + lua_getupvalue(L, -1, 1); + lua_pushvalue(L, 1); + lua_call(L, 1, 1); + } + + return 1; + } + + int dispatch_operator(lua_State* L) + { + for (int i = 0; i < 2; ++i) + { + if (get_instance(L, 1 + i)) + { + int nargs = lua_gettop(L); + + lua_pushvalue(L, lua_upvalueindex(1)); + lua_gettable(L, 1 + i); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + continue; + } + + lua_insert(L, 1); // move the function to the bottom + + nargs = lua_toboolean(L, lua_upvalueindex(2)) ? 1 : nargs; + + if (lua_toboolean(L, lua_upvalueindex(2))) // remove trailing nil + lua_remove(L, 3); + + lua_call(L, nargs, 1); + return 1; + } + } + + lua_pop(L, lua_gettop(L)); + lua_pushstring(L, "No such operator defined"); + lua_error(L); + + return 0; + } + + } // namespace unnamed + + LUABIND_API void push_instance_metatable(lua_State* L) + { + lua_newtable(L); + + // just indicate that this really is a class and not just + // any user data + lua_pushboolean(L, 1); + lua_setfield(L, -2, "__luabind_class"); + + // This is used as a tag to determine if a userdata is a luabind + // instance. We use a numeric key and a cclosure for fast comparision. + lua_pushnumber(L, 1); + lua_pushcclosure(L, get_instance_value, 0); + lua_rawset(L, -3); + + lua_pushcclosure(L, destroy_instance, 0); + lua_setfield(L, -2, "__gc"); + + lua_pushcclosure(L, get_instance_value, 0); + lua_setfield(L, -2, "__index"); + + lua_pushcclosure(L, set_instance_value, 0); + lua_setfield(L, -2, "__newindex"); + + for (int op = 0; op < number_of_operators; ++op) + { + lua_pushstring(L, get_operator_name(op)); + lua_pushvalue(L, -1); + lua_pushboolean(L, op == op_unm || op == op_len); + lua_pushcclosure(L, &dispatch_operator, 2); + lua_settable(L, -3); + } + } + + LUABIND_API object_rep* get_instance(lua_State* L, int index) + { + object_rep* result = static_cast(lua_touserdata(L, index)); + + if (!result || !lua_getmetatable(L, index)) + return 0; + + lua_rawgeti(L, -1, 1); + + if (lua_tocfunction(L, -1) != &get_instance_value) + result = 0; + + lua_pop(L, 2); + + return result; + } + + LUABIND_API object_rep* push_new_instance(lua_State* L, class_rep* cls) + { + void* storage = lua_newuserdata(L, sizeof(object_rep)); + object_rep* result = new (storage) object_rep(0, cls); + cls->get_table(L); + lua_setfenv(L, -2); + lua_rawgeti(L, LUA_REGISTRYINDEX, cls->metatable_ref()); + lua_setmetatable(L, -2); + return result; + } + +}} + diff --git a/luabind/src/open.cpp b/luabind/src/open.cpp new file mode 100644 index 000000000..f20dcfc83 --- /dev/null +++ b/luabind/src/open.cpp @@ -0,0 +1,199 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include +#include +#include + +namespace luabind { + +namespace +{ + + int make_property(lua_State* L) + { + int args = lua_gettop(L); + + if (args == 0 || args > 2) + { + lua_pushstring(L, "make_property() called with wrong number of arguments."); + lua_error(L); + } + + if (args == 1) + lua_pushnil(L); + + lua_pushcclosure(L, &detail::property_tag, 2); + return 1; + } + + int main_thread_tag; + + int deprecated_super(lua_State* L) + { + lua_pushstring(L, + "DEPRECATION: 'super' has been deprecated in favor of " + "directly calling the base class __init() function. " + "This error can be disabled by calling 'luabind::disable_super_deprecation()'." + ); + lua_error(L); + + return 0; + } + + int destroy_class_id_map(lua_State* L) + { + detail::class_id_map* m = + (detail::class_id_map*)lua_touserdata(L, 1); + m->~class_id_map(); + return 0; + } + + int destroy_cast_graph(lua_State* L) + { + detail::cast_graph* g = + (detail::cast_graph*)lua_touserdata(L, 1); + g->~cast_graph(); + return 0; + } + + int destroy_class_map(lua_State* L) + { + detail::class_map* m = + (detail::class_map*)lua_touserdata(L, 1); + m->~class_map(); + return 0; + } + +} // namespace unnamed + + LUABIND_API lua_State* get_main_thread(lua_State* L) + { + lua_pushlightuserdata(L, &main_thread_tag); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_State* result = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); + + if (!result) + throw std::runtime_error("Unable to get main thread, luabind::open() not called?"); + + return result; + } + + LUABIND_API void open(lua_State* L) + { + bool is_main_thread = lua_pushthread(L) == 1; + lua_pop(L, 1); + + if (!is_main_thread) + { + throw std::runtime_error( + "luabind::open() must be called with the main thread " + "lua_State*" + ); + } + + if (detail::class_registry::get_registry(L)) + return; + + lua_pushstring(L, "__luabind_classes"); + detail::class_registry* r = static_cast( + lua_newuserdata(L, sizeof(detail::class_registry))); + + // set gc metatable + lua_newtable(L); + lua_pushstring(L, "__gc"); + lua_pushcclosure( + L + , detail::garbage_collector_s< + detail::class_registry + >::apply + , 0); + + lua_settable(L, -3); + lua_setmetatable(L, -2); + + new(r) detail::class_registry(L); + lua_settable(L, LUA_REGISTRYINDEX); + + lua_pushstring(L, "__luabind_class_id_map"); + void* classes_storage = lua_newuserdata(L, sizeof(detail::class_id_map)); + detail::class_id_map* class_ids = new (classes_storage) detail::class_id_map; + (void)class_ids; + + lua_newtable(L); + lua_pushcclosure(L, &destroy_class_id_map, 0); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + + lua_settable(L, LUA_REGISTRYINDEX); + + lua_pushstring(L, "__luabind_cast_graph"); + void* cast_graph_storage = lua_newuserdata( + L, sizeof(detail::cast_graph)); + detail::cast_graph* graph = new (cast_graph_storage) detail::cast_graph; + (void)graph; + + lua_newtable(L); + lua_pushcclosure(L, &destroy_cast_graph, 0); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + + lua_settable(L, LUA_REGISTRYINDEX); + + lua_pushstring(L, "__luabind_class_map"); + void* class_map_storage = lua_newuserdata( + L, sizeof(detail::class_map)); + detail::class_map* classes = new (class_map_storage) detail::class_map; + (void)classes; + + lua_newtable(L); + lua_pushcclosure(L, &destroy_class_map, 0); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + + lua_settable(L, LUA_REGISTRYINDEX); + + // add functions (class, cast etc...) + lua_pushstring(L, "class"); + lua_pushcclosure(L, detail::create_class::stage1, 0); + lua_settable(L, LUA_GLOBALSINDEX); + + lua_pushstring(L, "property"); + lua_pushcclosure(L, &make_property, 0); + lua_settable(L, LUA_GLOBALSINDEX); + + lua_pushlightuserdata(L, &main_thread_tag); + lua_pushlightuserdata(L, L); + lua_rawset(L, LUA_REGISTRYINDEX); + + lua_pushstring(L, "super"); + lua_pushcclosure(L, &deprecated_super, 0); + lua_settable(L, LUA_GLOBALSINDEX); + } + +} // namespace luabind + diff --git a/luabind/src/pcall.cpp b/luabind/src/pcall.cpp new file mode 100644 index 000000000..66dbeaa18 --- /dev/null +++ b/luabind/src/pcall.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include +#include +#include + +namespace luabind { namespace detail +{ + int pcall(lua_State *L, int nargs, int nresults) + { + pcall_callback_fun e = get_pcall_callback(); + int en = 0; + if ( e ) + { + int base = lua_gettop(L) - nargs; + lua_pushcfunction(L, e); + lua_insert(L, base); // push pcall_callback under chunk and args + en = base; + } + int result = lua_pcall(L, nargs, nresults, en); + if ( en ) + lua_remove(L, en); // remove pcall_callback + return result; + } + + int resume_impl(lua_State *L, int nargs, int) + { +#if LUA_VERSION_NUM >= 501 + // Lua 5.1 added LUA_YIELD as a possible return value, + // this was causing crashes, because the caller expects 0 on success. + int res = lua_resume(L, nargs); + return (res == LUA_YIELD) ? 0 : res; +#else + return lua_resume(L, nargs); +#endif + } + +}} diff --git a/luabind/src/scope.cpp b/luabind/src/scope.cpp new file mode 100644 index 000000000..6495687b9 --- /dev/null +++ b/luabind/src/scope.cpp @@ -0,0 +1,209 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include +#include +#include +#include + +namespace luabind { namespace detail { + + registration::registration() + : m_next(0) + { + } + + registration::~registration() + { + delete m_next; + } + + } // namespace detail + + scope::scope() + : m_chain(0) + { + } + + scope::scope(std::auto_ptr reg) + : m_chain(reg.release()) + { + } + + scope::scope(scope const& other) + : m_chain(other.m_chain) + { + const_cast(other).m_chain = 0; + } + + scope& scope::operator=(scope const& other_) + { + delete m_chain; + m_chain = other_.m_chain; + const_cast(other_).m_chain = 0; + return *this; + } + + scope::~scope() + { + delete m_chain; + } + + scope& scope::operator,(scope s) + { + if (!m_chain) + { + m_chain = s.m_chain; + s.m_chain = 0; + return *this; + } + + for (detail::registration* c = m_chain;; c = c->m_next) + { + if (!c->m_next) + { + c->m_next = s.m_chain; + s.m_chain = 0; + break; + } + } + + return *this; + } + + void scope::register_(lua_State* L) const + { + for (detail::registration* r = m_chain; r != 0; r = r->m_next) + { + LUABIND_CHECK_STACK(L); + r->register_(L); + } + } + +} // namespace luabind + +namespace luabind { + + namespace { + + struct lua_pop_stack + { + lua_pop_stack(lua_State* L) + : m_state(L) + { + } + + ~lua_pop_stack() + { + lua_pop(m_state, 1); + } + + lua_State* m_state; + }; + + } // namespace unnamed + + module_::module_(lua_State* L, char const* name = 0) + : m_state(L) + , m_name(name) + { + } + + void module_::operator[](scope s) + { + if (m_name) + { + lua_pushstring(m_state, m_name); + lua_gettable(m_state, LUA_GLOBALSINDEX); + + if (!lua_istable(m_state, -1)) + { + lua_pop(m_state, 1); + + lua_newtable(m_state); + lua_pushstring(m_state, m_name); + lua_pushvalue(m_state, -2); + lua_settable(m_state, LUA_GLOBALSINDEX); + } + } + else + { + lua_pushvalue(m_state, LUA_GLOBALSINDEX); + } + + lua_pop_stack guard(m_state); + + s.register_(m_state); + } + + struct namespace_::registration_ : detail::registration + { + registration_(char const* name) + : m_name(name) + { + } + + void register_(lua_State* L) const + { + LUABIND_CHECK_STACK(L); + assert(lua_gettop(L) >= 1); + + lua_pushstring(L, m_name); + lua_gettable(L, -2); + + detail::stack_pop p(L, 1); // pops the table on exit + + if (!lua_istable(L, -1)) + { + lua_pop(L, 1); + + lua_newtable(L); + lua_pushstring(L, m_name); + lua_pushvalue(L, -2); + lua_settable(L, -4); + } + + m_scope.register_(L); + } + + char const* m_name; + scope m_scope; + }; + + namespace_::namespace_(char const* name) + : scope(std::auto_ptr( + m_registration = new registration_(name))) + { + } + + namespace_& namespace_::operator[](scope s) + { + m_registration->m_scope.operator,(s); + return *this; + } + +} // namespace luabind + diff --git a/luabind/src/stack_content_by_name.cpp b/luabind/src/stack_content_by_name.cpp new file mode 100644 index 000000000..38b5c691d --- /dev/null +++ b/luabind/src/stack_content_by_name.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include + +using namespace luabind::detail; + +std::string luabind::detail::stack_content_by_name(lua_State* L, int start_index) +{ + std::string ret; + int top = lua_gettop(L); + for (int i = start_index; i <= top; ++i) + { + object_rep* obj = get_instance(L, i); + class_rep* crep = is_class_rep(L, i)?(class_rep*)lua_touserdata(L, i):0; + if (obj == 0 && crep == 0) + { + int type = lua_type(L, i); + ret += lua_typename(L, type); + } + else if (obj) + { + if (obj->is_const()) ret += "const "; + ret += obj->crep()->name(); + } + else if (crep) + { + ret += "<"; + ret += crep->name(); + ret += ">"; + } + if (i < top) ret += ", "; + } + return ret; +} + diff --git a/luabind/src/weak_ref.cpp b/luabind/src/weak_ref.cpp new file mode 100644 index 000000000..245b26c2e --- /dev/null +++ b/luabind/src/weak_ref.cpp @@ -0,0 +1,157 @@ +// Copyright (c) 2004 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include + +#include + +#include +#include +#include + +namespace luabind { + +namespace +{ + + int weak_table_tag; + +} // namespace unnamed + +LUABIND_API void get_weak_table(lua_State* L) +{ + lua_pushlightuserdata(L, &weak_table_tag); + lua_rawget(L, LUA_REGISTRYINDEX); + + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_newtable(L); + // metatable + lua_newtable(L); + lua_pushliteral(L, "__mode"); + lua_pushliteral(L, "v"); + lua_rawset(L, -3); + // set metatable + lua_setmetatable(L, -2); + + lua_pushlightuserdata(L, &weak_table_tag); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } +} + +} // namespace luabind + +namespace luabind +{ + + struct weak_ref::impl + { + impl(lua_State* main, lua_State* s, int index) + : count(0) + , state(main) + , ref(0) + { + get_weak_table(s); + lua_pushvalue(s, index); + ref = luaL_ref(s, -2); + lua_pop(s, 1); + } + + ~impl() + { + get_weak_table(state); + luaL_unref(state, -1, ref); + lua_pop(state, 1); + } + + int count; + lua_State* state; + int ref; + }; + + weak_ref::weak_ref() + : m_impl(0) + { + } + + weak_ref::weak_ref(lua_State* main, lua_State* L, int index) + : m_impl(new impl(main, L, index)) + { + m_impl->count = 1; + } + + weak_ref::weak_ref(weak_ref const& other) + : m_impl(other.m_impl) + { + if (m_impl) ++m_impl->count; + } + + weak_ref::~weak_ref() + { + if (m_impl && --m_impl->count == 0) + { + delete m_impl; + } + } + + weak_ref& weak_ref::operator=(weak_ref const& other) + { + weak_ref(other).swap(*this); + return *this; + } + + void weak_ref::swap(weak_ref& other) + { + std::swap(m_impl, other.m_impl); + } + + int weak_ref::id() const + { + assert(m_impl); + return m_impl->ref; + } + + // L may not be the same pointer as + // was used when creating this reference + // since it may be a thread that shares + // the same globals table. + void weak_ref::get(lua_State* L) const + { + assert(m_impl); + assert(L); + get_weak_table(L); + lua_rawgeti(L, -1, m_impl->ref); + lua_remove(L, -2); + } + + lua_State* weak_ref::state() const + { + assert(m_impl); + return m_impl->state; + } + +} // namespace luabind + diff --git a/luabind/src/wrapper_base.cpp b/luabind/src/wrapper_base.cpp new file mode 100644 index 000000000..9fb54a5db --- /dev/null +++ b/luabind/src/wrapper_base.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2003 Daniel Wallin and Arvid Norberg + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. + +#define LUABIND_BUILDING + +#include +#include +#include +#include +#include +#include + +namespace luabind { namespace detail +{ + LUABIND_API void do_call_member_selection(lua_State* L, char const* name) + { + object_rep* obj = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); // pop self + + obj->crep()->get_table(L); // push the crep table + lua_pushstring(L, name); + lua_gettable(L, -2); + lua_remove(L, -2); // remove the crep table + + if (!is_luabind_function(L, -1)) + return; + + // this (usually) means the function has not been + // overridden by lua, call the default implementation + lua_pop(L, 1); + obj->crep()->get_default_table(L); // push the crep table + lua_pushstring(L, name); + lua_gettable(L, -2); + lua_remove(L, -2); // remove the crep table + } +}} diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 7779ceb88..54e0321c9 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -161,6 +161,11 @@ ADD_DEFINITIONS(-DZONE) TARGET_LINK_LIBRARIES(zone Common ${PERL_LIBRARY} debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} ${LUA_LIBRARY}) +IF(EQEMU_BUILD_LUA) + TARGET_LINK_LIBRARIES(zone luabind) +ENDIF(EQEMU_BUILD_LUA) + + IF(MSVC) SET_TARGET_PROPERTIES(zone PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF") TARGET_LINK_LIBRARIES(zone "Ws2_32.lib") diff --git a/zone/lua_entity.cpp b/zone/lua_entity.cpp index db7d1da17..f6227b7d5 100644 --- a/zone/lua_entity.cpp +++ b/zone/lua_entity.cpp @@ -69,15 +69,4 @@ Lua_Mob Lua_Entity::CastToMob() { return Lua_Mob(m); } - -//Lua_Client* CastToClient(); -//Lua_NPC* CastToNPC(); -//Lua_Mob* CastToMob(); -//Lua_Merc* CastToMerc(); -//Lua_Corpse* CastToCorpse(); -//Lua_Object* CastToObject(); -//Lua_Doors* CastToDoors(); -//Lua_Trap* CastToTrap(); -//Lua_Beacon* CastToBeacon(); - #endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 7630fe1b0..86edfcc0a 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -8,4 +8,13 @@ const char *Lua_Mob::GetName() { return m->GetName(); } +void Lua_Mob::Depop() { + Depop(true); +} + +void Lua_Mob::Depop(bool start_spawn_timer) { + Mob *m = reinterpret_cast(d_); + return m->Depop(start_spawn_timer); +} + #endif diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 4dd4440e3..8c71a67ba 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -14,6 +14,9 @@ public: virtual ~Lua_Mob() { } const char *GetName(); + + void Depop(); + void Depop(bool start_spawn_timer); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index ef80eab4d..3c359f283 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -5,7 +5,9 @@ #include #include -#include +#include +#include +//#include #include "masterentity.h" #include "lua_entity.h" @@ -99,15 +101,13 @@ double LuaParser::EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string da } L = iter->second; - lua_getfield(L, LUA_GLOBALSINDEX, LuaEvents[evt]); - int arg_count = 1; - int ret_count = 0; - Lua_Entity ent(npc); - - luabridge::Stack::push(L, ent); - if(lua_pcall(L, arg_count, ret_count, 0)) { - printf("Error: %s\n", lua_tostring(L, -1)); + + try { + double val = luabind::call_function(L, LuaEvents[evt], ent); + return val; + } catch(std::exception) { + return 100.0; } return 100.0; @@ -296,25 +296,35 @@ void LuaParser::ClearStates() { } void LuaParser::MapFunctions(lua_State *L) { - luabridge::getGlobalNamespace(L) - .beginClass("Entity") - .addFunction("IsClient", &Lua_Entity::IsClient) - .addFunction("IsNPC", &Lua_Entity::IsNPC) - .addFunction("IsMob", &Lua_Entity::IsMob) - .addFunction("IsMerc", &Lua_Entity::IsMerc) - .addFunction("IsCorpse", &Lua_Entity::IsCorpse) - .addFunction("IsPlayerCorpse", &Lua_Entity::IsPlayerCorpse) - .addFunction("IsNPCCorpse", &Lua_Entity::IsNPCCorpse) - .addFunction("IsObject", &Lua_Entity::IsObject) - .addFunction("IsDoor", &Lua_Entity::IsDoor) - .addFunction("IsTrap", &Lua_Entity::IsTrap) - .addFunction("IsBeacon", &Lua_Entity::IsBeacon) - .addFunction("GetID", &Lua_Entity::GetID) - .addFunction("CastToMob", &Lua_Entity::CastToMob) - .endClass() - .deriveClass("Mob") - .addFunction("GetName", &Lua_Mob::GetName) - .endClass(); + + try { + luabind::open(L); + + luabind::module(L) + [ + luabind::class_("Entity") + .def("IsClient", &Lua_Entity::IsClient) + .def("IsNPC", &Lua_Entity::IsNPC) + .def("IsMob", &Lua_Entity::IsMob) + .def("IsMerc", &Lua_Entity::IsMerc) + .def("IsCorpse", &Lua_Entity::IsCorpse) + .def("IsPlayerCorpse", &Lua_Entity::IsPlayerCorpse) + .def("IsNPCCorpse", &Lua_Entity::IsNPCCorpse) + .def("IsObject", &Lua_Entity::IsObject) + .def("IsDoor", &Lua_Entity::IsDoor) + .def("IsTrap", &Lua_Entity::IsTrap) + .def("IsBeacon", &Lua_Entity::IsBeacon) + .def("GetID", &Lua_Entity::GetID) + .def("CastToMob", &Lua_Entity::CastToMob), + luabind::class_("Mob") + .def("GetName", &Lua_Mob::GetName) + .def("Depop", (void(Lua_Mob::*)(void))&Lua_Mob::Depop) + .def("Depop", (void(Lua_Mob::*)(bool))&Lua_Mob::Depop) + ]; + + } catch(std::exception &ex) { + printf("Error: %s\n", ex.what()); + } } #endif