From 1f2349ef6e82b7b1b82e1de6db2776e2043fb18d Mon Sep 17 00:00:00 2001 From: Bernd Schoolmann Date: Sun, 12 May 2019 03:14:03 +0200 Subject: [PATCH] Update LuaBridge to e3f7a022 --- extern/LuaBridge/List.h | 55 + extern/LuaBridge/LuaBridge.h | 120 +- extern/LuaBridge/Manual.html | 1794 ------------------------ extern/LuaBridge/Map.h | 55 + extern/LuaBridge/RefCountedObject.h | 19 +- extern/LuaBridge/RefCountedPtr.h | 47 +- extern/LuaBridge/Vector.h | 54 + extern/LuaBridge/detail/CFunctions.h | 30 +- extern/LuaBridge/detail/ClassInfo.h | 5 + extern/LuaBridge/detail/Constructor.h | 7 +- extern/LuaBridge/detail/FuncTraits.h | 129 ++ extern/LuaBridge/detail/Iterator.h | 67 +- extern/LuaBridge/detail/LuaException.h | 9 + extern/LuaBridge/detail/LuaHelpers.h | 8 + extern/LuaBridge/detail/LuaRef.h | 1502 +++++++++----------- extern/LuaBridge/detail/Namespace.h | 59 +- extern/LuaBridge/detail/Security.h | 72 + extern/LuaBridge/detail/Stack.h | 195 +-- extern/LuaBridge/detail/TypeList.h | 11 + extern/LuaBridge/detail/TypeTraits.h | 8 +- extern/LuaBridge/detail/Userdata.h | 36 +- extern/LuaBridge/detail/dump.h | 35 + 22 files changed, 1352 insertions(+), 2965 deletions(-) create mode 100644 extern/LuaBridge/List.h delete mode 100644 extern/LuaBridge/Manual.html create mode 100644 extern/LuaBridge/Map.h create mode 100644 extern/LuaBridge/Vector.h create mode 100644 extern/LuaBridge/detail/Security.h diff --git a/extern/LuaBridge/List.h b/extern/LuaBridge/List.h new file mode 100644 index 000000000..bc731e6d8 --- /dev/null +++ b/extern/LuaBridge/List.h @@ -0,0 +1,55 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + static void push(lua_State* L, std::list const& list) + { + lua_createtable (L, static_cast (list.size ()), 0); + typename std::list ::const_iterator item = list.begin(); + for (std::size_t i = 1; i <= list.size (); ++i) + { + lua_pushinteger (L, static_cast (i)); + Stack ::push (L, *item); + lua_settable (L, -3); + ++item; + } + } + + static std::list get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + { + luaL_error(L, "#%d argments must be table", index); + } + + std::list list; + + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + list.push_back (Stack ::get (L, -1)); + lua_pop (L, 1); + } + return list; + } +}; + +template +struct Stack const&> : Stack > +{ +}; + +} // namespace luabridge diff --git a/extern/LuaBridge/LuaBridge.h b/extern/LuaBridge/LuaBridge.h index 1928e9a1f..ce488bf51 100644 --- a/extern/LuaBridge/LuaBridge.h +++ b/extern/LuaBridge/LuaBridge.h @@ -27,116 +27,32 @@ */ //============================================================================== -#ifndef LUABRIDGE_LUABRIDGE_HEADER -#define LUABRIDGE_LUABRIDGE_HEADER +#pragma once // All #include dependencies are listed here // instead of in the individual header files. // -#include -#include -#include -#include -#include #define LUABRIDGE_MAJOR_VERSION 2 #define LUABRIDGE_MINOR_VERSION 0 #define LUABRIDGE_VERSION 200 -namespace luabridge -{ - -// Forward declaration -// -template -struct Stack; - -#include "detail/LuaHelpers.h" - -#include "detail/TypeTraits.h" -#include "detail/TypeList.h" -#include "detail/FuncTraits.h" -#include "detail/Constructor.h" -#include "detail/Stack.h" -#include "detail/ClassInfo.h" - -class LuaRef; - -#include "detail/LuaException.h" -#include "detail/LuaRef.h" -#include "detail/Iterator.h" - -//------------------------------------------------------------------------------ -/** - 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; - } -}; - -#include "detail/Userdata.h" -#include "detail/CFunctions.h" -#include "detail/Namespace.h" - -//------------------------------------------------------------------------------ -/** - Push an object 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. - - @note This works on any type specialized by `Stack`, including `LuaRef` and - its table proxies. -*/ -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) -{ - Security::setHideMetatables (shouldHide); -} +#ifndef LUA_VERSION_NUM +#error "Lua headers must be included prior to LuaBridge ones" +#endif -} -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/extern/LuaBridge/Manual.html b/extern/LuaBridge/Manual.html deleted file mode 100644 index e2a7d0dfd..000000000 --- a/extern/LuaBridge/Manual.html +++ /dev/null @@ -1,1794 +0,0 @@ - - - -LuaBridge 2.0 Reference Manual - - - - - - - - - - - -
-
-

LuaBridge 2.0 Reference Manual

-
-
- - -Official repository is located at -https://github.com/vinniefalco/LuaBridge. -
-Copyright © 2012 Vinnie Falco. Freely available under the terms of the -MIT License. -
- - - - - -
- -

1 - Introduction

- -

-LuaBridge is a -lightweight and dependency-free library for mapping data, functions, and -classes back and forth between C++ and Lua, -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. It also works -transparently with LuaJIT. -

- -

-LuaBridge offers the following features: -

- -
    -
  • MIT Licensed, no usage restrictions!
  • -
  • Headers-only: No Makefile, no .cpp files, just one #include!
  • -
  • Simple, light, and nothing else needed (like Boost).
  • -
  • No macros, settings, or configuration scripts needed.
  • -
  • Supports different object lifetime management models.
  • -
  • Convenient, type-safe access to the Lua stack.
  • -
  • Automatic function parameter type binding.
  • -
  • Easy access to Lua objects like tables and functions.
  • -
  • Written in a clear and easy to debug style.
  • -
  • Does not require C++11.
  • -
- -

-LuaBridge is distributed as a a collection of header files. You simply add -one line, #include "LuaBridge/LuaBridge.h" where you want to -pass functions, classes, and variables back and forth between C++ and Lua. -There are no additional source files, no compilation settings, and no -Makefiles or IDE-specific project files. LuaBridge is easy to integrate. -

- -

-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. -

- -

-To expose Lua objects to C++, a class called LuaRef is provided. -The implementation allows C++ code to access Lua objects such as numbers -or strings, but more importantly to access things like tables and their -values. Using this class makes idioms like calling Lua functions simple -and clean. -

- - - -
- -

1.1 - Design

- -

-LuaBridge tries to be efficient as possible when creating the "glue" that -exposes C++ data and functions to Lua. At the same time, the code was -written with the intention that it is all as simple and clear as possible, -without resorting to obscure C++ idioms, ugly preprocessor macros, or -configuration settings. Furthermore, it is designed to be "header-only", -making it very easy to integrate into your projects. -

- -

-Because LuaBridge was written with simplicity in mind there are some features -that are not available. Although it comes close to the highest possible -performance, LuaBridge is not quite the fastest, -OOLua slightly outperforms -LuaBridge in some tests. LuaBridge also does not try to implement every -possible feature, -LuaBind -explores every corner of the C++ language (but it requires Boost). -

- -

-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. -
- -
- - - -
- -

1.2 - Repository

- -

-The official repository is located at -https://github.com/vinniefalco/LuaBridge. -The branches are organized as follows: -

- - - - - - - - - - - - - - -
masterTagged, stable release versions.
releaseA temporarily created branch that holds a release candidate for review.
developContains work in progress, possibly unfinished or with bugs.
- -

-These repositories are also available: -

- - - - - - - - - - -
LuaBridgeUnitTestsA stand alone command line application to exercise LuaBridge functionality.
LuaBridgeUnitDemoA stand alone GUI application that provides an interactive console.
- -
- - - -
- -

1.3 - License and Credits

- -

-LuaBridge is published under the terms of the -MIT License: -

- -
-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.
-
- -

-The original version of LuaBridge was written by Nathan Reed. The project -has been taken over by Vinnie Falco, who added new functionality and wrote -the new documentation. Vinnie also incorporated LuaRef and -other Lua to C++ binding contributions from Nigel Atkinson. -

- -

-For questions, comments, or bug reports feel free to open a Github issue -or contact Vinnie Falco directly at the email address indicated below. -

- - - -

-Older versions of LuaBridge up to and including 0.2 (available separately) are -distributed under the BSD 3-Clause License. See the corresponding license file -in those versions (distributed separately) for more details. -

- -
- - - -
- -
- -

2 - Accessing C++ from Lua

- -

-In order to expose C++ data and functions to Lua, each piece of exported -information must be registered. There are five types of objects that -LuaBridge can register: -

- - - - - - - - - - - - - - - - - - - - - - -
Namespaces  A Lua table that contains other registrations.
Data  Global or static variables, data members, and static data members.
Functions  Regular functions, member functions, and static member functions.
CFunctions  A regular function, member function, or static member function that - uses the lua_CFunction calling convention.
Properties  Global properties, property members, and static property members. - These appear like data to Lua, but are implemented in C++ using - functions to get and set the values.
- -

-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. -

- - - -
- -

2.1 - 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 ();
-
- -
- - - -
- -

2.2 - 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) { stringProperty = 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 -attempts will generate a run-time error. 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. -

- -
- - - -
- -

2.3 - Class Objects

- -

-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 on it. 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> ("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, A> ("B")
-      .addData ("data", &B::dataMember2)
-      .addFunction ("func1", &B::func1)
-      .addFunction ("func2", &B::func2)
-    .endClass ()
-  .endNameSpace ();
-
- -

-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. -

- -

-Remember that in Lua, the colon operator ':' is used for -method call syntax: -

- -
-local a = A ()
-
-a.func1 () -- Does nothing
-a:func1 () -- Works
-
- -
- - - -
- -

2.4 - 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 allows for 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 <unsigned index>
-  static float get (Vec const* vec)
-  {
-    return vec->coord [index];
-  }
-
-  template <unsigned index>
-  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> ("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 ();
-
- -
- - - -
- -

2.5 - 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> ("A")
-      .addConstructor <void (*) (void)> ()
-    .endClass ()
-    .beginClass <B> ("B")
-      .addConstructor <void (*) (char const*, int)> ()
-    .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
-
- -
- - - -
- -

2.6 - Lua Stack

- -

-In the Lua C API, all operations on the lua_State are performed -through the Lua stack. In order to pass values back and forth between C++ -and Lua, LuaBridge uses specializations of this template class concept: -

- -
-template <class T>
-struct Stack
-{
-  static void push (lua_State* L, T t);
-  static T get (lua_State* L, int index);
-};
-
- -

-When a specialization of Stack exists for a given type -T we say that the T is convertible. -Throughout this document and the LuaBridge API, these types can be used -anywhere a convertible type is expected. -

- -

-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: -

- -
-template <>
-struct Stack <juce::String>
-{
-  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));
-  }
-};
-
- -
- - - -
- -

2.7 - 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 the 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. -

- -
- - - -
- -
- -

3 - Passing Objects

- -

-An object of a registered class T may be passed to Lua as: -

- - - - - - - - - - - - - - - - - - - - - - - - - - -
TPassed by value (a copy), with Lua lifetime.
T constPassed by value (a copy), with Lua lifetime.
T*Passed by reference, with C++ lifetime.
T&Passed by reference, with C++ lifetime.
T const*Passed by const reference, with C++ lifetime.
T const&Passed by const reference, with C++ lifetime.
- - - -
- -

3.1 - 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 <A const*> (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");
-
- -
- - - -
- -

3.2 - 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. -

- -
- - - -
- -

3.3 - 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. -

- -
- - - -
- -

3.4 - 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. -

- - - -
- -

3.4.1 - Class RefCountedObjectPtr

- -

-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 <T>` 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> a; // holds a reference to A
-};
-
-void bar (RefCountedObjectPtr <A> a)
-{
-  a->foo ();
-}
-
- -
- - - -
- -

3.4.2 - Class RefCountedPtr

- -

-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> a;
-};
-
-RefCountedPtr <A> createA ()
-{
-  return new A;
-}
-
-void bar (RefCountedPtr <A> a)
-{
-  a->foo ();
-}
-
-void callFoo ()
-{
-  bar (createA ());
-
-  // The created A will be destroyed
-  // when we leave this scope
-}
-
- -
- - - -
- -

3.4.3 - User-defined 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 <class T>
-struct ContainerTraits <CustomContainer <T> >
-{
-  typedef typename T Type;
-
-  static T* get (CustomContainer <T> 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. -

- -
- - - -
- -

3.4.4 - Container Constructors

- -

-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> ("C")
-      .addConstructor <void (*) (void), RefCountedObjectPtr <C> > ()
-    .endClass ()
-    .beginClass <D> ("D")
-      .addConstructor <void (*) (void), RefCountedPtr <D> > ()
-    .endClass ();
-  .endNamespace ()
-
- -
- - - -
- -
- -

3.5 - 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. -

- -

- - - -
- -

3.6 - Convenience Functions

- -

-The setGlobal function can be used to assign any convertible -value into a global variable. -

- -
- - - -
- -
- -

4 - Accessing Lua from C++

- -

-Because Lua is a dynamically typed language, special consideration -is required to map values in Lua to C++. The following sections describe the -classes and functions used for representing Lua types. Only the essential -operations are explained; To gain understanding of all available functions, -please refer to the documentation comments in the corresponding source files. -

- - - -
- -

4.1 - Class LuaRef

- -

-The LuaRef class is a container which references any Lua type. -It can hold anything which a Lua variable can hold: nil, -number, boolean, string, table, function, thread, userdata, and -lightuserdata. Because LuaRef uses the Stack -template specializations to do its work, classes, functions, and data -exported to Lua through namespace registrations can also be stored (these -are instances of userdata). In general, a LuaRef can represent -any convertible C++ type as well as all Lua types. -

- -

-A LuaRef variable constructed with no parameters produces a -reference to nil: -

- -
-LuaRef v (L); // References nil
-
- -

-To construct a LuaRef to a specific value, the two parameter -constructor is used: -

- -
-LuaRef v1 (L, 1);                   // A LUA_TNUMBER
-LuaRef v2 (L, 1.1);                 // Also a LUA_TNUMBER
-LuaRef v3 (L, true);                // A LUA_TBOOLEAN
-LuaRef v4 (L, "string");            // A LUA_TSTRING
-
- -

-The functions newTable and getGlobal create -references to new empty table and an existing value in the global table -respectively: -

- -
-LuaRef v1 = newTable (L);           // Create a new table
-LuaRef v2 = getGlobal (L, "print")  // Reference to _G ["print"]
-
- -

-A LuaRef can hold classes registered using LuaBridge: -

- -
-class A;
-//...
-LuaRef v (L, new A); // A LuaBridge userdata holding a pointer to A
-
- -

-Any convertible type may be assigned to an already-existing LuaRef: -

- -
-LuaRef v (L);         // Nil
-v = newTable (L);     // An empty table
-v = "string"          // A string. The prevous value becomes
-                      // eligible for garbage collection.
-
- -

-A LuaRef is itself a convertible type, and the convertible -type Nil can be used to represent a Lua nil. -

- -
-LuaRef v1 (L, "x");   // assign "x"
-LuaRef v2 (L, "y");   // assign "y"
-v2 = v1;              // v2 becomes "x"
-v1 = "z";             // v1 becomes "z", v2 is unchanged
-v1 = newTable (L);    // An empty table
-v2 = v1;              // v2 references the same table as v1
-v1 = Nil ();          // v1 becomes nil, table is still
-                      // referenced by v2.
-
- -

-Values stored in a LuaRef object obey the same rules as -variables in Lua: tables, functions, threads, and full userdata values are -objects. The LuaRef does not actually contain -these values, only references to them. Assignment, parameter -passing, and function returns always manipulate references to such values; -these operations do not imply any kind of copy. -

- - - -
- -

4.1.1 - Type Conversions

- -

-A universal C++ conversion operator is provided for implicit conversions -which allow a LuaRef to be used where any convertible type is -expected. These operations will all compile: -

- -
-void passInt (int);
-void passBool (bool);
-void passString (std::string);
-void passObject (A*);
-
-LuaRef v (L);
-//...
-passInt (v);        // implicit conversion to int
-passBool (v);       // implicit conversion to bool
-passString (v);     // implicit conversion to string
-passObject (v);     // must hold a registered LuaBridge class or a
-                    // lua_error() will be called.
-
- -

-Since Lua types are dynamic, the conversion is performed at run time using -traditional functions like lua_toboolean or -lua_tostring. In some cases, the type information may be -incorrect especially when passing objects of registered class types. -When performing these conversions, LuaBridge may raise a Lua error by -directly or indirectly calling lua_error To be bullet-proof, -such code must either be wrapped in a lua_pcall, or you must -install a Lua panic function that throws an exception which you -can catch. -

- -

-When an explicit conversion is required (such as when writing templates), -use the cast template function or an explicit C++ style cast. -

- -
-void passString (std::string);
-
-LuaRef v (L);
-
-// The following are all equivalent:
-
-passString (std::string (v));
-passString ((std::string)v);
-passString (static_cast <std::string> (v));
-passString (v.cast <std::string> ());
-
- -
- - - -
- -

4.1.2 - Visual Studio 2010, 2012

- -

-There is a defect with all versions of Visual Studio up to and including -Visual Studio 2012 which prevents the implicit conversion operator from -being applied when it is used as an operand in a boolean operator: -

- -
-LuaRef v1 (L);
-LuaRef v2 (L);
-
-if (v1 || v2) { } // Compile error in Visual Studio
-
-// Work-arounds:
-if (v1.cast <bool> () || v2.cast <bool> ()) { }
-if (bool (v1) || bool (v2)) { }
-
- -
- - - -
- -
- -

4.2 - Table Proxies

- -

-As tables are the sole data structuring mechanism in Lua, the -LuaRef class provides robust facilities for accessing and -manipulating table elements using a simple, precise syntax. Any convertible -type may be used as a key or value. Applying the array indexing operator -[] to a LuaRef returns a special temporary object -called a table proxy which supports all the operations which can -be performed on a LuaRef. In addition, assignments made to -table proxies change the underlying table. Because table proxies are -compiler-created temporary objects, you don't work with them directly. A -LuaBridge table proxy should not be confused with the Lua proxy table -technique described in the book "Programming in Lua"; the LuaBridge table -proxy is simply an intermediate C++ class object that works behind the -scenes to make table manipulation syntax conform to C++ idioms. These -operations all invoke table proxies: -

- -
-LuaRef v (L);
-v = newTable (L);
-
-v ["name"] = "John Doe";      // string key, string value
-v [1] = 200;                  // integer key, integer value
-v [2] = newTable (L);         // integer key, LuaRef value
-v [3] = v [1];                // assign 200 to integer index 3
-v [1] = 100;                  // v[1] is 100, v[3] is still 200
-v [3] = v [2];                // v[2] and v[3] reference the same table
-v [2] = Nil ();               // Removes the value with key = 2. The table
-                              //   is still referenced by v[3].
-
- -
- - - -
- -

4.3 - Calling Lua

- -

-Table proxies and LuaRef objects provide a convenient syntax -for invoking lua_pcall on suitable referenced object. This -includes C functions, Lua functions, or Lua objects with an appropriate -__call metamethod set. The provided implementation supports -up to eight parameters (although more can be supported by adding new -functions). Any convertible C++ type can be passed as a parameter in its -native format. The return value of the function call is provided as a -LuaRef, which may be nil. -

- -
-LuaRef same = getGlobal (L, "same");
-
-// These all evaluate to true
-same (1,1);
-!same (1,2);
-same ("text", "text");
-!same (1, "text");
-same (1, 1, 2); // third param ignored
-
- -
-function same (arg1, arg)
-  return arg1 == arg2
-end
-
- -

-Table proxies support all of the Lua call notation that LuaRef -supports, making these statements possible: -

- -
-LuaRef v = getGlobal (L, "t");
-
-t[1]();
-t[2]("a", "b");
-t[2](t[1]); // Call t[3] with the value in t[2]
-t[4]=t[3]();   // Call t[3] and store the result in t[4].
-
-t [t[5]()] = "wow"; // Store "wow" at the key returned by
-                    //   the call to t[5]
-
- -
-t = {}
-t[1] = function () print ("hello") end
-t[2] = function (u, v) print (u, v) end
-t[3] = "foo"
-
- - - -

4.3.1 - Class LuaException

- -
- -

-When LuaRef is used to call into Lua using the () -operator it issues a protected call using lua_pcall. LuaBridge -uses the C++ exception handling mechanism, throwing a LuaException -object: -

- -
-LuaRef f (L) = getGlobal (L, "fail");
-
-try {
-  f ();
-}
-catch (LuaException const& e) {
-  std::cerr && e.what ();
-}
-
- -
-function fail ()
-  error ("A problem occurred")
-end
-
- -
- - - -
- - - -
- -
- -

5 - 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. -

- -
- - - - - - diff --git a/extern/LuaBridge/Map.h b/extern/LuaBridge/Map.h new file mode 100644 index 000000000..771ede469 --- /dev/null +++ b/extern/LuaBridge/Map.h @@ -0,0 +1,55 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + typedef std::map Map; + + static void push(lua_State* L, const Map& map) + { + lua_createtable (L, 0, static_cast (map.size ())); + typedef typename Map::const_iterator ConstIter; + for (ConstIter i = map.begin(); i != map.end(); ++i) + { + Stack ::push (L, i->first); + Stack ::push (L, i->second); + lua_settable (L, -3); + } + } + + static Map get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + { + luaL_error(L, "#%d argments must be table", index); + } + + Map map; + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + map.emplace (Stack ::get (L, -2), Stack ::get (L, -1)); + lua_pop (L, 1); + } + return map; + } +}; + +template +struct Stack const&> : Stack > +{ +}; + +} // namespace luabridge diff --git a/extern/LuaBridge/RefCountedObject.h b/extern/LuaBridge/RefCountedObject.h index 807b4606c..ebc749e3c 100644 --- a/extern/LuaBridge/RefCountedObject.h +++ b/extern/LuaBridge/RefCountedObject.h @@ -36,13 +36,16 @@ */ //============================================================================== -#ifndef LUABRIDGE_REFCOUNTEDOBJECT_HEADER -#define LUABRIDGE_REFCOUNTEDOBJECT_HEADER +#pragma once //#define LUABRIDGE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 +#include + #include +namespace luabridge { + //============================================================================== /** Adds reference-counting to an object. @@ -337,13 +340,6 @@ bool operator!= (ReferenceCountedObjectClass* object1, RefCountedObjectPtr -struct ContainerTraits; - template struct ContainerTraits > { @@ -355,9 +351,6 @@ struct ContainerTraits > } }; -} - //============================================================================== -#endif - +} // namespace luabridge diff --git a/extern/LuaBridge/RefCountedPtr.h b/extern/LuaBridge/RefCountedPtr.h index 7c27ca4dc..4db103f5a 100644 --- a/extern/LuaBridge/RefCountedPtr.h +++ b/extern/LuaBridge/RefCountedPtr.h @@ -2,6 +2,7 @@ /* https://github.com/vinniefalco/LuaBridge + Copyright 2019, Dmitry Tarakanov Copyright 2012, Vinnie Falco Copyright 2007, Nathan Reed @@ -27,15 +28,12 @@ */ //============================================================================== -#ifndef LUABRIDGE_REFCOUNTEDPTR_HEADER -#define LUABRIDGE_REFCOUNTEDPTR_HEADER +#pragma once -#ifdef _MSC_VER -# include -#else -# include -# include -#endif +#include +#include "RefCountedObject.h" + +namespace luabridge { //============================================================================== /** @@ -44,22 +42,10 @@ 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 + typedef std::unordered_map RefCountsType; protected: - inline RefCountsType& getRefCounts () + RefCountsType& getRefCounts () const { static RefCountsType refcounts; return refcounts ; @@ -226,10 +212,19 @@ private: T* m_p; }; -//============================================================================== +template +bool operator== (const RefCountedPtr & lhs, const RefCountedPtr & rhs) +{ + return lhs.get () == rhs.get (); +} -namespace luabridge +template +bool operator!= (const RefCountedPtr & lhs, const RefCountedPtr & rhs) { + return lhs.get() != rhs.get(); +} + +//============================================================================== // forward declaration template @@ -246,6 +241,4 @@ struct ContainerTraits > } }; -} - -#endif +} // namespace luabridge diff --git a/extern/LuaBridge/Vector.h b/extern/LuaBridge/Vector.h new file mode 100644 index 000000000..d37f8286b --- /dev/null +++ b/extern/LuaBridge/Vector.h @@ -0,0 +1,54 @@ +// https://github.com/vinniefalco/LuaBridge +// +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack > +{ + static void push(lua_State* L, std::vector const& vector) + { + lua_createtable (L, static_cast (vector.size ()), 0); + for (std::size_t i = 0; i < vector.size (); ++i) + { + lua_pushinteger (L, static_cast (i + 1)); + Stack ::push (L, vector [i]); + lua_settable (L, -3); + } + } + + static std::vector get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + { + luaL_error(L, "#%d argments must be table", index); + } + + std::vector vector; + vector.reserve (static_cast (get_length (L, index))); + + int const absindex = lua_absindex (L, index); + lua_pushnil (L); + while (lua_next (L, absindex) != 0) + { + vector.push_back (Stack ::get (L, -1)); + lua_pop (L, 1); + } + return vector; + } +}; + +template +struct Stack const&> : Stack > +{ +}; + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/CFunctions.h b/extern/LuaBridge/detail/CFunctions.h index 0497b6bb4..ae7cf4ab3 100644 --- a/extern/LuaBridge/detail/CFunctions.h +++ b/extern/LuaBridge/detail/CFunctions.h @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ /* https://github.com/vinniefalco/LuaBridge - + Copyright 2012, Vinnie Falco License: The MIT License (http://www.opensource.org/licenses/mit-license.php) @@ -26,6 +26,12 @@ */ //============================================================================== +#pragma once + +#include + +namespace luabridge { + // We use a structure so we can define everything in the header. // struct CFunc @@ -138,7 +144,7 @@ struct CFunc { assert (lua_isnil (L, -1)); lua_pop (L, 2); - result = luaL_error (L,"no writable variable '%s'", lua_tostring (L, 2)); + result = luaL_error (L, "no writable variable '%s'", lua_tostring (L, 2)); } } @@ -154,12 +160,12 @@ struct CFunc 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 ()); } - + //---------------------------------------------------------------------------- /** lua_CFunction to get a variable. @@ -206,8 +212,8 @@ struct CFunc The function pointer is in the first upvalue. */ template ::ReturnType> - struct Call + class ReturnType = typename FuncTraits ::ReturnType> + struct Call { typedef typename FuncTraits ::Params Params; static int f (lua_State* L) @@ -253,8 +259,8 @@ struct CFunc The class userdata object is at the top of the Lua stack. */ template ::ReturnType> - struct CallMember + class ReturnType = typename FuncTraits ::ReturnType> + struct CallMember { typedef typename FuncTraits ::ClassType T; typedef typename FuncTraits ::Params Params; @@ -272,8 +278,8 @@ struct CFunc }; template ::ReturnType> - struct CallConstMember + class ReturnType = typename FuncTraits ::ReturnType> + struct CallConstMember { typedef typename FuncTraits ::ClassType T; typedef typename FuncTraits ::Params Params; @@ -284,7 +290,7 @@ struct CFunc T const* const t = Userdata::get (L, 1, true); MemFnPtr const& fnptr = *static_cast (lua_touserdata (L, lua_upvalueindex (1))); assert (fnptr != 0); - ArgList args(L); + ArgList args (L); Stack ::push (L, FuncTraits ::call (t, fnptr, args)); return 1; } @@ -440,3 +446,5 @@ struct CFunc return 0; } }; + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/ClassInfo.h b/extern/LuaBridge/detail/ClassInfo.h index 8d5806947..9a86e549b 100644 --- a/extern/LuaBridge/detail/ClassInfo.h +++ b/extern/LuaBridge/detail/ClassInfo.h @@ -26,6 +26,10 @@ */ //============================================================================== +#pragma once + +namespace luabridge { + /** Unique Lua registry keys for a class. Each registered class inserts three keys into the registry, whose @@ -71,3 +75,4 @@ public: } }; +} // namespace luabridge diff --git a/extern/LuaBridge/detail/Constructor.h b/extern/LuaBridge/detail/Constructor.h index 7b2dad059..04b3dab03 100644 --- a/extern/LuaBridge/detail/Constructor.h +++ b/extern/LuaBridge/detail/Constructor.h @@ -27,8 +27,9 @@ */ //============================================================================== -#ifndef LUABRIDGE_CONSTRUCTOR_HEADER -#define LUABRIDGE_CONSTRUCTOR_HEADER +#pragma once + +namespace luabridge { /* * Constructor generators. These templates allow you to call operator new and @@ -201,4 +202,4 @@ struct Constructor } }; +/* Windows: WINAPI (a.k.a. __stdcall) function pointers. */ + +#ifdef _M_IX86 // Windows 32bit only + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef None Params; + static R call (D fp, TypeListValues ) + { + return fp (); + } +}; + +template +struct FuncTraits +{ + static bool const isMemberFunction = false; + typedef D DeclType; + typedef R ReturnType; + typedef TypeList Params; + static R call (D 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 (D 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 (D 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 (D 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 (D 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 (D 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 (D 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 (D 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); + } +}; + +#endif // _M_IX86 + /* Non-const member function pointers. */ template @@ -850,3 +977,5 @@ struct FuncTraits + +#include + +namespace luabridge { + /** Allows table iteration. */ class Iterator @@ -38,29 +46,32 @@ private: void next () { - m_table.push(m_L); - m_key.push (m_L); + m_table.push (); + m_key.push (); if (lua_next (m_L, -2)) { - m_value.pop (m_L); - m_key.pop (m_L); + m_value.pop (); + m_key.pop (); } else { - m_key = Nil(); - m_value = Nil(); + m_key = Nil (); + m_value = Nil (); } - lua_pop(m_L, 1); + lua_pop (m_L, 1); } public: - explicit Iterator (LuaRef table) + explicit Iterator (const LuaRef& table, bool isEnd = false) : m_L (table.state ()) , m_table (table) , m_key (table.state ()) // m_key is nil , m_value (table.state ()) // m_value is nil { - next (); // get the first (key, value) pair from table + if (!isEnd) + { + next (); // get the first (key, value) pair from table + } } lua_State* state () const @@ -68,9 +79,9 @@ public: return m_L; } - LuaRef operator* () const + std::pair operator* () const { - return m_value; + return std::make_pair (m_key, m_value); } LuaRef operator-> () const @@ -78,6 +89,12 @@ public: return m_value; } + bool operator!= (const Iterator& rhs) const + { + assert (m_L == rhs.m_L); + return !m_table.rawequal (rhs.m_table) || !m_key.rawequal (rhs.m_key); + } + Iterator& operator++ () { if (isNil()) @@ -92,17 +109,17 @@ public: } } - inline bool isNil () const + bool isNil () const { return m_key.isNil (); } - inline LuaRef key () const + LuaRef key () const { return m_key; } - inline LuaRef value () const + LuaRef value () const { return m_value; } @@ -112,3 +129,25 @@ private: Iterator operator++ (int); }; +class Range +{ + Iterator m_begin; + Iterator m_end; + +public: + Range (const Iterator& begin, const Iterator& end) + : m_begin (begin) + , m_end (end) + { + } + + const Iterator& begin () const { return m_begin; } + const Iterator& end () const { return m_end; } +}; + +inline Range pairs(const LuaRef& table) +{ + return Range (Iterator (table, false), Iterator (table, true)); +} + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/LuaException.h b/extern/LuaBridge/detail/LuaException.h index a0944961c..6ca98182a 100644 --- a/extern/LuaBridge/detail/LuaException.h +++ b/extern/LuaBridge/detail/LuaException.h @@ -27,6 +27,13 @@ */ //============================================================================== +#pragma once + +#include +#include + +namespace luabridge { + class LuaException : public std::exception { private: @@ -111,3 +118,5 @@ protected: } } }; + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/LuaHelpers.h b/extern/LuaBridge/detail/LuaHelpers.h index 7bc84eb16..e336cf2b2 100644 --- a/extern/LuaBridge/detail/LuaHelpers.h +++ b/extern/LuaBridge/detail/LuaHelpers.h @@ -27,6 +27,12 @@ */ //============================================================================== +#pragma once + +#include + +namespace luabridge { + // These are for Lua versions prior to 5.2.0. // #if LUA_VERSION_NUM < 502 @@ -141,3 +147,5 @@ inline bool equalstates (lua_State* L1, lua_State* L2) return lua_topointer (L1, LUA_REGISTRYINDEX) == lua_topointer (L2, LUA_REGISTRYINDEX); } + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/LuaRef.h b/extern/LuaBridge/detail/LuaRef.h index e726bcafe..50e497ed9 100644 --- a/extern/LuaBridge/detail/LuaRef.h +++ b/extern/LuaBridge/detail/LuaRef.h @@ -1,7 +1,8 @@ //------------------------------------------------------------------------------ /* https://github.com/vinniefalco/LuaBridge - + + Copyright 2018, Dmitry Tarakanov Copyright 2012, Vinnie Falco Copyright 2008, Nigel Atkinson @@ -27,6 +28,18 @@ */ //============================================================================== +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace luabridge { + //------------------------------------------------------------------------------ /** Type tag for representing LUA_TNIL. @@ -42,18 +55,27 @@ struct Nil { }; + //------------------------------------------------------------------------------ /** - Lightweight reference to a Lua object. - - The reference is maintained for the lifetime of the C++ object. + Stack specialization for Nil. */ -class LuaRef +template <> +struct Stack { -private: - class Proxy; - friend struct Stack ; + static void push (lua_State* L, Nil) + { + lua_pushnil (L); + } +}; +/** + * Base class for LuaRef and table value proxy classes. + */ +template +class LuaRefBase +{ +protected: //---------------------------------------------------------------------------- /** Pop the Lua stack. @@ -95,1042 +117,854 @@ private: int m_count; }; + friend struct Stack ; + //---------------------------------------------------------------------------- /** - A proxy for representing table values. + Type tag for stack construction. */ - class Proxy - { - private: - lua_State* m_L; - int m_tableRef; - int m_keyRef; - - public: - //-------------------------------------------------------------------------- - /** - Construct a Proxy from a table value. - - The table is in the registry, and the key is at the top of the stack. - The key is popped off the stack. - */ - Proxy (lua_State* L, int tableRef) - : m_L (L) - , m_tableRef (tableRef) - , m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX)) - { - } + struct FromStack { }; - //-------------------------------------------------------------------------- - /** - Create a Proxy via copy constructor. + LuaRefBase (lua_State* L) + : m_L (L) + { + } - It is best to avoid code paths that invoke this, because it creates - an extra temporary Lua reference. Typically this is done by passing - the Proxy parameter as a `const` reference. - */ - Proxy (Proxy const& other) - : m_L (other.m_L) - , m_tableRef (other.m_tableRef) - { - // If this assert goes off it means code is taking this path, - // which is better avoided. - // - assert (0); + //---------------------------------------------------------------------------- + /** + Create a reference to this ref. - lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef); - m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX); - } + This is used internally. + */ + int createRef () const + { + impl ().push (); + return luaL_ref (m_L, LUA_REGISTRYINDEX); + } - //-------------------------------------------------------------------------- - /** - Destroy the proxy. +public: + //---------------------------------------------------------------------------- + /** + converts to a string using luas tostring function + */ + std::string tostring() const + { + lua_getglobal (m_L, "tostring"); + impl ().push (); + lua_call (m_L, 1, 1); + const char* str = lua_tostring (m_L, -1); + lua_pop (m_L, 1); + return std::string(str); + } - This does not destroy the table value. - */ - ~Proxy () - { - luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef); - } + //---------------------------------------------------------------------------- + /** + Print a text description of the value to a stream. - //-------------------------------------------------------------------------- - /** - Return a reference to the table value. - */ - int createRef () const + This is used for diagnostics. + */ + void print (std::ostream& os) const + { + switch (type ()) { - push (m_L); - return luaL_ref (m_L, LUA_REGISTRYINDEX); - } + case LUA_TNIL: + os << "nil"; + break; - //-------------------------------------------------------------------------- - /** - Assign a new value to this table key. + case LUA_TNUMBER: + os << cast (); + break; - This may invoke metamethods. - */ - template - Proxy& operator= (T v) - { - StackPop p (m_L, 1); - lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); - lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); - Stack ::push (m_L, v); - lua_rawset (m_L, -3); - return *this; - } + case LUA_TBOOLEAN: + os << (cast () ? "true" : "false"); + break; - //-------------------------------------------------------------------------- - /** - Assign a new value to this table key. + case LUA_TSTRING: + os << '"' << cast () << '"'; + break; - The assignment is raw, no metamethods are invoked. - */ - template - Proxy& rawset (T v) - { - StackPop p (m_L, 1); - lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); - lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); - Stack ::push (m_L, v); - lua_settable (m_L, -3); - return *this; - } + case LUA_TTABLE: + os << "table: " << tostring(); + break; - //========================================================================== - // - // This group of member functions mirrors the member functions in LuaRef. + case LUA_TFUNCTION: + os << "function: " << tostring(); + break; - /** Retrieve the lua_State associated with the table value. - */ - lua_State* state () const - { - return m_L; - } + case LUA_TUSERDATA: + os << "userdata: " << tostring(); + break; - //-------------------------------------------------------------------------- - /** - Push the value onto the Lua stack. - */ - void push (lua_State* L) const - { - assert (equalstates (L, m_L)); - lua_rawgeti (L, LUA_REGISTRYINDEX, m_tableRef); - lua_rawgeti (L, LUA_REGISTRYINDEX, m_keyRef); - lua_gettable (L, -2); - lua_remove (L, -2); // remove the table - } + case LUA_TTHREAD: + os << "thread: " << tostring(); + break; - //-------------------------------------------------------------------------- - /** - Determine the object type. + case LUA_TLIGHTUSERDATA: + os << "lightuserdata: " << tostring(); + break; - The return values are the same as for `lua_type`. - */ - int type () const - { - int result; - push (m_L); - result = lua_type (m_L, -1); - lua_pop (m_L, 1); - return result; + default: + os << "unknown"; + break; } + } - inline bool isNil () const { return type () == LUA_TNIL; } - inline bool isNumber () const { return type () == LUA_TNUMBER; } - inline bool isString () const { return type () == LUA_TSTRING; } - inline bool isTable () const { return type () == LUA_TTABLE; } - inline bool isFunction () const { return type () == LUA_TFUNCTION; } - inline bool isUserdata () const { return type () == LUA_TUSERDATA; } - inline bool isThread () const { return type () == LUA_TTHREAD; } - inline bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; } + //------------------------------------------------------------------------------ + /** + Write a LuaRef to a stream. - //-------------------------------------------------------------------------- - /** - Perform an explicit conversion. - */ - template - T cast () const - { - StackPop p (m_L, 1); - push (m_L); + This allows LuaRef and table proxies to work with streams. + */ + friend std::ostream& operator<< (std::ostream& os, LuaRefBase const& ref) + { + ref.print (os); + return os; + } - // lua_gettop is used because Userdata::getClass() doesn't handle - // negative stack indexes. - // - return Stack ::get (m_L, lua_gettop (m_L)); - } + //============================================================================ + // + // This group of member functions is mirrored in Proxy + // - //-------------------------------------------------------------------------- - /** - Universal implicit conversion operator. - - NOTE: Visual Studio 2010 and 2012 have a bug where this function - is not used. See: - - http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014 - https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile - - // This code snippet fails to compile in vs2010,vs2012 - struct S { - template inline operator T () const { return T (); } - }; - int main () { - S () || false; - return 0; - } - */ - template - inline operator T () const - { - return cast (); - } + /** Retrieve the lua_State associated with the reference. + */ + lua_State* state () const + { + return m_L; + } - //-------------------------------------------------------------------------- - /** - Universal comparison operators. - */ - /** @{ */ - template - bool operator== (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; - } + //---------------------------------------------------------------------------- + /** + Place the object onto the Lua stack. + */ + void push (lua_State* L) const + { + assert (equalstates (L, m_L)); + (void) L; + impl ().push (); + } - template - bool operator< (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -2, -1, LUA_OPLT) == 1; - } + //---------------------------------------------------------------------------- + /** + Pop the top of Lua stack and assign the ref to m_ref + */ + void pop (lua_State* L) + { + assert (equalstates (L, m_L)); + (void) L; + impl ().pop (); + } - template - bool operator<= (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -2, -1, LUA_OPLE) == 1; - } + //---------------------------------------------------------------------------- + /** + Determine the object type. - template - bool operator> (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -1, -2, LUA_OPLT) == 1; - } + The return values are the same as for `lua_type`. + */ + /** @{ */ + int type () const + { + impl ().push (); + StackPop p (m_L, 1); + return lua_type (m_L, -1); + } - template - bool operator>= (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -1, -2, LUA_OPLE) == 1; - } + // should never happen + // bool isNone () const { return m_ref == LUA_NOREF; } + + bool isNil () const { return type () == LUA_TNIL; } + bool isBool () const { return type () == LUA_TBOOLEAN; } + bool isNumber () const { return type () == LUA_TNUMBER; } + bool isString () const { return type () == LUA_TSTRING; } + bool isTable () const { return type () == LUA_TTABLE; } + bool isFunction () const { return type () == LUA_TFUNCTION; } + bool isUserdata () const { return type () == LUA_TUSERDATA; } + bool isThread () const { return type () == LUA_TTHREAD; } + bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; } - template - bool rawequal (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_rawequal (m_L, -1, -2) == 1; - } - /** @} */ - - //-------------------------------------------------------------------------- - /** - Access a table value using a key. - - This invokes metamethods. - */ - template - Proxy operator[] (T key) const - { - return LuaRef (*this) [key]; - } - - //-------------------------------------------------------------------------- - /** - Access a table value using a key. - - The operation is raw, metamethods are not invoked. The result is - passed by value and may not be modified. - */ - template - LuaRef rawget (T key) const - { - StackPop (m_L, 1); - push (m_L); - Stack ::push (m_L, key); - lua_rawget (m_L, -2); - return LuaRef (m_L, FromStack ()); - } - - //-------------------------------------------------------------------------- - /** - Append a value to the table. - - If the table is a sequence this will add another element to it. - */ - template - void append (T v) const - { - push (m_L); - Stack ::push (m_L, v); - luaL_ref (m_L, -2); - lua_pop (m_L, 1); - } - - //-------------------------------------------------------------------------- - /** - Call the length operator. - - This is identical to applying the Lua # operator. - */ - int length () const - { - StackPop p (m_L, 1); - push (m_L); - return get_length (m_L, -1); - } - - //-------------------------------------------------------------------------- - /** - Call Lua code. - - These overloads allow Lua code to be called with up to 8 parameters. - The return value is provided as a LuaRef (which may be LUA_REFNIL). - If an error occurs, a LuaException is thrown. - */ - /** @{ */ - LuaRef const operator() () const - { - push (m_L); - LuaException::pcall (m_L, 0, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1) const - { - push (m_L); - Stack ::push (m_L, p1); - LuaException::pcall (m_L, 1, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - LuaException::pcall (m_L, 2, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - LuaException::pcall (m_L, 3, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - LuaException::pcall (m_L, 4, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - LuaException::pcall (m_L, 5, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - Stack ::push (m_L, p6); - LuaException::pcall (m_L, 6, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - Stack ::push (m_L, p6); - Stack ::push (m_L, p7); - LuaException::pcall (m_L, 7, 1); - return LuaRef (m_L, FromStack ()); - } - - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - Stack ::push (m_L, p6); - Stack ::push (m_L, p7); - Stack ::push (m_L, p8); - LuaException::pcall (m_L, 8, 1); - return LuaRef (m_L, FromStack ()); - } - /** @} */ - - //========================================================================== - }; - -private: - friend struct Stack ; + /** @} */ //---------------------------------------------------------------------------- /** - Type tag for stack construction. + Perform an explicit conversion. */ - struct FromStack { }; + template + T cast () const + { + StackPop p (m_L, 1); + impl ().push (); + + // lua_gettop is used because Userdata::getClass() doesn't handle + // negative stack indexes. + // + return Stack ::get (m_L, lua_gettop (m_L)); + } //---------------------------------------------------------------------------- /** - Create a reference to an object at the top of the Lua stack and pop it. + Universal implicit conversion operator. - This constructor is private and not invoked directly. - Instead, use the `fromStack` function. + NOTE: Visual Studio 2010 and 2012 have a bug where this function + is not used. See: - @note The object is popped. + http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014 + https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile + + // This code snippet fails to compile in vs2010,vs2012 + struct S { + template operator T () const { return T (); } + }; + int main () { + S () || false; + return 0; + } */ - LuaRef (lua_State* L, FromStack) - : m_L (L) + template + operator T () const { - m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); + return cast (); } //---------------------------------------------------------------------------- /** - Create a reference to an object on the Lua stack. - - This constructor is private and not invoked directly. - Instead, use the `fromStack` function. - - @note The object is not popped. + Universal comparison operators. */ - LuaRef (lua_State* L, int index, FromStack) - : m_L (L) + /** @{ */ + template + bool operator== (T rhs) const { - lua_pushvalue (m_L, index); - m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); + StackPop p (m_L, 2); + impl ().push (); + Stack ::push (m_L, rhs); + return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; } - //---------------------------------------------------------------------------- - - // This type of construction is disallowed, since we don't have a `lua_State`. - // template - LuaRef (T) + bool operator< (T rhs) const { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) + { + return lhsType < rhsType; + } + return lua_compare (m_L, -2, -1, LUA_OPLT) == 1; } - //---------------------------------------------------------------------------- - /** - Create a reference to this ref. - - This is used internally. - */ - int createRef () const + template + bool operator<= (T rhs) const { - if (m_ref != LUA_REFNIL) + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) { - push (m_L); - return luaL_ref (m_L, LUA_REGISTRYINDEX); + return lhsType <= rhsType; } - else + return lua_compare (m_L, -2, -1, LUA_OPLE) == 1; + } + + template + bool operator> (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) { - return LUA_REFNIL; + return lhsType > rhsType; } + return lua_compare (m_L, -1, -2, LUA_OPLT) == 1; } -public: - //---------------------------------------------------------------------------- - /** - Create a nil reference. + template + bool operator>= (T rhs) const + { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + int lhsType = lua_type (m_L, -2); + int rhsType = lua_type (m_L, -1); + if (lhsType != rhsType) + { + return lhsType >= rhsType; + } + return lua_compare (m_L, -1, -2, LUA_OPLE) == 1; + } - The LuaRef may be assigned later. - */ - LuaRef (lua_State* L) - : m_L (L) - , m_ref (LUA_REFNIL) + template + bool rawequal (T rhs) const { + StackPop p (m_L, 2); + impl ().push ();; + Stack ::push (m_L, rhs); + return lua_rawequal (m_L, -1, -2) == 1; } + /** @} */ //---------------------------------------------------------------------------- /** - Create a reference to a value. + Append a value to the table. + + If the table is a sequence this will add another element to it. */ template - LuaRef (lua_State* L, T v) - : m_L (L) + void append (T v) const { + impl ().push ();; Stack ::push (m_L, v); - m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); + luaL_ref (m_L, -2); + lua_pop (m_L, 1); } //---------------------------------------------------------------------------- /** - Create a reference to a table value. + Call the length operator. + + This is identical to applying the Lua # operator. */ - LuaRef (Proxy const& v) - : m_L (v.state ()) - , m_ref (v.createRef ()) + int length () const { + StackPop p (m_L, 1); + impl ().push ();; + return get_length (m_L, -1); } //---------------------------------------------------------------------------- /** - Create a new reference to an existing reference. + Call Lua code. + + These overloads allow Lua code to be called with up to 8 parameters. + The return value is provided as a LuaRef (which may be LUA_REFNIL). + If an error occurs, a LuaException is thrown. */ - LuaRef (LuaRef const& other) - : m_L (other.m_L) - , m_ref (other.createRef ()) + /** @{ */ + LuaRef operator() () const { + impl ().push ();; + LuaException::pcall (m_L, 0, 1); + return LuaRef::fromStack (m_L); } - //---------------------------------------------------------------------------- - /** - Destroy a reference. - - The corresponding Lua registry reference will be released. - - @note If the state refers to a thread, it is the responsibility of the - caller to ensure that the thread still exists when the LuaRef - is destroyed. - */ - ~LuaRef () + template + LuaRef operator() (P1 p1) const { - luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); + impl ().push ();; + Stack ::push (m_L, p1); + LuaException::pcall (m_L, 1, 1); + return LuaRef::fromStack (m_L); } - //---------------------------------------------------------------------------- - /** - Return a LuaRef from a stack item. - - The stack item is not popped. - */ - static LuaRef fromStack (lua_State* L, int index) + template + LuaRef operator() (P1 p1, P2 p2) const { - lua_pushvalue (L, index); - return LuaRef (L, FromStack ()); + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + LuaException::pcall (m_L, 2, 1); + return LuaRef::fromStack (m_L); } - //---------------------------------------------------------------------------- - /** - Create a new empty table and return a reference to it. - - It is also possible to use the free function `newTable`. + template + LuaRef operator() (P1 p1, P2 p2, P3 p3) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + LuaException::pcall (m_L, 3, 1); + return LuaRef::fromStack (m_L); + } - @see ::getGlobal - */ - static LuaRef newTable (lua_State* L) + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4) const { - lua_newtable (L); - return LuaRef (L, FromStack ()); + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + LuaException::pcall (m_L, 4, 1); + return LuaRef::fromStack (m_L); } - //---------------------------------------------------------------------------- - /** - Return a reference to a named global. + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + LuaException::pcall (m_L, 5, 1); + return LuaRef::fromStack (m_L); + } - It is also possible to use the free function `getGlobal`. + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const + { + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + LuaException::pcall (m_L, 6, 1); + return LuaRef::fromStack (m_L); + } - @see ::getGlobal - */ - static LuaRef getGlobal (lua_State *L, char const* name) + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const { - lua_getglobal (L, name); - return LuaRef (L, FromStack ()); + impl ().push ();; + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + Stack ::push (m_L, p7); + LuaException::pcall (m_L, 7, 1); + return LuaRef::fromStack (m_L); } - //---------------------------------------------------------------------------- - /** - Assign a different value to this LuaRef. - */ - template - LuaRef& operator= (T rhs) + template + LuaRef operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const { - luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); - Stack ::push (m_L, rhs); - m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); - return *this; + impl ().push (); + Stack ::push (m_L, p1); + Stack ::push (m_L, p2); + Stack ::push (m_L, p3); + Stack ::push (m_L, p4); + Stack ::push (m_L, p5); + Stack ::push (m_L, p6); + Stack ::push (m_L, p7); + Stack ::push (m_L, p8); + LuaException::pcall (m_L, 8, 1); + return LuaRef::fromStack (m_L); } + /** @} */ - //---------------------------------------------------------------------------- - /** - Assign another LuaRef to this LuaRef. - */ - LuaRef& operator= (LuaRef const& rhs) + //============================================================================ + +protected: + lua_State* m_L; + +private: + const Impl& impl() const { - luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); - rhs.push (m_L); - m_L = rhs.state (); - m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); - return *this; + return static_cast (*this); } - //---------------------------------------------------------------------------- - /** - converts to a string using luas tostring function - */ - std::string tostring() const + Impl& impl() { - lua_getglobal (m_L, "tostring"); - push (m_L); - lua_call (m_L, 1, 1); - const char* str = lua_tostring(m_L, 1); - lua_pop(m_L, 1); - return std::string(str); + return static_cast (*this); } +}; + +//------------------------------------------------------------------------------ +/** + Lightweight reference to a Lua object. + The reference is maintained for the lifetime of the C++ object. +*/ +class LuaRef : public LuaRefBase +{ //---------------------------------------------------------------------------- /** - Print a text description of the value to a stream. - - This is used for diagnostics. + A proxy for representing table values. */ - void print (std::ostream& os) const + class Proxy : public LuaRefBase { - switch (type ()) - { - case LUA_TNIL: - os << "nil"; - break; + friend class LuaRef; - case LUA_TNUMBER: - os << cast (); - break; + public: + //-------------------------------------------------------------------------- + /** + Construct a Proxy from a table value. - case LUA_TBOOLEAN: - os << (cast () ? "true" : "false"); - break; + The table is in the registry, and the key is at the top of the stack. + The key is popped off the stack. + */ + Proxy (lua_State* L, int tableRef) + : LuaRefBase (L) + , m_tableRef (LUA_NOREF) + , m_keyRef (luaL_ref (L, LUA_REGISTRYINDEX)) + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, tableRef); + m_tableRef = luaL_ref (L, LUA_REGISTRYINDEX); + } - case LUA_TSTRING: - os << '"' << cast () << '"'; - break; + //-------------------------------------------------------------------------- + /** + Create a Proxy via copy constructor. - case LUA_TTABLE: - os << "table: " << tostring(); - break; + It is best to avoid code paths that invoke this, because it creates + an extra temporary Lua reference. Typically this is done by passing + the Proxy parameter as a `const` reference. + */ + Proxy (Proxy const& other) + : LuaRefBase (other.m_L) + , m_tableRef (LUA_NOREF) + , m_keyRef (LUA_NOREF) + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_tableRef); + m_tableRef = luaL_ref (m_L, LUA_REGISTRYINDEX); - case LUA_TFUNCTION: - os << "function: " << tostring(); - break; + lua_rawgeti (m_L, LUA_REGISTRYINDEX, other.m_keyRef); + m_keyRef = luaL_ref (m_L, LUA_REGISTRYINDEX); + } - case LUA_TUSERDATA: - os << "userdata: " << tostring(); - break; + //-------------------------------------------------------------------------- + /** + Destroy the proxy. - case LUA_TTHREAD: - os << "thread: " << tostring(); - break; + This does not destroy the table value. + */ + ~Proxy () + { + luaL_unref (m_L, LUA_REGISTRYINDEX, m_keyRef); + luaL_unref (m_L, LUA_REGISTRYINDEX, m_tableRef); + } - case LUA_TLIGHTUSERDATA: - os << "lightuserdata: " << tostring(); - break; + //-------------------------------------------------------------------------- + /** + Assign a new value to this table key. - default: - os << "unknown"; - break; + This may invoke metamethods. + */ + template + Proxy& operator= (T v) + { + StackPop p (m_L, 1); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); + Stack ::push (m_L, v); + lua_settable (m_L, -3); + return *this; } - } - //============================================================================ - // - // This group of member functions is mirrored in Proxy - // + //-------------------------------------------------------------------------- + /** + Assign a new value to this table key. - /** Retrieve the lua_State associated with the reference. - */ - lua_State* state () const - { - return m_L; - } + The assignment is raw, no metamethods are invoked. + */ + template + Proxy& rawset (T v) + { + StackPop p (m_L, 1); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); + Stack ::push (m_L, v); + lua_rawset (m_L, -3); + return *this; + } - //---------------------------------------------------------------------------- - /** - Place the object onto the Lua stack. - */ - void push (lua_State* L) const - { - assert (equalstates (L, m_L)); - lua_rawgeti (L, LUA_REGISTRYINDEX, m_ref); - } + //-------------------------------------------------------------------------- + /** + Push the value onto the Lua stack. + */ + using LuaRefBase::push; - //---------------------------------------------------------------------------- - /** - Pop the top of Lua stack and assign the ref to m_ref - */ - void pop (lua_State* L) - { - assert (equalstates (L, m_L)); - luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); - m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); - } + void push () const + { + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef); + lua_gettable (m_L, -2); + lua_remove (m_L, -2); // remove the table + } - //---------------------------------------------------------------------------- - /** - Determine the object type. + //-------------------------------------------------------------------------- + /** + Access a table value using a key. - The return values are the same as for `lua_type`. - */ - /** @{ */ - int type () const - { - int result; - if (m_ref != LUA_REFNIL) + This invokes metamethods. + */ + template + Proxy operator[] (T key) const { - push (m_L); - result = lua_type (m_L, -1); - lua_pop (m_L, 1); + return LuaRef (*this) [key]; } - else + + //-------------------------------------------------------------------------- + /** + Access a table value using a key. + + The operation is raw, metamethods are not invoked. The result is + passed by value and may not be modified. + */ + template + LuaRef rawget (T key) const { - result = LUA_TNIL; + return LuaRef (*this).rawget (key); } - return result; - } + private: + int m_tableRef; + int m_keyRef; + }; - // should never happen - //inline bool isNone () const { return m_ref == LUA_NOREF; } - - inline bool isNil () const { return type () == LUA_TNIL; } - inline bool isNumber () const { return type () == LUA_TNUMBER; } - inline bool isString () const { return type () == LUA_TSTRING; } - inline bool isTable () const { return type () == LUA_TTABLE; } - inline bool isFunction () const { return type () == LUA_TFUNCTION; } - inline bool isUserdata () const { return type () == LUA_TUSERDATA; } - inline bool isThread () const { return type () == LUA_TTHREAD; } - inline bool isLightUserdata () const { return type () == LUA_TLIGHTUSERDATA; } - /** @} */ + friend struct Stack ; //---------------------------------------------------------------------------- /** - Perform an explicit conversion. + Create a reference to an object at the top of the Lua stack and pop it. + + This constructor is private and not invoked directly. + Instead, use the `fromStack` function. + + @note The object is popped. */ - template - T cast () const + LuaRef (lua_State* L, FromStack) + : LuaRefBase (L) + , m_ref (luaL_ref (m_L, LUA_REGISTRYINDEX)) { - StackPop p (m_L, 1); - push (m_L); - - // lua_gettop is used because Userdata::getClass() doesn't handle - // negative stack indexes. - // - return Stack ::get (m_L, lua_gettop (m_L)); } //---------------------------------------------------------------------------- /** - Universal implicit conversion operator. - - NOTE: Visual Studio 2010 and 2012 have a bug where this function - is not used. See: + Create a reference to an object on the Lua stack. - http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/e30b2664-a92d-445c-9db2-e8e0fbde2014 - https://connect.microsoft.com/VisualStudio/feedback/details/771509/correct-code-doesnt-compile + This constructor is private and not invoked directly. + Instead, use the `fromStack` function. - // This code snippet fails to compile in vs2010,vs2012 - struct S { - template inline operator T () const { return T (); } - }; - int main () { - S () || false; - return 0; - } + @note The object is not popped. */ - template - inline operator T () const + LuaRef (lua_State* L, int index, FromStack) + : LuaRefBase (L) + , m_ref (LUA_NOREF) { - return cast (); + lua_pushvalue (m_L, index); + m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); } + +public: //---------------------------------------------------------------------------- /** - Universal comparison operators. + Create a nil reference. + + The LuaRef may be assigned later. */ - /** @{ */ - template - bool operator== (T rhs) const + LuaRef (lua_State* L) + : LuaRefBase (L) + , m_ref (LUA_NOREF) { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -2, -1, LUA_OPEQ) == 1; } + //---------------------------------------------------------------------------- + /** + Create a reference to a value. + */ template - bool operator< (T rhs) const + LuaRef (lua_State* L, T v) + : LuaRefBase (L) + , m_ref (LUA_NOREF) { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -2, -1, LUA_OPLT) == 1; + Stack ::push (m_L, v); + m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); } - template - bool operator<= (T rhs) const + //---------------------------------------------------------------------------- + /** + Create a reference to a table value. + */ + LuaRef (Proxy const& v) + : LuaRefBase (v.state ()) + , m_ref (v.createRef ()) { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -2, -1, LUA_OPLE) == 1; } - template - bool operator> (T rhs) const + //---------------------------------------------------------------------------- + /** + Create a new reference to an existing reference. + */ + LuaRef (LuaRef const& other) + : LuaRefBase (other.m_L) + , m_ref (other.createRef ()) { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -1, -2, LUA_OPLT) == 1; } - template - bool operator>= (T rhs) const - { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_compare (m_L, -1, -2, LUA_OPLE) == 1; - } + //---------------------------------------------------------------------------- + /** + Destroy a reference. - template - bool rawequal (T rhs) const + The corresponding Lua registry reference will be released. + + @note If the state refers to a thread, it is the responsibility of the + caller to ensure that the thread still exists when the LuaRef + is destroyed. + */ + ~LuaRef () { - StackPop p (m_L, 2); - push (m_L); - Stack ::push (m_L, rhs); - return lua_rawequal (m_L, -1, -2) == 1; + luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); } - /** @} */ //---------------------------------------------------------------------------- /** - Append a value to the table. + Return a LuaRef from a top stack item. - If the table is a sequence this will add another element to it. + The stack item is not popped. */ - template - void append (T v) const + static LuaRef fromStack (lua_State* L) { - push (m_L); - Stack ::push (m_L, v); - luaL_ref (m_L, -2); - lua_pop (m_L, 1); + return LuaRef (L, FromStack ()); } //---------------------------------------------------------------------------- /** - Call the length operator. + Return a LuaRef from a stack item. - This is identical to applying the Lua # operator. + The stack item is not popped. */ - int length () const + static LuaRef fromStack (lua_State* L, int index) { - StackPop p (m_L, 1); - push (m_L); - return get_length (m_L, -1); + lua_pushvalue (L, index); + return LuaRef (L, FromStack ()); } //---------------------------------------------------------------------------- /** - Access a table value using a key. + Create a new empty table and return a reference to it. - This invokes metamethods. + It is also possible to use the free function `newTable`. + + @see ::luabridge::newTable */ - template - Proxy operator[] (T key) const + static LuaRef newTable (lua_State* L) { - Stack ::push (m_L, key); - return Proxy (m_L, m_ref); + lua_newtable (L); + return LuaRef (L, FromStack ()); } //---------------------------------------------------------------------------- /** - Call Lua code. + Return a reference to a named global. - These overloads allow Lua code to be called with up to 8 parameters. - The return value is provided as a LuaRef (which may be LUA_REFNIL). - If an error occurs, a LuaException is thrown. + It is also possible to use the free function `getGlobal`. + + @see ::luabridge::getGlobal */ - /** @{ */ - LuaRef const operator() () const + static LuaRef getGlobal (lua_State *L, char const* name) { - push (m_L); - LuaException::pcall (m_L, 0, 1); - return LuaRef (m_L, FromStack ()); + lua_getglobal (L, name); + return LuaRef (L, FromStack ()); } - template - LuaRef const operator() (P1 p1) const + //---------------------------------------------------------------------------- + /** + Assign another LuaRef to this LuaRef. + */ + LuaRef& operator= (LuaRef const& rhs) { - push (m_L); - Stack ::push (m_L, p1); - LuaException::pcall (m_L, 1, 1); - return LuaRef (m_L, FromStack ()); + LuaRef ref (rhs); + swap (ref); + return *this; } - template - LuaRef const operator() (P1 p1, P2 p2) const + //---------------------------------------------------------------------------- + /** + Assign Proxy to this LuaRef. + */ + LuaRef& operator= (LuaRef::Proxy const& rhs) { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - LuaException::pcall (m_L, 2, 1); - return LuaRef (m_L, FromStack ()); + LuaRef ref (rhs); + swap (ref); + return *this; } - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3) const + //---------------------------------------------------------------------------- + /** + Assign nil to this LuaRef. + */ + LuaRef& operator= (Nil const&) { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - LuaException::pcall (m_L, 3, 1); - return LuaRef (m_L, FromStack ()); + LuaRef ref (m_L); + swap (ref); + return *this; } - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4) const + //---------------------------------------------------------------------------- + /** + Assign a different value to this LuaRef. + */ + template + LuaRef& operator= (T rhs) { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - LuaException::pcall (m_L, 4, 1); - return LuaRef (m_L, FromStack ()); + LuaRef ref (m_L, rhs); + swap (ref); + return *this; } - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const - { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - LuaException::pcall (m_L, 5, 1); - return LuaRef (m_L, FromStack ()); - } + //---------------------------------------------------------------------------- + /** + Place the object onto the Lua stack. + */ + using LuaRefBase::push; - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) const + void push () const { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - Stack ::push (m_L, p6); - LuaException::pcall (m_L, 6, 1); - return LuaRef (m_L, FromStack ()); + lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_ref); } - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) const + //---------------------------------------------------------------------------- + /** + Pop the top of Lua stack and assign the ref to m_ref + */ + void pop () { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - Stack ::push (m_L, p6); - Stack ::push (m_L, p7); - LuaException::pcall (m_L, 7, 1); - return LuaRef (m_L, FromStack ()); + luaL_unref (m_L, LUA_REGISTRYINDEX, m_ref); + m_ref = luaL_ref (m_L, LUA_REGISTRYINDEX); } - template - LuaRef const operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) const + //---------------------------------------------------------------------------- + /** + Access a table value using a key. + + This invokes metamethods. + */ + template + Proxy operator[] (T key) const { - push (m_L); - Stack ::push (m_L, p1); - Stack ::push (m_L, p2); - Stack ::push (m_L, p3); - Stack ::push (m_L, p4); - Stack ::push (m_L, p5); - Stack ::push (m_L, p6); - Stack ::push (m_L, p7); - Stack ::push (m_L, p8); - LuaException::pcall (m_L, 8, 1); - return LuaRef (m_L, FromStack ()); + Stack ::push (m_L, key); + return Proxy (m_L, m_ref); } - /** @} */ - //============================================================================ + //-------------------------------------------------------------------------- + /** + Access a table value using a key. -private: - lua_State* m_L; - int m_ref; -}; + The operation is raw, metamethods are not invoked. The result is + passed by value and may not be modified. + */ + template + LuaRef rawget (T key) const + { + StackPop (m_L, 1); + push (m_L); + Stack ::push (m_L, key); + lua_rawget (m_L, -2); + return LuaRef (m_L, FromStack ()); + } -//------------------------------------------------------------------------------ -/** - Stack specialization for Nil -*/ -template <> -struct Stack -{ -public: - static inline void push (lua_State* L, Nil) +private: + void swap (LuaRef& other) { - lua_pushnil (L); + std::swap (m_L, other.m_L); + std::swap (m_ref, other.m_ref); } + + int m_ref; }; //------------------------------------------------------------------------------ @@ -1140,17 +974,16 @@ public: template <> struct Stack { -public: // The value is const& to prevent a copy construction. // - static inline void push (lua_State* L, LuaRef const& v) + static void push (lua_State* L, LuaRef const& v) { v.push (L); } - static inline LuaRef get (lua_State* L, int index) + static LuaRef get (lua_State* L, int index) { - return LuaRef (L, index, LuaRef::FromStack ()); + return LuaRef::fromStack (L, index); } }; @@ -1161,10 +994,9 @@ public: template <> struct Stack { -public: // The value is const& to prevent a copy construction. // - static inline void push (lua_State* L, LuaRef::Proxy const& v) + static void push (lua_State* L, LuaRef::Proxy const& v) { v.push (L); } @@ -1192,24 +1024,14 @@ inline LuaRef getGlobal (lua_State *L, char const* name) return LuaRef::getGlobal (L, name); } -//------------------------------------------------------------------------------ -/** - Write a LuaRef to a stream. - - This allows LuaRef and table proxies to work with streams. -*/ -inline std::ostream& operator<< (std::ostream& os, LuaRef const& ref) -{ - ref.print (os); - return os; -} - //------------------------------------------------------------------------------ // more C++-like cast syntax // template -inline T LuaRef_cast(LuaRef const& lr) +T LuaRef_cast(LuaRef const& lr) { return lr.cast(); } + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/Namespace.h b/extern/LuaBridge/detail/Namespace.h index ff22e6b09..4270b29a5 100644 --- a/extern/LuaBridge/detail/Namespace.h +++ b/extern/LuaBridge/detail/Namespace.h @@ -27,6 +27,16 @@ */ //============================================================================== +#pragma once + +#include +#include + +#include +#include + +namespace luabridge { + /** Provides C++ to Lua registration capabilities. This class is not instantiated directly, call `getGlobalNamespace` to start @@ -482,8 +492,9 @@ private: } else { - rawgetfield (L, -1, "__class"); - rawgetfield (L, -1, "__const"); + // Map T back from its stored tables + lua_rawgetp(L, LUA_REGISTRYINDEX, ClassInfo ::getClassKey()); + lua_rawgetp(L, LUA_REGISTRYINDEX, ClassInfo ::getConstKey()); // Reverse the top 3 stack elements lua_insert (L, -3); @@ -737,8 +748,8 @@ private: 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)) + template + Class & addProperty (char const* name, TG (*get) (T const*), void (*set) (T*, TS) = 0) { // Add to __propget in class and const tables. { @@ -768,24 +779,6 @@ private: 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, &CFunc::Call ::f, 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. @@ -793,6 +786,11 @@ private: template Class & addFunction (char const* name, MemFn mf) { + static const std::string GC = "__gc"; + if (name == GC) + { + throw std::logic_error (GC + " metamethod registration is forbidden"); + } CFunc::CallMemberFunctionHelper ::isConstMemberFunction>::add (L, name, mf); return *this; } @@ -868,10 +866,9 @@ private: */ explicit Namespace (lua_State* L_) : L (L_) - , m_stackSize (0) + , m_stackSize (1) { lua_getglobal (L, "_G"); - ++m_stackSize; } //---------------------------------------------------------------------------- @@ -1005,6 +1002,11 @@ public: template Namespace& addVariable (char const* name, T* pt, bool isWritable = true) { + if (m_stackSize == 1) + { + throw std::logic_error ("Unsupported addVariable on global namespace"); + } + assert (lua_istable (L, -1)); rawgetfield (L, -1, "__propget"); @@ -1038,9 +1040,14 @@ public: If the set function is omitted or null, the property is read-only. */ - template + template Namespace& addProperty (char const* name, TG (*get) (), void (*set)(TS) = 0) { + if (m_stackSize == 1) + { + throw std::logic_error ("Unsupported addProperty on global namespace"); + } + assert (lua_istable (L, -1)); rawgetfield (L, -1, "__propget"); @@ -1134,3 +1141,5 @@ inline Namespace getGlobalNamespace (lua_State* L) { return Namespace::getGlobalNamespace (L); } + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/Security.h b/extern/LuaBridge/detail/Security.h new file mode 100644 index 000000000..ae5053eef --- /dev/null +++ b/extern/LuaBridge/detail/Security.h @@ -0,0 +1,72 @@ +#pragma once + +namespace luabridge { + +//------------------------------------------------------------------------------ +/** +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; + } +}; + +//------------------------------------------------------------------------------ +/** +Push an object 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. + +@note This works on any type specialized by `Stack`, including `LuaRef` and +its table proxies. +*/ +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) +{ + Security::setHideMetatables(shouldHide); +} + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/Stack.h b/extern/LuaBridge/detail/Stack.h index d10fa8a2c..ce34d6bf9 100644 --- a/extern/LuaBridge/detail/Stack.h +++ b/extern/LuaBridge/detail/Stack.h @@ -27,6 +27,17 @@ */ //============================================================================== +#pragma once + +#include + +#include + +namespace luabridge { + +template +struct Stack; + //------------------------------------------------------------------------------ /** Receive the lua_State* as an argument. @@ -77,18 +88,10 @@ struct Stack }; template <> -struct Stack +struct Stack : public Stack { - 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 (luaL_checknumber (L, index)); - } }; + //------------------------------------------------------------------------------ /** Stack specialization for `unsigned int`. @@ -108,17 +111,8 @@ struct Stack }; template <> -struct Stack +struct Stack : Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -140,17 +134,8 @@ struct Stack }; template <> -struct Stack +struct Stack : Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -172,17 +157,8 @@ struct Stack }; template <> -struct Stack +struct Stack : Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -204,17 +180,8 @@ struct Stack }; template <> -struct Stack +struct Stack : Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -236,17 +203,8 @@ struct Stack }; template <> -struct Stack +struct Stack : public Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -268,17 +226,8 @@ struct Stack }; template <> -struct Stack +struct Stack : public Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -300,17 +249,8 @@ struct Stack }; template <> -struct Stack +struct Stack : Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -330,17 +270,9 @@ template <> struct Stack } }; -template <> struct Stack +template <> +struct Stack : Stack { - 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 (luaL_checknumber (L, index)); - } }; //------------------------------------------------------------------------------ @@ -348,7 +280,8 @@ template <> struct Stack Stack specialization for `bool`. */ template <> -struct Stack { +struct Stack +{ static inline void push (lua_State* L, bool value) { lua_pushboolean (L, value ? 1 : 0); @@ -361,16 +294,8 @@ struct Stack { }; 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) - { - return lua_toboolean (L, index) ? true : false; - } +struct Stack : Stack +{ }; //------------------------------------------------------------------------------ @@ -382,8 +307,7 @@ struct Stack { static inline void push (lua_State* L, char value) { - char str [2] = { value, 0 }; - lua_pushstring (L, str); + lua_pushlstring (L, &value, 1); } static inline char get (lua_State* L, int index) @@ -393,23 +317,13 @@ struct Stack }; template <> -struct Stack +struct Stack : 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]; - } }; //------------------------------------------------------------------------------ /** - Stack specialization for `float`. + Stack specialization for `const char*`. */ template <> struct Stack @@ -437,33 +351,64 @@ struct Stack { static inline void push (lua_State* L, std::string const& str) { - lua_pushlstring (L, str.c_str (), str.size()); + lua_pushlstring (L, str.data (), str.size()); } static inline std::string get (lua_State* L, int index) { size_t len; - const char *str = luaL_checklstring(L, index, &len); + const char *str = luaL_checklstring (L, index, &len); return std::string (str, len); } }; +template <> +struct Stack : Stack +{ +}; + //------------------------------------------------------------------------------ /** - Stack specialization for `std::string const&`. +Stack specialization for `long long`. */ template <> -struct Stack +struct Stack { - static inline void push (lua_State* L, std::string const& str) + static inline void push (lua_State* L, long long value) { - lua_pushlstring (L, str.c_str(), str.size()); + lua_pushinteger (L, static_cast (value)); + } + static inline long long get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); } +}; - static inline std::string get (lua_State* L, int index) +template <> +struct Stack : public Stack +{ +}; + +//------------------------------------------------------------------------------ +/** +Stack specialization for `unsigned long long`. +*/ +template <> +struct Stack +{ + static inline void push (lua_State* L, unsigned long long value) { - size_t len; - const char *str = luaL_checklstring(L, index, &len); - return std::string (str, len); + lua_pushinteger (L, static_cast (value)); + } + static inline unsigned long long get (lua_State* L, int index) + { + return static_cast (luaL_checkinteger (L, index)); } }; + +template <> +struct Stack : Stack +{ +}; + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/TypeList.h b/extern/LuaBridge/detail/TypeList.h index 21f850e89..4af7db591 100644 --- a/extern/LuaBridge/detail/TypeList.h +++ b/extern/LuaBridge/detail/TypeList.h @@ -43,6 +43,15 @@ */ //============================================================================== +#pragma once + +#include + +#include +#include + +namespace luabridge { + /** None type means void parameters or return value. */ @@ -172,3 +181,5 @@ struct ArgList , Start> { } }; + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/TypeTraits.h b/extern/LuaBridge/detail/TypeTraits.h index 5dd077194..7f9a2f2f2 100644 --- a/extern/LuaBridge/detail/TypeTraits.h +++ b/extern/LuaBridge/detail/TypeTraits.h @@ -26,8 +26,9 @@ */ //============================================================================== -#ifndef LUABRIDGE_TYPEINFO_HEADER -#define LUABRIDGE_TYPEINFO_HEADER +#pragma once + +namespace luabridge { //------------------------------------------------------------------------------ /** @@ -57,6 +58,7 @@ template struct ContainerTraits { typedef bool isNotContainer; + typedef T Type; }; //------------------------------------------------------------------------------ @@ -122,4 +124,4 @@ struct TypeTraits /**@}*/ }; -#endif +} // namespace luabridge diff --git a/extern/LuaBridge/detail/Userdata.h b/extern/LuaBridge/detail/Userdata.h index 19451bd7d..fde90174e 100644 --- a/extern/LuaBridge/detail/Userdata.h +++ b/extern/LuaBridge/detail/Userdata.h @@ -26,6 +26,14 @@ */ //============================================================================== +#pragma once + +#include + +#include + +namespace luabridge { + //============================================================================== /** Return the identity pointer for our lightuserdata tokens. @@ -179,14 +187,18 @@ private: void const* baseClassKey, bool canBeConst) { - assert (index > 0); + index = index > 0 ? index : lua_absindex (L, index); + Userdata* ud = 0; bool mismatch = false; char const* got = 0; lua_rawgetp (L, LUA_REGISTRYINDEX, baseClassKey); - assert (lua_istable (L, -1)); + if (!lua_istable (L, -1)) + { + throw std::logic_error ("The class is not registered in LuaBridge"); + } // Make sure we have a userdata. if (lua_isuserdata (L, index)) @@ -371,8 +383,10 @@ public: 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)); + if (!lua_istable (L, -1)) + { + throw std::logic_error ("The class is not registered in LuaBridge"); + } lua_setmetatable (L, -2); return ud->getPointer (); } @@ -408,8 +422,10 @@ private: { 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)); + if (!lua_istable (L, -1)) + { + throw std::logic_error ("The class is not registered in LuaBridge"); + } lua_setmetatable (L, -2); } else @@ -427,8 +443,10 @@ private: 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)); + if (!lua_istable (L, -1)) + { + throw std::logic_error ("The class is not registered in LuaBridge"); + } lua_setmetatable (L, -2); } else @@ -815,3 +833,5 @@ struct Stack return helper_t::get (L, index); } }; + +} // namespace luabridge diff --git a/extern/LuaBridge/detail/dump.h b/extern/LuaBridge/detail/dump.h index c06680357..d14669889 100644 --- a/extern/LuaBridge/detail/dump.h +++ b/extern/LuaBridge/detail/dump.h @@ -1,6 +1,39 @@ +//============================================================================== +/* + https://github.com/vinniefalco/LuaBridge + + Copyright 2012, Vinnie Falco + Copyright 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. +*/ +//============================================================================== + +#pragma once + #include #include +namespace luabridge { + std::string dumpLuaState(lua_State *L) { std::stringstream ostr; int i; @@ -26,3 +59,5 @@ std::string dumpLuaState(lua_State *L) { } return ostr.str(); } + +} // namespace luabridge