diff options
Diffstat (limited to '3rdparty/sol2')
191 files changed, 30263 insertions, 42610 deletions
diff --git a/3rdparty/sol2/.gitignore b/3rdparty/sol2/.gitignore deleted file mode 100644 index ae380bf9f41..00000000000 --- a/3rdparty/sol2/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -# Python (Bytecode) -*.pyc - -# ninja files -*.ninja - -# Visual Studio -*.props -*.user -.vs/ -Debug/ -Release/ -x64/ -*.vcxproj -*.vcxproj.filters -*.tlog -*.lastbuildstate -*.idb -*.sln -*.gitattributes - -# VSCode -.vscode/ - -# Compiler outputs -obj/* -bin/* - -# Dropbox interference -.dropbox* - -# QtCreator -*.creator.user.* -*.config -*.creator -*.files -*.includes - -# Scratchpad Files -main2.cpp -main.cpp - -# Local Lua Testbeds -lua-5.3.2/ -lua-5.3.1/ -lua-5.3.0/ -lua-5.2.4/ -lua-5.2.2/ -lua-5.2.3/ -lua-5.1.5/ -luajit-2.0.4/ -luajit-2.0.3/ -include/ -liblua.a -lib/liblua5.2.a - -# Windows Crap -desktop.ini -*.sublime-workspace -docs/build/ -*.sublime-project -m.lua -single/sol.hpp -*.db -lua53.dll -main.exe -main.o -lua-5.3.3/ -main.lua -LuaJIT-2.1.0/ -lua-5.3.3-cxx/ -lua-5.3.3.vcxproj-cxx.filters -sol.pyproj diff --git a/3rdparty/sol2/.travis.yml b/3rdparty/sol2/.travis.yml deleted file mode 100644 index 1428ce8c8d1..00000000000 --- a/3rdparty/sol2/.travis.yml +++ /dev/null @@ -1,192 +0,0 @@ -language: cpp -sudo: required -dist: trusty - -git: - depth: 5 - -before_install: -- source ./install.deps.sh - -install: -- install_os_deps - -script: -- echo "Configuration info:" -- export_compiler_vars -- ninja --version -- ./bootstrap.py --ci && ninja - -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/b864d553270a069d26c8 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always - email: - on_success: change - on_failure: change - -matrix: - include: - - os: linux - env: COMPILER=g++-4.9 LUA_VERSION=lua52 - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.9 - - g++-4.9 - - ninja-build - - liblua5.2-dev - - # gcc-5 - - os: linux - env: COMPILER=g++-4.9 LUA_VERSION=luajit51 - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.9 - - g++-4.9 - - ninja-build - - libluajit-5.1-dev - - # gcc-5 - - os: linux - env: COMPILER=g++-5 LUA_VERSION=lua52 - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-5 - - g++-5 - - ninja-build - - liblua5.2-dev - - # gcc-5 - - os: linux - env: COMPILER=g++-5 LUA_VERSION=luajit51 - compiler: gcc - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-5 - - g++-5 - - ninja-build - - libluajit-5.1-dev - - # clang - - os: linux - env: - - LLVM_VERSION=3.5.0 - - LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz - - COMPILER=clang++ - - CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1" - - CXXFLAGS=-lc++ - - PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH - - LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH - - LUA_VERSION=lua52 - before_install: - - wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH - - mkdir $HOME/clang-$LLVM_VERSION - - tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1 - - export PATH=$HOME/clang+llvm/bin:$PATH - - source ./install.deps.sh - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.9 - - g++-4.9 - - ninja-build - - liblua5.2-dev - - - os: linux - env: - - LLVM_VERSION=3.6.0 - - LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz - - COMPILER=clang++ - - CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1" - - CXXFLAGS=-lc++ - - PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH - - LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH - - LUA_VERSION=lua52 - before_install: - - wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH - - mkdir $HOME/clang-$LLVM_VERSION - - tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1 - - export PATH=$HOME/clang+llvm/bin:$PATH - - source ./install.deps.sh - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.9 - - g++-4.9 - - ninja-build - - liblua5.2-dev - - - os: linux - env: - - LLVM_VERSION=3.6.0 - - LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz - - COMPILER=clang++ - - CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1" - - CXXFLAGS=-lc++ - - PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH - - LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH - - LUA_VERSION=luajit51 - before_install: - - wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH - - mkdir $HOME/clang-$LLVM_VERSION - - tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1 - - export PATH=$HOME/clang+llvm/bin:$PATH - - source ./install.deps.sh - compiler: clang - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-4.9 - - g++-4.9 - - ninja-build - - libluajit-5.1-dev - - - os: osx - osx_image: xcode7 - compiler: gcc - env: COMPILER=g++-4.9 LUA_VERSION=lua53 - - - os: osx - osx_image: xcode7 - compiler: gcc - env: COMPILER=g++-5 LUA_VERSION=lua53 - - - os: osx - osx_image: xcode7 - compiler: gcc - env: COMPILER=g++-5 LUA_VERSION=luajit - - - os: osx - osx_image: xcode7 - compiler: clang - env: COMPILER=appleclang LUA_VERSION=lua53 - - allow_failures: - - os: osx - compiler: clang diff --git a/3rdparty/sol2/CONTRIBUTING.md b/3rdparty/sol2/CONTRIBUTING.md deleted file mode 100644 index e7a4147a648..00000000000 --- a/3rdparty/sol2/CONTRIBUTING.md +++ /dev/null @@ -1,58 +0,0 @@ -## Contributing to Sol - -Looking to contribute to Sol? Well, first thing I want to mention is thank you! -Second of all, this is probably where you should look :) - -## Reporting Issues - -If you found a bug, please make sure to make an issue in the issue tracker. - -The guidelines for reporting a bug are relatively simple and are as follows: - -1. Produce a simple, short, compilable test case that reproduces your problem. -2. Make a descriptive title that summarises the bug as a whole. -3. Explain the bug in as much detail as you can in the body of the issue. - -If you have all of those requirements set, then your issue reporting is golden. - -## Submitting a pull request - -Submitting a pull request is fairly simple, just make sure it focuses on a single aspect and doesn't -manage to have scope creep and it's probably good to go. It would be incredibly lovely if the style is -consistent to those found in the repository. - -They are as follows (more will be added as they come up): - -- No spaces between parentheses. e.g. `f(g())` not `f ( g ( ) )`. -- Tabs for indentation, spaces for alignment. -- Bracing style is - -```cpp -if(my_bool) { - -} -else if(my_other_bool) { - -} -else { - -} -``` - -- Variable names follow those in the C++ standard, basically snake_case. -- Maximum column length is 125 -- Trailing return type will always be in the same line. Even if it goes off the column length. e.g. -`auto f() -> decltype(/* my long expression */) {` -- Since this is a header-only library, all free functions must be marked `inline`. -- Use braces in optional contexts like `if`, `for`, `else`, `while`, etc. e.g. - -```cpp -if(x > 12) { - return x * 2; -} -``` - -- Use `typename` instead of `class` for template parameters. e.g. `template<typename T>`. - -If you don't meet all of these style guidelines, don't fret. I'll probably fix it. But please -do make an effort to actually meet them. Otherwise I'm more likely to reject the pull request. diff --git a/3rdparty/sol2/LICENSE.txt b/3rdparty/sol2/LICENSE.txt deleted file mode 100644 index 1b5ff3c1af3..00000000000 --- a/3rdparty/sol2/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2016 Rapptz and contributors - -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. diff --git a/3rdparty/sol2/README.md b/3rdparty/sol2/README.md deleted file mode 100644 index 198a7240a79..00000000000 --- a/3rdparty/sol2/README.md +++ /dev/null @@ -1,84 +0,0 @@ -## Sol 2.15 - -[](https://gitter.im/chat-sol2/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -[](https://travis-ci.org/ThePhD/sol2) -[](http://sol2.readthedocs.io/en/latest/?badge=latest) - -Sol is a C++ library binding to Lua. It currently supports all Lua versions 5.1+ (LuaJIT 2.x included). Sol aims to be easy to use and easy to add to a project. -The library is header-only for easy integration with projects. - -## Documentation - -Find it [here](http://sol2.rtfd.io/). A run-through kind of tutorial is [here](http://sol2.readthedocs.io/en/latest/tutorial/all-the-things.html)! The API documentation goes over most cases (particularly, the "api/usertype" and "api/proxy" and "api/function" sections) that should still get you off your feet and going, and there's an examples directory [here](https://github.com/ThePhD/sol2/tree/develop/examples) as well. - -## Sneak Peek - -```cpp -#include <sol.hpp> -#include <cassert> - -int main() { - sol::state lua; - int x = 0; - lua.set_function("beep", [&x]{ ++x; }); - lua.script("beep()"); - assert(x == 1); -} -``` - -```cpp -#include <sol.hpp> -#include <cassert> - -struct vars { - int boop = 0; -}; - -int main() { - sol::state lua; - lua.new_usertype<vars>("vars", "boop", &vars::boop); - lua.script("beep = vars.new()\n" - "beep.boop = 1"); - assert(lua.get<vars>("beep").boop == 1); -} -``` - -More examples are given in the examples directory. - -## Presentations - -"A Sun For the Moon - A Zero-Overhead Lua Abstraction using C++" -ThePhD -Lua Workshop 2016 - Mashape, San Francisco, CA -[Deck](https://github.com/ThePhD/sol2/blob/develop/docs/presentations/ThePhD%20-%20No%20Overhead%20C%20Abstraction%20-%202016.10.14.pdf) - -## Creating a single header - -You can grab a single header out of the library [here](https://github.com/ThePhD/sol2/tree/develop/single/sol). For stable version, check the releases tab on github for a provided single header file for maximum ease of use. A script called `single.py` is provided in the repository if there's some bleeding edge change that hasn't been published on the releases page. You can run this script to create a single file version of the library so you can only include that part of it. Check `single.py --help` for more info. - -## Features - -- [Fastest in the land](http://sol2.readthedocs.io/en/latest/benchmarks.html) (see: sol bar in graph). -- Supports retrieval and setting of multiple types including `std::string` and `std::map/unordered_map`. -- Lambda, function, and member function bindings are supported. -- Intermediate type for checking if a variable exists. -- Simple API that completely abstracts away the C stack API, including `protected_function` with the ability to use an error-handling function. -- `operator[]`-style manipulation of tables -- C++ type representations in lua userdata as `usertype`s with guaranteed cleanup. -- Customization points to allow your C++ objects to be pushed and retrieved from Lua as multiple consecutive objects, or anything else you desire! -- Overloaded function calls: `my_function(1); my_function("Hello")` in the same lua script route to different function calls based on parameters -- Support for tables, nested tables, table iteration with `table.for_each` / `begin()` and `end()` iterators. - -## Supported Compilers - -Sol makes use of C++11/14 features. GCC 4.9 and Clang 3.4 (with std=c++1z and appropriate standard library) or higher should be able to compile without problems. However, the -officially supported and CI-tested compilers are: - -- GCC 4.9.0+ -- Clang 3.5+ -- Visual Studio 2015 Community (Visual C++ 14.0)+ - -## License - -Sol is distributed with an MIT License. You can see LICENSE.txt for more info. diff --git a/3rdparty/sol2/bootstrap.py b/3rdparty/sol2/bootstrap.py deleted file mode 100644 index d1e6bfdfdcb..00000000000 --- a/3rdparty/sol2/bootstrap.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python - -import ninja_syntax -import os, sys, glob, re -import itertools -import argparse - -# utilities -def flags(*args): - return ' '.join(itertools.chain(*args)) - -def includes(l): - return ['-I"{}"'.format(x) for x in l] - -def library_includes(l): - return ['-L"{}"'.format(x) for x in l] - -def libraries(l): - return ['-l{}'.format(x) for x in l] - -def dependencies(l): - return ['-isystem"{}"'.format(x) for x in l] - -def object_file(f): - (root, ext) = os.path.splitext(f) - return os.path.join(objdir, root + '.o') - -def replace_extension(f, e): - (root, ext) = os.path.splitext(f) - return root + e - -# Default install dir -install_dir = os.path.join('/usr', 'include') if 'linux' in sys.platform else 'include' - -# Compiler: Read from environment or defaulted -cxx = os.environ.get('CXX', "g++") - -# command line stuff -parser = argparse.ArgumentParser() -parser.add_argument('--debug', action='store_true', help='compile with debug flags') -parser.add_argument('--cxx', metavar='<compiler>', help='compiler name to use (default: env.CXX=%s)' % cxx, default=cxx) -parser.add_argument('--cxx-flags', help='additional flags passed to the compiler', default='') -parser.add_argument('--ci', action='store_true', help=argparse.SUPPRESS) -parser.add_argument('--testing', action='store_true', help=argparse.SUPPRESS) -parser.add_argument('--lua-version', help='Lua version, e.g. lua53', default='lua53') -parser.add_argument('--lua-lib', help='lua library name (without the lib on *nix).', default='lua') -parser.add_argument('--lua-dir', metavar='<dir>', help='directory lua is in with include and lib subdirectories') -parser.add_argument('--install-dir', metavar='<dir>', help='directory to install the headers to', default=install_dir); -parser.epilog = """In order to install sol, administrative privileges might be required. -Note that installation is done through the 'ninja install' command. To uninstall, the -command used is 'ninja uninstall'. The default installation directory for this -system is {}""".format(install_dir) - -args = parser.parse_args() - -# general variables -include = [ '.', './include' ] -depends = [os.path.join('Catch', 'include')] -cxxflags = [ '-Wall', '-Wextra', '-Wpedantic', '-pedantic', '-pedantic-errors', '-std=c++14', '-ftemplate-depth=1024' ] -cxxflags.extend([p for p in re.split("( |\\\".*?\\\"|'.*?')", args.cxx_flags) if p.strip()]) -example_cxxflags = [ '-Wall', '-Wextra', '-Wpedantic', '-pedantic', '-pedantic-errors', '-std=c++14', '-ftemplate-depth=1024' ] -example_cxxflags.extend([p for p in re.split("( |\\\".*?\\\"|'.*?')", args.cxx_flags) if p.strip()]) -ldflags = [] -script_dir = os.path.dirname(os.path.realpath(sys.argv[0])) -sol_dir = os.path.join(script_dir, 'sol') -sol_file = os.path.join(script_dir, 'sol.hpp') - -copy_command = 'cp -rf {} $in && cp -f {} $in'.format(sol_dir, sol_file) -remove_command = 'rm -rf {} && rm -f {}'.format(os.path.join(args.install_dir, 'sol'), os.path.join(args.install_dir, 'sol.hpp')) -if sys.platform == 'win32': - copy_command = 'robocopy /COPYALL /E {} $in && robocopy /COPYALL {} $in'.format(sol_dir, sol_file) - remove_command = 'rmdir /S /Q {} && erase /F /S /Q /A {}'.format(os.path.join(args.install_dir, 'sol'), - os.path.join(args.install_dir, 'sol.hpp')) - -if not args.lua_lib: - args.lua_lib = 'lua' - -if args.debug: - cxxflags.extend(['-g', '-O0']) -else: - cxxflags.extend(['-DNDEBUG', '-O3']) -example_cxxflags.extend(['-g', '-O0']) - -if args.lua_dir: - include.extend([os.path.join(args.lua_dir, 'include')]) - ldflags.extend(library_includes([os.path.join(args.lua_dir, 'lib')])) - -if 'linux' in sys.platform: - lua_version = os.environ.get('LUA_VERSION', args.lua_version) - if re.match(r'lua5[1-3]', lua_version): - # Using normal lua - lua_lib = lua_version[:-1] + '.' + lua_version[-1] - lua_incl = lua_lib - elif re.match(r'luajit5[1-3]', lua_version): - # luajit - lua_incl = 'luajit-2.0' # I don't get this.. - lua_lib = lua_version[:-2] + '-' + lua_version[-2] + '.' + lua_version[-1] - include.extend(['/usr/include/luajit-2.0/', '/usr/local/include/luajit-2.0/']) - else: - raise Exception('Unknown lua_version={}' % lua_version) - - - include.extend(['/usr/include/' + lua_incl, '/usr/local/include/' + lua_incl]) - ldflags.extend(library_includes(['/usr/local/lib'])) - ldflags.extend(libraries([lua_lib])) -elif 'darwin' in sys.platform: - # OSX - lua_version = os.environ.get('LUA_VERSION', args.lua_version) - if re.match(r'lua5[1-3]', lua_version): - # Using normal lua - lua_incl = lua_version[:-1] + '.' + lua_version[-1] - lua_lib = lua_version[:-2] + '.' + lua_version[-2] + '.' + lua_version[-1] - elif re.match(r'luajit', lua_version): - # luajit - lua_incl = 'luajit-2.0' - lua_lib = 'luajit' - ldflags.extend(['-pagezero_size 10000', '-image_base 100000000']) - elif re.match(r'luajit5[1-3]', lua_version): - # luajit - lua_incl = 'luajit-2.0' - lua_lib = lua_version[:-2] + '-' + lua_version[-2] + '.' + lua_version[-1] - ldflags.extend(['-pagezero_size 10000', '-image_base 100000000']) - else: - raise Exception('Unknown lua_version={}' % lua_version) - - depends.extend(['/usr/include/' + lua_incl, '/usr/local/include/' + lua_incl]) - ldflags.extend(library_includes(['/usr/local/lib'])) - ldflags.extend(libraries([lua_lib])) -else: - ldflags.extend(libraries([args.lua_lib])) - -if args.testing: - cxxflags.append('-Wmissing-declarations') - -if 'linux' in sys.platform: - ldflags.extend(libraries(['dl'])) - -builddir = 'bin' -objdir = 'obj' -if 'win32' in sys.platform: - tests = os.path.join(builddir, 'tests.exe') -else: - tests = os.path.join(builddir, 'tests') - -tests_inputs = [] -tests_object_files = [] -for f in glob.glob('test*.cpp'): - obj = object_file(f) - tests_inputs.append(f) - tests_object_files.append(obj) - -examples = [] -examples_input = [] -for f in glob.glob('examples/*.cpp'): - if 'win32' in sys.platform: - example = os.path.join(builddir, replace_extension(f, '.exe')) - else: - example = os.path.join(builddir, replace_extension(f, '')) - examples_input.append(f) - examples.append(example) - - -# ninja file -ninja = ninja_syntax.Writer(open('build.ninja', 'w')) - -# variables -ninja.variable('ninja_required_version', '1.3') -ninja.variable('builddir', 'bin') -ninja.variable('cxx', args.cxx) -ninja.variable('cxxflags', flags(cxxflags + includes(include) + dependencies(depends))) -ninja.variable('example_cxxflags', flags(example_cxxflags + includes(include) + dependencies(depends))) -ninja.variable('ldflags', flags(ldflags)) -ninja.newline() - -# rules -ninja.rule('bootstrap', command = ' '.join(['python'] + sys.argv), generator = True) -ninja.rule('compile', command = '$cxx -MMD -MF $out.d -c $cxxflags -Werror $in -o $out', - deps = 'gcc', depfile = '$out.d', - description = 'compiling $in to $out') -ninja.rule('link', command = '$cxx $cxxflags $in -o $out $ldflags', description = 'creating $out') -ninja.rule('tests_runner', command = tests) -ninja.rule('examples_runner', command = 'cmd /c ' + (' && '.join(examples)) if 'win32' in sys.platform else ' && '.join(examples) ) -ninja.rule('example', command = '$cxx $example_cxxflags -MMD -MF $out.d $in -o $out $ldflags', - deps = 'gcc', depfile = '$out.d', - description = 'compiling example $in to $out') -ninja.rule('installer', command = copy_command) -ninja.rule('uninstaller', command = remove_command) -ninja.newline() - -# builds -ninja.build('build.ninja', 'bootstrap', implicit = sys.argv[0]) - -for obj, f in zip(tests_object_files, tests_inputs): - ninja.build(obj, 'compile', inputs = f) - -for example, f in zip(examples, examples_input): - ninja.build(example, 'example', inputs = f) - -ninja.build(tests, 'link', inputs = tests_object_files) -ninja.build('tests', 'phony', inputs = tests) -ninja.build('examples', 'phony', inputs = examples) -ninja.build('install', 'installer', inputs = args.install_dir) -ninja.build('uninstall', 'uninstaller') -ninja.build('run', 'tests_runner', implicit = 'tests') -ninja.build('run_examples', 'examples_runner', implicit = 'examples') -ninja.default('run run_examples') diff --git a/3rdparty/sol2/docs/Makefile b/3rdparty/sol2/docs/Makefile deleted file mode 100644 index ac69fbd7e5d..00000000000 --- a/3rdparty/sol2/docs/Makefile +++ /dev/null @@ -1,216 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " applehelp to make an Apple Help Book" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - @echo " coverage to run coverage check of the documentation (if enabled)" - -.PHONY: clean -clean: - rm -rf $(BUILDDIR)/* - -.PHONY: html -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -.PHONY: dirhtml -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -.PHONY: singlehtml -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -.PHONY: pickle -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -.PHONY: json -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -.PHONY: htmlhelp -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -.PHONY: qthelp -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Sol.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Sol.qhc" - -.PHONY: applehelp -applehelp: - $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - @echo - @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." - @echo "N.B. You won't be able to view it unless you put it in" \ - "~/Library/Documentation/Help or install it in your application" \ - "bundle." - -.PHONY: devhelp -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/Sol" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Sol" - @echo "# devhelp" - -.PHONY: epub -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -.PHONY: latex -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -.PHONY: latexpdf -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: latexpdfja -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -.PHONY: text -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -.PHONY: man -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -.PHONY: texinfo -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -.PHONY: info -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -.PHONY: gettext -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -.PHONY: changes -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -.PHONY: linkcheck -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -.PHONY: doctest -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -.PHONY: coverage -coverage: - $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - @echo "Testing of coverage in the sources finished, look at the " \ - "results in $(BUILDDIR)/coverage/python.txt." - -.PHONY: xml -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -.PHONY: pseudoxml -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/3rdparty/sol2/docs/make.bat b/3rdparty/sol2/docs/make.bat deleted file mode 100644 index ab1cb81297b..00000000000 --- a/3rdparty/sol2/docs/make.bat +++ /dev/null @@ -1,263 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source -set I18NSPHINXOPTS=%SPHINXOPTS% source -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^<target^>` where ^<target^> is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - echo. coverage to run coverage check of the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -REM Check if sphinx-build is available and fallback to Python version if any -%SPHINXBUILD% 1>NUL 2>NUL -if errorlevel 9009 goto sphinx_python -goto sphinx_ok - -:sphinx_python - -set SPHINXBUILD=python -m sphinx.__init__ -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -:sphinx_ok - - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Sol.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Sol.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %~dp0 - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %~dp0 - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "coverage" ( - %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage - if errorlevel 1 exit /b 1 - echo. - echo.Testing of coverage in the sources finished, look at the ^ -results in %BUILDDIR%/coverage/python.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end diff --git a/3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdf b/3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdf Binary files differdeleted file mode 100644 index 51c674b91eb..00000000000 --- a/3rdparty/sol2/docs/presentations/ThePhD - No Overhead C Abstraction - 2016.10.14.pdf +++ /dev/null diff --git a/3rdparty/sol2/docs/source/api/api-top.rst b/3rdparty/sol2/docs/source/api/api-top.rst deleted file mode 100644 index ebeabf3ee3b..00000000000 --- a/3rdparty/sol2/docs/source/api/api-top.rst +++ /dev/null @@ -1,48 +0,0 @@ -api reference manual -==================== - -Browse the various function and classes :doc:`Sol<../index>` utilizes to make your life easier when working with Lua. - - -.. toctree:: - :caption: Sol API - :name: apitoc - :maxdepth: 2 - - state - table - proxy - containers - as_table - usertype - simple_usertype - usertype_memory - unique_usertype_traits - tie - function - protected_function - coroutine - error - object - userdata - reference - thread - stack_reference - make_reference - optional - this_state - variadic_args - as_args - overload - property - var - protect - readonly - as_function - c_call - resolve - stack - user - compatibility - types - metatable_key diff --git a/3rdparty/sol2/docs/source/api/as_args.rst b/3rdparty/sol2/docs/source/api/as_args.rst deleted file mode 100644 index 8e323fdfaba..00000000000 --- a/3rdparty/sol2/docs/source/api/as_args.rst +++ /dev/null @@ -1,50 +0,0 @@ -as_args -======= -turn an iterable argument into multiple arguments -------------------------------------------------- - -.. code-block:: cpp - - template <typename T> - as_args_t { ... }; - - template <typename T> - as_args_t<T> as_args( T&& ); - - -``sol::as_args`` is a function that that takes an iterable and turns it into multiple arguments to a function call. It forwards its arguments, and is meant to be used as shown below: - -.. code-block:: cpp - :caption: as_args.c++ - - #define SOL_CHECK_ARGUMENTS - #include <sol.hpp> - - #include <vector> - #include <set> - - int main(int argc, const char* argv[]) { - - sol::state lua; - lua.open_libraries(); - - lua.script("function f (a, b, c, d) print(a, b, c, d) end"); - - sol::function f = lua["f"]; - - std::vector<int> v2{ 3, 4 }; - f(1, 2, sol::as_args(v2)); - - std::set<int> v4{ 3, 1, 2, 4 }; - f(sol::as_args(v4)); - - int v3[] = { 2, 3, 4 }; - f(1, sol::as_args(v3)); - - return 0; - } - - -It is basically implemented as a `one-way customization point`_. For more information about customization points, see the :doc:`tutorial on how to customize Sol to work with your types<../tutorial/customization>`. - -.. _one-way customization point: https://github.com/ThePhD/sol2/blob/develop/sol/as_args.hpp diff --git a/3rdparty/sol2/docs/source/api/as_function.rst b/3rdparty/sol2/docs/source/api/as_function.rst deleted file mode 100644 index bb058ba52c7..00000000000 --- a/3rdparty/sol2/docs/source/api/as_function.rst +++ /dev/null @@ -1,67 +0,0 @@ -as_function -=========== -make sure an object is pushed as a function -------------------------------------------- - -.. code-block:: cpp - - template <typename Sig = sol::function_sig<>, typename... Args> - function_argumants<Sig, Args...> as_function ( Args&& ... ); - -This function serves the purpose of ensuring that a callable struct (like a lambda) can be passed to the ``set( key, value )`` calls on :ref:`sol::table<set-value>` and be treated like a function binding instead of a userdata. It is recommended that one uses the :ref:`sol::table::set_function<set-function>` call instead, but if for some reason one must use ``set``, then ``as_function`` can help ensure a callable struct is handled like a lambda / callable, and not as just a userdata structure. - -This class can also make it so usertypes bind variable types as functions to for usertype bindings. - -.. code-block:: cpp - - #include <sol.hpp> - - int main () { - struct callable { - int operator()( int a, bool b ) { - return a + b ? 10 : 20; - } - }; - - - sol::state lua; - // Binds struct as userdata - lua.set( "not_func", callable() ); - // Binds struct as function - lua.set( "func", sol::as_function( callable() ) ); - // equivalent: lua.set_function( "func", callable() ); - // equivalent: lua["func"] = callable(); - } - -Note that if you actually want a userdata, but you want it to be callable, you simply need to create a :ref:`sol::table::new_usertype<new-usertype>` and then bind the ``"__call"`` metamethod (or just use ``sol::meta_function::call`` :ref:`enumeration<meta_function_enum>`). - -Here's an example of binding a variable as a function to a usertype: - -.. code-block:: cpp - - #include <sol.hpp> - - int main () { - class B { - public: - int bvar = 24; - }; - - sol::state lua; - lua.open_libraries(); - lua.new_usertype<B>("B", - // bind as variable - "b", &B::bvar, - // bind as function - "f", sol::as_function(&B::bvar) - ); - - B b; - lua.set("b", &b); - lua.script("x = b:f()"); - lua.script("y = b.b"); - int x = lua["x"]; - int y = lua["y"]; - assert(x == 24); - assert(y == 24); - } diff --git a/3rdparty/sol2/docs/source/api/as_table.rst b/3rdparty/sol2/docs/source/api/as_table.rst deleted file mode 100644 index e5b58b49fa4..00000000000 --- a/3rdparty/sol2/docs/source/api/as_table.rst +++ /dev/null @@ -1,28 +0,0 @@ -as_table -=========== -make sure an object is pushed as a table ----------------------------------------- - -.. code-block:: cpp - - template <typename T> - as_table_t { ... }; - - template <typename T> - as_table_t<T> as_function ( T&& container ); - -This function serves the purpose of ensuring that an object is pushed -- if possible -- like a table into Lua. The container passed here can be a pointer, a reference, a ``std::reference_wrapper`` around a container, or just a plain container value. It must have a begin/end function, and if it has a ``std::pair<Key, Value>`` as its ``value_type``, it will be pushed as a dictionary. Otherwise, it's pushed as a sequence. - -.. code-block:: cpp - - sol::state lua; - lua.open_libraries(); - lua.set("my_table", sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5 })); - lua.script("for k, v in ipairs(my_table) do print(k, v) assert(k == v) end"); - - -Note that any caveats with Lua tables apply the moment it is serialized, and the data cannot be gotten out back out in C++ as a C++ type without explicitly using the ``as_table_t`` marker for your get and conversion operations using Sol. - -If you need this functionality with a member variable, use a :doc:`property on a getter function<property>` that returns the result of ``sol::as_table``. - -This marker does NOT apply to :doc:`usertypes<usertype>`.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/c_call.rst b/3rdparty/sol2/docs/source/api/c_call.rst deleted file mode 100644 index 36395eea549..00000000000 --- a/3rdparty/sol2/docs/source/api/c_call.rst +++ /dev/null @@ -1,71 +0,0 @@ -c_call -====== -Templated type to transport functions through templates -------------------------------------------------------- - -.. code-block:: cpp - - template <typename Function, Function f> - int c_call (lua_State* L); - - template <typename... Functions> - int c_call (lua_State* L); - -The goal of ``sol::c_call<...>`` is to provide a way to wrap a function and transport it through a compile-time context. This enables faster speed at the cost of a much harder to read / poorer interface. ``sol::c_call`` expects a type for its first template argument, and a value of the previously provided type for the second template argument. To make a compile-time transported overloaded function, specify multiple functions in the same ``type, value`` pairing, but put it inside of a ``sol::wrap``. Note that is can also be placed into the argument list for a :doc:`usertype<usertype>` as well. - -It is advisable for the user to consider making a macro to do the necessary ``decltype( &function_name, ), function_name``. Sol does not provide one because many codebases already have `one similar to this`_. - -Here's an example below of various ways to use ``sol::c_call``: - -.. code-block:: cpp - :linenos: - :caption: Compile-time transported function calls - - #include "sol.hpp" - - int f1(int) { return 32; } - int f2(int, int) { return 1; } - struct fer { - double f3(int, int) { - return 2.5; - } - }; - - - int main() { - - sol::state lua; - // overloaded function f - lua.set("f", sol::c_call<sol::wrap<decltype(&f1), &f1>, sol::wrap<decltype(&f2), &f2>, sol::wrap<decltype(&fer::f3), &fer::f3>>); - // singly-wrapped function - lua.set("g", sol::c_call<sol::wrap<decltype(&f1), &f1>>); - // without the 'sol::wrap' boilerplate - lua.set("h", sol::c_call<decltype(&f2), &f2>); - // object used for the 'fer' member function call - lua.set("obj", fer()); - - // call them like any other bound function - lua.script("r1 = f(1)"); - lua.script("r2 = f(1, 2)"); - lua.script("r3 = f(obj, 1, 2)"); - lua.script("r4 = g(1)"); - lua.script("r5 = h(1, 2)"); - - // get the results and see - // if it worked out - int r1 = lua["r1"]; - // r1 == 32 - int r2 = lua["r2"]; - // r2 == 1 - double r3 = lua["r3"]; - // r3 == 2.5 - int r4 = lua["r4"]; - // r4 == 32 - int r5 = lua["r5"]; - // r5 == 1 - - return 0; - } - - -.. _one similar to this: http://stackoverflow.com/a/5628222/5280922 diff --git a/3rdparty/sol2/docs/source/api/compatibility.rst b/3rdparty/sol2/docs/source/api/compatibility.rst deleted file mode 100644 index 3299bff931b..00000000000 --- a/3rdparty/sol2/docs/source/api/compatibility.rst +++ /dev/null @@ -1,16 +0,0 @@ -compatibility.hpp -================= -Lua 5.3/5.2 compatibility for Lua 5.1/LuaJIT --------------------------------------------- - -This is a detail header used to maintain compatability with the 5.2 and 5.3 APIs. It contains code from the MIT-Licensed `Lua code`_ in some places and also from the `lua-compat`_ repository by KeplerProject. - -It is not fully documented as this header's only purpose is for internal use to make sure Sol compiles across all platforms / distributions with no errors or missing Lua functionality. If you think there's some compatibility features we are missing or if you are running into redefinition errors, please make an `issue in the issue tracker`_. - -If you have this already in your project or you have your own compatibility layer, then please ``#define SOL_NO_COMPAT 1`` before including ``sol.hpp`` or pass this flag on the command line to turn off the compatibility wrapper. - -For the licenses, see :doc:`here<../licenses>` - -.. _issue in the issue tracker: https://github.com/ThePhD/sol2/issues/ -.. _Lua code: http://www.Lua.org/ -.. _lua-compat: https://github.com/keplerproject/lua-compat-5.3
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/containers.rst b/3rdparty/sol2/docs/source/api/containers.rst deleted file mode 100644 index 8e084a908fd..00000000000 --- a/3rdparty/sol2/docs/source/api/containers.rst +++ /dev/null @@ -1,103 +0,0 @@ -containers -========== -for handling ``std::vector/map/set`` and others ------------------------------------------------ - -Sol2 automatically converts containers (detected using the ``sol::is_container<T>`` type trait, which simply looks for begin / end) to be a special kind of userdata with metatable on it. For Lua 5.2 and 5.3, this is extremely helpful as you can make typical containers behave like Lua tables without losing the actual container that they came from, as well as a small amount of indexing and other operations that behave properly given the table type. - - -a complete example ------------------- - -Here's a complete working example of it working for Lua 5.3 and Lua 5.2, and how you can retrieve out the container in all versions: - -.. code-block:: cpp - :caption: containers.cpp - - #define SOL_CHECK_ARGUMENTS - #include <sol.hpp> - - int main() { - sol::state lua; - lua.open_libraries(); - - lua.script(R"( - function f (x) - print('--- Calling f ---') - for k, v in pairs(x) do - print(k, v) - end - end - )"); - - // Have the function we - // just defined in Lua - sol::function f = lua["f"]; - - // Set a global variable called - // "arr" to be a vector of 5 lements - lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 }; - - // Call it, see 5 elements - // printed out - f(lua["arr"]); - - // Mess with it in C++ - std::vector<int>& reference_to_arr = lua["arr"]; - reference_to_arr.push_back(12); - - // Call it, see *6* elements - // printed out - f(lua["arr"]); - - return 0; - } - - -Note that this will not work well in Lua 5.1, as it has explicit table checks and does not check metamethods, even when ``pairs`` or ``ipairs`` is passed a table. In that case, you will need to use a more manual iteration scheme or you will have to convert it to a table. In C++, you can use :doc:`sol::as_table<as_table>` when passing something to the library to get a table out of it: ``lua["arr"] = as_table( std::vector<int>{ ... });``. For manual iteration in Lua code without using ``as_table`` for something with indices, try: - -.. code-block:: lua - :caption: iteration.lua - - for i = 1, #vec do - print(i, vec[i]) - end - -There are also other ways to iterate over key/values, but they can be difficult due to not having proper support in Lua 5.1. We recommend that you upgrade to Lua 5.2 or 5.3. - - -additional functions --------------------- - -Based on the type pushed, a few additional functions are added as "member functions" (``self`` functions called with ``obj:func()`` or ``obj.func(obj)`` syntax) within a Lua script: - -* ``my_container:clear()``: This will call the underlying containers ``clear`` function. -* ``my_container:add( key, value )`` or ``my_container:add( value )``: this will add to the end of the container, or if it is an associative or ordered container, simply put in an expected key-value pair into it. -* ``my_contaner:insert( where, value )`` or ``my_contaner:insert( key, value )``: similar to add, but it only takes two arguments. In the case of ``std::vector`` and the like, the first argument is a ``where`` integer index. The second argument is the value. For associative containers, a key and value argument are expected. - - -.. _container-detection: - -too-eager container detection? ------------------------------- - - -If you have a type that has ``begin`` or ``end`` member functions but don't provide iterators, you can specialize ``sol::is_container<T>`` to be ``std::false_type``, and that will treat the type as a regular usertype and push it as a regular userdata: - -.. code-block:: cpp - :caption: specialization.hpp - - struct not_container { - void begin() { - - } - - void end() { - - } - }; - - namespace sol { - template <> - struct is_container<not_container> : std::false_type {}; - }
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/coroutine.rst b/3rdparty/sol2/docs/source/api/coroutine.rst deleted file mode 100644 index 3d03da31f5c..00000000000 --- a/3rdparty/sol2/docs/source/api/coroutine.rst +++ /dev/null @@ -1,109 +0,0 @@ -coroutine -========= -resumable/yielding functions from Lua -------------------------------------- - -A ``coroutine`` is a :doc:`reference<reference>` to a function in Lua that can be called multiple times to yield a specific result. It is run on the :doc:`lua_State<state>` that was used to create it (see :doc:`thread<thread>` for an example on how to get a coroutine that runs on a thread separate from your usual "main" :doc:`lua_State<state>`). - -The ``coroutine`` object is entirely similar to the :doc:`protected_function<protected_function>` object, with additional member functions to check if a coroutine has yielded (:doc:`call_status::yielded<types>`) and is thus runnable again, whether it has completed (:ref:`call_status::ok<call-status>`) and thus cannot yield anymore values, or whether it has suffered an error (see :ref:`status()<status>` and :ref:`call_status<call-status>`'s error codes). - -For example, you can work with a coroutine like this: - -.. code-block:: lua - :caption: co.lua - - function loop() - while counter ~= 30 - do - coroutine.yield(counter); - counter = counter + 1; - end - return counter - end - -This is a function that yields: - -.. code-block:: cpp - :caption: main.cpp - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.script_file("co.lua"); - sol::coroutine cr = lua["loop"]; - - for (int counter = 0; // start from 0 - counter < 10 && cr; // we want 10 values, and we only want to run if the coroutine "cr" is valid - // Alternative: counter < 10 && cr.valid() - ++counter) { - // Call the coroutine, does the computation and then suspends - int value = cr(); - } - -Note that this code doesn't check for errors: to do so, you can call the function and assign it as ``auto result = cr();``, then check ``result.valid()`` as is the case with :doc:`protected_function<protected_function>`. Finally, you can run this coroutine on another thread by doing the following: - -.. code-block:: cpp - :caption: main_with_thread.cpp - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.script_file("co.lua"); - sol::thread runner = sol::thread::create(lua.lua_state()); - sol::state_view runnerstate = runner.state(); - sol::coroutine cr = runnerstate["loop"]; - - for (int counter = 0; counter < 10 && cr; ++counter) { - // Call the coroutine, does the computation and then suspends - int value = cr(); - } - -The following are the members of ``sol::coroutine``: - -members -------- - -.. code-block:: cpp - :caption: function: constructor - - coroutine(lua_State* L, int index = -1); - -Grabs the coroutine at the specified index given a ``lua_State*``. - -.. code-block:: cpp - :caption: returning the coroutine's status - :name: status - - call_status status() const noexcept; - -Returns the status of a coroutine. - - -.. code-block:: cpp - :caption: checks for an error - - bool error() const noexcept; - -Checks if an error occured when the coroutine was run. - -.. _runnable: - -.. code-block:: cpp - :caption: runnable and explicit operator bool - - bool runnable () const noexcept; - explicit operator bool() const noexcept; - -These functions allow you to check if a coroutine can still be called (has more values to yield and has not errored). If you have a coroutine object ``coroutine my_co = /*...*/``, you can either check ``runnable()`` or do ``if ( my_co ) { /* use coroutine */ }``. - -.. code-block:: cpp - :caption: calling a coroutine - - template<typename... Args> - protected_function_result operator()( Args&&... args ); - - template<typename... Ret, typename... Args> - decltype(auto) call( Args&&... args ); - - template<typename... Ret, typename... Args> - decltype(auto) operator()( types<Ret...>, Args&&... args ); - -Calls the coroutine. The second ``operator()`` lets you specify the templated return types using the ``my_co(sol::types<int, std::string>, ...)`` syntax. Check ``status()`` afterwards for more information about the success of the run or just check the coroutine object in an ifs tatement, as shown :ref:`above<runnable>`.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/error.rst b/3rdparty/sol2/docs/source/api/error.rst deleted file mode 100644 index 4bfe21e91a4..00000000000 --- a/3rdparty/sol2/docs/source/api/error.rst +++ /dev/null @@ -1,15 +0,0 @@ -error -===== -the single error/exception type -------------------------------- - -.. code-block:: cpp - - class error : public std::runtime_error { - public: - error(const std::string& str): std::runtime_error("Lua: error: " + str) {} - }; - -If an eror is thrown by Sol, it is going to be of this type. We use this in a single place: the default ``at_panic`` function we bind on construction of a :ref:`sol::state<set-panic>`. If you turn :doc:`off exceptions<../exceptions>`, the chances of you seeing this error are nil unless you specifically use it to pull errors out of things such as :doc:`sol::protected_function<protected_function>`. - -As it derives from ``std::runtime_error``, which derives from ``std::exception``, you can catch it with a ``catch (const std::exception& )`` clause in your try/catch blocks. You can retrieve a string error from Lua (Lua pushes all its errors as string returns) by using this type with any of the get or lookup functions in Sol.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/function.rst b/3rdparty/sol2/docs/source/api/function.rst deleted file mode 100644 index 1056bd2fe95..00000000000 --- a/3rdparty/sol2/docs/source/api/function.rst +++ /dev/null @@ -1,108 +0,0 @@ -function -======== -calling functions bound to Lua ------------------------------- - -.. note:: - - This abstraction assumes the function runs safely. If you expect your code to have errors (e.g., you don't always have explicit control over it or are trying to debug errors), please use :doc:`sol::protected_function<protected_function>`. - -.. code-block:: cpp - - class function : public reference; - -Function is a correct-assuming version of :doc:`protected_function<protected_function>`, omitting the need for typechecks and error handling. It is the default function type of Sol. Grab a function directly off the stack using the constructor: - -.. code-block:: cpp - :caption: constructor: function - - function(lua_State* L, int index = -1); - - -When called without the return types being specified by either a ``sol::types<...>`` list or a ``call<Ret...>( ... )`` template type list, it generates a :ref:`function_result<function-result>` class that gets implicitly converted to the requested return type. For example: - -.. code-block:: lua - :caption: func_barks.lua - :linenos: - - bark_power = 11; - - function woof ( bark_energy ) - return (bark_energy * (bark_power / 4)) - end - -The following C++ code will call this function from this file and retrieve the return value: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.script_file( "func_barks.lua" ); - - sol::function woof = lua["woof"]; - double numwoof = woof(20); - -The call ``woof(20)`` generates a :ref:`function_result<function-result>`, which is then implicitly converted to an ``double`` after being called. The intermediate temporary ``function_result`` is then destructed, popping the Lua function call results off the Lua stack. - -You can also return multiple values by using ``std::tuple``, or if you need to bind them to pre-existing variables use ``sol::tie``: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.script( "function f () return 10, 11, 12 end" ); - - sol::function f = lua["f"]; - std::tuple<int, int, int> abc = f(); // 10, 11, 12 from Lua - // or - int a, b, c; - sol::tie(a, b, c) = f(); // a = 10, b = 11, c = 12 from Lua - -This makes it much easier to work with multiple return values. Using ``std::tie`` from the C++ standard will result in dangling references or bad behavior because of the very poor way in which C++ tuples/``std::tie`` were specified and implemented: please use ``sol::tie( ... )`` instead to satisfy any multi-return needs. - -.. _function-result-warning: - -.. warning:: - - Do NOT save the return type of a :ref:`function_result<function-result>` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. Unlike its counterpart :ref:`protected_function_result<protected-function-result>`, ``function_result`` is NOT safe to store as it assumes that its return types are still at the top of the stack and when its destructor is called will pop the number of results the function was supposed to return off the top of the stack. If you mess with the Lua stack between saving ``function_result`` and it being destructed, you will be subject to an incredible number of surprising and hard-to-track bugs. Don't do it. - -.. code-block:: cpp - :caption: function: call operator / function call - - template<typename... Args> - protected_function_result operator()( Args&&... args ); - - template<typename... Ret, typename... Args> - decltype(auto) call( Args&&... args ); - - template<typename... Ret, typename... Args> - decltype(auto) operator()( types<Ret...>, Args&&... args ); - -Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types<int, std::string>, ...)`` syntax. Function assumes there are no runtime errors, and thusly will call the ``atpanic`` function if an error does occur. - - -.. _function-argument-handling: - -functions and argument passing ------------------------------- - -.. note:: - - All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state<state>` or :doc:`sol::table<table>`, value semantics are not used here. It is forwarding reference semantics, which do not copy/move unless it is specifically done by the receiving functions / specifically done by the user. - - -.. note:: - - This also means that you should pass and receive arguments in certain ways to maximize efficiency. For example, ``sol::table``, ``sol::object``, ``sol::userdata`` and friends are fairly cheap to copy, and should simply by taken as values. This includes primitive types like ``int`` and ``double``. However, C++ types -- if you do not want copies -- should be taken as ``const type&`` or ``type&``, to save on copies if it's important. Note that taking references from Lua also means you can modify the data inside of Lua directly, so be careful. Lua by default deals with things mostly by reference (save for primitive types). - - You can get even more speed out of ``sol::object`` style of types by taking a ``sol::stack_object`` (or ``sol::stack_...``, where ``...`` is ``userdata``, ``reference``, ``table``, etc.). These reference a stack position directly rather than cheaply/safely the internal Lua reference to make sure it can't be swept out from under you. Note that if you manipulate the stack out from under these objects, they may misbehave, so please do not blow up your Lua stack when working with these types. - - ``std::string`` (and ``std::wstring``) are special. Lua stores strings as ``const char*`` null-terminated strings. ``std::string`` will copy, so taking a ``std::string`` by value or by const reference still invokes a copy operation. You can take a ``const char*``, but that will mean you're exposed to what happens on the Lua stack (if you change it and start chopping off function arguments from it in your function calls and such, as warned about previously). - - -function call safety --------------------- - -You can have functions here and on usertypes check to definitely make sure that the types passed to C++ functions are what they're supposed to be by adding a ``#define SOL_CHECK_ARGUMENTS`` before including Sol, or passing it on the command line. Otherwise, for speed reasons, these checks are only used where absolutely necessary (like discriminating between :doc:`overloads<overload>`). See :doc:`safety<../safety>` for more information.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/make_reference.rst b/3rdparty/sol2/docs/source/api/make_reference.rst deleted file mode 100644 index cd39b5a31d9..00000000000 --- a/3rdparty/sol2/docs/source/api/make_reference.rst +++ /dev/null @@ -1,26 +0,0 @@ -make_object/make_reference -========================== -Create a value on the Lua stack and return it ---------------------------------------------- - -.. code-block:: cpp - :caption: function: make_reference - :name: make-reference - - template <typename R = reference, bool should_pop = (R is not base of sol::stack_index), typename T> - R make_reference(lua_State* L, T&& value); - template <typename T, typename R = reference, bool should_pop = (R is base of sol::stack_index), typename... Args> - R make_reference(lua_State* L, Args&&... args); - -Makes an ``R`` out of the value. The first overload deduces the type from the passed in argument, the second allows you to specify a template parameter and forward any relevant arguments to ``sol::stack::push``. The type figured out for ``R`` is what is referenced from the stack. This allows you to request arbitrary pop-able types from Sol and have it constructed from ``R(lua_State* L, int stack_index)``. If the template boolean ``should_pop`` is ``true``, the value that was pushed will be popped off the stack. It defaults to popping, but if it encounters a type such as :doc:`sol::stack_reference<stack_reference>` (or any of its typically derived types in Sol), it will leave the pushed values on the stack. - -.. code-block:: cpp - :caption: function: make_object - :name: make-object - - template <typename T> - object make_object(lua_State* L, T&& value); - template <typename T, typename... Args> - object make_object(lua_State* L, Args&&... args); - -Makes an object out of the value. It pushes it onto the stack, then pops it into the returned ``sol::object``. The first overload deduces the type from the passed in argument, the second allows you to specify a template parameter and forward any relevant arguments to ``sol::stack::push``. The implementation essentially defers to :ref:`sol::make_reference<make-reference>` with the specified arguments, ``R == object`` and ``should_pop == true``. It is preferred that one uses the :ref:`in_place object constructor instead<overloaded-object-constructor>`, since it's probably easier to deal with, but both versions will be supported for forever, since there's really no reason not to and people already have dependencies on ``sol::make_object``. diff --git a/3rdparty/sol2/docs/source/api/metatable_key.rst b/3rdparty/sol2/docs/source/api/metatable_key.rst deleted file mode 100644 index 718eb2b2ffc..00000000000 --- a/3rdparty/sol2/docs/source/api/metatable_key.rst +++ /dev/null @@ -1,154 +0,0 @@ -metatable_key -============= -A key for setting and getting an object's metatable ---------------------------------------------------- - -.. code-block:: cpp - - struct metatable_key_t {}; - const metatable_key_t metatable_key; - -You can use this in conjunction with :doc:`sol::table<table>` to set/get a metatable. Lua metatables are powerful ways to override default behavior of objects for various kinds of operators, among other things. Here is an entirely complete example, showing getting and working with a :doc:`usertype<usertype>`'s metatable defined by Sol: - -.. code-block:: cpp - :caption: messing with metatables - :linenos: - - #include <sol.hpp> - - int main () { - - struct bark { - int operator()(int x) { - return x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<bark>("bark", - sol::meta_function::call_function, &bark::operator() - ); - - bark b; - lua.set("b", &b); - - sol::table b_as_table = lua["b"]; - sol::table b_metatable = b_as_table[sol::metatable_key]; - sol::function b_call = b_metatable["__call"]; - sol::function b_as_function = lua["b"]; - - int result1 = b_as_function(1); - int result2 = b_call(b, 1); - // result1 == result2 == 1 - } - -It's further possible to have a "Dynamic Getter" (`thanks to billw2012 and Nava2 for this example`_!): - -.. code-block:: cpp - :caption: One way to make dynamic properties (there are others!) - :linenos: - - #include <sol.hpp> - #include <unordered_map> - - struct PropertySet { - sol::object get_property_lua(const char* name, sol::this_state s) - { - auto& var = props[name]; - return sol::make_object(s, var); - } - - void set_property_lua(const char* name, sol::stack_object object) - { - props[name] = object.as<std::string>(); - } - - std::unordered_map<std::string, std::string> props; - }; - - struct DynamicObject { - PropertySet& get_dynamic_props() { - return dynamic_props; - } - - PropertySet dynamic_props; - }; - - - int main () { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<PropertySet>("PropertySet", - sol::meta_function::new_index, &PropertySet::set_property_lua, - sol::meta_function::index, &PropertySet::get_property_lua - ); - - lua.new_usertype<DynamicObject>("DynamicObject", - "props", sol::property(&DynamicObject::get_dynamic_props) - ); - - lua.script(R"( - obj = DynamicObject:new() - obj.props.name = 'test name' - print('name = ' .. obj.props.name) - )"); - - std::string name = lua["obj"]["props"]["name"]; - // name == "test name"; - } - - -You can even manipulate the ability to set and get items using metatable objects on a usertype or similar: - -.. code-block:: cpp - :caption: messing with metatables - vector type - :linenos: - - #include <sol.hpp> - - class vector { - public: - double data[3]; - - vector() : data{ 0,0,0 } {} - - double& operator[](int i) - { - return data[i]; - } - - - static double my_index(vector& v, int i) - { - return v[i]; - } - - static void my_new_index(vector& v, int i, double x) - { - v[i] = x; - } - }; - - int main () { - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<vector>("vector", sol::constructors<sol::types<>>(), - sol::meta_function::index, &vector::my_index, - sol::meta_function::new_index, &vector::my_new_index); - lua.script("v = vector.new()\n" - "print(v[1])\n" - "v[2] = 3\n" - "print(v[2])\n" - ); - - vector& v = lua["v"]; - // v[0] == 0.0; - // v[1] == 0.0; - // v[2] == 3.0; - } - - -.. _thanks to billw2012 and Nava2 for this example: https://github.com/ThePhD/sol2/issues/71#issuecomment-225402055
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/object.rst b/3rdparty/sol2/docs/source/api/object.rst deleted file mode 100644 index f38f089cc4d..00000000000 --- a/3rdparty/sol2/docs/source/api/object.rst +++ /dev/null @@ -1,70 +0,0 @@ -object -====== -general-purpose safety reference to an existing object ------------------------------------------------------- - -.. code-block:: cpp - - class object : reference; - - -``object``'s goal is to allow someone to pass around the most generic form of a reference to something in Lua (or propogate a ``nil``). It is the logical extension of :doc:`sol::reference<reference>`, and is used in :ref:`sol::table's iterators<table-iterators>`. - - -members -------- - -.. code-block:: cpp - :caption: overloaded constructor: object - :name: overloaded-object-constructor - - template <typename T> - object(T&&); - object(lua_State* L, int index = -1); - template <typename T, typename... Args> - object(lua_State* L, in_place_t, T&& arg, Args&&... args); - template <typename T, typename... Args> - object(lua_State* L, in_place_type_t<T>, Args&&... args); - -There are 4 kinds of constructors here. One allows construction of an object from other reference types such as :doc:`sol::table<table>` and :doc:`sol::stack_reference<stack_reference>`. The second creates an object which references the specific element at the given index in the specified ``lua_State*``. The more advanced ``in_place...`` constructors create a single object by pushing the specified type ``T`` onto the stack and then setting it as the object. It gets popped from the stack afterwards (unless this is an instance of ``sol::stack_object``, in which case it is left on the stack). An example of using this and :doc:`sol::make_object<make_reference>` can be found in the `any_return example`_. - -.. code-block:: cpp - :caption: function: type conversion - - template<typename T> - decltype(auto) as() const; - -Performs a cast of the item this reference refers to into the type ``T`` and returns it. It obeys the same rules as :ref:`sol::stack::get\<T><getter>`. - -.. code-block:: cpp - :caption: function: type check - - template<typename T> - bool is() const; - -Performs a type check using the :ref:`sol::stack::check<checker>` api, after checking if the reference is valid. - - -non-members ------------ - -.. code-block:: cpp - :caption: functions: nil comparators - - bool operator==(const object& lhs, const nil_t&); - bool operator==(const nil_t&, const object& rhs); - bool operator!=(const object& lhs, const nil_t&); - bool operator!=(const nil_t&, const object& rhs); - -These allow a person to compare an ``sol::object`` against :ref:`nil<nil>`, which essentially checks if an object references a non-nil value, like so: - -.. code-block:: cpp - - if (myobj == sol::nil) { - // doesn't have anything... - } - -Use this to check objects. - - -.. _any_return example: https://github.com/ThePhD/sol2/blob/develop/examples/any_return.cpp
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/optional.rst b/3rdparty/sol2/docs/source/api/optional.rst deleted file mode 100644 index f999849bcd9..00000000000 --- a/3rdparty/sol2/docs/source/api/optional.rst +++ /dev/null @@ -1,6 +0,0 @@ -optional<T> -=========== - -This is an implemention of `optional from the standard library`_. If it detects that a proper optional exists, it will attempt to use it. This is mostly an implementation detail, used in the :ref:`sol::stack::check_get<stack-check-get>` and :ref:`sol::stack::get\<optional\<T>><stack-get>` and ``optional<T> maybe_value = table["arf"];`` implementations for additional safety reasons. - -.. _optional from the standard library: http://en.cppreference.com/w/cpp/utility/optional
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/overload.rst b/3rdparty/sol2/docs/source/api/overload.rst deleted file mode 100644 index 399b409d1af..00000000000 --- a/3rdparty/sol2/docs/source/api/overload.rst +++ /dev/null @@ -1,89 +0,0 @@ -overload -======== -calling different functions based on argument number/type ---------------------------------------------------------- - -this function helps users make overloaded functions that can be called from Lua using 1 name but multiple arguments. It is meant to replace the spaghetti of code whre users mock this up by doing strange if statemetns and switches on what version of a function to call based on `luaL_check{number/udata/string}`_. Its use is simple: whereever you can pass a function type to Lua, whether its on a :doc:`usertype<usertype>` or if you are just setting any kind of function with ``set`` or ``set_function`` (for :doc:`table<table>` or :doc:`state(_view)<state>`), simply wrap up the functions you wish to be considered for overload resolution on one function like so: - -.. code-block:: cpp - - sol::overload( func1, func2, ... funcN ); - - -The functions can be any kind of function / function object (lambda). Given these functions and struct: - -.. code-block:: cpp - :linenos: - - struct pup { - int barks = 0; - - void bark () { - ++barks; // bark! - } - - bool is_cute () const { - return true; - } - }; - - void ultra_bark( pup& p, int barks) { - for (; barks --> 0;) p.bark(); - } - - void picky_bark( pup& p, std::string s) { - if ( s == "bark" ) - p.bark(); - } - -You then use it just like you would for any other part of the api: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.set_function( "bark", sol::overload( - ultra_bark, - []() { return "the bark from nowhere"; } - ) ); - - lua.new_usertype<pup>( "pup", - // regular function - "is_cute", &pup::is_cute, - // overloaded function - "bark", sol::overload( &pup::bark, &picky_bark ) - ); - -Thusly, doing the following in Lua: - -.. code-block:: Lua - :caption: pup.lua - :linenos: - - local barker = pup.new() - pup:bark() -- calls member function pup::bark - pup:bark(20) -- calls ultra_bark - pup:bark("meow") -- picky_bark, no bark - pup:bark("bark") -- picky_bark, bark - - bark(pup, 20) -- calls ultra_bark - local nowherebark = bark() -- calls lambda which returns that string - -The actual class produced by ``sol::overload`` is essentially a type-wrapper around ``std::tuple`` that signals to the library that an overload is being created: - -.. code-block:: cpp - :caption: function: create overloaded set - :linenos: - - template <typename... Args> - struct overloaded_set : std::tuple<Args...> { /* ... */ }; - - template <typename... Args> - overloaded_set<Args...> overload( Args&&... args ); - -.. note:: - - Please keep in mind that doing this bears a runtime cost to find the proper overload. The cost scales directly not exactly with the number of overloads, but the number of functions that have the same argument count as each other (Sol will early-eliminate any functions that do not match the argument count). - -.. _luaL_check{number/udata/string}: http://www.Lua.org/manual/5.3/manual.html#luaL_checkinteger diff --git a/3rdparty/sol2/docs/source/api/property.rst b/3rdparty/sol2/docs/source/api/property.rst deleted file mode 100644 index e3ee02e2353..00000000000 --- a/3rdparty/sol2/docs/source/api/property.rst +++ /dev/null @@ -1,64 +0,0 @@ -property -======== - -.. code-block:: cpp - - template <typename Read, typename Write> - decltype(auto) property ( Read&& read_function, Write&& write_function ); - template <typename Read> - decltype(auto) property ( Read&& read_function ); - template <typename Write> - decltype(auto) property ( Write&& write_function ); - -These set of functions create a type which allows a setter and getter pair (or a single getter, or a single setter) to be used to create a variable that is either read-write, read-only, or write-only. When used during :doc:`usertype<usertype>` construction, it will create a variable that uses the setter/getter member function specified. - -.. code-block:: cpp - :caption: player.hpp - :linenos: - - class Player { - public: - int get_hp() const { - return hp; - } - - void set_hp( int value ) { - hp = value; - } - - int get_max_hp() const { - return hp; - } - - void set_max_hp( int value ) { - maxhp = value; - } - - private: - int hp = 50; - int maxHp = 50; - } - -.. code-block:: cpp - :caption: game.cpp - :linenos: - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set("theplayer", Player()); - - // Yes, you can register after you set a value and it will - // connect up the usertype automatically - lua.new_usertype<Player>( "Player", - "hp", sol::property(&Player::get_hp, &Player::set_hp), - "maxHp", sol::property(&Player::get_max_hp, &Player::set_max_hp) - ); - - -.. code-block:: lua - :caption: game-snippet.lua - - -- variable syntax, calls functions - theplayer.hp = 20 - print(theplayer.hp)
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/protect.rst b/3rdparty/sol2/docs/source/api/protect.rst deleted file mode 100644 index 4f14cb0db2a..00000000000 --- a/3rdparty/sol2/docs/source/api/protect.rst +++ /dev/null @@ -1,33 +0,0 @@ -protect -======= -Routine to mark a function / variable as requiring safety ---------------------------------------------------------- - -.. code-block:: cpp - - template <typename T> - auto protect( T&& value ); - -``sol::protect( my_func )`` allows you to protect a function call or member variable call when it is being set to Lua. It can be used with usertypes or when just setting a function into Sol. Below is an example that demonstrates that a call that would normally not error without :doc:`Safety features turned on<../safety>` that instead errors and makes the Lua safety-call wrapper ``pcall`` fail: - -.. code-block:: cpp - - struct protect_me { - int gen(int x) { - return x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<protect_me>("protect_me", - "gen", sol::protect( &protect_me::gen ) - ); - - lua.script(R"__( - pm = protect_me.new() - value = pcall(pm.gen,pm) - )__"); - ); - bool value = lua["value"]; - // value == false diff --git a/3rdparty/sol2/docs/source/api/protected_function.rst b/3rdparty/sol2/docs/source/api/protected_function.rst deleted file mode 100644 index c9fb9b4f425..00000000000 --- a/3rdparty/sol2/docs/source/api/protected_function.rst +++ /dev/null @@ -1,187 +0,0 @@ -protected_function -================== -Lua function calls that trap errors and provide error handling --------------------------------------------------------------- - -.. code-block:: cpp - - class protected_function : public reference; - -Inspired by a request from `starwing<https://github.com/starwing>` in the old repository, this class provides the same interface as :doc:`function<function>` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. You can grab a function directly off the stack using the constructor, or pass to it 2 valid functions, which we'll demonstrate a little later. - -When called without the return types being specified by either a ``sol::types<...>`` list or a ``call<Ret...>( ... )`` template type list, it generates a :doc:`protected_function_result<proxy>` class that gets implicitly converted to the requested return type. For example: - -.. code-block:: lua - :caption: pfunc_barks.lua - :linenos: - - bark_power = 11; - - function got_problems( error_msg ) - return "got_problems handler: " .. error_msg - end - - function woof ( bark_energy ) - if bark_energy < 20 - error("*whine*") - end - return (bark_energy * (bark_power / 4)) - end - - function woofers ( bark_energy ) - if bark_energy < 10 - error("*whine*") - end - return (bark_energy * (bark_power / 4)) - end - -The following C++ code will call this function from this file and retrieve the return value, unless an error occurs, in which case you can bind an error handling function like so: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.open_file( "pfunc_barks.lua" ); - - sol::protected_function problematicwoof = lua["woof"]; - problematicwoof.error_handler = lua["got_problems"]; - - auto firstwoof = problematic_woof(20); - if ( firstwoof.valid() ) { - // Can work with contents - double numwoof = first_woof; - } - else{ - // An error has occured - sol::error err = first_woof; - } - - // errors, calls handler and then returns a string error from Lua at the top of the stack - auto secondwoof = problematic_woof(19); - if (secondwoof.valid()) { - // Call succeeded - double numwoof = secondwoof; - } - else { - // Call failed - // Note that if the handler was successfully called, this will include - // the additional appended error message information of - // "got_problems handler: " ... - sol::error err = secondwoof; - std::string what = err.what(); - } - -This code is much more long-winded than its :doc:`function<function>` counterpart but allows a person to check for errors. The type here for ``auto`` are ``sol::protected_function_result``. They are implicitly convertible to result types, like all :doc:`proxy-style<proxy>` types are. - -Alternatively, with a bad or good function call, you can use ``sol::optional`` to check if the call succeeded or failed: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.open_file( "pfunc_barks.lua" ); - - sol::protected_function problematicwoof = lua["woof"]; - problematicwoof.error_handler = lua["got_problems"]; - - sol::optional<double> maybevalue = problematicwoof(19); - if (maybevalue) { - // Have a value, use it - double numwoof = maybevalue.value(); - } - else { - // No value! - } - -That makes the code a bit more concise and easy to reason about if you don't want to bother with reading the error. Thankfully, unlike ``sol::function_result``, you can save ``sol::protected_function_result`` in a variable and push/pop things above it on the stack where its returned values are. This makes it a bit more flexible than the rigid, performant ``sol::function_result`` type that comes from calling :doc:`sol::function<function>`. - -If you're confident the result succeeded, you can also just put the type you want (like ``double`` or ``std::string`` right there and it will get it. But, if it doesn't work out, sol can throw and/or panic if you have the :doc:`safety<../safety>` features turned on: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.open_file( "pfunc_barks.lua" ); - - // construct with function + error handler - // shorter than old syntax - sol::protected_function problematicwoof(lua["woof"], lua["got_problems"]); - - // dangerous if things go wrong! - double value = problematicwoof(19); - - -Finally, it is *important* to note you can set a default handler. The function is described below: please use it to avoid having to constantly set error handlers: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.open_file( "pfunc_barks.lua" ); - // sets got_problems as the default - // handler for all protected_function errors - sol::protected_function::set_default_handler(lua["got_problems"]); - - sol::protected_function problematicwoof = lua["woof"]; - sol::protected_function problematicwoofers = lua["woofers"]; - - double value = problematicwoof(19); - double value2 = problematicwoof(9); - - -members -------- - -.. code-block:: cpp - :caption: constructor: protected_function - - template <typename T> - protected_function( T&& func, reference handler = sol::protected_function::get_default_handler() ); - protected_function( lua_State* L, int index = -1, reference handler = sol::protected_function::get_default_handler() ); - -Constructs a ``protected_function``. Use the 2-argument version to pass a custom error handling function more easily. You can also set the :ref:`member variable error_handler<protected-function-error-handler>` after construction later. ``protected_function`` will always use the latest error handler set on the variable, which is either what you passed to it or the default *at the time of construction*. - -.. code-block:: cpp - :caption: function: call operator / protected function call - - template<typename... Args> - protected_function_result operator()( Args&&... args ); - - template<typename... Ret, typename... Args> - decltype(auto) call( Args&&... args ); - - template<typename... Ret, typename... Args> - decltype(auto) operator()( types<Ret...>, Args&&... args ); - -Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types<int, std::string>, ...)`` syntax. If you specify no return type in any way, it produces s ``protected_function_result``. - -.. note:: - - All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state<state>` or :doc:`sol::table<table>`, value semantics are not used here. It is forwarding reference semantics, which do not copy/move unless it is specifically done by the receiving functions / specifically done by the user. - - -.. code-block:: cpp - :caption: default handlers - - static const reference& get_default_handler (); - static void set_default_handler( reference& ref ); - -Get and set the Lua entity that is used as the default error handler. The default is a no-ref error handler. You can change that by calling ``protected_function::set_default_handler( lua["my_handler"] );`` or similar: anything that produces a reference should be fine. - -.. code-block:: cpp - :caption: variable: handler - :name: protected-function-error-handler - - reference error_handler; - -The error-handler that is called should a runtime error that Lua can detect occurs. The error handler function needs to take a single string argument (use type std::string if you want to use a C++ function bound to lua as the error handler) and return a single string argument (again, return a std::string or string-alike argument from the C++ function if you're using one as the error handler). If :doc:`exceptions<../exceptions>` are enabled, Sol will attempt to convert the ``.what()`` argument of the exception into a string and then call the error handling function. It is a :doc:`reference<reference>`, as it must refer to something that exists in the lua registry or on the Lua stack. This is automatically set to the default error handler when ``protected_function`` is constructed. - -.. note:: - - ``protected_function_result`` safely pops its values off the stack when its destructor is called, keeping track of the index and number of arguments that were supposed to be returned. If you remove items below it using ``lua_remove``, for example, it will not behave as expected. Please do not perform fundamentally stack-rearranging operations until the destructor is called (pushing/popping above it is just fine). - -To know more about how function arguments are handled, see :ref:`this note<function-argument-handling>`. diff --git a/3rdparty/sol2/docs/source/api/proxy.rst b/3rdparty/sol2/docs/source/api/proxy.rst deleted file mode 100644 index 897dbbaf7dd..00000000000 --- a/3rdparty/sol2/docs/source/api/proxy.rst +++ /dev/null @@ -1,201 +0,0 @@ -proxy, (protected\_)function_result - proxy_base derivatives -============================================================ -``table[x]`` and ``function(...)`` conversion struct ----------------------------------------------------- - -.. code-block:: c++ - - template <typename Recurring> - struct proxy_base; - - template <typename Table, typename Key> - struct proxy : proxy_base<...>; - - struct stack_proxy: proxy_base<...>; - - struct function_result : proxy_base<...>; - - struct protected_function_result: proxy_base<...>; - - -These classes provide implicit assignment operator ``operator=`` (for ``set``) and an implicit conversion operator ``operator T`` (for ``get``) to support items retrieved from the underlying Lua implementation, specifically :doc:`sol::table<table>` and the results of function calls on :doc:`sol::function<function>` and :doc:`sol::protected_function<protected_function>`. - -.. _proxy: - -proxy ------ - -``proxy`` is returned by lookups into :doc:`sol::table<table>` and table-like entities. Because it is templated on key and table type, it would be hard to spell: you can capture it using the word ``auto`` if you feel like you need to carry it around for some reason before using it. ``proxy`` evaluates its arguments lazily, when you finally call ``get`` or ``set`` on it. Here are some examples given the following lua script. - -.. code-block:: lua - :linenos: - :caption: lua nested table script - - bark = { - woof = { - [2] = "arf!" - } - } - - -After loading that file in or putting it in a string and reading the string directly in lua (see :doc:`state`), you can start kicking around with it in C++ like so: - -.. code-block:: c++ - :linenos: - - sol::state lua; - - // produces proxy, implicitly converts to std::string, quietly destroys proxy - std::string x = lua["bark"]["woof"][2]; - - -``proxy`` lazy evaluation: - -.. code-block:: c++ - :linenos: - :caption: multi-get - - auto x = lua["bark"]; - auto y = x["woof"]; - auto z = x[2]; - // retrivies value inside of lua table above - std::string value = z; // "arf!" - // Can change the value later... - z = 20; - // Yay, lazy-evaluation! - int changed_value = z; // now it's 20! - - -We don't recommend the above to be used across classes or between function: it's more of something you can do to save a reference to a value you like, call a script or run a lua function, and then get it afterwards. You can also set functions (and function objects :ref:`*<note 1>`) this way, and retrieve them as well. - -.. code-block:: c++ - :linenos: - - lua["bark_value"] = 24; - lua["chase_tail"] = floof::chase_tail; // chase_tail is a free function - - -members -------- - -.. code-block:: c++ - :caption: functions: [overloaded] implicit conversion get - :name: implicit-get - - requires( sol::is_primitive_type<T>::value == true ) - template <typename T> - operator T() const; - - requires( sol::is_primitive_type<T>::value == false ) - template <typename T> - operator T&() const; - -Gets the value associated with the keys the proxy was generated and convers it to the type ``T``. Note that this function will always return ``T&``, a non-const reference, to types which are not based on :doc:`sol::reference<reference>` and not a :doc:`primitive lua type<types>` - -.. code-block:: c++ - :caption: function: get a value - :name: regular-get - - template <typename T> - decltype(auto) get( ) const; - -Gets the value associated with the keys and converts it to the type ``T``. - -.. code-block:: c++ - :caption: function: optionally get a value - :name: regular-get-or - - template <typename T, typename Otherwise> - optional<T> get_or( Otherwise&& otherise ) const; - -Gets the value associated with the keys and converts it to the type ``T``. If it is not of the proper type, it will return a ``sol::nullopt`` instead. - -``operator[]`` proxy-only members ---------------------------------- - -.. code-block:: c++ - :caption: function: valid - :name: proxy-valid - - bool valid () const; - -Returns whether this proxy actually refers to a valid object. It uses :ref:`sol::stack::probe_get_field<stack-probe-get-field>` to determine whether or not its valid. - -.. code-block:: c++ - :caption: functions: [overloaded] implicit set - :name: implicit-set - - requires( sol::detail::Function<Fx> == false ) - template <typename T> - proxy& operator=( T&& value ); - - requires( sol::detail::Function<Fx> == true ) - template <typename Fx> - proxy& operator=( Fx&& function ); - -Sets the value associated with the keys the proxy was generated with to ``value``. If this is a function, calls ``set_function``. If it is not, just calls ``set``. Does not exist on :ref:`function_result<function-result>` or :ref:`protected_function_result<protected-function-result>`. See :ref:`note<note 1>` for caveats. - -.. code-block:: c++ - :caption: function: set a callable - :name: regular-set-function - - template <typename Fx> - proxy& set_function( Fx&& fx ); - -Sets the value associated with the keys the proxy was generated with to a function ``fx``. Does not exist on :ref:`function_result<function-result>` or :ref:`protected_function_result<protected-function-result>`. - - -.. code-block:: c++ - :caption: function: set a value - :name: regular-set - - template <typename T> - proxy& set( T&& value ); - -Sets the value associated with the keys the proxy was generated with to ``value``. Does not exist on :ref:`function_result<function-result>` or :ref:`protected_function_result<protected-function-result>`. - -stack_proxy ------------ - -``sol::stack_proxy`` is what gets returned by :doc:`sol::variadic_args<variadic_args>` and other parts of the framework. It is similar to proxy, but is meant to alias a stack index and not a named variable. - -.. _function-result: - -function_result ---------------- - -``function_result`` is a temporary-only, intermediate-only implicit conversion worker for when :doc:`function<function>` is called. It is *NOT* meant to be stored or captured with ``auto``. It provides fast access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=``, as is present on :ref:`proxy<proxy>`. - - -.. _protected-function-result: - -protected_function_result -------------------------- - -``protected_function_result`` is a nicer version of ``function_result`` that can be used to detect errors. Its gives safe access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=`` as is present on :ref:`proxy<proxy>`. - - -.. _note 1: - -on function objects and proxies -------------------------------- - -Consider the following: - -.. code-block:: cpp - :linenos: - :caption: Note 1 Case - - struct doge { - int bark; - - void operator()() { - bark += 1; - } - }; - - sol::state lua; - lua["object"] = doge{}; // bind constructed doge to "object" - // but it binds as a function - -When you use the ``lua["object"] = doge{};`` from above, keep in mind that Sol detects if this is a function *callable with any kind of arguments*. Since ``doge`` has overriden ``return_type operator()( argument_types... )`` on itself, it results in satisfying the ``requires`` constraint from above. This means that if you have a user-defined type you want to bind as a :doc:`userdata with usertype semantics<usertype>` with this syntax, it might get bound as a function and not as a user-defined type (d'oh!). use ``lua["object"].set(doge)`` directly to avoid this, or ``lua["object"].set_function(doge{})`` to perform this explicitly.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/readonly.rst b/3rdparty/sol2/docs/source/api/readonly.rst deleted file mode 100644 index e36db3358ff..00000000000 --- a/3rdparty/sol2/docs/source/api/readonly.rst +++ /dev/null @@ -1,68 +0,0 @@ -readonly -======== -routine to mark a member variable as read-only ----------------------------------------------- - -.. code-block:: cpp - - template <typename T> - auto readonly( T&& value ); - -The goal of read-only is to protect a variable set on a usertype or a function. Simply wrap it around a member variable, e.g. ``sol::readonly( &my_class::my_member_variable )`` in the appropriate place to use it. If someone tries to set it, it will throw an error. This can ONLY work on :doc:`usertypes<usertype>` and when you specifically set a member variable as a function and wrap it with this. It will NOT work anywhere else: doing so will invoke compiler errors. - -If you are looking to make a read-only table, you need to go through a bit of a complicated song and dance by overriding the ``__index`` metamethod. Here's a complete example on the way to do that using ``sol``: - - -.. code-block:: cpp - :caption: read-only.cpp - - #define SOL_CHECK_ARGUMENTS - #include <sol.hpp> - - #include <iostream> - - struct object { - void my_func() { - std::cout << "hello\n"; - } - }; - - int deny(lua_State* L) { - return luaL_error(L, "HAH! Deniiiiied!"); - } - - int main() { - sol::state lua; - lua.open_libraries(sol::lib::base); - - object my_obj; - - sol::table obj_table = lua.create_named_table("object"); - - sol::table obj_metatable = lua.create_table_with(); - obj_metatable.set_function("my_func", &object::my_func, &my_obj); - // Set whatever else you need to - // on the obj_metatable, - // not on the obj_table itself! - - // Properly self-index metatable to block things - obj_metatable[sol::meta_function::new_index] = deny; - obj_metatable[sol::meta_function::index] = obj_metatable; - - // Set it on the actual table - obj_table[sol::metatable_key] = obj_metatable; - - try { - lua.script(R"( - print(object.my_func) - object["my_func"] = 24 - print(object.my_func) - )"); - } - catch (const std::exception& e) { - std::cout << e.what() << std::endl; - } - return 0; - } - -It is a verbose example, but it explains everything. Because the process is a bit involved and can have unexpected consequences for users that make their own tables, making read-only tables is something that we ask the users to do themselves with the above code, as getting the semantics right for the dozens of use cases would be tremendously difficult. diff --git a/3rdparty/sol2/docs/source/api/reference.rst b/3rdparty/sol2/docs/source/api/reference.rst deleted file mode 100644 index 57869de7db0..00000000000 --- a/3rdparty/sol2/docs/source/api/reference.rst +++ /dev/null @@ -1,78 +0,0 @@ -reference -========= -general purpose reference to Lua object in registry ---------------------------------------------------- - -.. code-block:: cpp - :caption: reference - - class reference; - -This type keeps around a reference to something that was on the stack and places it in the Lua registry. It is the backbone for all things that reference items on the stack and needs to keep them around beyond their appearance and lifetime on said Lua stack. Its progeny include :doc:`sol::coroutine<coroutine>`, :doc:`sol::function<function>`, :doc:`sol::protected_function<protected_function>`, :doc:`sol::object<object>`, :doc:`sol::table<table>`/:doc:`sol::global_table<table>`, :doc:`sol::thread<thread>`, and :doc:`sol::userdata<userdata>`. - -For all of these types, there's also a ``stack_{x}`` version of them, such as ``stack_table`` - - -members -------- - -.. code-block:: cpp - :caption: constructor: reference - - reference(lua_State* L, int index = -1); - reference(lua_State* L, ref_index index); - template <typename Object> - reference(Object&& o); - -The first constructor creates a reference from the Lua stack at the specified index, saving it into the metatable registry. The second attemtps to register something that already exists in the registry. The third attempts to reference a pre-existing object and create a reference to it. These constructors are exposed on all types that derive from ``sol::reference``, meaning that you can grab tables, functions, and coroutines from the registry, stack, or from other objects easily. - -.. code-block:: cpp - :caption: function: push referred-to element from the stack - - int push() const noexcept; - -This function pushes the referred-to data onto the stack and returns how many things were pushed. Typically, it returns 1. - -.. code-block:: cpp - :caption: function: reference value - - int registry_index() const noexcept; - -The value of the reference in the registry. - -.. code-block:: cpp - :caption: functions: non-nil, non-null check - - bool valid () const noexcept; - explicit operator bool () const noexcept; - -These functions check if the reference at ``T`` is valid: that is, if it is not :ref:`nil<nil>` and if it is not non-existing (doesn't refer to anything, including nil) reference. The explicit operator bool allows you to use it in the context of an ``if ( my_obj )`` context. - -.. code-block:: cpp - :caption: function: retrieves the type - - type get_type() const noexcept; - -Gets the :doc:`sol::type<types>` of the reference; that is, the Lua reference. - -.. code-block:: cpp - :caption: function: lua_State* of the reference - - lua_State* lua_state() const noexcept; - -Gets the ``lua_State*`` this reference exists in. - - -non-members ------------ - -.. code-block:: cpp - :caption: functions: reference comparators - - bool operator==(const reference&, const reference&); - bool operator!=(const reference&, const reference&); - -Compares two references using the Lua API's `lua_compare`_ for equality. - - -.. _lua_compare: https://www.lua.org/manual/5.3/manual.html#lua_compare diff --git a/3rdparty/sol2/docs/source/api/resolve.rst b/3rdparty/sol2/docs/source/api/resolve.rst deleted file mode 100644 index b1ceffd0134..00000000000 --- a/3rdparty/sol2/docs/source/api/resolve.rst +++ /dev/null @@ -1,65 +0,0 @@ -resolve -======= -utility to pick overloaded C++ function calls ---------------------------------------------- - -.. code-block:: cpp - :caption: function: resolve C++ overload - - template <typename... Args, typename F> - constexpr auto resolve( F f ); - -``resolve`` is a function that is meant to help users pick a single function out of a group of overloaded functions in C++. It works for *both member and free functions* You can use it to pick overloads by specifying the signature as the first template argument. Given a collection of overloaded functions: - -.. code-block:: cpp - :linenos: - - int overloaded(int x); - int overloaded(int x, int y); - int overloaded(int x, int y, int z); - - struct thing { - int overloaded() const; - int overloaded(int x); - int overloaded(int x, int y); - int overloaded(int x, int y, int z); - }; - -You can disambiguate them using ``resolve``: - -.. code-block:: cpp - :linenos: - - auto one_argument_func = resolve<int(int)>( overloaded ); - auto two_argument_func = resolve<int(int, int)>( overloaded ); - auto three_argument_func = resolve<int(int, int, int)>( overloaded ); - auto member_three_argument_func = resolve<int(int, int, int)>( &thing::overloaded ); - auto member_zero_argument_const_func = resolve<int() const>( &thing::overloaded ); - -It is *important* to note that ``const`` is placed at the end for when you desire const overloads. You will get compiler errors if you are not specific and do not properly disambiguate for const member functions. This resolution also becomes useful when setting functions on a :doc:`table<table>` or :doc:`state_view<state>`: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.set_function("a", resolve<int(int)>( overloaded ) ); - lua.set_function("b", resolve<int(int, int)>( overloaded )); - lua.set_function("c", resolve<int(int, int, int)>( overloaded )); - - -It can also be used with :doc:`sol::c_call<c_call>`: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - auto f = sol::c_call< - decltype(sol::resolve<int(int, int)>(&overloaded)), - sol::resolve<int(int, int)>(&overloaded) - >; - lua.set_function("f", f); - - lua.script("f(1, 2)"); - diff --git a/3rdparty/sol2/docs/source/api/simple_usertype.rst b/3rdparty/sol2/docs/source/api/simple_usertype.rst deleted file mode 100644 index 0502e6b24ed..00000000000 --- a/3rdparty/sol2/docs/source/api/simple_usertype.rst +++ /dev/null @@ -1,33 +0,0 @@ -simple_usertype<T> -================== -structures and classes from C++ made available to Lua code (simpler) --------------------------------------------------------------------- - - -This type is no different from :doc:`regular usertype<usertype>`, but allows much of its work to be done at runtime instead of compile-time. You can reduce compilation times from a plain `usertype` when you have an exceedingly bulky registration listing. - -You can set functions incrementally to reduce compile-time burden with ``simple_usertype`` as well, as shown in `this example`_. This means both adding incrementally during registration, and afterwards by adding items to the metatable at runtime. - -Some developers used ``simple_usertype`` in older versions to have variables automatically be functions. To achieve this behavior, wrap the desired variable into :doc:`sol::as_function<as_function>`. - -The performance `seems to be good enough`_ (see below graphs as well) to not warn about any implications of having to serialize things at runtime. You do run the risk of using (slightly?) more memory, since variables and functions need to be stored differently and separately from the metatable data itself like with a regular ``usertype``. The goal here was to avoid compiler complaints about too-large usertypes (some individuals needed to register 190+ functions, and the compiler choked from the templated implementation of ``usertype``). As of Sol 2.14, this implementation has been heavily refactored to allow for all the same syntax and uses of usertype to apply here, with no caveats/exceptions. - - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls%20(simple).png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls%20(simple).png - :alt: bind several member functions to an object and call them in Lua code - - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access%20(simple).png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access%20(simple).png - :alt: bind a member variable to an object and modify it with Lua code - - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access%2C%20last%20registered%20(simple).png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access%2C%20last%20registered%20(simple).png - :alt: bind MANY member variables to an object and modify it with Lua code - - - -.. _seems to be good enough: https://github.com/ThePhD/sol2/issues/202#issuecomment-246767629 -.. _this example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/stack.rst b/3rdparty/sol2/docs/source/api/stack.rst deleted file mode 100644 index 0ebb2d2e40b..00000000000 --- a/3rdparty/sol2/docs/source/api/stack.rst +++ /dev/null @@ -1,199 +0,0 @@ -stack namespace -=============== -the nitty-gritty core abstraction layer over Lua ------------------------------------------------- - -.. code-block:: cpp - - namespace stack - -If you find that the higher level abstractions are not meeting your needs, you may want to delve into the ``stack`` namespace to try and get more out of Sol. ``stack.hpp`` and the ``stack`` namespace define several utilities to work with Lua, including pushing / popping utilities, getters, type checkers, Lua call helpers and more. This namespace is not thoroughly documented as the majority of its interface is mercurial and subject to change between releases to either heavily boost performance or improve the Sol :doc:`api<api-top>`. - -There are, however, a few :ref:`template customization points<extension_points>` that you may use for your purposes and a handful of potentially handy functions. These may help if you're trying to slim down the code you have to write, or if you want to make your types behave differently throughout the Sol stack. Note that overriding the defaults **can** throw out many of the safety guarantees Sol provides: therefore, modify the :ref:`extension points<extension_points>` at your own discretion. - -structures ----------- - -.. code-block:: cpp - :caption: struct: record - :name: stack-record - - struct record { - int last; - int used; - - void use(int count); - }; - -This structure is for advanced usage with :ref:`stack::get<stack-get>` and :ref:`stack::check_get<stack-get>`. When overriding the customization points, it is important to call the ``use`` member function on this class with the amount of things you are pulling from the stack. ``used`` contains the total accumulation of items produced. ``last`` is the number of items gotten from the stack with the last operation (not necessarily popped from the stack). In all trivial cases for types, ``last == 1`` and ``used == 1`` after an operation; structures such as ``std::pair`` and ``std::tuple`` may pull more depending on the classes it contains. - -When overriding the :doc:`customization points<../tutorial/customization>`, please note that this structure should enable you to push multiple return values and get multiple return values to the stack, and thus be able to seamlessly pack/unpack return values from Lua into a single C++ struct, and vice-versa. This functionality is only recommended for people who need to customize the library further than the basics. It is also a good way to add support for the type and propose it back to the original library so that others may benefit from your work. - -Note that customizations can also be put up on a separate page here, if individuals decide to make in-depth custom ones for their framework or other places. - -members -------- - -.. code-block:: cpp - :caption: function: get - :name: stack-get - - template <typename T> - auto get( lua_State* L, int index = -1 ) - template <typename T> - auto get( lua_State* L, int index, record& tracking ) - -Retrieves the value of the object at ``index`` in the stack. The return type varies based on ``T``: with primitive types, it is usually ``T``: for all unrecognized ``T``, it is generally a ``T&`` or whatever the extension point :ref:`stack::getter\<T><getter>` implementation returns. The type ``T`` has top-level ``const`` qualifiers and reference modifiers removed before being forwarded to the extension point :ref:`stack::getter\<T><getter>` struct. ``stack::get`` will default to forwarding all arguments to the :ref:`stack::check_get<stack-check-get>` function with a handler of ``type_panic`` to strongly alert for errors, if you ask for the :doc:`safety<../safety>`. - -`record` - -You may also retrieve an :doc:`sol::optional\<T><optional>` from this as well, to have it attempt to not throw errors when performing the get and the type is not correct. - -.. code-block:: cpp - :caption: function: check - :name: stack-check - - template <typename T> - bool check( lua_State* L, int index = -1 ) - - template <typename T, typename Handler> - bool check( lua_State* L, int index, Handler&& handler ) - -Checks if the object at ``index`` is of type ``T``. If it is not, it will call the ``handler`` function with ``lua_State*``, ``int index``, ``type`` expected, and ``type`` actual as arguments. - -.. code-block:: cpp - :caption: function: check_get - :name: stack-check-get - - template <typename T> - auto check_get( lua_State* L, int index = -1 ) - template <typename T, typename Handler> - auto check_get( lua_State* L, int index, Handler&& handler, record& tracking ) - -Retrieves the value of the object at ``index`` in the stack, but does so safely. It returns an ``optional<U>``, where ``U`` in this case is the return type deduced from ``stack::get<T>``. This allows a person to properly check if the type they're getting is what they actually want, and gracefully handle errors when working with the stack if they so choose to. You can define ``SOL_CHECK_ARGUMENTS`` to turn on additional :doc:`safety<../safety>`, in which ``stack::get`` will default to calling this version of the function with a handler of ``type_panic`` to strongly alert for errors and help you track bugs if you suspect something might be going wrong in your system. - -.. code-block:: cpp - :caption: function: push - :name: stack-push - - // push T inferred from call site, pass args... through to extension point - template <typename T, typename... Args> - int push( lua_State* L, T&& item, Args&&... args ) - - // push T that is explicitly specified, pass args... through to extension point - template <typename T, typename Arg, typename... Args> - int push( lua_State* L, Arg&& arg, Args&&... args ) - - // recursively call the the above "push" with T inferred, one for each argument - template <typename... Args> - int multi_push( lua_State* L, Args&&... args ) - -Based on how it is called, pushes a variable amount of objects onto the stack. in 99% of cases, returns for 1 object pushed onto the stack. For the case of a ``std::tuple<...>``, it recursively pushes each object contained inside the tuple, from left to right, resulting in a variable number of things pushed onto the stack (this enables multi-valued returns when binding a C++ function to a Lua). Can be called with ``sol::stack::push<T>( L, args... )`` to have arguments different from the type that wants to be pushed, or ``sol::stack::push( L, arg, args... )`` where ``T`` will be inferred from ``arg``. The final form of this function is ``sol::stack::multi_push``, which will call one ``sol::stack::push`` for each argument. The ``T`` that describes what to push is first sanitized by removing top-level ``const`` qualifiers and reference qualifiers before being forwarded to the extension point :ref:`stack::pusher\<T><pusher>` struct. - -.. code-block:: cpp - :caption: function: set_field - - template <bool global = false, typename Key, typename Value> - void set_field( lua_State* L, Key&& k, Value&& v ); - - template <bool global = false, typename Key, typename Value> - void set_field( lua_State* L, Key&& k, Value&& v, int objectindex); - -Sets the field referenced by the key ``k`` to the given value ``v``, by pushing the key onto the stack, pushing the value onto the stack, and then doing the equivalent of ``lua_setfield`` for the object at the given ``objectindex``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global. - -.. code-block:: cpp - :caption: function: get_field - - template <bool global = false, typename Key> - void get_field( lua_State* L, Key&& k [, int objectindex] ); - -Gets the field referenced by the key ``k``, by pushing the key onto the stack, and then doing the equivalent of ``lua_getfield``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global. - -This function leaves the retrieved value on the stack. - -.. code-block:: cpp - :caption: function: probe_get_field - :name: stack-probe-get-field - - template <bool global = false, typename Key> - probe probe_get_field( lua_State* L, Key&& k [, int objectindex] ); - -Gets the field referenced by the key ``k``, by pushing the key onto the stack, and then doing the equivalent of ``lua_getfield``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global. Furthermore, it does this safely by only going in as many levels deep as is possible: if the returned value is not something that can be indexed into, then traversal queries with ``std::tuple``/``std::pair`` will stop early and return probing information with the :ref:`probe struct<stack-probe-struct>`. - -This function leaves the retrieved value on the stack. - -.. code-block:: cpp - :caption: struct: probe - :name: stack-probe-struct - - struct probe { - bool success; - int levels; - - probe(bool s, int l); - operator bool() const; - }; - -This struct is used for showing whether or not a :ref:`probing get_field<stack-probe-get-field>` was successful or not. - -.. _extension_points: - -objects (extension points) --------------------------- - -You can customize the way Sol handles different structures and classes by following the information provided in the :doc:`adding your own types<../tutorial/customization>`. - -Below is more extensive information for the curious. - -The structs below are already overriden for a handful of types. If you try to mess with them for the types ``sol`` has already overriden them for, you're in for a world of thick template error traces and headaches. Overriding them for your own user defined types should be just fine, however. - -.. code-block:: cpp - :caption: struct: getter - :name: getter - - template <typename T, typename = void> - struct getter { - static T get (lua_State* L, int index, record& tracking) { - // ... - return // T, or something related to T. - } - }; - -This is an SFINAE-friendly struct that is meant to expose static function ``get`` that returns a ``T``, or something convertible to it. The default implementation assumes ``T`` is a usertype and pulls out a userdata from Lua before attempting to cast it to the desired ``T``. There are implementations for getting numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata_value<types>` and anything as upvalues with :doc:`upvalue_index<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``std::function<R(Args...)>``. It is also defined for anything that derives from :doc:`sol::reference<reference>`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory<usertype_memory>`). - -.. code-block:: cpp - :caption: struct: pusher - :name: pusher - - template <typename X, typename = void> - struct pusher { - template <typename T> - static int push ( lua_State* L, T&&, ... ) { - // can optionally take more than just 1 argument - // ... - return // number of things pushed onto the stack - } - }; - -This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a :ref:`usertype_traits\<T><usertype-traits>` metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata<types>` and raw upvalues with :doc:`upvalue<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference<reference>`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory<usertype_memory>`). - -.. code-block:: cpp - :caption: struct: checker - :name: checker - - template <typename T, type expected = lua_type_of<T>, typename = void> - struct checker { - template <typename Handler> - static bool check ( lua_State* L, int index, Handler&& handler, record& tracking ) { - // if the object in the Lua stack at index is a T, return true - if ( ... ) return true; - // otherwise, call the handler function, - // with the required 4 arguments, then return false - handler(L, index, expected, indextype); - return false; - } - }; - -This is an SFINAE-friendly struct that is meant to expose static function ``check`` that returns the number of things pushed onto the stack. The default implementation simply checks whether the expected type passed in through the template is equal to the type of the object at the specified index in the Lua stack. The default implementation for types which are considered ``userdata`` go through a myriad of checks to support checking if a type is *actually* of type ``T`` or if its the base class of what it actually stored as a userdata in that index. Down-casting from a base class to a more derived type is, unfortunately, impossible to do. - -.. _lua_CFunction: http://www.Lua.org/manual/5.3/manual.html#lua_CFunction
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/stack_reference.rst b/3rdparty/sol2/docs/source/api/stack_reference.rst deleted file mode 100644 index db5359d11aa..00000000000 --- a/3rdparty/sol2/docs/source/api/stack_reference.rst +++ /dev/null @@ -1,8 +0,0 @@ -stack_reference -=============== -zero-overhead object on the stack ---------------------------------- - -When you work with a :doc:`sol::reference<reference>`, the object gotten from the stack has a reference to it made in the registry, keeping it alive. If you want to work with the Lua stack directly without having any additional references made, ``sol::stack_reference`` is for you. Its API is identical to ``sol::reference`` in every way, except it contains a ``int stack_index()`` member function that allows you to retrieve the stack index. - -All of the base types have ``stack`` versions of themselves, and the APIs are identical to their non-stack forms. This includes :doc:`sol::stack_table<table>`, :doc:`sol::stack_function<function>`, :doc:`sol::stack_protected_function<protected_function>`, :doc:`sol::stack_(light\_)userdata<userdata>` and :doc:`sol::stack_object<object>`.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/state.rst b/3rdparty/sol2/docs/source/api/state.rst deleted file mode 100644 index b1b17a3cc67..00000000000 --- a/3rdparty/sol2/docs/source/api/state.rst +++ /dev/null @@ -1,150 +0,0 @@ -state -===== -owning and non-owning state holders for registry and globals ------------------------------------------------------------- - -.. code-block:: cpp - - class state_view; - - class state : state_view, std::unique_ptr<lua_State*, deleter>; - -The most important class here is ``state_view``. This structure takes a ``lua_State*`` that was already created and gives you simple, easy access to Lua's interfaces without taking ownership. ``state`` derives from ``state_view``, inheriting all of this functionality, but has the additional purpose of creating a fresh ``lua_State*`` and managing its lifetime for you in the default constructor. - -The majority of the members between ``state_view`` and :doc:`sol::table<table>` are identical, with added for this higher-level type. Therefore, all of the examples and notes in :doc:`sol::table<table>` apply here as well. - -enumerations ------------- - -.. code-block:: cpp - :caption: in-lua libraries - :name: lib-enum - - enum class lib : char { - base, - package, - coroutine, - string, - os, - math, - table, - debug, - bit32, - io, - ffi, - jit, - count // do not use - }; - -This enumeration details the various base libraries that come with Lua. See the `standard lua libraries`_ for details about the various standard libraries. - - -members -------- - -.. code-block:: cpp - :caption: function: open standard libraries/modules - :name: open-libraries - - template<typename... Args> - void open_libraries(Args&&... args); - -This function takes a number of :ref:`sol::lib<lib-enum>` as arguments and opens up the associated Lua core libraries. - -.. code-block:: cpp - :caption: function: script / script_file - :name: state-script-function - - sol::function_result script(const std::string& code); - sol::function_result script_file(const std::string& filename); - -These functions run the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run isolated: any scripts or code run will affect code in the ``lua_State*`` the object uses as well (unless ``local`` is applied to a variable declaration, as specified by the Lua language). Code ran in this fashion is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques. - -If your script returns a value, you can capture it from the returned :ref:`function_result<function-result>`. - -.. code-block:: cpp - :caption: function: require / require_file - :name: state-require-function - - sol::object require(const std::string& key, lua_CFunction open_function, bool create_global = true); - sol::object require_script(const std::string& key, const std::string& code, bool create_global = true); - sol::object require_file(const std::string& key, const std::string& file, bool create_global = true); - -These functions play a role similar to `luaL_requiref`_ except that they make this functionality available for loading a one-time script or a single file. The code here checks if a module has already been loaded, and if it has not, will either load / execute the file or execute the string of code passed in. If ``create_global`` is set to true, it will also link the name ``key`` to the result returned from the open function, the code or the file. Regardless or whether a fresh load happens or not, the returned module is given as a single :doc:`sol::object<object>` for you to use as you see fit. - -Thanks to `Eric (EToreo) for the suggestion on this one`_! - -.. code-block:: cpp - :caption: function: load / load_file - :name: state-load-code - - sol::load_result load(const std::string& code); - sol::load_result load_file(const std::string& filename); - -These functions *load* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run: it returns a ``load_result`` proxy that can be called to actually run the code, turned into a ``sol::function``, a ``sol::protected_function``, or some other abstraction. If it is called, it will run on the object's current ``lua_State*``: it is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques. - -.. code-block:: cpp - :caption: function: do_string / do_file - :name: state-do-code - - sol::protected_function_result do_string(const std::string& code); - sol::protected_function_result do_file(const std::string& filename); - -These functions *loads and performs* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It *will* run, and then return a ``protected_function_result`` proxy that can be examined for either an error or the return value. - -.. code-block:: cpp - :caption: function: global table / registry table - - sol::global_table globals() const; - sol::table registry() const; - -Get either the global table or the Lua registry as a :doc:`sol::table<table>`, which allows you to modify either of them directly. Note that getting the global table from a ``state``/``state_view`` is usually unnecessary as it has all the exact same functions as a :doc:`sol::table<table>` anyhow. - - -.. code-block:: cpp - :caption: function: set_panic - :name: set-panic - - void set_panic(lua_CFunction panic); - -Overrides the panic function Lua calls when something unrecoverable or unexpected happens in the Lua VM. Must be a function of the that matches the ``int(lua_State*)`` function signature. - - -.. code-block:: cpp - :caption: function: memory_used - :name: memory-used - - std::size_t memory_used() const; - -Returns the amount of memory used *in bytes* by the Lua State. - - -.. code-block:: cpp - :caption: function: collect_garbage - :name: collect-garbage - - void collect_garbage(); - -Attempts to run the garbage collector. Note that this is subject to the same rules as the Lua API's collect_garbage function: memory may or may not be freed, depending on dangling references or other things, so make sure you don't have tables or other stack-referencing items currently alive or referenced that you want to be collected. - - -.. code-block:: cpp - :caption: function: make a table - - sol::table create_table(int narr = 0, int nrec = 0); - template <typename Key, typename Value, typename... Args> - sol::table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args); - - - template <typename... Args> - sol::table create_table_with(Args&&... args); - - static sol::table create_table(lua_State* L, int narr = 0, int nrec = 0); - template <typename Key, typename Value, typename... Args> - static sol::table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args); - -Creates a table. Forwards its arguments to :ref:`table::create<table-create>`. - -.. _standard lua libraries: http://www.lua.org/manual/5.3/manual.html#6 -.. _luaL_requiref: https://www.lua.org/manual/5.3/manual.html#luaL_requiref -.. _Eric (EToreo) for the suggestion on this one: https://github.com/ThePhD/sol2/issues/90
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/table.rst b/3rdparty/sol2/docs/source/api/table.rst deleted file mode 100644 index 25197b126c7..00000000000 --- a/3rdparty/sol2/docs/source/api/table.rst +++ /dev/null @@ -1,216 +0,0 @@ -table -===== -a representation of a Lua (meta)table -------------------------------------- - -.. code-block:: cpp - - template <bool global> - class table_core; - - typedef table_core<false> table; - typedef table_core<true> global_table; - -``sol::table`` is an extremely efficient manipulator of state that brings most of the magic of the Sol abstraction. Capable of doing multiple sets at once, multiple gets into a ``std::tuple``, being indexed into using ``[key]`` syntax and setting keys with a similar syntax (see: :doc:`here<proxy>`), ``sol::table`` is the corner of the interaction between Lua and C++. - -There are two kinds of tables: the global table and non-global tables: however, both have the exact same interface and all ``sol::global_table`` s are convertible to regular ``sol::table`` s. - -Tables are the core of Lua, and they are very much the core of Sol. - - -members -------- - -.. code-block:: cpp - :caption: constructor: table - - table(lua_State* L, int index = -1); - -Takes a table from the Lua stack at the specified index and allows a person to use all of the abstractions therein. - -.. code-block:: cpp - :caption: function: get / traversing get - - template<typename... Args, typename... Keys> - decltype(auto) get(Keys&&... keys) const; - - template<typename T, typename... Keys> - decltype(auto) traverse_get(Keys&&... keys) const; - - template<typename T, typename Key> - decltype(auto) get_or(Key&& key, T&& otherwise) const; - - template<typename T, typename Key, typename D> - decltype(auto) get_or(Key&& key, D&& otherwise) const; - - -These functions retrieve items from the table. The first one (``get``) can pull out *multiple* values, 1 for each key value passed into the function. In the case of multiple return values, it is returned in a ``std::tuple<Args...>``. It is similar to doing ``return table["a"], table["b"], table["c"]``. Because it returns a ``std::tuple``, you can use ``std::tie``/``std::make_tuple`` on a multi-get to retrieve all of the necessary variables. The second one (``traverse_get``) pulls out a *single* value, using each successive key provided to do another lookup into the last. It is similar to doing ``x = table["a"]["b"]["c"][...]``. - -If the keys within nested queries try to traverse into a table that doesn't exist, the second lookup into the nil-returned variable and belong will cause a panic to be fired by the lua C API. If you need to check for keys, check with ``auto x = table.get<sol::optional<int>>( std::tie("a", "b", "c" ) );``, and then use the :doc:`optional<optional>` interface to check for errors. As a short-hand, easy method for returning a default if a value doesn't exist, you can use ``get_or`` instead. - -.. code-block:: cpp - :caption: function: set / traversing set - :name: set-value - - template<typename... Args> - table& set(Args&&... args); - - template<typename... Args> - table& traverse_set(Args&&... args); - -These functions set items into the table. The first one (``set``) can set *multiple* values, in the form ``key_a, value_a, key_b, value_b, ...``. It is similar to ``table[key_a] = value_a; table[key_b] = value_b, ...``. The second one (``traverse_set``) sets a *single* value, using all but the last argument as keys to do another lookup into the value retrieved prior to it. It is equivalent to ``table[key_a][key_b][...] = value;``. - -.. note:: - - Value semantics are applied to all set operations. If you do not ``std::ref( obj )`` or specifically make a pointer with ``std::addressof( obj )`` or ``&obj``, it will copy / move. This is different from how :doc:`sol::function<function>` behaves with its call operator. - -.. code-block:: cpp - :caption: function: set a function with the specified key into lua - :name: set-function - - template<typename Key, typename Fx> - state_view& set_function(Key&& key, Fx&& fx, [...]); - -Sets the desired function to the specified key value. Note that it also allows for passing a member function plus a member object or just a single member function: however, using a lambda is almost always better when you want to bind a member function + class instance to a single function call in Lua. - -.. code-block:: cpp - :caption: function: add - - template<typename... Args> - table& add(Args&&... args); - -This function appends a value to a table. The definition of appends here is only well-defined for a table which has a perfectly sequential (and integral) ordering of numeric keys with associated non-null values (the same requirement for the :ref:`size<size-function>` function). Otherwise, this falls to the implementation-defined behavior of your Lua VM, whereupon is may add keys into empty 'holes' in the array (e.g., the first empty non-sequential integer key it gets to from ``size``) or perhaps at the very "end" of the "array". Do yourself the favor of making sure your keys are sequential. - -Each argument is appended to the list one at a time. - -.. code-block:: cpp - :caption: function: size - :name: size-function - - std::size_t size() const; - -This function returns the size of a table. It is only well-defined in the case of a Lua table which has a perfectly sequential (and integral) ordering of numeric keys with associated non-null values. - -.. code-block:: cpp - :caption: function: setting a usertype - :name: new-usertype - - template<typename Class, typename... Args> - table& new_usertype(const std::string& name, Args&&... args); - template<typename Class, typename CTor0, typename... CTor, typename... Args> - table& new_usertype(const std::string& name, Args&&... args); - template<typename Class, typename... CArgs, typename... Args> - table& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args); - -This class of functions creates a new :doc:`usertype<usertype>` with the specified arguments, providing a few extra details for constructors. After creating a usertype with the specified argument, it passes it to :ref:`set_usertype<set_usertype>`. - -.. code-block:: cpp - :caption: function: setting a simple usertype - :name: new-simple-usertype - - template<typename Class, typename... Args> - table& new_simple_usertype(const std::string& name, Args&&... args); - template<typename Class, typename CTor0, typename... CTor, typename... Args> - table& new_simple_usertype(const std::string& name, Args&&... args); - template<typename Class, typename... CArgs, typename... Args> - table& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args); - -This class of functions creates a new :doc:`simple usertype<simple_usertype>` with the specified arguments, providing a few extra details for constructors and passing the ``sol::simple`` tag as well. After creating a usertype with the specified argument, it passes it to :ref:`set_usertype<set_usertype>`. - -.. code-block:: cpp - :caption: function: creating an enum - :name: new-enum - - template<bool read_only = true, typename... Args> - basic_table_core& new_enum(const std::string& name, Args&&... args); - -Use this function to create an enumeration type in Lua. By default, the enum will be made read-only, which creates a tiny performance hit to make the values stored in this table behave exactly like a read-only enumeration in C++. If you plan on changing the enum values in Lua, set the ``read_only`` template parameter in your ``new_enum`` call to false. The arguments are expected to come in ``key, value, key, value, ...`` list. - -.. _set_usertype: - -.. code-block:: cpp - :caption: function: setting a pre-created usertype - :name: set-usertype - - template<typename T> - table& set_usertype(usertype<T>& user); - template<typename Key, typename T> - table& set_usertype(Key&& key, usertype<T>& user); - -Sets a previously created usertype with the specified ``key`` into the table. Note that if you do not specify a key, the implementation falls back to setting the usertype with a ``key`` of ``usertype_traits<T>::name``, which is an implementation-defined name that tends to be of the form ``{namespace_name 1}_[{namespace_name 2 ...}_{class name}``. - -.. code-block:: cpp - :caption: function: begin / end for iteration - :name: table-iterators - - table_iterator begin () const; - table_iterator end() const; - table_iterator cbegin() const; - table_iterator cend() const; - -Provides (what can barely be called) `input iterators`_ for a table. This allows tables to work with single-pass, input-only algorithms (like ``std::for_each``). Note that manually getting an iterator from ``.begin()`` without a ``.end()`` or using postfix incrementation (``++mytable.begin()``) will lead to poor results. The Lua stack is manipulated by an iterator and thusly not performing the full iteration once you start is liable to ruin either the next iteration or break other things subtly. Use a C++11 ranged for loop, ``std::for_each``, or other algorithims which pass over the entire collection at least once and let the iterators fall out of scope. - -.. _iteration_note: -.. warning:: - - The iterators you use to walk through a ``sol::table`` are NOT guaranteed to iterate in numeric order, or ANY kind of order. They may iterate backwards, forwards, in the style of cuckoo-hashing, by accumulating a visited list while calling ``rand()`` to find the next target, or some other crazy scheme. Now, no implementation would be crazy, but it is behavior specifically left undefined because there are many ways that your Lua package can implement the table type. - - Iteration order is NOT something you should rely on. If you want to figure out the length of a table, call the length operation (``int count = mytable.size();`` using the sol API) and then iterate from ``1`` to ``count`` (inclusive of the value of count, because Lua expects iteration to work in the range of ``[1, count]``). This will save you some headaches in the future when the implementation decides not to iterate in numeric order. - - -.. code-block:: cpp - :caption: function: iteration with a function - :name: table-for-each - - template <typename Fx> - void for_each(Fx&& fx); - -A functional ``for_each`` loop that calls the desired function. The passed in function must take either ``sol::object key, sol::object value`` or take a ``std::pair<sol::object, sol::object> key_value_pair``. This version can be a bit safer as allows the implementation to definitively pop the key/value off the Lua stack after each call of the function. - -.. code-block:: cpp - :caption: function: operator[] access - - template<typename T> - proxy<table&, T> operator[](T&& key); - template<typename T> - proxy<const table&, T> operator[](T&& key) const; - -Generates a :doc:`proxy<proxy>` that is templated on the table type and the key type. Enables lookup of items and their implicit conversion to a desired type. - -.. code-block:: cpp - :caption: function: create a table with defaults - :name: table-create - - table create(int narr = 0, int nrec = 0); - template <typename Key, typename Value, typename... Args> - table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args); - - static table create(lua_State* L, int narr = 0, int nrec = 0); - template <typename Key, typename Value, typename... Args> - static table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args); - -Creates a table, optionally with the specified values pre-set into the table. If ``narr`` or ``nrec`` are 0, then compile-time shenanigans are used to guess the amount of array entries (e.g., integer keys) and the amount of hashable entries (e.g., all other entries). - -.. code-block:: cpp - :caption: function: create a table with compile-time defaults assumed - :name: table-create-with - - template <typename... Args> - table create_with(Args&&... args); - template <typename... Args> - static table create_with(lua_State* L, Args&&... args); - - -Creates a table, optionally with the specified values pre-set into the table. It checks every 2nd argument (the keys) and generates hints for how many array or map-style entries will be placed into the table. - -.. code-block:: cpp - :caption: function: create a named table with compile-time defaults assumed - :name: table-create-named - - template <typename Name, typename... Args> - table create_named(Name&& name, Args&&... args); - - -Creates a table, optionally with the specified values pre-set into the table, and sets it as the key ``name`` in the table. - -.. _input iterators: http://en.cppreference.com/w/cpp/concept/InputIterator
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/this_state.rst b/3rdparty/sol2/docs/source/api/this_state.rst deleted file mode 100644 index c4c6b3b7f75..00000000000 --- a/3rdparty/sol2/docs/source/api/this_state.rst +++ /dev/null @@ -1,31 +0,0 @@ -this_state -========== -transparent state argument for the current state ------------------------------------------------- - -.. code-block:: cpp - - struct this_state; - -This class is a transparent type that is meant to be gotten in functions to get the current lua state a bound function or usertype method is being called from. It does not actually retrieve anything from lua nor does it increment the argument count, making it "invisible" to function calls in lua and calls through ``std::function<...>`` and :doc:`sol::function<function>` on this type. It can be put in any position in the argument list of a function: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.set_function("bark", []( sol::this_state s, int a, int b ){ - lua_State* L = s; // current state - return a + b + lua_gettop(L); - }); - - lua.script("first = bark(2, 2)"); // only takes 2 arguments, NOT 3 - - // Can be at the end, too, or in the middle: doesn't matter - lua.set_function("bark", []( int a, int b, sol::this_state s ){ - lua_State* L = s; // current state - return a + b + lua_gettop(L); - }); - - lua.script("second = bark(2, 2)"); // only takes 2 arguments -
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/thread.rst b/3rdparty/sol2/docs/source/api/thread.rst deleted file mode 100644 index b7349d97efb..00000000000 --- a/3rdparty/sol2/docs/source/api/thread.rst +++ /dev/null @@ -1,80 +0,0 @@ -thread -====== -a separate state that can contain and run functions ---------------------------------------------------- - -.. code-block:: cpp - - class thread : public reference { /* ... */ }; - -``sol::thread`` is a separate runnable part of the Lua VM that can be used to execute work separately from the main thread, such as with :doc:`coroutines<coroutine>`. To take a table or a coroutine and run it specifically on the ``sol::thread`` you either pulled out of lua or created, just get that function through the :ref:`state of the thread<thread_state>` - -.. note:: - - A CPU thread is not always equivalent to a new thread in Lua: ``std::this_thread::get_id()`` can be the same for 2 callbacks that have 2 distinct Lua threads. In order to know which thread a callback was called in, hook into :doc:`sol::this_state<this_state>` from your Lua callback and then construct a ``sol::thread``, passing in the ``sol::this_state`` for both the first and last arguments. Then examine the results of the status and ``is_...`` calls below. - -free function -------------- - -.. code-block:: cpp - :caption: function: main_thread - - main_thread(lua_State* current, lua_State* backup_if_bad_platform = nullptr); - -The function ``sol::main_thread( ... )`` retrieves the main thread of the application on Lua 5.2 and above *only*. It is designed for code that needs to be multithreading-aware (e.g., uses multiple :doc:`threads<thread>` and :doc:`coroutines<coroutine>`). - -.. warning:: - - This code function will be present in Lua 5.1/LuaJIT, but only have proper behavior when given a single argument on Lua 5.2 and beyond. Lua 5.1 does not support retrieving the main thread from its registry, and therefore it is entirely suggested if you are writing cross-platform Lua code that you must store the main thread of your application in some global storage accessible somewhere. Then, pass this item into the ``sol::main_thread( possibly_thread_state, my_actual_main_state )`` and it will select that ``my_actual_main_state`` every time. If you are not going to use Lua 5.1 / LuaJIT, you can ignore the last parameter. - - -members -------- - -.. code-block:: cpp - :caption: constructor: thread - - thread(stack_reference r); - thread(lua_State* L, int index = -1); - thread(lua_State* L, lua_State* actual_thread); - -Takes a thread from the Lua stack at the specified index and allows a person to use all of the abstractions therein. It can also take an actual thread state to make a thread from that as well. - -.. code-block:: cpp - :caption: function: view into thread_state()'s state - - state_view state() const; - -This retrieves the current state of the thread, producing a :doc:`state_view<state>` that can be manipulated like any other. :doc:`Coroutines<coroutine>` pulled from Lua using the thread's state will be run on that thread specifically. - -.. _thread_state: - -.. code-block:: cpp - :caption: function: retrieve thread state object - - lua_State* thread_state () const; - -This function retrieves the ``lua_State*`` that represents the thread. - -.. code-block:: cpp - :caption: current thread status - - thread_status status () const; - -Retrieves the :doc:`thread status<types>` that describes the current state of the thread. - -.. code-block:: cpp - :caption: main thread status - - bool is_main_thread () const; - -Checks to see if the thread is the main Lua thread. - -.. code-block:: cpp - :caption: function: thread creation - :name: thread-create - - thread create(); - static thread create (lua_State* L); - -Creates a new thread from the given a ``lua_State*``.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/tie.rst b/3rdparty/sol2/docs/source/api/tie.rst deleted file mode 100644 index 080c8a1cc4f..00000000000 --- a/3rdparty/sol2/docs/source/api/tie.rst +++ /dev/null @@ -1,26 +0,0 @@ -tie -=== -An improved version of ``std::tie`` ------------------------------------ - -`std::tie()`_ does not work well with :doc:`sol::function<function>`'s ``sol::function_result`` returns. Use ``sol::tie`` instead. Because they're both named `tie`, you'll need to be explicit when you use Sol's by naming it with the namespace (``sol::tie``), even with a ``using namespace sol;``. Here's an example: - -.. code-block:: cpp - - sol::state lua; - lua.open_libraries(sol::lib::base); - - const auto& code = R"( - function test() - return 1, 2, 3 - end - )"; - lua.script(code); - - int a, b, c; - //std::tie(a, b, c) = lua["test"](); - // will error: use the line below - sol::tie(a, b, c) = lua["test"](); - - -.. _std::tie(): http://en.cppreference.com/w/cpp/utility/tuple/tie diff --git a/3rdparty/sol2/docs/source/api/types.rst b/3rdparty/sol2/docs/source/api/types.rst deleted file mode 100644 index 9f761ee25b9..00000000000 --- a/3rdparty/sol2/docs/source/api/types.rst +++ /dev/null @@ -1,207 +0,0 @@ -types -===== -nil, lua_primitive type traits, and other fundamentals ------------------------------------------------------- - -The ``types.hpp`` header contains various fundamentals and utilities of Sol. - - -enumerations ------------- - -.. code-block:: cpp - :caption: syntax of a function called by Lua - :name: call-syntax - - enum class call_syntax { - dot = 0, - colon = 1 - }; - -This enumeration indicates the syntax a function was called with in a specific scenario. There are two ways to call a function: with ``obj:func_name( ... )`` or ``obj.func_name( ... );`` The first one passes "obj" as the first argument: the second one does not. In the case of usertypes, this is used to determine whether the call to a :doc:`constructor/initializer<usertype>` was called with a ``:`` or a ``.``, and not misalign the arguments. - -.. code-block:: cpp - :caption: status of a Lua function call - :name: call-status - - enum class call_status : int { - ok = LUA_OK, - yielded = LUA_YIELD, - runtime = LUA_ERRRUN, - memory = LUA_ERRMEM, - handler = LUA_ERRERR, - gc = LUA_ERRGCMM - }; - -This strongly-typed enumeration contains the errors potentially generated by a call to a :doc:`protected function<protected_function>` or a :doc:`coroutine<coroutine>`. - -.. code-block:: cpp - :caption: status of a Lua thread - :name: thread-status - - enum class thread_status : int { - ok = LUA_OK, - yielded = LUA_YIELD, - runtime = LUA_ERRRUN, - memory = LUA_ERRMEM, - gc = LUA_ERRGCMM, - handler = LUA_ERRERR, - dead, - }; - -This enumeration contains the status of a thread. The ``thread_status::dead`` state is generated when the thread has nothing on its stack and it is not running anything. - -.. code-block:: cpp - :caption: status of a Lua load operation - :name: load-status - - enum class load_status : int { - ok = LUA_OK, - runtime = LUA_ERRSYNTAX, - memory = LUA_ERRMEM, - gc = LUA_ERRGCMM, - file = LUA_ERRFILE, - }; - -This enumeration contains the status of a load operation from :ref:`state::load(_file)<state-load-code>`. - -.. code-block:: cpp - :caption: type enumeration - :name: type-enum - - enum class type : int { - none = LUA_TNONE, - nil = LUA_TNIL, - string = LUA_TSTRING, - number = LUA_TNUMBER, - thread = LUA_TTHREAD, - boolean = LUA_TBOOLEAN, - function = LUA_TFUNCTION, - userdata = LUA_TUSERDATA, - lightuserdata = LUA_TLIGHTUSERDATA, - table = LUA_TTABLE, - poly = none | nil | string | number | thread | - table | boolean | function | userdata | lightuserdata - }; - -The base types that Lua natively communicates in and understands. Note that "poly" isn't really a true type, it's just a symbol used in Sol for something whose type hasn't been checked (and you should almost never see it). - - -type traits ------------ - -.. code-block:: cpp - :caption: lua_type_of trait - :name: lua-type-of - - template <typename T> - struct lua_type_of; - -This type trait maps a C++ type to a :ref:`type enumeration<type-enum>` value. The default value is ``type::userdata``. - -.. code-block:: cpp - :caption: primitive checking traits - :name: is-primitive - - template <typename T> - struct is_lua_primitive; - - template <typename T> - struct is_proxy_primitive; - - -This trait is used by :doc:`proxy<proxy>` to know which types should be returned as references to internal Lua memory (e.g., ``userdata`` types) and which ones to return as values (strings, numbers, :doc:`references<reference>`). ``std::reference_wrapper``, ``std::tuple<...>`` are returned as values, but their contents can be references. The default value is false. - -special types -------------- - -.. code-block:: cpp - :caption: nil - :name: nil - - strunil_t {}; - const nil_t nil {}; - bool operator==(nil_t, nil_t); - bool operator!=(nil_t, nil_t); - -``nil`` is a constant used to signify Lua's ``nil``, which is a type and object that something does not exist. It is comparable to itself, :doc:`sol::object<object>` and :doc:`proxy values<proxy>`. - - -.. code-block:: cpp - :caption: non_null - - template <typename T> - struct non_null {}; - -A tag type that, when used with :doc:`stack::get\<non_null\<T*>><stack>`, does not perform a ``nil`` check when attempting to retrieve the userdata pointer. - - -.. code-block:: cpp - :caption: type list - :name: type-list - - template <typename... Args> - struct types; - -A type list that, unlike ``std::tuple<Args...>``, does not actually contain anything. Used to indicate types and groups of types all over Sol. - - -functions ---------- - -.. code-block:: cpp - :caption: type_of - - template<typename T> - type type_of(); - - type type_of(lua_State* L, int index); - - -These functions get the type of a C++ type ``T``; or the type at the specified index on the Lua stack. - -.. code-block:: cpp - :caption: type checking convenience functions - - int type_panic(lua_State* L, int index, type expected, type actual); - - int no_panic(lua_State*, int, type, type) noexcept; - - void type_error(lua_State* L, int expected, int actual); - - void type_error(lua_State* L, type expected, type actual); - - void type_assert(lua_State* L, int index, type expected, type actual); - - void type_assert(lua_State* L, int index, type expected); - -The purpose of these functions is to assert / throw / crash / error (or do nothing, as is the case with ``no_panic``). They're mostly used internally in the framework, but they're provided here if you should need them. - -.. code-block:: cpp - :caption: type name retrieval - - std::string type_name(lua_State*L, type t); - -Gets the Lua-specified name of the :ref:`type<type-enum>`. - -structs -------- - -.. code-block:: cpp - - struct userdata_value { - void* value; - }; - - struct light_userdata_value { - void* value; - }; - - struct up_value_index { - int index; - }; - - -Types that differentiate between the two kinds of ``void*`` Lua hands back from its API: full userdata and light userdata, as well as a type that modifies the index passed to ``get`` to refer to `up values`_ These types can be used to trigger different underlying API calls to Lua when working with :doc:`stack<stack>` namespace and the ``push``/``get``/``pop``/``check`` functions. - -.. _up values: http://www.Lua.org/manual/5.3/manual.html#4.4
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/unique_usertype_traits.rst b/3rdparty/sol2/docs/source/api/unique_usertype_traits.rst deleted file mode 100644 index 4568b11349c..00000000000 --- a/3rdparty/sol2/docs/source/api/unique_usertype_traits.rst +++ /dev/null @@ -1,44 +0,0 @@ -unique_usertype_traits<T> -========================= -A trait for hooking special handles / pointers ----------------------------------------------- - -.. code-block:: cpp - :caption: unique_usertype - :name: unique-usertype - - template <typename T> - struct unique_usertype_traits { - typedef T type; - typedef T actual_type; - static const bool value = false; - - static bool is_null(const actual_type&) {...} - - static type* get (const actual_type&) {...} - }; - -This is a customization point for users who need to *work with special kinds of pointers/handles*. For generic customization, please review the :doc:`customization tutorial<../tutorial/customization>` A traits type for alerting the library that a certain type is to be pushed as a special userdata with special deletion / destruction semantics. It is already defined for ``std::unique_ptr<T, D>`` and ``std::shared_ptr<T>``. You can specialize this to get ``unique_usertype_traits`` semantics with your code, for example with ``boost::shared_ptr<T>`` like so: - -.. code-block:: cpp - - namespace sol { - template <typename T> - struct unique_usertype_traits<boost::shared_ptr<T>> { - typedef T type; - typedef boost::shared_ptr<T> actual_type; - static const bool value = true; - - static bool is_null(const actual_type& value) { - return value == nullptr; - } - - static type* get (const actual_type& p) { - return p.get(); - } - } - } - -This will allow the framework to properly handle ``boost::shared_ptr<T>``, with ref-counting and all. The `type` is the type that lua and sol will interact with, and will allow you to pull out a non-owning reference / pointer to the data when you just ask for a plain `T*` or `T&` or `T` using the getter functions and properties of Sol. - -Note that if ``is_null`` triggers, a ``nil`` value will be pushed into Sol.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/user.rst b/3rdparty/sol2/docs/source/api/user.rst deleted file mode 100644 index 9a0905d76bd..00000000000 --- a/3rdparty/sol2/docs/source/api/user.rst +++ /dev/null @@ -1,19 +0,0 @@ -light<T>/user<T> -================ -Utility class for the cheapest form of (light) userdata -------------------------------------------------------- - -.. code-block:: cpp - - template <typename T> - struct user; - - template <typename T> - struct light; - - -``sol::user<T>`` and ``sol::light<T>`` are two utility classes that do not participate in the full :doc:`sol::usertype\<T><usertype>` system. The goal of these classes is to provide the most minimal memory footprint and overhead for putting a single item and getting a single item out of Lua. ``sol::user<T>``, when pushed into Lua, will create a thin, unnamed metatable for that instance specifically which will be for calling its destructor. ``sol::light<T>`` specifically pushes a reference / pointer into Lua as a ``sol::type::lightuserdata``. - -If you feel that you do not need to have something participate in the full :doc:`usertype\<T><usertype>` system, use the utility functions ``sol::make_user( ... )`` and ``sol::make_light( ... )`` to create these types and store them into Lua. You can get them off the Lua stack / out of the Lua system by using the same retrieval techniques on ``get`` and ``operator[]`` on tables and with stack operations. - -Both have implicit conversion operators to ``T*`` and ``T&``, so you can set them immediately to their respective pointer and reference types if you need them.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/userdata.rst b/3rdparty/sol2/docs/source/api/userdata.rst deleted file mode 100644 index 6bc64791552..00000000000 --- a/3rdparty/sol2/docs/source/api/userdata.rst +++ /dev/null @@ -1,13 +0,0 @@ -userdata -======== -reference to a userdata ------------------------ - -.. code-block:: cpp - :caption: (light\_)userdata reference - - class userdata : public reference; - - class light_userdata : public reference; - -These type is meant to hold a reference to a (light) userdata from Lua and make it easy to push an existing userdata onto the stack. It is essentially identical to :doc:`reference<reference>` in every way, just with a definitive C++ type. diff --git a/3rdparty/sol2/docs/source/api/usertype.rst b/3rdparty/sol2/docs/source/api/usertype.rst deleted file mode 100644 index bd941c527dc..00000000000 --- a/3rdparty/sol2/docs/source/api/usertype.rst +++ /dev/null @@ -1,330 +0,0 @@ -usertype<T> -=========== -structures and classes from C++ made available to Lua code ----------------------------------------------------------- - -*Note: ``T`` refers to the type being turned into a usertype.* - -While other frameworks extend lua's syntax or create Data Structure Languages (DSLs) to create classes in lua, :doc:`Sol<../index>` instead offers the ability to generate easy bindings. These use metatables and userdata in lua for their implementation. If you need a usertype that is also extensible at runtime and has less compiler crunch to it, try the :doc:`simple version of this after reading these docs<simple_usertype>` Given this C++ class: - -.. code-block:: cpp - :linenos: - - struct ship { - int bullets = 20; - int life = 100; - - bool shoot () { - if (bullets > 0) { - --bullets; - // successfully shot - return true; - } - // cannot shoot - return false; - } - - bool hurt (int by) { - life -= by; - // have we died? - return life < 1; - } - }; - -You can bind the it to Lua using the following C++ code: - -.. code-block:: cpp - :linenos: - - sol::state lua; - - lua.new_usertype<ship>( "ship", // the name of the class, as you want it to be used in lua - // List the member functions you wish to bind: - // "name_of_item", &class_name::function_or_variable - "shoot", &ship::shoot, - "hurt", &ship::hurt, - // bind variable types, too - "life", &ship::bullets - // names in lua don't have to be the same as C++, - // but it probably helps if they're kept the same, - // here we change it just to show its possible - "bullet_count", &ship::bullets - ); - - -Equivalently, you can also write: - -.. code-block:: cpp - :linenos: - :emphasize-lines: 4,12 - - sol::state lua; - - // Use constructor directly - usertype<ship> shiptype( - "shoot", &ship::shoot, - "hurt", &ship::hurt, - "life", &ship::bullets - "bullet_count", &ship::bullets - ); - - // set usertype explicitly, with the given name - lua.set_usertype<ship>( "ship", shiptype ); - - // shiptype is now a useless skeleton type, just let it destruct naturally and don't use it again. - - -Note that here, because the C++ class is default-constructible, it will automatically generate a creation function that can be called in lua called "new" that takes no arguments. You can use it like this in lua code: - -.. code-block:: lua - :linenos: - - fwoosh = ship.new() - -- note the ":" that is there: this is mandatory for member function calls - -- ":" means "pass self" in Lua - local success = fwoosh:shoot() - local is_dead = fwoosh:hurt(20) - -- check if it works - print(is_dead) -- the ship is not dead at this point - print(fwoosh.life .. "life left") -- 80 life left - print(fwoosh.bullet_count) -- 19 - - -There are more advanced use cases for how to create and use a usertype, which are all based on how to use its constructor (see below). - -enumerations ------------- - -.. _meta_function_enum: - -.. code-block:: cpp - :caption: meta_function enumeration for names - :linenos: - - enum class meta_function { - construct, - index, - new_index, - mode, - call, - metatable, - to_string, - length, - unary_minus, - addition, - subtraction, - multiplication, - division, - modulus, - power_of, - involution = power_of, - concatenation, - equal_to, - less_than, - less_than_or_equal_to, - garbage_collect, - call_function, - }; - - -Use this enumeration to specify names in a manner friendlier than memorizing the special lua metamethod names for each of these. Each binds to a specific operation indicated by the descriptive name of the enum. - -members -------- - -.. code-block:: cpp - :caption: function: usertype<T> constructor - :name: usertype-constructor - - template<typename... Args> - usertype<T>(Args&&... args); - - -The constructor of usertype takes a variable number of arguments. It takes an even number of arguments (except in the case where the very first argument is passed as the :ref:`constructor list type<constructor>`). Names can either be strings, :ref:`special meta_function enumerations<meta_function_enum>`, or one of the special indicators for initializers. - - -usertype constructor options -++++++++++++++++++++++++++++ - -If you don't specify any constructor options at all and the type is `default_constructible`_, Sol will generate a ``new`` for you. Otherwise, the following are special ways to handle the construction of a usertype: - -.. _constructor: - -* ``"{name}", constructors<Type-List-0, Type-List-1, ...>`` - - ``Type-List-N`` must be a ``sol::types<Args...>``, where ``Args...`` is a list of types that a constructor takes. Supports overloading by default - - If you pass the ``constructors<...>`` argument first when constructing the usertype, then it will automatically be given a ``"{name}"`` of ``"new"`` -* ``"{name}", sol::initializers( func1, func2, ... )`` - - Used to handle *initializer functions* that need to initialize the memory itself (but not actually allocate the memory, since that comes as a userdata block from Lua) - - Given one or more functions, provides an overloaded Lua function for creating a the specified type - + The function must have the argument signature ``func( T*, Arguments... )`` or ``func( T&, Arguments... )``, where the pointer or reference will point to a place of allocated memory that has an uninitialized ``T``. Note that Lua controls the memory, so performing a ``new`` and setting it to the ``T*`` or ``T&`` is a bad idea: instead, use ``placement new`` to invoke a constructor, or deal with the memory exactly as you see fit -* ``{anything}, sol::factories( func1, func2, ... )`` - - Used to indicate that a factory function (e.g., something that produces a ``std::unique_ptr<T, ...>``, ``std::shared_ptr<T>``, ``T``, or similar) will be creating the object type - - Given one or more functions, provides an overloaded function for invoking - + The functions can take any form and return anything, since they're just considered to be some plain function and no placement new or otherwise needs to be done. Results from this function will be pushed into Lua according to the same rules as everything else. - + Can be used to stop the generation of a ``.new()`` default constructor since a ``sol::factories`` entry will be recognized as a constructor for the usertype - + If this is not sufficient, see next 2 entries on how to specifically block a constructor -* ``{anything}, sol::no_constructor`` - - Specifically tells Sol not to create a ``.new()`` if one is not specified and the type is default-constructible - - ``{anything}`` should probably be ``"new"``, which will specifically block its creation and give a proper warning if someone calls ``new`` (otherwise it will just give a nil value error) - - *Combine with the next one to only allow a factory function for your function type* -* ``{anything}, {some_factory_function}`` - - Essentially binds whatever the function is to name ``{anything}`` - - When used WITH the ``sol::no_constructor`` option above (e.g. ``"new", sol::no_constructor`` and after that having ``"create", &my_creation_func``), one can remove typical constructor avenues and then only provide specific factory functions. Note that this combination is similar to using the ``sol::factories`` method mentioned earlier in this list. To control the destructor as well, see further below -* ``sol::call_constructor, {valid constructor / initializer / factory}`` - - The purpose of this is to enable the syntax ``local v = my_class( 24 )`` and have that call a constructor; it has no other purpose - - This is compatible with luabind, kaguya and other Lua library syntaxes and looks similar to C++ syntax, but the general consensus in Programming with Lua and other places is to use a function named ``new`` - - Note that with the ``sol::call_constructor`` key, a construct type above must be specified. A free function without it will pass in the metatable describing this object as the first argument without that distinction, which can cause strange runtime errors. - -usertype destructor options -+++++++++++++++++++++++++++ - -If you don't specify anything at all and the type is `destructible`_, then a destructor will be bound to the garbage collection metamethod. Otherwise, the following are special ways to handle the destruction of a usertype: - -* ``"__gc", sol::destructor( func )`` or ``sol::meta_function::garbage_collect, sol::destructor( func )`` - - Creates a custom destructor that takes an argument ``T*`` or ``T&`` and expects it to be destructed/destroyed. Note that lua controls the memory and thusly will deallocate the necessary space AFTER this function returns (e.g., do not call ``delete`` as that will attempt to deallocate memory you did not ``new``) - - If you just want the default constructor, you can replace the second argument with ``sol::default_destructor`` - - The usertype will error / throw if you specify a destructor specifically but do not map it to ``sol::meta_function::gc`` or a string equivalent to ``"__gc"`` - -usertype regular function options -+++++++++++++++++++++++++++++++++ - -If you don't specify anything at all and the type ``T`` supports ``operator <``, ``operator <=``, or ``operator==`` (``const`` or non-``const`` qualified): - -* for ``operator <`` and ``operator <=`` - - These two ``sol::meta_function::less_than(_or_equal_to)`` are generated for you and overriden in Lua. -* for ``operator==`` - - An equality operator will always be generated, doing pointer comparison if ``operator==`` on the two value types is not supported or doing a reference comparison and a value comparison if ``operator==`` is supported -* heterogenous operators cannot be supported for equality, as Lua specifically checks if they use the same function to do the comparison: if they do not, then the equality method is not invoked; one way around this would be to write one ``int super_equality_function(lua_State* L) { ... }``, pull out arguments 1 and 2 from the stack for your type, and check all the types and then invoke ``operator==`` yourself after getting the types out of Lua (possibly using :ref:`sol::stack::get<stack-get>` and :ref:`sol::stack::check_get<stack-check-get>`) - -Otherwise, the following is used to specify functions to bind on the specific usertype for ``T``. - -* ``"{name}", &free_function`` - - Binds a free function / static class function / function object (lambda) to ``"{name}"``. If the first argument is ``T*`` or ``T&``, then it will bind it as a member function. If it is not, it will be bound as a "static" function on the lua table -* ``"{name}", &type::function_name`` or ``"{name}", &type::member_variable`` - - Binds a typical member function or variable to ``"{name}"``. In the case of a member variable or member function, ``type`` must be ``T`` or a base of ``T`` -* ``"{name}", sol::readonly( &type::member_variable )`` - - Binds a typical variable to ``"{name}"``. Similar to the above, but the variable will be read-only, meaning an error will be generated if anything attemps to write to this variable -* ``"{name}", sol::as_function( &type::member_variable )`` - - Binds a typical variable to ``"{name}"`` *but forces the syntax to be callable like a function*. This produces a getter and a setter accessible by ``obj:name()`` to get and ``obj::name(value)`` to set. -* ``"{name}", sol::property( getter_func, setter_func )`` - - Binds a typical variable to ``"{name}"``, but gets and sets using the specified setter and getter functions. Not that if you do not pass a setter function, the variable will be read-only. Also not that if you do not pass a getter function, it will be write-only -* ``"{name}", sol::var( some_value )`` or ``"{name}", sol::var( std::ref( some_value ) )`` - - Binds a typical variable to ``"{name}"``, optionally by reference (e.g., refers to the same memory in C++). This is useful for global variables / static class variables and the like -* ``"{name}", sol::overloaded( Func1, Func2, ... )`` - - Creates an oveloaded member function that discriminates on number of arguments and types. -* ``sol::base_classes, sol::bases<Bases...>`` - - Tells a usertype what its base classes are. You need this to have derived-to-base conversions work properly. See :ref:`inheritance<usertype-inheritance>` - - -usertype arguments - simple usertype -++++++++++++++++++++++++++++++++++++ - -* ``sol::simple`` - - Only allowed as the first argument to the usertype constructor, must be accompanied by a ``lua_State*`` - - This tag triggers the :doc:`simple usertype<simple_usertype>` changes / optimizations - - Only supported when directly invoking the constructor (e.g. not when calling ``sol::table::new_usertype`` or ``sol::table::new_simple_usertype``) - - Should probably not be used directly. Use ``sol::table::new_usertype`` or ``sol::table::new_simple_usertype`` instead - - - -overloading ------------ - -Functions set on a usertype support overloading. See :doc:`here<overload>` for an example. - - -.. _usertype-inheritance: - -inheritance ------------ - -Sol can adjust pointers from derived classes to base classes at runtime, but it has some caveats based on what you compile with: - -If your class has no complicatedâ„¢ virtual inheritance or multiple inheritance, than you can try to sneak away with a performance boost from not specifying any base classes and doing any casting checks. (What does "complicatedâ„¢" mean? Ask your compiler's documentation, if you're in that deep.) - -For the rest of us safe individuals out there: You must specify the ``sol::base_classes`` tag with the ``sol::bases<Types...>()`` argument, where ``Types...`` are all the base classes of the single type ``T`` that you are making a usertype out of. - -.. note:: - - Always specify your bases if you plan to retrieve a base class using the Sol abstraction directly and not casting yourself. - -.. code-block:: cpp - :linenos: - - struct A { - int a = 10; - virtual int call() { return 0; } - }; - struct B : A { - int b = 11; - virtual int call() override { return 20; } - }; - -Then, to register the base classes explicitly: - -.. code-block:: cpp - :linenos: - :emphasize-lines: 5 - - sol::state lua; - - lua.new_usertype<B>( "B", - "call", &B::call, - sol::base_classes, sol::bases<A>() - ); - -.. note:: - - You must list ALL base classes, including (if there were any) the base classes of A, and the base classes of those base classes, etc. if you want Sol/Lua to handle them automagically. - -.. note:: - - Sol does not support down-casting from a base class to a derived class at runtime. - -.. warning:: - - Specify all base class member variables and member functions to avoid current implementation caveats regarding automatic base member lookup. Sol currently attempts to link base class methods and variables with their derived classes with an undocumented, unsupported feature, provided you specify ``sol::base_classes<...>``. Unfortunately, this can come at the cost of performance, depending on how "far" the base is from the derived class in the bases lookup list. If you do not want to suffer the performance degradation while we iron out the kinks in the implementation (and want it to stay performant forever), please specify all the base methods on the derived class in the method listing you write. In the future, we hope that with reflection we will not have to worry about this. - - -inheritance + overloading -------------------------- - -While overloading is supported regardless of inheritance caveats or not, the current version of Sol has a first-match, first-call style of overloading when it comes to inheritance. Put the functions with the most derived arguments first to get the kind of matching you expect or cast inside of an intermediary C++ function and call the function you desire. - -traits ------- - -.. code-block:: cpp - :caption: usertype_traits<T> - :name: usertype-traits - - template<typename T> - struct usertype_traits { - static const std::string name; - static const std::string metatable; - static const std::string variable_metatable; - static const std::string gc_table; - }; - - -This trait is used to provide names for the various metatables and global tables used to perform cleanup and lookup. They are automagically generated at runtime. Sol attempts to parse the output of ``__PRETTY_FUCNTION__`` (``g++``/``clang++``) or ``_FUNCDSIG`` (``vc++``) to get the proper type name. If you have a special need you can override the names for your specific type. If you notice a bug in a class name when you don't manually specify it during setting a usertype, feel free to open an issue request or send an e-mail! - - -compilation speed ------------------ - -.. note:: - - If you find that compilation times are too long and you're only binding member functions, consider perhaps using :doc:`simple usertypes<simple_usertype>`. This can reduce compile times (but may cost memory size and speed). See the simple usertypes documentation for more details. - - -performance note ----------------- - -.. note:: - - Note that performance for member function calls goes down by a fixed overhead if you also bind variables as well as member functions. This is purely a limitation of the Lua implementation and there is, unfortunately, nothing that can be done about it. If you bind only functions and no variables, however, Sol will automatically optimize the Lua runtime and give you the maximum performance possible. *Please consider ease of use and maintenance of code before you make everything into functions.* - - -.. _destructible: http://en.cppreference.com/w/cpp/types/is_destructible -.. _default_constructible: http://en.cppreference.com/w/cpp/types/is_constructible
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/usertype_memory.rst b/3rdparty/sol2/docs/source/api/usertype_memory.rst deleted file mode 100644 index e3a82ed120e..00000000000 --- a/3rdparty/sol2/docs/source/api/usertype_memory.rst +++ /dev/null @@ -1,47 +0,0 @@ -usertype memory -=============== - -.. note:: - - Sol does not take ownership of raw pointers, returned from functions or set through the ``set`` functions. Return a value, a ``std::unique_ptr``, a ``std::shared_ptr`` of some kind, or hook up the :doc:`unique usertypes traits<unique_usertype_traits>` to work for some specific handle structure you use (AKA, for ``boost::shared_ptr``). - -The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from :ref:`usertype_traits\<T><usertype-traits>`. Note that we use 1 metatable per the 3 styles listed below, plus 1 additional metatable that is used for the actual table that you bind with the name when calling ``table::new/set_(simple_)usertype``. - -In general, we always insert a T* in the first `sizeof(T*)` bytes, so the any framework that pulls out those first bytes expecting a pointer will work. The rest of the data has some different alignments and contents based on what it's used for and how it's used. - -For ``T`` ---------- - -These are classified with the metatable name from :ref:`usertype_traits\<T><usertype-traits>`. - -The data layout for references is as follows:: - - | T* | T | - ^-sizeof(T*) bytes-^-sizeof(T) bytes, actual data-^ - -Lua will clean up the memory itself but does not know about any destruction semantics T may have imposed, so when we destroy this data we simply call the destructor to destroy the object and leave the memory changes to for lua to handle after the "__gc" method exits. - - -For ``T*`` ----------- - -These are classified as a separate ``T*`` metatable, essentially the "reference" table. Things passed to Sol as a pointer or as a ``std::reference<T>`` are considered to be references, and thusly do not have a ``__gc`` (garbage collection) method by default. All raw pointers are non-owning pointers in C++. If you're working with a C API, provide a wrapper around pointers that are supposed to own data and use the constructor/destructor idioms (e.g., with an internal ``std::unique_ptr``) to keep things clean. - -The data layout for data that only refers is as follows:: - - | T* | - ^-sizeof(T*) bytes-^ - -That is it. No destruction semantics need to be called. - -For ``std::unique_ptr<T, D>`` and ``std::shared_ptr<T>`` --------------------------------------------------------- - -These are classified as :ref:`"unique usertypes"<unique-usertype>`, and have a special metatable for them as well. The special metatable is either generated when you add the usertype to Lua using :ref:`set_usertype<set-usertype>` or when you first push one of these special types. In addition to the data, a deleter function that understands the following layout is injected into the userdata layout. - -The data layout for these kinds of types is as follows:: - - | T* | void(*)(void*) function_pointer | T | - ^-sizeof(T*) bytes-^-sizeof(void(*)(void*)) bytes, deleter-^- sizeof(T) bytes, actal data -^ - -Note that we put a special deleter function before the actual data. This is because the custom deleter must know where the offset to the data is and where the special deleter is. In other words, fixed-size-fields come before any variably-sized data (T can be known at compile time, but when serialized into Lua in this manner it becomes a runtime entity). Sol just needs to know about ``T*`` and the userdata (and userdata metatable) to work, everything else is for preserving construction / destruction semantics.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/var.rst b/3rdparty/sol2/docs/source/api/var.rst deleted file mode 100644 index 9e9bcec57d9..00000000000 --- a/3rdparty/sol2/docs/source/api/var.rst +++ /dev/null @@ -1,49 +0,0 @@ -var -=== -For hooking up static / global variables to Lua usertypes ---------------------------------------------------------- - -The sole purpose of this tagging type is to work with :doc:`usertypes<usertype>` to provide ``my_class.my_static_var`` access, and to also provide reference-based access as well. - -.. code-block:: cpp - - #include <sol.hpp> - - struct test { - static int muh_variable; - }; - int test::muh_variable = 25; - - - int main () { - sol::state lua; - lua.open_libraries(); - lua.new_usertype<test>("test", - "direct", sol::var(2), - "global", sol::var(test::muh_variable), - "ref_global", sol::var(std::ref(test::muh_variable)) - ); - - int direct_value = lua["test"]["direct"]; - // direct_value == 2 - - int global = lua["test"]["global"]; - // global == 25 - int global2 = lua["test"]["ref_global"]; - // global2 == 25 - - test::muh_variable = 542; - - global = lua["test"]["global"]; - // global == 25 - // global is its own memory: was passed by value - - global2 = lua["test"]["ref_global"]; - // global2 == 542 - // global2 was passed through std::ref - // global2 holds a reference to muh_variable - // if muh_variable goes out of scope or is deleted - // problems could arise, so be careful! - - return 0; - } diff --git a/3rdparty/sol2/docs/source/api/variadic_args.rst b/3rdparty/sol2/docs/source/api/variadic_args.rst deleted file mode 100644 index 5d3e0c10282..00000000000 --- a/3rdparty/sol2/docs/source/api/variadic_args.rst +++ /dev/null @@ -1,49 +0,0 @@ -variadic_args -============= -transparent argument to deal with multiple parameters to a function -------------------------------------------------------------------- - - -.. code-block:: cpp - - struct variadic_args; - -This class is meant to represent every single argument at its current index and beyond in a function list. It does not increment the argument count and is thus transparent. You can place it anywhere in the argument list, and it will represent all of the objects in a function call that come after it, whether they are listed explicitly or not. - -``variadic_args`` also has ``begin()`` and ``end()`` functions that return (almost) random-acess iterators. These return a proxy type that can be implicitly converted, much like the :doc:`table proxy type<proxy>`. - -.. code-block:: cpp - :linenos: - - #include <sol.hpp> - - int main () { - - sol::state lua; - - // Function requires 2 arguments - // rest can be variadic, but: - // va will include everything after "a" argument, - // which means "b" will be part of the varaidic_args list too - // at position 0 - lua.set_function("v", [](int a, sol::variadic_args va, int b) { - int r = 0; - for (auto v : va) { - int value = v; // get argument out (implicit conversion) - // can also do int v = va.get<int>(i); with index i - r += value; - } - // Only have to add a, b was included - return r + a; - }); - - lua.script("x = v(25, 25)"); - lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); - lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); - // will error: not enough arguments - //lua.script("x4 = v(1)"); - - lua.script("print(x)"); // 50 - lua.script("print(x2)"); // 600 - lua.script("print(x3)"); // 21 - } diff --git a/3rdparty/sol2/docs/source/benchmarks.rst b/3rdparty/sol2/docs/source/benchmarks.rst deleted file mode 100644 index 6fa3224ffda..00000000000 --- a/3rdparty/sol2/docs/source/benchmarks.rst +++ /dev/null @@ -1,94 +0,0 @@ -benchmarks -========== -because somebody is going to ask eventually... ----------------------------------------------- - - -Here are measurements of the *overhead that libraries impose around the Lua C API*: that is, the cost of abstracting / wrapping the plain Lua C API. Measurements are (at the time of writing) done with all libraries compiled against a DLL version of Lua 5.3.3 to make sure each Lua call has the same overhead between libraries (no Link Time Optimizations or other static library optimizations). - -These are some informal and formal benchmarks done by both the developers of sol and other library developers / users. We leave you to interpret the data as you see fit. - -* `lua_binding_benchmarks`_ by satoren (developer of `kaguya`_) (`Sol`_ is the "sol2" entry) -* `lua-bench`_ by ThePhD (developer of `Sol`_) - -As of the writing of this documentation (August 12th, 2016), :doc:`Sol<index>` (Sol2) seems to take the cake in most categories for speed! Below are some graphs from `lua-bench`_. You can read the benchmarking code there if you think something was done wrong, and submit a pull requests or comment on something to make sure that ThePhD is being honest about his work. All categories are the performance of things described at the top of the :doc:`feature table<features>`. - -Note that Sol here makes use of its more performant variants (see :doc:`c_call<api/c_call>`), and ThePhD also does his best to make use of the most performant variants for other frameworks by disabling type checks where possible as well (Thanks to Liam Devine of OOLua for explaining how to turn off type checks in OOLua). - -Bars go up to the average execution time. Lower is better. Reported times are for the desired operation run through `nonius`_. Results are sorted from top to bottom by best to worst. Note that there are error bars to show potential variance in performance: generally, same-sized errors bars plus very close average execution time implies no significant difference in speed, despite the vastly different abstraction techniques used. - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls.png - :alt: bind several member functions to an object and call them in Lua code - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20userdata%20variable%20access.png - :alt: bind a variable to an object and call it in Lua code - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20userdata%20variables%20access.png - :alt: bind MANY variables to an object and call it in Lua code - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function%20through%20lua.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function%20through%20lua.png - :alt: retrieve a C function bound in Lua and call it from C++ - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20stateful%20c%20function.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20stateful%20c%20function.png - :alt: bind a stateful C function (e.g., a mutable lambda), retrieve it, and call it from C++ - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function.png - :alt: call a C function through Lua code - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20lua%20function.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20lua%20function.png - :alt: retrieve a plain Lua function and call it from C++ - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20multi%20return.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20multi%20return.png - :alt: return mutliple objects from C++ using std::tuple or through a library-defined mechanism - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20get.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20get.png - :alt: retrieve a value from the global table - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20set.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20set.png - :alt: set a value into the global table - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20get.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20get.png - :alt: measures the cost of doing consecutive lookups into a table that exists from C++; some libraries fail here because they do not do lazy evaluation or chaining properly - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20get.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20get.png - :alt: measures the cost of retrieving a value from a table in C++; this nests 1 level so as to not be equivalent to any measured global table get optimzations - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20set.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20set.png - :alt: measures the cost of doing consecutive lookups into a table that exists from C++ and setting the final value; some libraries fail here because they do not do lazy evaluation or chaining properly - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20set.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20set.png - :alt: measures the cost of setting a value into a table in C++; this nests 1 level so as to not be equivalent to any measured global table set optimzations - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20return%20userdata.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20return%20userdata.png - :alt: bind a C function which returns a custom class by-value and call it through Lua code - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20get%20optional.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20get%20optional.png - :alt: retrieve an item from a table that does not exist in Lua and check for its existence (testing the cost of the failure case) - -.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20base%20from%20derived.png - :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20base%20from%20derived.png - :alt: retrieve base class pointer out of Lua without knowing exact derived at compile-time, and have it be correct for multiple-inheritance - - - -.. _lua-bench: https://github.com/ThePhD/lua-bench -.. _lua_binding_benchmarks: http://satoren.github.io/lua_binding_benchmark/ -.. _kaguya: https://github.com/satoren/kaguya -.. _Sol: https://github.com/ThePhD/sol2 -.. _nonius: https://github.com/rmartinho/nonius/ diff --git a/3rdparty/sol2/docs/source/cmake.rst b/3rdparty/sol2/docs/source/cmake.rst deleted file mode 100644 index 2d9e378d7e6..00000000000 --- a/3rdparty/sol2/docs/source/cmake.rst +++ /dev/null @@ -1,54 +0,0 @@ -CMake Script -============ - -Thanks to `Kevin Brightwell`_, you can drop this CMake Script into your CMake Projects to have Sol part of one of its builds: - -.. code-block:: cmake - :caption: CMake Build Script - :name: cmake-build-script - - # Needed for ExternalProject_Add() - include(ExternalProject) - - # Needed for building single header for sol2 - find_package(PythonInterp 3 REQUIRED) - - # Configuration data for What sol2 version to use and where to put it - set(SOL2_TAG v2.5.6) - set(SOL2_HPP "${CMAKE_BINARY_DIR}/include/sol.hpp") - - # Download and "install" sol2 - ExternalProject_add( - sol2 - PREFIX ${VENDOR_PATH} # Set this value yourself - - GIT_REPOSITORY "https://github.com/ThePhD/sol2.git" - GIT_TAG ${SOL2_TAG} - - # No CMake commands to run, so tell CMake not to configure - CONFIGURE_COMMAND "" - - # Generate the single header and put it in ${SOL2_HPP} - BINARY_DIR ${VENDOR_PREFIX}/src/sol2 - BUILD_COMMAND - ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/include - COMMAND - ${PYTHON_EXECUTABLE} ./single.py -o "${SOL2_HPP}" - - # No install or test command for the library - INSTALL_COMMAND "" - TEST_COMMAND "") - - # Conditionally turn on SOL_CHECK_ARGUMENTS if using Debug mode - if (CMAKE_BUILD_TYPE MATCHES "[Dd]ebug") - if (VERBOSE) - message(STATUS "Turning on SOL_CHECK_ARGUMENTS in Debug mode.") - endif() - add_definitions(-DSOL_CHECK_ARGUMENTS) - endif() - - # Make sure sol2 is found as a system directory - include_directories(SYSTEM ${CMAKE_BINARY_DIR}/include) - - -.. _Kevin Brightwell: https://github.com/ThePhD/sol2/issues/89 diff --git a/3rdparty/sol2/docs/source/codecvt.rst b/3rdparty/sol2/docs/source/codecvt.rst deleted file mode 100644 index 750f6936bd3..00000000000 --- a/3rdparty/sol2/docs/source/codecvt.rst +++ /dev/null @@ -1,8 +0,0 @@ -std::(w/u16/u32)string support -============================== -because this is surprisingly hard using standard C++ ----------------------------------------------------- - -Individuals using Visual Studio 2015, or on Windows with the VC++ and MinGW compilers (possibly Clang++ on Windows as well) have ``<codecvt>`` headers, and thusly Sol will attempt to include it. Individuals on GC 4.9.x, Clang 3.5.x, Clang 3.6.x do not seem to have ``<codecvt>`` shipped with the standard library that comes with installation of these compilers. If you want ``std::wstring``, ``std::u16string``, ``std::u32string`` automatic handling then you need to make sure you have those headers and then define ``SOL_CODECVT_SUPPORT`` on unsupported compilers. - -ThePhD did not want this to have to be a thing, but slow implementations and such force their hand. When GCC 7.x comes out, ThePhD will consider removing the effect of defining this macro and leaving <codecvt> support in at all times. diff --git a/3rdparty/sol2/docs/source/compilation.rst b/3rdparty/sol2/docs/source/compilation.rst deleted file mode 100644 index 22b894e7f8d..00000000000 --- a/3rdparty/sol2/docs/source/compilation.rst +++ /dev/null @@ -1,25 +0,0 @@ -binary size, compile time -========================= -getting good final product out of sol2 --------------------------------------- - -For individiauls who use :doc:`usertypes<api/usertype>` a lot, they can find their compilation times increase. This is due to C++11 and C++14 not having very good facilities for handling template parameters and variadic template parameters. There are a few things in cutting-edge C++17 and C++Next that sol can use, but the problem is many people cannot work with the latest and greatest: therefore, we have to use older techniques that result in a fair amount of redundant function specializations that can be subject to the pickiness of the compiler's inlining and other such techniques. - -what to do ----------- - -Here are some notes on achieving better compile-times without sacrificing too much performance: - -* When you bind lots of usertypes, put them all in a *single* translation unit (one C++ file) so that it is not recompiled multiple times over, only to be discarded later by the linker. - - Remember that the usertype binding ends up being serialized into the Lua state, so you never need them to appear in a header and cause that same compilation overhead for every compiled unit in your project. -* For extremely large usertypes, consider using :doc:`simple_usertype<api/simple_usertype>`. - - It performs much more work at runtime rather than compile-time, and should still give comparative performance (but it loses out in some cases for variable bindings or when you bind all functions to a usertype). -* If you are developing a shared library, restrict your overall surface area by specifically and explicitly marking functions as visible and exported and leaving everything else as hidden or invisible by default - - -next steps ----------- - -The next step for Sol from a developer standpoint is to formally make the library a C++17 one. This would mean using Fold Expressions and several other things which will reduce compilation time drastically. Unfortunately, that means also boosting compiler requirements. While most wouldn't care, others are very slow to upgrade: finding the balance is difficult, and often we have to opt for backwards compatibility and fixes for bad / older compilers (of which there are many in the codebase already). - -Hopefully, as things progress, we move things forward. diff --git a/3rdparty/sol2/docs/source/conf.py b/3rdparty/sol2/docs/source/conf.py deleted file mode 100644 index 02d00f92ef4..00000000000 --- a/3rdparty/sol2/docs/source/conf.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Sol documentation build configuration file, created by -# sphinx-quickstart on Mon Feb 29 21:49:51 2016. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.todo' -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'Sol' -copyright = '2016, ThePhD' -author = 'ThePhD' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '2.15' -# The full version, including alpha/beta/rc tags. -release = '2.15.5' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# The default highlighting language: default is python -highlight_language = 'c++' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "haiku" - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ["_themes", ] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (relative to this directory) to use as a favicon of -# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' -#html_search_language = 'en' - -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} - -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Soldoc' - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'Sol.tex', 'Sol Documentation', - 'ThePhD', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'sol', 'Sol Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'Sol', 'Sol Documentation', - author, 'Sol', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False diff --git a/3rdparty/sol2/docs/source/eevee_code_after.jpg b/3rdparty/sol2/docs/source/eevee_code_after.jpg Binary files differdeleted file mode 100644 index 33594ce5e0b..00000000000 --- a/3rdparty/sol2/docs/source/eevee_code_after.jpg +++ /dev/null diff --git a/3rdparty/sol2/docs/source/eevee_code_before.jpg b/3rdparty/sol2/docs/source/eevee_code_before.jpg Binary files differdeleted file mode 100644 index ea9650ff1ac..00000000000 --- a/3rdparty/sol2/docs/source/eevee_code_before.jpg +++ /dev/null diff --git a/3rdparty/sol2/docs/source/errors.rst b/3rdparty/sol2/docs/source/errors.rst deleted file mode 100644 index c44ebe76988..00000000000 --- a/3rdparty/sol2/docs/source/errors.rst +++ /dev/null @@ -1,56 +0,0 @@ -errors -====== -how to handle exceptions or other errors ----------------------------------------- - -Here is some advice and some tricks for common errors about iteration, compile time / linker errors, and other pitfalls, especially when dealing with thrown exceptions, error conditions and the like in Sol. - - -Linker Errors -------------- - -There are lots of reasons for compiler linker errors. A common one is not knowing that you've compiled the Lua library as C++: when building with C++, it is important to note that every typical (static or dynamic) library expects the C calling convention to be used and that Sol includes the code using ``extern 'C'`` where applicable. - -However, when the target Lua library is compiled with C++, one must change the calling convention and name mangling scheme by getting rid of the ``extern 'C'`` block. This can be achieved by adding ``#define SOL_USING_CXX_LUA`` before including sol2, or by adding it to your compilation's command line. - - -Catch and CRASH! ----------------- - -By default, Sol will add a ``default_at_panic`` handler. If exceptions are not turned off, this handler will throw to allow the user a chance to recover. However, in almost all cases, when Lua calls ``lua_atpanic`` and hits this function, it means that something *irreversibly wrong* occured in your code or the Lua code and the VM is in an unpredictable or dead state. Catching an error thrown from the default handler and then proceeding as if things are cleaned up or okay is NOT the best idea. Unexpected bugs in optimized and release mode builds can result, among other serious issues. - -It is preferred if you catch an error that you log what happened, terminate the Lua VM as soon as possible, and then crash if your application cannot handle spinning up a new Lua state. Catching can be done, but you should understand the risks of what you're doing when you do it. For more information about catching exceptions, the potentials, not turning off exceptions and other tricks and caveats, read about :doc:`exceptions in Sol here<exceptions>`. - -Lua is a C API first and foremost: exceptions bubbling out of it is essentially last-ditch, terminal behavior that the VM does not expect. You can see an example of handling a panic on the exceptions page :ref:`here<typical-panic-function>`. - - -Destructors and Safety ----------------------- - -Another issue is that Lua is a C API. It uses ``setjmp`` and ``longjmp`` to jump out of code when an error occurs. This means it will ignore destructors in your code if you use the library or the underlying Lua VM improperly. To solve this issue, build Lua as C++. When a Lua VM error occurs and ``lua_error`` is triggered, it raises it as an exception which will provoke proper unwinding semantics. - - -Protected Functions and Access ------------------------------- - -By default, :doc:`sol::function<api/function>` assumes the code ran just fine and there are no problems. :ref:`sol::state(_view)::script(_file)<state-script-function>` also assumes that code ran just fine. Use :doc:`sol::protected_function<api/protected_function>` to have function access where you can check if things worked out. Use :doc:`sol::optional<api/optional>` to get a value safely from Lua. Use :ref:`sol::state(_view)::do_string/do_file/load/load_file<state-do-code>` to safely load and get results from a script. The defaults are provided to be simple and fast with thrown exceptions to violently crash the VM in case things go wrong. - -Protected Functions Are Not Catch All -------------------------------------- - -Sometimes, some scripts load poorly. Even if you protect the function call, the actual file loading or file execution will be bad, in which case :doc:`sol::protected_function<api/protected_function>` will not save you. Make sure you register your own panic handler so you can catch errors, or follow the advice of the catch + crash behavior above. - -Raw Functions -------------- - -When you push a function into Lua using Sol using any methods and that function exactly matches the signature ``int( lua_State* );`` (and is a free function (e.g., not a member function pointer)), it will be treated as a *raw C function*. This means that the usual exception trampoline Sol wraps your other function calls in will not be present. You will be responsible for catching exceptions and handling them before they explode into the C API (and potentially destroy your code). Sol in all other cases adds an exception-handling trampoline that turns exceptions into Lua errors that can be caught by the above-mentioned protected functions and accessors. - -.. warning:: - - Do NOT assume that building Lua as C++ will allow you to throw directly from a raw function. If an exception is raised and it bubbles into the Lua framework, even if you compile as C++, Lua does not recognize exceptions other than the ones that it uses with ``lua_error``. In other words, it will return some completely bogus result, potentially leave your Lua stack thrashed, and the rest of your VM *can* be in a semi-trashed state. Please avoid this! - - -Iteration ---------- - -Tables may have other junk on them that makes iterating through their numeric part difficult when using a bland ``for-each`` loop, or when calling sol's ``for_each`` function. Use a numeric look to iterate through a table. Iteration does not iterate in any defined order also: see :ref:`this note in the table documentation for more explanation<iteration_note>`. diff --git a/3rdparty/sol2/docs/source/exceptions.rst b/3rdparty/sol2/docs/source/exceptions.rst deleted file mode 100644 index 0e6584a20ef..00000000000 --- a/3rdparty/sol2/docs/source/exceptions.rst +++ /dev/null @@ -1,65 +0,0 @@ -exceptions -========== -since somebody is going to ask about it... ------------------------------------------- - -Yes, you can turn off exceptions in Sol with ``#define SOL_NO_EXCEPTIONS`` before including or by passing the command line argument that defines ``SOL_NO_EXCEPTIONS``. We don't recommend it unless you're playing with a Lua distro that also doesn't play nice with exceptions (like non-x64 versions of :ref:`LuaJIT<LuaJIT and exceptions>` ). - -If you turn this off, the default `at_panic`_ function :doc:`state<api/state>` set for you will not throw. Instead, the default Lua behavior of aborting will take place (and give you no chance of escape unless you implement your own at_panic function and decide to try ``longjmp`` out). - -To make this not be the case, you can set a panic function directly with ``lua_atpanic( lua, my_panic_function );`` or when you create the ``sol::state`` with ``sol::state lua(my_panic_function);``. Here's an example ``my_panic_function`` you can have that prints out its errors: - -.. code-block:: cpp - :caption: regular panic function - :name: typical-panic-function - - #include <sol.hpp> - #include <iostream> - - inline void my_panic(sol::optional<std::string> maybe_msg) { - std::cerr << "Lua is in a panic state and will now abort() the application" << std::endl; - if (maybe_msg) { - const std::string& msg = maybe_msg.value(); - std::cerr << "\terror message: " << msg << std::endl; - } - // When this function exits, Lua will exhibit default behavior and abort() - } - - int main () { - sol::state lua(sol::c_call<decltype(&my_panic), &my_panic>); - // or, if you already have a lua_State* L - // lua_atpanic( L, sol::c_call<decltype(&my_panic)>, &my_panic> ); - // or, with state/state_view: - // sol::state_view lua(L); - // lua.set_panic( sol::c_call<decltype(&my_panic)>, &my_panic> ); - } - - -Note that ``SOL_NO_EXCEPTIONS`` will also disable :doc:`protected_function<api/protected_function>`'s ability to catch C++ errors you throw from C++ functions bound to Lua that you are calling through that API. So, only turn off exceptions in Sol if you're sure you're never going to use exceptions ever. Of course, if you are ALREADY not using Exceptions, you don't have to particularly worry about this and now you can use Sol! - -If there is a place where a throw statement is called or a try/catch is used and it is not hidden behind a ``#ifndef SOL_NO_EXCEPTIONS`` block, please file an issue at `issue`_ or submit your very own pull request so everyone can benefit! - - -.. _LuaJIT and exceptions: - -LuaJIT and exceptions ---------------------- - -It is important to note that a popular 5.1 distribution of Lua, LuaJIT, has some serious `caveats regarding exceptions`_. LuaJIT's exception promises are flaky at best on x64 (64-bit) platforms, and entirely terrible on non-x64 (32-bit, ARM, etc.) platforms. The trampolines we have in place for all functions bound through conventional means in Sol will catch exceptions and turn them into Lua errors so that LuaJIT remainds unperturbed, but if you link up a C function directly yourself and throw, chances are you might have screwed the pooch. - -Testing in `this closed issue`_ that it doesn't play nice on 64-bit Linux in many cases either, especially when it hits an error internal to the interpreter (and does not go through Sol). We do have tests, however, that compile for our continuous integration check-ins that check this functionality across several compilers and platforms to keep you protected and given hard, strong guarantees for what happens if you throw in a function bound by Sol. If you stray outside the realm of Sol's protection, however... Good luck. - -Lua and LuaJIT C++ Exception Full Interoperability --------------------------------------------------- - -You can ``#define SOL_EXCEPTIONS_SAFE_PROPAGATION`` before including Sol or define ``SOL_EXCEPTIONS_SAFE_PROPAGATION`` on the command line if you know your implmentation of Lua has proper unwinding semantics that can be thrown through the version of the Lua API you have built / are using. - -This will prevent sol from catching ``(...)`` errors in platforms and compilers that have full C++ exception interoperability. This means that Lua errors can be caught with ``catch (...)`` in the C++ end of your code after it goes through Lua, and exceptions can pass through the Lua API and Stack safely. - -Currently, the only known platform to do this is the listed "Full" `platforms for LuaJIT`_ and Lua compiled as C++. This define is not turned on automatically, even if Sol detects LuaJIT: *it is your job to define it if you know that your platform supports it*! - -.. _issue: https://github.com/ThePhD/sol2/issues/ -.. _at_panic: http://www.Lua.org/manual/5.3/manual.html#4.6 -.. _caveats regarding exceptions: http://luajit.org/extensions.html#exceptions -.. _platforms for LuaJIT: http://luajit.org/extensions.html#exceptions -.. _this closed issue: https://github.com/ThePhD/sol2/issues/28 diff --git a/3rdparty/sol2/docs/source/features.rst b/3rdparty/sol2/docs/source/features.rst deleted file mode 100644 index 6d52e317eeb..00000000000 --- a/3rdparty/sol2/docs/source/features.rst +++ /dev/null @@ -1,259 +0,0 @@ -features -======== -what does Sol (and other libraries) support? --------------------------------------------- - -The goal of Sol is to provide an incredibly clean API that provides high performance (comparable or better than the C it was written on) and extreme ease of use. That is, users should be able to say: "this works pretty much how I expected it to." - -For the hard technical components of Lua and its ecosystem we support, here is the full rundown: - -what Sol supports ------------------ - -* Support for Lua 5.1, 5.2, and 5.3. We achieve this through our "doc:`compatibility<compatibility>` header. - -* :doc:`Table<api/table>` support: setting values, getting values of multiple (different) types - - :doc:`Lazy evaluation<api/proxy>` for nested/chained queries - ``table["a"]["b"]["c"] = 24;`` - - Implicit conversion to the types you want - ``double b = table["computed_value"];`` - -* :doc:`Optional<api/optional>` support: setting values, getting values of multiple (different) types - - :doc:`Lazy evaluation<api/proxy>` for nested/chained queries - ``optional<int> maybe_number = table["a"]["b"]["invalid_key"];`` - - Turns on safety when you want it: speed when you don't - -* Support for callables (functions, lambdas, member functions) - - Pull out any Lua function with :doc:`sol::function<api/function>` - ``sol::function fx = table["socket_send"];`` - - Can also set callables into :doc:`operator[] proxies<api/proxy>` - ``table["move_dude"] = engine::move_dude;`` - - Safety: use :doc:`sol::protected_function<api/protected_function>` to catch any kind of error - + ANY kind: C++ exception or Lua erors are trapped and run through the optional ``error_handler`` variable - - *Advanced:* Overloading of a single function so you don't need to do boring typechecks - -* User-Defined Type (:doc:`sol::usertype<api/usertype>` in the API) support: - - Set member functions to be called - - Set member variables - - Set variables on a class that are based on setter/getter functions - - Use free-functions that take the Type as a first argument (pointer or reference) - - Support for "Factory" classes that do not expose constructor or destructor - - Modifying memory of userdata in C++ directly affects Lua without copying, and - - Modifying userdata in Lua directly affects C++ references/pointers - ``my_class& a = table["a"];`` - ``my_class* a_ptr = table["a"];`` - - If you want a copy, just use value semantics and get copies: - ``my_class a = table["a"];`` - -* Thread/Coroutine support - - Use, resume, and play with :doc:`coroutines<api/coroutine>` like regular functions - - Get and use them even on a separate Lua :doc:`thread<api/thread>` - - Monitor status and get check errors - -* *Advanced:* Customizable and extensible to your own types if you override :doc:`getter/pusher/checker<api/stack>` template struct definitions. - - -The Feature Matrix™ -------------------- - -The below feature table checks for the presence of something. It, however, does not actually account for any kind of laborious syntax. - -✔ full support: works as you'd expect (operator[] on tables, etc...) - -~ partial support / wonky support: this means its either supported through some other fashion (not with the desired syntax, serious caveats, etc.). Sometimes means dropping down to use the plain C API (at which point, what was the point of the abstraction?). - -✗ no support: feature doesn't work or, if it's there, it REALLY sucks to use - -Implementation notes from using the libraries are below the tables. - - -category explanations ---------------------- - -Explanations for a few categories are below (rest are self-explanatory). - -* optional: Support for getting an element, or potentially not (and not forcing the default construction of what amounts to a bogus/dead object). Usually comes with ``std(::experimental)::optional``. It's a fairly new class, so a hand-rolled class internal to the library with similar semantics is also acceptable -* tables: Some sort of abstraction for dealing with tables. Ideal support is ``mytable["some_key"] = value``, and everything that the syntax implies. -* table chaining: In conjunction with tables, having the ability to query deeply into tables ``mytable["key1"]["key2"]["key3"]``. Note that this becomes a tripping point for some libraries: crashing if ``"key1"`` doesn't exist while trying to access ``"key2"`` (Sol avoids this specifically when you use ``sol::optional``), and sometimes it's also a heavy performance bottleneck as expressions are not lazy-evaluated by a library. -* arbitrary keys: Letting C++ code use userdata, other tables, integers, etc. as keys for into a table. -* user-defined types (udts): C++ types given form and function in Lua code. -* udts - member functions: C++ member functions on a type, usually callable with ``my_object:foo(1)`` or similar in Lua. -* udts - table variables: C++ member variables/properties, manipulated by ``my_object.var = 24`` and in Lua -* function binding: Support for binding all types of functions. Lambdas, member functions, free functions, in different contexts, etc... -* protected function: Use of ``lua_pcall`` to call a function, which offers error-handling and trampolining (as well as the ability to opt-in / opt-out of this behavior) -* multi-return: returning multiple values from and to Lua (generally through ``std::tuple<...>`` or in some other way) -* variadic/variant argument: being able to accept "anything" from Lua, and even return "anything" to Lua (``object`` abstraction, variadic arguments, etc...) -* inheritance: allowing some degree of subtyping or inheritance on classes / userdata from Lua - this generally means that you can retrieve a base pointer from Lua even if you hand the library a derived pointer -* overloading: the ability to call overloaded functions, matched based on arity or type (``foo( 1 )`` from lua calls a different function then ``foo( "bark" )``). -* Lua thread: basic wrapping of the lua thread API; ties in with coroutine. -* coroutines: allowing a function to be called multiple times, resuming the execution of a Lua coroutine each time - -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| | plain C | luawrapper | lua-intf | luabind | Selene | Sol2 | oolua | lua-api-pp | kaguya | SLB3 | SWIG | luacppinterface | luwra | -| | | | | | | | | | | | | | | -+===========================+=============+============+==========+=========+==========+===========+===========+================+==========+==========+===========+=================+========+ -| optional | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| tables | ~ | ~ | ~ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✗ | ✗ | ~ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| table chaining | ~ | ~ | ~ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✗ | ✗ | ~ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| arbitrary keys | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ~ | ✔ | ✗ | ✗ | ✗ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| user-defined types (udts) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| udts: member functions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| udts: table variables | ~ | ~ | ~ | ~ | ~ | ✔ | ~ | ~ | ~ | ✗ | ✔ | ✗ | ~ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| stack abstractions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✗ | ~ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| lua callables from C(++) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| function binding | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ~ | ~ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| protected call | ~ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | ~ | ~ | ~ | ~ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| multi-return | ~ | ✗ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| variadic/variant argument | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ~ | ~ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| inheritance | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ✔ | ~ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| overloading | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| Lua thread | ~ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| coroutines | ~ | ✗ | ~ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| no-rtti support | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| no-exception support | ✔ | ✗ | ✔ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| Lua 5.1 | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| Lua 5.2 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| Lua 5.3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| luajit | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ -| distribution | compile | header | both | compile | header | header | compile | compile | header | compile | generated | compile | header | -+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ - - -notes on implementations ------------------------- - -Plain C - - -* Obviously you can do anything you want with Plain C, but the effort involved is astronomical in comparison to what frameworks offer -* Does not scale very well (in terms of developer ease of use) -* Compilation (or package manager use) is obviously required for your platform and required to use ANY of these libraries, but that's okay because all libraries need some version of Lua anyways, so you always have this! - -kaguya - - -* Table variables / member variables are automatically turned into ``obj:x( value )`` to set and ``obj:x()`` to get -* Has optional support -* Inspired coroutine support for Sol -* Library author (satoren) is a nice guy! -* C++11/14, or boostified (which makes it C++03 compatible) -* Class registration is a bit verbose, but not as offensive as OOLua or lua-intf or others - -Sol - - -* One of the few libraries with optional support! -* Basically the fastest in almomst all respects: http://sol2.readthedocs.io/en/latest/benchmarks.html -* Overloading support can get messy with inheritance, see :doc:`here<api/overload>` -* C++14/"C++1y" (-std=c++14, -std=c++1y, =std=c++1z) flags are used (available since GCC 4.9 and Clang 3.5) -* Active issues, active individuals -* Deserves lots of love! - -lua-intf - - -* Can be both header-only or compiled -* Has optional support -* C++11 -* Macro-based registration (strange pseudo-language) -* Fairly fast in most regards -* Registering classes/"modules" in using C++ code is extremely verbose -* In order to chain lookups, one has to glue the keys together (e.g. ``"mykey.mykey2"``) on the ``operator[]`` lookup (e.g., you can't nest them arbitrarily, you have to pre-compose the proper lookup string) (fails miserably for non-string lookups!). -* Not too shabby! - -Selene - - -* Table variables / member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get -* Registering classes/"modules" using C++ code is extremely verbose, similar to lua-intf's style -* Eats crap when it comes to performance, most of the time (see :doc:`benchmarks<benchmarks>`) -* Lots of users (blogpost etc. made it popular), but the Repository is kinda stagnant... - -luawrapper - - -* Takes the approach of writing and reading tables using ``readVariable`` and ``writeVariable`` functions -* C++11, no macros! -* The interface can be clunky (no table-like data structures: most things go though ``readVariable`` / ``writeVariable``) -* Internal Compiler errors in Visual Studio 2015 - submitted a PR to fix it, hopefully it'll get picked up - -SWIG (3.0) - - -* Very comprehensive for binding concepts of C++ (classes, variables, etc.) to Lua -* Helps with literally nothing else (tables, threads, stack abstractions, etc.) -* Not really a good, full-featured Library... -* Requires preprocessing step (but it's not a... TERRIBLY complicated preprocessing step); some boilerplate in writing additional classes that you've already declared - -luacppinterface - - -* The branch that fixes VC++ warnings and introduces some new work has type checker issues, so use the stable branch only -* No table variable support -* Actually has tables (but no operator[]) -* Does not support arbitrary keys - -luabind - - -* One of the older frameworks, but has many people updating it and providing "deboostified" versions -* Strange in-lua keywords and parsing to allow for classes to be written in lua - - not sure if good feature; vendor lock-in to that library to depend on this specific class syntax? -* Comprehensive lua bindings (can even bind "properties") -* There's some code that produces an ICE in Visual C++: I submitted a fix to the library in the hopes that it'll get accepted -* Wonky table support: no basic conversion functions on ``luabind::object``; have to push object then use lua API to get what you want - -lua-api-pp - - -* Compiled, but the recommendation is to add the source files directly to your project -* Userdata registration with thick setup-macros: LUAPP_USERDATA( ... ) plus a bunch of free functions that take a ``T& self`` argument - - You can bind member functions directly but only if you override metatable entries - - Otherwise, COMPLICATED self-registration that makes you wonder why you're using the framework -* You have to create a context and then call it to start accessing the lua state (adding more boilerplate... thanks) - - Thankfully, unlike many libraries, it actually has a Table type that can be used semi-easily. FINALLY -* C++11-ish in some regards -* Sad face, thanks to the way userdata registration is handled - -SLB3 - - -* Old code exported to github from dying google code -* ".NET Style" - to override functionality, derive from class -- boilerplate (isn't that what we're trying to get rid of?) -* Pointers everywhere: ownership semantics unclear -* Piss-poor documentation, ugh! -* Least favorite to work with, for sure! - -oolua - - -* The syntax for this library. `Go read the docs`_ -* The worst in terms of how to use it: may have docs, but the DSL is extraordinarily crappy with thick, hard-to-debug/hard-to-error-check macros - - Same problem as lua-api-pp: cannot have the declaration macros anywhere but the toplevel namespace because of template declaration macro -* Supports not having exceptions or rtti turned on (shiny!) -* Poor RAII support: default-construct-and-get style (requires some form of initalization to perform a ``get`` of an object, and it's hard to extend) - - The library author has informed me that he does personally advises individuals do not use the ``Table`` abstraction in OOLua... Do I likewise tell people to consider its table abstractions defunct? -* Table variables / member variables from C++ are turned into function calls (``get_x`` and ``set_x`` by default) - -luwra - - -* How do you store stateful functors / lambas? So far, no support for such. -* Cannot pull functions without first leaving them on the stack: manual cleanup becomes a thing -* Doesn't understand ``std::function`` conversions and the like (but with some extra code can get it to work) -* Recently improved by a lot: can chain tables and such, even if performance is a bit sad for that use case -* When you do manage to set function calls with the macros they are fast (can a template solution do just as good? Sol is going to find out!) -* No table variable support - get turned into getter/setter functions, similar to kaguya -* Table variables become class statics (surprising) - -.. _Go read the docs: https://oolua.org/docs/index.html diff --git a/3rdparty/sol2/docs/source/index.rst b/3rdparty/sol2/docs/source/index.rst deleted file mode 100644 index 77fb8fdf9b6..00000000000 --- a/3rdparty/sol2/docs/source/index.rst +++ /dev/null @@ -1,132 +0,0 @@ -.. Sol documentation master file, created by - sphinx-quickstart on Mon Feb 29 21:49:51 2016. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -.. image:: sol.png - :target: https://github.com/ThePhD/sol2 - :alt: sol2 repository - -Sol |version| -============= -a fast, simple C++ and Lua Binding ----------------------------------- - -When you need to hit the ground running with Lua and C++, `Sol`_ is the go-to framework for high-performance binding with an easy to use API. - -.. image:: https://travis-ci.org/ThePhD/sol2.svg?branch=develop - :target: https://travis-ci.org/ThePhD/sol2 - :alt: build status - -.. image:: https://badges.gitter.im/chat-sol2/Lobby.svg - :target: https://gitter.im/chat-sol2/Lobby - :alt: chat about sol2 on gitter - - -get going: ----------- - -.. toctree:: - :maxdepth: 1 - :name: mastertoc - - tutorial/all-the-things - tutorial/tutorial-top - errors - compilation - features - usertypes - traits - api/api-top - mentions - benchmarks - performance - safety - exceptions - rtti - codecvt - cmake - licenses - origin - - -"I need feature X, maybe you have it?" --------------------------------------- -Take a look at the :doc:`Features<features>` page: it links to much of the API. You can also just straight up browse the :doc:`api<api/api-top>` or ease in with the :doc:`tutorials<tutorial/tutorial-top>`. To know more about the implementation for usertypes, see :doc:`here<usertypes>` To know how function arguments are handled, see :ref:`this note<function-argument-handling>`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker. - - -the basics: ------------ - -.. note:: - More examples can be found in the `examples directory`_ - - -.. code-block:: c++ - :caption: functions - :linenos: - - #include <sol.hpp> - #include <cassert> - - int main() { - sol::state lua; - int x = 0; - lua.set_function("beep", [&x]{ ++x; }); - lua.script("beep()"); - assert(x == 1); - - sol::function beep = lua["beep"]; - beep(); - assert(x == 2); - - return 0; - } - - -.. code-block:: c++ - :caption: linking C++ structures to Lua - :linenos: - - #include <sol.hpp> - #include <cassert> - - struct vars { - int boop = 0; - - int bop () const { - return boop + 1; - } - }; - - int main() { - sol::state lua; - lua.new_usertype<vars>("vars", - "boop", &vars::boop - "bop", &vars::bop); - lua.script("beep = vars.new()\n" - "beep.boop = 1\n" - "bopvalue = beep:bop()"); - - vars& beep = lua["beep"]; - int bopvalue = lua["bopvalue"]; - - assert(beep.boop == 1); - assert(lua.get<vars>("beep").boop == 1); - assert(beep.bop() == 2); - assert(bopvalue == 2); - - return 0; - } - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` - -.. _Sol: https://github.com/ThePhD/sol2 -.. _issues: https://github.com/ThePhD/sol2/issues -.. _examples directory: https://github.com/ThePhD/sol2/tree/develop/examples
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/licenses.rst b/3rdparty/sol2/docs/source/licenses.rst deleted file mode 100644 index f43d97b5e3a..00000000000 --- a/3rdparty/sol2/docs/source/licenses.rst +++ /dev/null @@ -1,47 +0,0 @@ -licenses -======== - -The following licenses cover all of the code in Sol. Spoiler: they're all `MIT`_ and it's safe to use in commercial code: feel free to copy/paste the below right into your own attributions / licenses file. - -Sol - ThePhD/sol2: ------------------- - - The MIT License (MIT) - - Copyright (c) 2013-2016 Rapptz, ThePhD, and contributors - - 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. - - -Lua-compat-5.3 - keplerproject/Lua-compat-5.3: ----------------------------------------------- - - The MIT License (MIT) - - Copyright (c) 2015 Kepler Project. - - 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. - -Lua - Lua.org: --------------- - - The MIT License (MIT) - - Copyright © 1994–2015 Lua.org, PUC-Rio. - - 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. - - - .. _MIT: http://opensource.org/licenses/MIT
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/mentions.rst b/3rdparty/sol2/docs/source/mentions.rst deleted file mode 100644 index 7ce2a1f3485..00000000000 --- a/3rdparty/sol2/docs/source/mentions.rst +++ /dev/null @@ -1,62 +0,0 @@ -mentions -======== -so does anyone cool use this thing...? --------------------------------------- - -First off, feel free to `tell me about your uses!`_ - -Okay, so the features don't convince you, the documentation doesn't convince you, you want to see what *other* people think about Sol? Well, aside from the well-wishes that come through in the issue tracker, here's a few things floating around about sol2 that I occasionally get pinged about: - -`eevee`_ demonstrating the sheer code reduction by using sol2: - - -.. |before| image:: eevee_code_before.jpg - :target: https://twitter.com/eevee/status/762039984085798913 - :alt: Plain C API - :align: middle - -.. |after| image:: eevee_code_after.jpg - :target: https://twitter.com/eevee/status/762039984085798913 - :alt: Now with sol2! - :align: middle - -+----------+---------+ -| |before| | |after| | -+----------+---------+ - -* The `Multiple Arcade Machine Emulator (MAME)`_ project switched from using LuaBridge to sol2! - - `The pull request`_ in which it was introduced to the master branch. -* (CppNow) sol2 was mentioned in a comparison to other scripting languages by ChaiScript developer, Jason Turner (@lefticus), at a conference! - - `Jason Turner's presentation`_ -* (CppCast) Showed up in CppCast with Elias Daler! - - `Elias Daler's blog`_ - - `CppCast`_ -* (Eevee) A really nice and neat developer/artist/howaretheysotalented person is attempting to use it for zdoom! - - `eevee's blog`_ -* (Twitter) Twitter has some people that link it: - - The image above, `tweeted out by eevee`_ - - Eevee: `"I heartily recommend sol2"`_ - - Elias Daler: `"sol2 saved my life."`_ - - Racod's Lair: `"from outdated LuaBridge to superior #sol2"`_ -* (Reddit) Posts on reddit about it! - - `sol2's initial reddit release`_ - - `Benchmarking Discussing`_ -* Somehow landed on a Torque3D thread... - - http://forums.torque3d.org/viewtopic.php?f=32&t=629&p=5246&sid=8e759990ab1ce38a48e896fc9fd62653#p5241 - -Are you using sol2 for something neat? Want it to be featured here or think it's unfair that ThePhD hasn't found it yet? Well, drop an issue in the repo or send an e-mail! - -.. _tell me about your uses!: https://github.com/ThePhD/sol2/issues/189 -.. _eevee: https://twitter.com/eevee -.. _eevee's blog: https://eev.ee/dev/2016/08/07/weekly-roundup-three-big-things/ -.. _Jason Turner's presentation: https://github.com/lefticus/presentations/blob/master/HowAndWhyToAddScripting.md -.. _Elias Daler's blog: https://eliasdaler.github.io/cppcast#read-more -.. _CppCast: http://cppcast.com/2016/07/elias-daler/ -.. _tweeted out by eevee: https://twitter.com/eevee/status/762039984085798913 -.. _"I heartily recommend sol2": https://twitter.com/eevee/status/762040086540144644 -.. _"from outdated LuaBridge to superior #sol2": https://twitter.com/racodslair/status/754031870640267264 -.. _sol2's initial reddit release: https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/ -.. _Benchmarking Discussing: https://www.reddit.com/r/cpp/comments/4x82hd/plain_c_versus_lua_libraries_benchmarking_speed/ -.. _"sol2 saved my life.": https://twitter.com/EliasDaler/status/739215685264494593 -.. _Multiple Arcade Machine Emulator (MAME): http://www.mamedev.org/index.php -.. _The pull request: https://github.com/mamedev/mame/pull/1626 diff --git a/3rdparty/sol2/docs/source/origin.rst b/3rdparty/sol2/docs/source/origin.rst deleted file mode 100644 index cc2e3d72467..00000000000 --- a/3rdparty/sol2/docs/source/origin.rst +++ /dev/null @@ -1,28 +0,0 @@ -origin -====== - -In the beginning, there was Sir Dennis Ritchie. And Ritchie saw the void, and outstretched his hand, and commanded "Let there be water." And lo, it was so, and there was the C. And with the C, other entities dared to venture on the void given form. Lord Bjarne Stroustrup too did outstretch his hands and say "Let there be an abundance." And lo, into the sea was cast a double portion of surplus of all the things that swam. And for a while, it was good. But other entities were still curious about what yet lay undefined, and one such pantheon, PUC-RIO, saw that it fitting to create the moon. And with the waters and sea made and the moon cast in a starry night sky, PUC-RIO and Dennis and Stroustrup saw that they did good. They oversaw the moon and the sea and gave sound council and it grew. But as the time grew, humanity grew... discontent. No longer were the simple fishing rods and the flowing tides and the dark sky enough lit by a pale moon, no matter how miraculously they were made, enough. They sought out more. - -They sought out the light. - -And lo, `Danny Y., Rapptz`_ did stand firm in the sea and cast his hands to the sky and said "Let there be Light!". And in the sky was cast a sun. It was an early sun, a growing sun, and many gathered to its warmth, marveling at a life they never knew. And he saw that it was good... - - -seriously ---------- - -Sol was originally started by many moon cycles ago to interop with Lua and C++. `Rapptz`_ It was very successful and many rejoiced at having an easy to use abstraction on top of the Lua API. Rapptz continued to make a number of great projects and has been busy with other things, so upon seeing the repository grow stagnant and tired in the last very long while (over a year), `ThePhD`_ forked it into Sol2 and rebooted the code with the hopes of reaching the Milestone and the documentation you have today. - -To get to the old repo, head over `here`_. - - -the name --------- - -Sol means sun. The moon (Lua) needs a sun, because without it only the bleak night of copy-paste programming and off-by-one errors would prevail. - - -.. _here: https://github.com/Rapptz/sol -.. _ThePhD: https://github.com/ThePhD -.. _Danny Y., Rapptz: https://github.com/Rapptz -.. _Rapptz: https://github.com/Rapptz
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/performance.rst b/3rdparty/sol2/docs/source/performance.rst deleted file mode 100644 index 4115e01f5a0..00000000000 --- a/3rdparty/sol2/docs/source/performance.rst +++ /dev/null @@ -1,17 +0,0 @@ -getting performance -=================== -things to make Sol as fast as possible --------------------------------------- - - -As shown by the :doc:`benchmarks<benchmarks>`, Sol is very performant with its abstractions. However, in the case where you need every last drop of performance from Sol, a number of tips and API usage tricks will be documented here. PLEASE benchmark / profile your code before you start invoking these, as some of them trade in readability / clarity for performance. - -* If you have a bound function call / bound member function that you are going to call in a very tight, performance-heavy loop, considering using :doc:`sol::c_call<api/c_call>` -* Be wary of passing by value / reference, and what it means by reading :ref:`this note<function-argument-handling>`. -* It is currently undocumented that usertypes will "inherit" member function / member variables from bound classes, mostly because the semantics are unclear and it is not the most performant (although it is flexible: you can register base classes after / whenever you want in relation to the derived class, provided that derived class has its bases listed). Specifying all member functions / member variables for the usertype constructor / ``new_usertype`` function call and not relying on base lookup will boost performance of member lookup -* Use the :doc:`sol::stack_{}<api/stack_reference>` versions of functions in order to achieve maximum performance benefits when doing things like calling a function from Lua and knowing that certain arguments of certain Lua types will be on the stack. This can save you a very small fraction of performance to not copy to the register (but is also more dangerous and usually not terribly worth it). -* Specifying base classes can make getting the usertype out of Sol a bit slower since we have to check and cast; if you know the exact type wherever you're retrieving it, considering not specifying the bases, retrieving the exact type from Sol, and then casting to a base type yourself -* Member variables can sometimes cost an extra lookup to occur within the Lua system (as mentioned :doc:`bottom of the usertype page<api/usertype>`); until we find out a safe way around this, member variables will always incur that extra lookup cost - - -That's it as far as different performance options are avilable to make Sol run faster. Again, please make sure to invoke these only when you know Sol is the bottleneck. If you find some form of the performance unacceptable to you, also feel free to open an issue at the github.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/rtti.rst b/3rdparty/sol2/docs/source/rtti.rst deleted file mode 100644 index 91aad3e939b..00000000000 --- a/3rdparty/sol2/docs/source/rtti.rst +++ /dev/null @@ -1,14 +0,0 @@ -run-time type information (rtti) -================================ -because somebody's going to want to shut this off, too... ---------------------------------------------------------- - -Sol does not use RTTI anymore. - -*THE BELOW IS NO LONGER NEEDED.* - -Not compiling with C++'s run-time type information? Do a ``#define SOL_NO_RTII`` before you include ``sol.hpp`` or define ``SOL_NO_RTTI`` on your command line. Be sure to understand the :ref:`implications<usertype-inheritance>` of doing so if you also turn off exceptions. - -If you come across bugs or can't compile because there's a stray `typeid` or `typeinfo` that wasn't hidden behind a ``#ifndef SOL_NO_RTTI``, please file `an issue`_ or even make a pull request so it can be fixed for everyone. - -.. _an issue: https://github.com/ThePhD/sol2/issues
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/safety.rst b/3rdparty/sol2/docs/source/safety.rst deleted file mode 100644 index 321c37aaa70..00000000000 --- a/3rdparty/sol2/docs/source/safety.rst +++ /dev/null @@ -1,22 +0,0 @@ -safety -====== - -Sol was designed to be correct and fast, and in the pursuit of both uses the regular ``lua_to{x}`` functions of Lua rather than the checking versions (``lua_check{X}``) functions. The API defaults to paranoidly-safe alternatives if you have a ``#define SOL_CHECK_ARGUMENTS`` before you include Sol, or if you pass the ``SOL_CHECK_ARGUMENTS`` define on the build command for your build system. By default, it is off and remains off unless you define this, even in debug mode. The same goes for ``#define SOL_SAFE_USERTYPE``. - -Note that you can obtain safety with regards to functions you bind by using the :doc:`protect<api/protect>` wrapper around function/variable bindings you set into Lua. Additionally, you can have basic boolean checks when using the API by just converting to a :doc:`sol::optional\<T><api/optional>` when necessary for getting things out of Lua and for function arguments. - -``SOL_SAFE_USERTYPE`` triggers the following change: - * If the userdata to a usertype function is nil, will trigger an error instead of letting things go through and letting the system segfault. - -``SOL_CHECK_ARGUMENTS`` triggers the following changes: - * ``sol::stack::get`` (used everywhere) defaults to using ``sol::stack::check_get`` and dereferencing the argument. It uses ``sol::type_panic`` as the handler if something goes wrong. - * ``sol::stack::call`` and its variants will, if no templated boolean is specified, check all of the arguments for a function call. - * If ``SOL_SAFE_USERTYPE`` is not defined, it gets defined to turn being on. - -Tests are compiled with this on to ensure everything is going as expected. Remember that if you want these features, you must explicitly turn them on. - -Finally, some warnings that may help with errors when working with Sol: - -.. warning:: - - Do NOT save the return type of a :ref:`function_result<function-result>` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. See :ref:`here<function-result-warning>`.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/sol.png b/3rdparty/sol2/docs/source/sol.png Binary files differdeleted file mode 100644 index eedee2ed3d0..00000000000 --- a/3rdparty/sol2/docs/source/sol.png +++ /dev/null diff --git a/3rdparty/sol2/docs/source/sol.psd b/3rdparty/sol2/docs/source/sol.psd Binary files differdeleted file mode 100644 index 84865d5198b..00000000000 --- a/3rdparty/sol2/docs/source/sol.psd +++ /dev/null diff --git a/3rdparty/sol2/docs/source/traits.rst b/3rdparty/sol2/docs/source/traits.rst deleted file mode 100644 index b064223be08..00000000000 --- a/3rdparty/sol2/docs/source/traits.rst +++ /dev/null @@ -1,15 +0,0 @@ -customization traits -==================== - -These are customization points within the library to help you make sol2 work for the types in your framework and types. - -To learn more about various customizable traits, visit: - -* :ref:`containers detection trait<container-detection>` - - This is how to work with containers when you have an compiler error when serializing a type that has ``begin`` and ``end`` functions but isn't exactly a container. -* :doc:`unique usertype (custom pointer) traits<api/unique_usertype_traits>` - - This is how to deal with unique usertypes, e.g. ``boost::shared_ptr``, reference-counted pointers, etc. - - Useful for custom pointers from all sorts of frameworks or handle types that employ very specific kinds of destruction semantics and access. -* :doc:`customization point tutorial<tutorial/customization>` - - This is how to customize a type to work with sol2. - - Can be used for specializations to push strings and other class types that are not natively ``std::string`` or ``const char*``. diff --git a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst b/3rdparty/sol2/docs/source/tutorial/all-the-things.rst deleted file mode 100644 index 3b764b8d2e9..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/all-the-things.rst +++ /dev/null @@ -1,628 +0,0 @@ -tutorial: quick 'n' dirty -========================= - -These are all the things. Use your browser's search to find things you want. - -You'll need to ``#include <sol.hpp>``/``#include "sol.hpp"`` somewhere in your code. Sol is header-only, so you don't need to compile anything. - -opening a state ---------------- - -.. code-block:: cpp - - int main (int argc, char* argv[]) { - sol::state lua; - // open some common libraries - lua.open_libraries(sol::lib::base, sol::lib::package); - lua.script( "print('bark bark bark!')" ); - } - - -sol::state on lua_State* ------------------------- - -For your system/game that already has lua, but you'd like something nice: - -.. code-block:: cpp - - int pre_existing_system( lua_State* L ) { - sol::state_view lua(L); - lua.script( "print('bark bark bark!')" ); - return 0; - } - - -running lua code ----------------- - -.. code-block:: cpp - - sol::state lua; - // load and execute from string - lua.script("a = 'test'"); - // load and execute from file - lua.script_file("path/to/luascript.lua"); - - // run a script, get the result - int value = lua.script("return 54"); - // value == 54 - -To check the success of a loading operation: - -.. code-block:: cpp - - // load file without execute - sol::load_result script1 = lua.load_file("path/to/luascript.lua"); - script1(); //execute - // load string without execute - sol::load_result script2 = lua.load("a = 'test'"); - script2(); //execute - - sol::load_result script3 = lua.load("return 24"); - int value2 = script3(); // execute, get return value - // value2 == 24 - - -To check whether a script was successfully run or not (after loading is assumed to be successful): - -.. code-block:: cpp - - // execute and return result - sol::protected_function_result result1 = lua.do_string("return 24"); - if (result1.valid()) { - int value = result1; - // value == 24 - // yay! - } - else { - // ahhh :c - } - - -There is also ``lua.do_file("path/to/luascript.lua");``. - -set and get variables ---------------------- - -You can set/get everything. - -.. code-block:: cpp - - sol::lua_state lua; - - lua.open_libraries(sol::lib::base); - - // integer types - lua.set("number", 24); - - // floating point numbers - lua["number2"] = 24.5; - - // string types - lua["important_string"] = "woof woof"; - - // non-recognized types is stored as userdata - // is callable, therefore gets stored as a function - lua["a_function"] = [](){ return 100; }; - - // make a table - lua["some_table"] = lua.create_table_wth("value", 24); - - -Equivalent to loading a lua file with: - -.. code-block:: lua - - number = 24 - number2 = 24.5 - important_string = "woof woof" - a_function = function () return 100 end - some_table = { value = 24 } - -Retrieve these variables using this syntax: - -.. code-block:: cpp - - // implicit conversion - int number = lua["number"]; - - // explicit get - auto number2 = lua.get<double>("number2"); - - // strings too - std::string important_string = lua["important_string"]; - - // dig into a table - int value = lua["some_table"]["value"]; - - // get a function - sol::function a_function = lua["a_function"]; - int value_is_100 = a_function(); - - // get a std::function - std::function<int()> a_std_function = lua["a_function"]; - int value_is_still_100 = a_std_function(); - -Retrieve Lua types using ``object`` and other ``sol::`` types. - -.. code-block:: cpp - - sol::state lua; - - // ... everything from before - - sol::object number_obj = lua.get<sol::object>( "number" ); - // sol::type::number - sol::type t1 = number_obj.get_type(); - - sol::object function_obj = lua[ "a_function" ]; - // sol::type::function - sol::type t2 = function_obj.get_type(); - bool is_it_really = function_obj.is<std::function<int()>>(); // true - - // will not contain data - sol::optional<int> check_for_me = lua["a_function"]; - - -You can erase things by setting it to ``nullptr`` or ``sol::nil``. - -.. code-block:: cpp - - sol::state lua; - - lua.script("exists = 250"); - - int first_try = lua.get_or( "exists", 322 ); - // first_try == 250 - - lua.set("exists", sol::nil); - int second_try = lua.get_or( "exists", 322 ); - // second_try == 322 - - -Note that if its a :doc:`userdata/usertype<../api/usertype>` for a C++ type, the destructor will run only when the garbage collector deems it appropriate to destroy the memory. If you are relying on the destructor being run when its set to ``sol::nil``, you're probably committing a mistake. - -tables ------- - -:doc:`sol::state<../api/state>` is a table too. - -.. code-block:: cpp - - sol::state lua; - - // Raw string literal for easy multiline - lua.script( R"( - abc = { [0] = 24 } - def = { - ghi = { - bark = 50, - woof = abc - } - } - )" - ); - - sol::table abc = lua["abc"]; - sol::table def = lua["def"]; - sol::table ghi = lua["def"]["ghi"]; - - int bark1 = def["ghi"]["bark"]; - int bark2 = lua["def"]["ghi"]["bark"]; - // bark1 == bark2 == 50 - - int abcval1 = abc[0]; - int abcval2 = ghi["woof"][0]; - // abcval1 == abcval2 == 24 - -If you're going deep, be safe: - -.. code-block:: cpp - - sol::state lua; - - sol::optional<int> will_not_error = lua["abc"]["DOESNOTEXIST"]["ghi"]; - // will_not_error == sol::nullopt - int also_will_not_error = lua["abc"]["def"]["ghi"]["jklm"].get_or(25); - // is 25 - - // if you don't go safe, - // will throw (or do at_panic if no exceptions) - int aaaahhh = lua["boom"]["the_dynamite"]; - - -make tables ------------ - -Make some: - -.. code-block:: cpp - - sol::state lua; - - lua["abc"] = lua.create_table_with( - 0, 24 - ); - - lua.create_named_table("def", - "ghi", lua.create_table_with( - "bark", 50, - // can reference other existing stuff too - "woof", lua["abc"] - ) - ); - -Equivalent Lua code: - -.. code-block:: lua - - abc = { [0] = 24 } - def = { - ghi = { - bark = 50, - woof = abc - } - } - - -You can put anything you want in tables as values or keys, including strings, numbers, functions, other tables. - -Note that this idea that things can be nested is important and will help later when you get into :ref:`namespacing<namespacing>`. - - -functions ---------- - -They're great. Use them: - -.. code-block:: cpp - - sol::state lua; - - lua.script("function f (a, b, c, d) return 1 end"); - lua.script("function g (a, b) return a + b end"); - - // fixed signature std::function<...> - std::function<int(int, double, int, std::string)> stdfx = lua["f"]; - // sol::function is often easier: - // takes a variable number/types of arguments... - sol::function fx = lua["f"]; - - int is_one = stdfx(1, 34.5, 3, "bark"); - int is_also_one = fx(1, "boop", 3, "bark"); - - // call through operator[] - int is_three = lua["g"](1, 2); - // is_three == 3 - double is_4_8 = lua["g"](2.4, 2.4); - // is_4_8 == 4.8 - -If you need to protect against errors and parser problems and you're not ready to deal with Lua's `longjmp` problems (if you compiled with C), use :doc:`sol::protected_function<../api/protected_function>`. - -You can bind member variables as functions too, as well as all KINDS of function-like things: - -.. code-block:: cpp - - void some_function () { - std::cout << "some function!" << std::endl; - } - - void some_other_function () { - std::cout << "some other function!" << std::endl; - } - - struct some_class { - int variable = 30; - - double member_function () { - return 24.5; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - // put an instance of "some_class" into lua - // (we'll go into more detail about this later - // just know here that it works and is - // put into lua as a userdata - lua.set("sc", some_class()); - - // binds a plain function - lua["f1"] = some_function; - lua.set_function("f2", &some_other_function); - - // binds just the member function - lua["m1"] = &some_class::member_function; - - // binds the class to the type - lua.set_function("m2", &some_class::member_function, some_class{}); - - // binds just the member variable as a function - lua["v1"] = &some_class::variable; - - // binds class with member variable as function - lua.set_function("v2", &some_class::variable, some_class{}); - -The lua code to call these things is: - -.. code-block:: lua - - f1() -- some function! - f2() -- some other function! - - -- need class instance if you don't bind it with the function - print(m1(sc)) -- 24.5 - -- does not need class instance: was bound to lua with one - print(m2()) -- 24.5 - - -- need class instance if you - -- don't bind it with the function - print(v1(sc)) -- 30 - -- does not need class instance: - -- it was bound with one - print(v2()) -- 30 - - -- can set, still - -- requires instance - v1(sc, 212) - -- can set, does not need - -- class instance: was bound with one - v2(254) - - print(v1(sc)) -- 212 - print(v2()) -- 254 - -Can use ``sol::readonly( &some_class::variable )`` to make a variable readonly and error if someone tries to write to it. - - -self call ---------- - -You can pass the 'self' argument through C++ to emulate 'member function' calls in Lua. - -.. code-block:: cpp - - sol::state lua; - - lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table); - - // a small script using 'self' syntax - lua.script(R"( - some_table = { some_val = 100 } - - function some_table:add_to_some_val(value) - self.some_val = self.some_val + value - end - - function print_some_val() - print("some_table.some_val = " .. some_table.some_val) - end - )"); - - // do some printing - lua["print_some_val"](); - // 100 - - sol::table self = lua["some_table"]; - self["add_to_some_val"](self, 10); - lua["print_some_val"](); - - - -multiple returns from lua -------------------------- - -.. code-block:: cpp - - sol::state lua; - - lua.script("function f (a, b, c) return a, b, c end"); - - std::tuple<int, int, int> result; - result = lua["f"](100, 200, 300); - // result == { 100, 200, 300 } - int a; - int b; - std::string c; - sol::tie( a, b, c ) = lua["f"](100, 200, "bark"); - // a == 100 - // b == 200 - // c == "bark" - - -multiple returns to lua ------------------------ - -.. code-block:: cpp - - sol::state lua; - - lua["f"] = [](int a, int b, sol::object c) { - // sol::object can be anything here: just pass it through - return std::make_tuple( a, b, c ); - }; - - std::tuple<int, int, int> result = lua["f"](100, 200, 300); - // result == { 100, 200, 300 } - - std::tuple<int, int, std::string> result2; - result2 = lua["f"](100, 200, "BARK BARK BARK!"); - // result2 == { 100, 200, "BARK BARK BARK!" } - - int a, int b; - std::string c; - sol::tie( a, b, c ) = lua["f"](100, 200, "bark"); - // a == 100 - // b == 200 - // c == "bark" - - -C++ classes from C++ --------------------- - -Everything that is not a: - - * primitive type: ``bool``, ``char/short/int/long/long long``, ``float/double`` - * string type: ``std::string``, ``const char*`` - * function type: function pointers, ``lua_CFunction``, ``std::function``, :doc:`sol::function/sol::protected_function<../api/function>`, :doc:`sol::coroutine<../api/coroutine>`, member variable, member function - * designated sol type: :doc:`sol::table<../api/table>`, :doc:`sol::thread<../api/thread>`, :doc:`sol::error<../api/error>`, :doc:`sol::object<../api/object>` - * transparent argument type: :doc:`sol::variadic_arg<../api/variadic_args>`, :doc:`sol::this_state<../api/this_state>` - * usertype<T> class: :doc:`sol::usertype<../api/usertype>` - -Is set as a :doc:`userdata + usertype<../api/usertype>`. - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - Doge dog{}; - - // Copy into lua: destroyed by Lua VM during garbage collection - lua["dog"] = dog; - // OR: move semantics - will call move constructor if present instead - // Again, owned by Lua - lua["dog"] = std::move( dog ); - lua["dog"] = Doge{}; - lua["dog"] = std::make_unique<Doge>(); - lua["dog"] = std::make_shared<Doge>(); - // Identical to above - - Doge dog2{}; - - lua.set("dog", dog2); - lua.set("dog", std::move(dog2)); - lua.set("dog", Doge{}); - lua.set("dog", std::unique_ptr<Doge>(new Doge())); - lua.set("dog", std::shared_ptr<Doge>(new Doge())); - -``std::unique_ptr``/``std::shared_ptr``'s reference counts / deleters will :doc:`be respected<../api/unique_usertype_traits>`. If you want it to refer to something, whose memory you know won't die in C++, do the following: - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - Doge dog{}; // Kept alive somehow - - // Later... - // The following stores a reference, and does not copy/move - // lifetime is same as dog in C++ - // (access after it is destroyed is bad) - lua["dog"] = &dog; - // Same as above: respects std::reference_wrapper - lua["dog"] = std::ref(dog); - // These two are identical to above - lua.set( "dog", &dog ); - lua.set( "dog", std::ref( dog ) ); - -Get userdata in the same way as everything else: - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - Doge& dog = lua["dog"]; // References Lua memory - Doge* dog_pointer = lua["dog"]; // References Lua memory - Doge dog_copy = lua["dog"]; // Copies, will not affect lua - -Note that you can change the data of usertype variables and it will affect things in lua if you get a pointer or a reference from Sol: - -.. code-block:: cpp - - struct Doge { - int tailwag = 50; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - Doge& dog = lua["dog"]; // References Lua memory - Doge* dog_pointer = lua["dog"]; // References Lua memory - Doge dog_copy = lua["dog"]; // Copies, will not affect lua - - dog_copy.tailwag = 525; - // Still 50 - lua.script("assert(dog.tailwag == 50)"); - - dog.tailwag = 100; - // Now 100 - lua.script("assert(dog.tailwag == 100)"); - - -C++ classes put into Lua ------------------------- - -See this :doc:`section here<cxx-in-lua>` and after perhaps see if :doc:`simple usertypes suit your needs<../api/simple_usertype>`. Also check out some `a basic example`_, `special functions`_ and `initializers`_, - - -.. _namespacing: - -namespacing ------------ - -You can emulate namespacing by having a table and giving it the namespace names you want before registering enums or usertypes: - -.. code-block:: cpp - - struct my_class { - int b = 24; - - int f () const { - return 24; - } - - void g () { - ++b; - } - }; - - sol::state lua; - lua.open_libraries(); - - // set up table - sol::table bark = lua.create_named_table("bark"); - - bark.new_usertype<my_class>( "my_class", - "f", &my_class::f, - "g", &my_class::g - ); // the usual - - // 'bark' namespace - lua.script("obj = bark.my_class.new()" ); - lua.script("obj:g()"); - my_class& obj = lua["obj"]; - // obj.b == 25 - - -This technique can be used to register namespace-like functions and classes. It can be as deep as you want. Just make a table and name it appropriately, in either Lua script or using the equivalent Sol code. As long as the table FIRST exists (e.g., make it using a script or with one of Sol's methods or whatever you like), you can put anything you want specifically into that table using :doc:`sol::table's<../api/table>` abstractions. - -advanced --------- - -Some more advanced things you can do/read about: - * :doc:`metatable manipulations<../api/metatable_key>` allow a user to change how indexing, function calls, and other things work on a single type. - * :doc:`ownership semantics<ownership>` are described for how lua deals with (raw) pointers. - * :doc:`stack manipulation<../api/stack>` to safely play with the stack. You can also define customization points for ``stack::get``/``stack::check``/``stack::push`` for your type. - * :doc:`make_reference/make_object convenience function<../api/make_reference>` to get the same benefits and conveniences as the low-level stack API but put into objects you can specify. - * :doc:`stack references<../api/stack_reference>` to have zero-overhead Sol abstractions while not copying to the Lua registry. - * :doc:`unique usertype traits<../api/unique_usertype_traits>` allows you to specialize handle/RAII types from other frameworks, like boost, and Unreal, to work with Sol. - * :doc:`variadic arguments<../api/variadic_args>` in functions with ``sol::variadic_args``. - * :doc:`this_state<../api/this_state>` to get the current ``lua_State*``. - * :doc:`resolve<../api/resolve>` overloads in case you have overloaded functions; a cleaner casting utility. - -.. _a basic example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype.cpp -.. _special functions: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_special_functions.cpp -.. _initializers: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_initializers.cpp - diff --git a/3rdparty/sol2/docs/source/tutorial/customization.rst b/3rdparty/sol2/docs/source/tutorial/customization.rst deleted file mode 100644 index 5479c804115..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/customization.rst +++ /dev/null @@ -1,117 +0,0 @@ -adding your own types -===================== - -Sometimes, overriding Sol to make it handle certain ``struct``'s and ``class``'es as something other than just userdata is desirable. The way to do this is to take advantage of the 4 customization points for Sol. These are ``sol::lua_size<T>``, ``sol::stack::pusher<T, C>``, ``sol::stack::getter<T, C>``, ``sol::stack::checker<T, sol::type t, C>``. - -These are template class/structs, so you'll override them using a technique C++ calls *class/struct specialization*. Below is an example of a struct that gets broken apart into 2 pieces when going in the C++ --> Lua direction, and then pulled back into a struct when going in the Lua --> C++: - -.. code-block:: cpp - :caption: two_things.hpp - :name: customization-overriding - - #include <sol.hpp> - - struct two_things { - int a; - bool b; - }; - - namespace sol { - - // First, the expected size - // Specialization of a struct - // We expect 2, so use 2 - template <> - struct lua_size<two_things> : std::integral_constant<int, 2> {}; - - // Now, specialize various stack structures - namespace stack { - - template <> - struct checker<two_things> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - // indices can be negative to count backwards from the top of the stack, - // rather than the bottom up - // to deal with this, we adjust the index to - // its absolute position using the lua_absindex function - int absolute_index = lua_absindex(L, index); - // Check first and second second index for being the proper types - bool success = stack::check<int>(L, absolute_index - 1, handler) - && stack::check<bool>(L, absolute_index, handler); - tracking.use(2); - return success; - } - }; - - template <> - struct getter<two_things> { - static two_things get(lua_State* L, int index, record& tracking) { - int absolute_index = lua_absindex(L, index); - // Get the first element - int a = stack::get<int>(L, absolute_index - 1); - // Get the second element, - // in the +1 position from the first - bool b = stack::get<bool>(L, absolute_index); - // we use 2 slots, each of the previous takes 1 - tracking.use(2); - return two_things{ a, b }; - } - }; - - template <> - struct pusher<two_things> { - static int push(lua_State* L, const two_things& things) { - int amount = stack::push(L, things.a); - // amount will be 1: int pushes 1 item - amount += stack::push(L, things.b); - // amount 2 now, since bool pushes a single item - // Return 2 things - return amount; - } - }; - - } - } - - -This is the base formula that you can follow to extend to your own classes. Using it in the rest of the library should then be seamless: - -.. code-block:: cpp - :caption: customization: using it - :name: customization-using - - #include <sol.hpp> - #include <two_things.hpp> - - int main () { - - sol::state lua; - - // Create a pass-through style of function - lua.script("function f ( a, b ) return a, b end"); - - // get the function out of Lua - sol::function f = lua["f"]; - - two_things things = f(two_things{24, true}); - // things.a == 24 - // things.b == true - - return 0; - } - - -And that's it! - -A few things of note about the implementation: First, there's an auxiliary parameter of type :doc:`sol::stack::record<../api/stack>` for the getters and checkers. This keeps track of what the last complete operation performed. Since we retrieved 2 members, we use ``tracking.use(2);`` to indicate that we used 2 stack positions (one for ``bool``, one for ``int``). The second thing to note here is that we made sure to use the ``index`` parameter, and then proceeded to add 1 to it for the next one. - -You can make something pushable into Lua, but not get-able in the same way if you only specialize one part of the system. If you need to retrieve it (as a return using one or multiple values from Lua), you should specialize the ``sol::stack::getter`` template class and the ``sol::stack::checker`` template class. If you need to push it into Lua at some point, then you'll want to specialize the ``sol::stack::pusher`` template class. The ``sol::lua_size`` template class trait needs to be specialized for both cases, unless it only pushes 1 item, in which case the default implementation will assume 1. - -.. note:: - - It is important to note here that the ``getter``, ``pusher`` and ``checker`` differentiate between a type ``T`` and a pointer to a type ``T*``. This means that if you want to work purely with, say, a ``T*`` handle that does not have the same semantics as just ``T``, you may need to specify checkers/getters/pushers for both ``T*`` and ``T``. The checkers for ``T*`` forward to the checkers for ``T``, but the getter for ``T*`` does not forward to the getter for ``T`` (e.g., because of ``int*`` not being quite the same as ``int``). - -In general, this is fine since most getters/checkers only use 1 stack point. But, if you're doing more complex nested classes, it would be useful to use ``tracking.last`` to understand how many stack indices the last getter/checker operation did and increment it by ``index + tracking.last`` after using a ``stack::check<..>( L, index, tracking)`` call. - -You can read more about the structs themselves :ref:`over on the API page for stack<extension_points>`, and if there's something that goes wrong or you have anymore questions, please feel free to drop a line on the Github Issues page or send an e-mail!
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst b/3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst deleted file mode 100644 index dac47dfb228..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst +++ /dev/null @@ -1,138 +0,0 @@ -C++ in Lua -========== - -Using user defined types ("usertype"s, or just "udt"s) is simple with Sol. If you don't call any member variables or functions, then you don't even have to 'register' the usertype at all: just pass it through. But if you want variables and functions on your usertype inside of Lua, you need to register it. We're going to give a short example here that includes a bunch of information on how to work with things. - -Take this ``player`` struct in C++ in a header file: - -.. code-block:: cpp - :caption: test_player.hpp - - struct player { - public: - int bullets; - int speed; - - player() - : player(3, 100) { - - } - - player(int ammo) - : player(ammo, 100) { - - } - - player(int ammo, int hitpoints) - : bullets(ammo), hp(hitpoints) { - - } - - void boost () { - speed += 10; - } - - bool shoot () { - if (bullets < 1) - return false; - --bullets; - return true; - } - - void set_hp(int value) { - hp = value; - } - - int get_hp() const { - return hp; - } - - private: - int hp; - }; - - -It's a fairly minimal class, but we don't want to have to rewrite this with metatables in Lua. We want this to be part of Lua easily. The following is the Lua code that we'd like to have work properly: - -.. code-block:: lua - :caption: player_script.lua - - -- call single argument integer constructor - p1 = player.new(2) - - -- p2 is still here from being - -- set with lua["p2"] = player(0); - -- in cpp file - local p2shoots = p2:shoot() - assert(not p2shoots) - -- had 0 ammo - - -- set variable property setter - p1.hp = 545; - -- get variable through property getter - print(p1.hp); - - local did_shoot_1 = p1:shoot() - print(did_shoot_1) - print(p1.bullets) - local did_shoot_2 = p1:shoot() - print(did_shoot_2) - print(p1.bullets) - local did_shoot_3 = p1:shoot() - print(did_shoot_3) - - -- can read - print(p1.bullets) - -- would error: is a readonly variable, cannot write - -- p1.bullets = 20 - - p1:boost() - -To do this, you bind things using the ``new_usertype`` and ``set_usertype`` methods as shown below. These methods are on both :doc:`table<../api/table>` and :doc:`state(_view)<../api/state>`, but we're going to just use it on ``state``: - -.. code-block:: cpp - :caption: player_script.cpp - - #include <sol.hpp> - - int main () { - sol::state lua; - - // note that you can set a - // userdata before you register a usertype, - // and it will still carry - // the right metatable if you register it later - - // set a variable "p2" of type "player" with 0 ammo - lua["p2"] = player(0); - - // make usertype metatable - lua.new_usertype<player>( "player", - - // 3 constructors - sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>>(), - - // typical member function that returns a variable - "shoot", &player::shoot, - // typical member function - "boost", &player::boost, - - // gets or set the value using member variable syntax - "hp", sol::property(&player::get_hp, &player::set_hp), - - // read and write variable - "speed", &player::speed, - // can only read from, not write to - "bullets", sol::readonly( &player::bullets ) - ); - - lua.script_file("player_script.lua"); - } - -That script should run fine now, and you can observe and play around with the values. Even more stuff :doc:`you can do<../api/usertype>` is described elsewhere, like initializer functions (private constructors / destructors support), "static" functions callable with ``name.my_function( ... )``, and overloaded member functions. You can even bind global variables (even by reference with ``std::ref``) with ``sol::var``. There's a lot to try out! - -This is a powerful way to allow reuse of C++ code from Lua beyond just registering functions, and should get you on your way to having more complex classes and data structures! In the case that you need more customization than just usertypes, however, you can customize Sol to behave more fit to your desires by using the desired :doc:`customization and extension structures<customization>`. - -You can check out this code and more complicated code at the `examples directory`_ by looking at the ``usertype_``-prefixed examples. - -.. _examples directory: https://github.com/ThePhD/sol2/tree/develop/examples
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/existing.rst b/3rdparty/sol2/docs/source/tutorial/existing.rst deleted file mode 100644 index 89a83f8078d..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/existing.rst +++ /dev/null @@ -1,27 +0,0 @@ -integrating into existing code -============================== - -If you're already using lua and you just want to use ``sol`` in some places, you can use ``state_view``: - -.. code-block:: cpp - :linenos: - :caption: using state_view - :name: state-view-snippet - - void something_in_my_system (lua_State* L) { - // start using Sol with a pre-existing system - sol::state_view lua(L); // non-owning - - lua.script("print('bark bark bark!')"); - - sol::table expected_table(L); // get the table off the top of the stack - // start using it... - } - -:doc:`sol::state_view<../api/state>` is exactly like ``sol::state``, but it doesn't manage the lifetime of a ``lua_State*``. Therefore, you get all the goodies that come with a ``sol::state`` without any of the ownership implications. Sol has no initialization components that need to deliberately remain alive for the duration of the program. It's entirely self-containing and uses lua's garbage collectors and various implementation techniques to require no state C++-side. After you do that, all of the power of `Sol` is available to you, and then some! - -You may also want to call ``require`` and supply a string of a script file or something that returns an object that you set equal to something in C++. For that, you can use the :ref:`require functionality<state-require-function>`. - -Remember that Sol can be as lightweight as you want it: almost all of Sol's types take the ``lua_State*`` argument and then a second ``int index`` stack index argument, meaning you can use :doc:`tables<../api/table>`, :doc:`lua functions<../api/function>`, :doc:`coroutines<../api/coroutine>`, and other reference-derived objects that expose the proper constructor for your use. You can also set :doc:`usertypes<../api/usertype>` and other things you need without changing your entire architecture. - -Note that you can also make non-standard pointer and reference types with custom reference counting and such also play nice with the system. See :doc:`unique_usertype_traits\<T><../api/unique_usertype_traits>` to see how! Custom types is also mentioned in the :doc:`customization tutorial<customization>`.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/functions.rst b/3rdparty/sol2/docs/source/tutorial/functions.rst deleted file mode 100644 index 5fa8d823fd3..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/functions.rst +++ /dev/null @@ -1,341 +0,0 @@ -functions and You -================= - -Sol can register all kinds of functions. Many are shown in the :doc:`quick 'n' dirty<all-the-things>`, but here we will discuss many of the additional ways you can register functions into a sol-wrapped Lua system. - -Setting a new function ----------------------- - -Given a C++ function, you can drop it into Sol in several equivalent ways, working similar to how :ref:`setting variables<writing-main-cpp>` works: - -.. code-block:: cpp - :linenos: - :caption: Registering C++ functions - :name: writing-functions - - #include <sol.hpp> - - std::string my_function( int a, std::string b ) { - // Create a string with the letter 'D' "a" times, - // append it to 'b' - return b + std::string( 'D', a ); - } - - int main () { - - sol::state lua; - - lua["my_func"] = my_function; // way 1 - lua.set("my_func", my_function); // way 2 - lua.set_function("my_func", my_function); // way 3 - - // This function is now accessible as 'my_func' in - // lua scripts / code run on this state: - lua.script("some_str = my_func(1, "Da"); - - // Read out the global variable we stored in 'some_str' in the - // quick lua code we just executed - std::string some_str = lua["some_str"]; - // some_str == "DaD" - } - -The same code works with all sorts of functions, from member function/variable pointers you have on a class as well as lambdas: - -.. code-block:: cpp - :linenos: - :caption: Registering C++ member functions - :name: writing-member-functions - - struct my_class { - int a = 0; - - my_class(int x) : a(x) { - - } - - int func() { - ++a; // increment a by 1 - return a; - } - }; - - int main () { - - sol::state lua; - - // Here, we are binding the member function and a class instance: it will call the function on - // the given class instance - lua.set_function("my_class_func", &my_class::func, my_class()); - - // We do not pass a class instance here: - // the function will need you to pass an instance of "my_class" to it - // in lua to work, as shown below - lua.set_function("my_class_func_2", &my_class::func); - - // With a pre-bound instance: - lua.script(R"( - first_value = my_class_func() - second_value = my_class_func() - )"); - // first_value == 1 - // second_value == 2 - - // With no bound instance: - lua.set("obj", my_class(24)); - // Calls "func" on the class instance - // referenced by "obj" in Lua - lua.script(R"( - third_value = my_class_func_2(obj) - fourth_value = my_class_func_2(obj) - )"); - // first_value == 25 - // second_value == 26 - } - -Member class functions and member class variables will both be turned into functions when set in this manner. You can get intuitive variable with the ``obj.a = value`` access after this section when you learn about :doc:`usertypes to have C++ in Lua<cxx-in-lua>`, but for now we're just dealing with functions! - - -Another question a lot of people have is about function templates. Function templates -- member functions or free functions -- cannot be registered because they do not exist until you instantiate them in C++. Therefore, given a templated function such as: - -.. code-block:: cpp - :linenos: - :caption: A C++ templated function - :name: writing-templated-functions-the-func - - template <typename A, typename B> - auto my_add( A a, B b ) { - return a + b; - } - - -You must specify all the template arguments in order to bind and use it, like so: - -.. code-block:: cpp - :linenos: - :caption: Registering function template instantiations - :name: writing-templated-functions - - - int main () { - - sol::state lua; - - // adds 2 integers - lua["my_int_add"] = my_add<int, int>; - - // concatenates 2 strings - lua["my_string_combine"] = my_add<std::string, std::string>; - - lua.script("my_num = my_int_add(1, 2)"); - int my_num = lua["my_num"]; - // my_num == 3 - - lua.script("my_str = my_string_combine('bark bark', ' woof woof')"); - std::string my_str = lua["my_str"]; - // my_str == "bark bark woof woof" - } - -Notice here that we bind two separate functions. What if we wanted to bind only one function, but have it behave differently based on what arguments it is called with? This is called Overloading, and it can be done with :doc:`sol::overload<../api/overload>` like so: - -.. code-block:: cpp - :linenos: - :caption: Registering C++ function template instantiations - :name: writing-templated-functions-overloaded - - - int main () { - - sol::state lua; - - // adds 2 integers - lua["my_combine"] = sol::overload( my_add<int, int>, my_add<std::string, std::string> ); - - lua.script("my_num = my_combine(1, 2)"); - lua.script("my_str = my_combine('bark bark', ' woof woof')"); - int my_num = lua["my_num"]; - std::string my_str = lua["my_str"]; - // my_num == 3 - // my_str == "bark bark woof woof" - } - -This is useful for functions which can take multiple types and need to behave differently based on those types. You can set as many overloads as you want, and they can be of many different types. - -.. note:: - - Function object ``obj`` -- a struct with a ``return_type operator()( ... )`` member defined on them, like all C++ lambdas -- are not interpreted as functions when you use ``set`` for ``mytable.set( key, value )``. This only happens automagically with ``mytable[key] = obj``. To be explicit about wanting a struct to be interpreted as a function, use ``mytable.set_function( key, func_value );``. You can be explicit about wanting a function as well by using the :doc:`sol::as_function<../api/as_function>` call. - - -Getting a function from Lua ---------------------------- - -There are 2 ways to get a function from Lua. One is with :doc:`sol::function<../api/function>` and the other is a more advanced wrapper with :doc:`sol::protected_function<../api/protected_function>`. Use them to retrieve callables from Lua and call the underlying function, in two ways: - -.. code-block:: cpp - :linenos: - :caption: Retrieving a sol::function - :name: reading-functions - - int main () { - - sol::state lua; - - lua.script(R"( - function f (a) - return a + 5 - end - )"); - - // Get and immediately call - int x = lua["f"](30); - // x == 35 - - // Store it into a variable first, then call - sol::function f = lua["f"]; - int y = f(20); - // y == 25 - } - -You can get anything that's a callable in Lua, including C++ functions you bind using ``set_function`` or similar. ``sol::protected_function`` behaves similarly to ``sol::function``, but has a :ref:`error_handler<protected-function-error-handler>` variable you can set to a Lua function. This catches all errors and runs them through the error-handling function: - - -.. code-block:: cpp - :linenos: - :caption: Retrieving a sol::protected_function - :name: reading-protected-functions - - int main () { - sol::state lua; - - lua.script(R"( - function handler (message) - return "Handled this message: " .. message - end - - function f (a) - if a < 0 then - error("negative number detected") - end - return a + 5 - end - )"); - - sol::protected_function f = lua["f"]; - f.error_handler = lua["handler"]; - - sol::protected_function_result result = f(-500); - if (result.valid()) { - // Call succeeded - int x = result; - } - else { - // Call failed - sol::error err = result; - std::string what = err.what(); - // 'what' Should read - // "Handled this message: negative number detected" - } - } - - -Multiple returns to and from Lua --------------------------------- - -You can return multiple items to and from Lua using ``std::tuple``/``std::pair`` classes provided by C++. These enable you to also use :doc:`sol::tie<../api/tie>` to set return values into pre-declared items. To recieve multiple returns, just ask for a ``std::tuple`` type from the result of a function's computation, or ``sol::tie`` a bunch of pre-declared variables together and set the result equal to that: - -.. code-block:: cpp - :linenos: - :caption: Multiple returns from Lua - :name: multi-return-lua-functions - - int main () { - sol::state lua; - - lua.script("function f (a, b, c) return a, b, c end"); - - std::tuple<int, int, int> result; - result = lua["f"](1, 2, 3); - // result == { 1, 2, 3 } - int a, int b; - std::string c; - sol::tie( a, b, c ) = lua["f"](1, 2, "bark"); - // a == 1 - // b == 2 - // c == "bark" - } - -You can also return mutiple items yourself from a C++-bound function. Here, we're going to bind a C++ lambda into Lua, and then call it through Lua and get a ``std::tuple`` out on the other side: - -.. code-block:: cpp - :linenos: - :caption: Multiple returns into Lua - :name: multi-return-cxx-functions - - int main () { - sol::state lua; - - lua["f"] = [](int a, int b, sol::object c) { - // sol::object can be anything here: just pass it through - return std::make_tuple( a, b, c ); - }; - - std::tuple<int, int, int> result = lua["f"](1, 2, 3); - // result == { 1, 2, 3 } - - std::tuple<int, int, std::string> result2; - result2 = lua["f"](1, 2, "Arf?") - // result2 == { 1, 2, "Arf?" } - - int a, int b; - std::string c; - sol::tie( a, b, c ) = lua["f"](1, 2, "meow"); - // a == 1 - // b == 2 - // c == "meow" - } - - -Note here that we use :doc:`sol::object<../api/object>` to transport through "any value" that can come from Lua. You can also use ``sol::make_object`` to create an object from some value, so that it can be returned into Lua as well. - - -Any return to and from Lua --------------------------- - -It was hinted at in the previous code example, but ``sol::object`` is a good way to pass "any type" back into Lua (while we all wait for ``std::variant<...>`` to get implemented and shipped by C++ compiler/library implementers). - -It can be used like so, inconjunction with ``sol::this_state``: - -.. code-block:: cpp - :linenos: - :caption: Return anything into Lua - :name: object-return-cxx-functions - - sol::object fancy_func (sol::object a, sol::object b, sol::this_state s) { - sol::state_view lua(s); - if (a.is<int>() && b.is<int>()) { - return sol::make_object(lua, a.as<int>() + b.as<int>()); - } - else if (a.is<bool>()) { - bool do_triple = a.as<bool>(); - return sol::make_object(lua, b.as<double>() * ( do_triple ? 3 : 1 ) ); - } - return sol::make_object(lua, sol::nil); - } - - int main () { - sol::state lua; - - lua["f"] = fancy_func; - - int result = lua["f"](1, 2); - // result == 3 - double result2 = lua["f"](false, 2.5); - // result2 == 2.5 - - // call in Lua, get result - lua.script("result3 = f(true, 5.5)"); - double result3 = lua["result3"]; - // result3 == 16.5 - } - - -This covers almost everything you need to know about Functions and how they interact with Sol. For some advanced tricks and neat things, check out :doc:`sol::this_state<../api/this_state>` and :doc:`sol::variadic_args<../api/variadic_args>`. The next stop in this tutorial is about :doc:`C++ types (usertypes) in Lua<cxx-in-lua>`! If you need a bit more information about functions in the C++ side and how to best utilize arguments from C++, see :ref:`this note<function-argument-handling>`.
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/getting-started.rst b/3rdparty/sol2/docs/source/tutorial/getting-started.rst deleted file mode 100644 index 02fc2daadf0..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/getting-started.rst +++ /dev/null @@ -1,79 +0,0 @@ -getting started -=============== - -Let's get you going with Sol! To start, you'll need to use a lua distribution of some sort. Sol doesn't provide that: it only wraps the API that comes with it, so you can pick whatever distribution you like for your application. There are lots, but the two popular ones are `vanilla Lua`_ and speedy `LuaJIT`_ . We recommend vanilla Lua if you're getting started, LuaJIT if you need speed and can handle some caveats: the interface for Sol doesn't change no matter what Lua version you're using. - -If you need help getting or building Lua, check out the `Lua page on getting started`_. Note that for Visual Studio, one can simply download the sources, include all the Lua library files in that project, and then build for debug/release, x86/x64/ARM rather easily and with minimal interference. Just make sure to adjust the Project Property page to build as a static library (or a DLL with the proper define set in the ``Preprocessor`` step). - -After that, make sure you grab either the `single header file release`_, or just perform a clone of the `github repository here`_ and set your include paths up so that you can get at ``sol.hpp`` somehow. Note that we also have the latest version of the single header file with all dependencies included kept in the `repository as well`_. We recommend the single-header-file release, since it's easier to move around, manage and update if you commit it with some form of version control. You can also clone/submodule the repository and then point at the `single/sol/sol.hpp`_ on your include files path. Clone with: - ->>> git clone https://github.com/ThePhD/sol2.git - -When you're ready, try compiling this short snippet: - -.. code-block:: cpp - :linenos: - :caption: test.cpp: the first snippet - :name: the-first-snippet - - #include <sol.hpp> // or #include "sol.hpp", whichever suits your needs - - int main (int argc, char* argv[]) { - - sol::state lua; - lua.open_libraries( sol::lib::base ); - - lua.script( "print('bark bark bark!')" ); - - return 0; - } - -Using this simple command line: - ->>> g++ -std=c++14 test.cpp -I"path/to/lua/include" -L"path/to/lua/lib" -llua - -Or using your favorite IDE / tool after setting up your include paths and library paths to Lua according to the documentation of the Lua distribution you got. Remember your linked lua library (``-llua``) and include / library paths will depend on your OS, file system, Lua distribution and your installation / compilation method of your Lua distribution. - -.. note:: - - If you get an avalanche of errors (particularly referring to ``auto``), you may not have enabled C++14 / C++17 mode for your compiler. Add one of ``std=c++14``, ``std=c++1z`` OR ``std=c++1y`` to your compiler options. By default, this is always-on for VC++ compilers in Visual Studio and friends, but g++ and clang++ require a flag (unless you're on `GCC 6.0`_). - -If this works, you're ready to start! The first line creates the ``lua_State`` and will hold onto it for the duration of the scope its declared in (e.g., from the opening ``{`` to the closing ``}``). It will automatically close / cleanup that lua state when it gets destructed. The second line opens a single lua-provided library, "base". There are several other libraries that come with lua that you can open by default, and those are included in the :ref:`sol::lib<lib-enum>` enumeration. You can open multiple base libraries by specifying multiple ``sol::lib`` arguments: - -.. code-block:: cpp - :linenos: - :caption: test.cpp: the first snippet - :name: the-second-snippet - - #include <sol.hpp> - - int main (int argc, char* argv[]) { - - sol::state lua; - lua.open_libraries( sol::lib::base, sol::lib::coroutine, sol::lib::string, sol::lib::io ); - - lua.script( "print('bark bark bark!')" ); - - return 0; - } - -If you're interested in integrating Sol with a project that already uses some other library or Lua in the codebase, check out the :doc:`existing example<existing>` to see how to work with Sol when you add it to a project (the existing example covers ``require`` as well)! - -Next, let's start :doc:`reading/writing some variables<variables>` from Lua into C++, and vice-versa! - - -.. _vanilla Lua: https://www.lua.org/ - -.. _LuaJIT: http://luajit.org/ - -.. _GCC 6.0: https://gcc.gnu.org/gcc-6/changes.html - -.. _single header file release: https://github.com/ThePhD/sol2/releases - -.. _repository as well: https://github.com/ThePhD/sol2/blob/develop/single/sol/sol.hpp - -.. _single/sol/sol.hpp: https://github.com/ThePhD/sol2/blob/develop/single/sol/sol.hpp - -.. _github repository here: https://github.com/ThePhD/sol2 - -.. _Lua page on getting started: https://www.lua.org/start.html
\ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/ownership.rst b/3rdparty/sol2/docs/source/tutorial/ownership.rst deleted file mode 100644 index 96eb350da78..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/ownership.rst +++ /dev/null @@ -1,94 +0,0 @@ -ownership -========= - -Sol will not take ownership of raw pointers: raw pointers do not own anything. - -.. code-block:: cpp - - struct my_type { - void stuff () {} - }; - - sol::state lua; - - // AAAHHH BAD - // dangling pointer! - lua["my_func"] = []() -> my_type* { - return new my_type(); - }; - - // AAAHHH! - lua.set("something", new my_type()); - - // AAAAAAHHH!!! - lua["something_else"] = new my_type(); - -Use/return a ``unique_ptr`` or ``shared_ptr`` instead or just return a value: - -.. code-block:: cpp - - // :ok: - lua["my_func"] = []() -> std::unique_ptr<my_type> { - return std::make_unique<my_type>(); - }; - - // :ok: - lua["my_func"] = []() -> std::shared_ptr<my_type> { - return std::make_shared<my_type>(); - }; - - // :ok: - lua["my_func"] = []() -> my_type { - return my_type(); - }; - - // :ok: - lua.set("something", std::unique_ptr<my_type>(new my_type())); - - std::shared_ptr<my_type> my_shared = std::make_shared<my_type>(); - // :ok: - lua.set("something_else", my_shared); - - auto my_unique = std::make_unique<my_type>(); - lua["other_thing"] = std::move(my_unique); - -If you have something you know is going to last and you just want to give it to Lua as a reference, then it's fine too: - -.. code-block:: cpp - - // :ok: - lua["my_func"] = []() -> my_type* { - static my_type mt; - return &mt; - }; - - -Sol can detect ``nullptr``, so if you happen to return it there won't be any dangling because a ``sol::nil`` will be pushed. - -.. code-block:: cpp - - struct my_type { - void stuff () {} - }; - - sol::state lua; - - // BUT THIS IS STILL BAD DON'T DO IT AAAHHH BAD - // return a unique_ptr still or something! - lua["my_func"] = []() -> my_type* { - return nullptr; - }; - - lua["my_func_2"] = [] () -> std::unique_ptr<my_type> { - // default-constructs as a nullptr, - // gets pushed as nil to Lua - return std::unique_ptr<my_type>(); - // same happens for std::shared_ptr - } - - // Acceptable, it will set 'something' to nil - // (and delete it on next GC if there's no more references) - lua.set("something", nullptr); - - // Also fine - lua["something_else"] = nullptr; diff --git a/3rdparty/sol2/docs/source/tutorial/tutorial-top.rst b/3rdparty/sol2/docs/source/tutorial/tutorial-top.rst deleted file mode 100644 index 730423fdb5a..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/tutorial-top.rst +++ /dev/null @@ -1,21 +0,0 @@ -tutorial -======== - -Take some time to learn the framework with thse tutorials. But, if you need to get going FAST, try using the :doc:`quick 'n' dirty<all-the-things>` approach and your browser's / editors search function. It will also serve you well to look at all the `examples`_, which have recently gotten a bit of an overhaul to contain more relevant working examples. - - -.. toctree:: - :caption: Sol Tutorial - :name: tutorialtoc - :maxdepth: 2 - - all-the-things - getting-started - existing - variables - functions - cxx-in-lua - ownership - customization - -.. _examples: https://github.com/ThePhD/sol2/tree/develop/examples diff --git a/3rdparty/sol2/docs/source/tutorial/variables.rst b/3rdparty/sol2/docs/source/tutorial/variables.rst deleted file mode 100644 index a911fcefdb4..00000000000 --- a/3rdparty/sol2/docs/source/tutorial/variables.rst +++ /dev/null @@ -1,202 +0,0 @@ -variables -========= - -Working with variables is easy with Sol, and behaves pretty much like any associative array / map structure you've dealt with previously. Given this lua file that gets loaded into Sol: - -reading -------- - -.. code-block:: lua - :caption: variables.lua - - config = { - fullscreen = false, - resolution = { x = 1024, y = 768 } - } - -.. code-block:: cpp - :caption: main.cpp - :name: variables-main-cpp - - #include <sol.hpp> - - int main () { - - sol::state lua; - lua.script_file( variables.lua ); - - return 0; - } - -You can interact with the variables like this: - -.. code-block:: cpp - :caption: main.cpp extended - :name: extended-variables-main-cpp - - #include <sol.hpp> - #include <tuple> - #include <utility> // for std::pair - - int main () { - - sol::state lua; - lua.script_file( variables.lua ); - - // the type "state" behaves exactly like a table! - bool isfullscreen = lua["config"]["fullscreen"]; // can get nested variables - sol::table config = lua["config"]; - - // can also get it using the "get" member function - // auto replaces the unqualified type name - auto resolution = config.get<sol::table>( "config" ); - - // table and state can have multiple things pulled out of it too - std::pair<int, int> xyresolution = resolution.get<int, int>( "x", "y" ); - // As an example, you can also pull out a tuple as well - std::tuple<int, int> xyresolutiontuple = resolution.get<int, int>( "x", "y" ); - - - return 0; - } - -From this example, you can see that there's many ways to pull out the varaibles you want. For example, to determine if a nested variable exists or not, you can use ``auto`` to capture the value of a ``table[key]`` lookup, and then use the ``.valid()`` method: - -.. code-block:: cpp - :caption: safe lookup - - auto bark = lua["config"]["bark"]; - if (bark.valid()) { - // branch not taken: config / bark is not a variable - } - else { - // Branch taken: config is a not a variable - } - -This comes in handy when you want to check if a nested variable exists. You can also check if a toplevel variable is present or not by using ``sol::optional``, which also checks if A) the keys you're going into exist and B) the type you're trying to get is of a specific type: - -.. code-block:: cpp - :caption: optional lookup - - sol::optional<int> not_an_integer = lua["config"]["fullscreen"]; - if (not_an_integer) { - // Branch not taken: value is not an integer - } - - sol::optional<bool> is_a_boolean = lua["config"]["fullscreen"]; - if (is_a_boolean) { - // Branch taken: the value is a boolean - } - - sol::optional<double> does_not_exist = lua["not_a_variable"]; - if (does_not_exist) { - // Branch not taken: that variable is not present - } - -This can come in handy when, even in optimized or release modes, you still want the safety of checking. You can also use the `get_or` methods to, if a certain value may be present but you just want to default the value to something else: - -.. code-block:: cpp - :caption: get_or lookup - - // this will result in a value of '24' - int is_defaulted = lua["config"]["fullscreen"].get_or( 24 ); - - // This will result in the value of the config, which is 'false' - bool is_not_defaulted = lua["config"]["fullscreen"]; - -That's all it takes to read variables! - - -writing -------- - -Writing gets a lot simpler. Even without scripting a file or a string, you can read and write variables into lua as you please: - -.. code-block:: cpp - :caption: main.cpp - :name: writing-main-cpp - - #include <sol.hpp> - #include <iostream> - - int main () { - - sol::state lua; - - // open those basic lua libraries again, like print() etc. - lua.open_libraries( sol::lib::base ); - - // value in the global table - lua["bark"] = 50; - - // a table being created in the global table - lua["some_table"] = lua.create_table_with( - "key0", 24, - "key1", 25, - lua["bark"], "the key is 50 and this string is its value!" - ); - - // Run a plain ol' string of lua code - // Note you can interact with things set through Sol in C++ with lua! - // Using a "Raw String Literal" to have multi-line goodness: http://en.cppreference.com/w/cpp/language/string_literal - lua.script(R"( - - print(some_table[50]) - print(some_table["key0"]) - print(some_table["key1"]) - - -- a lua comment: access a global in a lua script with the _G table - print(_G["bark"]) - - )"); - - return 0; - } - -This example pretty much sums up what can be done. Note that the syntax ``lua["non_existing_key_1"] = 1`` will make that variable, but if you tunnel too deep without first creating a table, the Lua API will panic (e.g., ``lua["does_not_exist"]["b"] = 20`` will trigger a panic). You can also be lazy with reading / writing values: - -.. code-block:: cpp - :caption: main.cpp - :name: lazy-main-cpp - - #include <sol.hpp> - #include <iostream> - - int main () { - - sol::state lua; - - auto barkkey = lua["bark"]; - if (barkkey.valid()) { - // Branch not taken: doesn't exist yet - std::cout << "How did you get in here, arf?!" << std::endl; - } - - barkkey = 50; - if (barkkey.valid()) { - // Branch taken: value exists! - std::cout << "Bark Bjork Wan Wan Wan" << std::endl; - } - } - -Finally, it's possible to erase a reference/variable by setting it to ``nil``, using the constant ``sol::nil`` in C++: - -.. code-block:: cpp - :caption: main.cpp - :name: erase-main-cpp - - #include <sol.hpp> - - int main () { - - sol::state lua; - lua["bark"] = 50; - sol::optional<int> x = lua["bark"]; - // x will have a value - - lua["bark"] = sol::nil; - sol::optional<int> y = lua["bark"]; - // y will not have a value - } - -It's easy to see that there's a lot of options to do what you want here. But, these are just traditional numbers and strings. What if we want more power, more capabilities than what these limited types can offer us? Let's throw some :doc:`functions in there<functions>` :doc:`C++ classes into the mix<cxx-in-lua>`! diff --git a/3rdparty/sol2/docs/source/usertypes.rst b/3rdparty/sol2/docs/source/usertypes.rst deleted file mode 100644 index 081be5ed6eb..00000000000 --- a/3rdparty/sol2/docs/source/usertypes.rst +++ /dev/null @@ -1,29 +0,0 @@ -usertypes -========= - -Perhaps the most powerful feature of sol2, ``usertypes`` are the way sol2 and C++ communicate your classes to the Lua runtime and bind things between both tables and to specific blocks of C++ memory, allowing you to treat Lua userdata and other things like classes. - -To learn more about usertypes, visit: - -* :doc:`the basic tutorial<tutorial/cxx-in-lua>` -* :doc:`customization point tutorial<tutorial/customization>` -* :doc:`api documentation<api/usertype>` -* :doc:`memory documentation<api/usertype_memory>` - -The examples folder also has a number of really great examples for you to see. There are also some notes about guarantees you can find about usertypes, and their associated userdata, below: - -* You can push types classified as userdata before you register a usertype. - - You can register a usertype with the Lua runtime at any time sol2 - - You can retrieve them from the Lua runtime as well through sol2 - - Methods and properties will be added to the type only after you register it in the Lua runtime -* Types either copy once or move once into the memory location, if it is a value type. If it is a pointer, we store only the reference. - - This means take arguments of class types (not primitive types like strings or integers) by ``T&`` or ``T*`` to modify the data in Lua directly, or by plain ``T`` to get a copy - - Return types and passing arguments to ``sol::function`` use perfect forwarding and reference semantics, which means no copies happen unless you specify a value explicitly. See :ref:`this note for details<function-argument-handling>`. -* The first ``sizeof( void* )`` bytes is always a pointer to the typed C++ memory. What comes after is based on what you've pushed into the system according to :doc:`the memory specification for usertypes<api/usertype_memory>`. This is compatible with a number of systems. -* Member methods, properties, variables and functions taking ``self&`` arguments modify data directly - - Work on a copy by taking or returning a copy by value. -* The actual metatable associated with the usertype has a long name and is defined to be opaque by the Sol implementation. -* Containers get pushed as special usertypes, but can be disabled if problems arising as detailed :doc:`here<api/containers>`. -* You can use bitfields but it requires some finesse on your part. We have an example to help you get started `here that uses a few tricks`_. - -.. _here that uses a few tricks: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_bitfields.cpp diff --git a/3rdparty/sol2/examples/any_return.cpp b/3rdparty/sol2/examples/any_return.cpp deleted file mode 100644 index f286071b8d8..00000000000 --- a/3rdparty/sol2/examples/any_return.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include <sol.hpp> - -#include <iostream> -#include <cassert> - -// Uses some of the fancier bits of sol2, including the "transparent argument", -// sol::this_state, which gets the current state and does not increment -// function arguments -sol::object fancy_func(sol::object a, sol::object b, sol::this_state s) { - sol::state_view lua(s); - if (a.is<int>() && b.is<int>()) { - return sol::object(lua, sol::in_place, a.as<int>() + b.as<int>()); - } - else if (a.is<bool>()) { - bool do_triple = a.as<bool>(); - return sol::object(lua, sol::in_place<double>, b.as<double>() * (do_triple ? 3 : 1)); - } - // Can also use make_object - return sol::make_object(lua, sol::nil); -} - -int main() { - sol::state lua; - - lua["f"] = fancy_func; - - int result = lua["f"](1, 2); - // result == 3 - assert(result == 3); - double result2 = lua["f"](false, 2.5); - // result2 == 2.5 - assert(result2 == 2.5); - - // call in Lua, get result - // notice we only need 2 arguments here, not 3 (sol::this_state is transparent) - lua.script("result3 = f(true, 5.5)"); - double result3 = lua["result3"]; - // result3 == 16.5 - assert(result3 == 16.5); - - std::cout << "=== any_return example ===" << std::endl; - std::cout << "result : " << result << std::endl; - std::cout << "result2: " << result2 << std::endl; - std::cout << "result3: " << result3 << std::endl; - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/basic.cpp b/3rdparty/sol2/examples/basic.cpp deleted file mode 100644 index cf00ee70ab2..00000000000 --- a/3rdparty/sol2/examples/basic.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <sol.hpp> - -#include <iostream> - -int main() { - // create an empty lua state - sol::state lua; - - // by default, libraries are not opened - // you can open libraries by using open_libraries - // the libraries reside in the sol::lib enum class - lua.open_libraries(sol::lib::base); - - // call lua code directly - std::cout << "=== basic example ===" << std::endl; - lua.script("print('hello world')"); - - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/config.cpp b/3rdparty/sol2/examples/config.cpp deleted file mode 100644 index d899de385ca..00000000000 --- a/3rdparty/sol2/examples/config.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include <sol.hpp> -#include <string> -#include <iostream> - -// shows how to load basic data to a struct - -struct config { - std::string name; - int width; - int height; - - void print() { - std::cout << "Name: " << name << '\n' - << "Width: " << width << '\n' - << "Height: " << height << '\n'; - } -}; - -int main() { - sol::state lua; - config screen; - // To use the file, uncomment here and make sure it is in local dir - //lua.script_file("config.lua"); - lua.script(R"( -name = "Asus" -width = 1920 -height = 1080 -)"); - screen.name = lua.get<std::string>("name"); - screen.width = lua.get<int>("width"); - screen.height = lua.get<int>("height"); - assert(screen.name == "Asus"); - assert(screen.width == 1920); - assert(screen.height == 1080); - - std::cout << "=== config example ===" << std::endl; - screen.print(); - std::cout << std::endl; -} diff --git a/3rdparty/sol2/examples/config.lua b/3rdparty/sol2/examples/config.lua deleted file mode 100644 index 0144f989a84..00000000000 --- a/3rdparty/sol2/examples/config.lua +++ /dev/null @@ -1,3 +0,0 @@ -name = "Asus" -width = 1920 -height = 1080 diff --git a/3rdparty/sol2/examples/coroutine.cpp b/3rdparty/sol2/examples/coroutine.cpp deleted file mode 100644 index 75b4f817a3b..00000000000 --- a/3rdparty/sol2/examples/coroutine.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include <string> -#include "sol.hpp" - -#include <iostream> - -int main() { - std::cout << "=== coroutine example ===" << std::endl; - - sol::state lua; - std::vector<sol::coroutine> tasks; - - lua.open_libraries(sol::lib::base, sol::lib::coroutine); - - sol::thread runner_thread = sol::thread::create(lua); - - lua.set_function("start_task", - [&runner_thread, &tasks](sol::function f, sol::variadic_args va) { - // You must ALWAYS get the current state - sol::state_view runner_thread_state = runner_thread.state(); - // Put the task in our task list to keep it alive and track it - std::size_t task_index = tasks.size(); - tasks.emplace_back(runner_thread_state, f); - sol::coroutine& f_on_runner_thread = tasks[task_index]; - // call coroutine with arguments that came - // from main thread / other thread - // pusher for `variadic_args` and other sol types will transfer the - // arguments from the calling thread to - // the runner thread automatically for you - // using `lua_xmove` internally - int wait = f_on_runner_thread(va); - std::cout << "First return: " << wait << std::endl; - // When you call it again, you don't need new arguments - // (they remain the same from the first call) - f_on_runner_thread(); - std::cout << "Second run complete: " << wait << std::endl; - }); - - lua.script( - R"( -function main(x, y, z) - -- do something - coroutine.yield(20) - -- do something else - -- do ... - print(x, y, z) -end - -function main2(x, y) - coroutine.yield(10) - print(x, y) -end - - start_task(main, 10, 12, 8) - start_task(main2, 1, 2) -)" -); - - return 0; -} diff --git a/3rdparty/sol2/examples/customization.cpp b/3rdparty/sol2/examples/customization.cpp deleted file mode 100644 index 45280e5989b..00000000000 --- a/3rdparty/sol2/examples/customization.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include <sol.hpp> - -#include <iostream> -#include <iomanip> -#include <cassert> - -struct two_things { - int a; - bool b; -}; - -namespace sol { - - // First, the expected size - // Specialization of a struct - template <> - struct lua_size<two_things> : std::integral_constant<int, 2> {}; - - // Now, specialize various stack structures - namespace stack { - - template <> - struct checker<two_things> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - // indices can be negative to count backwards from the top of the stack, - // rather than the bottom up - // to deal with this, we adjust the index to - // its absolute position using the lua_absindex function - int absolute_index = lua_absindex(L, index); - // Check first and second second index for being the proper types - bool success = stack::check<int>(L, absolute_index + 1, handler) - && stack::check<bool>(L, absolute_index, handler); - tracking.use(2); - return success; - } - }; - - template <> - struct getter<two_things> { - static two_things get(lua_State* L, int index, record& tracking) { - int absolute_index = lua_absindex(L, index); - // Get the first element - int a = stack::get<int>(L, absolute_index); - // Get the second element, - // in the +1 position from the first - bool b = stack::get<bool>(L, absolute_index + 1); - // we use 2 slots, each of the previous takes 1 - tracking.use(2); - return two_things{ a, b }; - } - }; - - template <> - struct pusher<two_things> { - static int push(lua_State* L, const two_things& things) { - int amount = stack::push(L, things.a); - // amount will be 1: int pushes 1 item - amount += stack::push(L, things.b); - // amount 2 now, since bool pushes a single item - // Return 2 things - return amount; - } - }; - - } -} - -int main() { - sol::state lua; - - // Create a pass-through style of function - lua.script("function f ( a, b ) return a, b end"); - - // get the function out of Lua - sol::function f = lua["f"]; - - two_things things = f(two_things{ 24, true }); - assert(things.a == 24); - assert(things.b == true); - // things.a == 24 - // things.b == true - - std::cout << "=== customization example ===" << std::endl; - std::cout << std::boolalpha; - std::cout << "things.a: " << things.a << std::endl; - std::cout << "things.b: " << things.b << std::endl; - std::cout << std::endl; - - return 0; -} diff --git a/3rdparty/sol2/examples/functions.cpp b/3rdparty/sol2/examples/functions.cpp deleted file mode 100644 index b4f9a1da140..00000000000 --- a/3rdparty/sol2/examples/functions.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include <sol.hpp> -#include <cassert> -#include <iostream> - -inline int my_add(int x, int y) { - return x + y; -} - -struct multiplier { - int operator()(int x) { - return x * 10; - } - - static int by_five(int x) { - return x * 5; - } -}; - -inline std::string make_string( std::string input ) { - return "string: " + input; -} - -int main() { - std::cout << "=== functions example ===" << std::endl; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - // setting a function is simple - lua.set_function("my_add", my_add); - - // you could even use a lambda - lua.set_function("my_mul", [](double x, double y) { return x * y; }); - - // member function pointers and functors as well - lua.set_function("mult_by_ten", multiplier{}); - lua.set_function("mult_by_five", &multiplier::by_five); - - // assert that the functions work - lua.script("assert(my_add(10, 11) == 21)"); - lua.script("assert(my_mul(4.5, 10) == 45)"); - lua.script("assert(mult_by_ten(50) == 500)"); - lua.script("assert(mult_by_five(10) == 50)"); - - // using lambdas, functions can have state. - int x = 0; - lua.set_function("inc", [&x]() { x += 10; }); - - // calling a stateful lambda modifies the value - lua.script("inc()"); - assert(x == 10); - if (x == 10) { - // Do something based on this information - std::cout << "Yahoo! x is " << x << std::endl; - } - - // this can be done as many times as you want - lua.script(R"( -inc() -inc() -inc() -)"); - assert(x == 40); - if (x == 40) { - // Do something based on this information - std::cout << "Yahoo! x is " << x << std::endl; - } - // retrieval of a function is done similarly - // to other variables, using sol::function - sol::function add = lua["my_add"]; - int value = add(10, 11); - // second way to call the function - int value2 = add.call<int>(10, 11); - assert(value == 21); - assert(value2 == 21); - if (value == 21 && value2 == 21) { - std::cout << "Woo, value is 21!" << std::endl; - } - - // multi-return functions are supported using - // std::tuple as the interface. - lua.set_function("multi", [] { return std::make_tuple(10, "goodbye"); }); - lua.script("x, y = multi()"); - lua.script("assert(x == 10 and y == 'goodbye')"); - - auto multi = lua.get<sol::function>("multi"); - int first; - std::string second; - sol::tie(first, second) = multi(); - - // use the values - assert(first == 10); - assert(second == "goodbye"); - - // you can even overload functions - // just pass in the different functions - // you want to pack into a single name: - // make SURE they take different types! - - lua.set_function("func", sol::overload([](int x) { return x; }, make_string, my_add)); - - // All these functions are now overloaded through "func" - lua.script(R"( -print(func(1)) -print(func("bark")) -print(func(1,2)) -)"); - - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/namespacing.cpp b/3rdparty/sol2/examples/namespacing.cpp deleted file mode 100644 index 8d32744eb64..00000000000 --- a/3rdparty/sol2/examples/namespacing.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <cassert> - -int main() { - struct my_class { - int b = 24; - - int f() const { - return 24; - } - - void g() { - ++b; - } - }; - - sol::state lua; - lua.open_libraries(); - - sol::table bark = lua.create_named_table("bark"); - bark.new_usertype<my_class>("my_class", - "f", &my_class::f, - "g", &my_class::g - ); // the usual - - lua.script("obj = bark.my_class.new()"); // this works - lua.script("obj:g()"); - my_class& obj = lua["obj"]; - assert(obj.b == 25); - - return 0; -} diff --git a/3rdparty/sol2/examples/player_script.lua b/3rdparty/sol2/examples/player_script.lua deleted file mode 100644 index 432983e02a7..00000000000 --- a/3rdparty/sol2/examples/player_script.lua +++ /dev/null @@ -1,29 +0,0 @@ --- call single argument integer constructor -p1 = player.new(2) - --- p2 is still here from being --- set with lua["p2"] = player(0); below -local p2shoots = p2:shoot() -assert(not p2shoots) --- had 0 ammo - --- set variable property setter -p1.hp = 545; --- get variable through property getter -print(p1.hp); - -local did_shoot_1 = p1:shoot() -print(did_shoot_1) -print(p1.bullets) -local did_shoot_2 = p1:shoot() -print(did_shoot_2) -print(p1.bullets) -local did_shoot_3 = p1:shoot() -print(did_shoot_3) - --- can read -print(p1.bullets) --- would error: is a readonly variable, cannot write --- p1.bullets = 20 - -p1:boost()
\ No newline at end of file diff --git a/3rdparty/sol2/examples/protected_functions.cpp b/3rdparty/sol2/examples/protected_functions.cpp deleted file mode 100644 index 340f0134d63..00000000000 --- a/3rdparty/sol2/examples/protected_functions.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include <sol.hpp> - -#include <iostream> - -int main() { - std::cout << "=== protected_functions example ===" << std::endl; - - sol::state lua; - - // A complicated function which can error out - // We define both in terms of Lua code - - lua.script(R"( - function handler (message) - return "Handled this message: " .. message - end - - function f (a) - if a < 0 then - error("negative number detected") - end - return a + 5 - end - )"); - - // Get a protected function out of Lua - sol::protected_function f = lua["f"]; - // Set a non-default error handler - f.error_handler = lua["handler"]; - - sol::protected_function_result result = f(-500); - if (result.valid()) { - // Call succeeded - int x = result; - std::cout << "call succeeded, result is " << x << std::endl; - } - else { - // Call failed - sol::error err = result; - std::string what = err.what(); - std::cout << "call failed, sol::error::what() is " << what << std::endl; - // 'what' Should read - // "Handled this message: negative number detected" - } - - std::cout << std::endl; -} diff --git a/3rdparty/sol2/examples/require.cpp b/3rdparty/sol2/examples/require.cpp deleted file mode 100644 index a94765b9453..00000000000 --- a/3rdparty/sol2/examples/require.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <cassert> - -#include <iostream> - -struct some_class { - int bark = 2012; -}; - -sol::table open_mylib(sol::this_state s) { - sol::state_view lua(s); - - sol::table module = lua.create_table(); - module["func"] = []() { /* super cool function here */ }; - // register a class too - module.new_usertype<some_class>("some_class", - "bark", &some_class::bark - ); - - return module; -} - -int main() { - std::cout << "=== require example ===" << std::endl; - - sol::state lua; - lua.open_libraries(sol::lib::package); - // sol::c_call takes functions at the template level - // and turns it into a lua_CFunction - // alternatively, one can use sol::c_call<sol::wrap<callable_struct, callable_struct{}>> to make the call - // if it's a constexpr struct - lua.require("my_lib", sol::c_call<decltype(&open_mylib), &open_mylib>); - - // do ALL THE THINGS YOU LIKE - lua.script(R"( -s = my_lib.some_class.new() -s.bark = 20; -)"); - some_class& s = lua["s"]; - assert(s.bark == 20); - std::cout << "s.bark = " << s.bark << std::endl; - - std::cout << std::endl; - - return 0; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/self_call.cpp b/3rdparty/sol2/examples/self_call.cpp deleted file mode 100644 index c64ded34133..00000000000 --- a/3rdparty/sol2/examples/self_call.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <cassert> -#include <iostream> - -int main() { - std::cout << "=== self_call example ===" << std::endl; - - sol::state lua; - - lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table); - - // a small script using 'self' syntax - lua.script(R"( - some_table = { some_val = 100 } - - function some_table:add_to_some_val(value) - self.some_val = self.some_val + value - end - - function print_some_val() - print("some_table.some_val = " .. some_table.some_val) - end - )"); - - // do some printing - lua["print_some_val"](); - // 100 - - sol::table self = lua["some_table"]; - self["add_to_some_val"](self, 10); - lua["print_some_val"](); - - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/static_variables.cpp b/3rdparty/sol2/examples/static_variables.cpp deleted file mode 100644 index c101e824484..00000000000 --- a/3rdparty/sol2/examples/static_variables.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include <sol.hpp> - -#include <iostream> -#include <cassert> - -struct test { - static int muh_variable; -}; -int test::muh_variable = 25; - - -int main() { - std::cout << "=== static_variables example ===" << std::endl; - - sol::state lua; - lua.open_libraries(); - lua.new_usertype<test>("test", - "direct", sol::var(2), - "global", sol::var(test::muh_variable), - "ref_global", sol::var(std::ref(test::muh_variable)) - ); - - int direct_value = lua["test"]["direct"]; - // direct_value == 2 - assert(direct_value == 2); - std::cout << "direct_value: " << direct_value << std::endl; - - int global = lua["test"]["global"]; - int global2 = lua["test"]["ref_global"]; - // global == 25 - // global2 == 25 - assert(global == 25); - assert(global2 == 25); - - std::cout << "First round of values --" << std::endl; - std::cout << global << std::endl; - std::cout << global2 << std::endl; - - test::muh_variable = 542; - - global = lua["test"]["global"]; - // global == 25 - // global is its own memory: was passed by value - - global2 = lua["test"]["ref_global"]; - // global2 == 542 - // global2 was passed through std::ref - // global2 holds a reference to muh_variable - // if muh_variable goes out of scope or is deleted - // problems could arise, so be careful! - - assert(global == 25); - assert(global2 == 542); - - std::cout << "Second round of values --" << std::endl; - std::cout << "global : " << global << std::endl; - std::cout << "global2: " << global2 << std::endl; - std::cout << std::endl; - - return 0; -} diff --git a/3rdparty/sol2/examples/tables.cpp b/3rdparty/sol2/examples/tables.cpp deleted file mode 100644 index 41798d3b0b4..00000000000 --- a/3rdparty/sol2/examples/tables.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include <sol.hpp> -#include <string> -#include <iostream> - -// this example shows how to read data in from a lua table - -int main() { - std::cout << "=== tables example ===" << std::endl; - - sol::state lua; - // table used as an array - lua.script("table1 = {\"hello\", \"table\"}"); - // table with a nested table and the key value syntax - lua.script("table2 = {" - "[\"nestedTable\"] = {" - "[\"key1\"] = \"value1\"," - "[\"key2\"]= \"value2\"" - "}," - "[\"name\"]= \"table2\"" - "}"); - - - /* Shorter Syntax: */ - // using the values stored in table1 - /*std::cout << (std::string)lua["table1"][1] << " " - << (std::string)lua["table1"][2] << '\n'; - */ - // some retrieval of values from the nested table - // the cleaner way of doing things - // chain off the the get<>() / [] results - auto t2 = lua.get<sol::table>("table2"); - auto nestedTable = t2.get<sol::table>("nestedTable"); - // Alternatively: - //sol::table t2 = lua["table2"]; - //sol::table nestedTable = t2["nestedTable"]; - - std::string x = lua["table2"]["nestedTable"]["key2"]; - std::cout << "nested table: key1 : " << nestedTable.get<std::string>("key1") << ", key2: " - << x - << '\n'; - std::cout << "name of t2: " << t2.get<std::string>("name") << '\n'; - std::string t2name = t2["name"]; - std::cout << "name of t2: " << t2name << '\n'; - - /* Longer Syntax: */ - // using the values stored in table1 - std::cout << lua.get<sol::table>("table1").get<std::string>(1) << " " - << lua.get<sol::table>("table1").get<std::string>(2) << '\n'; - - // some retrieval of values from the nested table - // the cleaner way of doing things - std::cout << "nested table: key1 : " << nestedTable.get<std::string>("key1") << ", key2: " - // yes you can chain the get<>() results - << lua.get<sol::table>("table2").get<sol::table>("nestedTable").get<std::string>("key2") - << '\n'; - std::cout << "name of t2: " << t2.get<std::string>("name") << '\n'; - - std::cout << std::endl; -} diff --git a/3rdparty/sol2/examples/usertype.cpp b/3rdparty/sol2/examples/usertype.cpp deleted file mode 100644 index 496a0b763d3..00000000000 --- a/3rdparty/sol2/examples/usertype.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include <sol.hpp> -#include <iostream> -#include <cassert> -#include <cmath> - -struct foo { -private: - std::string name; -public: - foo(std::string name): name(std::string(name)) {} - - void print() { - std::cout << name << '\n'; - } - - int test(int x) { - return name.length() + x; - } -}; - -struct vector { -private: - float x = 0; - float y = 0; -public: - vector() = default; - vector(float x): x(x) {} - vector(float x, float y): x(x), y(y) {} - - bool is_unit() const { - return (x * x + y * y) == 1.f; - } -}; - -struct variables { - bool low_gravity = false; - int boost_level = 0; - -}; - -int main() { - std::cout << "=== usertype example ===" << std::endl; - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::math); - - // the simplest way to create a class is through - // sol::state::new_userdata - // the first template is the class type - // the rest are the constructor parameters - // using new_userdata you can only have one constructor - - - // you must make sure that the name of the function - // goes before the member function pointer - lua.new_usertype<foo, std::string>("foo", "print", &foo::print, "test", &foo::test); - - // making the class from lua is simple - // same with calling member functions - lua.script("x = foo.new('test')\n" - "x:print()\n" - "y = x:test(10)"); - - auto y = lua.get<int>("y"); - std::cout << y << std::endl; // show 14 - - // if you want a class to have more than one constructor - // the way to do so is through set_userdata and creating - // a userdata yourself with constructor types - - { - // Notice the brace: this means we're in a new scope - // first, define the different types of constructors - sol::constructors<sol::types<>, sol::types<float>, sol::types<float, float>> ctor; - - // the only template parameter is the class type - // the first argument of construction is the name - // second is the constructor types - // then the rest are function name and member function pointer pairs - sol::usertype<vector> utype(ctor, "is_unit", &vector::is_unit); - - // then you must register it - lua.set_usertype("vector", utype); - // You can throw away the usertype after you set it: you do NOT - // have to keep it around - // cleanup happens automagically - } - // calling it is the same as new_userdata - - lua.script("v = vector.new()\n" - "v = vector.new(12)\n" - "v = vector.new(10, 10)\n" - "assert(not v:is_unit())\n"); - - // You can even have C++-like member-variable-access - // just pass is public member variables in the same style as functions - lua.new_usertype<variables>("variables", "low_gravity", &variables::low_gravity, "boost_level", &variables::boost_level); - - // making the class from lua is simple - // same with calling member functions/variables - lua.script("local vars = variables.new()\n" - "assert(not vars.low_gravity)\n" - "vars.low_gravity = true\n" - "local x = vars.low_gravity\n" - "assert(x)"); - - std::cout << std::endl; - -} diff --git a/3rdparty/sol2/examples/usertype_advanced.cpp b/3rdparty/sol2/examples/usertype_advanced.cpp deleted file mode 100644 index 32679089844..00000000000 --- a/3rdparty/sol2/examples/usertype_advanced.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include <sol.hpp> - -#include <iostream> - -struct player { -public: - int bullets; - int speed; - - player() - : player(3, 100) { - - } - - player(int ammo) - : player(ammo, 100) { - - } - - player(int ammo, int hitpoints) - : bullets(ammo), hp(hitpoints) { - - } - - void boost() { - speed += 10; - } - - bool shoot() { - if (bullets < 1) - return false; - --bullets; - return true; - } - - void set_hp(int value) { - hp = value; - } - - int get_hp() const { - return hp; - } - -private: - int hp; -}; - -int main() { - std::cout << "=== usertype_advanced example ===" << std::endl; - sol::state lua; - - lua.open_libraries(sol::lib::base); - - // note that you can set a - // userdata before you register a usertype, - // and it will still carry - // the right metatable if you register it later - - // set a variable "p2" of type "player" with 0 ammo - lua["p2"] = player(0); - - // make usertype metatable - lua.new_usertype<player>("player", - - // 3 constructors - sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>>(), - - // typical member function that returns a variable - "shoot", &player::shoot, - // typical member function - "boost", &player::boost, - - // gets or set the value using member variable syntax - "hp", sol::property(&player::get_hp, &player::set_hp), - - // read and write variable - "speed", &player::speed, - // can only read from, not write to - "bullets", sol::readonly(&player::bullets) - ); - - std::string player_script = R"( --- call single argument integer constructor -p1 = player.new(2) - --- p2 is still here from being --- set with lua["p2"] = player(0); below -local p2shoots = p2:shoot() -assert(not p2shoots) --- had 0 ammo - --- set variable property setter -p1.hp = 545 --- get variable through property getter -print(p1.hp) -assert(p1.hp == 545) - -local did_shoot_1 = p1:shoot() -print(did_shoot_1) -print(p1.bullets) -local did_shoot_2 = p1:shoot() -print(did_shoot_2) -print(p1.bullets) -local did_shoot_3 = p1:shoot() -print(did_shoot_3) - --- can read -print(p1.bullets) --- would error: is a readonly variable, cannot write --- p1.bullets = 20 - -p1:boost() -)"; - - // Uncomment and use the file to try that out, too! - // Make sure it's in the local directory of the executable after you build, or adjust the filename path - // Or whatever else you like! - //lua.script_file("player_script.lua"); - lua.script(player_script); - std::cout << std::endl; -} diff --git a/3rdparty/sol2/examples/usertype_bitfields.cpp b/3rdparty/sol2/examples/usertype_bitfields.cpp deleted file mode 100644 index 271045babcd..00000000000 --- a/3rdparty/sol2/examples/usertype_bitfields.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> - -#include <cstddef> -#include <cstdint> -#include <climits> -#include <type_traits> - -namespace itsy_bitsy { - - template <std::size_t sz, typename C = void> - struct bit_type { - typedef uint64_t type; - }; - - template <std::size_t sz> - struct bit_type<sz, std::enable_if_t<(sz <= 1)>> { - typedef bool type; - }; - - template <std::size_t sz> - struct bit_type<sz, std::enable_if_t<(sz > 2 && sz <= 16)>> { - typedef uint16_t type; - }; - - template <std::size_t sz> - struct bit_type<sz, std::enable_if_t<(sz > 16 && sz <= 32)>> { - typedef uint32_t type; - }; - - template <std::size_t sz> - struct bit_type<sz, std::enable_if_t<(sz > 32 && sz <= 64)>> { - typedef uint64_t type; - }; - - template <std::size_t sz> - using bit_type_t = typename bit_type<sz>::type; - - template <typename T, typename V> - bool vcxx_warning_crap(std::true_type, V val) { - return val != 0; - } - - template <typename T, typename V> - T vcxx_warning_crap(std::false_type, V val) { - return static_cast<T>(val); - } - - template <typename T, typename V> - auto vcxx_warning_crap(V val) { - return vcxx_warning_crap<T>(std::is_same<bool, T>(), val); - } - - template <typename Base, std::size_t bit_target = 0x0, std::size_t size = 0x1> - void write(Base& b, bit_type_t<size> bits) { - typedef bit_type_t<sizeof(Base) * CHAR_BIT> aligned_type; - static const std::size_t aligned_type_bit_size = sizeof(aligned_type) * CHAR_BIT; - static_assert(sizeof(Base) * CHAR_BIT >= (bit_target + size), "bit offset and size are too large for the desired structure."); - static_assert((bit_target % aligned_type_bit_size) <= ((bit_target + size) % aligned_type_bit_size), "bit offset and size cross beyond largest integral constant boundary."); - - const std::size_t aligned_target = (bit_target + size) / aligned_type_bit_size; - const aligned_type bits_left = static_cast<aligned_type>(bit_target - aligned_target); - const aligned_type shifted_mask = ((static_cast<aligned_type>(1) << size) - 1) << bits_left; - const aligned_type compl_shifted_mask = ~shifted_mask; - // Jump by native size of a pointer to target - // then OR the bits - aligned_type* jumper = static_cast<aligned_type*>(static_cast<void*>(&b)); - jumper += aligned_target; - aligned_type& aligned = *jumper; - aligned &= compl_shifted_mask; - aligned |= (static_cast<aligned_type>(bits) << bits_left); - } - - template <typename Base, std::size_t bit_target = 0x0, std::size_t size = 0x1> - bit_type_t<size> read(Base& b) { - typedef bit_type_t<sizeof(Base) * CHAR_BIT> aligned_type; - typedef bit_type_t<size> field_type; - static const std::size_t aligned_type_bit_size = sizeof(aligned_type) * CHAR_BIT; - static_assert(sizeof(Base) * CHAR_BIT >= (bit_target + size), "bit offset and size are too large for the desired structure."); - static_assert((bit_target % aligned_type_bit_size) <= ((bit_target + size) % aligned_type_bit_size), "bit offset and size cross beyond largest integral constant boundary."); - - const std::size_t aligned_target = (bit_target + size) / aligned_type_bit_size; - const aligned_type bits_left = static_cast<aligned_type>(bit_target - aligned_target); - const aligned_type mask = (static_cast<aligned_type>(1) << size) - 1; - // Jump by native size of a pointer to target - // then OR the bits - aligned_type* jumper = static_cast<aligned_type*>(static_cast<void*>(&b)); - jumper += aligned_target; - const aligned_type& aligned = *jumper; - aligned_type field_bits = (aligned >> bits_left) & mask; - field_type bits = vcxx_warning_crap<field_type>(field_bits); - return bits; - } - -} - -#include <iostream> -#include <cassert> - -#if defined(_MSC_VER) || defined(__MINGW32__) -#pragma pack(1) -struct flags_t { -#else -struct __attribute__((packed, aligned(1))) flags_t { -#endif - uint8_t C : 1; - uint8_t N : 1; - uint8_t PV : 1; - uint8_t _3 : 1; - uint8_t H : 1; - uint8_t _5 : 1; - uint8_t Z : 1; - uint8_t S : 1; - uint16_t D : 14; -} flags{}; - -int main() { - std::cout << "=== usertype_bitfields example ===" << std::endl; -#ifdef __MINGW32__ - std::cout << "MinGW Detected, packing structs is broken in MinGW and this test may fail" << std::endl; -#endif - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<flags_t>("flags_t", - "C", sol::property(itsy_bitsy::read<flags_t, 0>, itsy_bitsy::write<flags_t, 0>), - "N", sol::property(itsy_bitsy::read<flags_t, 1>, itsy_bitsy::write<flags_t, 1>), - "D", sol::property(itsy_bitsy::read<flags_t, 8, 14>, itsy_bitsy::write<flags_t, 8, 14>) - ); - - lua["f"] = std::ref(flags); - - lua.script(R"( - print(f.C) - f.C = true; - print(f.C) - - print(f.N) - f.N = true; - print(f.N) - - print(f.D) - f.D = 0xDF; - print(f.D) -)"); - - bool C = flags.C; - bool N = flags.N; - uint16_t D = flags.D; - - std::cout << std::hex; - std::cout << "sizeof(flags): " << sizeof(flags) << std::endl; - std::cout << "C: " << C << std::endl; - std::cout << "N: " << N << std::endl; - std::cout << "D: " << D << std::endl; - - assert(C); - assert(N); - assert(D == 0xDF); - - std::cout << std::endl; - - return 0; -} diff --git a/3rdparty/sol2/examples/usertype_initializers.cpp b/3rdparty/sol2/examples/usertype_initializers.cpp deleted file mode 100644 index 10f1f68cb94..00000000000 --- a/3rdparty/sol2/examples/usertype_initializers.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <memory> -#include <iostream> -#include <cassert> - -struct holy { -private: - holy() : data() {} - holy(int value) : data(value) {} - ~holy() {} - -public: - struct deleter { - void operator()(holy* p) const { - destroy(*p); - } - }; - - const int data; - - static std::unique_ptr<holy, deleter> create() { - std::cout << "creating 'holy' unique_ptr directly and letting sol/Lua handle it" << std::endl; - return std::unique_ptr<holy, deleter>(new holy(50)); - } - - static void initialize(holy& uninitialized_memory) { - std::cout << "initializing 'holy' userdata at " << static_cast<void*>(&uninitialized_memory) << std::endl; - // receive uninitialized memory from Lua: - // properly set it by calling a constructor - // on it - // "placement new" - new (&uninitialized_memory) holy(); - } - - static void destroy(holy& memory_from_lua) { - std::cout << "destroying 'holy' userdata at " << static_cast<void*>(&memory_from_lua) << std::endl; - memory_from_lua.~holy(); - } -}; - -int main() { - std::cout << "=== usertype_initializers example ===" << std::endl; - { // additional scope to make usertype destroy earlier - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<holy>("holy", - "new", sol::initializers(&holy::initialize), - "create", sol::factories(&holy::create), - sol::meta_function::garbage_collect, sol::destructor(&holy::destroy), - "data", &holy::data - ); - - lua.script(R"( -h1 = holy.create() -h2 = holy.new() -print('h1.data is ' .. h1.data) -print('h2.data is ' .. h2.data) -)"); - holy& h1 = lua["h1"]; - holy& h2 = lua["h2"]; - assert(h1.data == 50); - assert(h2.data == 0); - } - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/usertype_simple.cpp b/3rdparty/sol2/examples/usertype_simple.cpp deleted file mode 100644 index 1b64e3b403f..00000000000 --- a/3rdparty/sol2/examples/usertype_simple.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <memory> -#include <iostream> -#include <cassert> - -class generator { -private: - int data = 2; - -public: - int get_data() const { return data; } - void set_data(int value) { data = value % 10; } - - std::vector<int> generate_list() { - return { data, data * 2, data * 3, data * 4, data * 5 }; - } -}; - -struct my_data { - int first = 4; - int second = 8; - int third = 12; -}; - -int main() { - std::cout << "=== usertype_simple example ===" << std::endl; - - sol::state lua; - lua.open_libraries(); - - // simple_usertype acts and behaves like - // a regular usertype - lua.new_simple_usertype<my_data>("my_data", - "first", &my_data::first, - "second", &my_data::second, - "third", &my_data::third - ); - - { - // But, simple_usertype also has a `set` function - // where you can append things to the - // method listing after doing `create_simple_usertype`. - auto generator_registration = lua.create_simple_usertype<generator>(); - generator_registration.set("data", sol::property(&generator::get_data, &generator::set_data)); - // you MUST set the usertype after - // creating it - lua.set_usertype("generator", generator_registration); - } - - // Can update a simple_usertype at runtime, after registration - lua["generator"]["generate_list"] = [](generator& self) { return self.generate_list(); }; - // can set 'static methods' (no self) as well - lua["generator"]["get_num"] = []() { return 100; }; - - // Mix it all together! - lua.script(R"( -mdata = my_data.new() - -local g = generator.new() -g.data = mdata.first -list1 = g:generate_list() -g.data = mdata.second -list2 = g:generate_list() -g.data = mdata.third -list3 = g:generate_list() - -print("From lua: ") -for i = 1, #list1 do - print("\tlist1[" .. i .. "] = " .. list1[i]) -end -for i = 1, #list2 do - print("\tlist2[" .. i .. "] = " .. list2[i]) -end -for i = 1, #list3 do - print("\tlist3[" .. i .. "] = " .. list3[i]) -end - -)"); - my_data& mdata = lua["mdata"]; - std::vector<int>& list1 = lua["list1"]; - std::vector<int>& list2 = lua["list2"]; - std::vector<int>& list3 = lua["list3"]; - assert(list1.size() == 5); - assert(list2.size() == 5); - assert(list3.size() == 5); - for (int i = 1; i <= 5; ++i) { - assert(list1[i - 1] == (mdata.first % 10) * i); - assert(list2[i - 1] == (mdata.second % 10) * i); - assert(list3[i - 1] == (mdata.third % 10) * i); - } - - std::cout << std::endl; - return 0; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/usertype_special_functions.cpp b/3rdparty/sol2/examples/usertype_special_functions.cpp deleted file mode 100644 index 6528b684047..00000000000 --- a/3rdparty/sol2/examples/usertype_special_functions.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <iostream> -#include <cassert> -#include <cmath> - -struct vec { - double x; - double y; - - vec() : x(0), y(0) {} - vec(double x, double y) : x(x), y(y) {} - - vec operator-(const vec& right) const { - return vec(x - right.x, y - right.y); - } -}; - -double dot(const vec& left, const vec& right) { - return left.x * right.x + left.x * right.x; -} - -vec operator+(const vec& left, const vec& right) { - return vec(left.x + right.x, left.y + right.y); -} - -int main() { - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<vec>("vec", - sol::constructors<sol::types<>, sol::types<double, double>>(), - "dot", &dot, - "norm", [](const vec& self) { double len = std::sqrt(dot(self, self)); return vec(self.x / len, self.y / len); }, - // we use `sol::resolve` because other operator+ can exist - // in the (global) namespace - sol::meta_function::addition, sol::resolve<vec(const vec&, const vec&)>(::operator+), - sol::meta_function::subtraction, &vec::operator- - ); - - lua.script(R"( - v1 = vec.new(1, 0) - v2 = vec.new(0, 1) - -- as "member function" - d1 = v1:dot(v2) - -- as "static" / "free function" - d2 = vec.dot(v1, v2) - assert(d1 == d2) - - -- doesn't matter if - -- bound as free function - -- or member function: - a1 = v1 + v2 - s1 = v1 - v2 -)"); - - vec& a1 = lua["a1"]; - vec& s1 = lua["s1"]; - - assert(a1.x == 1 && a1.y == 1); - assert(s1.x == 1 && s1.y == -1); - - lua["a2"] = lua["a1"]; - - lua.script(R"( - assert(a1 == a2) - )"); - - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/usertype_var.cpp b/3rdparty/sol2/examples/usertype_var.cpp deleted file mode 100644 index 9f56490aa29..00000000000 --- a/3rdparty/sol2/examples/usertype_var.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#define SOL_CHECK_ARGUMENTS -#include <sol.hpp> -#include <iostream> - -struct test { - static int number; -}; -int test::number = 25; - - -int main() { - sol::state lua; - lua.open_libraries(); - lua.new_usertype<test>("test", - "direct", sol::var(2), - "number", sol::var(test::number), - "ref_number", sol::var(std::ref(test::number)) - ); - - int direct_value = lua["test"]["direct"]; - assert(direct_value == 2); - // direct_value == 2 - - int number = lua["test"]["number"]; - assert(number == 25); - int ref_number = lua["test"]["ref_number"]; - assert(ref_number == 25); - - test::number = 542; - - assert(lua["test"]["number"] == 25); - // number is its own memory: was passed by value - // So does not change - - assert(lua["test"]["ref_number"] == 542); - // ref_number is just test::number - // passed through std::ref - // so, it holds a reference - // which can be updated - // be careful about referencing local variables, - // if they go out of scope but are still reference - // you'll suffer dangling reference bugs! - - return 0; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/variables.cpp b/3rdparty/sol2/examples/variables.cpp deleted file mode 100644 index ece88915703..00000000000 --- a/3rdparty/sol2/examples/variables.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include <sol.hpp> -#include <iostream> - -int main() { - std::cout << "=== variables example ===" << std::endl; - - sol::state lua; - - // need the base library for assertions - lua.open_libraries(sol::lib::base); - - // basic setting of a variable - // through multiple ways - lua["x"] = 10; - lua.set("y", "hello"); - - // assert values are as given - lua.script("assert(x == 10)"); - lua.script("assert(y == 'hello')"); - - - // basic retrieval of a variable - // through multiple ways - int x = lua["x"]; - auto y = lua.get<std::string>("y"); - - int x2; - std::string y2; - std::tie(x2, y2) = lua.get<int, std::string>("x", "y"); - - // show the values - std::cout << x << std::endl; - std::cout << y << std::endl; - std::cout << x2 << std::endl; - std::cout << y2 << std::endl; - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/examples/variadic_args.cpp b/3rdparty/sol2/examples/variadic_args.cpp deleted file mode 100644 index 918e33ec790..00000000000 --- a/3rdparty/sol2/examples/variadic_args.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include <sol.hpp> - -#include <iostream> - -int main() { - std::cout << "=== variadic_args example ===" << std::endl; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - // Function requires 2 arguments - // rest can be variadic, but: - // va will include everything after "a" argument, - // which means "b" will be part of the varaidic_args list too - // at position 0 - lua.set_function("v", [](int a, sol::variadic_args va, int /*b*/) { - int r = 0; - for (auto v : va) { - int value = v; // get argument out (implicit conversion) - // can also do int v = va.get<int>(i); with index i - r += value; - } - // Only have to add a, b was included from variadic_args and beyond - return r + a; - }); - - lua.script("x = v(25, 25)"); - lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); - lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); - // will error: not enough arguments - //lua.script("x4 = v(1)"); - - lua.script("assert(x == 50)"); - lua.script("assert(x2 == 600)"); - lua.script("assert(x3 == 21)"); - lua.script("print(x)"); // 50 - lua.script("print(x2)"); // 600 - lua.script("print(x3)"); // 21 - std::cout << std::endl; -}
\ No newline at end of file diff --git a/3rdparty/sol2/install.deps.sh b/3rdparty/sol2/install.deps.sh deleted file mode 100644 index b3571190663..00000000000 --- a/3rdparty/sol2/install.deps.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env bash - -# This script installs and configures the dependencies for the project - -case `uname` in - Darwin) export OS_NAME="osx" ;; - Linux) export OS_NAME="linux" ;; -esac - -echo "Building on: ${OS_NAME}" - -if env | grep -qE '^(?:TRAVIS|CI)='; then -# We're on Travis, intialize variables: - echo "Detected CI Build -> CI=${CI}" -else -# We're building locally - export CI=false - echo "Detected Local Build -> CI=${CI}" -fi - -export_compiler_vars() { - case ${COMPILER} in - appleclang*) - export CC=clang - export CXX=clang++ - ;; - - clang*) - export CC=$(echo ${COMPILER} | sed 's/\+//g') - export CXX=${COMPILER} - ;; - - g++-*) - export CC=$(echo ${COMPILER} | sed 's/\+/c/g') - export CXX=${COMPILER} - ;; - - *) echo "Invalid compiler version" ; exit 2 ;; - esac - - echo "CC=${CC}" - $CC --version - - echo "CXX=${CXX}" - $CXX --version -} - -install_os_deps() { - # Install all of the OS specific OS dependencies - echo "Install: os-based dependencies" - - local wd=`pwd` - - case ${OS_NAME} in - osx) - export HOMEBREW_NO_EMOJI=1 - - echo "brew update ..."; brew update > /dev/null - - case ${COMPILER} in - appleclang*) ;; - - g++-5) - brew install gcc5 - brew link gcc5 --overwrite --force - ;; - - g++-4.9) ;; - - *) echo "Invalid compiler version" ; exit 2 ;; - esac - - brew install ninja - - local lua_pkg - case ${LUA_VERSION} in - lua53) lua_pkg=lua53 ;; - lua52) lua_pkg=lua ;; - lua51) lua_pkg=lua51 ;; - luajit52) lua_pkg=luajit ;; - luajit) lua_pkg=luajit ;; - *) echo "Invalid Lua Version for OSX" - exit 2 - ;; - esac - - brew install ${lua_pkg} - ;; - - linux) - # no extras currently - ;; - esac - - cd ${wd} -} diff --git a/3rdparty/sol2/ninja_syntax.py b/3rdparty/sol2/ninja_syntax.py deleted file mode 100644 index 14b932ff4c8..00000000000 --- a/3rdparty/sol2/ninja_syntax.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/python - -"""Python module for generating .ninja files. - -Note that this is emphatically not a required piece of Ninja; it's -just a helpful utility for build-file-generation systems that already -use Python. -""" - -import textwrap - -def escape_path(word): - return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') - -class Writer(object): - def __init__(self, output, width=78): - self.output = output - self.width = width - - def newline(self): - self.output.write('\n') - - def comment(self, text): - for line in textwrap.wrap(text, self.width - 2): - self.output.write('# ' + line + '\n') - - def variable(self, key, value, indent=0): - if value is None: - return - if isinstance(value, list): - value = ' '.join(filter(None, value)) # Filter out empty strings. - self._line('%s = %s' % (key, value), indent) - - def pool(self, name, depth): - self._line('pool %s' % name) - self.variable('depth', depth, indent=1) - - def rule(self, name, command, description=None, depfile=None, - generator=False, pool=None, restat=False, rspfile=None, - rspfile_content=None, deps=None): - self._line('rule %s' % name) - self.variable('command', command, indent=1) - if description: - self.variable('description', description, indent=1) - if depfile: - self.variable('depfile', depfile, indent=1) - if generator: - self.variable('generator', '1', indent=1) - if pool: - self.variable('pool', pool, indent=1) - if restat: - self.variable('restat', '1', indent=1) - if rspfile: - self.variable('rspfile', rspfile, indent=1) - if rspfile_content: - self.variable('rspfile_content', rspfile_content, indent=1) - if deps: - self.variable('deps', deps, indent=1) - - def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, - variables=None): - outputs = self._as_list(outputs) - out_outputs = [escape_path(x) for x in outputs] - all_inputs = [escape_path(x) for x in self._as_list(inputs)] - - if implicit: - implicit = [escape_path(x) for x in self._as_list(implicit)] - all_inputs.append('|') - all_inputs.extend(implicit) - if order_only: - order_only = [escape_path(x) for x in self._as_list(order_only)] - all_inputs.append('||') - all_inputs.extend(order_only) - - self._line('build %s: %s' % (' '.join(out_outputs), - ' '.join([rule] + all_inputs))) - - if variables: - if isinstance(variables, dict): - iterator = iter(variables.items()) - else: - iterator = iter(variables) - - for key, val in iterator: - self.variable(key, val, indent=1) - - return outputs - - def include(self, path): - self._line('include %s' % path) - - def subninja(self, path): - self._line('subninja %s' % path) - - def default(self, paths): - self._line('default %s' % ' '.join(self._as_list(paths))) - - def _count_dollars_before_index(self, s, i): - """Returns the number of '$' characters right in front of s[i].""" - dollar_count = 0 - dollar_index = i - 1 - while dollar_index > 0 and s[dollar_index] == '$': - dollar_count += 1 - dollar_index -= 1 - return dollar_count - - def _line(self, text, indent=0): - """Write 'text' word-wrapped at self.width characters.""" - leading_space = ' ' * indent - while len(leading_space) + len(text) > self.width: - # The text is too wide; wrap if possible. - - # Find the rightmost space that would obey our width constraint and - # that's not an escaped space. - available_space = self.width - len(leading_space) - len(' $') - space = available_space - while True: - space = text.rfind(' ', 0, space) - if (space < 0 or - self._count_dollars_before_index(text, space) % 2 == 0): - break - - if space < 0: - # No such space; just use the first unescaped space we can find. - space = available_space - 1 - while True: - space = text.find(' ', space + 1) - if (space < 0 or - self._count_dollars_before_index(text, space) % 2 == 0): - break - if space < 0: - # Give up on breaking. - break - - self.output.write(leading_space + text[0:space] + ' $\n') - text = text[space+1:] - - # Subsequent lines are continuations, so indent them. - leading_space = ' ' * (indent+2) - - self.output.write(leading_space + text + '\n') - - def _as_list(self, input): - if input is None: - return [] - if isinstance(input, list): - return input - return [input] - - -def escape(string): - """Escape a string such that it can be embedded into a Ninja file without - further interpretation.""" - assert '\n' not in string, 'Ninja syntax does not allow newlines' - # We only have one special metacharacter: '$'. - return string.replace('$', '$$') diff --git a/3rdparty/sol2/single.py b/3rdparty/sol2/single.py deleted file mode 100644 index 7607d51e530..00000000000 --- a/3rdparty/sol2/single.py +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env python - -import argparse -import os, sys -import re -import datetime as dt - -# python 3 compatibility -try: - import cStringIO as sstream -except ImportError: - from io import StringIO - -description = "Converts sol to a single file for convenience." - -# command line parser -parser = argparse.ArgumentParser(usage='%(prog)s [options...]', description=description) -parser.add_argument('--output', '-o', help='name and location of where to place file', metavar='file', default='sol.hpp') -parser.add_argument('--quiet', help='suppress all output', action='store_true') -args = parser.parse_args() - -script_path = os.path.normpath(os.path.dirname(os.path.realpath(__file__))) -working_dir = os.getcwd() -os.chdir(script_path) - -intro = """// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// This file was generated with a script. -// Generated {time} UTC -// This header was generated with sol {version} (revision {revision}) -// https://github.com/ThePhD/sol2 - -#ifndef {guard} -#define {guard} - -""" - -module_path = os.path.join(script_path) - -includes = set([]) -standard_include = re.compile(r'#include <(.*?)>') -local_include = re.compile(r'#include "(.*?)"') -ifndef_cpp = re.compile(r'#ifndef SOL_.*?_HPP') -define_cpp = re.compile(r'#define SOL_.*?_HPP') -endif_cpp = re.compile(r'#endif // SOL_.*?_HPP') - -def get_include(line, base_path): - local_match = local_include.match(line) - if local_match: - # local include found - full_path = os.path.normpath(os.path.join(base_path, local_match.group(1))).replace('\\', '/') - return full_path - - return None - - -def is_include_guard(line): - return ifndef_cpp.match(line) or define_cpp.match(line) or endif_cpp.match(line) - -def get_revision(): - return os.popen('git rev-parse --short HEAD').read().strip() - -def get_version(): - return os.popen('git describe --tags --abbrev=0').read().strip() - -def process_file(filename, out): - global includes - filename = os.path.normpath(filename) - relativefilename = filename.replace(script_path + os.sep, "").replace("\\", "/") - - if filename in includes: - return - - includes.add(filename) - - if not args.quiet: - print('processing {}'.format(filename)) - - out.write('// beginning of {}\n\n'.format(relativefilename)) - empty_line_state = True - - with open(filename, 'r', encoding='utf-8') as f: - for line in f: - # skip comments - if line.startswith('//'): - continue - - # skip include guard non-sense - if is_include_guard(line): - continue - - # get relative directory - base_path = os.path.dirname(filename) - - # check if it's a standard file - std = standard_include.search(line) - if std: - std_file = os.path.join('std', std.group(0)) - if std_file in includes: - continue - includes.add(std_file) - - # see if it's an include file - name = get_include(line, base_path) - - if name: - process_file(name, out) - continue - - empty_line = len(line.strip()) == 0 - - if empty_line and empty_line_state: - continue - - empty_line_state = empty_line - - # line is fine - out.write(line) - - out.write('// end of {}\n\n'.format(relativefilename)) - - -version = get_version() -revision = get_revision() -include_guard = 'SOL_SINGLE_INCLUDE_HPP' - -if not args.quiet: - print('Creating single header for sol') - print('Current version: {version} (revision {revision})\n'.format(version = version, revision = revision)) - - -processed_files = [os.path.join(script_path, x) for x in ['sol.hpp']] -result = '' - -ss = StringIO() -ss.write(intro.format(time=dt.datetime.utcnow(), revision=revision, version=version, guard=include_guard)) -for processed_file in processed_files: - process_file(processed_file, ss) - -ss.write('#endif // {}\n'.format(include_guard)) -result = ss.getvalue() -ss.close() - -with open(args.output, 'w', encoding='utf-8') as f: - f.write(result) - diff --git a/3rdparty/sol2/single/sol/sol.hpp b/3rdparty/sol2/single/sol/sol.hpp deleted file mode 100644 index 95f0e173fec..00000000000 --- a/3rdparty/sol2/single/sol/sol.hpp +++ /dev/null @@ -1,13160 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// This file was generated with a script. -// Generated 2017-02-01 11:49:07.483904 UTC -// This header was generated with sol v2.15.7 (revision 8d6f304) -// https://github.com/ThePhD/sol2 - -#ifndef SOL_SINGLE_INCLUDE_HPP -#define SOL_SINGLE_INCLUDE_HPP - -// beginning of sol.hpp - -#ifndef SOL_HPP -#define SOL_HPP - -#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) -#define SOL_INSIDE_UNREAL -#endif // Unreal Engine 4 bullshit - -#ifdef SOL_INSIDE_UNREAL -#ifdef check -#define SOL_INSIDE_UNREAL_REMOVED_CHECK -#undef check -#endif -#endif // Unreal Engine 4 Bullshit - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wconversion" -#elif defined _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier -#endif // g++ - -// beginning of sol/state.hpp - -// beginning of sol/state_view.hpp - -// beginning of sol/error.hpp - -#include <stdexcept> -#include <string> - -namespace sol { - namespace detail { - struct direct_error_tag {}; - const auto direct_error = direct_error_tag{}; - } // detail - - class error : public std::runtime_error { - private: - // Because VC++ is a fuccboi - std::string w; - public: - error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} - error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {} - error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} - error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} - - error(const error& e) = default; - error(error&& e) = default; - error& operator=(const error& e) = default; - error& operator=(error&& e) = default; - - virtual const char* what() const noexcept override { - return w.c_str(); - } - }; - -} // sol - -// end of sol/error.hpp - -// beginning of sol/table.hpp - -// beginning of sol/table_core.hpp - -// beginning of sol/proxy.hpp - -// beginning of sol/traits.hpp - -// beginning of sol/tuple.hpp - -#include <tuple> -#include <cstddef> - -namespace sol { - namespace detail { - using swallow = std::initializer_list<int>; - } // detail - - template<typename... Args> - struct types { typedef std::make_index_sequence<sizeof...(Args)> indices; static constexpr std::size_t size() { return sizeof...(Args); } }; - namespace meta { - namespace detail { - template<typename... Args> - struct tuple_types_ { typedef types<Args...> type; }; - - template<typename... Args> - struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; }; - } // detail - - template<typename T> - using unqualified = std::remove_cv<std::remove_reference_t<T>>; - - template<typename T> - using unqualified_t = typename unqualified<T>::type; - - template<typename... Args> - using tuple_types = typename detail::tuple_types_<Args...>::type; - - template<typename Arg> - struct pop_front_type; - - template<typename Arg> - using pop_front_type_t = typename pop_front_type<Arg>::type; - - template<typename... Args> - struct pop_front_type<types<Args...>> { typedef void front_type; typedef types<Args...> type; }; - - template<typename Arg, typename... Args> - struct pop_front_type<types<Arg, Args...>> { typedef Arg front_type; typedef types<Args...> type; }; - - template <std::size_t N, typename Tuple> - using tuple_element = std::tuple_element<N, unqualified_t<Tuple>>; - - template <std::size_t N, typename Tuple> - using tuple_element_t = std::tuple_element_t<N, unqualified_t<Tuple>>; - - template <std::size_t N, typename Tuple> - using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>; - - template <std::size_t N, typename Tuple> - using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>; - - } // meta -} // sol - -// end of sol/tuple.hpp - -// beginning of sol/bind_traits.hpp - -namespace sol { - namespace meta { - namespace meta_detail { - - template<class F> - struct check_deducible_signature { - struct nat {}; - template<class G> - static auto test(int) -> decltype(&G::operator(), void()); - template<class> - static auto test(...)->nat; - - using type = std::is_void<decltype(test<F>(0))>; - }; - } // meta_detail - - template<class F> - struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { }; - - namespace meta_detail { - - template <std::size_t I, typename T> - struct void_tuple_element : meta::tuple_element<I, T> {}; - - template <std::size_t I> - struct void_tuple_element<I, std::tuple<>> { typedef void type; }; - - template <std::size_t I, typename T> - using void_tuple_element_t = typename void_tuple_element<I, T>::type; - - template <bool has_c_variadic, typename T, typename R, typename... Args> - struct basic_traits { - private: - typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type; - - public: - static const bool is_member_function = std::is_void<T>::value; - static const bool has_c_var_arg = has_c_variadic; - static const std::size_t arity = sizeof...(Args); - static const std::size_t free_arity = sizeof...(Args)+static_cast<std::size_t>(!std::is_void<T>::value); - typedef types<Args...> args_list; - typedef std::tuple<Args...> args_tuple; - typedef T object_type; - typedef R return_type; - typedef tuple_types<R> returns_list; - typedef R(function_type)(Args...); - typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list; - typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type; - typedef std::conditional_t<std::is_void<T>::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; - typedef std::remove_pointer_t<free_function_pointer_type> signature_type; - template<std::size_t i> - using arg_at = void_tuple_element_t<i, args_tuple>; - }; - - template<typename Signature, bool b = has_deducible_signature<Signature>::value> - struct fx_traits : basic_traits<false, void, void> {}; - - // Free Functions - template<typename R, typename... Args> - struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> { - typedef R(*function_pointer_type)(Args...); - }; - - template<typename R, typename... Args> - struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> { - typedef R(*function_pointer_type)(Args...); - }; - - template<typename R, typename... Args> - struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> { - typedef R(*function_pointer_type)(Args..., ...); - }; - - template<typename R, typename... Args> - struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> { - typedef R(*function_pointer_type)(Args..., ...); - }; - - // Member Functions - /* C-Style Variadics */ - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...); - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...); - }; - - /* Const Volatile */ - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const volatile; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile; - }; - - /* Member Function Qualifiers */ - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const volatile &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) && , false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) && ; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) && , false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) && ; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const &&; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const &&; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const volatile &&; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; - }; - - template<typename Signature> - struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {}; - - template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value> - struct callable_traits : fx_traits<std::decay_t<Signature>> { - - }; - - template<typename R, typename T> - struct callable_traits<R(T::*), true> { - typedef R Arg; - typedef T object_type; - using signature_type = R(T::*); - static const bool is_member_function = false; - static const std::size_t arity = 1; - static const std::size_t free_arity = 2; - typedef std::tuple<Arg> args_tuple; - typedef R return_type; - typedef types<Arg> args_list; - typedef types<T, Arg> free_args_list; - typedef meta::tuple_types<R> returns_list; - typedef R(function_type)(T&, R); - typedef R(*function_pointer_type)(T&, R); - typedef R(*free_function_pointer_type)(T&, R); - template<std::size_t i> - using arg_at = void_tuple_element_t<i, args_tuple>; - }; - } // meta_detail - - template<typename Signature> - struct bind_traits : meta_detail::callable_traits<Signature> {}; - - template<typename Signature> - using function_args_t = typename bind_traits<Signature>::args_list; - - template<typename Signature> - using function_signature_t = typename bind_traits<Signature>::signature_type; - - template<typename Signature> - using function_return_t = typename bind_traits<Signature>::return_type; - - } // meta -} // sol - -// end of sol/bind_traits.hpp - -#include <type_traits> -#include <memory> -#include <functional> - -namespace sol { - template<std::size_t I> - using index_value = std::integral_constant<std::size_t, I>; - - namespace meta { - template<typename T> - struct identity { typedef T type; }; - - template<typename T> - using identity_t = typename identity<T>::type; - - template<typename... Args> - struct is_tuple : std::false_type { }; - - template<typename... Args> - struct is_tuple<std::tuple<Args...>> : std::true_type { }; - - template <typename T> - struct is_builtin_type : std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value> {}; - - template<typename T> - struct unwrapped { - typedef T type; - }; - - template<typename T> - struct unwrapped<std::reference_wrapper<T>> { - typedef T type; - }; - - template<typename T> - using unwrapped_t = typename unwrapped<T>::type; - - template <typename T> - struct unwrap_unqualified : unwrapped<unqualified_t<T>> {}; - - template <typename T> - using unwrap_unqualified_t = typename unwrap_unqualified<T>::type; - - template<typename T> - struct remove_member_pointer; - - template<typename R, typename T> - struct remove_member_pointer<R T::*> { - typedef R type; - }; - - template<typename R, typename T> - struct remove_member_pointer<R T::* const> { - typedef R type; - }; - - template<typename T> - using remove_member_pointer_t = remove_member_pointer<T>; - - template<template<typename...> class Templ, typename T> - struct is_specialization_of : std::false_type { }; - template<typename... T, template<typename...> class Templ> - struct is_specialization_of<Templ, Templ<T...>> : std::true_type { }; - - template<class T, class...> - struct all_same : std::true_type { }; - - template<class T, class U, class... Args> - struct all_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { }; - - template<class T, class...> - struct any_same : std::false_type { }; - - template<class T, class U, class... Args> - struct any_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { }; - - template<typename T> - using invoke_t = typename T::type; - - template<bool B> - using boolean = std::integral_constant<bool, B>; - - template<typename T> - using neg = boolean<!T::value>; - - template<typename Condition, typename Then, typename Else> - using condition = std::conditional_t<Condition::value, Then, Else>; - - template<typename... Args> - struct all : boolean<true> {}; - - template<typename T, typename... Args> - struct all<T, Args...> : condition<T, all<Args...>, boolean<false>> {}; - - template<typename... Args> - struct any : boolean<false> {}; - - template<typename T, typename... Args> - struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {}; - - enum class enable_t { - _ - }; - - constexpr const auto enabler = enable_t::_; - - template<bool value, typename T = void> - using disable_if_t = std::enable_if_t<!value, T>; - - template<typename... Args> - using enable = std::enable_if_t<all<Args...>::value, enable_t>; - - template<typename... Args> - using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>; - - template<typename... Args> - using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>; - - template<typename V, typename... Vs> - struct find_in_pack_v : boolean<false> { }; - - template<typename V, typename Vs1, typename... Vs> - struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { }; - - namespace meta_detail { - template<std::size_t I, typename T, typename... Args> - struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { }; - - template<std::size_t I, typename T, typename T1, typename... Args> - struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { }; - } - - template<typename T, typename... Args> - struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; - - template<typename T, typename List> - struct index_in : meta_detail::index_in_pack<0, T, List> { }; - - template<typename T, typename... Args> - struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> { }; - - template<std::size_t I, typename... Args> - struct at_in_pack {}; - - template<std::size_t I, typename... Args> - using at_in_pack_t = typename at_in_pack<I, Args...>::type; - - template<std::size_t I, typename Arg, typename... Args> - struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {}; - - template<typename Arg, typename... Args> - struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; - - namespace meta_detail { - template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename... Ts> - struct count_for_pack : std::integral_constant<std::size_t, 0> {}; - template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename T, typename... Ts> - struct count_for_pack<Limit, I, Pred, T, Ts...> : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, - std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>, - count_for_pack<Limit - 1, I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...> - > { }; - template<std::size_t I, template<typename...> class Pred, typename... Ts> - struct count_2_for_pack : std::integral_constant<std::size_t, 0> {}; - template<std::size_t I, template<typename...> class Pred, typename T, typename U, typename... Ts> - struct count_2_for_pack<I, Pred, T, U, Ts...> : std::conditional_t<sizeof...(Ts) == 0, - std::integral_constant<std::size_t, I + static_cast<std::size_t>(Pred<T>::value)>, - count_2_for_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...> - > { }; - } // meta_detail - - template<template<typename...> class Pred, typename... Ts> - struct count_for_pack : meta_detail::count_for_pack<sizeof...(Ts), 0, Pred, Ts...> { }; - - template<template<typename...> class Pred, typename List> - struct count_for; - - template<template<typename...> class Pred, typename... Args> - struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {}; - - template<std::size_t Limit, template<typename...> class Pred, typename... Ts> - struct count_for_to_pack : meta_detail::count_for_pack<Limit, 0, Pred, Ts...> { }; - - template<template<typename...> class Pred, typename... Ts> - struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; - - template<typename... Args> - struct return_type { - typedef std::tuple<Args...> type; - }; - - template<typename T> - struct return_type<T> { - typedef T type; - }; - - template<> - struct return_type<> { - typedef void type; - }; - - template <typename... Args> - using return_type_t = typename return_type<Args...>::type; - - namespace meta_detail { - template <typename> struct always_true : std::true_type {}; - struct is_invokable_tester { - template <typename Fun, typename... Args> - always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); - template <typename...> - std::false_type static test(...); - }; - } // meta_detail - - template <typename T> - struct is_invokable; - template <typename Fun, typename... Args> - struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {}; - - namespace meta_detail { - - template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value> - struct is_callable : std::is_function<std::remove_pointer_t<T>> {}; - - template<typename T> - struct is_callable<T, true> { - using yes = char; - using no = struct { char s[2]; }; - - struct F { void operator()(); }; - struct Derived : T, F {}; - template<typename U, U> struct Check; - - template<typename V> - static no test(Check<void (F::*)(), &V::operator()>*); - - template<typename> - static yes test(...); - - static const bool value = sizeof(test<Derived>(0)) == sizeof(yes); - }; - - struct has_begin_end_impl { - template<typename T, typename U = unqualified_t<T>, - typename B = decltype(std::declval<U&>().begin()), - typename E = decltype(std::declval<U&>().end())> - static std::true_type test(int); - - template<typename...> - static std::false_type test(...); - }; - - struct has_key_value_pair_impl { - template<typename T, typename U = unqualified_t<T>, - typename V = typename U::value_type, - typename F = decltype(std::declval<V&>().first), - typename S = decltype(std::declval<V&>().second)> - static std::true_type test(int); - - template<typename...> - static std::false_type test(...); - }; - - template <typename T, typename U = T, typename = decltype(std::declval<T&>() < std::declval<U&>())> - std::true_type supports_op_less_test(const T&); - std::false_type supports_op_less_test(...); - template <typename T, typename U = T, typename = decltype(std::declval<T&>() == std::declval<U&>())> - std::true_type supports_op_equal_test(const T&); - std::false_type supports_op_equal_test(...); - template <typename T, typename U = T, typename = decltype(std::declval<T&>() <= std::declval<U&>())> - std::true_type supports_op_less_equal_test(const T&); - std::false_type supports_op_less_equal_test(...); - - } // meta_detail - - template <typename T> - using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>())); - template <typename T> - using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>())); - template <typename T> - using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>())); - - template<typename T> - struct is_callable : boolean<meta_detail::is_callable<T>::value> {}; - - template<typename T> - struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {}; - - template<typename T> - struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {}; - - template <typename T> - using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>; - - template <typename T> - using is_c_str = any< - std::is_same<std::decay_t<unqualified_t<T>>, const char*>, - std::is_same<std::decay_t<unqualified_t<T>>, char*>, - std::is_same<unqualified_t<T>, std::string> - >; - - template <typename T> - struct is_move_only : all< - neg<std::is_reference<T>>, - neg<std::is_copy_constructible<unqualified_t<T>>>, - std::is_move_constructible<unqualified_t<T>> - > {}; - - template <typename T> - using is_not_move_only = neg<is_move_only<T>>; - - namespace meta_detail { - template <typename T, meta::disable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler> - decltype(auto) force_tuple(T&& x) { - return std::forward_as_tuple(std::forward<T>(x)); - } - - template <typename T, meta::enable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler> - decltype(auto) force_tuple(T&& x) { - return std::forward<T>(x); - } - } // meta_detail - - template <typename... X> - decltype(auto) tuplefy(X&&... x) { - return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...); - } - } // meta - namespace detail { - template <std::size_t I, typename Tuple> - decltype(auto) forward_get(Tuple&& tuple) { - return std::forward<meta::tuple_element_t<I, Tuple>>(std::get<I>(tuple)); - } - - template <std::size_t... I, typename Tuple> - auto forward_tuple_impl(std::index_sequence<I...>, Tuple&& tuple) -> decltype(std::tuple<decltype(forward_get<I>(tuple))...>(forward_get<I>(tuple)...)) { - return std::tuple<decltype(forward_get<I>(tuple))...>(std::move(std::get<I>(tuple))...); - } - - template <typename Tuple> - auto forward_tuple(Tuple&& tuple) { - auto x = forward_tuple_impl(std::make_index_sequence<std::tuple_size<meta::unqualified_t<Tuple>>::value>(), std::forward<Tuple>(tuple)); - return x; - } - - template<typename T> - auto unwrap(T&& item) -> decltype(std::forward<T>(item)) { - return std::forward<T>(item); - } - - template<typename T> - T& unwrap(std::reference_wrapper<T> arg) { - return arg.get(); - } - - template<typename T> - auto deref(T&& item) -> decltype(std::forward<T>(item)) { - return std::forward<T>(item); - } - - template<typename T> - inline T& deref(T* item) { - return *item; - } - - template<typename T, typename Dx> - inline std::add_lvalue_reference_t<T> deref(std::unique_ptr<T, Dx>& item) { - return *item; - } - - template<typename T> - inline std::add_lvalue_reference_t<T> deref(std::shared_ptr<T>& item) { - return *item; - } - - template<typename T, typename Dx> - inline std::add_lvalue_reference_t<T> deref(const std::unique_ptr<T, Dx>& item) { - return *item; - } - - template<typename T> - inline std::add_lvalue_reference_t<T> deref(const std::shared_ptr<T>& item) { - return *item; - } - - template<typename T> - inline T* ptr(T& val) { - return std::addressof(val); - } - - template<typename T> - inline T* ptr(std::reference_wrapper<T> val) { - return std::addressof(val.get()); - } - - template<typename T> - inline T* ptr(T* val) { - return val; - } - } // detail -} // sol - -// end of sol/traits.hpp - -// beginning of sol/object.hpp - -// beginning of sol/reference.hpp - -// beginning of sol/types.hpp - -// beginning of sol/optional.hpp - -// beginning of sol/compatibility.hpp - -// beginning of sol/compatibility/version.hpp - -#ifdef SOL_USING_CXX_LUA -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> -#else -#include <lua.hpp> -#endif // C++-compiler Lua - -#if defined(_WIN32) || defined(_MSC_VER) -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // sol codecvt support -#elif defined(__GNUC__) -#if __GNUC__ >= 5 -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // codecvt support -#endif // g++ 5.x.x (MinGW too) -#else -#endif // Windows/VC++ vs. g++ vs Others - -#ifdef LUAJIT_VERSION -#ifndef SOL_LUAJIT -#define SOL_LUAJIT -#define SOL_LUAJIT_VERSION LUAJIT_VERSION_NUM -#endif // sol luajit -#endif // luajit - -#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 -#define SOL_LUA_VERSION LUA_VERSION_NUM -#elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 -#define SOL_LUA_VERSION LUA_VERSION_NUM -#elif !defined(LUA_VERSION_NUM) -#define SOL_LUA_VERSION 500 -#else -#define SOL_LUA_VERSION 502 -#endif // Lua Version 502, 501 || luajit, 500 - -#ifdef _MSC_VER -#ifdef _DEBUG -#ifndef NDEBUG -#ifndef SOL_CHECK_ARGUMENTS -#endif // Check Arguments -#ifndef SOL_SAFE_USERTYPE -#define SOL_SAFE_USERTYPE -#endif // Safe Usertypes -#endif // NDEBUG -#endif // Debug - -#ifndef _CPPUNWIND -#ifndef SOL_NO_EXCEPTIONS -#define SOL_NO_EXCEPTIONS 1 -#endif -#endif // Automatic Exceptions - -#ifndef _CPPRTTI -#ifndef SOL_NO_RTTI -#define SOL_NO_RTTI 1 -#endif -#endif // Automatic RTTI - -#elif defined(__GNUC__) || defined(__clang__) - -#ifndef NDEBUG -#ifndef __OPTIMIZE__ -#ifndef SOL_CHECK_ARGUMENTS -#endif // Check Arguments -#ifndef SOL_SAFE_USERTYPE -#define SOL_SAFE_USERTYPE -#endif // Safe Usertypes -#endif // g++ optimizer flag -#endif // Not Debug - -#ifndef __EXCEPTIONS -#ifndef SOL_NO_EXCEPTIONS -#define SOL_NO_EXCEPTIONS 1 -#endif -#endif // No Exceptions - -#ifndef __GXX_RTTI -#ifndef SOL_NO_RTII -#define SOL_NO_RTTI 1 -#endif -#endif // No RTTI - -#endif // vc++ || clang++/g++ - -#ifndef SOL_SAFE_USERTYPE -#ifdef SOL_CHECK_ARGUMENTS -#define SOL_SAFE_USERTYPE -#endif // Turn on Safety for all -#endif // Safe Usertypes - -// end of sol/compatibility/version.hpp - -#ifndef SOL_NO_COMPAT - -#ifdef __cplusplus -extern "C" { -#endif -// beginning of sol/compatibility/5.1.0.h - -#ifndef SOL_5_1_0_H -#define SOL_5_1_0_H - -#if SOL_LUA_VERSION == 501 -/* Lua 5.1 */ - -#include <stddef.h> -#include <string.h> -#include <stdio.h> - -/* LuaJIT doesn't define these unofficial macros ... */ -#if !defined(LUAI_INT32) -#include <limits.h> -#if INT_MAX-20 < 32760 -#define LUAI_INT32 long -#define LUAI_UINT32 unsigned long -#elif INT_MAX > 2147483640L -#define LUAI_INT32 int -#define LUAI_UINT32 unsigned int -#else -#error "could not detect suitable lua_Unsigned datatype" -#endif -#endif - -/* LuaJIT does not have the updated error codes for thread status/function returns */ -#ifndef LUA_ERRGCMM -#define LUA_ERRGCMM (LUA_ERRERR + 1) -#endif // LUA_ERRGCMM - -/* LuaJIT does not support continuation contexts / return error codes? */ -#ifndef LUA_KCONTEXT -#define LUA_KCONTEXT std::ptrdiff_t -typedef LUA_KCONTEXT lua_KContext; -typedef int(*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); -#endif // LUA_KCONTEXT - -#define LUA_OPADD 0 -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 - -typedef LUAI_UINT32 lua_Unsigned; - -typedef struct luaL_Buffer_52 { - luaL_Buffer b; /* make incorrect code crash! */ - char *ptr; - size_t nelems; - size_t capacity; - lua_State *L2; -} luaL_Buffer_52; -#define luaL_Buffer luaL_Buffer_52 - -#define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) - -#define lua_rawlen(L, i) lua_objlen(L, i) - -inline void lua_callk(lua_State *L, int nargs, int nresults, lua_KContext, lua_KFunction) { - // should probably warn the user of Lua 5.1 that continuation isn't supported... - lua_call(L, nargs, nresults); -} -inline int lua_pcallk(lua_State *L, int nargs, int nresults, int errfunc, lua_KContext, lua_KFunction) { - // should probably warn the user of Lua 5.1 that continuation isn't supported... - return lua_pcall(L, nargs, nresults, errfunc); -} -void lua_arith(lua_State *L, int op); -int lua_compare(lua_State *L, int idx1, int idx2, int op); -void lua_pushunsigned(lua_State *L, lua_Unsigned n); -lua_Unsigned luaL_checkunsigned(lua_State *L, int i); -lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum); -lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def); -lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); -void lua_len(lua_State *L, int i); -int luaL_len(lua_State *L, int i); -const char *luaL_tolstring(lua_State *L, int idx, size_t *len); -void luaL_requiref(lua_State *L, char const* modname, lua_CFunction openf, int glb); - -#define luaL_buffinit luaL_buffinit_52 -void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B); - -#define luaL_prepbuffsize luaL_prepbuffsize_52 -char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s); - -#define luaL_addlstring luaL_addlstring_52 -void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l); - -#define luaL_addvalue luaL_addvalue_52 -void luaL_addvalue(luaL_Buffer_52 *B); - -#define luaL_pushresult luaL_pushresult_52 -void luaL_pushresult(luaL_Buffer_52 *B); - -#undef luaL_buffinitsize -#define luaL_buffinitsize(L, B, s) \ - (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) - -#undef luaL_prepbuffer -#define luaL_prepbuffer(B) \ - luaL_prepbuffsize(B, LUAL_BUFFERSIZE) - -#undef luaL_addchar -#define luaL_addchar(B, c) \ - ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ - ((B)->ptr[(B)->nelems++] = (c))) - -#undef luaL_addsize -#define luaL_addsize(B, s) \ - ((B)->nelems += (s)) - -#undef luaL_addstring -#define luaL_addstring(B, s) \ - luaL_addlstring(B, s, strlen(s)) - -#undef luaL_pushresultsize -#define luaL_pushresultsize(B, s) \ - (luaL_addsize(B, s), luaL_pushresult(B)) - -typedef struct kepler_lua_compat_get_string_view { - const char *s; - size_t size; -} kepler_lua_compat_get_string_view; - -inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t* size) { - kepler_lua_compat_get_string_view* ls = (kepler_lua_compat_get_string_view*) ud; - (void)L; - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - -#if !defined(SOL_LUAJIT) || (SOL_LUAJIT_VERSION < 20100) - -inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { - kepler_lua_compat_get_string_view ls; - ls.s = buff; - ls.size = size; - return lua_load(L, kepler_lua_compat_get_string, &ls, name/*, mode*/); -} - -#endif // LuaJIT 2.1.x beta and beyond - -#endif /* Lua 5.1 */ - -#endif // SOL_5_1_0_H -// end of sol/compatibility/5.1.0.h - -// beginning of sol/compatibility/5.0.0.h - -#ifndef SOL_5_0_0_H -#define SOL_5_0_0_H - -#if SOL_LUA_VERSION < 501 -/* Lua 5.0 */ - -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - -#define luaL_Reg luaL_reg - -#define luaL_opt(L, f, n, d) \ - (lua_isnoneornil(L, n) ? (d) : f(L, n)) - -#define luaL_addchar(B,c) \ - ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) - -#endif // Lua 5.0 - -#endif // SOL_5_0_0_H -// end of sol/compatibility/5.0.0.h - -// beginning of sol/compatibility/5.x.x.h - -#ifndef SOL_5_X_X_H -#define SOL_5_X_X_H - -#if SOL_LUA_VERSION < 502 - -#define LUA_RIDX_GLOBALS LUA_GLOBALSINDEX - -#define LUA_OK 0 - -#define lua_pushglobaltable(L) \ - lua_pushvalue(L, LUA_GLOBALSINDEX) - -#define luaL_newlib(L, l) \ - (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) - -void luaL_checkversion(lua_State *L); - -int lua_absindex(lua_State *L, int i); -void lua_copy(lua_State *L, int from, int to); -void lua_rawgetp(lua_State *L, int i, const void *p); -void lua_rawsetp(lua_State *L, int i, const void *p); -void *luaL_testudata(lua_State *L, int i, const char *tname); -lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); -void lua_getuservalue(lua_State *L, int i); -void lua_setuservalue(lua_State *L, int i); -void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); -void luaL_setmetatable(lua_State *L, const char *tname); -int luaL_getsubtable(lua_State *L, int i, const char *name); -void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); -int luaL_fileresult(lua_State *L, int stat, const char *fname); - -#endif // Lua 5.1 and below - -#endif // SOL_5_X_X_H -// end of sol/compatibility/5.x.x.h - -// beginning of sol/compatibility/5.x.x.inl - -#ifndef SOL_5_X_X_INL -#define SOL_5_X_X_INL - -// beginning of sol/compatibility/5.2.0.h - -#ifndef SOL_5_2_0_H -#define SOL_5_2_0_H - -#if SOL_LUA_VERSION < 503 - -inline int lua_isinteger(lua_State* L, int idx) { - if (lua_type(L, idx) != LUA_TNUMBER) - return 0; - // This is a very slipshod way to do the testing - // but lua_totingerx doesn't play ball nicely - // on older versions... - lua_Number n = lua_tonumber(L, idx); - lua_Integer i = lua_tointeger(L, idx); - if (i != n) - return 0; - // it's DEFINITELY an integer - return 1; -} - -#endif // SOL_LUA_VERSION == 502 -#endif // SOL_5_2_0_H -// end of sol/compatibility/5.2.0.h - -#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 - -#include <errno.h> - -#define PACKAGE_KEY "_sol.package" - -inline int lua_absindex(lua_State *L, int i) { - if (i < 0 && i > LUA_REGISTRYINDEX) - i += lua_gettop(L) + 1; - return i; -} - -inline void lua_copy(lua_State *L, int from, int to) { - int abs_to = lua_absindex(L, to); - luaL_checkstack(L, 1, "not enough stack slots"); - lua_pushvalue(L, from); - lua_replace(L, abs_to); -} - -inline void lua_rawgetp(lua_State *L, int i, const void *p) { - int abs_i = lua_absindex(L, i); - lua_pushlightuserdata(L, (void*)p); - lua_rawget(L, abs_i); -} - -inline void lua_rawsetp(lua_State *L, int i, const void *p) { - int abs_i = lua_absindex(L, i); - luaL_checkstack(L, 1, "not enough stack slots"); - lua_pushlightuserdata(L, (void*)p); - lua_insert(L, -2); - lua_rawset(L, abs_i); -} - -inline void *luaL_testudata(lua_State *L, int i, const char *tname) { - void *p = lua_touserdata(L, i); - luaL_checkstack(L, 2, "not enough stack slots"); - if (p == NULL || !lua_getmetatable(L, i)) - return NULL; - else { - int res = 0; - luaL_getmetatable(L, tname); - res = lua_rawequal(L, -1, -2); - lua_pop(L, 2); - if (!res) - p = NULL; - } - return p; -} - -inline lua_Number lua_tonumberx(lua_State *L, int i, int *isnum) { - lua_Number n = lua_tonumber(L, i); - if (isnum != NULL) { - *isnum = (n != 0 || lua_isnumber(L, i)); - } - return n; -} - -inline static void push_package_table(lua_State *L) { - lua_pushliteral(L, PACKAGE_KEY); - lua_rawget(L, LUA_REGISTRYINDEX); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - /* try to get package table from globals */ - lua_pushliteral(L, "package"); - lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_istable(L, -1)) { - lua_pushliteral(L, PACKAGE_KEY); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - } - } -} - -inline void lua_getuservalue(lua_State *L, int i) { - luaL_checktype(L, i, LUA_TUSERDATA); - luaL_checkstack(L, 2, "not enough stack slots"); - lua_getfenv(L, i); - lua_pushvalue(L, LUA_GLOBALSINDEX); - if (lua_rawequal(L, -1, -2)) { - lua_pop(L, 1); - lua_pushnil(L); - lua_replace(L, -2); - } - else { - lua_pop(L, 1); - push_package_table(L); - if (lua_rawequal(L, -1, -2)) { - lua_pop(L, 1); - lua_pushnil(L); - lua_replace(L, -2); - } - else - lua_pop(L, 1); - } -} - -inline void lua_setuservalue(lua_State *L, int i) { - luaL_checktype(L, i, LUA_TUSERDATA); - if (lua_isnil(L, -1)) { - luaL_checkstack(L, 1, "not enough stack slots"); - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_replace(L, -2); - } - lua_setfenv(L, i); -} - -/* -** Adapted from Lua 5.2.0 -*/ -inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup + 1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup + 1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ - } - lua_pop(L, nup); /* remove upvalues */ -} - -inline void luaL_setmetatable(lua_State *L, const char *tname) { - luaL_checkstack(L, 1, "not enough stack slots"); - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - -inline int luaL_getsubtable(lua_State *L, int i, const char *name) { - int abs_i = lua_absindex(L, i); - luaL_checkstack(L, 3, "not enough stack slots"); - lua_pushstring(L, name); - lua_gettable(L, abs_i); - if (lua_istable(L, -1)) - return 1; - lua_pop(L, 1); - lua_newtable(L); - lua_pushstring(L, name); - lua_pushvalue(L, -2); - lua_settable(L, abs_i); - return 0; -} - -#ifndef SOL_LUAJIT -inline static int countlevels(lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le) / 2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; -} - -inline static int findfield(lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - lua_remove(L, -2); /* remove table (but keep name) */ - lua_pushliteral(L, "."); - lua_insert(L, -2); /* place '.' between the two names */ - lua_concat(L, 3); - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ -} - -inline static int pushglobalfuncname(lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - if (findfield(L, top + 1, 2)) { - lua_copy(L, -1, top + 1); /* move name to proper place */ - lua_pop(L, 2); /* remove pushed values */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } -} - -inline static void pushfuncname(lua_State *L, lua_Debug *ar) { - if (*ar->namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, "function " LUA_QS, ar->name); - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what == 'C') { - if (pushglobalfuncname(L, ar)) { - lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else - lua_pushliteral(L, "?"); - } - else - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); -} - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -inline void luaL_traceback(lua_State *L, lua_State *L1, - const char *msg, int level) { - lua_Debug ar; - int top = lua_gettop(L); - int numlevels = countlevels(L1); - int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; - if (msg) lua_pushfstring(L, "%s\n", msg); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level == mark) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = numlevels - LEVELS2; /* and skip to last ones */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - lua_pushliteral(L, " in "); - pushfuncname(L, &ar); - lua_concat(L, lua_gettop(L) - top); - } - } - lua_concat(L, lua_gettop(L) - top); -} -#endif - -inline const lua_Number *lua_version(lua_State *L) { - static const lua_Number version = LUA_VERSION_NUM; - if (L == NULL) return &version; - // TODO: wonky hacks to get at the inside of the incomplete type lua_State? - //else return L->l_G->version; - else return &version; -} - -inline static void luaL_checkversion_(lua_State *L, lua_Number ver) { - const lua_Number* v = lua_version(L); - if (v != lua_version(NULL)) - luaL_error(L, "multiple Lua VMs detected"); - else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - ver, *v); - /* check conversions number -> integer types */ - lua_pushnumber(L, -(lua_Number)0x1234); - if (lua_tointeger(L, -1) != -0x1234 || - lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) - luaL_error(L, "bad conversion number->int;" - " must recompile Lua with proper settings"); - lua_pop(L, 1); -} - -inline void luaL_checkversion(lua_State* L) { - luaL_checkversion_(L, LUA_VERSION_NUM); -} - -#ifndef SOL_LUAJIT -inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - char buf[1024]; -#if defined(__GLIBC__) || defined(_POSIX_VERSION) - strerror_r(en, buf, 1024); -#else - strerror_s(buf, 1024, en); -#endif - lua_pushnil(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, buf); - else - lua_pushstring(L, buf); - lua_pushnumber(L, (lua_Number)en); - return 3; - } -} -#endif // luajit -#endif // Lua 5.0 or Lua 5.1 - -#if SOL_LUA_VERSION == 501 - -typedef LUAI_INT32 LUA_INT32; - -/********************************************************************/ -/* extract of 5.2's luaconf.h */ -/* detects proper defines for faster unsigned<->number conversion */ -/* see copyright notice at the end of this file */ -/********************************************************************/ - -#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_WIN /* enable goodies for regular Windows platforms */ -#endif - -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ - -/* Microsoft compiler on a Pentium (32 bit) ? */ -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ - -#define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - -/* pentium 32 bits? */ -#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEELL -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - -/* pentium 64 bits? */ -#elif defined(__x86_64) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 - -#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 - -#else /* }{ */ - -/* assume IEEE754 and a 32-bit integer type */ -#define LUA_IEEE754TRICK - -#endif /* } */ - -#endif /* } */ - -/********************************************************************/ -/* extract of 5.2's llimits.h */ -/* gives us lua_number2unsigned and lua_unsigned2number */ -/* see copyright notice just below this one here */ -/********************************************************************/ - -/********************************************************************* -* This file contains parts of Lua 5.2's source code: -* -* Copyright (C) 1994-2013 Lua.org, PUC-Rio. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*********************************************************************/ - -#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ -/* trick with Microsoft assembler for X86 */ - -#define lua_number2unsigned(i,n) \ - {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} - -#elif defined(LUA_IEEE754TRICK) /* }{ */ -/* the next trick should work on any machine using IEEE754 with -a 32-bit int type */ - -union compat52_luai_Cast { double l_d; LUA_INT32 l_p[2]; }; - -#if !defined(LUA_IEEEENDIAN) /* { */ -#define LUAI_EXTRAIEEE \ - static const union compat52_luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; -#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) -#else -#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN -#define LUAI_EXTRAIEEE /* empty */ -#endif /* } */ - -#define lua_number2int32(i,n,t) \ - { LUAI_EXTRAIEEE \ - volatile union compat52_luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ - (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } - -#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) - -#endif /* } */ - -/* the following definitions always work, but may be slow */ - -#if !defined(lua_number2unsigned) /* { */ -/* the following definition assures proper modulo behavior */ -#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) -#include <math.h> -#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) -#define lua_number2unsigned(i,n) \ - ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) -#else -#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) -#endif -#endif /* } */ - -#if !defined(lua_unsigned2number) -/* on several machines, coercion from unsigned to double is slow, -so it may be worth to avoid */ -#define lua_unsigned2number(u) \ - (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) -#endif - -/********************************************************************/ - -inline static void compat52_call_lua(lua_State *L, char const code[], size_t len, - int nargs, int nret) { - lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); - if (lua_type(L, -1) != LUA_TFUNCTION) { - lua_pop(L, 1); - if (luaL_loadbuffer(L, code, len, "=none")) - lua_error(L); - lua_pushvalue(L, -1); - lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); - } - lua_insert(L, -nargs - 1); - lua_call(L, nargs, nret); -} - -static const char compat52_arith_code[] = { - "local op,a,b=...\n" - "if op==0 then return a+b\n" - "elseif op==1 then return a-b\n" - "elseif op==2 then return a*b\n" - "elseif op==3 then return a/b\n" - "elseif op==4 then return a%b\n" - "elseif op==5 then return a^b\n" - "elseif op==6 then return -a\n" - "end\n" -}; - -inline void lua_arith(lua_State *L, int op) { - if (op < LUA_OPADD || op > LUA_OPUNM) - luaL_error(L, "invalid 'op' argument for lua_arith"); - luaL_checkstack(L, 5, "not enough stack slots"); - if (op == LUA_OPUNM) - lua_pushvalue(L, -1); - lua_pushnumber(L, op); - lua_insert(L, -3); - compat52_call_lua(L, compat52_arith_code, - sizeof(compat52_arith_code) - 1, 3, 1); -} - -static const char compat52_compare_code[] = { - "local a,b=...\n" - "return a<=b\n" -}; - -inline int lua_compare(lua_State *L, int idx1, int idx2, int op) { - int result = 0; - switch (op) { - case LUA_OPEQ: - return lua_equal(L, idx1, idx2); - case LUA_OPLT: - return lua_lessthan(L, idx1, idx2); - case LUA_OPLE: - luaL_checkstack(L, 5, "not enough stack slots"); - idx1 = lua_absindex(L, idx1); - idx2 = lua_absindex(L, idx2); - lua_pushvalue(L, idx1); - lua_pushvalue(L, idx2); - compat52_call_lua(L, compat52_compare_code, - sizeof(compat52_compare_code) - 1, 2, 1); - result = lua_toboolean(L, -1); - lua_pop(L, 1); - return result; - default: - luaL_error(L, "invalid 'op' argument for lua_compare"); - } - return 0; -} - -inline void lua_pushunsigned(lua_State *L, lua_Unsigned n) { - lua_pushnumber(L, lua_unsigned2number(n)); -} - -inline lua_Unsigned luaL_checkunsigned(lua_State *L, int i) { - lua_Unsigned result; - lua_Number n = lua_tonumber(L, i); - if (n == 0 && !lua_isnumber(L, i)) - luaL_checktype(L, i, LUA_TNUMBER); - lua_number2unsigned(result, n); - return result; -} - -inline lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum) { - lua_Unsigned result; - lua_Number n = lua_tonumberx(L, i, isnum); - lua_number2unsigned(result, n); - return result; -} - -inline lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def) { - return luaL_opt(L, luaL_checkunsigned, i, def); -} - -inline lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum) { - lua_Integer n = lua_tointeger(L, i); - if (isnum != NULL) { - *isnum = (n != 0 || lua_isnumber(L, i)); - } - return n; -} - -inline void lua_len(lua_State *L, int i) { - switch (lua_type(L, i)) { - case LUA_TSTRING: /* fall through */ - case LUA_TTABLE: - if (!luaL_callmeta(L, i, "__len")) - lua_pushnumber(L, (int)lua_objlen(L, i)); - break; - case LUA_TUSERDATA: - if (luaL_callmeta(L, i, "__len")) - break; - /* maybe fall through */ - default: - luaL_error(L, "attempt to get length of a %s value", - lua_typename(L, lua_type(L, i))); - } -} - -inline int luaL_len(lua_State *L, int i) { - int res = 0, isnum = 0; - luaL_checkstack(L, 1, "not enough stack slots"); - lua_len(L, i); - res = (int)lua_tointegerx(L, -1, &isnum); - lua_pop(L, 1); - if (!isnum) - luaL_error(L, "object length is not a number"); - return res; -} - -inline const char *luaL_tolstring(lua_State *L, int idx, size_t *len) { - if (!luaL_callmeta(L, idx, "__tostring")) { - int t = lua_type(L, idx); - switch (t) { - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - case LUA_TSTRING: - case LUA_TNUMBER: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - if (lua_toboolean(L, idx)) - lua_pushliteral(L, "true"); - else - lua_pushliteral(L, "false"); - break; - default: - lua_pushfstring(L, "%s: %p", lua_typename(L, t), - lua_topointer(L, idx)); - break; - } - } - return lua_tolstring(L, -1, len); -} - -inline void luaL_requiref(lua_State *L, char const* modname, - lua_CFunction openf, int glb) { - luaL_checkstack(L, 3, "not enough stack slots"); - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); - lua_call(L, 1, 1); - lua_getglobal(L, "package"); - if (lua_istable(L, -1) == 0) { - lua_pop(L, 1); - lua_createtable(L, 0, 16); - lua_setglobal(L, "package"); - lua_getglobal(L, "package"); - } - lua_getfield(L, -1, "loaded"); - if (lua_istable(L, -1) == 0) { - lua_pop(L, 1); - lua_createtable(L, 0, 1); - lua_setfield(L, -2, "loaded"); - lua_getfield(L, -1, "loaded"); - } - lua_replace(L, -2); - lua_pushvalue(L, -2); - lua_setfield(L, -2, modname); - lua_pop(L, 1); - if (glb) { - lua_pushvalue(L, -1); - lua_setglobal(L, modname); - } -} - -inline void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B) { - /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ - B->b.p = NULL; - B->b.L = NULL; - B->b.lvl = 0; - /* reuse the buffer from the 5.1-style luaL_Buffer though! */ - B->ptr = B->b.buffer; - B->capacity = LUAL_BUFFERSIZE; - B->nelems = 0; - B->L2 = L; -} - -inline char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s) { - if (B->capacity - B->nelems < s) { /* needs to grow */ - char* newptr = NULL; - size_t newcap = B->capacity * 2; - if (newcap - B->nelems < s) - newcap = B->nelems + s; - if (newcap < B->capacity) /* overflow */ - luaL_error(B->L2, "buffer too large"); - newptr = (char*)lua_newuserdata(B->L2, newcap); - memcpy(newptr, B->ptr, B->nelems); - if (B->ptr != B->b.buffer) - lua_replace(B->L2, -2); /* remove old buffer */ - B->ptr = newptr; - B->capacity = newcap; - } - return B->ptr + B->nelems; -} - -inline void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l) { - memcpy(luaL_prepbuffsize(B, l), s, l); - luaL_addsize(B, l); -} - -inline void luaL_addvalue(luaL_Buffer_52 *B) { - size_t len = 0; - const char *s = lua_tolstring(B->L2, -1, &len); - if (!s) - luaL_error(B->L2, "cannot convert value to string"); - if (B->ptr != B->b.buffer) - lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ - luaL_addlstring(B, s, len); - lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); -} - -inline void luaL_pushresult(luaL_Buffer_52 *B) { - lua_pushlstring(B->L2, B->ptr, B->nelems); - if (B->ptr != B->b.buffer) - lua_replace(B->L2, -2); /* remove userdata buffer */ -} - -#endif /* SOL_LUA_VERSION == 501 */ - -#endif // SOL_5_X_X_INL -// end of sol/compatibility/5.x.x.inl - -#ifdef __cplusplus -} -#endif - -#endif // SOL_NO_COMPAT - -// end of sol/compatibility.hpp - -// beginning of sol/in_place.hpp - -namespace sol { - - namespace detail { - struct in_place_of {}; - template <std::size_t I> - struct in_place_of_i {}; - template <typename T> - struct in_place_of_t {}; - } // detail - - struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; }; - constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); } - template <typename T> - constexpr inline in_place_tag in_place(detail::in_place_of_t<T>) { return in_place_tag(in_place_tag::init()); } - template <std::size_t I> - constexpr inline in_place_tag in_place(detail::in_place_of_i<I>) { return in_place_tag(in_place_tag::init()); } - - using in_place_t = in_place_tag(&)(detail::in_place_of); - template <typename T> - using in_place_type_t = in_place_tag(&)(detail::in_place_of_t<T>); - template <std::size_t I> - using in_place_index_t = in_place_tag(&)(detail::in_place_of_i<I>); - -} // sol - -// end of sol/in_place.hpp - -#if defined(SOL_USE_BOOST) -#include <boost/optional.hpp> -#else -// beginning of sol/optional_implementation.hpp - -# ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP -# define SOL_OPTIONAL_IMPLEMENTATION_HPP - -# include <utility> -# include <type_traits> -# include <initializer_list> -# include <cassert> -# include <functional> -# include <string> -# include <stdexcept> -#ifdef SOL_NO_EXCEPTIONS -#include <cstdlib> -#endif // Exceptions - -# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false - -# if defined __GNUC__ // NOTE: GNUC is also defined for Clang -# if (__GNUC__ >= 5) -# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# endif -# endif -# -# if defined __clang_major__ -# if (__clang_major__ == 3 && __clang_minor__ >= 5) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# elif (__clang_major__ > 3) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# endif -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# endif -# endif -# -# if defined _MSC_VER -# if (_MSC_VER >= 1900) -# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# endif -# endif - -# if defined __clang__ -# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif -# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif - -# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 -# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr -# else -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 -# define OPTIONAL_CONSTEXPR_INIT_LIST -# endif - -# if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || (defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)) -# define OPTIONAL_HAS_MOVE_ACCESSORS 1 -# else -# define OPTIONAL_HAS_MOVE_ACCESSORS 0 -# endif - -# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr -# if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || ((defined __cplusplus) && (__cplusplus == 201103L)) -# define OPTIONAL_MUTABLE_CONSTEXPR -# else -# define OPTIONAL_MUTABLE_CONSTEXPR constexpr -# endif - -# if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -#pragma warning( push ) -#pragma warning( disable : 4814 ) -#endif - -namespace sol { - - // BEGIN workaround for missing is_trivially_destructible -# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it: it is already there -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - template <typename T> - using is_trivially_destructible = ::std::has_trivial_destructor<T>; -# endif - // END workaround for missing is_trivially_destructible - -# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - - template <class T> - struct is_nothrow_move_constructible - { - constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value; - }; - - template <class T, class U> - struct is_assignable - { - template <class X, class Y> - constexpr static bool has_assign(...) { return false; } - - template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) > - // the comma operator is necessary for the cases where operator= returns void - constexpr static bool has_assign(bool) { return true; } - - constexpr static bool value = has_assign<T, U>(true); - }; - - template <class T> - struct is_nothrow_move_assignable - { - template <class X, bool has_any_move_assign> - struct has_nothrow_move_assign { - constexpr static bool value = false; - }; - - template <class X> - struct has_nothrow_move_assign<X, true> { - constexpr static bool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>()); - }; - - constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; - }; - // end workaround - -# endif - - template <class T> class optional; - - // 20.5.5, optional for lvalue reference types - template <class T> class optional<T&>; - - // workaround: std utility functions aren't constexpr yet - template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept - { - return static_cast<T&&>(t); - } - - template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept - { - static_assert(!::std::is_lvalue_reference<T>::value, "!!"); - return static_cast<T&&>(t); - } - - template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept - { - return static_cast<typename ::std::remove_reference<T>::type&&>(t); - } - -#if defined NDEBUG -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) -#else -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) -#endif - - namespace detail_ - { - - // static_addressof: a constexpr version of addressof - template <typename T> - struct has_overloaded_addressof - { - template <class X> - constexpr static bool has_overload(...) { return false; } - - template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) > - constexpr static bool has_overload(bool) { return true; } - - constexpr static bool value = has_overload<T>(true); - }; - - template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> - constexpr T* static_addressof(T& ref) - { - return &ref; - } - - template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> - T* static_addressof(T& ref) - { - return ::std::addressof(ref); - } - - // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A - template <class U> - constexpr U convert(U v) { return v; } - - } // namespace detail_ - - constexpr struct trivial_init_t {} trivial_init{}; - - // 20.5.7, Disengaged state indicator - struct nullopt_t - { - struct init {}; - constexpr explicit nullopt_t(init) {} - }; - constexpr nullopt_t nullopt{ nullopt_t::init() }; - - // 20.5.8, class bad_optional_access - class bad_optional_access : public ::std::logic_error { - public: - explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {} - explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {} - }; - - template <class T> - struct alignas(T) optional_base { - char storage_[sizeof(T)]; - bool init_; - - constexpr optional_base() noexcept : storage_(), init_(false) {}; - - explicit optional_base(const T& v) : storage_(), init_(true) { - new (&storage())T(v); - } - - explicit optional_base(T&& v) : storage_(), init_(true) { - new (&storage())T(constexpr_move(v)); - } - - template <class... Args> explicit optional_base(in_place_t, Args&&... args) - : init_(true), storage_() { - new (&storage())T(constexpr_forward<Args>(args)...); - } - - template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> - explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) - : init_(true), storage_() { - new (&storage())T(il, constexpr_forward<Args>(args)...); - } -#if defined __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif - T& storage() { - return *reinterpret_cast<T*>(&storage_[0]); - } - - constexpr const T& storage() const { - return *reinterpret_cast<T const*>(&storage_[0]); - } -#if defined __GNUC__ -#pragma GCC diagnostic pop -#endif - - ~optional_base() { if (init_) { storage().T::~T(); } } - }; - -#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ - // Sorry, GCC 4.x; you're just a piece of shit - template <typename T> - using constexpr_optional_base = optional_base<T>; -#else - template <class T> - struct alignas(T) constexpr_optional_base { - char storage_[sizeof(T)]; - bool init_; - constexpr constexpr_optional_base() noexcept : storage_(), init_(false) {} - - explicit constexpr constexpr_optional_base(const T& v) : storage_(), init_(true) { - new (&storage())T(v); - } - - explicit constexpr constexpr_optional_base(T&& v) : storage_(), init_(true) { - new (&storage())T(constexpr_move(v)); - } - - template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) - : init_(true), storage_() { - new (&storage())T(constexpr_forward<Args>(args)...); - } - - template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) - : init_(true), storage_() { - new (&storage())T(il, constexpr_forward<Args>(args)...); - } - -#if defined __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif - T& storage() { - return (*reinterpret_cast<T*>(&storage_[0])); - } - - constexpr const T& storage() const { - return (*reinterpret_cast<T const*>(&storage_[0])); - } -#if defined __GNUC__ -#pragma GCC diagnostic pop -#endif - - ~constexpr_optional_base() = default; - }; -#endif - - template <class T> - using OptionalBase = typename ::std::conditional< - ::std::is_trivially_destructible<T>::value, - constexpr_optional_base<typename ::std::remove_const<T>::type>, - optional_base<typename ::std::remove_const<T>::type> - >::type; - - template <class T> - class optional : private OptionalBase<T> - { - static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T"); - static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T"); - - constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; } - typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); } - constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); } - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); } - OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); } -# else - T& contained_val() & { return OptionalBase<T>::storage(); } - T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); } -# endif -# else - constexpr const T& contained_val() const { return OptionalBase<T>::storage(); } - T& contained_val() { return OptionalBase<T>::storage(); } -# endif - - void clear() noexcept { - if (initialized()) dataptr()->T::~T(); - OptionalBase<T>::init_ = false; - } - - template <class... Args> - void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...))) - { - assert(!OptionalBase<T>::init_); - ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...); - OptionalBase<T>::init_ = true; - } - - template <class U, class... Args> - void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...))) - { - assert(!OptionalBase<T>::init_); - ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...); - OptionalBase<T>::init_ = true; - } - - public: - typedef T value_type; - - // 20.5.5.1, constructors - constexpr optional() noexcept : OptionalBase<T>() {}; - constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {}; - - optional(const optional& rhs) - : OptionalBase<T>() - { - if (rhs.initialized()) { - ::new (static_cast<void*>(dataptr())) T(*rhs); - OptionalBase<T>::init_ = true; - } - } - - optional(const optional<T&>& rhs) : optional() - { - if (rhs) { - ::new (static_cast<void*>(dataptr())) T(*rhs); - OptionalBase<T>::init_ = true; - } - } - - optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value) - : OptionalBase<T>() - { - if (rhs.initialized()) { - ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs)); - OptionalBase<T>::init_ = true; - } - } - - constexpr optional(const T& v) : OptionalBase<T>(v) {} - - constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {} - - template <class... Args> - explicit constexpr optional(in_place_t, Args&&... args) - : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {} - - template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args) - : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {} - - // 20.5.4.2, Destructor - ~optional() = default; - - // 20.5.4.3, assignment - optional& operator=(nullopt_t) noexcept - { - clear(); - return *this; - } - - optional& operator=(const optional& rhs) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); - else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; - return *this; - } - - optional& operator=(optional&& rhs) - noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs)); - else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs); - return *this; - } - - template <class U> - auto operator=(U&& v) - -> typename ::std::enable_if - < - ::std::is_same<typename ::std::decay<U>::type, T>::value, - optional& - >::type - { - if (initialized()) { contained_val() = ::std::forward<U>(v); } - else { initialize(::std::forward<U>(v)); } - return *this; - } - - template <class... Args> - void emplace(Args&&... args) - { - clear(); - initialize(::std::forward<Args>(args)...); - } - - template <class U, class... Args> - void emplace(::std::initializer_list<U> il, Args&&... args) - { - clear(); - initialize<U, Args...>(il, ::std::forward<Args>(args)...); - } - - // 20.5.4.4, Swap - void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>()))) - { - if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); } - else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); } - else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); } - } - - // 20.5.4.5, Observers - - explicit constexpr operator bool() const noexcept { return initialized(); } - - constexpr T const* operator ->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { - assert(initialized()); - return dataptr(); - } - - constexpr T const& operator *() const& { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { - assert(initialized()); - return contained_val(); - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { - assert(initialized()); - return constexpr_move(contained_val()); - } - - constexpr T const& value() const& { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - - OPTIONAL_MUTABLE_CONSTEXPR T& value() & { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - : *(T*)nullptr; -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : std::move(*(T*)nullptr); -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - -# else - - T* operator ->() { - assert(initialized()); - return dataptr(); - } - - constexpr T const& operator *() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - T& operator *() { - assert(initialized()); - return contained_val(); - } - - constexpr T const& value() const { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - - T& value() { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can abort here - // but the others are constexpr, so we can't... - : (std::abort(), *(T*)nullptr); -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - -# endif - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - - template <class V> - constexpr T value_or(V&& v) const& - { - return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - template <class V> - OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# else - - template <class V> - T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# endif - -# else - - template <class V> - constexpr T value_or(V&& v) const - { - return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# endif - - }; - - template <class T> - class optional<T&> - { - static_assert(!::std::is_same<T, nullopt_t>::value, "bad T"); - static_assert(!::std::is_same<T, in_place_t>::value, "bad T"); - T* ref; - - public: - - // 20.5.5.1, construction/destruction - constexpr optional() noexcept : ref(nullptr) {} - - constexpr optional(nullopt_t) noexcept : ref(nullptr) {} - - constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} - - optional(T&&) = delete; - - constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} - - explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} - - explicit optional(in_place_t, T&&) = delete; - - ~optional() = default; - - // 20.5.5.2, mutation - optional& operator=(nullopt_t) noexcept { - ref = nullptr; - return *this; - } - - // optional& operator=(const optional& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - // optional& operator=(optional&& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - template <typename U> - auto operator=(U&& rhs) noexcept - -> typename ::std::enable_if - < - ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, - optional& - >::type - { - ref = rhs.ref; - return *this; - } - - template <typename U> - auto operator=(U&& rhs) noexcept - -> typename ::std::enable_if - < - !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, - optional& - >::type - = delete; - - void emplace(T& v) noexcept { - ref = detail_::static_addressof(v); - } - - void emplace(T&&) = delete; - - void swap(optional<T&>& rhs) noexcept - { - ::std::swap(ref, rhs.ref); - } - - // 20.5.5.3, observers - constexpr T* operator->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); - } - - constexpr T& operator*() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); - } - - constexpr T& value() const { - return ref ? - *ref -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; -#else - : throw bad_optional_access("bad optional access"); -#endif - } - - explicit constexpr operator bool() const noexcept { - return ref != nullptr; - } - - template <typename V> - constexpr T& value_or(V&& v) const - { - return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v)); - } - }; - - template <class T> - class optional<T&&> - { - static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); - }; - - // 20.5.8, Relational operators - template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y) - { - return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; - } - - template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y) - { - return !(x == y); - } - - template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y) - { - return (!y) ? false : (!x) ? true : *x < *y; - } - - template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y) - { - return (y < x); - } - - template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y) - { - return !(y < x); - } - - template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y) - { - return !(x < y); - } - - // 20.5.9, Comparison with nullopt - template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept - { - return (!x); - } - - template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept - { - return (!x); - } - - template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept - { - return false; - } - - template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept - { - return (!x); - } - - template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept - { - return true; - } - - template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept - { - return false; - } - - template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept - { - return true; - } - - template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept - { - return (!x); - } - - // 20.5.10, Comparison with T - template <class T> constexpr bool operator==(const optional<T>& x, const T& v) - { - return bool(x) ? *x == v : false; - } - - template <class T> constexpr bool operator==(const T& v, const optional<T>& x) - { - return bool(x) ? v == *x : false; - } - - template <class T> constexpr bool operator!=(const optional<T>& x, const T& v) - { - return bool(x) ? *x != v : true; - } - - template <class T> constexpr bool operator!=(const T& v, const optional<T>& x) - { - return bool(x) ? v != *x : true; - } - - template <class T> constexpr bool operator<(const optional<T>& x, const T& v) - { - return bool(x) ? *x < v : true; - } - - template <class T> constexpr bool operator>(const T& v, const optional<T>& x) - { - return bool(x) ? v > *x : true; - } - - template <class T> constexpr bool operator>(const optional<T>& x, const T& v) - { - return bool(x) ? *x > v : false; - } - - template <class T> constexpr bool operator<(const T& v, const optional<T>& x) - { - return bool(x) ? v < *x : false; - } - - template <class T> constexpr bool operator>=(const optional<T>& x, const T& v) - { - return bool(x) ? *x >= v : false; - } - - template <class T> constexpr bool operator<=(const T& v, const optional<T>& x) - { - return bool(x) ? v <= *x : false; - } - - template <class T> constexpr bool operator<=(const optional<T>& x, const T& v) - { - return bool(x) ? *x <= v : true; - } - - template <class T> constexpr bool operator>=(const T& v, const optional<T>& x) - { - return bool(x) ? v >= *x : true; - } - - // Comparison of optional<T&> with T - template <class T> constexpr bool operator==(const optional<T&>& x, const T& v) - { - return bool(x) ? *x == v : false; - } - - template <class T> constexpr bool operator==(const T& v, const optional<T&>& x) - { - return bool(x) ? v == *x : false; - } - - template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v) - { - return bool(x) ? *x != v : true; - } - - template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x) - { - return bool(x) ? v != *x : true; - } - - template <class T> constexpr bool operator<(const optional<T&>& x, const T& v) - { - return bool(x) ? *x < v : true; - } - - template <class T> constexpr bool operator>(const T& v, const optional<T&>& x) - { - return bool(x) ? v > *x : true; - } - - template <class T> constexpr bool operator>(const optional<T&>& x, const T& v) - { - return bool(x) ? *x > v : false; - } - - template <class T> constexpr bool operator<(const T& v, const optional<T&>& x) - { - return bool(x) ? v < *x : false; - } - - template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v) - { - return bool(x) ? *x >= v : false; - } - - template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x) - { - return bool(x) ? v <= *x : false; - } - - template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v) - { - return bool(x) ? *x <= v : true; - } - - template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x) - { - return bool(x) ? v >= *x : true; - } - - // Comparison of optional<T const&> with T - template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x == v : false; - } - - template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x) - { - return bool(x) ? v == *x : false; - } - - template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x != v : true; - } - - template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x) - { - return bool(x) ? v != *x : true; - } - - template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x < v : true; - } - - template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x) - { - return bool(x) ? v > *x : true; - } - - template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x > v : false; - } - - template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x) - { - return bool(x) ? v < *x : false; - } - - template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x >= v : false; - } - - template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x) - { - return bool(x) ? v <= *x : false; - } - - template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x <= v : true; - } - - template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x) - { - return bool(x) ? v >= *x : true; - } - - // 20.5.12, Specialized algorithms - template <class T> - void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) { - x.swap(y); - } - - template <class T> - constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) { - return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v)); - } - - template <class X> - constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) { - return optional<X&>(v.get()); - } - -} // namespace - -namespace std -{ - template <typename T> - struct hash<sol::optional<T>> { - typedef typename hash<T>::result_type result_type; - typedef sol::optional<T> argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? ::std::hash<T>{}(*arg) : result_type{}; - } - }; - - template <typename T> - struct hash<sol::optional<T&>> { - typedef typename hash<T>::result_type result_type; - typedef sol::optional<T&> argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? ::std::hash<T>{}(*arg) : result_type{}; - } - }; -} - -# if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -#pragma warning( pop ) -#endif - -# undef TR2_OPTIONAL_REQUIRES -# undef TR2_OPTIONAL_ASSERTED_EXPRESSION - -# endif // SOL_OPTIONAL_IMPLEMENTATION_HPP -// end of sol/optional_implementation.hpp - -#endif // Boost vs. Better optional - -namespace sol { - -#if defined(SOL_USE_BOOST) - template <typename T> - using optional = boost::optional<T>; - using nullopt_t = boost::none_t; - const nullopt_t nullopt = boost::none; -#endif // Boost vs. Better optional - -} // sol - -// end of sol/optional.hpp - -// beginning of sol/string_shim.hpp - -namespace sol { - namespace string_detail { - struct string_shim { - std::size_t s; - const char* p; - - string_shim(const std::string& r) : string_shim(r.data(), r.size()) {} - string_shim(const char* ptr) : string_shim(ptr, std::char_traits<char>::length(ptr)) {} - string_shim(const char* ptr, std::size_t sz) : s(sz), p(ptr) {} - - static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) { - int result = std::char_traits<char>::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); - if (result != 0) - return result; - if (lhs_sz < rhs_sz) - return -1; - if (lhs_sz > rhs_sz) - return 1; - return 0; - } - - const char* c_str() const { - return p; - } - - const char* data() const { - return p; - } - - std::size_t size() const { - return s; - } - - bool operator==(const string_shim& r) const { - return compare(p, s, r.data(), r.size()) == 0; - } - - bool operator==(const char* r) const { - return compare(r, std::char_traits<char>::length(r), p, s) == 0; - } - - bool operator==(const std::string& r) const { - return compare(r.data(), r.size(), p, s) == 0; - } - - bool operator!=(const string_shim& r) const { - return !(*this == r); - } - - bool operator!=(const char* r) const { - return !(*this == r); - } - - bool operator!=(const std::string& r) const { - return !(*this == r); - } - }; - } -} - -// end of sol/string_shim.hpp - -#include <array> - -namespace sol { - namespace detail { -#ifdef SOL_NO_EXCEPTIONS - template <lua_CFunction f> - int static_trampoline(lua_State* L) { - return f(L); - } - - template <typename Fx, typename... Args> - int trampoline(lua_State* L, Fx&& f, Args&&... args) { - return f(L, std::forward<Args>(args)...); - } - - inline int c_trampoline(lua_State* L, lua_CFunction f) { - return trampoline(L, f); - } -#else - template <lua_CFunction f> - int static_trampoline(lua_State* L) { - try { - return f(L); - } - catch (const char *s) { - lua_pushstring(L, s); - } - catch (const std::exception& e) { - lua_pushstring(L, e.what()); - } -#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) - catch (...) { - lua_pushstring(L, "caught (...) exception"); - } -#endif - return lua_error(L); - } - - template <typename Fx, typename... Args> - int trampoline(lua_State* L, Fx&& f, Args&&... args) { - try { - return f(L, std::forward<Args>(args)...); - } - catch (const char *s) { - lua_pushstring(L, s); - } - catch (const std::exception& e) { - lua_pushstring(L, e.what()); - } -#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) - catch (...) { - lua_pushstring(L, "caught (...) exception"); - } -#endif - return lua_error(L); - } - - inline int c_trampoline(lua_State* L, lua_CFunction f) { - return trampoline(L, f); - } -#endif // Exceptions vs. No Exceptions - - template <typename T> - struct unique_usertype {}; - - template <typename T> - struct implicit_wrapper { - T& item; - implicit_wrapper(T* item) : item(*item) {} - implicit_wrapper(T& item) : item(item) {} - operator T& () { - return item; - } - operator T* () { - return std::addressof(item); - } - }; - } // detail - - struct lua_nil_t {}; - const lua_nil_t lua_nil{}; - inline bool operator==(lua_nil_t, lua_nil_t) { return true; } - inline bool operator!=(lua_nil_t, lua_nil_t) { return false; } -#ifndef __OBJC__ - typedef lua_nil_t nil_t; - const nil_t nil{}; -#endif - - struct metatable_key_t {}; - const metatable_key_t metatable_key = {}; - - struct no_metatable_t {}; - const no_metatable_t no_metatable = {}; - - typedef std::remove_pointer_t<lua_CFunction> lua_r_CFunction; - - template <typename T> - struct unique_usertype_traits { - typedef T type; - typedef T actual_type; - static const bool value = false; - - template <typename U> - static bool is_null(U&&) { - return false; - } - - template <typename U> - static auto get(U&& value) { - return std::addressof(detail::deref(value)); - } - }; - - template <typename T> - struct unique_usertype_traits<std::shared_ptr<T>> { - typedef T type; - typedef std::shared_ptr<T> actual_type; - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - - template <typename T, typename D> - struct unique_usertype_traits<std::unique_ptr<T, D>> { - typedef T type; - typedef std::unique_ptr<T, D> actual_type; - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - - template <typename T> - struct non_null {}; - - template <typename... Args> - struct function_sig {}; - - struct upvalue_index { - int index; - upvalue_index(int idx) : index(lua_upvalueindex(idx)) {} - operator int() const { return index; } - }; - - struct raw_index { - int index; - raw_index(int i) : index(i) {} - operator int() const { return index; } - }; - - struct absolute_index { - int index; - absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {} - operator int() const { return index; } - }; - - struct ref_index { - int index; - ref_index(int idx) : index(idx) {} - operator int() const { return index; } - }; - - struct lightuserdata_value { - void* value; - lightuserdata_value(void* data) : value(data) {} - operator void*() const { return value; } - }; - - struct userdata_value { - void* value; - userdata_value(void* data) : value(data) {} - operator void*() const { return value; } - }; - - template <typename L> - struct light { - L* value; - - light(L& x) : value(std::addressof(x)) {} - light(L* x) : value(x) {} - light(void* x) : value(static_cast<L*>(x)) {} - operator L* () const { return value; } - operator L& () const { return *value; } - }; - - template <typename T> - auto make_light(T& l) { - typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L; - return light<L>(l); - } - - template <typename U> - struct user { - U value; - - user(U x) : value(std::move(x)) {} - operator U* () { return std::addressof(value); } - operator U& () { return value; } - operator const U& () const { return value; } - }; - - template <typename T> - auto make_user(T&& u) { - typedef meta::unwrapped_t<meta::unqualified_t<T>> U; - return user<U>(std::forward<T>(u)); - } - - template <typename T> - struct metatable_registry_key { - T key; - - metatable_registry_key(T key) : key(std::forward<T>(key)) {} - }; - - template <typename T> - auto meta_registry_key(T&& key) { - typedef meta::unqualified_t<T> K; - return metatable_registry_key<K>(std::forward<T>(key)); - } - - template <typename... Upvalues> - struct closure { - lua_CFunction c_function; - std::tuple<Upvalues...> upvalues; - closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward<Upvalues>(targetupvalues)...) {} - }; - - template <> - struct closure<> { - lua_CFunction c_function; - int upvalues; - closure(lua_CFunction f, int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) {} - }; - - typedef closure<> c_closure; - - template <typename... Args> - closure<Args...> make_closure(lua_CFunction f, Args&&... args) { - return closure<Args...>(f, std::forward<Args>(args)...); - } - - template <typename Sig, typename... Ps> - struct function_arguments { - std::tuple<Ps...> arguments; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, function_arguments>> = meta::enabler> - function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - - template <typename Sig = function_sig<>, typename... Args> - auto as_function(Args&&... args) { - return function_arguments<Sig, std::decay_t<Args>...>(std::forward<Args>(args)...); - } - - template <typename Sig = function_sig<>, typename... Args> - auto as_function_reference(Args&&... args) { - return function_arguments<Sig, Args...>(std::forward<Args>(args)...); - } - - template <typename T> - struct as_table_t { - T source; - template <typename... Args> - as_table_t(Args&&... args) : source(std::forward<Args>(args)...) {} - - operator std::add_lvalue_reference_t<T> () { - return source; - } - }; - - template <typename T> - as_table_t<T> as_table(T&& container) { - return as_table_t<T>(std::forward<T>(container)); - } - - struct this_state { - lua_State* L; - operator lua_State* () const { - return L; - } - lua_State* operator-> () const { - return L; - } - }; - - enum class call_syntax { - dot = 0, - colon = 1 - }; - - enum class call_status : int { - ok = LUA_OK, - yielded = LUA_YIELD, - runtime = LUA_ERRRUN, - memory = LUA_ERRMEM, - handler = LUA_ERRERR, - gc = LUA_ERRGCMM - }; - - enum class thread_status : int { - ok = LUA_OK, - yielded = LUA_YIELD, - runtime = LUA_ERRRUN, - memory = LUA_ERRMEM, - gc = LUA_ERRGCMM, - handler = LUA_ERRERR, - dead = -1, - }; - - enum class load_status : int { - ok = LUA_OK, - syntax = LUA_ERRSYNTAX, - memory = LUA_ERRMEM, - gc = LUA_ERRGCMM, - file = LUA_ERRFILE, - }; - - enum class type : int { - none = LUA_TNONE, - lua_nil = LUA_TNIL, -#ifndef __OBJC__ - nil = lua_nil, -#endif // Objective C++ Keyword - string = LUA_TSTRING, - number = LUA_TNUMBER, - thread = LUA_TTHREAD, - boolean = LUA_TBOOLEAN, - function = LUA_TFUNCTION, - userdata = LUA_TUSERDATA, - lightuserdata = LUA_TLIGHTUSERDATA, - table = LUA_TTABLE, - poly = none | lua_nil | string | number | thread | - table | boolean | function | userdata | lightuserdata - }; - - enum class meta_function { - construct, - index, - new_index, - mode, - call, - call_function = call, - metatable, - to_string, - length, - unary_minus, - addition, - subtraction, - multiplication, - division, - modulus, - power_of, - involution = power_of, - concatenation, - equal_to, - less_than, - less_than_or_equal_to, - garbage_collect, - floor_division, - bitwise_left_shift, - bitwise_right_shift, - bitwise_not, - bitwise_and, - bitwise_or, - bitwise_xor, - pairs, - next - }; - - typedef meta_function meta_method; - - const std::array<std::string, 2> meta_variable_names = { { - "__index", - "__newindex", - } }; - - const std::array<std::string, 29> meta_function_names = { { - "new", - "__index", - "__newindex", - "__mode", - "__call", - "__mt", - "__tostring", - "__len", - "__unm", - "__add", - "__sub", - "__mul", - "__div", - "__mod", - "__pow", - "__concat", - "__eq", - "__lt", - "__le", - "__gc", - - "__idiv", - "__shl", - "__shr", - "__bnot", - "__band", - "__bor", - "__bxor", - - "__pairs", - "__next" - } }; - - inline const std::string& name_of(meta_function mf) { - return meta_function_names[static_cast<int>(mf)]; - } - - inline type type_of(lua_State* L, int index) { - return static_cast<type>(lua_type(L, index)); - } - - inline int type_panic(lua_State* L, int index, type expected, type actual) { - return luaL_error(L, "stack index %d, expected %s, received %s", index, - expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)), - expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(actual)) - ); - } - - // Specify this function as the handler for lua::check if you know there's nothing wrong - inline int no_panic(lua_State*, int, type, type) noexcept { - return 0; - } - - inline void type_error(lua_State* L, int expected, int actual) { - luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); - } - - inline void type_error(lua_State* L, type expected, type actual) { - type_error(L, static_cast<int>(expected), static_cast<int>(actual)); - } - - inline void type_assert(lua_State* L, int index, type expected, type actual) { - if (expected != type::poly && expected != actual) { - type_panic(L, index, expected, actual); - } - } - - inline void type_assert(lua_State* L, int index, type expected) { - type actual = type_of(L, index); - type_assert(L, index, expected, actual); - } - - inline std::string type_name(lua_State* L, type t) { - return lua_typename(L, static_cast<int>(t)); - } - - class reference; - class stack_reference; - template <typename Table, typename Key> - struct proxy; - template<typename T> - class usertype; - template <bool, typename T> - class basic_table_core; - template <bool b> - using table_core = basic_table_core<b, reference>; - template <bool b> - using stack_table_core = basic_table_core<b, stack_reference>; - typedef table_core<false> table; - typedef table_core<true> global_table; - typedef stack_table_core<false> stack_table; - typedef stack_table_core<true> stack_global_table; - template <typename T> - class basic_function; - template <typename T> - class basic_protected_function; - using function = basic_function<reference>; - using protected_function = basic_protected_function<reference>; - using stack_function = basic_function<stack_reference>; - using stack_protected_function = basic_protected_function<stack_reference>; - template <typename base_t> - class basic_object; - template <typename base_t> - class basic_userdata; - template <typename base_t> - class basic_lightuserdata; - struct variadic_args; - using object = basic_object<reference>; - using stack_object = basic_object<stack_reference>; - using userdata = basic_userdata<reference>; - using stack_userdata = basic_userdata<stack_reference>; - using lightuserdata = basic_lightuserdata<reference>; - using stack_lightuserdata = basic_lightuserdata<stack_reference>; - class coroutine; - class thread; - struct variadic_args; - struct this_state; - - namespace detail { - template <typename T, typename = void> - struct lua_type_of : std::integral_constant<type, type::userdata> {}; - - template <> - struct lua_type_of<std::string> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<std::wstring> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<std::u16string> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<std::u32string> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<char[N]> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<wchar_t[N]> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<char16_t[N]> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<char32_t[N]> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<char> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<wchar_t> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<char16_t> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<char32_t> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<const char*> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<string_detail::string_shim> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<bool> : std::integral_constant<type, type::boolean> {}; - - template <> - struct lua_type_of<lua_nil_t> : std::integral_constant<type, type::lua_nil> { }; - - template <> - struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> { }; - - template <> - struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> { }; - - template <> - struct lua_type_of<sol::error> : std::integral_constant<type, type::string> { }; - - template <bool b, typename Base> - struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> { }; - - template <> - struct lua_type_of<reference> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {}; - - template <typename Base> - struct lua_type_of<basic_object<Base>> : std::integral_constant<type, type::poly> {}; - - template <typename... Args> - struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> {}; - - template <typename A, typename B> - struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<void*> : std::integral_constant<type, type::lightuserdata> {}; - - template <> - struct lua_type_of<lightuserdata_value> : std::integral_constant<type, type::lightuserdata> {}; - - template <> - struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {}; - - template <typename T> - struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> {}; - - template <typename T> - struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> {}; - - template <typename Base> - struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {}; - - template <typename Base> - struct lua_type_of<basic_userdata<Base>> : std::integral_constant<type, type::userdata> {}; - - template <> - struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> {}; - - template <> - struct lua_type_of<std::remove_pointer_t<lua_CFunction>> : std::integral_constant<type, type::function> {}; - - template <typename Base> - struct lua_type_of<basic_function<Base>> : std::integral_constant<type, type::function> {}; - - template <typename Base> - struct lua_type_of<basic_protected_function<Base>> : std::integral_constant<type, type::function> {}; - - template <> - struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {}; - - template <> - struct lua_type_of<thread> : std::integral_constant<type, type::thread> {}; - - template <typename Signature> - struct lua_type_of<std::function<Signature>> : std::integral_constant<type, type::function> {}; - - template <typename T> - struct lua_type_of<optional<T>> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<variadic_args> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<this_state> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<type> : std::integral_constant<type, type::poly> {}; - - template <typename T> - struct lua_type_of<T*> : std::integral_constant<type, type::userdata> {}; - - template <typename T> - struct lua_type_of<T, std::enable_if_t<std::is_arithmetic<T>::value>> : std::integral_constant<type, type::number> {}; - - template <typename T> - struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {}; - - template <typename T, typename C = void> - struct is_container : std::false_type {}; - - template <typename T> - struct is_container<T, std::enable_if_t<meta::has_begin_end<meta::unqualified_t<T>>::value>> : std::true_type {}; - - template <> - struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {}; - - template <typename C, C v, template <typename...> class V, typename... Args> - struct accumulate : std::integral_constant<C, v> {}; - - template <typename C, C v, template <typename...> class V, typename T, typename... Args> - struct accumulate<C, v, V, T, Args...> : accumulate<C, v + V<T>::value, V, Args...> {}; - } // detail - - template <typename T> - struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {}; - - template <typename T> - struct lua_type_of : detail::lua_type_of<T> {}; - - template <typename T> - struct lua_size : std::integral_constant<int, 1> { }; - - template <typename A, typename B> - struct lua_size<std::pair<A, B>> : std::integral_constant<int, lua_size<A>::value + lua_size<B>::value> { }; - - template <typename... Args> - struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> { }; - - template <typename T> - struct is_lua_primitive : std::integral_constant<bool, - type::userdata != lua_type_of<meta::unqualified_t<T>>::value - || (lua_size<T>::value > 1) - || std::is_base_of<reference, meta::unqualified_t<T>>::value - || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value - || meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>::value - || meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value - > { }; - - template <typename T> - struct is_lua_reference : std::integral_constant<bool, - std::is_base_of<reference, meta::unqualified_t<T>>::value - || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value - || meta::is_specialization_of<proxy, meta::unqualified_t<T>>::value - > { }; - - template <typename T> - struct is_lua_primitive<T*> : std::true_type {}; - template <typename T> - struct is_lua_primitive<std::reference_wrapper<T>> : std::true_type { }; - template <typename T> - struct is_lua_primitive<user<T>> : std::true_type { }; - template <typename T> - struct is_lua_primitive<light<T>> : is_lua_primitive<T*> { }; - template <typename T> - struct is_lua_primitive<optional<T>> : std::true_type {}; - template <> - struct is_lua_primitive<userdata_value> : std::true_type {}; - template <> - struct is_lua_primitive<lightuserdata_value> : std::true_type {}; - template <typename T> - struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> {}; - - template <typename T> - struct is_proxy_primitive : is_lua_primitive<T> { }; - - template <typename T> - struct is_transparent_argument : std::false_type {}; - - template <> - struct is_transparent_argument<this_state> : std::true_type {}; - - template <> - struct is_transparent_argument<variadic_args> : std::true_type {}; - - template <typename T> - struct is_variadic_arguments : std::is_same<T, variadic_args> {}; - - template <typename Signature> - struct lua_bind_traits : meta::bind_traits<Signature> { - private: - typedef meta::bind_traits<Signature> base_t; - public: - typedef std::integral_constant<bool, meta::count_for<is_transparent_argument, typename base_t::args_list>::value != 0> runtime_variadics_t; - static const std::size_t true_arity = base_t::arity; - static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; - static const std::size_t true_free_arity = base_t::free_arity; - static const std::size_t free_arity = base_t::free_arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; - }; - - template <typename T> - struct is_table : std::false_type {}; - template <bool x, typename T> - struct is_table<basic_table_core<x, T>> : std::true_type {}; - - template <typename T> - struct is_function : std::false_type {}; - template <typename T> - struct is_function<basic_function<T>> : std::true_type {}; - template <typename T> - struct is_function<basic_protected_function<T>> : std::true_type {}; - - template <typename T> - struct is_lightuserdata : std::false_type {}; - template <typename T> - struct is_lightuserdata<basic_lightuserdata<T>> : std::true_type {}; - - template <typename T> - struct is_userdata : std::false_type {}; - template <typename T> - struct is_userdata<basic_userdata<T>> : std::true_type {}; - - template <typename T> - struct is_container : detail::is_container<T>{}; - - template<typename T> - inline type type_of() { - return lua_type_of<meta::unqualified_t<T>>::value; - } -} // sol - -// end of sol/types.hpp - -// beginning of sol/stack_reference.hpp - -namespace sol { - class stack_reference { - private: - lua_State* L = nullptr; - int index = 0; - - protected: - int registry_index() const noexcept { - return LUA_NOREF; - } - - public: - stack_reference() noexcept = default; - stack_reference(lua_nil_t) noexcept : stack_reference() {}; - stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {} - stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {} - stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {} - stack_reference(lua_State* L, ref_index i) noexcept = delete; - stack_reference(stack_reference&& o) noexcept = default; - stack_reference& operator=(stack_reference&&) noexcept = default; - stack_reference(const stack_reference&) noexcept = default; - stack_reference& operator=(const stack_reference&) noexcept = default; - - int push() const noexcept { - return push(lua_state()); - } - - int push(lua_State* Ls) const noexcept { - lua_pushvalue(lua_state(), index); - if (Ls != lua_state()) { - lua_xmove(lua_state(), Ls, 1); - } - return 1; - } - - void pop() const noexcept { - pop(lua_state()); - } - - void pop(lua_State* Ls, int n = 1) const noexcept { - lua_pop(Ls, n); - } - - int stack_index() const noexcept { - return index; - } - - type get_type() const noexcept { - int result = lua_type(L, index); - return static_cast<type>(result); - } - - lua_State* lua_state() const noexcept { - return L; - } - - bool valid() const noexcept { - type t = get_type(); - return t != type::lua_nil && t != type::none; - } - }; - - inline bool operator== (const stack_reference& l, const stack_reference& r) { - return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0; - } - - inline bool operator!= (const stack_reference& l, const stack_reference& r) { - return !operator==(l, r); - } -} // sol - -// end of sol/stack_reference.hpp - -namespace sol { - namespace stack { - template <bool top_level> - struct push_popper_n { - lua_State* L; - int t; - push_popper_n(lua_State* luastate, int x) : L(luastate), t(x) { } - ~push_popper_n() { lua_pop(L, t); } - }; - template <> - struct push_popper_n<true> { - push_popper_n(lua_State*, int) { } - }; - template <bool top_level, typename T> - struct push_popper { - T t; - push_popper(T x) : t(x) { t.push(); } - ~push_popper() { t.pop(); } - }; - template <typename T> - struct push_popper<true, T> { - push_popper(T) {} - ~push_popper() {} - }; - template <bool top_level = false, typename T> - push_popper<top_level, T> push_pop(T&& x) { - return push_popper<top_level, T>(std::forward<T>(x)); - } - template <bool top_level = false> - push_popper_n<top_level> pop_n(lua_State* L, int x) { - return push_popper_n<top_level>(L, x); - } - } // stack - - namespace detail { - struct global_tag { } const global_{}; - } // detail - - class reference { - private: - lua_State* luastate = nullptr; // non-owning - int ref = LUA_NOREF; - - int copy() const noexcept { - if (ref == LUA_NOREF) - return LUA_NOREF; - push(); - return luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - - protected: - reference(lua_State* L, detail::global_tag) noexcept : luastate(L) { - lua_pushglobaltable(lua_state()); - ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - - int stack_index() const noexcept { - return -1; - } - - void deref() const noexcept { - luaL_unref(lua_state(), LUA_REGISTRYINDEX, ref); - } - - public: - reference() noexcept = default; - reference(lua_nil_t) noexcept : reference() {} - reference(const stack_reference& r) noexcept : reference(r.lua_state(), r.stack_index()) {} - reference(stack_reference&& r) noexcept : reference(r.lua_state(), r.stack_index()) {} - reference(lua_State* L, int index = -1) noexcept : luastate(L) { - lua_pushvalue(lua_state(), index); - ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - reference(lua_State* L, ref_index index) noexcept : luastate(L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, index.index); - ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - - ~reference() noexcept { - deref(); - } - - reference(reference&& o) noexcept { - luastate = o.luastate; - ref = o.ref; - - o.luastate = nullptr; - o.ref = LUA_NOREF; - } - - reference& operator=(reference&& o) noexcept { - luastate = o.luastate; - ref = o.ref; - - o.luastate = nullptr; - o.ref = LUA_NOREF; - - return *this; - } - - reference(const reference& o) noexcept { - luastate = o.luastate; - ref = o.copy(); - } - - reference& operator=(const reference& o) noexcept { - luastate = o.luastate; - deref(); - ref = o.copy(); - return *this; - } - - int push() const noexcept { - return push(lua_state()); - } - - int push(lua_State* Ls) const noexcept { - lua_rawgeti(Ls, LUA_REGISTRYINDEX, ref); - return 1; - } - - void pop() const noexcept { - pop(lua_state()); - } - - void pop(lua_State* Ls, int n = 1) const noexcept { - lua_pop(Ls, n); - } - - int registry_index() const noexcept { - return ref; - } - - bool valid() const noexcept { - return !(ref == LUA_NOREF || ref == LUA_REFNIL); - } - - explicit operator bool() const noexcept { - return valid(); - } - - type get_type() const noexcept { - auto pp = stack::push_pop(*this); - int result = lua_type(lua_state(), -1); - return static_cast<type>(result); - } - - lua_State* lua_state() const noexcept { - return luastate; - } - }; - - inline bool operator== (const reference& l, const reference& r) { - auto ppl = stack::push_pop(l); - auto ppr = stack::push_pop(r); - return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; - } - - inline bool operator!= (const reference& l, const reference& r) { - return !operator==(l, r); - } -} // sol - -// end of sol/reference.hpp - -// beginning of sol/stack.hpp - -// beginning of sol/stack_core.hpp - -// beginning of sol/userdata.hpp - -namespace sol { - template <typename base_t> - class basic_userdata : public base_t { - public: - basic_userdata() noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_userdata>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_userdata(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_userdata<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - type_assert(base_t::lua_state(), -1, type::userdata); - } -#endif // Safety - } - basic_userdata(const basic_userdata&) = default; - basic_userdata(basic_userdata&&) = default; - basic_userdata& operator=(const basic_userdata&) = default; - basic_userdata& operator=(basic_userdata&&) = default; - basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {} - basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} - basic_userdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::userdata); -#endif // Safety - } - basic_userdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::userdata); -#endif // Safety - } - }; - - template <typename base_t> - class basic_lightuserdata : public base_t { - public: - basic_lightuserdata() noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_lightuserdata>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_lightuserdata(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_userdata<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - type_assert(base_t::lua_state(), -1, type::lightuserdata); - } -#endif // Safety - } - basic_lightuserdata(const basic_lightuserdata&) = default; - basic_lightuserdata(basic_lightuserdata&&) = default; - basic_lightuserdata& operator=(const basic_lightuserdata&) = default; - basic_lightuserdata& operator=(basic_lightuserdata&&) = default; - basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} - basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} - basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::lightuserdata); -#endif // Safety - } - basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::lightuserdata); -#endif // Safety - } - }; - -} // sol - -// end of sol/userdata.hpp - -// beginning of sol/tie.hpp - -namespace sol { - - namespace detail { - template <typename T> - struct is_speshul : std::false_type {}; - } - - template <typename T> - struct tie_size : std::tuple_size<T> {}; - - template <typename T> - struct is_tieable : std::integral_constant<bool, (::sol::tie_size<T>::value > 0)> {}; - - template <typename... Tn> - struct tie_t : public std::tuple<std::add_lvalue_reference_t<Tn>...> { - private: - typedef std::tuple<std::add_lvalue_reference_t<Tn>...> base_t; - - template <typename T> - void set(std::false_type, T&& target) { - std::get<0>(*this) = std::forward<T>(target); - } - - template <typename T> - void set(std::true_type, T&& target) { - typedef tie_size<meta::unqualified_t<T>> value_size; - typedef tie_size<std::tuple<Tn...>> tie_size; - typedef std::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; - typedef std::make_index_sequence<indices_size::value> indices; - set_extra(detail::is_speshul<meta::unqualified_t<T>>(), indices(), std::forward<T>(target)); - } - - template <std::size_t... I, typename T> - void set_extra(std::true_type, std::index_sequence<I...>, T&& target) { - using std::get; - (void)detail::swallow{ 0, - (get<I>(static_cast<base_t&>(*this)) = get<I>(types<Tn...>(), target), 0)... - , 0 }; - } - - template <std::size_t... I, typename T> - void set_extra(std::false_type, std::index_sequence<I...>, T&& target) { - using std::get; - (void)detail::swallow{ 0, - (get<I>(static_cast<base_t&>(*this)) = get<I>(target), 0)... - , 0 }; - } - - public: - using base_t::base_t; - - template <typename T> - tie_t& operator= (T&& value) { - typedef is_tieable<meta::unqualified_t<T>> tieable; - set(tieable(), std::forward<T>(value)); - return *this; - } - - }; - - template <typename... Tn> - struct tie_size< tie_t<Tn...> > : std::tuple_size< std::tuple<Tn...> > { }; - - namespace adl_barrier_detail { - template <typename... Tn> - inline tie_t<std::remove_reference_t<Tn>...> tie(Tn&&... argn) { - return tie_t<std::remove_reference_t<Tn>...>(std::forward<Tn>(argn)...); - } - } - - using namespace adl_barrier_detail; - -} // sol - -// end of sol/tie.hpp - -// beginning of sol/stack_guard.hpp - -namespace sol { - namespace detail { - inline void stack_fail(int, int) { -#ifndef SOL_NO_EXCEPTIONS - throw error(detail::direct_error, "imbalanced stack after operation finish"); -#else - // Lol, what do you want, an error printout? :3c - // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so - // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. -#endif // No Exceptions - } - } // detail - - struct stack_guard { - lua_State* L; - int top; - std::function<void(int, int)> on_mismatch; - - stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {} - stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {} - bool check_stack(int modification = 0) const { - int bottom = lua_gettop(L) + modification; - if (top == bottom) { - return true; - } - on_mismatch(top, bottom); - return false; - } - ~stack_guard() { - check_stack(); - } - }; -} // sol - -// end of sol/stack_guard.hpp - -#include <vector> - -namespace sol { - namespace detail { - struct as_reference_tag {}; - template <typename T> - struct as_pointer_tag {}; - template <typename T> - struct as_value_tag {}; - - using special_destruct_func = void(*)(void*); - - template <typename T, typename Real> - inline void special_destruct(void* memory) { - T** pointerpointer = static_cast<T**>(memory); - special_destruct_func* dx = static_cast<special_destruct_func*>(static_cast<void*>(pointerpointer + 1)); - Real* target = static_cast<Real*>(static_cast<void*>(dx + 1)); - target->~Real(); - } - - template <typename T> - inline int unique_destruct(lua_State* L) { - void* memory = lua_touserdata(L, 1); - T** pointerpointer = static_cast<T**>(memory); - special_destruct_func& dx = *static_cast<special_destruct_func*>(static_cast<void*>(pointerpointer + 1)); - (dx)(memory); - return 0; - } - - template <typename T> - inline int user_alloc_destroy(lua_State* L) { - void* rawdata = lua_touserdata(L, 1); - T* data = static_cast<T*>(rawdata); - std::allocator<T> alloc; - alloc.destroy(data); - return 0; - } - - template <typename T> - inline int usertype_alloc_destroy(lua_State* L) { - void* rawdata = lua_touserdata(L, 1); - T** pdata = static_cast<T**>(rawdata); - T* data = *pdata; - std::allocator<T> alloc{}; - alloc.destroy(data); - return 0; - } - - template <typename T> - void reserve(T&, std::size_t) {} - - template <typename T, typename Al> - void reserve(std::vector<T, Al>& arr, std::size_t hint) { - arr.reserve(hint); - } - - template <typename T, typename Tr, typename Al> - void reserve(std::basic_string<T, Tr, Al>& arr, std::size_t hint) { - arr.reserve(hint); - } - } // detail - - namespace stack { - - template<typename T, bool global = false, bool raw = false, typename = void> - struct field_getter; - template <typename T, bool global = false, bool raw = false, typename = void> - struct probe_field_getter; - template<typename T, bool global = false, bool raw = false, typename = void> - struct field_setter; - template<typename T, typename = void> - struct getter; - template<typename T, typename = void> - struct popper; - template<typename T, typename = void> - struct pusher; - template<typename T, type = lua_type_of<T>::value, typename = void> - struct checker; - template<typename T, typename = void> - struct check_getter; - - struct probe { - bool success; - int levels; - - probe(bool s, int l) : success(s), levels(l) {} - - operator bool() const { return success; }; - }; - - struct record { - int last; - int used; - - record() : last(), used() {} - void use(int count) { - last = count; - used += count; - } - }; - - namespace stack_detail { - template <typename T> - struct strip { - typedef T type; - }; - template <typename T> - struct strip<std::reference_wrapper<T>> { - typedef T& type; - }; - template <typename T> - struct strip<user<T>> { - typedef T& type; - }; - template <typename T> - struct strip<non_null<T>> { - typedef T type; - }; - template <typename T> - using strip_t = typename strip<T>::type; - const bool default_check_arguments = -#ifdef SOL_CHECK_ARGUMENTS - true; -#else - false; -#endif - template<typename T> - inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { - return getter<meta::unqualified_t<T>>{}.get(L, index, tracking); - } - } // stack_detail - - inline bool maybe_indexable(lua_State* L, int index = -1) { - type t = type_of(L, index); - return t == type::userdata || t == type::table; - } - - template<typename T, typename... Args> - inline int push(lua_State* L, T&& t, Args&&... args) { - return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...); - } - - // overload allows to use a pusher of a specific type, but pass in any kind of args - template<typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>> - inline int push(lua_State* L, Arg&& arg, Args&&... args) { - return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); - } - - template<typename T, typename... Args> - inline int push_reference(lua_State* L, T&& t, Args&&... args) { - typedef meta::all< - std::is_lvalue_reference<T>, - meta::neg<std::is_const<T>>, - meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, - meta::neg<is_unique_usertype<meta::unqualified_t<T>>> - > use_reference_tag; - return pusher<std::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...); - } - - inline int multi_push(lua_State*) { - // do nothing - return 0; - } - - template<typename T, typename... Args> - inline int multi_push(lua_State* L, T&& t, Args&&... args) { - int pushcount = push(L, std::forward<T>(t)); - void(sol::detail::swallow{ (pushcount += sol::stack::push(L, std::forward<Args>(args)), 0)... }); - return pushcount; - } - - inline int multi_push_reference(lua_State*) { - // do nothing - return 0; - } - - template<typename T, typename... Args> - inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { - int pushcount = push_reference(L, std::forward<T>(t)); - void(sol::detail::swallow{ (pushcount += sol::stack::push_reference(L, std::forward<Args>(args)), 0)... }); - return pushcount; - } - - template <typename T, typename Handler> - bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - typedef meta::unqualified_t<T> Tu; - checker<Tu> c; - // VC++ has a bad warning here: shut it up - (void)c; - return c.check(L, index, std::forward<Handler>(handler), tracking); - } - - template <typename T, typename Handler> - bool check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check<T>(L, index, std::forward<Handler>(handler), tracking); - } - - template <typename T> - bool check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { - auto handler = no_panic; - return check<T>(L, index, handler); - } - - template<typename T, typename Handler> - inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { - return check_getter<meta::unqualified_t<T>>{}.get(L, index, std::forward<Handler>(handler), tracking); - } - - template<typename T, typename Handler> - inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check_get<T>(L, index, handler, tracking); - } - - template<typename T> - inline decltype(auto) check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { - auto handler = no_panic; - return check_get<T>(L, index, handler); - } - - namespace stack_detail { - -#ifdef SOL_CHECK_ARGUMENTS - template <typename T> - inline auto tagged_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) { - auto op = check_get<T>(L, index, type_panic, tracking); - return *std::move(op); - } -#else - template <typename T> - inline decltype(auto) tagged_get(types<T>, lua_State* L, int index, record& tracking) { - return stack_detail::unchecked_get<T>(L, index, tracking); - } -#endif - - template <typename T> - inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) { - return stack_detail::unchecked_get<optional<T>>(L, index, tracking); - } - - template <bool b> - struct check_types { - template <typename T, typename... Args, typename Handler> - static bool check(types<T, Args...>, lua_State* L, int firstargument, Handler&& handler, record& tracking) { - if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking)) - return false; - return check(types<Args...>(), L, firstargument, std::forward<Handler>(handler), tracking); - } - - template <typename Handler> - static bool check(types<>, lua_State*, int, Handler&&, record&) { - return true; - } - }; - - template <> - struct check_types<false> { - template <typename... Args, typename Handler> - static bool check(types<Args...>, lua_State*, int, Handler&&, record&) { - return true; - } - }; - - } // stack_detail - - template <bool b, typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack_detail::check_types<b>{}.check(types<meta::unqualified_t<Args>...>(), L, index, std::forward<Handler>(handler), tracking); - } - - template <bool b, typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return multi_check<b, Args...>(L, index, std::forward<Handler>(handler), tracking); - } - - template <bool b, typename... Args> - bool multi_check(lua_State* L, int index) { - auto handler = no_panic; - return multi_check<b, Args...>(L, index, handler); - } - - template <typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { - return multi_check<true, Args...>(L, index, std::forward<Handler>(handler), tracking); - } - - template <typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler) { - return multi_check<true, Args...>(L, index, std::forward<Handler>(handler)); - } - - template <typename... Args> - bool multi_check(lua_State* L, int index) { - return multi_check<true, Args...>(L, index); - } - - template<typename T> - inline decltype(auto) get(lua_State* L, int index, record& tracking) { - return stack_detail::tagged_get(types<T>(), L, index, tracking); - } - - template<typename T> - inline decltype(auto) get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { - record tracking{}; - return get<T>(L, index, tracking); - } - - template<typename T> - inline decltype(auto) pop(lua_State* L) { - return popper<meta::unqualified_t<T>>{}.pop(L); - } - - template <bool global = false, bool raw = false, typename Key> - void get_field(lua_State* L, Key&& key) { - field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key)); - } - - template <bool global = false, bool raw = false, typename Key> - void get_field(lua_State* L, Key&& key, int tableindex) { - field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, typename Key> - void raw_get_field(lua_State* L, Key&& key) { - get_field<global, true>(L, std::forward<Key>(key)); - } - - template <bool global = false, typename Key> - void raw_get_field(lua_State* L, Key&& key, int tableindex) { - get_field<global, true>(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, bool raw = false, typename Key> - probe probe_get_field(lua_State* L, Key&& key) { - return probe_field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key)); - } - - template <bool global = false, bool raw = false, typename Key> - probe probe_get_field(lua_State* L, Key&& key, int tableindex) { - return probe_field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, typename Key> - probe probe_raw_get_field(lua_State* L, Key&& key) { - return probe_get_field<global, true>(L, std::forward<Key>(key)); - } - - template <bool global = false, typename Key> - probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { - return probe_get_field<global, true>(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, bool raw = false, typename Key, typename Value> - void set_field(lua_State* L, Key&& key, Value&& value) { - field_setter<meta::unqualified_t<Key>, global, raw>{}.set(L, std::forward<Key>(key), std::forward<Value>(value)); - } - - template <bool global = false, bool raw = false, typename Key, typename Value> - void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { - field_setter<meta::unqualified_t<Key>, global, raw>{}.set(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); - } - - template <bool global = false, typename Key, typename Value> - void raw_set_field(lua_State* L, Key&& key, Value&& value) { - set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value)); - } - - template <bool global = false, typename Key, typename Value> - void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { - set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); - } - } // stack -} // sol - -// end of sol/stack_core.hpp - -// beginning of sol/stack_check.hpp - -// beginning of sol/usertype_traits.hpp - -// beginning of sol/demangle.hpp - -#include <cctype> - -namespace sol { - namespace detail { -#ifdef _MSC_VER - template <typename T> - inline std::string ctti_get_type_name() { - const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } }; - std::string name = __FUNCSIG__; - std::size_t start = name.find("get_type_name"); - if (start == std::string::npos) - start = 0; - else - start += 13; - if (start < name.size() - 1) - start += 1; - std::size_t end = name.find_last_of('>'); - if (end == std::string::npos) - end = name.size(); - name = name.substr(start, end - start); - if (name.find("struct", 0) == 0) - name.replace(0, 6, "", 0); - if (name.find("class", 0) == 0) - name.replace(0, 5, "", 0); - while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); - while (!name.empty() && std::isblank(name.back())) name.pop_back(); - - for (std::size_t r = 0; r < removals.size(); ++r) { - auto found = name.find(removals[r]); - while (found != std::string::npos) { - name.erase(found, removals[r].size()); - found = name.find(removals[r]); - } - } - - return name; - } -#elif defined(__GNUC__) || defined(__clang__) - template <typename T, class seperator_mark = int> - inline std::string ctti_get_type_name() { - const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } }; - std::string name = __PRETTY_FUNCTION__; - std::size_t start = name.find_first_of('['); - start = name.find_first_of('=', start); - std::size_t end = name.find_last_of(']'); - if (end == std::string::npos) - end = name.size(); - if (start == std::string::npos) - start = 0; - if (start < name.size() - 1) - start += 1; - name = name.substr(start, end - start); - start = name.rfind("seperator_mark"); - if (start != std::string::npos) { - name.erase(start - 2, name.length()); - } - while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); - while (!name.empty() && std::isblank(name.back())) name.pop_back(); - - for (std::size_t r = 0; r < removals.size(); ++r) { - auto found = name.find(removals[r]); - while (found != std::string::npos) { - name.erase(found, removals[r].size()); - found = name.find(removals[r]); - } - } - - return name; - } -#else -#error Compiler not supported for demangling -#endif // compilers - - template <typename T> - inline std::string demangle_once() { - std::string realname = ctti_get_type_name<T>(); - return realname; - } - - template <typename T> - inline std::string short_demangle_once() { - std::string realname = ctti_get_type_name<T>(); - // This isn't the most complete but it'll do for now...? - static const std::array<std::string, 10> ops = { { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" } }; - int level = 0; - std::ptrdiff_t idx = 0; - for (idx = static_cast<std::ptrdiff_t>(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { - if (level == 0 && realname[idx] == ':') { - break; - } - bool isleft = realname[idx] == '<'; - bool isright = realname[idx] == '>'; - if (!isleft && !isright) - continue; - bool earlybreak = false; - for (const auto& op : ops) { - std::size_t nisop = realname.rfind(op, idx); - if (nisop == std::string::npos) - continue; - std::size_t nisopidx = idx - op.size() + 1; - if (nisop == nisopidx) { - idx = static_cast<std::ptrdiff_t>(nisopidx); - earlybreak = true; - } - break; - } - if (earlybreak) { - continue; - } - level += isleft ? -1 : 1; - } - if (idx > 0) { - realname.erase(0, realname.length() < static_cast<std::size_t>(idx) ? realname.length() : idx + 1); - } - return realname; - } - - template <typename T> - inline const std::string& demangle() { - static const std::string d = demangle_once<T>(); - return d; - } - - template <typename T> - inline const std::string& short_demangle() { - static const std::string d = short_demangle_once<T>(); - return d; - } - } // detail -} // sol - -// end of sol/demangle.hpp - -namespace sol { - - template<typename T> - struct usertype_traits { - static const std::string& name() { - static const std::string& n = detail::short_demangle<T>(); - return n; - } - static const std::string& qualified_name() { - static const std::string& q_n = detail::demangle<T>(); - return q_n; - } - static const std::string& metatable() { - static const std::string m = std::string("sol.").append(detail::demangle<T>()); - return m; - } - static const std::string& user_metatable() { - static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user"); - return u_m; - } - static const std::string& user_gc_metatable() { - static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB"); - return u_g_m; - } - static const std::string& gc_table() { - static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB"); - return g_t; - } - }; - -} - -// end of sol/usertype_traits.hpp - -// beginning of sol/inheritance.hpp - -#include <atomic> - -namespace sol { - template <typename... Args> - struct base_list { }; - template <typename... Args> - using bases = base_list<Args...>; - - typedef bases<> base_classes_tag; - const auto base_classes = base_classes_tag(); - - namespace detail { - - template <typename T> - struct has_derived { - static bool value; - }; - - template <typename T> - bool has_derived<T>::value = false; - - inline std::size_t unique_id() { - static std::atomic<std::size_t> x(0); - return ++x; - } - - template <typename T> - struct id_for { - static const std::size_t value; - }; - - template <typename T> - const std::size_t id_for<T>::value = unique_id(); - - inline decltype(auto) base_class_check_key() { - static const auto& key = "class_check"; - return key; - } - - inline decltype(auto) base_class_cast_key() { - static const auto& key = "class_cast"; - return key; - } - - inline decltype(auto) base_class_index_propogation_key() { - static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; - return key; - } - - inline decltype(auto) base_class_new_index_propogation_key() { - static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; - return key; - } - - template <typename T, typename... Bases> - struct inheritance { - static bool type_check_bases(types<>, std::size_t) { - return false; - } - - template <typename Base, typename... Args> - static bool type_check_bases(types<Base, Args...>, std::size_t ti) { - return ti == id_for<Base>::value || type_check_bases(types<Args...>(), ti); - } - - static bool type_check(std::size_t ti) { - return ti == id_for<T>::value || type_check_bases(types<Bases...>(), ti); - } - - static void* type_cast_bases(types<>, T*, std::size_t) { - return nullptr; - } - - template <typename Base, typename... Args> - static void* type_cast_bases(types<Base, Args...>, T* data, std::size_t ti) { - // Make sure to convert to T first, and then dynamic cast to the proper type - return ti != id_for<Base>::value ? type_cast_bases(types<Args...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data)); - } - - static void* type_cast(void* voiddata, std::size_t ti) { - T* data = static_cast<T*>(voiddata); - return static_cast<void*>(ti != id_for<T>::value ? type_cast_bases(types<Bases...>(), data, ti) : data); - } - }; - - using inheritance_check_function = decltype(&inheritance<void>::type_check); - using inheritance_cast_function = decltype(&inheritance<void>::type_cast); - - } // detail -} // sol - -// end of sol/inheritance.hpp - -#include <utility> - -namespace sol { - namespace stack { - namespace stack_detail { - template <typename T, bool poptable = true> - inline bool check_metatable(lua_State* L, int index = -2) { - const auto& metakey = usertype_traits<T>::metatable(); - luaL_getmetatable(L, &metakey[0]); - const type expectedmetatabletype = static_cast<type>(lua_type(L, -1)); - if (expectedmetatabletype != type::lua_nil) { - if (lua_rawequal(L, -1, index) == 1) { - lua_pop(L, 1 + static_cast<int>(poptable)); - return true; - } - } - lua_pop(L, 1); - return false; - } - - template <type expected, int(*check_func)(lua_State*, int)> - struct basic_check { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = check_func(L, index) == 1; - if (!success) { - // expected type, actual type - handler(L, index, expected, type_of(L, index)); - } - return success; - } - }; - } // stack_detail - - template <typename T, type expected, typename> - struct checker { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - const type indextype = type_of(L, index); - bool success = expected == indextype; - if (!success) { - // expected type, actual type - handler(L, index, expected, indextype); - } - return success; - } - }; - - template<typename T> - struct checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = lua_isinteger(L, index) == 1; - if (!success) { - // expected type, actual type - handler(L, index, type::number, type_of(L, index)); - } - return success; - } - }; - - template<typename T> - struct checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = lua_isnumber(L, index) == 1; - if (!success) { - // expected type, actual type - handler(L, index, type::number, type_of(L, index)); - } - return success; - } - }; - - template <type expected, typename C> - struct checker<lua_nil_t, expected, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - bool success = lua_isnil(L, index); - if (success) { - tracking.use(1); - return success; - } - tracking.use(0); - success = lua_isnone(L, index); - if (!success) { - // expected type, actual type - handler(L, index, expected, type_of(L, index)); - } - return success; - } - }; - - template <type expected, typename C> - struct checker<nullopt_t, expected, C> : checker<lua_nil_t> {}; - - template <typename C> - struct checker<this_state, type::poly, C> { - template <typename Handler> - static bool check(lua_State*, int, Handler&&, record& tracking) { - tracking.use(0); - return true; - } - }; - - template <typename C> - struct checker<variadic_args, type::poly, C> { - template <typename Handler> - static bool check(lua_State*, int, Handler&&, record& tracking) { - tracking.use(0); - return true; - } - }; - - template <typename C> - struct checker<type, type::poly, C> { - template <typename Handler> - static bool check(lua_State*, int, Handler&&, record& tracking) { - tracking.use(0); - return true; - } - }; - - template <typename T, typename C> - struct checker<T, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = !lua_isnone(L, index); - if (!success) { - // expected type, actual type - handler(L, index, type::none, type_of(L, index)); - } - return success; - } - }; - - template <typename T, typename C> - struct checker<T, type::lightuserdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - bool success = t == type::userdata || t == type::lightuserdata; - if (!success) { - // expected type, actual type - handler(L, index, type::lightuserdata, t); - } - return success; - } - }; - - template <typename C> - struct checker<userdata_value, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - bool success = t == type::userdata; - if (!success) { - // expected type, actual type - handler(L, index, type::userdata, t); - } - return success; - } - }; - - template <typename T, typename C> - struct checker<user<T>, type::userdata, C> : checker<user<T>, type::lightuserdata, C> {}; - - template <typename T, typename C> - struct checker<non_null<T>, type::userdata, C> : checker<T, lua_type_of<T>::value, C> {}; - - template <typename C> - struct checker<lua_CFunction, type::function, C> : stack_detail::basic_check<type::function, lua_iscfunction> {}; - template <typename C> - struct checker<std::remove_pointer_t<lua_CFunction>, type::function, C> : checker<lua_CFunction, type::function, C> {}; - template <typename C> - struct checker<c_closure, type::function, C> : checker<lua_CFunction, type::function, C> {}; - - template <typename T, typename C> - struct checker<T, type::function, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - if (t == type::lua_nil || t == type::none || t == type::function) { - // allow for lua_nil to be returned - return true; - } - if (t != type::userdata && t != type::table) { - handler(L, index, type::function, t); - return false; - } - // Do advanced check for call-style userdata? - static const auto& callkey = name_of(meta_function::call); - if (lua_getmetatable(L, index) == 0) { - // No metatable, no __call key possible - handler(L, index, type::function, t); - return false; - } - if (lua_isnoneornil(L, -1)) { - lua_pop(L, 1); - handler(L, index, type::function, t); - return false; - } - lua_getfield(L, -1, &callkey[0]); - if (lua_isnoneornil(L, -1)) { - lua_pop(L, 2); - handler(L, index, type::function, t); - return false; - } - // has call, is definitely a function - lua_pop(L, 2); - return true; - } - }; - - template <typename T, typename C> - struct checker<T, type::table, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - if (t == type::table) { - return true; - } - if (t != type::userdata) { - handler(L, index, type::function, t); - return false; - } - return true; - } - }; - - template <typename T, typename C> - struct checker<detail::as_value_tag<T>, type::userdata, C> { - template <typename U, typename Handler> - static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { - tracking.use(1); - if (indextype != type::userdata) { - handler(L, index, type::userdata, indextype); - return false; - } - if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value) - return true; - if (lua_getmetatable(L, index) == 0) { - return true; - } - int metatableindex = lua_gettop(L); - if (stack_detail::check_metatable<U>(L, metatableindex)) - return true; - if (stack_detail::check_metatable<U*>(L, metatableindex)) - return true; - if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex)) - return true; - bool success = false; - if (detail::has_derived<T>::value) { - auto pn = stack::pop_n(L, 1); - lua_pushstring(L, &detail::base_class_check_key()[0]); - lua_rawget(L, metatableindex); - if (type_of(L, -1) != type::lua_nil) { - void* basecastdata = lua_touserdata(L, -1); - detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata; - success = ic(detail::id_for<T>::value); - } - } - if (!success) { - lua_pop(L, 1); - handler(L, index, type::userdata, indextype); - return false; - } - lua_pop(L, 1); - return true; - } - }; - - template <typename T, typename C> - struct checker<T, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - const type indextype = type_of(L, index); - return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking); - } - }; - - template <typename T, typename C> - struct checker<T*, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - const type indextype = type_of(L, index); - // Allow lua_nil to be transformed to nullptr - if (indextype == type::lua_nil) { - tracking.use(1); - return true; - } - return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename T> - struct checker<T, type::userdata, std::enable_if_t<is_unique_usertype<T>::value>> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return checker<typename unique_usertype_traits<T>::type, type::userdata>{}.check(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename T, typename C> - struct checker<std::reference_wrapper<T>, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return checker<T, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename... Args, typename C> - struct checker<std::tuple<Args...>, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack::multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename A, typename B, typename C> - struct checker<std::pair<A, B>, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack::multi_check<A, B>(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename T, typename C> - struct checker<optional<T>, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&&, record& tracking) { - type t = type_of(L, index); - if (t == type::none) { - tracking.use(0); - return true; - } - if (t == type::lua_nil) { - tracking.use(1); - return true; - } - return stack::check<T>(L, index, no_panic, tracking); - } - }; - } // stack -} // sol - -// end of sol/stack_check.hpp - -// beginning of sol/stack_get.hpp - -// beginning of sol/overload.hpp - -namespace sol { - template <typename... Functions> - struct overload_set { - std::tuple<Functions...> functions; - template <typename Arg, typename... Args, meta::disable<std::is_same<overload_set, meta::unqualified_t<Arg>>> = meta::enabler> - overload_set (Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - overload_set(const overload_set&) = default; - overload_set(overload_set&&) = default; - overload_set& operator=(const overload_set&) = default; - overload_set& operator=(overload_set&&) = default; - }; - - template <typename... Args> - decltype(auto) overload(Args&&... args) { - return overload_set<std::decay_t<Args>...>(std::forward<Args>(args)...); - } -} - -// end of sol/overload.hpp - -#ifdef SOL_CODECVT_SUPPORT -#include <codecvt> -#include <locale> -#endif - -namespace sol { - namespace stack { - - template<typename T, typename> - struct getter { - static T& get(lua_State* L, int index, record& tracking) { - return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tonumber(L, index)); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tointeger(L, index)); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tointeger(L, index)); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<std::is_enum<T>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tointegerx(L, index, nullptr)); - } - }; - - template<typename T> - struct getter<as_table_t<T>, std::enable_if_t<!meta::has_key_value_pair<meta::unqualified_t<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - typedef typename T::value_type V; - tracking.use(1); - - index = lua_absindex(L, index); - T arr; - get_field<false, true>(L, static_cast<lua_Integer>(-1), index); - int isnum; - std::size_t sizehint = static_cast<std::size_t>(lua_tointegerx(L, -1, &isnum)); - if (isnum != 0) { - detail::reserve(arr, sizehint); - } - lua_pop(L, 1); -#if SOL_LUA_VERSION >= 503 - // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 - for (lua_Integer i = 0; ; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { - for (int vi = 0; vi < lua_size<V>::value; ++vi) { - type t = static_cast<type>(lua_geti(L, index, i + vi)); - if (t == type::lua_nil) { - if (i == 0) { - continue; - } - else { - lua_pop(L, (vi + 1)); - return arr; - } - } - } - arr.push_back(stack::get<V>(L, -lua_size<V>::value)); - } -#else - // Zzzz slower but necessary thanks to the lower version API and missing functions qq - for (lua_Integer i = 0; ; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { - for (int vi = 0; vi < lua_size<V>::value; ++vi) { - lua_pushinteger(L, i); - lua_gettable(L, index); - type t = type_of(L, -1); - if (t == type::lua_nil) { - if (i == 0) { - continue; - } - else { - lua_pop(L, (vi + 1)); - return arr; - } - } - } - arr.push_back(stack::get<V>(L, -1)); - } -#endif - return arr; - } - }; - - template<typename T> - struct getter<as_table_t<T>, std::enable_if_t<meta::has_key_value_pair<meta::unqualified_t<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - typedef typename T::value_type P; - typedef typename P::first_type K; - typedef typename P::second_type V; - tracking.use(1); - - T associative; - index = lua_absindex(L, index); - lua_pushnil(L); - while (lua_next(L, index) != 0) { - decltype(auto) key = stack::check_get<K>(L, -2); - if (!key) { - lua_pop(L, 1); - continue; - } - associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1)); - lua_pop(L, 1); - } - return associative; - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return T(L, index); - } - }; - - template<> - struct getter<userdata_value> { - static userdata_value get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return userdata_value(lua_touserdata(L, index)); - } - }; - - template<> - struct getter<lightuserdata_value> { - static lightuserdata_value get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lightuserdata_value(lua_touserdata(L, index)); - } - }; - - template<typename T> - struct getter<light<T>> { - static light<T> get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return light<T>(static_cast<T*>(lua_touserdata(L, index))); - } - }; - - template<typename T> - struct getter<user<T>> { - static T& get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return *static_cast<T*>(lua_touserdata(L, index)); - } - }; - - template<typename T> - struct getter<user<T*>> { - static T* get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T*>(lua_touserdata(L, index)); - } - }; - - template<> - struct getter<type> { - static type get(lua_State *L, int index, record& tracking) { - tracking.use(1); - return static_cast<type>(lua_type(L, index)); - } - }; - - template<> - struct getter<bool> { - static bool get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_toboolean(L, index) != 0; - } - }; - - template<> - struct getter<std::string> { - static std::string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - std::size_t len; - auto str = lua_tolstring(L, index, &len); - return std::string( str, len ); - } - }; - - template <> - struct getter<string_detail::string_shim> { - string_detail::string_shim get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - const char* p = lua_tolstring(L, index, &len); - return string_detail::string_shim(p, len); - } - }; - - template<> - struct getter<const char*> { - static const char* get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_tostring(L, index); - } - }; - - template<> - struct getter<char> { - static char get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - return len > 0 ? str[0] : '\0'; - } - }; - -#ifdef SOL_CODECVT_SUPPORT - template<> - struct getter<std::wstring> { - static std::wstring get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::wstring(); - if (sizeof(wchar_t) == 2) { - static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; - std::wstring r = convert.from_bytes(str, str + len); -#ifdef __MINGW32__ - // Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug - // https://sourceforge.net/p/mingw-w64/bugs/538/ - // http://chat.stackoverflow.com/transcript/message/32271369#32271369 - for (auto& c : r) { - uint8_t* b = reinterpret_cast<uint8_t*>(&c); - std::swap(b[0], b[1]); - } -#endif - return r; - } - static std::wstring_convert<std::codecvt_utf8<wchar_t>> convert; - std::wstring r = convert.from_bytes(str, str + len); - return r; - } - }; - - template<> - struct getter<std::u16string> { - static std::u16string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::u16string(); -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert; - auto intd = convert.from_bytes(str, str + len); - std::u16string r(intd.size(), '\0'); - std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); -#else - static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; - std::u16string r = convert.from_bytes(str, str + len); -#endif // VC++ is a shit - return r; - } - }; - - template<> - struct getter<std::u32string> { - static std::u32string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::u32string(); -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert; - auto intd = convert.from_bytes(str, str + len); - std::u32string r(intd.size(), '\0'); - std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); -#else - static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; - std::u32string r = convert.from_bytes(str, str + len); -#endif // VC++ is a shit - return r; - } - }; - - template<> - struct getter<wchar_t> { - static wchar_t get(lua_State* L, int index, record& tracking) { - auto str = getter<std::wstring>{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : wchar_t(0); - } - }; - - template<> - struct getter<char16_t> { - static char16_t get(lua_State* L, int index, record& tracking) { - auto str = getter<std::u16string>{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : char16_t(0); - } - }; - - template<> - struct getter<char32_t> { - static char32_t get(lua_State* L, int index, record& tracking) { - auto str = getter<std::u32string>{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : char32_t(0); - } - }; -#endif // codecvt header support - - template<> - struct getter<meta_function> { - static meta_function get(lua_State *L, int index, record& tracking) { - tracking.use(1); - const char* name = getter<const char*>{}.get(L, index, tracking); - for (std::size_t i = 0; i < meta_function_names.size(); ++i) - if (meta_function_names[i] == name) - return static_cast<meta_function>(i); - return meta_function::construct; - } - }; - - template<> - struct getter<lua_nil_t> { - static lua_nil_t get(lua_State*, int, record& tracking) { - tracking.use(1); - return lua_nil; - } - }; - - template<> - struct getter<std::nullptr_t> { - static std::nullptr_t get(lua_State*, int, record& tracking) { - tracking.use(1); - return nullptr; - } - }; - - template<> - struct getter<nullopt_t> { - static nullopt_t get(lua_State*, int, record& tracking) { - tracking.use(1); - return nullopt; - } - }; - - template<> - struct getter<this_state> { - static this_state get(lua_State* L, int, record& tracking) { - tracking.use(0); - return this_state{ L }; - } - }; - - template<> - struct getter<lua_CFunction> { - static lua_CFunction get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_tocfunction(L, index); - } - }; - - template<> - struct getter<c_closure> { - static c_closure get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return c_closure(lua_tocfunction(L, index), -1); - } - }; - - template<> - struct getter<error> { - static error get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t sz = 0; - const char* err = lua_tolstring(L, index, &sz); - if (err == nullptr) { - return error(detail::direct_error, ""); - } - return error(detail::direct_error, std::string(err, sz)); - } - }; - - template<> - struct getter<void*> { - static void* get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_touserdata(L, index); - } - }; - - template<typename T> - struct getter<detail::as_value_tag<T>> { - static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { - tracking.use(1); - void** pudata = static_cast<void**>(lua_touserdata(L, index)); - void* udata = *pudata; - return get_no_lua_nil_from(L, udata, index, tracking); - } - - static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) { - if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { - void* basecastdata = lua_touserdata(L, -1); - detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata; - // use the casting function to properly adjust the pointer for the desired T - udata = ic(udata, detail::id_for<T>::value); - lua_pop(L, 1); - } - T* obj = static_cast<T*>(udata); - return obj; - } - - static T& get(lua_State* L, int index, record& tracking) { - return *get_no_lua_nil(L, index, tracking); - } - }; - - template<typename T> - struct getter<detail::as_pointer_tag<T>> { - static T* get(lua_State* L, int index, record& tracking) { - type t = type_of(L, index); - if (t == type::lua_nil) { - tracking.use(1); - return nullptr; - } - return getter<detail::as_value_tag<T>>::get_no_lua_nil(L, index, tracking); - } - }; - - template<typename T> - struct getter<non_null<T*>> { - static T* get(lua_State* L, int index, record& tracking) { - return getter<detail::as_value_tag<T>>::get_no_lua_nil(L, index, tracking); - } - }; - - template<typename T> - struct getter<T&> { - static T& get(lua_State* L, int index, record& tracking) { - return getter<detail::as_value_tag<T>>::get(L, index, tracking); - } - }; - - template<typename T> - struct getter<std::reference_wrapper<T>> { - static T& get(lua_State* L, int index, record& tracking) { - return getter<T&>{}.get(L, index, tracking); - } - }; - - template<typename T> - struct getter<T*> { - static T* get(lua_State* L, int index, record& tracking) { - return getter<detail::as_pointer_tag<T>>::get(L, index, tracking); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<is_unique_usertype<T>::value>> { - typedef typename unique_usertype_traits<T>::type P; - typedef typename unique_usertype_traits<T>::actual_type Real; - - static Real& get(lua_State* L, int index, record& tracking) { - tracking.use(1); - P** pref = static_cast<P**>(lua_touserdata(L, index)); - detail::special_destruct_func* fx = static_cast<detail::special_destruct_func*>(static_cast<void*>(pref + 1)); - Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1)); - return *mem; - } - }; - - template<typename... Args> - struct getter<std::tuple<Args...>> { - typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R; - - template <typename... TArgs> - static R apply(std::index_sequence<>, lua_State*, int, record&, TArgs&&... args) { - // Fuck you too, VC++ - return R{std::forward<TArgs>(args)...}; - } - - template <std::size_t I, std::size_t... Ix, typename... TArgs> - static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, TArgs&&... args) { - // Fuck you too, VC++ - typedef std::tuple_element_t<I, std::tuple<Args...>> T; - return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<TArgs>(args)..., stack::get<T>(L, index + tracking.used, tracking)); - } - - static R get(lua_State* L, int index, record& tracking) { - return apply(std::make_index_sequence<sizeof...(Args)>(), L, index, tracking); - } - }; - - template<typename A, typename B> - struct getter<std::pair<A, B>> { - static decltype(auto) get(lua_State* L, int index, record& tracking) { - return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))>{stack::get<A>(L, index, tracking), stack::get<B>(L, index + tracking.used, tracking)}; - } - }; - - } // stack -} // sol - -// end of sol/stack_get.hpp - -// beginning of sol/stack_check_get.hpp - -namespace sol { - namespace stack { - template <typename T, typename> - struct check_getter { - typedef decltype(stack_detail::unchecked_get<T>(nullptr, 0, std::declval<record&>())) R; - - template <typename Handler> - static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) { - if (!check<T>(L, index, std::forward<Handler>(handler))) { - tracking.use(static_cast<int>(!lua_isnone(L, index))); - return nullopt; - } - return stack_detail::unchecked_get<T>(L, index, tracking); - } - }; - - template <typename T> - struct check_getter<optional<T>> { - template <typename Handler> - static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) { - return check_get<T>(L, index, no_panic, tracking); - } - }; - - template <typename T> - struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> { - template <typename Handler> - static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { - int isnum = 0; - lua_Integer value = lua_tointegerx(L, index, &isnum); - if (isnum == 0) { - type t = type_of(L, index); - tracking.use(static_cast<int>(t != type::none)); - handler(L, index, type::number, t); - return nullopt; - } - tracking.use(1); - return static_cast<T>(value); - } - }; - - template <typename T> - struct check_getter<T, std::enable_if_t<std::is_enum<T>::value && !meta::any_same<T, meta_function, type>::value>> { - template <typename Handler> - static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { - int isnum = 0; - lua_Integer value = lua_tointegerx(L, index, &isnum); - if (isnum == 0) { - type t = type_of(L, index); - tracking.use(static_cast<int>(t != type::none)); - handler(L, index, type::number, t); - return nullopt; - } - tracking.use(1); - return static_cast<T>(value); - } - }; - - template <typename T> - struct check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { - template <typename Handler> - static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { - int isnum = 0; - lua_Number value = lua_tonumberx(L, index, &isnum); - if (isnum == 0) { - type t = type_of(L, index); - tracking.use(static_cast<int>(t != type::none)); - handler(L, index, type::number, t); - return nullopt; - } - tracking.use(1); - return static_cast<T>(value); - } - }; - - template <typename T> - struct getter<optional<T>> { - static decltype(auto) get(lua_State* L, int index, record& tracking) { - return check_get<T>(L, index, no_panic, tracking); - } - }; - } // stack -} // sol - -// end of sol/stack_check_get.hpp - -// beginning of sol/stack_push.hpp - -// beginning of sol/raii.hpp - -namespace sol { - namespace detail { - struct default_construct { - template<typename T, typename... Args> - static void construct(T&& obj, Args&&... args) { - std::allocator<meta::unqualified_t<T>> alloc{}; - alloc.construct(obj, std::forward<Args>(args)...); - } - - template<typename T, typename... Args> - void operator()(T&& obj, Args&&... args) const { - construct(std::forward<T>(obj), std::forward<Args>(args)...); - } - }; - - struct default_destruct { - template<typename T> - static void destroy(T&& obj) { - std::allocator<meta::unqualified_t<T>> alloc{}; - alloc.destroy(obj); - } - - template<typename T> - void operator()(T&& obj) const { - destroy(std::forward<T>(obj)); - } - }; - - struct deleter { - template <typename T> - void operator()(T* p) const { - delete p; - } - }; - - template <typename T, typename Dx, typename... Args> - inline std::unique_ptr<T, Dx> make_unique_deleter(Args&&... args) { - return std::unique_ptr<T, Dx>(new T(std::forward<Args>(args)...)); - } - - template <typename Tag, typename T> - struct tagged { - T value; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, tagged>> = meta::enabler> - tagged(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - } // detail - - template <typename... Args> - struct constructor_list {}; - - template<typename... Args> - using constructors = constructor_list<Args...>; - - const auto default_constructor = constructors<types<>>{}; - - struct no_construction {}; - const auto no_constructor = no_construction{}; - - struct call_construction {}; - const auto call_constructor = call_construction{}; - - template <typename... Functions> - struct constructor_wrapper { - std::tuple<Functions...> functions; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, constructor_wrapper>> = meta::enabler> - constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - - template <typename... Functions> - inline auto initializers(Functions&&... functions) { - return constructor_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); - } - - template <typename... Functions> - struct factory_wrapper { - std::tuple<Functions...> functions; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, factory_wrapper>> = meta::enabler> - factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - - template <typename... Functions> - inline auto factories(Functions&&... functions) { - return factory_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); - } - - template <typename Function> - struct destructor_wrapper { - Function fx; - destructor_wrapper(Function f) : fx(std::move(f)) {} - }; - - template <> - struct destructor_wrapper<void> {}; - - const destructor_wrapper<void> default_destructor{}; - - template <typename Fx> - inline auto destructor(Fx&& fx) { - return destructor_wrapper<std::decay_t<Fx>>(std::forward<Fx>(fx)); - } - -} // sol - -// end of sol/raii.hpp - -#ifdef SOL_CODECVT_SUPPORT -#endif - -namespace sol { - namespace stack { - template <typename T> - struct pusher<detail::as_value_tag<T>> { - template <typename F, typename... Args> - static int push_fx(lua_State* L, F&& f, Args&&... args) { - // Basically, we store all user-data like this: - // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new - // data in the first sizeof(T*) bytes, and then however many bytes it takes to - // do the actual object. Things that are std::ref or plain T* are stored as - // just the sizeof(T*), and nothing else. - T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - T*& referencereference = *pointerpointer; - T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1); - referencereference = allocationtarget; - std::allocator<T> alloc{}; - alloc.construct(allocationtarget, std::forward<Args>(args)...); - f(); - return 1; - } - - template <typename K, typename... Args> - static int push_keyed(lua_State* L, K&& k, Args&&... args) { - return push_fx(L, [&L, &k]() { - luaL_newmetatable(L, &k[0]); - lua_setmetatable(L, -2); - }, std::forward<Args>(args)...); - } - - template <typename... Args> - static int push(lua_State* L, Args&&... args) { - return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Args>(args)...); - } - }; - - template <typename T> - struct pusher<detail::as_pointer_tag<T>> { - template <typename F> - static int push_fx(lua_State* L, F&& f, T* obj) { - if (obj == nullptr) - return stack::push(L, lua_nil); - T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*))); - *pref = obj; - f(); - return 1; - } - - template <typename K> - static int push_keyed(lua_State* L, K&& k, T* obj) { - return push_fx(L, [&L, &k]() { - luaL_newmetatable(L, &k[0]); - lua_setmetatable(L, -2); - }, obj); - } - - static int push(lua_State* L, T* obj) { - return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable(), obj); - } - }; - - template <> - struct pusher<detail::as_reference_tag> { - template <typename T> - static int push(lua_State* L, T&& obj) { - return stack::push(L, detail::ptr(obj)); - } - }; - - template<typename T, typename> - struct pusher { - template <typename... Args> - static int push(lua_State* L, Args&&... args) { - return pusher<detail::as_value_tag<T>>{}.push(L, std::forward<Args>(args)...); - } - }; - - template<typename T> - struct pusher<T*, meta::disable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - template <typename... Args> - static int push(lua_State* L, Args&&... args) { - return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...); - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<is_unique_usertype<T>::value>> { - typedef typename unique_usertype_traits<T>::type P; - typedef typename unique_usertype_traits<T>::actual_type Real; - - template <typename Arg, meta::enable<std::is_base_of<Real, meta::unqualified_t<Arg>>> = meta::enabler> - static int push(lua_State* L, Arg&& arg) { - if (unique_usertype_traits<T>::is_null(arg)) - return stack::push(L, lua_nil); - return push_deep(L, std::forward<Arg>(arg)); - } - - template <typename Arg0, typename Arg1, typename... Args> - static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) { - return push_deep(L, std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...); - } - - template <typename... Args> - static int push_deep(lua_State* L, Args&&... args) { - P** pref = static_cast<P**>(lua_newuserdata(L, sizeof(P*) + sizeof(detail::special_destruct_func) + sizeof(Real))); - detail::special_destruct_func* fx = static_cast<detail::special_destruct_func*>(static_cast<void*>(pref + 1)); - Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1)); - *fx = detail::special_destruct<P, Real>; - detail::default_construct::construct(mem, std::forward<Args>(args)...); - *pref = unique_usertype_traits<T>::get(*mem); - if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) { - set_field(L, "__gc", detail::unique_destruct<P>); - } - lua_setmetatable(L, -2); - return 1; - } - }; - - template<typename T> - struct pusher<std::reference_wrapper<T>> { - static int push(lua_State* L, const std::reference_wrapper<T>& t) { - return stack::push(L, std::addressof(detail::deref(t.get()))); - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<std::is_floating_point<T>::value>> { - static int push(lua_State* L, const T& value) { - lua_pushnumber(L, value); - return 1; - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { - static int push(lua_State* L, const T& value) { - lua_pushinteger(L, static_cast<lua_Integer>(value)); - return 1; - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<std::is_enum<T>::value>> { - static int push(lua_State* L, const T& value) { - if (std::is_same<char, T>::value) { - return stack::push(L, static_cast<int>(value)); - } - return stack::push(L, static_cast<std::underlying_type_t<T>>(value)); - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { - static int push(lua_State* L, const T& value) { - lua_pushinteger(L, static_cast<lua_Integer>(value)); - return 1; - } - }; - - template<typename T> - struct pusher<as_table_t<T>, std::enable_if_t<!meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>::value>> { - static int push(lua_State* L, const as_table_t<T>& tablecont) { - auto& cont = detail::deref(detail::unwrap(tablecont.source)); - lua_createtable(L, static_cast<int>(cont.size()), 0); - int tableindex = lua_gettop(L); - std::size_t index = 1; - for (const auto& i : cont) { -#if SOL_LUA_VERSION >= 503 - int p = stack::push(L, i); - for (int pi = 0; pi < p; ++pi) { - lua_seti(L, tableindex, static_cast<lua_Integer>(index++)); - } -#else - lua_pushinteger(L, static_cast<lua_Integer>(index)); - int p = stack::push(L, i); - if (p == 1) { - ++index; - lua_settable(L, tableindex); - } - else { - int firstindex = tableindex + 1 + 1; - for (int pi = 0; pi < p; ++pi) { - stack::push(L, index); - lua_pushvalue(L, firstindex); - lua_settable(L, tableindex); - ++index; - ++firstindex; - } - lua_pop(L, 1 + p); - } -#endif - } - // TODO: figure out a better way to do this...? - //set_field(L, -1, cont.size()); - return 1; - } - }; - - template<typename T> - struct pusher<as_table_t<T>, std::enable_if_t<meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>::value>> { - static int push(lua_State* L, const as_table_t<T>& tablecont) { - auto& cont = detail::deref(detail::unwrap(tablecont.source)); - lua_createtable(L, static_cast<int>(cont.size()), 0); - int tableindex = lua_gettop(L); - for (const auto& pair : cont) { - set_field(L, pair.first, pair.second, tableindex); - } - return 1; - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> { - static int push(lua_State* L, const T& ref) { - return ref.push(L); - } - - static int push(lua_State* L, T&& ref) { - return ref.push(L); - } - }; - - template<> - struct pusher<bool> { - static int push(lua_State* L, bool b) { - lua_pushboolean(L, b); - return 1; - } - }; - - template<> - struct pusher<lua_nil_t> { - static int push(lua_State* L, lua_nil_t) { - lua_pushnil(L); - return 1; - } - }; - - template<> - struct pusher<metatable_key_t> { - static int push(lua_State* L, metatable_key_t) { - lua_pushlstring(L, "__mt", 4); - return 1; - } - }; - - template<> - struct pusher<std::remove_pointer_t<lua_CFunction>> { - static int push(lua_State* L, lua_CFunction func, int n = 0) { - lua_pushcclosure(L, func, n); - return 1; - } - }; - - template<> - struct pusher<lua_CFunction> { - static int push(lua_State* L, lua_CFunction func, int n = 0) { - lua_pushcclosure(L, func, n); - return 1; - } - }; - - template<> - struct pusher<c_closure> { - static int push(lua_State* L, c_closure cc) { - lua_pushcclosure(L, cc.c_function, cc.upvalues); - return 1; - } - }; - - template<typename Arg, typename... Args> - struct pusher<closure<Arg, Args...>> { - template <std::size_t... I, typename T> - static int push(std::index_sequence<I...>, lua_State* L, T&& c) { - int pushcount = multi_push(L, detail::forward_get<I>(c.upvalues)...); - return stack::push(L, c_closure(c.c_function, pushcount)); - } - - template <typename T> - static int push(lua_State* L, T&& c) { - return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c)); - } - }; - - template<> - struct pusher<void*> { - static int push(lua_State* L, void* userdata) { - lua_pushlightuserdata(L, userdata); - return 1; - } - }; - - template<> - struct pusher<lightuserdata_value> { - static int push(lua_State* L, lightuserdata_value userdata) { - lua_pushlightuserdata(L, userdata); - return 1; - } - }; - - template<typename T> - struct pusher<light<T>> { - static int push(lua_State* L, light<T> l) { - lua_pushlightuserdata(L, static_cast<void*>(l.value)); - return 1; - } - }; - - template<typename T> - struct pusher<user<T>> { - template <bool with_meta = true, typename Key, typename... Args> - static int push_with(lua_State* L, Key&& name, Args&&... args) { - // A dumb pusher - void* rawdata = lua_newuserdata(L, sizeof(T)); - T* data = static_cast<T*>(rawdata); - std::allocator<T> alloc; - alloc.construct(data, std::forward<Args>(args)...); - if (with_meta) { - lua_CFunction cdel = detail::user_alloc_destroy<T>; - // Make sure we have a plain GC set for this data - if (luaL_newmetatable(L, name) != 0) { - lua_pushcclosure(L, cdel, 0); - lua_setfield(L, -2, "__gc"); - } - lua_setmetatable(L, -2); - } - return 1; - } - - template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_key_t>> = meta::enabler> - static int push(lua_State* L, Arg&& arg, Args&&... args) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...); - } - - template <typename... Args> - static int push(lua_State* L, no_metatable_t, Args&&... args) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with<false>(L, name, std::forward<Args>(args)...); - } - - template <typename Key, typename... Args> - static int push(lua_State* L, metatable_key_t, Key&& key, Args&&... args) { - const auto name = &key[0]; - return push_with<true>(L, name, std::forward<Args>(args)...); - } - - static int push(lua_State* L, const user<T>& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with(L, name, u.value); - } - - static int push(lua_State* L, user<T>&& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with(L, name, std::move(u.value)); - } - - static int push(lua_State* L, no_metatable_t, const user<T>& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with<false>(L, name, u.value); - } - - static int push(lua_State* L, no_metatable_t, user<T>&& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with<false>(L, name, std::move(u.value)); - } - }; - - template<> - struct pusher<userdata_value> { - static int push(lua_State* L, userdata_value data) { - void** ud = static_cast<void**>(lua_newuserdata(L, sizeof(void*))); - *ud = data.value; - return 1; - } - }; - - template<> - struct pusher<const char*> { - static int push_sized(lua_State* L, const char* str, std::size_t len) { - lua_pushlstring(L, str, len); - return 1; - } - - static int push(lua_State* L, const char* str) { - if (str == nullptr) - return stack::push(L, lua_nil); - return push_sized(L, str, std::char_traits<char>::length(str)); - } - - static int push(lua_State* L, const char* strb, const char* stre) { - return push_sized(L, strb, stre - strb); - } - - static int push(lua_State* L, const char* str, std::size_t len) { - return push_sized(L, str, len); - } - }; - - template<size_t N> - struct pusher<char[N]> { - static int push(lua_State* L, const char(&str)[N]) { - lua_pushlstring(L, str, N - 1); - return 1; - } - - static int push(lua_State* L, const char(&str)[N], std::size_t sz) { - lua_pushlstring(L, str, sz); - return 1; - } - }; - - template <> - struct pusher<char> { - static int push(lua_State* L, char c) { - const char str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template<> - struct pusher<std::string> { - static int push(lua_State* L, const std::string& str) { - lua_pushlstring(L, str.c_str(), str.size()); - return 1; - } - - static int push(lua_State* L, const std::string& str, std::size_t sz) { - lua_pushlstring(L, str.c_str(), sz); - return 1; - } - }; - - template<> - struct pusher<meta_function> { - static int push(lua_State* L, meta_function m) { - const std::string& str = name_of(m); - lua_pushlstring(L, str.c_str(), str.size()); - return 1; - } - }; - -#ifdef SOL_CODECVT_SUPPORT - template<> - struct pusher<const wchar_t*> { - static int push(lua_State* L, const wchar_t* wstr) { - return push(L, wstr, std::char_traits<wchar_t>::length(wstr)); - } - - static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { - return push(L, wstr, wstr + sz); - } - - static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { - if (sizeof(wchar_t) == 2) { - static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; - std::string u8str = convert.to_bytes(strb, stre); - return stack::push(L, u8str); - } - static std::wstring_convert<std::codecvt_utf8<wchar_t>> convert; - std::string u8str = convert.to_bytes(strb, stre); - return stack::push(L, u8str); - } - }; - - template<> - struct pusher<const char16_t*> { - static int push(lua_State* L, const char16_t* u16str) { - return push(L, u16str, std::char_traits<char16_t>::length(u16str)); - } - - static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { - return push(L, u16str, u16str + sz); - } - - static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert; - std::string u8str = convert.to_bytes(reinterpret_cast<const int16_t*>(strb), reinterpret_cast<const int16_t*>(stre)); -#else - static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; - std::string u8str = convert.to_bytes(strb, stre); -#endif // VC++ is a shit - return stack::push(L, u8str); - } - }; - - template<> - struct pusher<const char32_t*> { - static int push(lua_State* L, const char32_t* u32str) { - return push(L, u32str, u32str + std::char_traits<char32_t>::length(u32str)); - } - - static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { - return push(L, u32str, u32str + sz); - } - - static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert; - std::string u8str = convert.to_bytes(reinterpret_cast<const int32_t*>(strb), reinterpret_cast<const int32_t*>(stre)); -#else - static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; - std::string u8str = convert.to_bytes(strb, stre); -#endif // VC++ is a shit - return stack::push(L, u8str); - } - }; - - template<size_t N> - struct pusher<wchar_t[N]> { - static int push(lua_State* L, const wchar_t(&str)[N]) { - return push(L, str, N - 1); - } - - static int push(lua_State* L, const wchar_t(&str)[N], std::size_t sz) { - return stack::push<const wchar_t*>(L, str, str + sz); - } - }; - - template<size_t N> - struct pusher<char16_t[N]> { - static int push(lua_State* L, const char16_t(&str)[N]) { - return push(L, str, N - 1); - } - - static int push(lua_State* L, const char16_t(&str)[N], std::size_t sz) { - return stack::push<const char16_t*>(L, str, str + sz); - } - }; - - template<size_t N> - struct pusher<char32_t[N]> { - static int push(lua_State* L, const char32_t(&str)[N]) { - return push(L, str, N - 1); - } - - static int push(lua_State* L, const char32_t(&str)[N], std::size_t sz) { - return stack::push<const char32_t*>(L, str, str + sz); - } - }; - - template <> - struct pusher<wchar_t> { - static int push(lua_State* L, wchar_t c) { - const wchar_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template <> - struct pusher<char16_t> { - static int push(lua_State* L, char16_t c) { - const char16_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template <> - struct pusher<char32_t> { - static int push(lua_State* L, char32_t c) { - const char32_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template<> - struct pusher<std::wstring> { - static int push(lua_State* L, const std::wstring& wstr) { - return push(L, wstr.data(), wstr.size()); - } - - static int push(lua_State* L, const std::wstring& wstr, std::size_t sz) { - return stack::push(L, wstr.data(), wstr.data() + sz); - } - }; - - template<> - struct pusher<std::u16string> { - static int push(lua_State* L, const std::u16string& u16str) { - return push(L, u16str, u16str.size()); - } - - static int push(lua_State* L, const std::u16string& u16str, std::size_t sz) { - return stack::push(L, u16str.data(), u16str.data() + sz); - } - }; - - template<> - struct pusher<std::u32string> { - static int push(lua_State* L, const std::u32string& u32str) { - return push(L, u32str, u32str.size()); - } - - static int push(lua_State* L, const std::u32string& u32str, std::size_t sz) { - return stack::push(L, u32str.data(), u32str.data() + sz); - } - }; -#endif // codecvt Header Support - - template<typename... Args> - struct pusher<std::tuple<Args...>> { - template <std::size_t... I, typename T> - static int push(std::index_sequence<I...>, lua_State* L, T&& t) { - int pushcount = 0; - (void)detail::swallow{ 0, (pushcount += stack::push(L, - detail::forward_get<I>(t) - ), 0)... }; - return pushcount; - } - - template <typename T> - static int push(lua_State* L, T&& t) { - return push(std::index_sequence_for<Args...>(), L, std::forward<T>(t)); - } - }; - - template<typename A, typename B> - struct pusher<std::pair<A, B>> { - template <typename T> - static int push(lua_State* L, T&& t) { - int pushcount = stack::push(L, detail::forward_get<0>(t)); - pushcount += stack::push(L, detail::forward_get<1>(t)); - return pushcount; - } - }; - - template<typename O> - struct pusher<optional<O>> { - template <typename T> - static int push(lua_State* L, T&& t) { - if (t == nullopt) { - return stack::push(L, nullopt); - } - return stack::push(L, t.value()); - } - }; - - template<> - struct pusher<nullopt_t> { - static int push(lua_State* L, nullopt_t) { - return stack::push(L, lua_nil); - } - }; - - template<> - struct pusher<std::nullptr_t> { - static int push(lua_State* L, std::nullptr_t) { - return stack::push(L, lua_nil); - } - }; - - template<> - struct pusher<this_state> { - static int push(lua_State*, const this_state&) { - return 0; - } - }; - } // stack -} // sol - -// end of sol/stack_push.hpp - -// beginning of sol/stack_pop.hpp - -namespace sol { - namespace stack { - template <typename T, typename> - struct popper { - inline static decltype(auto) pop(lua_State* L) { - record tracking{}; - decltype(auto) r = get<T>(L, -lua_size<T>::value, tracking); - lua_pop(L, tracking.used); - return r; - } - }; - - template <typename T> - struct popper<T, std::enable_if_t<std::is_base_of<stack_reference, meta::unqualified_t<T>>::value>> { - static_assert(meta::neg<std::is_base_of<stack_reference, meta::unqualified_t<T>>>::value, "You cannot pop something that derives from stack_reference: it will not remain on the stack and thusly will go out of scope!"); - }; - } // stack -} // sol - -// end of sol/stack_pop.hpp - -// beginning of sol/stack_field.hpp - -namespace sol { - namespace stack { - template <typename T, bool, bool, typename> - struct field_getter { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -2) { - push(L, std::forward<Key>(key)); - lua_gettable(L, tableindex); - } - }; - - template <typename T, bool global, typename C> - struct field_getter<T, global, true, C> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -2) { - push(L, std::forward<Key>(key)); - lua_rawget(L, tableindex); - } - }; - - template <bool b, bool raw, typename C> - struct field_getter<metatable_key_t, b, raw, C> { - void get(lua_State* L, metatable_key_t, int tableindex = -1) { - if (lua_getmetatable(L, tableindex) == 0) - push(L, lua_nil); - } - }; - - template <typename T, bool raw> - struct field_getter<T, true, raw, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int = -1) { - lua_getglobal(L, &key[0]); - } - }; - - template <typename T> - struct field_getter<T, false, false, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -1) { - lua_getfield(L, tableindex, &key[0]); - } - }; - -#if SOL_LUA_VERSION >= 503 - template <typename T> - struct field_getter<T, false, false, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -1) { - lua_geti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; -#endif // Lua 5.3.x - -#if SOL_LUA_VERSION >= 502 - template <typename C> - struct field_getter<void*, false, true, C> { - void get(lua_State* L, void* key, int tableindex = -1) { - lua_rawgetp(L, tableindex, key); - } - }; -#endif // Lua 5.3.x - - template <typename T> - struct field_getter<T, false, true, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -1) { - lua_rawgeti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; - - template <typename... Args, bool b, bool raw, typename C> - struct field_getter<std::tuple<Args...>, b, raw, C> { - template <std::size_t... I, typename Keys> - void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { - get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); - void(detail::swallow{ (get_field<false, raw>(L, detail::forward_get<I>(keys)), 0)... }); - reference saved(L, -1); - lua_pop(L, static_cast<int>(sizeof...(I))); - saved.push(); - } - - template <typename Keys> - void get(lua_State* L, Keys&& keys) { - apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), lua_absindex(L, -1)); - } - - template <typename Keys> - void get(lua_State* L, Keys&& keys, int tableindex) { - apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), tableindex); - } - }; - - template <typename A, typename B, bool b, bool raw, typename C> - struct field_getter<std::pair<A, B>, b, raw, C> { - template <typename Keys> - void get(lua_State* L, Keys&& keys, int tableindex) { - get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); - get_field<false, raw>(L, detail::forward_get<1>(keys)); - reference saved(L, -1); - lua_pop(L, static_cast<int>(2)); - saved.push(); - } - - template <typename Keys> - void get(lua_State* L, Keys&& keys) { - get_field<b, raw>(L, detail::forward_get<0>(keys)); - get_field<false, raw>(L, detail::forward_get<1>(keys)); - reference saved(L, -1); - lua_pop(L, static_cast<int>(2)); - saved.push(); - } - }; - - template <typename T, bool, bool, typename> - struct field_setter { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { - push(L, std::forward<Key>(key)); - push(L, std::forward<Value>(value)); - lua_settable(L, tableindex); - } - }; - - template <typename T, bool b, typename C> - struct field_setter<T, b, true, C> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { - push(L, std::forward<Key>(key)); - push(L, std::forward<Value>(value)); - lua_rawset(L, tableindex); - } - }; - - template <bool b, bool raw, typename C> - struct field_setter<metatable_key_t, b, raw, C> { - template <typename Value> - void set(lua_State* L, metatable_key_t, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_setmetatable(L, tableindex); - } - }; - - template <typename T, bool raw> - struct field_setter<T, true, raw, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int = -2) { - push(L, std::forward<Value>(value)); - lua_setglobal(L, &key[0]); - } - }; - - template <typename T> - struct field_setter<T, false, false, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_setfield(L, tableindex, &key[0]); - } - }; - -#if SOL_LUA_VERSION >= 503 - template <typename T> - struct field_setter<T, false, false, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_seti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; -#endif // Lua 5.3.x - - template <typename T> - struct field_setter<T, false, true, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_rawseti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; - -#if SOL_LUA_VERSION >= 502 - template <typename C> - struct field_setter<void*, false, true, C> { - template <typename Key, typename Value> - void set(lua_State* L, void* key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_rawsetp(L, tableindex, key); - } - }; -#endif // Lua 5.2.x - - template <typename... Args, bool b, bool raw, typename C> - struct field_setter<std::tuple<Args...>, b, raw, C> { - template <bool g, std::size_t I, typename Key, typename Value> - void apply(std::index_sequence<I>, lua_State* L, Key&& keys, Value&& value, int tableindex) { - I < 1 ? - set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value), tableindex) : - set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value)); - } - - template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value> - void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { - I0 < 1 ? get_field<g, raw>(L, detail::forward_get<I0>(keys), tableindex) : get_field<g, raw>(L, detail::forward_get<I0>(keys), -1); - apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1); - } - - template <bool g, std::size_t I0, std::size_t... I, typename Keys, typename Value> - void top_apply(std::index_sequence<I0, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { - apply<g>(std::index_sequence<I0, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); - lua_pop(L, static_cast<int>(sizeof...(I))); - } - - template <typename Keys, typename Value> - void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { - top_apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); - } - }; - - template <typename A, typename B, bool b, bool raw, typename C> - struct field_setter<std::pair<A, B>, b, raw, C> { - template <typename Keys, typename Value> - void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { - get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); - set_field<false, raw>(L, detail::forward_get<1>(keys), std::forward<Value>(value)); - lua_pop(L, 1); - } - }; - } // stack -} // sol - -// end of sol/stack_field.hpp - -// beginning of sol/stack_probe.hpp - -namespace sol { - namespace stack { - template <typename T, bool b, bool raw, typename> - struct probe_field_getter { - template <typename Key> - probe get(lua_State* L, Key&& key, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); - } - get_field<b, raw>(L, std::forward<Key>(key), tableindex); - return probe(!check<lua_nil_t>(L), 1); - } - }; - - template <typename A, typename B, bool b, bool raw, typename C> - struct probe_field_getter<std::pair<A, B>, b, raw, C> { - template <typename Keys> - probe get(lua_State* L, Keys&& keys, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); - } - get_field<b, raw>(L, std::get<0>(keys), tableindex); - if (!maybe_indexable(L)) { - return probe(false, 1); - } - get_field<false, raw>(L, std::get<1>(keys), tableindex); - return probe(!check<lua_nil_t>(L), 2); - } - }; - - template <typename... Args, bool b, bool raw, typename C> - struct probe_field_getter<std::tuple<Args...>, b, raw, C> { - template <std::size_t I, typename Keys> - probe apply(std::index_sequence<I>, int sofar, lua_State* L, Keys&& keys, int tableindex) { - get_field < I < 1 && b, raw>(L, std::get<I>(keys), tableindex); - return probe(!check<lua_nil_t>(L), sofar); - } - - template <std::size_t I, std::size_t I1, std::size_t... In, typename Keys> - probe apply(std::index_sequence<I, I1, In...>, int sofar, lua_State* L, Keys&& keys, int tableindex) { - get_field < I < 1 && b, raw>(L, std::get<I>(keys), tableindex); - if (!maybe_indexable(L)) { - return probe(false, sofar); - } - return apply(std::index_sequence<I1, In...>(), sofar + 1, L, std::forward<Keys>(keys), -1); - } - - template <typename Keys> - probe get(lua_State* L, Keys&& keys, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); - } - return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex); - } - }; - } // stack -} // sol - -// end of sol/stack_probe.hpp - -#include <cstring> - -namespace sol { - namespace stack { - namespace stack_detail { - template<typename T> - inline int push_as_upvalues(lua_State* L, T& item) { - typedef std::decay_t<T> TValue; - const static std::size_t itemsize = sizeof(TValue); - const static std::size_t voidsize = sizeof(void*); - const static std::size_t voidsizem1 = voidsize - 1; - const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; - typedef std::array<void*, data_t_count> data_t; - - data_t data{ {} }; - std::memcpy(&data[0], std::addressof(item), itemsize); - int pushcount = 0; - for (auto&& v : data) { - pushcount += push(L, lightuserdata_value(v)); - } - return pushcount; - } - - template<typename T> - inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) { - const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); - typedef std::array<void*, data_t_count> data_t; - data_t voiddata{ {} }; - for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { - voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++)); - } - return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index); - } - - struct evaluator { - template <typename Fx, typename... Args> - static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) { - return std::forward<Fx>(fx)(std::forward<Args>(args)...); - } - - template <typename Fx, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename... FxArgs> - static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { - return eval(types<Args...>(), std::index_sequence<Is...>(), L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)..., stack_detail::unchecked_get<Arg>(L, start + tracking.used, tracking)); - } - }; - - template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER - static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so fucking sad - multi_check<checkargs, Args...>(L, start, type_panic); - record tracking{}; - return evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool checkargs = default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs> - inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER - static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so fucking sad - multi_check<checkargs, Args...>(L, start, type_panic); - record tracking{}; - evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - } // stack_detail - - template <typename T> - int set_ref(lua_State* L, T&& arg, int tableindex = -2) { - push(L, std::forward<T>(arg)); - return luaL_ref(L, tableindex); - } - - inline void remove(lua_State* L, int index, int count) { - if (count < 1) - return; - int top = lua_gettop(L); - if (index == -1 || top == index) { - // Slice them right off the top - lua_pop(L, static_cast<int>(count)); - return; - } - - // Remove each item one at a time using stack operations - // Probably slower, maybe, haven't benchmarked, - // but necessary - if (index < 0) { - index = lua_gettop(L) + (index + 1); - } - int last = index + count; - for (int i = index; i < last; ++i) { - lua_remove(L, index); - } - } - - template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence<sizeof...(Args)> args_indices; - return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline void call(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence<sizeof...(Args)> args_indices; - stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - return call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline void call_from_top(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template<bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); - lua_settop(L, 0); - return 0; - } - - template<bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>> - inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); - lua_settop(L, 0); - return push_reference(L, std::forward<decltype(r)>(r)); - } - - template<bool check_args = stack_detail::default_check_arguments, typename Fx, typename... FxArgs> - inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::returns_list returns_list; - return call_into_lua(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); - } - - inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index) { - if (lua_gettop(L) == 0) { - return call_syntax::dot; - } - luaL_getmetatable(L, key.c_str()); - auto pn = pop_n(L, 1); - if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { - return call_syntax::dot; - } - return call_syntax::colon; - } - - inline void script(lua_State* L, const std::string& code) { - if (luaL_dostring(L, code.c_str())) { - lua_error(L); - } - } - - inline void script_file(lua_State* L, const std::string& filename) { - if (luaL_dofile(L, filename.c_str())) { - lua_error(L); - } - } - - inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { -#ifdef SOL_LUAJIT - lua_pushlightuserdata(L, (void*)handler); - auto pn = pop_n(L, 1); - luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); -#else - (void)L; - (void)handler; -#endif - } - - inline void luajit_exception_off(lua_State* L) { -#ifdef SOL_LUAJIT - luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); -#else - (void)L; -#endif - } - } // stack -} // sol - -// end of sol/stack.hpp - -// beginning of sol/as_args.hpp - -namespace sol { - template <typename T> - struct to_args_t { - T src; - }; - - template <typename Source> - auto as_args(Source&& source) { - return to_args_t<Source>{ std::forward<Source>(source) }; - } - - namespace stack { - template <typename T> - struct pusher<to_args_t<T>> { - int push(lua_State* L, const to_args_t<T>& e) { - int p = 0; - for (const auto& i : e.src) { - p += stack::push(L, i); - } - return p; - } - }; - } -} // sol - -// end of sol/as_args.hpp - -// beginning of sol/variadic_args.hpp - -// beginning of sol/stack_proxy.hpp - -// beginning of sol/function.hpp - -// beginning of sol/function_result.hpp - -// beginning of sol/proxy_base.hpp - -namespace sol { - template <typename Super> - struct proxy_base { - operator std::string() const { - const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); - return super.template get<std::string>(); - } - - template<typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, is_proxy_primitive<meta::unqualified_t<T>>> = meta::enabler> - operator T () const { - const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); - return super.template get<T>(); - } - - template<typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, meta::neg<is_proxy_primitive<meta::unqualified_t<T>>>> = meta::enabler> - operator T& () const { - const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); - return super.template get<T&>(); - } - }; -} // sol - -// end of sol/proxy_base.hpp - -#include <cstdint> - -namespace sol { - struct function_result : public proxy_base<function_result> { - private: - lua_State* L; - int index; - int returncount; - - public: - function_result() = default; - function_result(lua_State* Ls, int idx = -1, int retnum = 0) : L(Ls), index(idx), returncount(retnum) { - - } - function_result(const function_result&) = default; - function_result& operator=(const function_result&) = default; - function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - } - function_result& operator=(function_result&& o) { - L = o.L; - index = o.index; - returncount = o.returncount; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - return *this; - } - - template<typename T> - decltype(auto) get() const { - return stack::get<T>(L, index); - } - - call_status status() const noexcept { - return call_status::ok; - } - - bool valid() const noexcept { - return status() == call_status::ok || status() == call_status::yielded; - } - - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; - - ~function_result() { - lua_pop(L, returncount); - } - }; -} // sol - -// end of sol/function_result.hpp - -// beginning of sol/function_types.hpp - -// beginning of sol/function_types_core.hpp - -// beginning of sol/wrapper.hpp - -namespace sol { - - template <typename F, typename = void> - struct wrapper { - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::args_list free_args_list; - typedef typename traits_type::returns_list returns_list; - - template <typename... Args> - static decltype(auto) call(F& f, Args&&... args) { - return f(std::forward<Args>(args)...); - } - - struct caller { - template <typename... Args> - decltype(auto) operator()(F& fx, Args&&... args) const { - return call(fx, std::forward<Args>(args)...); - } - }; - }; - - template <typename F> - struct wrapper<F, std::enable_if_t<std::is_function<meta::unqualified_t<std::remove_pointer_t<F>>>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::args_list free_args_list; - typedef typename traits_type::returns_list returns_list; - - template <F fx, typename... Args> - static decltype(auto) invoke(Args&&... args) { - return fx(std::forward<Args>(args)...); - } - - template <typename... Args> - static decltype(auto) call(F& fx, Args&&... args) { - return fx(std::forward<Args>(args)...); - } - - struct caller { - template <typename... Args> - decltype(auto) operator()(F& fx, Args&&... args) const { - return call(fx, std::forward<Args>(args)...); - } - }; - - template <F fx> - struct invoker { - template <typename... Args> - decltype(auto) operator()(Args&&... args) const { - return invoke<fx>(std::forward<Args>(args)...); - } - }; - }; - - template <typename F> - struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::object_type object_type; - typedef typename traits_type::return_type return_type; - typedef typename traits_type::args_list args_list; - typedef types<object_type&, return_type> free_args_list; - typedef typename traits_type::returns_list returns_list; - - template <F fx, typename... Args> - static decltype(auto) invoke(object_type& mem, Args&&... args) { - return (mem.*fx)(std::forward<Args>(args)...); - } - - template <typename Fx> - static decltype(auto) call(Fx&& fx, object_type& mem) { - return (mem.*fx); - } - - template <typename Fx, typename Arg, typename... Args> - static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { - (mem.*fx) = std::forward<Arg>(arg); - } - - struct caller { - template <typename Fx, typename... Args> - decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { - return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); - } - }; - - template <F fx> - struct invoker { - template <typename... Args> - decltype(auto) operator()(Args&&... args) const { - return invoke<fx>(std::forward<Args>(args)...); - } - }; - }; - - template <typename F, typename R, typename O, typename... FArgs> - struct member_function_wrapper { - typedef O object_type; - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::args_list args_list; - typedef types<object_type&, FArgs...> free_args_list; - typedef meta::tuple_types<R> returns_list; - - template <F fx, typename... Args> - static R invoke(O& mem, Args&&... args) { - return (mem.*fx)(std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static R call(Fx&& fx, O& mem, Args&&... args) { - return (mem.*fx)(std::forward<Args>(args)...); - } - - struct caller { - template <typename Fx, typename... Args> - decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { - return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); - } - }; - - template <F fx> - struct invoker { - template <typename... Args> - decltype(auto) operator()(O& mem, Args&&... args) const { - return invoke<fx>(mem, std::forward<Args>(args)...); - } - }; - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...)> : public member_function_wrapper<R(O:: *)(Args...), R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const> : public member_function_wrapper<R(O:: *)(Args...) const, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const volatile> : public member_function_wrapper<R(O:: *)(Args...) const volatile, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) &> : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const &> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const volatile &> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) &> : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const &> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const volatile &> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) && > : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const &&> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) && > : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> { - - }; - -} // sol - -// end of sol/wrapper.hpp - -namespace sol { - namespace function_detail { - template <typename Fx> - inline int call(lua_State* L) { - Fx& fx = stack::get<user<Fx>>(L, upvalue_index(1)); - return fx(L); - } - } // function_detail -} // sol - -// end of sol/function_types_core.hpp - -// beginning of sol/function_types_templated.hpp - -// beginning of sol/call.hpp - -// beginning of sol/protect.hpp - -namespace sol { - - template <typename T> - struct protect_t { - T value; - - template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler> - protect_t(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - - protect_t(const protect_t&) = default; - protect_t(protect_t&&) = default; - protect_t& operator=(const protect_t&) = default; - protect_t& operator=(protect_t&&) = default; - - }; - - template <typename T> - auto protect(T&& value) { - return protect_t<std::decay_t<T>>(std::forward<T>(value)); - } - -} // sol - -// end of sol/protect.hpp - -// beginning of sol/property.hpp - -namespace sol { - - struct no_prop { }; - - template <typename R, typename W> - struct property_wrapper { - typedef std::integral_constant<bool, !std::is_void<R>::value> can_read; - typedef std::integral_constant<bool, !std::is_void<W>::value> can_write; - typedef std::conditional_t<can_read::value, R, no_prop> Read; - typedef std::conditional_t<can_write::value, W, no_prop> Write; - Read read; - Write write; - - template <typename Rx, typename Wx> - property_wrapper(Rx&& r, Wx&& w) : read(std::forward<Rx>(r)), write(std::forward<Wx>(w)) {} - }; - - namespace property_detail { - template <typename R, typename W> - inline decltype(auto) property(std::true_type, R&& read, W&& write) { - return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write)); - } - template <typename W, typename R> - inline decltype(auto) property(std::false_type, W&& write, R&& read) { - return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write)); - } - template <typename R> - inline decltype(auto) property(std::true_type, R&& read) { - return property_wrapper<std::decay_t<R>, void>(std::forward<R>(read), no_prop()); - } - template <typename W> - inline decltype(auto) property(std::false_type, W&& write) { - return property_wrapper<void, std::decay_t<W>>(no_prop(), std::forward<W>(write)); - } - } // property_detail - - template <typename F, typename G> - inline decltype(auto) property(F&& f, G&& g) { - typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; - typedef lua_bind_traits<meta::unqualified_t<G>> right_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward<F>(f), std::forward<G>(g)); - } - - template <typename F> - inline decltype(auto) property(F&& f) { - typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward<F>(f)); - } - - template <typename F> - inline decltype(auto) readonly_property(F&& f) { - return property_detail::property(std::true_type(), std::forward<F>(f)); - } - - // Allow someone to make a member variable readonly (const) - template <typename R, typename T> - inline auto readonly(R T::* v) { - typedef const R C; - return static_cast<C T::*>(v); - } - - template <typename T> - struct var_wrapper { - T value; - template <typename... Args> - var_wrapper(Args&&... args) : value(std::forward<Args>(args)...) {} - var_wrapper(const var_wrapper&) = default; - var_wrapper(var_wrapper&&) = default; - var_wrapper& operator=(const var_wrapper&) = default; - var_wrapper& operator=(var_wrapper&&) = default; - }; - - template <typename V> - inline auto var(V&& v) { - typedef meta::unqualified_t<V> T; - return var_wrapper<T>(std::forward<V>(v)); - } - -} // sol - -// end of sol/property.hpp - -namespace sol { - namespace call_detail { - - template <typename R, typename W> - inline auto& pick(std::true_type, property_wrapper<R, W>& f) { - return f.read; - } - - template <typename R, typename W> - inline auto& pick(std::false_type, property_wrapper<R, W>& f) { - return f.write; - } - - template <typename T, typename List> - struct void_call; - - template <typename T, typename... Args> - struct void_call<T, types<Args...>> { - static void call(Args...) {} - }; - - template <typename T> - struct constructor_match { - T* obj; - - constructor_match(T* o) : obj(o) {} - - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const { - detail::default_construct func{}; - return stack::call_into_lua<stack::stack_detail::default_check_arguments>(r, a, L, start, func, obj); - } - }; - - namespace overload_detail { - template <std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) { - return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); - } - - template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; - typedef meta::tuple_types<typename traits::return_type> return_types; - typedef typename traits::free_args_list args_list; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { - return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - stack::record tracking{}; - if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); - } - - template <std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; - typedef meta::tuple_types<typename traits::return_type> return_types; - typedef typename traits::free_args_list args_list; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; - typedef meta::tuple_types<typename traits::return_type> return_types; - typedef typename traits::free_args_list args_list; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { - return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - stack::record tracking{}; - if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); - } - } // overload_detail - - template <typename... Functions, typename Match, typename... Args> - inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename... Functions, typename Match, typename... Args> - inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { - int fxarity = lua_gettop(L) - (start - 1); - return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename T, typename... TypeLists, typename Match, typename... Args> - inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - // use same overload resolution matching as all other parts of the framework - return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename T, typename... TypeLists> - inline int construct(lua_State* L) { - static const auto& meta = usertype_traits<T>::metatable(); - int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot; - argcount -= static_cast<int>(syntax); - - T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast<T*>(pointerpointer + 1); - referencepointer = obj; - reference userdataref(L, -1); - userdataref.pop(); - - construct_match<T, TypeLists...>(constructor_match<T>(obj), L, argcount, 1 + static_cast<int>(syntax)); - - userdataref.push(); - luaL_getmetatable(L, &meta[0]); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return luaL_error(L, "sol: unable to get usertype metatable"); - } - - lua_setmetatable(L, -2); - return 1; - } - - template <typename F, bool is_index, bool is_variable, bool checked, int boost, typename = void> - struct agnostic_lua_call_wrapper { - template <typename Fx, typename... Args> - static int call(lua_State* L, Fx&& f, Args&&... args) { - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::returns_list returns_list; - typedef typename wrap::free_args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...); - } - }; - - template <typename T, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<var_wrapper<T>, true, is_variable, checked, boost, C> { - template <typename F> - static int call(lua_State* L, F&& f) { - return stack::push_reference(L, detail::unwrap(f.value)); - } - }; - - template <typename T, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<var_wrapper<T>, false, is_variable, checked, boost, C> { - template <typename V> - static int call_assign(std::true_type, lua_State* L, V&& f) { - detail::unwrap(f.value) = stack::get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1)); - return 0; - } - - template <typename... Args> - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template <typename... Args> - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef meta::unwrapped_t<T> R; - return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...); - } - - template <typename... Args> - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template <typename V> - static int call(lua_State* L, V&& f) { - return call_const(std::is_const<meta::unwrapped_t<T>>(), L, f); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, lua_r_CFunction f) { - return f(L); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, lua_CFunction f) { - return f(L); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, const no_prop&) { - return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, const no_construction&) { - return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); - } - }; - - template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, C> { - static int call(lua_State*, const bases<Args...>&) { - // Uh. How did you even call this, lul - return 0; - } - }; - - template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void> - struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {}; - - template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, F, is_index, is_variable, checked, boost, std::enable_if_t<std::is_member_function_pointer<F>::value>> { - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::object_type object_type; - - template <typename Fx> - static int call(lua_State* L, Fx&& f, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward<Fx>(f), o); - } - - template <typename Fx> - static int call(lua_State* L, Fx&& f) { - typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - return luaL_error(L, "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); - return call(L, std::forward<Fx>(f), *o); -#else - object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); - return call(L, std::forward<Fx>(f), o); -#endif // Safety - } - }; - - template <typename T, typename F, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, F, false, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::object_type object_type; - - template <typename V> - static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(types<void>(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); - } - - template <typename V> - static int call_assign(std::true_type, lua_State* L, V&& f) { - typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); - } - return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); - return call_assign(std::true_type(), L, f, *o); -#else - object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); - return call_assign(std::true_type(), L, f, o); -#endif // Safety - } - - template <typename... Args> - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template <typename... Args> - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef typename traits_type::return_type R; - return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...); - } - - template <typename... Args> - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template <typename V> - static int call(lua_State* L, V&& f) { - return call_const(std::is_const<typename traits_type::return_type>(), L, f); - } - - template <typename V> - static int call(lua_State* L, V&& f, object_type& o) { - return call_const(std::is_const<typename traits_type::return_type>(), L, f, o); - } - }; - - template <typename T, typename F, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, F, true, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::object_type object_type; - - template <typename V> - static int call(lua_State* L, V&& f, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); - } - - template <typename V> - static int call(lua_State* L, V&& f) { - typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); - return call(L, f, *o); -#else - object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); - return call(L, f, o); -#endif // Safety - } - }; - - template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, constructor_list<Args...>, is_index, is_variable, checked, boost, C> { - typedef constructor_list<Args...> F; - - static int call(lua_State* L, F&) { - const auto& metakey = usertype_traits<T>::metatable(); - int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot; - argcount -= static_cast<int>(syntax); - - T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - reference userdataref(L, -1); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast<T*>(pointerpointer + 1); - referencepointer = obj; - - construct_match<T, Args...>(constructor_match<T>(obj), L, argcount, boost + 1 + static_cast<int>(syntax)); - - userdataref.push(); - luaL_getmetatable(L, &metakey[0]); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return luaL_error(L, "sol: unable to get usertype metatable"); - } - - lua_setmetatable(L, -2); - return 1; - } - }; - - template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, C> { - typedef constructor_wrapper<Cxs...> F; - - struct onmatch { - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) { - const auto& metakey = usertype_traits<T>::metatable(); - T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - reference userdataref(L, -1); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast<T*>(pointerpointer + 1); - referencepointer = obj; - - auto& func = std::get<I>(f.functions); - stack::call_into_lua<checked>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj)); - - userdataref.push(); - luaL_getmetatable(L, &metakey[0]); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - std::string err = "sol: unable to get usertype metatable for "; - err += usertype_traits<T>::name(); - return luaL_error(L, err.c_str()); - } - lua_setmetatable(L, -2); - - return 1; - } - }; - - static int call(lua_State* L, F& f) { - call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1); - int syntaxval = static_cast<int>(syntax); - int argcount = lua_gettop(L) - syntaxval; - return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f); - } - - }; - - template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<std::is_void<Fx>::value>> { - typedef destructor_wrapper<Fx> F; - - static int call(lua_State* L, const F&) { - return detail::usertype_alloc_destroy<T>(L); - } - }; - - template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<!std::is_void<Fx>::value>> { - typedef destructor_wrapper<Fx> F; - - static int call(lua_State* L, const F& f) { - T& obj = stack::get<T>(L); - f.fx(detail::implicit_wrapper<T>(obj)); - return 0; - } - }; - - template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, C> { - typedef overload_set<Fs...> F; - - struct on_match { - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { - auto& f = std::get<I>(fx.functions); - return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost>{}.call(L, f); - } - }; - - static int call(lua_State* L, F& fx) { - return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); - } - }; - - template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, factory_wrapper<Fs...>, is_index, is_variable, checked, boost, C> { - typedef factory_wrapper<Fs...> F; - - struct on_match { - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { - auto& f = std::get<I>(fx.functions); - return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost>{}.call(L, f); - } - }; - - static int call(lua_State* L, F& fx) { - return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx); - } - }; - - template <typename T, typename R, typename W, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, property_wrapper<R, W>, is_index, is_variable, checked, boost, C> { - typedef std::conditional_t<is_index, R, W> P; - typedef meta::unqualified_t<P> U; - typedef lua_bind_traits<U> traits_type; - - template <typename F> - static int self_call(lua_State* L, F&& f) { - typedef wrapper<U> wrap; - typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type; - typedef meta::pop_front_type_t<typename traits_type::free_args_list> args_list; - typedef T Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); -#else - object_type* o = static_cast<object_type*>(stack::get<non_null<Ta*>>(L, 1)); -#endif // Safety - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, *o); - } - - template <typename F, typename... Args> - static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { - return self_call(L, pick(meta::boolean<is_index>(), f), std::forward<Args>(args)...); - } - - template <typename F, typename... Args> - static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { - auto& p = pick(meta::boolean<is_index>(), std::forward<F>(f)); - return lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost>{}.call(L, p, std::forward<Args>(args)...); - } - - template <typename F, typename... Args> - static int call(lua_State* L, F&& f, Args&&... args) { - typedef meta::any< - std::is_void<U>, - std::is_same<U, no_prop>, - meta::is_specialization_of<var_wrapper, U>, - meta::is_specialization_of<constructor_wrapper, U>, - meta::is_specialization_of<constructor_list, U>, - std::is_member_pointer<U> - > is_specialized; - return defer_call(is_specialized(), L, std::forward<F>(f), std::forward<Args>(args)...); - } - }; - - template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, C> { - typedef protect_t<V> F; - - template <typename... Args> - static int call(lua_State* L, F& fx, Args&&... args) { - return lua_call_wrapper<T, V, is_index, is_variable, true, boost>{}.call(L, fx.value, std::forward<Args>(args)...); - } - }; - - template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, C> { - template <typename F> - static int call(lua_State* L, F&& f) { - return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::get<0>(f.arguments)); - } - }; - - template <typename T, bool is_index, bool is_variable, int boost = 0, typename Fx, typename... Args> - inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { - return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename T, bool is_index, bool is_variable, typename F> - inline int call_user(lua_State* L) { - auto& fx = stack::get<user<F>>(L, upvalue_index(1)); - return call_wrapped<T, is_index, is_variable>(L, fx); - } - - template <typename T, typename = void> - struct is_var_bind : std::false_type {}; - - template <typename T> - struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {}; - - template <> - struct is_var_bind<no_prop> : std::true_type {}; - - template <typename R, typename W> - struct is_var_bind<property_wrapper<R, W>> : std::true_type {}; - - template <typename T> - struct is_var_bind<var_wrapper<T>> : std::true_type {}; - } // call_detail - - template <typename T> - struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {}; - - template <typename T> - struct is_function_binding : meta::neg<is_variable_binding<T>> {}; - -} // sol - -// end of sol/call.hpp - -namespace sol { - namespace function_detail { - template <typename F, F fx> - inline int call_wrapper_variable(std::false_type, lua_State* L) { - typedef meta::bind_traits<meta::unqualified_t<F>> traits_type; - typedef typename traits_type::args_list args_list; - typedef meta::tuple_types<typename traits_type::return_type> return_type; - return stack::call_into_lua(return_type(), args_list(), L, 1, fx); - } - - template <typename R, typename V, V, typename T> - inline int call_set_assignable(std::false_type, T&&, lua_State* L) { - return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); - } - - template <typename R, typename V, V variable, typename T> - inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { - (mem.*variable) = stack::get<R>(L, 2); - return 0; - } - - template <typename R, typename V, V, typename T> - inline int call_set_variable(std::false_type, lua_State* L, T&&) { - return luaL_error(L, "cannot write to a const variable"); - } - - template <typename R, typename V, V variable, typename T> - inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { - return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem)); - } - - template <typename V, V variable> - inline int call_wrapper_variable(std::true_type, lua_State* L) { - typedef meta::bind_traits<meta::unqualified_t<V>> traits_type; - typedef typename traits_type::object_type T; - typedef typename traits_type::return_type R; - auto& mem = stack::get<T>(L, 1); - switch (lua_gettop(L)) { - case 1: { - decltype(auto) r = (mem.*variable); - stack::push_reference(L, std::forward<decltype(r)>(r)); - return 1; } - case 2: - return call_set_variable<R, V, variable>(meta::neg<std::is_const<R>>(), L, mem); - default: - return luaL_error(L, "incorrect number of arguments to member variable function call"); - } - } - - template <typename F, F fx> - inline int call_wrapper_function(std::false_type, lua_State* L) { - return call_wrapper_variable<F, fx>(std::is_member_object_pointer<F>(), L); - } - - template <typename F, F fx> - inline int call_wrapper_function(std::true_type, lua_State* L) { - return call_detail::call_wrapped<void, false, false>(L, fx); - } - - template <typename F, F fx> - int call_wrapper_entry(lua_State* L) { - return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L); - } - - template <typename... Fxs> - struct c_call_matcher { - template <typename Fx, std::size_t I, typename R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R>, types<Args...>, lua_State* L, int, int) const { - typedef meta::at_in_pack_t<I, Fxs...> target; - return target::call(L); - } - }; - - } // function_detail - - template <typename F, F fx> - inline int c_call(lua_State* L) { -#ifdef __clang__ - return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>); -#else - return detail::static_trampoline<(&function_detail::call_wrapper_entry<F, fx>)>(L); -#endif // fuck you clang :c - } - - template <typename F, F f> - struct wrap { - typedef F type; - - static int call(lua_State* L) { - return c_call<type, f>(L); - } - }; - - template <typename... Fxs> - inline int c_call(lua_State* L) { - if (sizeof...(Fxs) < 2) { - return meta::at_in_pack_t<0, Fxs...>::call(L); - } - else { - return call_detail::overload_match_arity<typename Fxs::type...>(function_detail::c_call_matcher<Fxs...>(), L, lua_gettop(L), 1); - } - } - -} // sol - -// end of sol/function_types_templated.hpp - -// beginning of sol/function_types_stateless.hpp - -namespace sol { - namespace function_detail { - template<typename Function> - struct upvalue_free_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L); - function_type* fx = udata.first; - return call_detail::call_wrapped<void, true, false>(L, fx); - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_member_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member function pointer - // idx n + 1: is the object's void pointer - // We don't need to store the size, because the other side is templated - // with the same member function pointer type - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); - function_type& memfx = memberdata.first; - auto& item = *objdata.first; - return call_detail::call_wrapped<T, true, false, -1>(L, memfx, item); - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_member_variable { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - // idx n + 1: is the object's void pointer - // We don't need to store the size, because the other side is templated - // with the same member function pointer type - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); - auto& mem = *objdata.first; - function_type& var = memberdata.first; - switch (lua_gettop(L)) { - case 0: - return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); - case 1: - return call_detail::call_wrapped<T, false, false, -1>(L, var, mem); - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_this_member_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - function_type& memfx = memberdata.first; - return call_detail::call_wrapped<T, false, false>(L, memfx); - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_this_member_variable { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - function_type& var = memberdata.first; - switch (lua_gettop(L)) { - case 1: - return call_detail::call_wrapped<T, true, false>(L, var); - case 2: - return call_detail::call_wrapped<T, false, false>(L, var); - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - } // function_detail -} // sol - -// end of sol/function_types_stateless.hpp - -// beginning of sol/function_types_stateful.hpp - -namespace sol { - namespace function_detail { - template<typename Func> - struct functor_function { - typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function; - Function fx; - - template<typename... Args> - functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward<Args>(args)...) {} - - int call(lua_State* L) { - return call_detail::call_wrapped<void, true, false>(L, fx); - } - - int operator()(lua_State* L) { - auto f = [&](lua_State*) -> int { return this->call(L); }; - return detail::trampoline(L, f); - } - }; - - template<typename T, typename Function> - struct member_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef meta::function_return_t<function_type> return_type; - typedef meta::function_args_t<function_type> args_lists; - function_type invocation; - T member; - - template<typename... Args> - member_function(function_type f, Args&&... args) : invocation(std::move(f)), member(std::forward<Args>(args)...) {} - - int call(lua_State* L) { - return call_detail::call_wrapped<T, true, false, -1>(L, invocation, detail::unwrap(detail::deref(member))); - } - - int operator()(lua_State* L) { - auto f = [&](lua_State*) -> int { return this->call(L); }; - return detail::trampoline(L, f); - } - }; - - template<typename T, typename Function> - struct member_variable { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef typename meta::bind_traits<function_type>::return_type return_type; - typedef typename meta::bind_traits<function_type>::args_list args_lists; - function_type var; - T member; - typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M; - - template<typename... Args> - member_variable(function_type v, Args&&... args) : var(std::move(v)), member(std::forward<Args>(args)...) {} - - int call(lua_State* L) { - M mem = detail::unwrap(detail::deref(member)); - switch (lua_gettop(L)) { - case 0: - return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); - case 1: - return call_detail::call_wrapped<T, false, false, -1>(L, var, mem); - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } - - int operator()(lua_State* L) { - auto f = [&](lua_State*) -> int { return this->call(L); }; - return detail::trampoline(L, f); - } - }; - } // function_detail -} // sol - -// end of sol/function_types_stateful.hpp - -// beginning of sol/function_types_overloaded.hpp - -namespace sol { - namespace function_detail { - template <typename... Functions> - struct overloaded_function { - typedef std::tuple<Functions...> overload_list; - typedef std::make_index_sequence<sizeof...(Functions)> indices; - overload_list overloads; - - overloaded_function(overload_list set) - : overloads(std::move(set)) {} - - overloaded_function(Functions... fxs) - : overloads(fxs...) { - - } - - template <typename Fx, std::size_t I, typename... R, typename... Args> - int call(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int) { - auto& func = std::get<I>(overloads); - return call_detail::call_wrapped<void, true, false>(L, func); - } - - int operator()(lua_State* L) { - auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); }; - return call_detail::overload_match<Functions...>(mfx, L, 1); - } - }; - } // function_detail -} // sol - -// end of sol/function_types_overloaded.hpp - -// beginning of sol/resolve.hpp - -namespace sol { - -#ifndef __clang__ - // constexpr is fine for not-clang - - namespace detail { - template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> - inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) { - using Sig = R(Args...); - typedef meta::unqualified_t<F> Fu; - return static_cast<Sig Fu::*>(&Fu::operator()); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline constexpr auto resolve_f(std::true_type, F&& f) - -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { - return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); - } - - template<typename F> - inline constexpr void resolve_f(std::false_type, F&&) { - static_assert(meta::has_deducible_signature<F>::value, - "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) { - return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f)); - } - - template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>> - inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { - return resolve_i(types<R(Args...)>(), std::forward<F>(f)); - } - - template<typename Sig, typename C> - inline constexpr Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { - return mem_func_ptr; - } - - template<typename Sig, typename C> - inline constexpr Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { - return mem_variable_ptr; - } - } // detail - - template<typename... Args, typename R> - inline constexpr auto resolve(R fun_ptr(Args...))->R(*)(Args...) { - return fun_ptr; - } - - template<typename Sig> - inline constexpr Sig* resolve(Sig* fun_ptr) { - return fun_ptr; - } - - template<typename... Args, typename R, typename C> - inline constexpr auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { - return mem_ptr; - } - - template<typename Sig, typename C> - inline constexpr Sig C::* resolve(Sig C::* mem_ptr) { - return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); - } - - template<typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler> - inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { - return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); - } -#else - - // Clang has distinct problems with constexpr arguments, - // so don't use the constexpr versions inside of clang. - - namespace detail { - template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> - inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) { - using Sig = R(Args...); - typedef meta::unqualified_t<F> Fu; - return static_cast<Sig Fu::*>(&Fu::operator()); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline auto resolve_f(std::true_type, F&& f) - -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { - return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); - } - - template<typename F> - inline void resolve_f(std::false_type, F&&) { - static_assert(meta::has_deducible_signature<F>::value, - "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) { - return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f)); - } - - template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>> - inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { - return resolve_i(types<R(Args...)>(), std::forward<F>(f)); - } - - template<typename Sig, typename C> - inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { - return mem_func_ptr; - } - - template<typename Sig, typename C> - inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { - return mem_variable_ptr; - } - } // detail - - template<typename... Args, typename R> - inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) { - return fun_ptr; - } - - template<typename Sig> - inline Sig* resolve(Sig* fun_ptr) { - return fun_ptr; - } - - template<typename... Args, typename R, typename C> - inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { - return mem_ptr; - } - - template<typename Sig, typename C> - inline Sig C::* resolve(Sig C::* mem_ptr) { - return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); - } - - template<typename... Sig, typename F> - inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { - return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); - } - -#endif - -} // sol - -// end of sol/resolve.hpp - -namespace sol { - namespace stack { - template<typename... Sigs> - struct pusher<function_sig<Sigs...>> { - template <typename... Sig, typename Fx, typename... Args> - static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; - typedef function_detail::functor_function<clean_fx> F; - set_fx<F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename R, typename... A, typename Fx, typename... Args> - static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) { - using fx_ptr_t = R(*)(A...); - fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx)); - select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...); - } - - template <typename R, typename... A, typename Fx, typename... Args> - static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t; - typedef R(*fx_ptr_t)(A...); - typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible; - select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { - typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig; - select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; - typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx> F; - set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t<Fx> dFx; - dFx memfxptr(std::forward<Fx>(fx)); - auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename... Args> - static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; - select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx> - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t<Fx> clean_fx; - typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx> F; - set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t<Fx> dFx; - dFx memfxptr(std::forward<Fx>(fx)); - auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename... Args> - static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; - select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx> - static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename... Args> - static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { - std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...); - lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, target); - stack::push(L, c_closure(freefunc, upvalues)); - } - - static void select_function(std::true_type, lua_State* L, lua_CFunction f) { - stack::push(L, f); - } - - template <typename Fx, typename... Args> - static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static void set_fx(lua_State* L, Args&&... args) { - lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>>; - - stack::push<user<Fx>>(L, std::forward<Args>(args)...); - stack::push(L, c_closure(freefunc, 1)); - } - - template<typename... Args> - static int push(lua_State* L, Args&&... args) { - // Set will always place one thing (function) on the stack - select(L, std::forward<Args>(args)...); - return 1; - } - }; - - template<typename T, typename... Args> - struct pusher<function_arguments<T, Args...>> { - template <std::size_t... I, typename FP> - static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) { - return stack::push<T>(L, detail::forward_get<I>(fp.arguments)...); - } - - static int push(lua_State* L, const function_arguments<T, Args...>& fp) { - return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp); - } - - static int push(lua_State* L, function_arguments<T, Args...>&& fp) { - return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp)); - } - }; - - template<typename Signature> - struct pusher<std::function<Signature>> { - static int push(lua_State* L, std::function<Signature> fx) { - return pusher<function_sig<Signature>>{}.push(L, std::move(fx)); - } - }; - - template<typename Signature> - struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> { - template <typename F> - static int push(lua_State* L, F&& f) { - return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); - } - }; - - template<typename Signature> - struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> { - template <typename F> - static int push(lua_State* L, F&& f) { - return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); - } - }; - - template<typename... Functions> - struct pusher<overload_set<Functions...>> { - static int push(lua_State* L, overload_set<Functions...>&& set) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions)); - return 1; - } - - static int push(lua_State* L, const overload_set<Functions...>& set) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, set.functions); - return 1; - } - }; - - template <typename T> - struct pusher<protect_t<T>> { - static int push(lua_State* L, protect_t<T>&& pw) { - lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>; - int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value)); - return stack::push(L, c_closure(cf, closures)); - } - - static int push(lua_State* L, const protect_t<T>& pw) { - lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>; - int closures = stack::push<user<protect_t<T>>>(L, pw.value); - return stack::push(L, c_closure(cf, closures)); - } - }; - - template <typename F, typename G> - struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> { - static int push(lua_State* L, property_wrapper<F, G>&& pw) { - return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); - } - static int push(lua_State* L, const property_wrapper<F, G>& pw) { - return stack::push(L, sol::overload(pw.read, pw.write)); - } - }; - - template <typename F> - struct pusher<property_wrapper<F, void>> { - static int push(lua_State* L, property_wrapper<F, void>&& pw) { - return stack::push(L, std::move(pw.read)); - } - static int push(lua_State* L, const property_wrapper<F, void>& pw) { - return stack::push(L, pw.read); - } - }; - - template <typename F> - struct pusher<property_wrapper<void, F>> { - static int push(lua_State* L, property_wrapper<void, F>&& pw) { - return stack::push(L, std::move(pw.write)); - } - static int push(lua_State* L, const property_wrapper<void, F>& pw) { - return stack::push(L, pw.write); - } - }; - - template <typename T> - struct pusher<var_wrapper<T>> { - static int push(lua_State* L, var_wrapper<T>&& vw) { - return stack::push(L, std::move(vw.value)); - } - static int push(lua_State* L, const var_wrapper<T>& vw) { - return stack::push(L, vw.value); - } - }; - - template <typename... Functions> - struct pusher<factory_wrapper<Functions...>> { - static int push(lua_State* L, const factory_wrapper<Functions...>& fw) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, fw.functions); - return 1; - } - - static int push(lua_State* L, factory_wrapper<Functions...>&& fw) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions)); - return 1; - } - }; - - template <typename T, typename... Lists> - struct pusher<detail::tagged<T, constructor_list<Lists...>>> { - static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) { - lua_CFunction cf = call_detail::construct<T, Lists...>; - return stack::push(L, cf); - } - }; - - template <typename T, typename... Fxs> - struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> { - template <typename C> - static int push(lua_State* L, C&& c) { - lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>; - int closures = stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c)); - return stack::push(L, c_closure(cf, closures)); - } - }; - - template <typename T> - struct pusher<detail::tagged<T, destructor_wrapper<void>>> { - static int push(lua_State* L, destructor_wrapper<void>) { - lua_CFunction cf = detail::usertype_alloc_destroy<T>; - return stack::push(L, cf); - } - }; - - template <typename T, typename Fx> - struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> { - static int push(lua_State* L, destructor_wrapper<Fx> c) { - lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>; - int closures = stack::push<user<T>>(L, std::move(c)); - return stack::push(L, c_closure(cf, closures)); - } - }; - - } // stack -} // sol - -// end of sol/function_types.hpp - -namespace sol { - template <typename base_t> - class basic_function : public base_t { - private: - void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { - lua_callk(base_t::lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), 0, nullptr); - } - - template<std::size_t... I, typename... Ret> - auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) const { - luacall(n, lua_size<std::tuple<Ret...>>::value); - return stack::pop<std::tuple<Ret...>>(base_t::lua_state()); - } - - template<std::size_t I, typename Ret> - Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) const { - luacall(n, lua_size<Ret>::value); - return stack::pop<Ret>(base_t::lua_state()); - } - - template <std::size_t I> - void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const { - luacall(n, 0); - } - - function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { - int stacksize = lua_gettop(base_t::lua_state()); - int firstreturn = (std::max)(1, stacksize - static_cast<int>(n)); - luacall(n, LUA_MULTRET); - int poststacksize = lua_gettop(base_t::lua_state()); - int returncount = poststacksize - (firstreturn - 1); - return function_result(base_t::lua_state(), firstreturn, returncount); - } - - public: - basic_function() = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_function(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_function<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - stack::check<basic_function>(base_t::lua_state(), -1, type_panic); - } -#endif // Safety - } - basic_function(const basic_function&) = default; - basic_function& operator=(const basic_function&) = default; - basic_function(basic_function&&) = default; - basic_function& operator=(basic_function&&) = default; - basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} - basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_function(lua_State* L, T&& r) : basic_function(L, sol::ref_index(r.registry_index())) {} - basic_function(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<basic_function>(L, index, type_panic); -#endif // Safety - } - basic_function(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<basic_function>(L, -1, type_panic); -#endif // Safety - } - - template<typename... Args> - function_result operator()(Args&&... args) const { - return call<>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) operator()(types<Ret...>, Args&&... args) const { - return call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) const { - base_t::push(); - int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward<Args>(args)...); - return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); - } - }; - - namespace stack { - template<typename Signature> - struct getter<std::function<Signature>> { - typedef meta::bind_traits<Signature> fx_t; - typedef typename fx_t::args_list args_lists; - typedef meta::tuple_types<typename fx_t::return_type> return_types; - - template<typename... Args, typename... Ret> - static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index) { - sol::function f(L, index); - auto fx = [f, L, index](Args&&... args) -> meta::return_type_t<Ret...> { - return f.call<Ret...>(std::forward<Args>(args)...); - }; - return std::move(fx); - } - - template<typename... FxArgs> - static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index) { - sol::function f(L, index); - auto fx = [f, L, index](FxArgs&&... args) -> void { - f(std::forward<FxArgs>(args)...); - }; - return std::move(fx); - } - - template<typename... FxArgs> - static std::function<Signature> get_std_func(types<>, types<FxArgs...> t, lua_State* L, int index) { - return get_std_func(types<void>(), t, L, index); - } - - static std::function<Signature> get(lua_State* L, int index, record& tracking) { - tracking.last = 1; - tracking.used += 1; - type t = type_of(L, index); - if (t == type::none || t == type::lua_nil) { - return nullptr; - } - return get_std_func(return_types(), args_lists(), L, index); - } - }; - } // stack -} // sol - -// end of sol/function.hpp - -// beginning of sol/protected_function.hpp - -// beginning of sol/protected_function_result.hpp - -namespace sol { - struct protected_function_result : public proxy_base<protected_function_result> { - private: - lua_State* L; - int index; - int returncount; - int popcount; - call_status err; - - template <typename T> - decltype(auto) tagged_get(types<sol::optional<T>>) const { - if (!valid()) { - return sol::optional<T>(nullopt); - } - return stack::get<sol::optional<T>>(L, index); - } - - template <typename T> - decltype(auto) tagged_get(types<T>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (!valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return stack::get<T>(L, index); - } - - optional<error> tagged_get(types<optional<error>>) const { - if (valid()) { - return nullopt; - } - return error(detail::direct_error, stack::get<std::string>(L, index)); - } - - error tagged_get(types<error>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return error(detail::direct_error, stack::get<std::string>(L, index)); - } - - public: - protected_function_result() = default; - protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) { - - } - protected_function_result(const protected_function_result&) = default; - protected_function_result& operator=(const protected_function_result&) = default; - protected_function_result(protected_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = call_status::runtime; - } - protected_function_result& operator=(protected_function_result&& o) noexcept { - L = o.L; - index = o.index; - returncount = o.returncount; - popcount = o.popcount; - err = o.err; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = call_status::runtime; - return *this; - } - - call_status status() const noexcept { - return err; - } - - bool valid() const noexcept { - return status() == call_status::ok || status() == call_status::yielded; - } - - template<typename T> - decltype(auto) get() const { - return tagged_get(types<meta::unqualified_t<T>>()); - } - - lua_State* lua_state() const noexcept { return L; }; - int stack_index() const noexcept { return index; }; - - ~protected_function_result() { - stack::remove(L, index, popcount); - } - }; -} // sol - -// end of sol/protected_function_result.hpp - -#include <algorithm> - -namespace sol { - namespace detail { - inline reference& handler_storage() { - static sol::reference h; - return h; - } - - struct handler { - const reference& target; - int stackindex; - handler(const reference& target) : target(target), stackindex(0) { - if (target.valid()) { - stackindex = lua_gettop(target.lua_state()) + 1; - target.push(); - } - } - bool valid() const { return stackindex != 0; } - ~handler() { - if (valid()) { - lua_remove(target.lua_state(), stackindex); - } - } - }; - } - - template <typename base_t> - class basic_protected_function : public base_t { - public: - static reference& get_default_handler() { - return detail::handler_storage(); - } - - static void set_default_handler(const reference& ref) { - detail::handler_storage() = ref; - } - - static void set_default_handler(reference&& ref) { - detail::handler_storage() = std::move(ref); - } - - private: - call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler& h) const { - return static_cast<call_status>(lua_pcallk(base_t::lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr)); - } - - template<std::size_t... I, typename... Ret> - auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::handler& h) const { - luacall(n, sizeof...(Ret), h); - return stack::pop<std::tuple<Ret...>>(base_t::lua_state()); - } - - template<std::size_t I, typename Ret> - Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler& h) const { - luacall(n, 1, h); - return stack::pop<Ret>(base_t::lua_state()); - } - - template <std::size_t I> - void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler& h) const { - luacall(n, 0, h); - } - - protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler& h) const { - int stacksize = lua_gettop(base_t::lua_state()); - int poststacksize = stacksize; - int firstreturn = 1; - int returncount = 0; - call_status code = call_status::ok; -#ifndef SOL_NO_EXCEPTIONS - auto onexcept = [&](const char* error) { - h.stackindex = 0; - if (h.target.valid()) { - h.target.push(); - stack::push(base_t::lua_state(), error); - lua_call(base_t::lua_state(), 1, 1); - } - else { - stack::push(base_t::lua_state(), error); - } - }; - try { -#endif // No Exceptions - firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid()))); - code = luacall(n, LUA_MULTRET, h); - poststacksize = lua_gettop(base_t::lua_state()) - static_cast<int>(h.valid()); - returncount = poststacksize - (firstreturn - 1); -#ifndef SOL_NO_EXCEPTIONS - } - // Handle C++ errors thrown from C++ functions bound inside of lua - catch (const char* error) { - onexcept(error); - firstreturn = lua_gettop(base_t::lua_state()); - return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); - } - catch (const std::exception& error) { - onexcept(error.what()); - firstreturn = lua_gettop(base_t::lua_state()); - return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); - } - catch (...) { - onexcept("caught (...) unknown error during protected_function call"); - firstreturn = lua_gettop(base_t::lua_state()); - return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); - } -#endif // No Exceptions - return protected_function_result(base_t::lua_state(), firstreturn, returncount, returncount, code); - } - - public: - reference error_handler; - - basic_protected_function() = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_function<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - stack::check<basic_protected_function>(base_t::lua_state(), -1, type_panic); - } -#endif // Safety - } - basic_protected_function(const basic_protected_function&) = default; - basic_protected_function& operator=(const basic_protected_function&) = default; - basic_protected_function(basic_protected_function&&) = default; - basic_protected_function& operator=(basic_protected_function&&) = default; - basic_protected_function(const basic_function<base_t>& b, reference eh = get_default_handler()) : base_t(b), error_handler(std::move(eh)) {} - basic_protected_function(basic_function<base_t>&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} - basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} - basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} - template <typename Super> - basic_protected_function(proxy_base<Super>&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function<base_t>(), std::move(eh)) {} - template <typename Super> - basic_protected_function(const proxy_base<Super>& p, reference eh = get_default_handler()) : basic_protected_function(static_cast<basic_function<base_t>>(p), std::move(eh)) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_protected_function(lua_State* L, T&& r, reference eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {} - basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<basic_protected_function>(L, index, type_panic); -#endif // Safety - } - basic_protected_function(lua_State* L, ref_index index, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<basic_protected_function>(L, -1, type_panic); -#endif // Safety - } - - template<typename... Args> - protected_function_result operator()(Args&&... args) const { - return call<>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) operator()(types<Ret...>, Args&&... args) const { - return call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) const { - detail::handler h(error_handler); - base_t::push(); - int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward<Args>(args)...); - return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); - } - }; -} // sol - -// end of sol/protected_function.hpp - -namespace sol { - struct stack_proxy : public proxy_base<stack_proxy> { - private: - lua_State* L; - int index; - - public: - stack_proxy() : L(nullptr), index(0) {} - stack_proxy(lua_State* L, int index) : L(L), index(index) {} - - template<typename T> - decltype(auto) get() const { - return stack::get<T>(L, stack_index()); - } - - int push() const { - return push(L); - } - - int push(lua_State* Ls) const { - lua_pushvalue(Ls, index); - return 1; - } - - lua_State* lua_state() const { return L; } - int stack_index() const { return index; } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - return get<function>().template call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Args> - decltype(auto) operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - }; - - namespace stack { - template <> - struct getter<stack_proxy> { - static stack_proxy get(lua_State* L, int index = -1) { - return stack_proxy(L, index); - } - }; - - template <> - struct pusher<stack_proxy> { - static int push(lua_State*, const stack_proxy& ref) { - return ref.push(); - } - }; - } // stack - - namespace detail { - template <> - struct is_speshul<function_result> : std::true_type {}; - template <> - struct is_speshul<protected_function_result> : std::true_type {}; - - template <std::size_t I, typename... Args, typename T> - stack_proxy get(types<Args...>, index_value<0>, index_value<I>, const T& fr) { - return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); - } - - template <std::size_t I, std::size_t N, typename Arg, typename... Args, typename T, meta::enable<meta::boolean<(N > 0)>> = meta::enabler> - stack_proxy get(types<Arg, Args...>, index_value<N>, index_value<I>, const T& fr) { - return get(types<Args...>(), index_value<N - 1>(), index_value<I + lua_size<Arg>::value>(), fr); - } - } - - template <> - struct tie_size<function_result> : std::integral_constant<std::size_t, SIZE_MAX> {}; - - template <std::size_t I> - stack_proxy get(const function_result& fr) { - return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); - } - - template <std::size_t I, typename... Args> - stack_proxy get(types<Args...> t, const function_result& fr) { - return detail::get(t, index_value<I>(), index_value<0>(), fr); - } - - template <> - struct tie_size<protected_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {}; - - template <std::size_t I> - stack_proxy get(const protected_function_result& fr) { - return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); - } - - template <std::size_t I, typename... Args> - stack_proxy get(types<Args...> t, const protected_function_result& fr) { - return detail::get(t, index_value<I>(), index_value<0>(), fr); - } -} // sol - -// end of sol/stack_proxy.hpp - -#include <limits> -#include <iterator> - -namespace sol { - template <bool is_const> - struct va_iterator : std::iterator<std::random_access_iterator_tag, std::conditional_t<is_const, const stack_proxy, stack_proxy>, std::ptrdiff_t, std::conditional_t<is_const, const stack_proxy*, stack_proxy*>, std::conditional_t<is_const, const stack_proxy, stack_proxy>> { - typedef std::iterator<std::random_access_iterator_tag, std::conditional_t<is_const, const stack_proxy, stack_proxy>, std::ptrdiff_t, std::conditional_t<is_const, const stack_proxy*, stack_proxy*>, std::conditional_t<is_const, const stack_proxy, stack_proxy>> base_t; - typedef typename base_t::reference reference; - typedef typename base_t::pointer pointer; - typedef typename base_t::value_type value_type; - typedef typename base_t::difference_type difference_type; - typedef typename base_t::iterator_category iterator_category; - lua_State* L; - int index; - int stacktop; - stack_proxy sp; - - va_iterator() : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()) {} - va_iterator(lua_State* luastate, int idx, int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {} - - reference operator*() { - return stack_proxy(L, index); - } - - pointer operator->() { - sp = stack_proxy(L, index); - return &sp; - } - - va_iterator& operator++ () { - ++index; - return *this; - } - - va_iterator operator++ (int) { - auto r = *this; - this->operator ++(); - return r; - } - - va_iterator& operator-- () { - --index; - return *this; - } - - va_iterator operator-- (int) { - auto r = *this; - this->operator --(); - return r; - } - - va_iterator& operator+= (difference_type idx) { - index += static_cast<int>(idx); - return *this; - } - - va_iterator& operator-= (difference_type idx) { - index -= static_cast<int>(idx); - return *this; - } - - difference_type operator- (const va_iterator& r) const { - return index - r.index; - } - - va_iterator operator+ (difference_type idx) const { - va_iterator r = *this; - r += idx; - return r; - } - - reference operator[](difference_type idx) { - return stack_proxy(L, index + static_cast<int>(idx)); - } - - bool operator==(const va_iterator& r) const { - if (stacktop == (std::numeric_limits<int>::max)()) { - return r.index == r.stacktop; - } - else if (r.stacktop == (std::numeric_limits<int>::max)()) { - return index == stacktop; - } - return index == r.index; - } - - bool operator != (const va_iterator& r) const { - return !(this->operator==(r)); - } - - bool operator < (const va_iterator& r) const { - return index < r.index; - } - - bool operator > (const va_iterator& r) const { - return index > r.index; - } - - bool operator <= (const va_iterator& r) const { - return index <= r.index; - } - - bool operator >= (const va_iterator& r) const { - return index >= r.index; - } - }; - - template <bool is_const> - inline va_iterator<is_const> operator+(typename va_iterator<is_const>::difference_type n, const va_iterator<is_const>& r) { - return r + n; - } - - struct variadic_args { - private: - lua_State* L; - int index; - int stacktop; - - public: - typedef stack_proxy reference_type; - typedef stack_proxy value_type; - typedef stack_proxy* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::size_t size_type; - typedef va_iterator<false> iterator; - typedef va_iterator<true> const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - variadic_args() = default; - variadic_args(lua_State* luastate, int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {} - variadic_args(const variadic_args&) = default; - variadic_args& operator=(const variadic_args&) = default; - variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.stacktop = 0; - } - variadic_args& operator=(variadic_args&& o) { - L = o.L; - index = o.index; - stacktop = o.stacktop; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.stacktop = 0; - return *this; - } - - iterator begin() { return iterator(L, index, stacktop + 1); } - iterator end() { return iterator(L, stacktop + 1, stacktop + 1); } - const_iterator begin() const { return const_iterator(L, index, stacktop + 1); } - const_iterator end() const { return const_iterator(L, stacktop + 1, stacktop + 1); } - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - reverse_iterator rbegin() { return std::reverse_iterator<iterator>(begin()); } - reverse_iterator rend() { return std::reverse_iterator<iterator>(end()); } - const_reverse_iterator rbegin() const { return std::reverse_iterator<const_iterator>(begin()); } - const_reverse_iterator rend() const { return std::reverse_iterator<const_iterator>(end()); } - const_reverse_iterator crbegin() const { return std::reverse_iterator<const_iterator>(cbegin()); } - const_reverse_iterator crend() const { return std::reverse_iterator<const_iterator>(cend()); } - - int push() const { - return push(L); - } - - int push(lua_State* target) const { - int pushcount = 0; - for (int i = index; i <= stacktop; ++i) { - lua_pushvalue(L, i); - pushcount += 1; - } - if (target != L) { - lua_xmove(L, target, pushcount); - } - return pushcount; - } - - template<typename T> - decltype(auto) get(difference_type start = 0) const { - return stack::get<T>(L, index + static_cast<int>(start)); - } - - stack_proxy operator[](difference_type start) const { - return stack_proxy(L, index + static_cast<int>(start)); - } - - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; - int leftover_count() const { return stacktop - (index - 1); } - int top() const { return stacktop; } - }; - - namespace stack { - template <> - struct getter<variadic_args> { - static variadic_args get(lua_State* L, int index, record& tracking) { - tracking.last = 0; - return variadic_args(L, index); - } - }; - - template <> - struct pusher<variadic_args> { - static int push(lua_State* L, const variadic_args& ref) { - return ref.push(L); - } - }; - } // stack -} // sol - -// end of sol/variadic_args.hpp - -namespace sol { - - template <typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename T> - R make_reference(lua_State* L, T&& value) { - int backpedal = stack::push(L, std::forward<T>(value)); - R r = stack::get<R>(L, -backpedal); - if (should_pop) { - lua_pop(L, backpedal); - } - return r; - } - - template <typename T, typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename... Args> - R make_reference(lua_State* L, Args&&... args) { - int backpedal = stack::push<T>(L, std::forward<Args>(args)...); - R r = stack::get<R>(L, -backpedal); - if (should_pop) { - lua_pop(L, backpedal); - } - return r; - } - - template <typename base_t> - class basic_object : public base_t { - private: - template<typename T> - decltype(auto) as_stack(std::true_type) const { - return stack::get<T>(base_t::lua_state(), base_t::stack_index()); - } - - template<typename T> - decltype(auto) as_stack(std::false_type) const { - base_t::push(); - return stack::pop<T>(base_t::lua_state()); - } - - template<typename T> - bool is_stack(std::true_type) const { - return stack::check<T>(base_t::lua_state(), base_t::stack_index(), no_panic); - } - - template<typename T> - bool is_stack(std::false_type) const { - auto pp = stack::push_pop(*this); - return stack::check<T>(base_t::lua_state(), -1, no_panic); - } - - template <bool invert_and_pop = false> - basic_object(std::integral_constant<bool, invert_and_pop>, lua_State* L, int index = -1) noexcept : base_t(L, index) { - if (invert_and_pop) { - lua_pop(L, -index); - } - } - - public: - basic_object() noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_object(T&& r) : base_t(std::forward<T>(r)) {} - basic_object(lua_nil_t r) : base_t(r) {} - basic_object(const basic_object&) = default; - basic_object(basic_object&&) = default; - basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} - basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} - template <typename Super> - basic_object(const proxy_base<Super>& r) noexcept : basic_object(r.operator basic_object()) {} - template <typename Super> - basic_object(proxy_base<Super>&& r) noexcept : basic_object(r.operator basic_object()) {} - basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} - basic_object(lua_State* L, ref_index index) noexcept : base_t(L, index) {} - template <typename T, typename... Args> - basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept : basic_object(std::integral_constant<bool, !std::is_base_of<stack_reference, base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) {} - template <typename T, typename... Args> - basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place<T>, std::forward<T>(arg), std::forward<Args>(args)...) {} - basic_object& operator=(const basic_object&) = default; - basic_object& operator=(basic_object&&) = default; - basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } - basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } - template <typename Super> - basic_object& operator=(const proxy_base<Super>& r) { this->operator=(r.operator basic_object()); return *this; } - template <typename Super> - basic_object& operator=(proxy_base<Super>&& r) { this->operator=(r.operator basic_object()); return *this; } - - template<typename T> - decltype(auto) as() const { - return as_stack<T>(std::is_same<base_t, stack_reference>()); - } - - template<typename T> - bool is() const { - if (!base_t::valid()) - return false; - return is_stack<T>(std::is_same<base_t, stack_reference>()); - } - }; - - template <typename T> - object make_object(lua_State* L, T&& value) { - return make_reference<object, true>(L, std::forward<T>(value)); - } - - template <typename T, typename... Args> - object make_object(lua_State* L, Args&&... args) { - return make_reference<T, object, true>(L, std::forward<Args>(args)...); - } - - inline bool operator==(const object& lhs, const lua_nil_t&) { - return !lhs.valid(); - } - - inline bool operator==(const lua_nil_t&, const object& rhs) { - return !rhs.valid(); - } - - inline bool operator!=(const object& lhs, const lua_nil_t&) { - return lhs.valid(); - } - - inline bool operator!=(const lua_nil_t&, const object& rhs) { - return rhs.valid(); - } -} // sol - -// end of sol/object.hpp - -namespace sol { - template<typename Table, typename Key> - struct proxy : public proxy_base<proxy<Table, Key>> { - private: - typedef meta::condition<meta::is_specialization_of<std::tuple, Key>, Key, std::tuple<meta::condition<std::is_array<meta::unqualified_t<Key>>, Key&, meta::unqualified_t<Key>>>> key_type; - - template<typename T, std::size_t... I> - decltype(auto) tuple_get(std::index_sequence<I...>) const { - return tbl.template traverse_get<T>(std::get<I>(key)...); - } - - template<std::size_t... I, typename T> - void tuple_set(std::index_sequence<I...>, T&& value) { - tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value)); - } - - public: - Table tbl; - key_type key; - - template<typename T> - proxy(Table table, T&& k) : tbl(table), key(std::forward<T>(k)) {} - - template<typename T> - proxy& set(T&& item) { - tuple_set(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>(), std::forward<T>(item)); - return *this; - } - - template<typename... Args> - proxy& set_function(Args&&... args) { - tbl.set_function(key, std::forward<Args>(args)...); - return *this; - } - - template<typename U, meta::enable<meta::neg<is_lua_reference<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> - proxy& operator=(U&& other) { - return set_function(std::forward<U>(other)); - } - - template<typename U, meta::disable<meta::neg<is_lua_reference<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> - proxy& operator=(U&& other) { - return set(std::forward<U>(other)); - } - - template<typename T> - decltype(auto) get() const { - return tuple_get<T>(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>()); - } - - template<typename T> - decltype(auto) get_or(T&& otherwise) const { - typedef decltype(get<T>()) U; - sol::optional<U> option = get<sol::optional<U>>(); - if (option) { - return static_cast<U>(option.value()); - } - return static_cast<U>(std::forward<T>(otherwise)); - } - - template<typename T, typename D> - decltype(auto) get_or(D&& otherwise) const { - sol::optional<T> option = get<sol::optional<T>>(); - if (option) { - return static_cast<T>(option.value()); - } - return static_cast<T>(std::forward<D>(otherwise)); - } - - template <typename K> - decltype(auto) operator[](K&& k) const { - auto keys = meta::tuplefy(key, std::forward<K>(k)); - return proxy<Table, decltype(keys)>(tbl, std::move(keys)); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - return get<function>().template call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Args> - decltype(auto) operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - - bool valid() const { - auto pp = stack::push_pop(tbl); - auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); - lua_pop(tbl.lua_state(), p.levels); - return p; - } - }; - - template<typename Table, typename Key, typename T> - inline bool operator==(T&& left, const proxy<Table, Key>& right) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key, typename T> - inline bool operator==(const proxy<Table, Key>& right, T&& left) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key, typename T> - inline bool operator!=(T&& left, const proxy<Table, Key>& right) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key, typename T> - inline bool operator!=(const proxy<Table, Key>& right, T&& left) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key> - inline bool operator==(lua_nil_t, const proxy<Table, Key>& right) { - return !right.valid(); - } - - template<typename Table, typename Key> - inline bool operator==(const proxy<Table, Key>& right, lua_nil_t) { - return !right.valid(); - } - - template<typename Table, typename Key> - inline bool operator!=(lua_nil_t, const proxy<Table, Key>& right) { - return right.valid(); - } - - template<typename Table, typename Key> - inline bool operator!=(const proxy<Table, Key>& right, lua_nil_t) { - return right.valid(); - } - - namespace stack { - template <typename Table, typename Key> - struct pusher<proxy<Table, Key>> { - static int push(lua_State* L, const proxy<Table, Key>& p) { - sol::reference r = p; - return r.push(L); - } - }; - } // stack -} // sol - -// end of sol/proxy.hpp - -// beginning of sol/usertype.hpp - -// beginning of sol/usertype_metatable.hpp - -// beginning of sol/deprecate.hpp - -#ifndef SOL_DEPRECATED - #ifdef _MSC_VER - #define SOL_DEPRECATED __declspec(deprecated) - #elif __GNUC__ - #define SOL_DEPRECATED __attribute__((deprecated)) - #else - #define SOL_DEPRECATED [[deprecated]] - #endif // compilers -#endif // SOL_DEPRECATED - -namespace sol { - namespace detail { - template <typename T> - struct SOL_DEPRECATED deprecate_type { - using type = T; - }; - } // detail -} // sol - -// end of sol/deprecate.hpp - -#include <unordered_map> -#include <cstdio> - -namespace sol { - namespace usertype_detail { - struct no_comp { - template <typename A, typename B> - bool operator()(A&&, B&&) const { - return false; - } - }; - - typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); - typedef int(*member_search)(lua_State*, void*); - - struct find_call_pair { - member_search first; - member_search second; - - find_call_pair(member_search first, member_search second) : first(first), second(second) {} - }; - - inline bool is_indexer(string_detail::string_shim s) { - return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); - } - - inline bool is_indexer(meta_function mf) { - return mf == meta_function::index || mf == meta_function::new_index; - } - - inline bool is_indexer(call_construction) { - return false; - } - - inline bool is_indexer(base_classes_tag) { - return false; - } - - inline auto make_shim(string_detail::string_shim s) { - return s; - } - - inline auto make_shim(call_construction) { - return string_detail::string_shim(name_of(meta_function::call_function)); - } - - inline auto make_shim(meta_function mf) { - return string_detail::string_shim(name_of(mf)); - } - - inline auto make_shim(base_classes_tag) { - return string_detail::string_shim(detail::base_class_cast_key()); - } - - template <typename Arg> - inline std::string make_string(Arg&& arg) { - string_detail::string_shim s = make_shim(arg); - return std::string(s.c_str(), s.size()); - } - - template <typename N> - inline luaL_Reg make_reg(N&& n, lua_CFunction f) { - luaL_Reg l{ make_shim(std::forward<N>(n)).c_str(), f }; - return l; - } - - struct registrar { - virtual int push_um(lua_State* L) = 0; - virtual ~registrar() {} - }; - - template <bool is_index> - inline int indexing_fail(lua_State* L) { - auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2); - string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); - if (is_index) - return luaL_error(L, "sol: attempt to index (get) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); - else - return luaL_error(L, "sol: attempt to index (set) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); - } - - template <bool is_index, typename Base> - static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { - if (found) - return; - const char* metakey = &usertype_traits<Base>::metatable()[0]; - const char* gcmetakey = &usertype_traits<Base>::gc_table()[0]; - const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); - - luaL_getmetatable(L, metakey); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return; - } - - stack::get_field(L, basewalkkey); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 2); - return; - } - lua_CFunction basewalkfunc = stack::pop<lua_CFunction>(L); - lua_pop(L, 1); - - stack::get_field<true>(L, gcmetakey); - int value = basewalkfunc(L); - if (value > -1) { - found = true; - ret = value; - } - } - - template <bool is_index, typename... Bases> - static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { - (void)L; - (void)found; - (void)ret; - (void)accessor; - (void)detail::swallow{ 0, (walk_single_base<is_index, Bases>(L, found, ret, accessor), 0)... }; - } - - template <typename T, typename Op> - inline int operator_wrap(lua_State* L) { - auto maybel = stack::check_get<T>(L, 1); - if (maybel) { - auto mayber = stack::check_get<T>(L, 2); - if (mayber) { - auto& l = *maybel; - auto& r = *mayber; - if (std::is_same<no_comp, Op>::value) { - return stack::push(L, detail::ptr(l) == detail::ptr(r)); - } - else { - Op op; - return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); - } - } - } - return stack::push(L, false); - } - - template <typename T, typename Op, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler> - inline void make_reg_op(Regs& l, int& index, const char* name) { - l[index] = { name, &operator_wrap<T, Op> }; - ++index; - } - - template <typename T, typename Op, typename Supports, typename Regs, meta::disable<Supports> = meta::enabler> - inline void make_reg_op(Regs&, int&, const char*) { - // Do nothing if there's no support - } - - struct add_destructor_tag {}; - struct check_destructor_tag {}; - struct verified_tag {} const verified{}; - - template <typename T> - struct is_non_factory_constructor : std::false_type {}; - - template <typename... Args> - struct is_non_factory_constructor<constructors<Args...>> : std::true_type {}; - - template <typename... Args> - struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {}; - - template <> - struct is_non_factory_constructor<no_construction> : std::true_type {}; - - template <typename T> - struct is_constructor : is_non_factory_constructor<T> {}; - - template <typename... Args> - struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; - - template <typename... Args> - using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; - - template <typename T> - struct is_destructor : std::false_type {}; - - template <typename Fx> - struct is_destructor<destructor_wrapper<Fx>> : std::true_type {}; - - template <typename... Args> - using has_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>; - - } // usertype_detail - - template <typename T> - struct clean_type { - typedef std::conditional_t<std::is_array<meta::unqualified_t<T>>::value, T&, std::decay_t<T>> type; - }; - - template <typename T> - using clean_type_t = typename clean_type<T>::type; - - template <typename T, typename IndexSequence, typename... Tn> - struct usertype_metatable : usertype_detail::registrar {}; - - template <typename T, std::size_t... I, typename... Tn> - struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_detail::registrar { - typedef std::make_index_sequence<sizeof...(I) * 2> indices; - typedef std::index_sequence<I...> half_indices; - typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 3> regs_t; - typedef std::tuple<Tn...> RawTuple; - typedef std::tuple<clean_type_t<Tn> ...> Tuple; - template <std::size_t Idx> - struct check_binding : is_variable_binding<meta::unqualified_tuple_element_t<Idx, Tuple>> {}; - typedef std::unordered_map<std::string, usertype_detail::find_call_pair> mapping_t; - Tuple functions; - mapping_t mapping; - lua_CFunction indexfunc; - lua_CFunction newindexfunc; - lua_CFunction destructfunc; - lua_CFunction callconstructfunc; - lua_CFunction indexbase; - lua_CFunction newindexbase; - usertype_detail::base_walk indexbaseclasspropogation; - usertype_detail::base_walk newindexbaseclasspropogation; - void* baseclasscheck; - void* baseclasscast; - bool mustindex; - bool secondarymeta; - bool hasequals; - bool hasless; - bool haslessequals; - - template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> - inline lua_CFunction make_func() { - return std::get<Idx + 1>(functions); - } - - template <std::size_t Idx, meta::disable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> - inline lua_CFunction make_func() { - return call<Idx + 1>; - } - - static bool contains_variable() { - typedef meta::any<check_binding<(I * 2 + 1)>...> has_variables; - return has_variables::value; - } - - bool contains_index() const { - bool idx = false; - (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get<I * 2>(functions))), 0) ... }; - return idx; - } - - int finish_regs(regs_t& l, int& index) { - if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); - usertype_detail::make_reg_op<T, std::less<>, meta::supports_op_less<T>>(l, index, name); - } - if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); - usertype_detail::make_reg_op<T, std::less_equal<>, meta::supports_op_less_equal<T>>(l, index, name); - } - if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); - usertype_detail::make_reg_op<T, std::conditional_t<meta::supports_op_equal<T>::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); - } - if (destructfunc != nullptr) { - l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; - ++index; - } - return index; - } - - template <std::size_t Idx, typename F> - void make_regs(regs_t&, int&, call_construction, F&&) { - callconstructfunc = call<Idx + 1>; - secondarymeta = true; - } - - template <std::size_t, typename... Bases> - void make_regs(regs_t&, int&, base_classes_tag, bases<Bases...>) { - if (sizeof...(Bases) < 1) { - return; - } - mustindex = true; - (void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... }; - - static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); - static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); - baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check; - baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast; - indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; - newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; - } - - template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>> - void make_regs(regs_t& l, int& index, N&& n, F&&) { - if (is_variable_binding<meta::unqualified_t<F>>::value) { - return; - } - luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>()); - // Returnable scope - // That would be a neat keyword for C++ - // returnable { ... }; - if (reg.name == name_of(meta_function::equal_to)) { - hasequals = true; - } - if (reg.name == name_of(meta_function::less_than)) { - hasless = true; - } - if (reg.name == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - if (reg.name == name_of(meta_function::garbage_collect)) { - destructfunc = reg.func; - return; - } - else if (reg.name == name_of(meta_function::index)) { - indexfunc = reg.func; - mustindex = true; - return; - } - else if (reg.name == name_of(meta_function::new_index)) { - newindexfunc = reg.func; - mustindex = true; - return; - } - l[index] = reg; - ++index; - } - - template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == sizeof...(Tn)>> - usertype_metatable(Args&&... args) : functions(std::forward<Args>(args)...), - mapping(), - indexfunc(usertype_detail::indexing_fail<true>), newindexfunc(usertype_detail::indexing_fail<false>), - destructfunc(nullptr), callconstructfunc(nullptr), - indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), - indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), - baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()), - hasequals(false), hasless(false), haslessequals(false) { - std::initializer_list<typename mapping_t::value_type> ilist{ { - std::pair<std::string, usertype_detail::find_call_pair>( - usertype_detail::make_string(std::get<I * 2>(functions)), - usertype_detail::find_call_pair(&usertype_metatable::real_find_call<I * 2, I * 2 + 1, false>, - &usertype_metatable::real_find_call<I * 2, I * 2 + 1, true>) - ) - }... }; - mapping.insert(ilist); - } - - template <std::size_t I0, std::size_t I1, bool is_index> - static int real_find_call(lua_State* L, void* um) { - auto& f = *static_cast<usertype_metatable*>(um); - if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) { - return real_call_with<I1, is_index, true>(L, f); - } - return stack::push(L, c_closure(call<I1, is_index>, stack::push(L, light<usertype_metatable>(f)))); - } - - template <bool is_index, bool toplevel = false> - static int core_indexing_call(lua_State* L) { - usertype_metatable& f = toplevel ? stack::get<light<usertype_metatable>>(L, upvalue_index(1)) : stack::pop<light<usertype_metatable>>(L); - static const int keyidx = -2 + static_cast<int>(is_index); - if (toplevel && stack::get<type>(L, keyidx) != type::string) { - return is_index ? f.indexfunc(L) : f.newindexfunc(L); - } - std::string name = stack::get<std::string>(L, keyidx); - auto memberit = f.mapping.find(name); - if (memberit != f.mapping.cend()) { - auto& member = is_index ? memberit->second.second : memberit->second.first; - return (member)(L, static_cast<void*>(&f)); - } - string_detail::string_shim accessor = name; - int ret = 0; - bool found = false; - // Otherwise, we need to do propagating calls through the bases - if (is_index) - f.indexbaseclasspropogation(L, found, ret, accessor); - else - f.newindexbaseclasspropogation(L, found, ret, accessor); - if (found) { - return ret; - } - return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; - } - - static int real_index_call(lua_State* L) { - return core_indexing_call<true, true>(L); - } - - static int real_new_index_call(lua_State* L) { - return core_indexing_call<false, true>(L); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int real_call(lua_State* L) { - usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(1)); - return real_call_with<Idx, is_index, is_variable>(L, f); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int real_call_with(lua_State* L, usertype_metatable& um) { - typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K; - typedef meta::unqualified_tuple_element_t<Idx, Tuple> F; - static const int boost = - !usertype_detail::is_non_factory_constructor<F>::value - && std::is_same<K, call_construction>::value ? - 1 : 0; - auto& f = std::get<Idx>(um.functions); - return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call<Idx, is_index, is_variable>)>(L); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int call_with(lua_State* L) { - return detail::static_trampoline<(&real_call_with<Idx, is_index, is_variable>)>(L); - } - - static int index_call(lua_State* L) { - return detail::static_trampoline<(&real_index_call)>(L); - } - - static int new_index_call(lua_State* L) { - return detail::static_trampoline<(&real_new_index_call)>(L); - } - - virtual int push_um(lua_State* L) override { - return stack::push(L, std::move(*this)); - } - - ~usertype_metatable() override { - - } - }; - - namespace stack { - - template <typename T, std::size_t... I, typename... Args> - struct pusher<usertype_metatable<T, std::index_sequence<I...>, Args...>> { - typedef usertype_metatable<T, std::index_sequence<I...>, Args...> umt_t; - typedef typename umt_t::regs_t regs_t; - - static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { - // ensure some sort of uniqueness - static int uniqueness = 0; - std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); - // std::to_string doesn't exist in android still, with NDK, so this bullshit - // is necessary - // thanks, Android :v - int appended = snprintf(nullptr, 0, "%d", uniqueness); - std::size_t insertionpoint = uniquegcmetakey.length() - 1; - uniquegcmetakey.append(appended, '\0'); - char* uniquetarget = &uniquegcmetakey[insertionpoint]; - snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); - ++uniqueness; - - const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; - // Make sure userdata's memory is properly in lua first, - // otherwise all the light userdata we make later will become invalid - stack::push<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx)); - // Create the top level thing that will act as our deleter later on - stack_reference umt(L, -1); - stack::set_field<true>(L, gcmetakey, umt); - umt.pop(); - - stack::get_field<true>(L, gcmetakey); - return stack::pop<light<umt_t>>(L); - } - - static int push(lua_State* L, umt_t&& umx) { - - umt_t& um = make_cleanup(L, std::move(umx)); - regs_t value_table{ {} }; - int lastreg = 0; - (void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... }; - um.finish_regs(value_table, lastreg); - value_table[lastreg] = { nullptr, nullptr }; - regs_t ref_table = value_table; - regs_t unique_table = value_table; - bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; - if (hasdestructor) { - ref_table[lastreg - 1] = { nullptr, nullptr }; - unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> }; - } - - // Now use um - const bool& mustindex = um.mustindex; - for (std::size_t i = 0; i < 3; ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - luaL_Reg* metaregs = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - metaregs = ref_table.data(); - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - metaregs = unique_table.data(); - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - metaregs = value_table.data(); - break; - } - luaL_newmetatable(L, metakey); - stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, metaregs, 1); - - if (um.baseclasscheck != nullptr) { - stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); - } - if (um.baseclasscast != nullptr) { - stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); - } - - stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um)), t.stack_index()); - stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um)), t.stack_index()); - - if (mustindex) { - // Basic index pushing: specialize - // index and newindex to give variables and stuff - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), t.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), t.stack_index()); - } - else { - // If there's only functions, we can use the fast index version - stack::set_field(L, meta_function::index, t, t.stack_index()); - } - // metatable on the metatable - // for call constructor purposes and such - lua_createtable(L, 0, 3); - stack_reference metabehind(L, -1); - if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - // We want to just leave the table - // in the registry only, otherwise we return it - t.pop(); - } - - // Now for the shim-table that actually gets assigned to the name - luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); - stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, value_table.data(), 1); - { - lua_createtable(L, 0, 3); - stack_reference metabehind(L, -1); - if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - } - - return 1; - } - }; - - } // stack - -} // sol - -// end of sol/usertype_metatable.hpp - -// beginning of sol/simple_usertype_metatable.hpp - -namespace sol { - - namespace usertype_detail { - const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001); - - struct variable_wrapper { - virtual int index(lua_State* L) = 0; - virtual int new_index(lua_State* L) = 0; - virtual ~variable_wrapper() {}; - }; - - template <typename T, typename F> - struct callable_binding : variable_wrapper { - F fx; - - template <typename Arg> - callable_binding(Arg&& arg) : fx(std::forward<Arg>(arg)) {} - - virtual int index(lua_State* L) override { - return call_detail::call_wrapped<T, true, true>(L, fx); - } - - virtual int new_index(lua_State* L) override { - return call_detail::call_wrapped<T, false, true>(L, fx); - } - }; - - typedef std::unordered_map<std::string, std::unique_ptr<variable_wrapper>> variable_map; - typedef std::unordered_map<std::string, object> function_map; - - struct simple_map { - const char* metakey; - variable_map variables; - function_map functions; - base_walk indexbaseclasspropogation; - base_walk newindexbaseclasspropogation; - - simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} - }; - - template <typename T> - inline int simple_metatable_newindex(lua_State* L) { - int isnum = 0; - lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum); - if (isnum != 0 && magic == toplevel_magic) { - for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - break; - } - luaL_getmetatable(L, metakey); - int tableindex = lua_gettop(L); - if (type_of(L, tableindex) == type::lua_nil) { - continue; - } - stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex); - } - lua_settop(L, 0); - return 0; - } - lua_pop(L, 1); - return indexing_fail<false>(L); - } - - template <bool is_index, bool toplevel = false> - inline int simple_core_indexing_call(lua_State* L) { - simple_map& sm = toplevel ? stack::get<user<simple_map>>(L, upvalue_index(1)) : stack::pop<user<simple_map>>(L); - variable_map& variables = sm.variables; - function_map& functions = sm.functions; - static const int keyidx = -2 + static_cast<int>(is_index); - if (toplevel) { - if (stack::get<type>(L, keyidx) != type::string) { - lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3)); - return indexingfunc(L); - } - } - string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, keyidx); - std::string accessorkey = accessor.c_str(); - auto vit = variables.find(accessorkey); - if (vit != variables.cend()) { - auto& varwrap = *(vit->second); - if (is_index) { - return varwrap.index(L); - } - return varwrap.new_index(L); - } - auto fit = functions.find(accessorkey); - if (fit != functions.cend()) { - auto& func = (fit->second); - return stack::push(L, func); - } - // Check table storage first for a method that works - luaL_getmetatable(L, sm.metakey); - if (type_of(L, -1) != type::lua_nil) { - stack::get_field<false, true>(L, accessor.c_str(), lua_gettop(L)); - if (type_of(L, -1) != type::lua_nil) { - // Woo, we found it? - lua_remove(L, -2); - return 1; - } - lua_pop(L, 1); - } - lua_pop(L, 1); - - int ret = 0; - bool found = false; - // Otherwise, we need to do propagating calls through the bases - if (is_index) { - sm.indexbaseclasspropogation(L, found, ret, accessor); - } - else { - sm.newindexbaseclasspropogation(L, found, ret, accessor); - } - if (found) { - return ret; - } - if (toplevel) { - lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3)); - return indexingfunc(L); - } - return -1; - } - - inline int simple_real_index_call(lua_State* L) { - return simple_core_indexing_call<true, true>(L); - } - - inline int simple_real_new_index_call(lua_State* L) { - return simple_core_indexing_call<false, true>(L); - } - - inline int simple_index_call(lua_State* L) { - return detail::static_trampoline<(&simple_real_index_call)>(L); - } - - inline int simple_new_index_call(lua_State* L) { - return detail::static_trampoline<(&simple_real_new_index_call)>(L); - } - } - - struct simple_tag {} const simple{}; - - template <typename T> - struct simple_usertype_metatable : usertype_detail::registrar { - public: - usertype_detail::function_map registrations; - usertype_detail::variable_map varmap; - object callconstructfunc; - lua_CFunction indexfunc; - lua_CFunction newindexfunc; - lua_CFunction indexbase; - lua_CFunction newindexbase; - usertype_detail::base_walk indexbaseclasspropogation; - usertype_detail::base_walk newindexbaseclasspropogation; - void* baseclasscheck; - void* baseclasscast; - bool mustindex; - bool secondarymeta; - - template <typename N> - void insert(N&& n, object&& o) { - std::string key = usertype_detail::make_string(std::forward<N>(n)); - auto hint = registrations.find(key); - if (hint == registrations.cend()) { - registrations.emplace_hint(hint, std::move(key), std::move(o)); - return; - } - hint->second = std::move(o); - } - - template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> - void add_function(lua_State* L, N&& n, F&& f) { - insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f)))); - } - - template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> - void add_function(lua_State* L, N&& n, F&& f) { - object o = make_object(L, std::forward<F>(f)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> - void add(lua_State* L, N&& n, F&& f) { - add_function(L, std::forward<N>(n), std::forward<F>(f)); - } - - template <typename N, typename F, meta::enable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> - void add(lua_State*, N&& n, F&& f) { - mustindex = true; - secondarymeta = true; - std::string key = usertype_detail::make_string(std::forward<N>(n)); - auto o = std::make_unique<usertype_detail::callable_binding<T, std::decay_t<F>>>(std::forward<F>(f)); - auto hint = varmap.find(key); - if (hint == varmap.cend()) { - varmap.emplace_hint(hint, std::move(key), std::move(o)); - return; - } - hint->second = std::move(o); - } - - template <typename N, typename... Fxs> - void add(lua_State* L, N&& n, constructor_wrapper<Fxs...> c) { - object o(L, in_place<detail::tagged<T, constructor_wrapper<Fxs...>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N, typename... Lists> - void add(lua_State* L, N&& n, constructor_list<Lists...> c) { - object o(L, in_place<detail::tagged<T, constructor_list<Lists...>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N> - void add(lua_State* L, N&& n, destructor_wrapper<void> c) { - object o(L, in_place<detail::tagged<T, destructor_wrapper<void>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N, typename Fx> - void add(lua_State* L, N&& n, destructor_wrapper<Fx> c) { - object o(L, in_place<detail::tagged<T, destructor_wrapper<Fx>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename... Bases> - void add(lua_State*, base_classes_tag, bases<Bases...>) { - static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report."); - if (sizeof...(Bases) < 1) { - return; - } - mustindex = true; - (void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... }; - - static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); - static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); - baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check; - baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast; - indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; - newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; - } - - private: - template<std::size_t... I, typename Tuple> - simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args) - : callconstructfunc(lua_nil), - indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>), - indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>), - indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>), - baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(false), secondarymeta(false) { - (void)detail::swallow{ 0, - (add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)... - }; - } - - template<typename... Args> - simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {} - - template<typename... Args> - simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) {} - - template<typename... Args> - simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward<Args>(args)...) {} - - public: - simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>>, decltype(default_constructor), usertype_detail::check_destructor_tag>()) {} - - template<typename Arg, typename... Args, meta::disable_any< - meta::any_same<meta::unqualified_t<Arg>, - usertype_detail::verified_tag, - usertype_detail::add_destructor_tag, - usertype_detail::check_destructor_tag - >, - meta::is_specialization_of<constructors, meta::unqualified_t<Arg>>, - meta::is_specialization_of<constructor_wrapper, meta::unqualified_t<Arg>> - > = meta::enabler> - simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward<Arg>(arg), std::forward<Args>(args)...) {} - - template<typename... Args, typename... CArgs> - simple_usertype_metatable(lua_State* L, constructors<CArgs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - template<typename... Args, typename... Fxs> - simple_usertype_metatable(lua_State* L, constructor_wrapper<Fxs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - virtual int push_um(lua_State* L) override { - return stack::push(L, std::move(*this)); - } - }; - - namespace stack { - template <typename T> - struct pusher<simple_usertype_metatable<T>> { - typedef simple_usertype_metatable<T> umt_t; - - static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { - static int uniqueness = 0; - std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); - // std::to_string doesn't exist in android still, with NDK, so this bullshit - // is necessary - // thanks, Android :v - int appended = snprintf(nullptr, 0, "%d", uniqueness); - std::size_t insertionpoint = uniquegcmetakey.length() - 1; - uniquegcmetakey.append(appended, '\0'); - char* uniquetarget = &uniquegcmetakey[insertionpoint]; - snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); - ++uniqueness; - - const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; - stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0], - umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, - std::move(umx.varmap), std::move(umx.registrations) - ); - stack_reference stackvarmap(L, -1); - stack::set_field<true>(L, gcmetakey, stackvarmap); - stackvarmap.pop(); - - stack::get_field<true>(L, gcmetakey); - usertype_detail::simple_map& varmap = stack::pop<light<usertype_detail::simple_map>>(L); - return varmap; - } - - static int push(lua_State* L, umt_t&& umx) { - auto& varmap = make_cleanup(L, umx); - bool hasequals = false; - bool hasless = false; - bool haslessequals = false; - auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { - if (first == name_of(meta_function::equal_to)) { - hasequals = true; - } - else if (first == name_of(meta_function::less_than)) { - hasless = true; - } - else if (first == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - else if (first == name_of(meta_function::index)) { - umx.indexfunc = second.template as<lua_CFunction>(); - } - else if (first == name_of(meta_function::new_index)) { - umx.newindexfunc = second.template as<lua_CFunction>(); - } - switch (i) { - case 0: - if (first == name_of(meta_function::garbage_collect)) { - return; - } - break; - case 1: - if (first == name_of(meta_function::garbage_collect)) { - stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index()); - return; - } - break; - case 2: - default: - break; - } - stack::set_field(L, first, second, t.stack_index()); - }; - for (std::size_t i = 0; i < 3; ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - break; - } - luaL_newmetatable(L, metakey); - stack_reference t(L, -1); - for (auto& kvp : varmap.functions) { - auto& first = std::get<0>(kvp); - auto& second = std::get<1>(kvp); - register_kvp(i, t, first, second); - } - luaL_Reg opregs[4]{}; - int opregsindex = 0; - if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); - usertype_detail::make_reg_op<T, std::less<>, meta::supports_op_less<T>>(opregs, opregsindex, name); - } - if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); - usertype_detail::make_reg_op<T, std::less_equal<>, meta::supports_op_less_equal<T>>(opregs, opregsindex, name); - } - if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); - usertype_detail::make_reg_op<T, std::conditional_t<meta::supports_op_equal<T>::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); - } - t.push(); - luaL_setfuncs(L, opregs, 0); - t.pop(); - - if (umx.baseclasscheck != nullptr) { - stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); - } - if (umx.baseclasscast != nullptr) { - stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); - } - - // Base class propagation features - stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); - stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); - - if (umx.mustindex) { - // use indexing function - stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), t.stack_index()); - stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), t.stack_index()); - } - else { - // Metatable indexes itself - stack::set_field(L, meta_function::index, t, t.stack_index()); - } - // metatable on the metatable - // for call constructor purposes and such - lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid())); - stack_reference metabehind(L, -1); - if (umx.callconstructfunc.valid()) { - stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); - } - if (umx.secondarymeta) { - stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - - t.pop(); - } - - // Now for the shim-table that actually gets pushed - luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); - stack_reference t(L, -1); - for (auto& kvp : varmap.functions) { - auto& first = std::get<0>(kvp); - auto& second = std::get<1>(kvp); - register_kvp(2, t, first, second); - } - { - lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid())); - stack_reference metabehind(L, -1); - if (umx.callconstructfunc.valid()) { - stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); - } - // use indexing function - stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex<T>, - usertype_detail::toplevel_magic - ), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, - make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex<T>, - usertype_detail::toplevel_magic - ), metabehind.stack_index()); - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - } - - // Don't pop the table when we're done; - // return it - return 1; - } - }; - } // stack -} // sol - -// end of sol/simple_usertype_metatable.hpp - -// beginning of sol/container_usertype_metatable.hpp - -namespace sol { - - namespace detail { - - template <typename T> - struct has_find { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(&C::find)); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - struct has_push_back { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(std::declval<C>().push_back(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - struct has_clear { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(&C::clear)); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - struct has_insert { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - T& get_first(const T& t) { - return std::forward<T>(t); - } - - template <typename A, typename B> - decltype(auto) get_first(const std::pair<A, B>& t) { - return t.first; - } - - template <typename C, typename I, meta::enable<has_find<meta::unqualified_t<C>>> = meta::enabler> - auto find(C& c, I&& i) { - return c.find(std::forward<I>(i)); - } - - template <typename C, typename I, meta::disable<has_find<meta::unqualified_t<C>>> = meta::enabler> - auto find(C& c, I&& i) { - using std::begin; - using std::end; - return std::find_if(begin(c), end(c), [&i](auto&& x) { - return i == get_first(x); - }); - } - - } - - template <typename Raw, typename C = void> - struct container_usertype_metatable { - typedef meta::has_key_value_pair<meta::unqualified_t<Raw>> is_associative; - typedef meta::unqualified_t<Raw> T; - typedef typename T::iterator I; - typedef std::conditional_t<is_associative::value, typename T::value_type, std::pair<std::size_t, typename T::value_type>> KV; - typedef typename KV::first_type K; - typedef typename KV::second_type V; - typedef std::remove_reference_t<decltype(*std::declval<I&>())> IR; - - struct iter { - T& source; - I it; - - iter(T& source, I it) : source(source), it(std::move(it)) {} - }; - - static auto& get_src(lua_State* L) { -#ifdef SOL_SAFE_USERTYPE - auto p = stack::check_get<T*>(L, 1); - if (!p || p.value() == nullptr) { - luaL_error(L, "sol: 'self' argument is not the proper type (pass 'self' as first argument with ':' or call on proper type)"); - } - return *p.value(); -#else - return stack::get<T>(L, 1); -#endif - } - - static int real_index_call_associative(std::true_type, lua_State* L) { - auto k = stack::check_get<K>(L, 2); - if (k) { - auto& src = get_src(L); - using std::end; - auto it = detail::find(src, *k); - if (it != end(src)) { - auto& v = *it; - return stack::push_reference(L, v.second); - } - } - else { - auto maybename = stack::check_get<string_detail::string_shim>(L, 2); - if (maybename) { - auto& name = *maybename; - if (name == "add") { - return stack::push(L, &add_call); - } - else if (name == "insert") { - return stack::push(L, &insert_call); - } - else if (name == "clear") { - return stack::push(L, &clear_call); - } - } - } - return stack::push(L, lua_nil); - } - - static int real_index_call_associative(std::false_type, lua_State* L) { - auto& src = get_src(L); - auto maybek = stack::check_get<K>(L, 2); - if (maybek) { - using std::begin; - auto it = begin(src); - K k = *maybek; -#ifdef SOL_SAFE_USERTYPE - if (k > src.size() || k < 1) { - return stack::push(L, lua_nil); - } -#else -#endif // Safety - --k; - std::advance(it, k); - return stack::push_reference(L, *it); - } - else { - auto maybename = stack::check_get<string_detail::string_shim>(L, 2); - if (maybename) { - auto& name = *maybename; - if (name == "add") { - return stack::push(L, &add_call); - } - else if (name == "insert") { - return stack::push(L, &insert_call); - } - else if (name == "clear") { - return stack::push(L, &clear_call); - } - } - } - - return stack::push(L, lua_nil); - } - - static int real_index_call(lua_State* L) { - return real_index_call_associative(is_associative(), L); - } - - static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) { - return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); - } - - static int real_new_index_call_const(std::false_type, std::true_type, lua_State* L) { - return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); - } - - static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { - auto& src = get_src(L); - auto k = stack::check_get<K>(L, 2); - if (k) { - using std::end; - auto it = detail::find(src, *k); - if (it != end(src)) { - auto& v = *it; - v.second = stack::get<V>(L, 3); - } - else { - src.insert(it, { std::move(*k), stack::get<V>(L, 3) }); - } - } - return 0; - } - - static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) { - auto& src = get_src(L); -#ifdef SOL_SAFE_USERTYPE - auto maybek = stack::check_get<K>(L, 2); - if (!maybek) { - return stack::push(L, lua_nil); - } - K k = *maybek; -#else - K k = stack::get<K>(L, 2); -#endif - using std::begin; - auto it = begin(src); - if (k == src.size()) { - real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src, 1); - return 0; - } - --k; - std::advance(it, k); - *it = stack::get<V>(L, 3); - return 0; - } - - static int real_new_index_call(lua_State* L) { - return real_new_index_call_const(meta::neg<meta::any<std::is_const<V>, std::is_const<IR>>>(), is_associative(), L); - } - - static int real_pairs_next_call_assoc(std::true_type, lua_State* L) { - using std::end; - iter& i = stack::get<user<iter>>(L, 1); - auto& source = i.source; - auto& it = i.it; - if (it == end(source)) { - return 0; - } - int p = stack::multi_push_reference(L, it->first, it->second); - std::advance(it, 1); - return p; - } - - static int real_pairs_call_assoc(std::true_type, lua_State* L) { - auto& src = get_src(L); - using std::begin; - stack::push(L, pairs_next_call); - stack::push<user<iter>>(L, src, begin(src)); - stack::push(L, 1); - return 3; - } - - static int real_pairs_next_call_assoc(std::false_type, lua_State* L) { - using std::end; - iter& i = stack::get<user<iter>>(L, 1); - auto& source = i.source; - auto& it = i.it; - K k = stack::get<K>(L, 2); - if (it == end(source)) { - return 0; - } - int p = stack::multi_push_reference(L, k + 1, *it); - std::advance(it, 1); - return p; - } - - static int real_pairs_call_assoc(std::false_type, lua_State* L) { - auto& src = get_src(L); - using std::begin; - stack::push(L, pairs_next_call); - stack::push<user<iter>>(L, src, begin(src)); - stack::push(L, 0); - return 3; - } - - static int real_pairs_next_call(lua_State* L) { - return real_pairs_next_call_assoc(is_associative(), L); - } - - static int real_pairs_call(lua_State* L) { - return real_pairs_call_assoc(is_associative(), L); - } - - static int real_length_call(lua_State*L) { - auto& src = get_src(L); - return stack::push(L, src.size()); - } - - static int real_add_call_insert(std::true_type, lua_State*L, T& src, int boost = 0) { - using std::end; - src.insert(end(src), stack::get<V>(L, 2 + boost)); - return 0; - } - - static int real_add_call_insert(std::false_type, lua_State*L, T&, int = 0) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call insert on type %s", s.c_str()); - } - - static int real_add_call_push(std::true_type, lua_State*L, T& src, int boost = 0) { - src.push_back(stack::get<V>(L, 2 + boost)); - return 0; - } - - static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) { - return real_add_call_insert(std::integral_constant<bool, detail::has_insert<T>::value>(), L, src, boost); - } - - static int real_add_call_associative(std::true_type, lua_State* L) { - return real_insert_call(L); - } - - static int real_add_call_associative(std::false_type, lua_State* L) { - auto& src = get_src(L); - return real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src); - } - - static int real_add_call_capable(std::true_type, lua_State* L) { - return real_add_call_associative(is_associative(), L); - } - - static int real_add_call_capable(std::false_type, lua_State* L) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call add on type %s", s.c_str()); - } - - static int real_add_call(lua_State* L) { - return real_add_call_capable(std::integral_constant<bool, detail::has_push_back<T>::value || detail::has_insert<T>::value>(), L); - } - - static int real_insert_call_capable(std::false_type, std::false_type, lua_State*L) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call insert on type %s", s.c_str()); - } - - static int real_insert_call_capable(std::false_type, std::true_type, lua_State*L) { - return real_insert_call_capable(std::false_type(), std::false_type(), L); - } - - static int real_insert_call_capable(std::true_type, std::false_type, lua_State* L) { - using std::begin; - auto& src = get_src(L); - src.insert(std::next(begin(src), stack::get<K>(L, 2)), stack::get<V>(L, 3)); - return 0; - } - - static int real_insert_call_capable(std::true_type, std::true_type, lua_State* L) { - return real_new_index_call(L); - } - - static int real_insert_call(lua_State*L) { - return real_insert_call_capable(std::integral_constant<bool, detail::has_insert<T>::value>(), is_associative(), L); - } - - static int real_clear_call_capable(std::false_type, lua_State* L) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call clear on type %s", s.c_str()); - } - - static int real_clear_call_capable(std::true_type, lua_State* L) { - auto& src = get_src(L); - src.clear(); - return 0; - } - - static int real_clear_call(lua_State*L) { - return real_clear_call_capable(std::integral_constant<bool, detail::has_clear<T>::value>(), L); - } - - static int add_call(lua_State*L) { - return detail::static_trampoline<(&real_add_call)>(L); - } - - static int insert_call(lua_State*L) { - return detail::static_trampoline<(&real_insert_call)>(L); - } - - static int clear_call(lua_State*L) { - return detail::static_trampoline<(&real_clear_call)>(L); - } - - static int length_call(lua_State*L) { - return detail::static_trampoline<(&real_length_call)>(L); - } - - static int pairs_next_call(lua_State*L) { - return detail::static_trampoline<(&real_pairs_next_call)>(L); - } - - static int pairs_call(lua_State*L) { - return detail::static_trampoline<(&real_pairs_call)>(L); - } - - static int index_call(lua_State*L) { - return detail::static_trampoline<(&real_index_call)>(L); - } - - static int new_index_call(lua_State*L) { - return detail::static_trampoline<(&real_new_index_call)>(L); - } - }; - - namespace stack { - namespace stack_detail { - template <typename T> - inline auto container_metatable() { - typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt; - std::array<luaL_Reg, 10> reg = { { - { "__index", &meta_cumt::index_call }, - { "__newindex", &meta_cumt::new_index_call }, - { "__pairs", &meta_cumt::pairs_call }, - { "__ipairs", &meta_cumt::pairs_call }, - { "__len", &meta_cumt::length_call }, - { "clear", &meta_cumt::clear_call }, - { "insert", &meta_cumt::insert_call }, - { "add", &meta_cumt::add_call }, - std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy<T> }, - { nullptr, nullptr } - } }; - return reg; - } - - template <typename T> - inline auto container_metatable_behind() { - typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt; - std::array<luaL_Reg, 3> reg = { { - { "__index", &meta_cumt::index_call }, - { "__newindex", &meta_cumt::new_index_call }, - { nullptr, nullptr } - } }; - return reg; - } - - template <typename T> - struct metatable_setup { - lua_State* L; - - metatable_setup(lua_State* L) : L(L) {} - - void operator()() { - static const auto reg = container_metatable<T>(); - static const auto containerreg = container_metatable_behind<T>(); - static const char* metakey = &usertype_traits<T>::metatable()[0]; - - if (luaL_newmetatable(L, metakey) == 1) { - stack_reference metatable(L, -1); - luaL_setfuncs(L, reg.data(), 0); - - lua_createtable(L, 0, static_cast<int>(containerreg.size())); - stack_reference metabehind(L, -1); - luaL_setfuncs(L, containerreg.data(), 0); - - stack::set_field(L, metatable_key, metabehind, metatable.stack_index()); - metabehind.pop(); - } - lua_setmetatable(L, -2); - } - }; - } - - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - static int push(lua_State* L, const T& cont) { - stack_detail::metatable_setup<T> fx(L); - return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, cont); - } - - static int push(lua_State* L, T&& cont) { - stack_detail::metatable_setup<T> fx(L); - return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::move(cont)); - } - }; - - template<typename T> - struct pusher<T*, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - static int push(lua_State* L, T* cont) { - stack_detail::metatable_setup<meta::unqualified_t<std::remove_pointer_t<T>>*> fx(L); - return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont); - } - }; - } // stack - -} // sol - -// end of sol/container_usertype_metatable.hpp - -namespace sol { - - template<typename T> - class usertype { - private: - std::unique_ptr<usertype_detail::registrar, detail::deleter> metatableregister; - - template<typename... Args> - usertype(usertype_detail::verified_tag, Args&&... args) : metatableregister(detail::make_unique_deleter<usertype_metatable<T, std::make_index_sequence<sizeof...(Args) / 2>, Args...>, detail::deleter>(std::forward<Args>(args)...)) {} - - template<typename... Args> - usertype(usertype_detail::add_destructor_tag, Args&&... args) : usertype(usertype_detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) {} - - template<typename... Args> - usertype(usertype_detail::check_destructor_tag, Args&&... args) : usertype(meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward<Args>(args)...) {} - - public: - - template<typename... Args> - usertype(Args&&... args) : usertype(meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward<Args>(args)...) {} - - template<typename... Args, typename... CArgs> - usertype(constructors<CArgs...> constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - template<typename... Args, typename... Fxs> - usertype(constructor_wrapper<Fxs...> constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - template<typename... Args> - usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter<simple_usertype_metatable<T>, detail::deleter>(L, std::forward<Args>(args)...)) {} - - usertype_detail::registrar* registrar_data() { - return metatableregister.get(); - } - - int push(lua_State* L) { - return metatableregister->push_um(L); - } - }; - - template<typename T> - class simple_usertype : public usertype<T> { - private: - typedef usertype<T> base_t; - lua_State* state; - - public: - template<typename... Args> - simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward<Args>(args)...), state(L) {} - - template <typename N, typename F> - void set(N&& n, F&& f) { - auto meta = static_cast<simple_usertype_metatable<T>*>(base_t::registrar_data()); - meta->add(state, n, f); - } - }; - - namespace stack { - template<typename T> - struct pusher<usertype<T>> { - static int push(lua_State* L, usertype<T>& user) { - return user.push(L); - } - }; - } // stack -} // sol - -// end of sol/usertype.hpp - -// beginning of sol/table_iterator.hpp - -namespace sol { - - template <typename reference_type> - class basic_table_iterator : public std::iterator<std::input_iterator_tag, std::pair<object, object>> { - private: - typedef std::iterator<std::input_iterator_tag, std::pair<object, object>> base_t; - public: - typedef object key_type; - typedef object mapped_type; - typedef base_t::value_type value_type; - typedef base_t::iterator_category iterator_category; - typedef base_t::difference_type difference_type; - typedef base_t::pointer pointer; - typedef base_t::reference reference; - typedef const value_type& const_reference; - - private: - std::pair<object, object> kvp; - reference_type ref; - int tableidx = 0; - int keyidx = 0; - std::ptrdiff_t idx = 0; - - public: - - basic_table_iterator() : keyidx(-1), idx(-1) { - - } - - basic_table_iterator(reference_type x) : ref(std::move(x)) { - ref.push(); - tableidx = lua_gettop(ref.lua_state()); - stack::push(ref.lua_state(), lua_nil); - this->operator++(); - if (idx == -1) { - return; - } - --idx; - } - - basic_table_iterator& operator++() { - if (idx == -1) - return *this; - - if (lua_next(ref.lua_state(), tableidx) == 0) { - idx = -1; - keyidx = -1; - return *this; - } - ++idx; - kvp.first = object(ref.lua_state(), -2); - kvp.second = object(ref.lua_state(), -1); - lua_pop(ref.lua_state(), 1); - // leave key on the stack - keyidx = lua_gettop(ref.lua_state()); - return *this; - } - - basic_table_iterator operator++(int) { - auto saved = *this; - this->operator++(); - return saved; - } - - reference operator*() { - return kvp; - } - - const_reference operator*() const { - return kvp; - } - - bool operator== (const basic_table_iterator& right) const { - return idx == right.idx; - } - - bool operator!= (const basic_table_iterator& right) const { - return idx != right.idx; - } - - ~basic_table_iterator() { - if (keyidx != -1) { - stack::remove(ref.lua_state(), keyidx, 1); - } - if (ref.valid()) { - stack::remove(ref.lua_state(), tableidx, 1); - } - } - }; - -} // sol - -// end of sol/table_iterator.hpp - -namespace sol { - namespace detail { - template <std::size_t n> - struct clean { lua_State* L; clean(lua_State* luastate) : L(luastate) {} ~clean() { lua_pop(L, static_cast<int>(n)); } }; - struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* luastate, int& n) : L(luastate), n(n) {} ~ref_clean() { lua_pop(L, static_cast<int>(n)); } }; - inline int fail_on_newindex(lua_State* L) { - return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); - } - } - - template <bool top_level, typename base_t> - class basic_table_core : public base_t { - friend class state; - friend class state_view; - - template <typename... Args> - using is_global = meta::all<meta::boolean<top_level>, meta::is_c_str<Args>...>; - - template<typename Fx> - void for_each(std::true_type, Fx&& fx) const { - auto pp = stack::push_pop(*this); - stack::push(base_t::lua_state(), lua_nil); - while (lua_next(base_t::lua_state(), -2)) { - sol::object key(base_t::lua_state(), -2); - sol::object value(base_t::lua_state(), -1); - std::pair<sol::object&, sol::object&> keyvalue(key, value); - auto pn = stack::pop_n(base_t::lua_state(), 1); - fx(keyvalue); - } - } - - template<typename Fx> - void for_each(std::false_type, Fx&& fx) const { - auto pp = stack::push_pop(*this); - stack::push(base_t::lua_state(), lua_nil); - while (lua_next(base_t::lua_state(), -2)) { - sol::object key(base_t::lua_state(), -2); - sol::object value(base_t::lua_state(), -1); - auto pn = stack::pop_n(base_t::lua_state(), 1); - fx(key, value); - } - } - - template<typename Ret0, typename Ret1, typename... Ret, std::size_t... I, typename Keys> - auto tuple_get(types<Ret0, Ret1, Ret...>, std::index_sequence<0, 1, I...>, Keys&& keys) const - -> decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) { - typedef decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) Tup; - return Tup( - traverse_get_optional<top_level, Ret0>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret0>>(), detail::forward_get<0>(keys)), - traverse_get_optional<top_level, Ret1>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret1>>(), detail::forward_get<1>(keys)), - traverse_get_optional<top_level, Ret>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret>>(), detail::forward_get<I>(keys))... - ); - } - - template<typename Ret, std::size_t I, typename Keys> - decltype(auto) tuple_get(types<Ret>, std::index_sequence<I>, Keys&& keys) const { - return traverse_get_optional<top_level, Ret>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret>>(), detail::forward_get<I>(keys)); - } - - template<typename Pairs, std::size_t... I> - void tuple_set(std::index_sequence<I...>, Pairs&& pairs) { - auto pp = stack::push_pop<top_level && (is_global<decltype(detail::forward_get<I * 2>(pairs))...>::value)>(*this); - void(detail::swallow{ (stack::set_field<top_level>(base_t::lua_state(), - detail::forward_get<I * 2>(pairs), - detail::forward_get<I * 2 + 1>(pairs), - lua_gettop(base_t::lua_state()) - ), 0)... }); - } - - template <bool global, typename T, typename Key> - decltype(auto) traverse_get_deep(Key&& key) const { - stack::get_field<global>(base_t::lua_state(), std::forward<Key>(key)); - return stack::get<T>(base_t::lua_state()); - } - - template <bool global, typename T, typename Key, typename... Keys> - decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { - stack::get_field<global>(base_t::lua_state(), std::forward<Key>(key)); - return traverse_get_deep<false, T>(std::forward<Keys>(keys)...); - } - - template <bool global, typename T, std::size_t I, typename Key> - decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { - typedef decltype(stack::get<T>(base_t::lua_state())) R; - auto p = stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), lua_gettop(base_t::lua_state())); - popcount += p.levels; - if (!p.success) - return R(nullopt); - return stack::get<T>(base_t::lua_state()); - } - - template <bool global, typename T, std::size_t I, typename Key, typename... Keys> - decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { - auto p = I > 0 ? stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), -1) : stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), lua_gettop(base_t::lua_state())); - popcount += p.levels; - if (!p.success) - return T(nullopt); - return traverse_get_deep_optional<false, T, I + 1>(popcount, std::forward<Keys>(keys)...); - } - - template <bool global, typename T, typename... Keys> - decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { - detail::clean<sizeof...(Keys)> c(base_t::lua_state()); - return traverse_get_deep<top_level, T>(std::forward<Keys>(keys)...); - } - - template <bool global, typename T, typename... Keys> - decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { - int popcount = 0; - detail::ref_clean c(base_t::lua_state(), popcount); - return traverse_get_deep_optional<top_level, T, 0>(popcount, std::forward<Keys>(keys)...); - } - - template <bool global, typename Key, typename Value> - void traverse_set_deep(Key&& key, Value&& value) const { - stack::set_field<global>(base_t::lua_state(), std::forward<Key>(key), std::forward<Value>(value)); - } - - template <bool global, typename Key, typename... Keys> - void traverse_set_deep(Key&& key, Keys&&... keys) const { - stack::get_field<global>(base_t::lua_state(), std::forward<Key>(key)); - traverse_set_deep<false>(std::forward<Keys>(keys)...); - } - - basic_table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { } - - public: - typedef basic_table_iterator<base_t> iterator; - typedef iterator const_iterator; - - basic_table_core() noexcept : base_t() { } - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_table_core(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_table<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - stack::check<basic_table_core>(base_t::lua_state(), -1, type_panic); - } -#endif // Safety - } - basic_table_core(const basic_table_core&) = default; - basic_table_core(basic_table_core&&) = default; - basic_table_core& operator=(const basic_table_core&) = default; - basic_table_core& operator=(basic_table_core&&) = default; - basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {} - basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_table_core(lua_State* L, T&& r) : basic_table_core(L, sol::ref_index(r.registry_index())) {} - basic_table_core(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<basic_table_core>(L, index, type_panic); -#endif // Safety - } - basic_table_core(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<basic_table_core>(L, -1, type_panic); -#endif // Safety - } - - iterator begin() const { - return iterator(*this); - } - - iterator end() const { - return iterator(); - } - - const_iterator cbegin() const { - return begin(); - } - - const_iterator cend() const { - return end(); - } - - template<typename... Ret, typename... Keys> - decltype(auto) get(Keys&&... keys) const { - static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); - auto pp = stack::push_pop<is_global<Keys...>::value>(*this); - return tuple_get(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), std::forward_as_tuple(std::forward<Keys>(keys)...)); - } - - template<typename T, typename Key> - decltype(auto) get_or(Key&& key, T&& otherwise) const { - typedef decltype(get<T>("")) U; - sol::optional<U> option = get<sol::optional<U>>(std::forward<Key>(key)); - if (option) { - return static_cast<U>(option.value()); - } - return static_cast<U>(std::forward<T>(otherwise)); - } - - template<typename T, typename Key, typename D> - decltype(auto) get_or(Key&& key, D&& otherwise) const { - sol::optional<T> option = get<sol::optional<T>>(std::forward<Key>(key)); - if (option) { - return static_cast<T>(option.value()); - } - return static_cast<T>(std::forward<D>(otherwise)); - } - - template <typename T, typename... Keys> - decltype(auto) traverse_get(Keys&&... keys) const { - auto pp = stack::push_pop<is_global<Keys...>::value>(*this); - return traverse_get_optional<top_level, T>(meta::is_specialization_of<sol::optional, meta::unqualified_t<T>>(), std::forward<Keys>(keys)...); - } - - template <typename... Keys> - basic_table_core& traverse_set(Keys&&... keys) { - auto pp = stack::push_pop<is_global<Keys...>::value>(*this); - auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys)-2)); - traverse_set_deep<top_level>(std::forward<Keys>(keys)...); - return *this; - } - - template<typename... Args> - basic_table_core& set(Args&&... args) { - tuple_set(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); - return *this; - } - - template<typename T> - basic_table_core& set_usertype(usertype<T>& user) { - return set_usertype(usertype_traits<T>::name(), user); - } - - template<typename Key, typename T> - basic_table_core& set_usertype(Key&& key, usertype<T>& user) { - return set(std::forward<Key>(key), user); - } - - template<typename Class, typename... Args> - basic_table_core& new_usertype(const std::string& name, Args&&... args) { - usertype<Class> utype(std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - basic_table_core& new_usertype(const std::string& name, Args&&... args) { - constructors<types<CTor0, CTor...>> ctor{}; - return new_usertype<Class>(name, ctor, std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - basic_table_core& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - usertype<Class> utype(ctor, std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename... Args> - basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { - constructors<types<CTor0, CTor...>> ctor{}; - return new_simple_usertype<Class>(name, ctor, std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - basic_table_core& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), ctor, std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), std::forward<Args>(args)...); - return utype; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - constructors<types<CTor0, CTor...>> ctor{}; - return create_simple_usertype<Class>(ctor, std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - simple_usertype<Class> create_simple_usertype(constructors<CArgs...> ctor, Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), ctor, std::forward<Args>(args)...); - return utype; - } - - template<bool read_only = true, typename... Args> - basic_table_core& new_enum(const std::string& name, Args&&... args) { - if (read_only) { - table idx = create_with(std::forward<Args>(args)...); - table x = create_with( - meta_function::new_index, detail::fail_on_newindex, - meta_function::index, idx - ); - table target = create_named(name); - target[metatable_key] = x; - } - else { - create_named(name, std::forward<Args>(args)...); - } - return *this; - } - - template<typename Fx> - void for_each(Fx&& fx) const { - typedef meta::is_invokable<Fx(std::pair<sol::object, sol::object>)> is_paired; - for_each(is_paired(), std::forward<Fx>(fx)); - } - - size_t size() const { - auto pp = stack::push_pop(*this); - lua_len(base_t::lua_state(), -1); - return stack::pop<size_t>(base_t::lua_state()); - } - - bool empty() const { - return cbegin() == cend(); - } - - template<typename T> - proxy<basic_table_core&, T> operator[](T&& key) & { - return proxy<basic_table_core&, T>(*this, std::forward<T>(key)); - } - - template<typename T> - proxy<const basic_table_core&, T> operator[](T&& key) const & { - return proxy<const basic_table_core&, T>(*this, std::forward<T>(key)); - } - - template<typename T> - proxy<basic_table_core, T> operator[](T&& key) && { - return proxy<basic_table_core, T>(*this, std::forward<T>(key)); - } - - template<typename Sig, typename Key, typename... Args> - basic_table_core& set_function(Key&& key, Args&&... args) { - set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template<typename Key, typename... Args> - basic_table_core& set_function(Key&& key, Args&&... args) { - set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template <typename... Args> - basic_table_core& add(Args&&... args) { - auto pp = stack::push_pop(*this); - (void)detail::swallow{0, - (stack::set_ref(base_t::lua_state(), std::forward<Args>(args)), 0)... - }; - return *this; - } - - private: - template<typename R, typename... Args, typename Fx, typename Key, typename = std::result_of_t<Fx(Args...)>> - void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) { - set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx)); - } - - template<typename Fx, typename Key, meta::enable<meta::is_specialization_of<overload_set, meta::unqualified_t<Fx>>> = meta::enabler> - void set_fx(types<>, Key&& key, Fx&& fx) { - set(std::forward<Key>(key), std::forward<Fx>(fx)); - } - - template<typename Fx, typename Key, typename... Args, meta::disable<meta::is_specialization_of<overload_set, meta::unqualified_t<Fx>>> = meta::enabler> - void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { - set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...)); - } - - template<typename... Sig, typename... Args, typename Key> - void set_resolved_function(Key&& key, Args&&... args) { - set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...)); - } - - public: - static inline table create(lua_State* L, int narr = 0, int nrec = 0) { - lua_createtable(L, narr, nrec); - table result(L); - lua_pop(L, 1); - return result; - } - - template <typename Key, typename Value, typename... Args> - static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - lua_createtable(L, narr, nrec); - table result(L); - result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - lua_pop(L, 1); - return result; - } - - template <typename... Args> - static inline table create_with(lua_State* L, Args&&... args) { - static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); - static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); - return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...); - } - - table create(int narr = 0, int nrec = 0) { - return create(base_t::lua_state(), narr, nrec); - } - - template <typename Key, typename Value, typename... Args> - table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename Name> - table create(Name&& name, int narr = 0, int nrec = 0) { - table x = create(base_t::lua_state(), narr, nrec); - this->set(std::forward<Name>(name), x); - return x; - } - - template <typename Name, typename Key, typename Value, typename... Args> - table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - this->set(std::forward<Name>(name), x); - return x; - } - - template <typename... Args> - table create_with(Args&&... args) { - return create_with(base_t::lua_state(), std::forward<Args>(args)...); - } - - template <typename Name, typename... Args> - table create_named(Name&& name, Args&&... args) { - static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); - return create(std::forward<Name>(name), narr, sizeof...(Args) / 2 - narr, std::forward<Args>(args)...); - } - - ~basic_table_core() { - - } - }; -} // sol - -// end of sol/table_core.hpp - -namespace sol { - typedef table_core<false> table; -} // sol - -// end of sol/table.hpp - -// beginning of sol/load_result.hpp - -namespace sol { - struct load_result : public proxy_base<load_result> { - private: - lua_State* L; - int index; - int returncount; - int popcount; - load_status err; - - template <typename T> - decltype(auto) tagged_get(types<sol::optional<T>>) const { - if (!valid()) { - return sol::optional<T>(nullopt); - } - return stack::get<sol::optional<T>>(L, index); - } - - template <typename T> - decltype(auto) tagged_get(types<T>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (!valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return stack::get<T>(L, index); - } - - sol::optional<sol::error> tagged_get(types<sol::optional<sol::error>>) const { - if (valid()) { - return nullopt; - } - return sol::error(detail::direct_error, stack::get<std::string>(L, index)); - } - - sol::error tagged_get(types<sol::error>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return sol::error(detail::direct_error, stack::get<std::string>(L, index)); - } - - public: - load_result() = default; - load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) { - - } - load_result(const load_result&) = default; - load_result& operator=(const load_result&) = default; - load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = load_status::syntax; - } - load_result& operator=(load_result&& o) noexcept { - L = o.L; - index = o.index; - returncount = o.returncount; - popcount = o.popcount; - err = o.err; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = load_status::syntax; - return *this; - } - - load_status status() const noexcept { - return err; - } - - bool valid() const noexcept { - return status() == load_status::ok; - } - - template<typename T> - T get() const { - return tagged_get(types<meta::unqualified_t<T>>()); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Args> - decltype(auto) operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - - lua_State* lua_state() const noexcept { return L; }; - int stack_index() const noexcept { return index; }; - - ~load_result() { - stack::remove(L, index, popcount); - } - }; -} // sol - -// end of sol/load_result.hpp - -namespace sol { - enum class lib : char { - base, - package, - coroutine, - string, - os, - math, - table, - debug, - bit32, - io, - ffi, - jit, - utf8, - count - }; - - inline std::size_t total_memory_used(lua_State* L) { - std::size_t kb = lua_gc(L, LUA_GCCOUNT, 0); - kb *= 1024; - kb += lua_gc(L, LUA_GCCOUNTB, 0); - return kb; - } - - class state_view { - private: - lua_State* L; - table reg; - global_table global; - - optional<object> is_loaded_package(const std::string& key) { - auto loaded = reg.traverse_get<optional<object>>("_LOADED", key); - bool is53mod = loaded && !(loaded->is<bool>() && !loaded->as<bool>()); - if (is53mod) - return loaded; -#if SOL_LUA_VERSION <= 501 - auto loaded51 = global.traverse_get<optional<object>>("package", "loaded", key); - bool is51mod = loaded51 && !(loaded51->is<bool>() && !loaded51->as<bool>()); - if (is51mod) - return loaded51; -#endif - return nullopt; - } - - template <typename T> - void ensure_package(const std::string& key, T&& sr) { -#if SOL_LUA_VERSION <= 501 - auto pkg = global["package"]; - if (!pkg.valid()) { - pkg = create_table_with("loaded", create_table_with(key, sr)); - } - else { - auto ld = pkg["loaded"]; - if (!ld.valid()) { - ld = create_table_with(key, sr); - } - else { - ld[key] = sr; - } - } -#endif - auto loaded = reg["_LOADED"]; - if (!loaded.valid()) { - loaded = create_table_with(key, sr); - } - else { - loaded[key] = sr; - } - } - - template <typename Fx> - object require_core(const std::string& key, Fx&& action, bool create_global = true) { - optional<object> loaded = is_loaded_package(key); - if (loaded && loaded->valid()) - return std::move(*loaded); - action(); - auto sr = stack::get<stack_reference>(L); - if (create_global) - set(key, sr); - ensure_package(key, sr); - return stack::pop<object>(L); - } - - public: - typedef global_table::iterator iterator; - typedef global_table::const_iterator const_iterator; - - state_view(lua_State* Ls) : - L(Ls), - reg(Ls, LUA_REGISTRYINDEX), - global(Ls, detail::global_) { - - } - - state_view(this_state Ls) : state_view(Ls.L){ - - } - - lua_State* lua_state() const { - return L; - } - - template<typename... Args> - void open_libraries(Args&&... args) { - static_assert(meta::all_same<lib, Args...>::value, "all types must be libraries"); - if (sizeof...(args) == 0) { - luaL_openlibs(L); - return; - } - - lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... }; - - for (auto&& library : libraries) { - switch (library) { -#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) - case lib::coroutine: -#endif // luajit opens coroutine base stuff - case lib::base: - luaL_requiref(L, "base", luaopen_base, 1); - lua_pop(L, 1); - break; - case lib::package: - luaL_requiref(L, "package", luaopen_package, 1); - lua_pop(L, 1); - break; -#if !defined(SOL_LUAJIT) - case lib::coroutine: -#if SOL_LUA_VERSION > 501 - luaL_requiref(L, "coroutine", luaopen_coroutine, 1); - lua_pop(L, 1); -#endif // Lua 5.2+ only - break; -#endif // Not LuaJIT - comes builtin - case lib::string: - luaL_requiref(L, "string", luaopen_string, 1); - lua_pop(L, 1); - break; - case lib::table: - luaL_requiref(L, "table", luaopen_table, 1); - lua_pop(L, 1); - break; - case lib::math: - luaL_requiref(L, "math", luaopen_math, 1); - lua_pop(L, 1); - break; - case lib::bit32: -#ifdef SOL_LUAJIT - luaL_requiref(L, "bit32", luaopen_bit, 1); - lua_pop(L, 1); -#elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) - luaL_requiref(L, "bit32", luaopen_bit32, 1); - lua_pop(L, 1); -#else -#endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) - break; - case lib::io: - luaL_requiref(L, "io", luaopen_io, 1); - lua_pop(L, 1); - break; - case lib::os: - luaL_requiref(L, "os", luaopen_os, 1); - lua_pop(L, 1); - break; - case lib::debug: - luaL_requiref(L, "debug", luaopen_debug, 1); - lua_pop(L, 1); - break; - case lib::utf8: -#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) - luaL_requiref(L, "utf8", luaopen_utf8, 1); - lua_pop(L, 1); -#endif // Lua 5.3+ only - break; - case lib::ffi: -#ifdef SOL_LUAJIT - luaL_requiref(L, "ffi", luaopen_ffi, 1); - lua_pop(L, 1); -#endif // LuaJIT only - break; - case lib::jit: -#ifdef SOL_LUAJIT - luaL_requiref(L, "jit", luaopen_jit, 1); - lua_pop(L, 1); -#endif // LuaJIT Only - break; - case lib::count: - default: - break; - } - } - } - - object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { - luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); - return stack::pop<object>(L); - } - - object require_script(const std::string& key, const std::string& code, bool create_global = true) { - return require_core(key, [this, &code]() {stack::script(L, code); }, create_global); - } - - object require_file(const std::string& key, const std::string& filename, bool create_global = true) { - return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); - } - - protected_function_result do_string(const std::string& code) { - sol::protected_function pf = load(code); - return pf(); - } - - protected_function_result do_file(const std::string& filename) { - sol::protected_function pf = load_file(filename); - return pf(); - } - - function_result script(const std::string& code) { - int index = lua_gettop(L); - stack::script(L, code); - int postindex = lua_gettop(L); - int returns = postindex - index; - return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); - } - - function_result script_file(const std::string& filename) { - int index = lua_gettop(L); - stack::script_file(L, filename); - int postindex = lua_gettop(L); - int returns = postindex - index; - return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); - } - - load_result load(const std::string& code) { - load_status x = static_cast<load_status>(luaL_loadstring(L, code.c_str())); - return load_result(L, lua_absindex(L, -1), 1, 1, x); - } - - load_result load_file(const std::string& filename) { - load_status x = static_cast<load_status>(luaL_loadfile(L, filename.c_str())); - return load_result(L, lua_absindex(L, -1), 1, 1, x); - } - - load_result load_buffer(const char *buff, size_t size, const char *name, const char* mode = nullptr) { - load_status x = static_cast<load_status>(luaL_loadbufferx(L, buff, size, name, mode)); - return load_result(L, lua_absindex(L, -1), 1, 1, x); - } - - iterator begin() const { - return global.begin(); - } - - iterator end() const { - return global.end(); - } - - const_iterator cbegin() const { - return global.cbegin(); - } - - const_iterator cend() const { - return global.cend(); - } - - global_table globals() const { - return global; - } - - table registry() const { - return reg; - } - - std::size_t memory_used() const { - return total_memory_used(lua_state()); - } - - void collect_garbage() { - lua_gc(lua_state(), LUA_GCCOLLECT, 0); - } - - operator lua_State* () const { - return lua_state(); - } - - void set_panic(lua_CFunction panic) { - lua_atpanic(L, panic); - } - - template<typename... Args, typename... Keys> - decltype(auto) get(Keys&&... keys) const { - return global.get<Args...>(std::forward<Keys>(keys)...); - } - - template<typename T, typename Key> - decltype(auto) get_or(Key&& key, T&& otherwise) const { - return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise)); - } - - template<typename T, typename Key, typename D> - decltype(auto) get_or(Key&& key, D&& otherwise) const { - return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise)); - } - - template<typename... Args> - state_view& set(Args&&... args) { - global.set(std::forward<Args>(args)...); - return *this; - } - - template<typename T, typename... Keys> - decltype(auto) traverse_get(Keys&&... keys) const { - return global.traverse_get<T>(std::forward<Keys>(keys)...); - } - - template<typename... Args> - state_view& traverse_set(Args&&... args) { - global.traverse_set(std::forward<Args>(args)...); - return *this; - } - - template<typename T> - state_view& set_usertype(usertype<T>& user) { - return set_usertype(usertype_traits<T>::name(), user); - } - - template<typename Key, typename T> - state_view& set_usertype(Key&& key, usertype<T>& user) { - global.set_usertype(std::forward<Key>(key), user); - return *this; - } - - template<typename Class, typename... Args> - state_view& new_usertype(const std::string& name, Args&&... args) { - global.new_usertype<Class>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - state_view& new_usertype(const std::string& name, Args&&... args) { - global.new_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... CArgs, typename... Args> - state_view& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - global.new_usertype<Class>(name, ctor, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... Args> - state_view& new_simple_usertype(const std::string& name, Args&&... args) { - global.new_simple_usertype<Class>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - state_view& new_simple_usertype(const std::string& name, Args&&... args) { - global.new_simple_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... CArgs, typename... Args> - state_view& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - global.new_simple_usertype<Class>(name, ctor, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - return global.create_simple_usertype<Class>(std::forward<Args>(args)...); - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - return global.create_simple_usertype<Class, CTor0, CTor...>(std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - simple_usertype<Class> create_simple_usertype(constructors<CArgs...> ctor, Args&&... args) { - return global.create_simple_usertype<Class>(ctor, std::forward<Args>(args)...); - } - - template<bool read_only = true, typename... Args> - state_view& new_enum(const std::string& name, Args&&... args) { - global.new_enum<read_only>(name, std::forward<Args>(args)...); - return *this; - } - - template <typename Fx> - void for_each(Fx&& fx) { - global.for_each(std::forward<Fx>(fx)); - } - - template<typename T> - proxy<global_table&, T> operator[](T&& key) { - return global[std::forward<T>(key)]; - } - - template<typename T> - proxy<const global_table&, T> operator[](T&& key) const { - return global[std::forward<T>(key)]; - } - - template<typename Sig, typename... Args, typename Key> - state_view& set_function(Key&& key, Args&&... args) { - global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template<typename... Args, typename Key> - state_view& set_function(Key&& key, Args&&... args) { - global.set_function(std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template <typename Name> - table create_table(Name&& name, int narr = 0, int nrec = 0) { - return global.create(std::forward<Name>(name), narr, nrec); - } - - template <typename Name, typename Key, typename Value, typename... Args> - table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename Name, typename... Args> - table create_named_table(Name&& name, Args&&... args) { - table x = global.create_with(std::forward<Args>(args)...); - global.set(std::forward<Name>(name), x); - return x; - } - - table create_table(int narr = 0, int nrec = 0) { - return create_table(lua_state(), narr, nrec); - } - - template <typename Key, typename Value, typename... Args> - table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename... Args> - table create_table_with(Args&&... args) { - return create_table_with(lua_state(), std::forward<Args>(args)...); - } - - static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { - return global_table::create(L, narr, nrec); - } - - template <typename Key, typename Value, typename... Args> - static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename... Args> - static inline table create_table_with(lua_State* L, Args&&... args) { - return global_table::create_with(L, std::forward<Args>(args)...); - } - }; -} // sol - -// end of sol/state_view.hpp - -namespace sol { - inline int default_at_panic(lua_State* L) { -#ifdef SOL_NO_EXCEPTIONS - (void)L; - return -1; -#else - const char* message = lua_tostring(L, -1); - if (message) { - std::string err = message; - lua_pop(L, 1); - throw error(err); - } - throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic")); -#endif - } - - inline int default_error_handler(lua_State*L) { - using namespace sol; - std::string msg = "An unknown error has triggered the default error handler"; - optional<string_detail::string_shim> maybetopmsg = stack::check_get<string_detail::string_shim>(L, 1); - if (maybetopmsg) { - const string_detail::string_shim& topmsg = maybetopmsg.value(); - msg.assign(topmsg.c_str(), topmsg.size()); - } - luaL_traceback(L, L, msg.c_str(), 1); - optional<string_detail::string_shim> maybetraceback = stack::check_get<string_detail::string_shim>(L, -1); - if (maybetraceback) { - const string_detail::string_shim& traceback = maybetraceback.value(); - msg.assign(traceback.c_str(), traceback.size()); - } - return stack::push(L, msg); - } - - class state : private std::unique_ptr<lua_State, void(*)(lua_State*)>, public state_view { - private: - typedef std::unique_ptr<lua_State, void(*)(lua_State*)> unique_base; - public: - state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), - state_view(unique_base::get()) { - set_panic(panic); - stack::luajit_exception_handler(unique_base::get()); - } - - state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close), - state_view(unique_base::get()) { - set_panic(panic); - sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler)); - stack::luajit_exception_handler(unique_base::get()); - } - - state(const state&) = delete; - state(state&&) = default; - state& operator=(const state&) = delete; - state& operator=(state&&) = default; - - using state_view::get; - - ~state() { - auto& handler = protected_function::get_default_handler(); - if (handler.lua_state() == this->lua_state()) { - protected_function::set_default_handler(reference()); - } - } - }; -} // sol - -// end of sol/state.hpp - -// beginning of sol/coroutine.hpp - -// beginning of sol/thread.hpp - -namespace sol { - struct lua_thread_state { - lua_State* L; - operator lua_State* () const { - return L; - } - lua_State* operator-> () const { - return L; - } - }; - - namespace stack { - - template <> - struct pusher<lua_thread_state> { - int push(lua_State*, lua_thread_state lts) { - lua_pushthread(lts.L); - return 1; - } - }; - - template <> - struct getter<lua_thread_state> { - lua_thread_state get(lua_State* L, int index, record& tracking) { - tracking.use(1); - lua_thread_state lts{ lua_tothread(L, index) }; - return lts; - } - }; - - template <> - struct check_getter<lua_thread_state> { - template <typename Handler> - optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) { - lua_thread_state lts{ lua_tothread(L, index) }; - if (lts.L == nullptr) { - handler(L, index, type::thread, type_of(L, index)); - return nullopt; - } - tracking.use(1); - return lts; - } - }; - - } - -#if SOL_LUA_VERSION < 502 - inline lua_State* main_thread(lua_State*, lua_State* backup_if_unsupported = nullptr) { - return backup_if_unsupported; - } -#else - inline lua_State* main_thread(lua_State* L, lua_State* = nullptr) { - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); - lua_thread_state s = stack::pop<lua_thread_state>(L); - return s.L; - } -#endif // Lua 5.2+ has the main thread getter - - class thread : public reference { - public: - thread() noexcept = default; - thread(const thread&) = default; - thread(thread&&) = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, thread>>, std::is_base_of<reference, meta::unqualified_t<T>>> = meta::enabler> - thread(T&& r) : reference(std::forward<T>(r)) {} - thread(const stack_reference& r) : thread(r.lua_state(), r.stack_index()) {}; - thread(stack_reference&& r) : thread(r.lua_state(), r.stack_index()) {}; - thread& operator=(const thread&) = default; - thread& operator=(thread&&) = default; - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - thread(lua_State* L, T&& r) : thread(L, sol::ref_index(r.registry_index())) {} - thread(lua_State* L, int index = -1) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::thread); -#endif // Safety - } - thread(lua_State* L, ref_index index) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::thread); -#endif // Safety - } - thread(lua_State* L, lua_State* actualthread) : thread(L, lua_thread_state{ actualthread }) {} - thread(lua_State* L, sol::this_state actualthread) : thread(L, lua_thread_state{ actualthread.L }) {} - thread(lua_State* L, lua_thread_state actualthread) : reference(L, -stack::push(L, actualthread)) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, -1, type::thread); -#endif // Safety - lua_pop(L, 1); - } - - state_view state() const { - return state_view(this->thread_state()); - } - - bool is_main_thread() const { - int ismainthread = lua_pushthread(this->thread_state()); - lua_pop(this->thread_state(), 1); - return ismainthread == 1; - } - - lua_State* thread_state() const { - auto pp = stack::push_pop(*this); - lua_State* lthread = lua_tothread(lua_state(), -1); - return lthread; - } - - thread_status status() const { - lua_State* lthread = thread_state(); - thread_status lstat = static_cast<thread_status>(lua_status(lthread)); - if (lstat != thread_status::ok && lua_gettop(lthread) == 0) { - // No thing on the thread's stack means its dead - return thread_status::dead; - } - return lstat; - } - - thread create() { - return create(lua_state()); - } - - static thread create(lua_State* L) { - lua_newthread(L); - thread result(L); - lua_pop(L, 1); - return result; - } - }; -} // sol - -// end of sol/thread.hpp - -namespace sol { - class coroutine : public reference { - private: - call_status stats = call_status::yielded; - - void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { -#if SOL_LUA_VERSION < 502 - stats = static_cast<call_status>(lua_resume(lua_state(), static_cast<int>(argcount))); -#else - stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount))); -#endif // Lua 5.1 compat - } - - template<std::size_t... I, typename... Ret> - auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) { - luacall(n, sizeof...(Ret)); - return stack::pop<std::tuple<Ret...>>(lua_state()); - } - - template<std::size_t I, typename Ret> - Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) { - luacall(n, 1); - return stack::pop<Ret>(lua_state()); - } - - template <std::size_t I> - void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) { - luacall(n, 0); - } - - protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { - int stacksize = lua_gettop(lua_state()); - int firstreturn = (std::max)(1, stacksize - static_cast<int>(n)); - luacall(n, LUA_MULTRET); - int poststacksize = lua_gettop(lua_state()); - int returncount = poststacksize - (firstreturn - 1); - if (error()) { - return protected_function_result(lua_state(), lua_absindex(lua_state(), -1), 1, returncount, status()); - } - return protected_function_result(lua_state(), firstreturn, returncount, returncount, status()); - } - - public: - coroutine() noexcept = default; - coroutine(const coroutine&) noexcept = default; - coroutine(coroutine&&) noexcept = default; - coroutine& operator=(const coroutine&) noexcept = default; - coroutine& operator=(coroutine&&) noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, coroutine>>, std::is_base_of<reference, meta::unqualified_t<T>>> = meta::enabler> - coroutine(T&& r) : reference(std::forward<T>(r)) {} - coroutine(lua_nil_t r) : reference(r) {} - coroutine(const stack_reference& r) noexcept : coroutine(r.lua_state(), r.stack_index()) {} - coroutine(stack_reference&& r) noexcept : coroutine(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - coroutine(lua_State* L, T&& r) : coroutine(L, sol::ref_index(r.registry_index())) {} - coroutine(lua_State* L, int index = -1) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<coroutine>(L, index, type_panic); -#endif // Safety - } - coroutine(lua_State* L, ref_index index) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<coroutine>(L, -1, type_panic); -#endif // Safety - } - - call_status status() const noexcept { - return stats; - } - - bool error() const noexcept { - call_status cs = status(); - return cs != call_status::ok && cs != call_status::yielded; - } - - bool runnable() const noexcept { - return valid() - && (status() == call_status::yielded); - } - - explicit operator bool() const noexcept { - return runnable(); - } - - template<typename... Args> - protected_function_result operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) operator()(types<Ret...>, Args&&... args) { - return call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - push(); - int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...); - return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); - } - }; -} // sol - -// end of sol/coroutine.hpp - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#elif defined _MSC_VER -#pragma warning( push ) -#endif // g++ - -#ifdef SOL_INSIDE_UNREAL -#ifdef SOL_INSIDE_UNREAL_REMOVED_CHECK -#define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } }} -#endif -#endif // Unreal Engine 4 Bullshit - -#endif // SOL_HPP -// end of sol.hpp - -#endif // SOL_SINGLE_INCLUDE_HPP diff --git a/3rdparty/sol2/sol.hpp b/3rdparty/sol2/sol.hpp deleted file mode 100644 index cafabcac837..00000000000 --- a/3rdparty/sol2/sol.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_HPP -#define SOL_HPP - -#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) -#define SOL_INSIDE_UNREAL -#endif // Unreal Engine 4 bullshit - -#ifdef SOL_INSIDE_UNREAL -#ifdef check -#define SOL_INSIDE_UNREAL_REMOVED_CHECK -#undef check -#endif -#endif // Unreal Engine 4 Bullshit - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wconversion" -#elif defined _MSC_VER -#pragma warning( push ) -#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier -#endif // g++ - -#include "sol/state.hpp" -#include "sol/object.hpp" -#include "sol/function.hpp" -#include "sol/protected_function.hpp" -#include "sol/state.hpp" -#include "sol/coroutine.hpp" -#include "sol/variadic_args.hpp" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#elif defined _MSC_VER -#pragma warning( push ) -#endif // g++ - -#ifdef SOL_INSIDE_UNREAL -#ifdef SOL_INSIDE_UNREAL_REMOVED_CHECK -#define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } }} -#endif -#endif // Unreal Engine 4 Bullshit - -#endif // SOL_HPP diff --git a/3rdparty/sol2/sol/as_args.hpp b/3rdparty/sol2/sol/as_args.hpp deleted file mode 100644 index 2b5092cc9cf..00000000000 --- a/3rdparty/sol2/sol/as_args.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TO_ARGS_HPP -#define SOL_TO_ARGS_HPP - -#include "stack.hpp" - -namespace sol { - template <typename T> - struct to_args_t { - T src; - }; - - template <typename Source> - auto as_args(Source&& source) { - return to_args_t<Source>{ std::forward<Source>(source) }; - } - - namespace stack { - template <typename T> - struct pusher<to_args_t<T>> { - int push(lua_State* L, const to_args_t<T>& e) { - int p = 0; - for (const auto& i : e.src) { - p += stack::push(L, i); - } - return p; - } - }; - } -} // sol - -#endif // SOL_TO_ARGS_HPP diff --git a/3rdparty/sol2/sol/bind_traits.hpp b/3rdparty/sol2/sol/bind_traits.hpp deleted file mode 100644 index a78cb6a3ee1..00000000000 --- a/3rdparty/sol2/sol/bind_traits.hpp +++ /dev/null @@ -1,243 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_BIND_TRAITS_HPP -#define SOL_BIND_TRAITS_HPP - -#include "tuple.hpp" - -namespace sol { - namespace meta { - namespace meta_detail { - - template<class F> - struct check_deducible_signature { - struct nat {}; - template<class G> - static auto test(int) -> decltype(&G::operator(), void()); - template<class> - static auto test(...)->nat; - - using type = std::is_void<decltype(test<F>(0))>; - }; - } // meta_detail - - template<class F> - struct has_deducible_signature : meta_detail::check_deducible_signature<F>::type { }; - - namespace meta_detail { - - template <std::size_t I, typename T> - struct void_tuple_element : meta::tuple_element<I, T> {}; - - template <std::size_t I> - struct void_tuple_element<I, std::tuple<>> { typedef void type; }; - - template <std::size_t I, typename T> - using void_tuple_element_t = typename void_tuple_element<I, T>::type; - - template <bool has_c_variadic, typename T, typename R, typename... Args> - struct basic_traits { - private: - typedef std::conditional_t<std::is_void<T>::value, int, T>& first_type; - - public: - static const bool is_member_function = std::is_void<T>::value; - static const bool has_c_var_arg = has_c_variadic; - static const std::size_t arity = sizeof...(Args); - static const std::size_t free_arity = sizeof...(Args)+static_cast<std::size_t>(!std::is_void<T>::value); - typedef types<Args...> args_list; - typedef std::tuple<Args...> args_tuple; - typedef T object_type; - typedef R return_type; - typedef tuple_types<R> returns_list; - typedef R(function_type)(Args...); - typedef std::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list; - typedef std::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type; - typedef std::conditional_t<std::is_void<T>::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; - typedef std::remove_pointer_t<free_function_pointer_type> signature_type; - template<std::size_t i> - using arg_at = void_tuple_element_t<i, args_tuple>; - }; - - template<typename Signature, bool b = has_deducible_signature<Signature>::value> - struct fx_traits : basic_traits<false, void, void> {}; - - // Free Functions - template<typename R, typename... Args> - struct fx_traits<R(Args...), false> : basic_traits<false, void, R, Args...> { - typedef R(*function_pointer_type)(Args...); - }; - - template<typename R, typename... Args> - struct fx_traits<R(*)(Args...), false> : basic_traits<false, void, R, Args...> { - typedef R(*function_pointer_type)(Args...); - }; - - template<typename R, typename... Args> - struct fx_traits<R(Args..., ...), false> : basic_traits<true, void, R, Args...> { - typedef R(*function_pointer_type)(Args..., ...); - }; - - template<typename R, typename... Args> - struct fx_traits<R(*)(Args..., ...), false> : basic_traits<true, void, R, Args...> { - typedef R(*function_pointer_type)(Args..., ...); - }; - - // Member Functions - /* C-Style Variadics */ - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...), false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...); - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...), false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...); - }; - - /* Const Volatile */ - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const volatile, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const volatile; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const volatile, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile; - }; - - /* Member Function Qualifiers */ - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) &, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) &, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const &, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const &, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const volatile &, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const volatile &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const volatile &, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) && , false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) && ; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) && , false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) && ; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const &&, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const &&; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const &&, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const &&; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args...) const volatile &&, false> : basic_traits<false, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args...) const volatile &&; - }; - - template<typename T, typename R, typename... Args> - struct fx_traits<R(T::*)(Args..., ...) const volatile &&, false> : basic_traits<true, T, R, Args...> { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; - }; - - template<typename Signature> - struct fx_traits<Signature, true> : fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> {}; - - template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value> - struct callable_traits : fx_traits<std::decay_t<Signature>> { - - }; - - template<typename R, typename T> - struct callable_traits<R(T::*), true> { - typedef R Arg; - typedef T object_type; - using signature_type = R(T::*); - static const bool is_member_function = false; - static const std::size_t arity = 1; - static const std::size_t free_arity = 2; - typedef std::tuple<Arg> args_tuple; - typedef R return_type; - typedef types<Arg> args_list; - typedef types<T, Arg> free_args_list; - typedef meta::tuple_types<R> returns_list; - typedef R(function_type)(T&, R); - typedef R(*function_pointer_type)(T&, R); - typedef R(*free_function_pointer_type)(T&, R); - template<std::size_t i> - using arg_at = void_tuple_element_t<i, args_tuple>; - }; - } // meta_detail - - template<typename Signature> - struct bind_traits : meta_detail::callable_traits<Signature> {}; - - template<typename Signature> - using function_args_t = typename bind_traits<Signature>::args_list; - - template<typename Signature> - using function_signature_t = typename bind_traits<Signature>::signature_type; - - template<typename Signature> - using function_return_t = typename bind_traits<Signature>::return_type; - - } // meta -} // sol - -#endif // SOL_BIND_TRAITS_HPP diff --git a/3rdparty/sol2/sol/call.hpp b/3rdparty/sol2/sol/call.hpp deleted file mode 100644 index d09cc023b70..00000000000 --- a/3rdparty/sol2/sol/call.hpp +++ /dev/null @@ -1,615 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_CALL_HPP -#define SOL_CALL_HPP - -#include "protect.hpp" -#include "wrapper.hpp" -#include "property.hpp" -#include "stack.hpp" - -namespace sol { - namespace call_detail { - - template <typename R, typename W> - inline auto& pick(std::true_type, property_wrapper<R, W>& f) { - return f.read; - } - - template <typename R, typename W> - inline auto& pick(std::false_type, property_wrapper<R, W>& f) { - return f.write; - } - - template <typename T, typename List> - struct void_call; - - template <typename T, typename... Args> - struct void_call<T, types<Args...>> { - static void call(Args...) {} - }; - - template <typename T> - struct constructor_match { - T* obj; - - constructor_match(T* o) : obj(o) {} - - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const { - detail::default_construct func{}; - return stack::call_into_lua<stack::stack_detail::default_check_arguments>(r, a, L, start, func, obj); - } - }; - - namespace overload_detail { - template <std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) { - return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); - } - - template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; - typedef meta::tuple_types<typename traits::return_type> return_types; - typedef typename traits::free_args_list args_list; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { - return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - stack::record tracking{}; - if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); - } - - template <std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity_single(types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; - typedef meta::tuple_types<typename traits::return_type> return_types; - typedef typename traits::free_args_list args_list; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, typename... Args> - inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits; - typedef meta::tuple_types<typename traits::return_type> return_types; - typedef typename traits::free_args_list args_list; - // compile-time eliminate any functions that we know ahead of time are of improper arity - if (meta::find_in_pack_v<index_value<traits::free_arity>, index_value<M>...>::value) { - return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { - return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<traits::free_arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - stack::record tracking{}; - if (!stack::stack_detail::check_types<true>{}.check(args_list(), L, start, no_panic, tracking)) { - return overload_match_arity(types<Fx1, Fxs...>(), std::index_sequence<I1, In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - return matchfx(types<Fx>(), index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); - } - } // overload_detail - - template <typename... Functions, typename Match, typename... Args> - inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - return overload_detail::overload_match_arity_single(types<Functions...>(), std::make_index_sequence<sizeof...(Functions)>(), std::index_sequence<>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename... Functions, typename Match, typename... Args> - inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { - int fxarity = lua_gettop(L) - (start - 1); - return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename T, typename... TypeLists, typename Match, typename... Args> - inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - // use same overload resolution matching as all other parts of the framework - return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); - } - - template <typename T, typename... TypeLists> - inline int construct(lua_State* L) { - static const auto& meta = usertype_traits<T>::metatable(); - int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot; - argcount -= static_cast<int>(syntax); - - T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast<T*>(pointerpointer + 1); - referencepointer = obj; - reference userdataref(L, -1); - userdataref.pop(); - - construct_match<T, TypeLists...>(constructor_match<T>(obj), L, argcount, 1 + static_cast<int>(syntax)); - - userdataref.push(); - luaL_getmetatable(L, &meta[0]); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return luaL_error(L, "sol: unable to get usertype metatable"); - } - - lua_setmetatable(L, -2); - return 1; - } - - template <typename F, bool is_index, bool is_variable, bool checked, int boost, typename = void> - struct agnostic_lua_call_wrapper { - template <typename Fx, typename... Args> - static int call(lua_State* L, Fx&& f, Args&&... args) { - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::returns_list returns_list; - typedef typename wrap::free_args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...); - } - }; - - template <typename T, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<var_wrapper<T>, true, is_variable, checked, boost, C> { - template <typename F> - static int call(lua_State* L, F&& f) { - return stack::push_reference(L, detail::unwrap(f.value)); - } - }; - - template <typename T, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<var_wrapper<T>, false, is_variable, checked, boost, C> { - template <typename V> - static int call_assign(std::true_type, lua_State* L, V&& f) { - detail::unwrap(f.value) = stack::get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1)); - return 0; - } - - template <typename... Args> - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template <typename... Args> - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef meta::unwrapped_t<T> R; - return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...); - } - - template <typename... Args> - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template <typename V> - static int call(lua_State* L, V&& f) { - return call_const(std::is_const<meta::unwrapped_t<T>>(), L, f); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, lua_r_CFunction f) { - return f(L); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, lua_CFunction f) { - return f(L); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, const no_prop&) { - return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); - } - }; - - template <bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, C> { - static int call(lua_State* L, const no_construction&) { - return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); - } - }; - - template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, C> { - static int call(lua_State*, const bases<Args...>&) { - // Uh. How did you even call this, lul - return 0; - } - }; - - template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void> - struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {}; - - template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, F, is_index, is_variable, checked, boost, std::enable_if_t<std::is_member_function_pointer<F>::value>> { - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::object_type object_type; - - template <typename Fx> - static int call(lua_State* L, Fx&& f, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward<Fx>(f), o); - } - - template <typename Fx> - static int call(lua_State* L, Fx&& f) { - typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - return luaL_error(L, "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); - return call(L, std::forward<Fx>(f), *o); -#else - object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); - return call(L, std::forward<Fx>(f), o); -#endif // Safety - } - }; - - template <typename T, typename F, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, F, false, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::object_type object_type; - - template <typename V> - static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { - typedef typename wrap::args_list args_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(types<void>(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); - } - - template <typename V> - static int call_assign(std::true_type, lua_State* L, V&& f) { - typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); - } - return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); - return call_assign(std::true_type(), L, f, *o); -#else - object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); - return call_assign(std::true_type(), L, f, o); -#endif // Safety - } - - template <typename... Args> - static int call_assign(std::false_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); - } - - template <typename... Args> - static int call_const(std::false_type, lua_State* L, Args&&... args) { - typedef typename traits_type::return_type R; - return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...); - } - - template <typename... Args> - static int call_const(std::true_type, lua_State* L, Args&&...) { - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - - template <typename V> - static int call(lua_State* L, V&& f) { - return call_const(std::is_const<typename traits_type::return_type>(), L, f); - } - - template <typename V> - static int call(lua_State* L, V&& f, object_type& o) { - return call_const(std::is_const<typename traits_type::return_type>(), L, f, o); - } - }; - - template <typename T, typename F, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, F, true, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef wrapper<meta::unqualified_t<F>> wrap; - typedef typename wrap::object_type object_type; - - template <typename V> - static int call(lua_State* L, V&& f, object_type& o) { - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); - } - - template <typename V> - static int call(lua_State* L, V&& f) { - typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); - return call(L, f, *o); -#else - object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); - return call(L, f, o); -#endif // Safety - } - }; - - template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, constructor_list<Args...>, is_index, is_variable, checked, boost, C> { - typedef constructor_list<Args...> F; - - static int call(lua_State* L, F&) { - const auto& metakey = usertype_traits<T>::metatable(); - int argcount = lua_gettop(L); - call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot; - argcount -= static_cast<int>(syntax); - - T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - reference userdataref(L, -1); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast<T*>(pointerpointer + 1); - referencepointer = obj; - - construct_match<T, Args...>(constructor_match<T>(obj), L, argcount, boost + 1 + static_cast<int>(syntax)); - - userdataref.push(); - luaL_getmetatable(L, &metakey[0]); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return luaL_error(L, "sol: unable to get usertype metatable"); - } - - lua_setmetatable(L, -2); - return 1; - } - }; - - template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, C> { - typedef constructor_wrapper<Cxs...> F; - - struct onmatch { - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) { - const auto& metakey = usertype_traits<T>::metatable(); - T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - reference userdataref(L, -1); - T*& referencepointer = *pointerpointer; - T* obj = reinterpret_cast<T*>(pointerpointer + 1); - referencepointer = obj; - - auto& func = std::get<I>(f.functions); - stack::call_into_lua<checked>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj)); - - userdataref.push(); - luaL_getmetatable(L, &metakey[0]); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - std::string err = "sol: unable to get usertype metatable for "; - err += usertype_traits<T>::name(); - return luaL_error(L, err.c_str()); - } - lua_setmetatable(L, -2); - - return 1; - } - }; - - static int call(lua_State* L, F& f) { - call_syntax syntax = stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1); - int syntaxval = static_cast<int>(syntax); - int argcount = lua_gettop(L) - syntaxval; - return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f); - } - - }; - - template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<std::is_void<Fx>::value>> { - typedef destructor_wrapper<Fx> F; - - static int call(lua_State* L, const F&) { - return detail::usertype_alloc_destroy<T>(L); - } - }; - - template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost> - struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<!std::is_void<Fx>::value>> { - typedef destructor_wrapper<Fx> F; - - static int call(lua_State* L, const F& f) { - T& obj = stack::get<T>(L); - f.fx(detail::implicit_wrapper<T>(obj)); - return 0; - } - }; - - template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, C> { - typedef overload_set<Fs...> F; - - struct on_match { - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { - auto& f = std::get<I>(fx.functions); - return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost>{}.call(L, f); - } - }; - - static int call(lua_State* L, F& fx) { - return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); - } - }; - - template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, factory_wrapper<Fs...>, is_index, is_variable, checked, boost, C> { - typedef factory_wrapper<Fs...> F; - - struct on_match { - template <typename Fx, std::size_t I, typename... R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { - auto& f = std::get<I>(fx.functions); - return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost>{}.call(L, f); - } - }; - - static int call(lua_State* L, F& fx) { - return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx); - } - }; - - template <typename T, typename R, typename W, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, property_wrapper<R, W>, is_index, is_variable, checked, boost, C> { - typedef std::conditional_t<is_index, R, W> P; - typedef meta::unqualified_t<P> U; - typedef lua_bind_traits<U> traits_type; - - template <typename F> - static int self_call(lua_State* L, F&& f) { - typedef wrapper<U> wrap; - typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type; - typedef meta::pop_front_type_t<typename traits_type::free_args_list> args_list; - typedef T Ta; -#ifdef SOL_SAFE_USERTYPE - auto maybeo = stack::check_get<Ta*>(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); - } - return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); - } - object_type* o = static_cast<object_type*>(maybeo.value()); -#else - object_type* o = static_cast<object_type*>(stack::get<non_null<Ta*>>(L, 1)); -#endif // Safety - typedef typename wrap::returns_list returns_list; - typedef typename wrap::caller caller; - return stack::call_into_lua<checked>(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, *o); - } - - template <typename F, typename... Args> - static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { - return self_call(L, pick(meta::boolean<is_index>(), f), std::forward<Args>(args)...); - } - - template <typename F, typename... Args> - static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { - auto& p = pick(meta::boolean<is_index>(), std::forward<F>(f)); - return lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost>{}.call(L, p, std::forward<Args>(args)...); - } - - template <typename F, typename... Args> - static int call(lua_State* L, F&& f, Args&&... args) { - typedef meta::any< - std::is_void<U>, - std::is_same<U, no_prop>, - meta::is_specialization_of<var_wrapper, U>, - meta::is_specialization_of<constructor_wrapper, U>, - meta::is_specialization_of<constructor_list, U>, - std::is_member_pointer<U> - > is_specialized; - return defer_call(is_specialized(), L, std::forward<F>(f), std::forward<Args>(args)...); - } - }; - - template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, C> { - typedef protect_t<V> F; - - template <typename... Args> - static int call(lua_State* L, F& fx, Args&&... args) { - return lua_call_wrapper<T, V, is_index, is_variable, true, boost>{}.call(L, fx.value, std::forward<Args>(args)...); - } - }; - - template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, typename C> - struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, C> { - template <typename F> - static int call(lua_State* L, F&& f) { - return lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::get<0>(f.arguments)); - } - }; - - template <typename T, bool is_index, bool is_variable, int boost = 0, typename Fx, typename... Args> - inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { - return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename T, bool is_index, bool is_variable, typename F> - inline int call_user(lua_State* L) { - auto& fx = stack::get<user<F>>(L, upvalue_index(1)); - return call_wrapped<T, is_index, is_variable>(L, fx); - } - - template <typename T, typename = void> - struct is_var_bind : std::false_type {}; - - template <typename T> - struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type {}; - - template <> - struct is_var_bind<no_prop> : std::true_type {}; - - template <typename R, typename W> - struct is_var_bind<property_wrapper<R, W>> : std::true_type {}; - - template <typename T> - struct is_var_bind<var_wrapper<T>> : std::true_type {}; - } // call_detail - - template <typename T> - struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> {}; - - template <typename T> - struct is_function_binding : meta::neg<is_variable_binding<T>> {}; - -} // sol - -#endif // SOL_CALL_HPP diff --git a/3rdparty/sol2/sol/compatibility.hpp b/3rdparty/sol2/sol/compatibility.hpp deleted file mode 100644 index 81e7742df0c..00000000000 --- a/3rdparty/sol2/sol/compatibility.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_COMPATIBILITY_HPP -#define SOL_COMPATIBILITY_HPP - -// The various pieces of the compatibility layer -// comes from https://github.com/keplerproject/lua-compat-5.2 -// but has been modified in many places for use with Sol and luajit, -// though the core abstractions remain the same - -#include "compatibility/version.hpp" - -#ifndef SOL_NO_COMPAT - -#ifdef __cplusplus -extern "C" { -#endif -#include "compatibility/5.1.0.h" -#include "compatibility/5.0.0.h" -#include "compatibility/5.x.x.h" -#include "compatibility/5.x.x.inl" -#ifdef __cplusplus -} -#endif - -#endif // SOL_NO_COMPAT - -#endif // SOL_COMPATIBILITY_HPP diff --git a/3rdparty/sol2/sol/compatibility/5.0.0.h b/3rdparty/sol2/sol/compatibility/5.0.0.h deleted file mode 100644 index 549badba962..00000000000 --- a/3rdparty/sol2/sol/compatibility/5.0.0.h +++ /dev/null @@ -1,44 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_5_0_0_H -#define SOL_5_0_0_H - -#include "version.hpp" - -#if SOL_LUA_VERSION < 501 -/* Lua 5.0 */ - -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - -#define luaL_Reg luaL_reg - -#define luaL_opt(L, f, n, d) \ - (lua_isnoneornil(L, n) ? (d) : f(L, n)) - -#define luaL_addchar(B,c) \ - ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) - -#endif // Lua 5.0 - -#endif // SOL_5_0_0_H diff --git a/3rdparty/sol2/sol/compatibility/5.1.0.h b/3rdparty/sol2/sol/compatibility/5.1.0.h deleted file mode 100644 index 45225a0a805..00000000000 --- a/3rdparty/sol2/sol/compatibility/5.1.0.h +++ /dev/null @@ -1,175 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_5_1_0_H -#define SOL_5_1_0_H - -#include "version.hpp" - -#if SOL_LUA_VERSION == 501 -/* Lua 5.1 */ - -#include <lua.hpp> -#include <stddef.h> -#include <string.h> -#include <stdio.h> - -/* LuaJIT doesn't define these unofficial macros ... */ -#if !defined(LUAI_INT32) -#include <limits.h> -#if INT_MAX-20 < 32760 -#define LUAI_INT32 long -#define LUAI_UINT32 unsigned long -#elif INT_MAX > 2147483640L -#define LUAI_INT32 int -#define LUAI_UINT32 unsigned int -#else -#error "could not detect suitable lua_Unsigned datatype" -#endif -#endif - -/* LuaJIT does not have the updated error codes for thread status/function returns */ -#ifndef LUA_ERRGCMM -#define LUA_ERRGCMM (LUA_ERRERR + 1) -#endif // LUA_ERRGCMM - -/* LuaJIT does not support continuation contexts / return error codes? */ -#ifndef LUA_KCONTEXT -#define LUA_KCONTEXT std::ptrdiff_t -typedef LUA_KCONTEXT lua_KContext; -typedef int(*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); -#endif // LUA_KCONTEXT - -#define LUA_OPADD 0 -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 - -typedef LUAI_UINT32 lua_Unsigned; - -typedef struct luaL_Buffer_52 { - luaL_Buffer b; /* make incorrect code crash! */ - char *ptr; - size_t nelems; - size_t capacity; - lua_State *L2; -} luaL_Buffer_52; -#define luaL_Buffer luaL_Buffer_52 - -#define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) - -#define lua_rawlen(L, i) lua_objlen(L, i) - -inline void lua_callk(lua_State *L, int nargs, int nresults, lua_KContext, lua_KFunction) { - // should probably warn the user of Lua 5.1 that continuation isn't supported... - lua_call(L, nargs, nresults); -} -inline int lua_pcallk(lua_State *L, int nargs, int nresults, int errfunc, lua_KContext, lua_KFunction) { - // should probably warn the user of Lua 5.1 that continuation isn't supported... - return lua_pcall(L, nargs, nresults, errfunc); -} -void lua_arith(lua_State *L, int op); -int lua_compare(lua_State *L, int idx1, int idx2, int op); -void lua_pushunsigned(lua_State *L, lua_Unsigned n); -lua_Unsigned luaL_checkunsigned(lua_State *L, int i); -lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum); -lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def); -lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); -void lua_len(lua_State *L, int i); -int luaL_len(lua_State *L, int i); -const char *luaL_tolstring(lua_State *L, int idx, size_t *len); -void luaL_requiref(lua_State *L, char const* modname, lua_CFunction openf, int glb); - -#define luaL_buffinit luaL_buffinit_52 -void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B); - -#define luaL_prepbuffsize luaL_prepbuffsize_52 -char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s); - -#define luaL_addlstring luaL_addlstring_52 -void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l); - -#define luaL_addvalue luaL_addvalue_52 -void luaL_addvalue(luaL_Buffer_52 *B); - -#define luaL_pushresult luaL_pushresult_52 -void luaL_pushresult(luaL_Buffer_52 *B); - -#undef luaL_buffinitsize -#define luaL_buffinitsize(L, B, s) \ - (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) - -#undef luaL_prepbuffer -#define luaL_prepbuffer(B) \ - luaL_prepbuffsize(B, LUAL_BUFFERSIZE) - -#undef luaL_addchar -#define luaL_addchar(B, c) \ - ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ - ((B)->ptr[(B)->nelems++] = (c))) - -#undef luaL_addsize -#define luaL_addsize(B, s) \ - ((B)->nelems += (s)) - -#undef luaL_addstring -#define luaL_addstring(B, s) \ - luaL_addlstring(B, s, strlen(s)) - -#undef luaL_pushresultsize -#define luaL_pushresultsize(B, s) \ - (luaL_addsize(B, s), luaL_pushresult(B)) - -typedef struct kepler_lua_compat_get_string_view { - const char *s; - size_t size; -} kepler_lua_compat_get_string_view; - -inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t* size) { - kepler_lua_compat_get_string_view* ls = (kepler_lua_compat_get_string_view*) ud; - (void)L; - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - -#if !defined(SOL_LUAJIT) || (SOL_LUAJIT_VERSION < 20100) -// Luajit 2.1.0 has this function already - -inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { - kepler_lua_compat_get_string_view ls; - ls.s = buff; - ls.size = size; - return lua_load(L, kepler_lua_compat_get_string, &ls, name/*, mode*/); -} - -#endif // LuaJIT 2.1.x beta and beyond - -#endif /* Lua 5.1 */ - -#endif // SOL_5_1_0_H diff --git a/3rdparty/sol2/sol/compatibility/5.2.0.h b/3rdparty/sol2/sol/compatibility/5.2.0.h deleted file mode 100644 index 7068f2a3291..00000000000 --- a/3rdparty/sol2/sol/compatibility/5.2.0.h +++ /dev/null @@ -1,43 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_5_2_0_H -#define SOL_5_2_0_H -#include "version.hpp" - -#if SOL_LUA_VERSION < 503 - -inline int lua_isinteger(lua_State* L, int idx) { - if (lua_type(L, idx) != LUA_TNUMBER) - return 0; - // This is a very slipshod way to do the testing - // but lua_totingerx doesn't play ball nicely - // on older versions... - lua_Number n = lua_tonumber(L, idx); - lua_Integer i = lua_tointeger(L, idx); - if (i != n) - return 0; - // it's DEFINITELY an integer - return 1; -} - -#endif // SOL_LUA_VERSION == 502 -#endif // SOL_5_2_0_H diff --git a/3rdparty/sol2/sol/compatibility/5.x.x.h b/3rdparty/sol2/sol/compatibility/5.x.x.h deleted file mode 100644 index 95f48792a00..00000000000 --- a/3rdparty/sol2/sol/compatibility/5.x.x.h +++ /dev/null @@ -1,57 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_5_X_X_H -#define SOL_5_X_X_H - -#include "version.hpp" - -#if SOL_LUA_VERSION < 502 - -#define LUA_RIDX_GLOBALS LUA_GLOBALSINDEX - -#define LUA_OK 0 - -#define lua_pushglobaltable(L) \ - lua_pushvalue(L, LUA_GLOBALSINDEX) - -#define luaL_newlib(L, l) \ - (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) - -void luaL_checkversion(lua_State *L); - -int lua_absindex(lua_State *L, int i); -void lua_copy(lua_State *L, int from, int to); -void lua_rawgetp(lua_State *L, int i, const void *p); -void lua_rawsetp(lua_State *L, int i, const void *p); -void *luaL_testudata(lua_State *L, int i, const char *tname); -lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); -void lua_getuservalue(lua_State *L, int i); -void lua_setuservalue(lua_State *L, int i); -void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); -void luaL_setmetatable(lua_State *L, const char *tname); -int luaL_getsubtable(lua_State *L, int i, const char *name); -void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); -int luaL_fileresult(lua_State *L, int stat, const char *fname); - -#endif // Lua 5.1 and below - -#endif // SOL_5_X_X_H diff --git a/3rdparty/sol2/sol/compatibility/5.x.x.inl b/3rdparty/sol2/sol/compatibility/5.x.x.inl deleted file mode 100644 index b32cb7f26f7..00000000000 --- a/3rdparty/sol2/sol/compatibility/5.x.x.inl +++ /dev/null @@ -1,708 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_5_X_X_INL -#define SOL_5_X_X_INL - -#include "version.hpp" -#include "5.2.0.h" -#include "5.1.0.h" -#include "5.0.0.h" -#include "5.x.x.h" - -#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 - -#include <errno.h> -#include <string.h> - -#define PACKAGE_KEY "_sol.package" - -inline int lua_absindex(lua_State *L, int i) { - if (i < 0 && i > LUA_REGISTRYINDEX) - i += lua_gettop(L) + 1; - return i; -} - -inline void lua_copy(lua_State *L, int from, int to) { - int abs_to = lua_absindex(L, to); - luaL_checkstack(L, 1, "not enough stack slots"); - lua_pushvalue(L, from); - lua_replace(L, abs_to); -} - -inline void lua_rawgetp(lua_State *L, int i, const void *p) { - int abs_i = lua_absindex(L, i); - lua_pushlightuserdata(L, (void*)p); - lua_rawget(L, abs_i); -} - -inline void lua_rawsetp(lua_State *L, int i, const void *p) { - int abs_i = lua_absindex(L, i); - luaL_checkstack(L, 1, "not enough stack slots"); - lua_pushlightuserdata(L, (void*)p); - lua_insert(L, -2); - lua_rawset(L, abs_i); -} - -inline void *luaL_testudata(lua_State *L, int i, const char *tname) { - void *p = lua_touserdata(L, i); - luaL_checkstack(L, 2, "not enough stack slots"); - if (p == NULL || !lua_getmetatable(L, i)) - return NULL; - else { - int res = 0; - luaL_getmetatable(L, tname); - res = lua_rawequal(L, -1, -2); - lua_pop(L, 2); - if (!res) - p = NULL; - } - return p; -} - -inline lua_Number lua_tonumberx(lua_State *L, int i, int *isnum) { - lua_Number n = lua_tonumber(L, i); - if (isnum != NULL) { - *isnum = (n != 0 || lua_isnumber(L, i)); - } - return n; -} - -inline static void push_package_table(lua_State *L) { - lua_pushliteral(L, PACKAGE_KEY); - lua_rawget(L, LUA_REGISTRYINDEX); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - /* try to get package table from globals */ - lua_pushliteral(L, "package"); - lua_rawget(L, LUA_GLOBALSINDEX); - if (lua_istable(L, -1)) { - lua_pushliteral(L, PACKAGE_KEY); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - } - } -} - -inline void lua_getuservalue(lua_State *L, int i) { - luaL_checktype(L, i, LUA_TUSERDATA); - luaL_checkstack(L, 2, "not enough stack slots"); - lua_getfenv(L, i); - lua_pushvalue(L, LUA_GLOBALSINDEX); - if (lua_rawequal(L, -1, -2)) { - lua_pop(L, 1); - lua_pushnil(L); - lua_replace(L, -2); - } - else { - lua_pop(L, 1); - push_package_table(L); - if (lua_rawequal(L, -1, -2)) { - lua_pop(L, 1); - lua_pushnil(L); - lua_replace(L, -2); - } - else - lua_pop(L, 1); - } -} - -inline void lua_setuservalue(lua_State *L, int i) { - luaL_checktype(L, i, LUA_TUSERDATA); - if (lua_isnil(L, -1)) { - luaL_checkstack(L, 1, "not enough stack slots"); - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_replace(L, -2); - } - lua_setfenv(L, i); -} - -/* -** Adapted from Lua 5.2.0 -*/ -inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup + 1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup + 1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ - } - lua_pop(L, nup); /* remove upvalues */ -} - -inline void luaL_setmetatable(lua_State *L, const char *tname) { - luaL_checkstack(L, 1, "not enough stack slots"); - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - -inline int luaL_getsubtable(lua_State *L, int i, const char *name) { - int abs_i = lua_absindex(L, i); - luaL_checkstack(L, 3, "not enough stack slots"); - lua_pushstring(L, name); - lua_gettable(L, abs_i); - if (lua_istable(L, -1)) - return 1; - lua_pop(L, 1); - lua_newtable(L); - lua_pushstring(L, name); - lua_pushvalue(L, -2); - lua_settable(L, abs_i); - return 0; -} - -#ifndef SOL_LUAJIT -inline static int countlevels(lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le) / 2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; -} - -inline static int findfield(lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - lua_remove(L, -2); /* remove table (but keep name) */ - lua_pushliteral(L, "."); - lua_insert(L, -2); /* place '.' between the two names */ - lua_concat(L, 3); - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ -} - -inline static int pushglobalfuncname(lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - if (findfield(L, top + 1, 2)) { - lua_copy(L, -1, top + 1); /* move name to proper place */ - lua_pop(L, 2); /* remove pushed values */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } -} - -inline static void pushfuncname(lua_State *L, lua_Debug *ar) { - if (*ar->namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, "function " LUA_QS, ar->name); - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what == 'C') { - if (pushglobalfuncname(L, ar)) { - lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else - lua_pushliteral(L, "?"); - } - else - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); -} - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -inline void luaL_traceback(lua_State *L, lua_State *L1, - const char *msg, int level) { - lua_Debug ar; - int top = lua_gettop(L); - int numlevels = countlevels(L1); - int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; - if (msg) lua_pushfstring(L, "%s\n", msg); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level == mark) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = numlevels - LEVELS2; /* and skip to last ones */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - lua_pushliteral(L, " in "); - pushfuncname(L, &ar); - lua_concat(L, lua_gettop(L) - top); - } - } - lua_concat(L, lua_gettop(L) - top); -} -#endif - -inline const lua_Number *lua_version(lua_State *L) { - static const lua_Number version = LUA_VERSION_NUM; - if (L == NULL) return &version; - // TODO: wonky hacks to get at the inside of the incomplete type lua_State? - //else return L->l_G->version; - else return &version; -} - -inline static void luaL_checkversion_(lua_State *L, lua_Number ver) { - const lua_Number* v = lua_version(L); - if (v != lua_version(NULL)) - luaL_error(L, "multiple Lua VMs detected"); - else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - ver, *v); - /* check conversions number -> integer types */ - lua_pushnumber(L, -(lua_Number)0x1234); - if (lua_tointeger(L, -1) != -0x1234 || - lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) - luaL_error(L, "bad conversion number->int;" - " must recompile Lua with proper settings"); - lua_pop(L, 1); -} - -inline void luaL_checkversion(lua_State* L) { - luaL_checkversion_(L, LUA_VERSION_NUM); -} - -#ifndef SOL_LUAJIT -inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - char buf[1024]; -#if defined(__GLIBC__) || defined(_POSIX_VERSION) - strerror_r(en, buf, 1024); -#else - strerror_s(buf, 1024, en); -#endif - lua_pushnil(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, buf); - else - lua_pushstring(L, buf); - lua_pushnumber(L, (lua_Number)en); - return 3; - } -} -#endif // luajit -#endif // Lua 5.0 or Lua 5.1 - - -#if SOL_LUA_VERSION == 501 -#include <limits.h> - -typedef LUAI_INT32 LUA_INT32; - -/********************************************************************/ -/* extract of 5.2's luaconf.h */ -/* detects proper defines for faster unsigned<->number conversion */ -/* see copyright notice at the end of this file */ -/********************************************************************/ - -#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_WIN /* enable goodies for regular Windows platforms */ -#endif - - -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ - -/* Microsoft compiler on a Pentium (32 bit) ? */ -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ - -#define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - -/* pentium 32 bits? */ -#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEELL -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - -/* pentium 64 bits? */ -#elif defined(__x86_64) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 - -#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 - -#else /* }{ */ - -/* assume IEEE754 and a 32-bit integer type */ -#define LUA_IEEE754TRICK - -#endif /* } */ - -#endif /* } */ - - -/********************************************************************/ -/* extract of 5.2's llimits.h */ -/* gives us lua_number2unsigned and lua_unsigned2number */ -/* see copyright notice just below this one here */ -/********************************************************************/ - -/********************************************************************* -* This file contains parts of Lua 5.2's source code: -* -* Copyright (C) 1994-2013 Lua.org, PUC-Rio. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*********************************************************************/ - -#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ -/* trick with Microsoft assembler for X86 */ - -#define lua_number2unsigned(i,n) \ - {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} - - -#elif defined(LUA_IEEE754TRICK) /* }{ */ -/* the next trick should work on any machine using IEEE754 with -a 32-bit int type */ - -union compat52_luai_Cast { double l_d; LUA_INT32 l_p[2]; }; - -#if !defined(LUA_IEEEENDIAN) /* { */ -#define LUAI_EXTRAIEEE \ - static const union compat52_luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; -#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) -#else -#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN -#define LUAI_EXTRAIEEE /* empty */ -#endif /* } */ - -#define lua_number2int32(i,n,t) \ - { LUAI_EXTRAIEEE \ - volatile union compat52_luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ - (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } - -#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) - -#endif /* } */ - - -/* the following definitions always work, but may be slow */ - -#if !defined(lua_number2unsigned) /* { */ -/* the following definition assures proper modulo behavior */ -#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) -#include <math.h> -#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) -#define lua_number2unsigned(i,n) \ - ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) -#else -#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) -#endif -#endif /* } */ - - -#if !defined(lua_unsigned2number) -/* on several machines, coercion from unsigned to double is slow, -so it may be worth to avoid */ -#define lua_unsigned2number(u) \ - (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) -#endif - -/********************************************************************/ - -inline static void compat52_call_lua(lua_State *L, char const code[], size_t len, - int nargs, int nret) { - lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); - if (lua_type(L, -1) != LUA_TFUNCTION) { - lua_pop(L, 1); - if (luaL_loadbuffer(L, code, len, "=none")) - lua_error(L); - lua_pushvalue(L, -1); - lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); - } - lua_insert(L, -nargs - 1); - lua_call(L, nargs, nret); -} - -static const char compat52_arith_code[] = { - "local op,a,b=...\n" - "if op==0 then return a+b\n" - "elseif op==1 then return a-b\n" - "elseif op==2 then return a*b\n" - "elseif op==3 then return a/b\n" - "elseif op==4 then return a%b\n" - "elseif op==5 then return a^b\n" - "elseif op==6 then return -a\n" - "end\n" -}; - -inline void lua_arith(lua_State *L, int op) { - if (op < LUA_OPADD || op > LUA_OPUNM) - luaL_error(L, "invalid 'op' argument for lua_arith"); - luaL_checkstack(L, 5, "not enough stack slots"); - if (op == LUA_OPUNM) - lua_pushvalue(L, -1); - lua_pushnumber(L, op); - lua_insert(L, -3); - compat52_call_lua(L, compat52_arith_code, - sizeof(compat52_arith_code) - 1, 3, 1); -} - -static const char compat52_compare_code[] = { - "local a,b=...\n" - "return a<=b\n" -}; - -inline int lua_compare(lua_State *L, int idx1, int idx2, int op) { - int result = 0; - switch (op) { - case LUA_OPEQ: - return lua_equal(L, idx1, idx2); - case LUA_OPLT: - return lua_lessthan(L, idx1, idx2); - case LUA_OPLE: - luaL_checkstack(L, 5, "not enough stack slots"); - idx1 = lua_absindex(L, idx1); - idx2 = lua_absindex(L, idx2); - lua_pushvalue(L, idx1); - lua_pushvalue(L, idx2); - compat52_call_lua(L, compat52_compare_code, - sizeof(compat52_compare_code) - 1, 2, 1); - result = lua_toboolean(L, -1); - lua_pop(L, 1); - return result; - default: - luaL_error(L, "invalid 'op' argument for lua_compare"); - } - return 0; -} - -inline void lua_pushunsigned(lua_State *L, lua_Unsigned n) { - lua_pushnumber(L, lua_unsigned2number(n)); -} - -inline lua_Unsigned luaL_checkunsigned(lua_State *L, int i) { - lua_Unsigned result; - lua_Number n = lua_tonumber(L, i); - if (n == 0 && !lua_isnumber(L, i)) - luaL_checktype(L, i, LUA_TNUMBER); - lua_number2unsigned(result, n); - return result; -} - -inline lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum) { - lua_Unsigned result; - lua_Number n = lua_tonumberx(L, i, isnum); - lua_number2unsigned(result, n); - return result; -} - -inline lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def) { - return luaL_opt(L, luaL_checkunsigned, i, def); -} - -inline lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum) { - lua_Integer n = lua_tointeger(L, i); - if (isnum != NULL) { - *isnum = (n != 0 || lua_isnumber(L, i)); - } - return n; -} - -inline void lua_len(lua_State *L, int i) { - switch (lua_type(L, i)) { - case LUA_TSTRING: /* fall through */ - case LUA_TTABLE: - if (!luaL_callmeta(L, i, "__len")) - lua_pushnumber(L, (int)lua_objlen(L, i)); - break; - case LUA_TUSERDATA: - if (luaL_callmeta(L, i, "__len")) - break; - /* maybe fall through */ - default: - luaL_error(L, "attempt to get length of a %s value", - lua_typename(L, lua_type(L, i))); - } -} - -inline int luaL_len(lua_State *L, int i) { - int res = 0, isnum = 0; - luaL_checkstack(L, 1, "not enough stack slots"); - lua_len(L, i); - res = (int)lua_tointegerx(L, -1, &isnum); - lua_pop(L, 1); - if (!isnum) - luaL_error(L, "object length is not a number"); - return res; -} - -inline const char *luaL_tolstring(lua_State *L, int idx, size_t *len) { - if (!luaL_callmeta(L, idx, "__tostring")) { - int t = lua_type(L, idx); - switch (t) { - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - case LUA_TSTRING: - case LUA_TNUMBER: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - if (lua_toboolean(L, idx)) - lua_pushliteral(L, "true"); - else - lua_pushliteral(L, "false"); - break; - default: - lua_pushfstring(L, "%s: %p", lua_typename(L, t), - lua_topointer(L, idx)); - break; - } - } - return lua_tolstring(L, -1, len); -} - -inline void luaL_requiref(lua_State *L, char const* modname, - lua_CFunction openf, int glb) { - luaL_checkstack(L, 3, "not enough stack slots"); - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); - lua_call(L, 1, 1); - lua_getglobal(L, "package"); - if (lua_istable(L, -1) == 0) { - lua_pop(L, 1); - lua_createtable(L, 0, 16); - lua_setglobal(L, "package"); - lua_getglobal(L, "package"); - } - lua_getfield(L, -1, "loaded"); - if (lua_istable(L, -1) == 0) { - lua_pop(L, 1); - lua_createtable(L, 0, 1); - lua_setfield(L, -2, "loaded"); - lua_getfield(L, -1, "loaded"); - } - lua_replace(L, -2); - lua_pushvalue(L, -2); - lua_setfield(L, -2, modname); - lua_pop(L, 1); - if (glb) { - lua_pushvalue(L, -1); - lua_setglobal(L, modname); - } -} - -inline void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B) { - /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ - B->b.p = NULL; - B->b.L = NULL; - B->b.lvl = 0; - /* reuse the buffer from the 5.1-style luaL_Buffer though! */ - B->ptr = B->b.buffer; - B->capacity = LUAL_BUFFERSIZE; - B->nelems = 0; - B->L2 = L; -} - -inline char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s) { - if (B->capacity - B->nelems < s) { /* needs to grow */ - char* newptr = NULL; - size_t newcap = B->capacity * 2; - if (newcap - B->nelems < s) - newcap = B->nelems + s; - if (newcap < B->capacity) /* overflow */ - luaL_error(B->L2, "buffer too large"); - newptr = (char*)lua_newuserdata(B->L2, newcap); - memcpy(newptr, B->ptr, B->nelems); - if (B->ptr != B->b.buffer) - lua_replace(B->L2, -2); /* remove old buffer */ - B->ptr = newptr; - B->capacity = newcap; - } - return B->ptr + B->nelems; -} - -inline void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l) { - memcpy(luaL_prepbuffsize(B, l), s, l); - luaL_addsize(B, l); -} - -inline void luaL_addvalue(luaL_Buffer_52 *B) { - size_t len = 0; - const char *s = lua_tolstring(B->L2, -1, &len); - if (!s) - luaL_error(B->L2, "cannot convert value to string"); - if (B->ptr != B->b.buffer) - lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ - luaL_addlstring(B, s, len); - lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); -} - -inline void luaL_pushresult(luaL_Buffer_52 *B) { - lua_pushlstring(B->L2, B->ptr, B->nelems); - if (B->ptr != B->b.buffer) - lua_replace(B->L2, -2); /* remove userdata buffer */ -} - -#endif /* SOL_LUA_VERSION == 501 */ - -#endif // SOL_5_X_X_INL diff --git a/3rdparty/sol2/sol/compatibility/version.hpp b/3rdparty/sol2/sol/compatibility/version.hpp deleted file mode 100644 index 5397cbdb1b3..00000000000 --- a/3rdparty/sol2/sol/compatibility/version.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_VERSION_HPP -#define SOL_VERSION_HPP - -#ifdef SOL_USING_CXX_LUA -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> -#else -#include <lua.hpp> -#endif // C++-compiler Lua - -#if defined(_WIN32) || defined(_MSC_VER) -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // sol codecvt support -#elif defined(__GNUC__) -#if __GNUC__ >= 5 -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // codecvt support -#endif // g++ 5.x.x (MinGW too) -#else -// Clang sucks and doesn't really utilize codecvt support, -// not without checking the library versions explicitly (and we're not gonna do that, so fuck you) -#endif // Windows/VC++ vs. g++ vs Others - -#ifdef LUAJIT_VERSION -#ifndef SOL_LUAJIT -#define SOL_LUAJIT -#define SOL_LUAJIT_VERSION LUAJIT_VERSION_NUM -#endif // sol luajit -#endif // luajit - -#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 -#define SOL_LUA_VERSION LUA_VERSION_NUM -#elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 -#define SOL_LUA_VERSION LUA_VERSION_NUM -#elif !defined(LUA_VERSION_NUM) -// Definitely 5.0 -#define SOL_LUA_VERSION 500 -#else -// ??? Not sure, assume 502? -#define SOL_LUA_VERSION 502 -#endif // Lua Version 502, 501 || luajit, 500 - -#ifdef _MSC_VER -#ifdef _DEBUG -#ifndef NDEBUG -#ifndef SOL_CHECK_ARGUMENTS -// Do not define by default: let user turn it on -//#define SOL_CHECK_ARGUMENTS -#endif // Check Arguments -#ifndef SOL_SAFE_USERTYPE -#define SOL_SAFE_USERTYPE -#endif // Safe Usertypes -#endif // NDEBUG -#endif // Debug - -#ifndef _CPPUNWIND -#ifndef SOL_NO_EXCEPTIONS -#define SOL_NO_EXCEPTIONS 1 -#endif -#endif // Automatic Exceptions - -#ifndef _CPPRTTI -#ifndef SOL_NO_RTTI -#define SOL_NO_RTTI 1 -#endif -#endif // Automatic RTTI - -#elif defined(__GNUC__) || defined(__clang__) - -#ifndef NDEBUG -#ifndef __OPTIMIZE__ -#ifndef SOL_CHECK_ARGUMENTS -// Do not define by default: let user choose -//#define SOL_CHECK_ARGUMENTS -// But do check userdata by default: -#endif // Check Arguments -#ifndef SOL_SAFE_USERTYPE -#define SOL_SAFE_USERTYPE -#endif // Safe Usertypes -#endif // g++ optimizer flag -#endif // Not Debug - -#ifndef __EXCEPTIONS -#ifndef SOL_NO_EXCEPTIONS -#define SOL_NO_EXCEPTIONS 1 -#endif -#endif // No Exceptions - -#ifndef __GXX_RTTI -#ifndef SOL_NO_RTII -#define SOL_NO_RTTI 1 -#endif -#endif // No RTTI - -#endif // vc++ || clang++/g++ - -#ifndef SOL_SAFE_USERTYPE -#ifdef SOL_CHECK_ARGUMENTS -#define SOL_SAFE_USERTYPE -#endif // Turn on Safety for all -#endif // Safe Usertypes - -#endif // SOL_VERSION_HPP diff --git a/3rdparty/sol2/sol/protect.hpp b/3rdparty/sol2/sol/config.hpp index 42655c6b74b..3b7ef023f51 100644 --- a/3rdparty/sol2/sol/protect.hpp +++ b/3rdparty/sol2/sol/config.hpp @@ -1,6 +1,6 @@ -// The MIT License (MIT) +// The MIT License (MIT) -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors // 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 @@ -19,33 +19,35 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -#ifndef SOL_PROTECT_HPP -#define SOL_PROTECT_HPP +// This file was generated with a script. +// Generated 2022-06-25 08:14:19.336233 UTC +// This header was generated with sol v3.3.0 (revision eba86625) +// https://github.com/ThePhD/sol2 -#include "traits.hpp" -#include <utility> +#ifndef SOL_SINGLE_CONFIG_HPP +#define SOL_SINGLE_CONFIG_HPP -namespace sol { - - template <typename T> - struct protect_t { - T value; +// beginning of sol/config.hpp - template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler> - protect_t(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {} +/* Base, empty configuration file! - protect_t(const protect_t&) = default; - protect_t(protect_t&&) = default; - protect_t& operator=(const protect_t&) = default; - protect_t& operator=(protect_t&&) = default; + To override, place a file in your include paths of the form: - }; +. (your include path here) +| sol (directory, or equivalent) + | config.hpp (your config.hpp file) - template <typename T> - auto protect(T&& value) { - return protect_t<std::decay_t<T>>(std::forward<T>(value)); - } + So that when sol2 includes the file -} // sol +#include <sol/config.hpp> -#endif // SOL_PROTECT_HPP + it gives you the configuration values you desire. Configuration values can be +seen in the safety.rst of the doc/src, or at +https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through +the build system, or the command line options of your compiler. + +*/ + +// end of sol/config.hpp + +#endif // SOL_SINGLE_CONFIG_HPP diff --git a/3rdparty/sol2/sol/container_usertype_metatable.hpp b/3rdparty/sol2/sol/container_usertype_metatable.hpp deleted file mode 100644 index fc5d6894f95..00000000000 --- a/3rdparty/sol2/sol/container_usertype_metatable.hpp +++ /dev/null @@ -1,513 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_CONTAINER_USERTYPE_HPP -#define SOL_CONTAINER_USERTYPE_HPP - -#include "stack.hpp" - -namespace sol { - - namespace detail { - - template <typename T> - struct has_find { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(&C::find)); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - struct has_push_back { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(std::declval<C>().push_back(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - struct has_clear { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(&C::clear)); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - struct has_insert { - private: - typedef std::array<char, 1> one; - typedef std::array<char, 2> two; - - template <typename C> static one test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); - template <typename C> static two test(...); - - public: - static const bool value = sizeof(test<T>(0)) == sizeof(char); - }; - - template <typename T> - T& get_first(const T& t) { - return std::forward<T>(t); - } - - template <typename A, typename B> - decltype(auto) get_first(const std::pair<A, B>& t) { - return t.first; - } - - template <typename C, typename I, meta::enable<has_find<meta::unqualified_t<C>>> = meta::enabler> - auto find(C& c, I&& i) { - return c.find(std::forward<I>(i)); - } - - template <typename C, typename I, meta::disable<has_find<meta::unqualified_t<C>>> = meta::enabler> - auto find(C& c, I&& i) { - using std::begin; - using std::end; - return std::find_if(begin(c), end(c), [&i](auto&& x) { - return i == get_first(x); - }); - } - - } - - template <typename Raw, typename C = void> - struct container_usertype_metatable { - typedef meta::has_key_value_pair<meta::unqualified_t<Raw>> is_associative; - typedef meta::unqualified_t<Raw> T; - typedef typename T::iterator I; - typedef std::conditional_t<is_associative::value, typename T::value_type, std::pair<std::size_t, typename T::value_type>> KV; - typedef typename KV::first_type K; - typedef typename KV::second_type V; - typedef std::remove_reference_t<decltype(*std::declval<I&>())> IR; - - struct iter { - T& source; - I it; - - iter(T& source, I it) : source(source), it(std::move(it)) {} - }; - - static auto& get_src(lua_State* L) { -#ifdef SOL_SAFE_USERTYPE - auto p = stack::check_get<T*>(L, 1); - if (!p || p.value() == nullptr) { - luaL_error(L, "sol: 'self' argument is not the proper type (pass 'self' as first argument with ':' or call on proper type)"); - } - return *p.value(); -#else - return stack::get<T>(L, 1); -#endif - } - - static int real_index_call_associative(std::true_type, lua_State* L) { - auto k = stack::check_get<K>(L, 2); - if (k) { - auto& src = get_src(L); - using std::end; - auto it = detail::find(src, *k); - if (it != end(src)) { - auto& v = *it; - return stack::push_reference(L, v.second); - } - } - else { - auto maybename = stack::check_get<string_detail::string_shim>(L, 2); - if (maybename) { - auto& name = *maybename; - if (name == "add") { - return stack::push(L, &add_call); - } - else if (name == "insert") { - return stack::push(L, &insert_call); - } - else if (name == "clear") { - return stack::push(L, &clear_call); - } - } - } - return stack::push(L, lua_nil); - } - - static int real_index_call_associative(std::false_type, lua_State* L) { - auto& src = get_src(L); - auto maybek = stack::check_get<K>(L, 2); - if (maybek) { - using std::begin; - auto it = begin(src); - K k = *maybek; -#ifdef SOL_SAFE_USERTYPE - if (k > src.size() || k < 1) { - return stack::push(L, lua_nil); - } -#else -#endif // Safety - --k; - std::advance(it, k); - return stack::push_reference(L, *it); - } - else { - auto maybename = stack::check_get<string_detail::string_shim>(L, 2); - if (maybename) { - auto& name = *maybename; - if (name == "add") { - return stack::push(L, &add_call); - } - else if (name == "insert") { - return stack::push(L, &insert_call); - } - else if (name == "clear") { - return stack::push(L, &clear_call); - } - } - } - - return stack::push(L, lua_nil); - } - - static int real_index_call(lua_State* L) { - return real_index_call_associative(is_associative(), L); - } - - static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) { - return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); - } - - static int real_new_index_call_const(std::false_type, std::true_type, lua_State* L) { - return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); - } - - static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { - auto& src = get_src(L); - auto k = stack::check_get<K>(L, 2); - if (k) { - using std::end; - auto it = detail::find(src, *k); - if (it != end(src)) { - auto& v = *it; - v.second = stack::get<V>(L, 3); - } - else { - src.insert(it, { std::move(*k), stack::get<V>(L, 3) }); - } - } - return 0; - } - - static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) { - auto& src = get_src(L); -#ifdef SOL_SAFE_USERTYPE - auto maybek = stack::check_get<K>(L, 2); - if (!maybek) { - return stack::push(L, lua_nil); - } - K k = *maybek; -#else - K k = stack::get<K>(L, 2); -#endif - using std::begin; - auto it = begin(src); - if (k == src.size()) { - real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src, 1); - return 0; - } - --k; - std::advance(it, k); - *it = stack::get<V>(L, 3); - return 0; - } - - static int real_new_index_call(lua_State* L) { - return real_new_index_call_const(meta::neg<meta::any<std::is_const<V>, std::is_const<IR>>>(), is_associative(), L); - } - - static int real_pairs_next_call_assoc(std::true_type, lua_State* L) { - using std::end; - iter& i = stack::get<user<iter>>(L, 1); - auto& source = i.source; - auto& it = i.it; - if (it == end(source)) { - return 0; - } - int p = stack::multi_push_reference(L, it->first, it->second); - std::advance(it, 1); - return p; - } - - static int real_pairs_call_assoc(std::true_type, lua_State* L) { - auto& src = get_src(L); - using std::begin; - stack::push(L, pairs_next_call); - stack::push<user<iter>>(L, src, begin(src)); - stack::push(L, 1); - return 3; - } - - static int real_pairs_next_call_assoc(std::false_type, lua_State* L) { - using std::end; - iter& i = stack::get<user<iter>>(L, 1); - auto& source = i.source; - auto& it = i.it; - K k = stack::get<K>(L, 2); - if (it == end(source)) { - return 0; - } - int p = stack::multi_push_reference(L, k + 1, *it); - std::advance(it, 1); - return p; - } - - static int real_pairs_call_assoc(std::false_type, lua_State* L) { - auto& src = get_src(L); - using std::begin; - stack::push(L, pairs_next_call); - stack::push<user<iter>>(L, src, begin(src)); - stack::push(L, 0); - return 3; - } - - static int real_pairs_next_call(lua_State* L) { - return real_pairs_next_call_assoc(is_associative(), L); - } - - static int real_pairs_call(lua_State* L) { - return real_pairs_call_assoc(is_associative(), L); - } - - static int real_length_call(lua_State*L) { - auto& src = get_src(L); - return stack::push(L, src.size()); - } - - static int real_add_call_insert(std::true_type, lua_State*L, T& src, int boost = 0) { - using std::end; - src.insert(end(src), stack::get<V>(L, 2 + boost)); - return 0; - } - - static int real_add_call_insert(std::false_type, lua_State*L, T&, int = 0) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call insert on type %s", s.c_str()); - } - - static int real_add_call_push(std::true_type, lua_State*L, T& src, int boost = 0) { - src.push_back(stack::get<V>(L, 2 + boost)); - return 0; - } - - static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) { - return real_add_call_insert(std::integral_constant<bool, detail::has_insert<T>::value>(), L, src, boost); - } - - static int real_add_call_associative(std::true_type, lua_State* L) { - return real_insert_call(L); - } - - static int real_add_call_associative(std::false_type, lua_State* L) { - auto& src = get_src(L); - return real_add_call_push(std::integral_constant<bool, detail::has_push_back<T>::value>(), L, src); - } - - static int real_add_call_capable(std::true_type, lua_State* L) { - return real_add_call_associative(is_associative(), L); - } - - static int real_add_call_capable(std::false_type, lua_State* L) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call add on type %s", s.c_str()); - } - - static int real_add_call(lua_State* L) { - return real_add_call_capable(std::integral_constant<bool, detail::has_push_back<T>::value || detail::has_insert<T>::value>(), L); - } - - static int real_insert_call_capable(std::false_type, std::false_type, lua_State*L) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call insert on type %s", s.c_str()); - } - - static int real_insert_call_capable(std::false_type, std::true_type, lua_State*L) { - return real_insert_call_capable(std::false_type(), std::false_type(), L); - } - - static int real_insert_call_capable(std::true_type, std::false_type, lua_State* L) { - using std::begin; - auto& src = get_src(L); - src.insert(std::next(begin(src), stack::get<K>(L, 2)), stack::get<V>(L, 3)); - return 0; - } - - static int real_insert_call_capable(std::true_type, std::true_type, lua_State* L) { - return real_new_index_call(L); - } - - static int real_insert_call(lua_State*L) { - return real_insert_call_capable(std::integral_constant<bool, detail::has_insert<T>::value>(), is_associative(), L); - } - - static int real_clear_call_capable(std::false_type, lua_State* L) { - static const std::string& s = detail::demangle<T>(); - return luaL_error(L, "sol: cannot call clear on type %s", s.c_str()); - } - - static int real_clear_call_capable(std::true_type, lua_State* L) { - auto& src = get_src(L); - src.clear(); - return 0; - } - - static int real_clear_call(lua_State*L) { - return real_clear_call_capable(std::integral_constant<bool, detail::has_clear<T>::value>(), L); - } - - static int add_call(lua_State*L) { - return detail::static_trampoline<(&real_add_call)>(L); - } - - static int insert_call(lua_State*L) { - return detail::static_trampoline<(&real_insert_call)>(L); - } - - static int clear_call(lua_State*L) { - return detail::static_trampoline<(&real_clear_call)>(L); - } - - static int length_call(lua_State*L) { - return detail::static_trampoline<(&real_length_call)>(L); - } - - static int pairs_next_call(lua_State*L) { - return detail::static_trampoline<(&real_pairs_next_call)>(L); - } - - static int pairs_call(lua_State*L) { - return detail::static_trampoline<(&real_pairs_call)>(L); - } - - static int index_call(lua_State*L) { - return detail::static_trampoline<(&real_index_call)>(L); - } - - static int new_index_call(lua_State*L) { - return detail::static_trampoline<(&real_new_index_call)>(L); - } - }; - - namespace stack { - namespace stack_detail { - template <typename T> - inline auto container_metatable() { - typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt; - std::array<luaL_Reg, 10> reg = { { - { "__index", &meta_cumt::index_call }, - { "__newindex", &meta_cumt::new_index_call }, - { "__pairs", &meta_cumt::pairs_call }, - { "__ipairs", &meta_cumt::pairs_call }, - { "__len", &meta_cumt::length_call }, - { "clear", &meta_cumt::clear_call }, - { "insert", &meta_cumt::insert_call }, - { "add", &meta_cumt::add_call }, - std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy<T> }, - { nullptr, nullptr } - } }; - return reg; - } - - template <typename T> - inline auto container_metatable_behind() { - typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt; - std::array<luaL_Reg, 3> reg = { { - { "__index", &meta_cumt::index_call }, - { "__newindex", &meta_cumt::new_index_call }, - { nullptr, nullptr } - } }; - return reg; - } - - template <typename T> - struct metatable_setup { - lua_State* L; - - metatable_setup(lua_State* L) : L(L) {} - - void operator()() { - static const auto reg = container_metatable<T>(); - static const auto containerreg = container_metatable_behind<T>(); - static const char* metakey = &usertype_traits<T>::metatable()[0]; - - if (luaL_newmetatable(L, metakey) == 1) { - stack_reference metatable(L, -1); - luaL_setfuncs(L, reg.data(), 0); - - lua_createtable(L, 0, static_cast<int>(containerreg.size())); - stack_reference metabehind(L, -1); - luaL_setfuncs(L, containerreg.data(), 0); - - stack::set_field(L, metatable_key, metabehind, metatable.stack_index()); - metabehind.pop(); - } - lua_setmetatable(L, -2); - } - }; - } - - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - static int push(lua_State* L, const T& cont) { - stack_detail::metatable_setup<T> fx(L); - return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, cont); - } - - static int push(lua_State* L, T&& cont) { - stack_detail::metatable_setup<T> fx(L); - return pusher<detail::as_value_tag<T>>{}.push_fx(L, fx, std::move(cont)); - } - }; - - template<typename T> - struct pusher<T*, std::enable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - static int push(lua_State* L, T* cont) { - stack_detail::metatable_setup<meta::unqualified_t<std::remove_pointer_t<T>>*> fx(L); - return pusher<detail::as_pointer_tag<T>>{}.push_fx(L, fx, cont); - } - }; - } // stack - -} // sol - -#endif // SOL_CONTAINER_USERTYPE_HPP diff --git a/3rdparty/sol2/sol/coroutine.hpp b/3rdparty/sol2/sol/coroutine.hpp deleted file mode 100644 index 17294aa5dc6..00000000000 --- a/3rdparty/sol2/sol/coroutine.hpp +++ /dev/null @@ -1,134 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_COROUTINE_HPP -#define SOL_COROUTINE_HPP - -#include "reference.hpp" -#include "stack.hpp" -#include "function_result.hpp" -#include "thread.hpp" - -namespace sol { - class coroutine : public reference { - private: - call_status stats = call_status::yielded; - - void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { -#if SOL_LUA_VERSION < 502 - stats = static_cast<call_status>(lua_resume(lua_state(), static_cast<int>(argcount))); -#else - stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount))); -#endif // Lua 5.1 compat - } - - template<std::size_t... I, typename... Ret> - auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) { - luacall(n, sizeof...(Ret)); - return stack::pop<std::tuple<Ret...>>(lua_state()); - } - - template<std::size_t I, typename Ret> - Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) { - luacall(n, 1); - return stack::pop<Ret>(lua_state()); - } - - template <std::size_t I> - void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) { - luacall(n, 0); - } - - protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { - int stacksize = lua_gettop(lua_state()); - int firstreturn = (std::max)(1, stacksize - static_cast<int>(n)); - luacall(n, LUA_MULTRET); - int poststacksize = lua_gettop(lua_state()); - int returncount = poststacksize - (firstreturn - 1); - if (error()) { - return protected_function_result(lua_state(), lua_absindex(lua_state(), -1), 1, returncount, status()); - } - return protected_function_result(lua_state(), firstreturn, returncount, returncount, status()); - } - - public: - coroutine() noexcept = default; - coroutine(const coroutine&) noexcept = default; - coroutine(coroutine&&) noexcept = default; - coroutine& operator=(const coroutine&) noexcept = default; - coroutine& operator=(coroutine&&) noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, coroutine>>, std::is_base_of<reference, meta::unqualified_t<T>>> = meta::enabler> - coroutine(T&& r) : reference(std::forward<T>(r)) {} - coroutine(lua_nil_t r) : reference(r) {} - coroutine(const stack_reference& r) noexcept : coroutine(r.lua_state(), r.stack_index()) {} - coroutine(stack_reference&& r) noexcept : coroutine(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - coroutine(lua_State* L, T&& r) : coroutine(L, sol::ref_index(r.registry_index())) {} - coroutine(lua_State* L, int index = -1) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<coroutine>(L, index, type_panic); -#endif // Safety - } - coroutine(lua_State* L, ref_index index) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<coroutine>(L, -1, type_panic); -#endif // Safety - } - - call_status status() const noexcept { - return stats; - } - - bool error() const noexcept { - call_status cs = status(); - return cs != call_status::ok && cs != call_status::yielded; - } - - bool runnable() const noexcept { - return valid() - && (status() == call_status::yielded); - } - - explicit operator bool() const noexcept { - return runnable(); - } - - template<typename... Args> - protected_function_result operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) operator()(types<Ret...>, Args&&... args) { - return call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - push(); - int pushcount = stack::multi_push(lua_state(), std::forward<Args>(args)...); - return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); - } - }; -} // sol - -#endif // SOL_COUROUTINE_HPP diff --git a/3rdparty/sol2/sol/debug.hpp b/3rdparty/sol2/sol/debug.hpp deleted file mode 100644 index 1219484df3b..00000000000 --- a/3rdparty/sol2/sol/debug.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_DEBUG_HPP -#define SOL_DEBUG_HPP - -#include "stack.hpp" -#include <iostream> - -namespace sol { - namespace detail { - namespace debug { - inline std::string dump_types(lua_State* L) { - std::string visual; - std::size_t size = lua_gettop(L) + 1; - for (std::size_t i = 1; i < size; ++i) { - if (i != 1) { - visual += " | "; - } - visual += type_name(L, stack::get<type>(L, static_cast<int>(i))); - } - return visual; - } - - inline void print_stack(lua_State* L) { - std::cout << dump_types(L) << std::endl; - } - - inline void print_section(const std::string& message, lua_State* L) { - std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl; - } - } // detail - } // debug -} // sol - -#endif // SOL_DEBUG_HPP diff --git a/3rdparty/sol2/sol/demangle.hpp b/3rdparty/sol2/sol/demangle.hpp deleted file mode 100644 index be9aa30594c..00000000000 --- a/3rdparty/sol2/sol/demangle.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_DEMANGLE_HPP -#define SOL_DEMANGLE_HPP - -#include <string> -#include <array> -#include <cctype> - -namespace sol { - namespace detail { -#ifdef _MSC_VER - template <typename T> - inline std::string ctti_get_type_name() { - const static std::array<std::string, 7> removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } }; - std::string name = __FUNCSIG__; - std::size_t start = name.find("get_type_name"); - if (start == std::string::npos) - start = 0; - else - start += 13; - if (start < name.size() - 1) - start += 1; - std::size_t end = name.find_last_of('>'); - if (end == std::string::npos) - end = name.size(); - name = name.substr(start, end - start); - if (name.find("struct", 0) == 0) - name.replace(0, 6, "", 0); - if (name.find("class", 0) == 0) - name.replace(0, 5, "", 0); - while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); - while (!name.empty() && std::isblank(name.back())) name.pop_back(); - - for (std::size_t r = 0; r < removals.size(); ++r) { - auto found = name.find(removals[r]); - while (found != std::string::npos) { - name.erase(found, removals[r].size()); - found = name.find(removals[r]); - } - } - - return name; - } -#elif defined(__GNUC__) || defined(__clang__) - template <typename T, class seperator_mark = int> - inline std::string ctti_get_type_name() { - const static std::array<std::string, 2> removals = { { "{anonymous}", "(anonymous namespace)" } }; - std::string name = __PRETTY_FUNCTION__; - std::size_t start = name.find_first_of('['); - start = name.find_first_of('=', start); - std::size_t end = name.find_last_of(']'); - if (end == std::string::npos) - end = name.size(); - if (start == std::string::npos) - start = 0; - if (start < name.size() - 1) - start += 1; - name = name.substr(start, end - start); - start = name.rfind("seperator_mark"); - if (start != std::string::npos) { - name.erase(start - 2, name.length()); - } - while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); - while (!name.empty() && std::isblank(name.back())) name.pop_back(); - - for (std::size_t r = 0; r < removals.size(); ++r) { - auto found = name.find(removals[r]); - while (found != std::string::npos) { - name.erase(found, removals[r].size()); - found = name.find(removals[r]); - } - } - - return name; - } -#else -#error Compiler not supported for demangling -#endif // compilers - - template <typename T> - inline std::string demangle_once() { - std::string realname = ctti_get_type_name<T>(); - return realname; - } - - template <typename T> - inline std::string short_demangle_once() { - std::string realname = ctti_get_type_name<T>(); - // This isn't the most complete but it'll do for now...? - static const std::array<std::string, 10> ops = { { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" } }; - int level = 0; - std::ptrdiff_t idx = 0; - for (idx = static_cast<std::ptrdiff_t>(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { - if (level == 0 && realname[idx] == ':') { - break; - } - bool isleft = realname[idx] == '<'; - bool isright = realname[idx] == '>'; - if (!isleft && !isright) - continue; - bool earlybreak = false; - for (const auto& op : ops) { - std::size_t nisop = realname.rfind(op, idx); - if (nisop == std::string::npos) - continue; - std::size_t nisopidx = idx - op.size() + 1; - if (nisop == nisopidx) { - idx = static_cast<std::ptrdiff_t>(nisopidx); - earlybreak = true; - } - break; - } - if (earlybreak) { - continue; - } - level += isleft ? -1 : 1; - } - if (idx > 0) { - realname.erase(0, realname.length() < static_cast<std::size_t>(idx) ? realname.length() : idx + 1); - } - return realname; - } - - template <typename T> - inline const std::string& demangle() { - static const std::string d = demangle_once<T>(); - return d; - } - - template <typename T> - inline const std::string& short_demangle() { - static const std::string d = short_demangle_once<T>(); - return d; - } - } // detail -} // sol - -#endif // SOL_DEMANGLE_HPP diff --git a/3rdparty/sol2/sol/deprecate.hpp b/3rdparty/sol2/sol/deprecate.hpp deleted file mode 100644 index 0d9551a33b0..00000000000 --- a/3rdparty/sol2/sol/deprecate.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_DEPRECATE_HPP -#define SOL_DEPRECATE_HPP - -#ifndef SOL_DEPRECATED - #ifdef _MSC_VER - #define SOL_DEPRECATED __declspec(deprecated) - #elif __GNUC__ - #define SOL_DEPRECATED __attribute__((deprecated)) - #else - #define SOL_DEPRECATED [[deprecated]] - #endif // compilers -#endif // SOL_DEPRECATED - -namespace sol { - namespace detail { - template <typename T> - struct SOL_DEPRECATED deprecate_type { - using type = T; - }; - } // detail -} // sol - -#endif // SOL_DEPRECATE_HPP diff --git a/3rdparty/sol2/sol/error.hpp b/3rdparty/sol2/sol/error.hpp deleted file mode 100644 index e24861effe9..00000000000 --- a/3rdparty/sol2/sol/error.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_ERROR_HPP -#define SOL_ERROR_HPP - -#include <stdexcept> -#include <string> - -namespace sol { - namespace detail { - struct direct_error_tag {}; - const auto direct_error = direct_error_tag{}; - } // detail - - class error : public std::runtime_error { - private: - // Because VC++ is a fuccboi - std::string w; - public: - error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} - error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {} - error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} - error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} - - error(const error& e) = default; - error(error&& e) = default; - error& operator=(const error& e) = default; - error& operator=(error&& e) = default; - - virtual const char* what() const noexcept override { - return w.c_str(); - } - }; - -} // sol - -#endif // SOL_ERROR_HPP diff --git a/3rdparty/sol2/sol/forward.hpp b/3rdparty/sol2/sol/forward.hpp new file mode 100644 index 00000000000..8690690871f --- /dev/null +++ b/3rdparty/sol2/sol/forward.hpp @@ -0,0 +1,1321 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2022-06-25 08:14:19.328625 UTC +// This header was generated with sol v3.3.0 (revision eba86625) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP +#define SOL_SINGLE_INCLUDE_FORWARD_HPP + +// beginning of sol/forward.hpp + +#ifndef SOL_FORWARD_HPP +#define SOL_FORWARD_HPP + +// beginning of sol/version.hpp + +#include <sol/config.hpp> + +#define SOL_VERSION_MAJOR 3 +#define SOL_VERSION_MINOR 2 +#define SOL_VERSION_PATCH 3 +#define SOL_VERSION_STRING "3.2.3" +#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) + +#define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN +#define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) + +#define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT +#define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) + +#define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) +#define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) +#define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) +#define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) + +#define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) +#define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) + +#define SOL_ON | +#define SOL_OFF ^ +#define SOL_DEFAULT_ON + +#define SOL_DEFAULT_OFF - + +#if defined(SOL_BUILD_CXX_MODE) + #if (SOL_BUILD_CXX_MODE != 0) + #define SOL_BUILD_CXX_MODE_I_ SOL_ON + #else + #define SOL_BUILD_CXX_MODE_I_ SOL_OFF + #endif +#elif defined(__cplusplus) + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_BUILD_C_MODE) + #if (SOL_BUILD_C_MODE != 0) + #define SOL_BUILD_C_MODE_I_ SOL_ON + #else + #define SOL_BUILD_C_MODE_I_ SOL_OFF + #endif +#elif defined(__STDC__) + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if SOL_IS_ON(SOL_BUILD_C_MODE) + #include <stddef.h> + #include <stdint.h> + #include <limits.h> +#else + #include <cstddef> + #include <cstdint> + #include <climits> +#endif + +#if defined(SOL_COMPILER_VCXX) + #if defined(SOL_COMPILER_VCXX != 0) + #define SOL_COMPILER_VCXX_I_ SOL_ON + #else + #define SOL_COMPILER_VCXX_I_ SOL_OFF + #endif +#elif defined(_MSC_VER) + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_GCC) + #if defined(SOL_COMPILER_GCC != 0) + #define SOL_COMPILER_GCC_I_ SOL_ON + #else + #define SOL_COMPILER_GCC_I_ SOL_OFF + #endif +#elif defined(__GNUC__) + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_CLANG) + #if defined(SOL_COMPILER_CLANG != 0) + #define SOL_COMPILER_CLANG_I_ SOL_ON + #else + #define SOL_COMPILER_CLANG_I_ SOL_OFF + #endif +#elif defined(__clang__) + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_EDG) + #if defined(SOL_COMPILER_EDG != 0) + #define SOL_COMPILER_EDG_I_ SOL_ON + #else + #define SOL_COMPILER_EDG_I_ SOL_OFF + #endif +#else + #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_MINGW) + #if (SOL_COMPILER_MINGW != 0) + #define SOL_COMPILER_MINGW_I_ SOL_ON + #else + #define SOL_COMPILER_MINGW_I_ SOL_OFF + #endif +#elif defined(__MINGW32__) + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF +#endif + +#if SIZE_MAX <= 0xFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_ON + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_OFF +#elif SIZE_MAX <= 0xFFFFFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_ON + #define SOL_PLATFORM_X64_I_ SOL_OFF +#else + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_ON +#endif + +#define SOL_PLATFORM_ARM32_I_ SOL_OFF +#define SOL_PLATFORM_ARM64_I_ SOL_OFF + +#if defined(SOL_PLATFORM_WINDOWS) + #if (SOL_PLATFORM_WINDOWS != 0) + #define SOL_PLATFORM_WINDOWS_I_ SOL_ON + #else + #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF + #endif +#elif defined(_WIN32) + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_CYGWIN) + #if (SOL_PLATFORM_CYGWIN != 0) + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #else + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #endif +#elif defined(__CYGWIN__) + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_APPLE) + #if (SOL_PLATFORM_APPLE != 0) + #define SOL_PLATFORM_APPLE_I_ SOL_ON + #else + #define SOL_PLATFORM_APPLE_I_ SOL_OFF + #endif +#elif defined(__APPLE__) + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_UNIX) + #if (SOL_PLATFORM_UNIX != 0) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF + #endif +#elif defined(__unix__) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_LINUX) + #if (SOL_PLATFORM_LINUX != 0) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF + #endif +#elif defined(__LINUX__) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF +#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF + +#if defined(SOL_IN_DEBUG_DETECTED) + #if SOL_IN_DEBUG_DETECTED != 0 + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#elif !defined(NDEBUG) + #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF +#endif // We are in a debug mode of some sort + +#if defined(SOL_NO_EXCEPTIONS) + #if (SOL_NO_EXCEPTIONS != 0) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPUNWIND) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__EXCEPTIONS) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#else + #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_RTTI) + #if (SOL_NO_RTTI != 0) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPRTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__GXX_RTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#else + #define SOL_RTTI_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_THREAD_LOCAL) + #if SOL_NO_THREAD_LOCAL != 0 + #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF + #else + #define SOL_USE_THREAD_LOCAL_I_ SOL_ON + #endif +#else + #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON +#endif // thread_local keyword is bjorked on some platforms + +#if defined(SOL_ALL_SAFETIES_ON) + #if SOL_ALL_SAFETIES_ON != 0 + #define SOL_ALL_SAFETIES_ON_I_ SOL_ON + #else + #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF + #endif +#else + #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_GETTER) + #if SOL_SAFE_GETTER != 0 + #define SOL_SAFE_GETTER_I_ SOL_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_GETTER_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_USERTYPE) + #if SOL_SAFE_USERTYPE != 0 + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_REFERENCES) + #if SOL_SAFE_REFERENCES != 0 + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTIONS) + #if SOL_SAFE_FUNCTIONS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#elif defined (SOL_SAFE_FUNCTION_OBJECTS) + #if SOL_SAFE_FUNCTION_OBJECTS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTION_CALLS) + #if SOL_SAFE_FUNCTION_CALLS != 0 + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_PROXIES) + #if SOL_SAFE_PROXIES != 0 + #define SOL_SAFE_PROXIES_I_ SOL_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_NUMERICS) + #if SOL_SAFE_NUMERICS != 0 + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_STACK_CHECK) + #if SOL_SAFE_STACK_CHECK != 0 + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_CHECK_NUMBER_PRECISION) + #if SOL_NO_CHECK_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) + #if SOL_NO_CHECKING_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_SAFE_NUMERICS) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_STRINGS_ARE_NUMBERS) + #if (SOL_STRINGS_ARE_NUMBERS != 0) + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON + #else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF + #endif +#else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ENABLE_INTEROP) + #if SOL_ENABLE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#elif defined(SOL_USE_INTEROP) + #if SOL_USE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#else + #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_NIL) + #if (SOL_NO_NIL != 0) + #define SOL_NIL_I_ SOL_OFF + #else + #define SOL_NIL_I_ SOL_ON + #endif +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) + #define SOL_NIL_I_ SOL_DEFAULT_OFF +#else + #define SOL_NIL_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USERTYPE_TYPE_BINDING_INFO) + #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON + #else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF + #endif +#else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON +#endif // We should generate a my_type.__type table with lots of class information for usertypes + +#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) + #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) + #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON +#endif // make is_automagical on/off by default + +#if defined(SOL_STD_VARIANT) + #if (SOL_STD_VARIANT != 0) + #define SOL_STD_VARIANT_I_ SOL_ON + #else + #define SOL_STD_VARIANT_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) + #if defined(__has_include) + #if __has_include(<variant>) + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #endif +#endif // make is_automagical on/off by default + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) + #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #endif +#else + #if defined(__cpp_noexcept_function_type) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) + // There is a bug in the VC++ compiler?? + // on /std:c++latest under x86 conditions (VS 15.5.2), + // compiler errors are tossed for noexcept markings being on function types + // that are identical in every other way to their non-noexcept marked types function types... + // VS 2019: There is absolutely a bug. + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON + #endif +#endif // noexcept is part of a function's type + +#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && SOL_STACK_STRING_OPTIMIZATION_SIZE > 0 + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE +#else + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 +#endif + +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_I_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_I_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_I_ 2048 +#endif + +#if defined(SOL_PRINT_ERRORS) + #if (SOL_PRINT_ERRORS != 0) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#endif + +#if defined(SOL_DEFAULT_PASS_ON_ERROR) + #if (SOL_DEFAULT_PASS_ON_ERROR != 0) + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON + #else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUA) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUA) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUA_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUAJIT) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUAJIT) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUAJIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_LUA_HPP) + #if (SOL_NO_LUA_HPP != 0) + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #else + #define SOL_USE_LUA_HPP_I_ SOL_ON + #endif +#elif defined(SOL_USING_CXX_LUA) + #define SOL_USE_LUA_HPP_I_ SOL_OFF +#elif defined(__has_include) + #if __has_include(<lua.hpp>) + #define SOL_USE_LUA_HPP_I_ SOL_ON + #else + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #endif +#else + #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_CONTAINERS_START) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START +#elif defined(SOL_CONTAINERS_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX +#elif defined(SOL_CONTAINER_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX +#else + #define SOL_CONTAINER_START_INDEX_I_ 1 +#endif + +#if defined (SOL_NO_MEMORY_ALIGNMENT) + #if (SOL_NO_MEMORY_ALIGNMENT != 0) + #define SOL_ALIGN_MEMORY_I_ SOL_OFF + #else + #define SOL_ALIGN_MEMORY_I_ SOL_ON + #endif +#else + #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USE_BOOST) + #if (SOL_USE_BOOST != 0) + #define SOL_USE_BOOST_I_ SOL_ON + #else + #define SOL_USE_BOOST_I_ SOL_OFF + #endif +#else + #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USE_UNSAFE_BASE_LOOKUP) + #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON + #else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF + #endif +#else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_INSIDE_UNREAL) + #if (SOL_INSIDE_UNREAL != 0) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF + #endif +#else + #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_COMPAT) + #if (SOL_NO_COMPAT != 0) + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF + #else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON + #endif +#else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) + #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON + #else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF + #endif +#else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON + #else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF + #endif +#else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_MINGW_CCTYPE_IS_POISONED) + #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON + #else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) + // MinGW is off its rocker in some places... + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON +#else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CHAR8_T) + #if (SOL_CHAR8_T != 0) + #define SOL_CHAR8_T_I_ SOL_ON + #else + #define SOL_CHAR8_T_I_ SOL_OFF + #endif +#else + #if defined(__cpp_char8_t) + #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON + #else + #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if SOL_IS_ON(SOL_USE_BOOST) + #include <boost/version.hpp> + + #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr + #else + #define SOL_BOOST_NONE_CONSTEXPR_I_ const + #endif // BOOST_VERSION +#else + // assume boost isn't using a garbage version + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr +#endif + +#if defined(SOL2_CI) + #if (SOL2_CI != 0) + #define SOL2_CI_I_ SOL_ON + #else + #define SOL2_CI_I_ SOL_OFF + #endif +#else + #define SOL2_CI_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_C_ASSERT) + #define SOL_USER_C_ASSERT_I_ SOL_ON +#else + #define SOL_USER_C_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_M_ASSERT) + #define SOL_USER_M_ASSERT_I_ SOL_ON +#else + #define SOL_USER_M_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +// beginning of sol/prologue.hpp + +#if defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." +#endif + +#define SOL_PROLOGUE_I_ 1 + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ ) + + #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) + #else + #include <type_traits> + + #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) + #endif +#endif + +// end of sol/prologue.hpp + +// beginning of sol/epilogue.hpp + +#if !defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue is missing from this translation unit." +#else + #undef SOL_PROLOGUE_I_ +#endif + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #undef _FWD + #undef _MOVE +#endif + +// end of sol/epilogue.hpp + +// beginning of sol/detail/build_version.hpp + +#if defined(SOL_DLL) + #if (SOL_DLL != 0) + #define SOL_DLL_I_ SOL_ON + #else + #define SOL_DLL_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) + #define SOL_DLL_I_ SOL_DEFAULT_ON +#else + #define SOL_DLL_I_ SOL_DEFAULT_OFF +#endif // DLL definition + +#if defined(SOL_HEADER_ONLY) + #if (SOL_HEADER_ONLY != 0) + #define SOL_HEADER_ONLY_I_ SOL_ON + #else + #define SOL_HEADER_ONLY_I_ SOL_OFF + #endif +#else + #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_BUILD) + #if (SOL_BUILD != 0) + #define SOL_BUILD_I_ SOL_ON + #else + #define SOL_BUILD_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_BUILD_I_ SOL_DEFAULT_OFF +#else + #define SOL_BUILD_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_UNITY_BUILD) + #if (SOL_UNITY_BUILD != 0) + #define SOL_UNITY_BUILD_I_ SOL_ON + #else + #define SOL_UNITY_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_C_FUNCTION_LINKAGE) + #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE +#else + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + // C++ + #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" + #else + // normal + #define SOL_C_FUNCTION_LINKAGE_I_ + #endif // C++ or not +#endif // Linkage specification for C functions + +#if defined(SOL_API_LINKAGE) + #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE +#else + #if SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) + // MSVC Compiler; or, Windows, or Cygwin platforms + #if SOL_IS_ON(SOL_BUILD) + // Building the library + #if SOL_IS_ON(SOL_COMPILER_GCC) + // Using GCC + #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) + #else + // Using Clang, MSVC, etc... + #define SOL_API_LINKAGE_I_ __declspec(dllexport) + #endif + #else + #if SOL_IS_ON(SOL_COMPILER_GCC) + #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) + #else + #define SOL_API_LINKAGE_I_ __declspec(dllimport) + #endif + #endif + #else + // extern if building normally on non-MSVC + #define SOL_API_LINKAGE_I_ extern + #endif + #elif SOL_IS_ON(SOL_UNITY_BUILD) + // Built-in library, like how stb typical works + #if SOL_IS_ON(SOL_HEADER_ONLY) + // Header only, so functions are defined "inline" + #define SOL_API_LINKAGE_I_ inline + #else + // Not header only, so seperately compiled files + #define SOL_API_LINKAGE_I_ extern + #endif + #else + // Normal static library + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define SOL_API_LINKAGE_I_ + #else + #define SOL_API_LINKAGE_I_ extern + #endif + #endif // DLL or not +#endif // Build definitions + +#if defined(SOL_PUBLIC_FUNC_DECL) + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL +#else + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DECL_) + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ +#else + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_PUBLIC_FUNC_DEF) + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF +#else + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DEF) + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF +#else + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_FUNC_DECL) + #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_FUNC_DEFN) + #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DEFN_I_ __declspec(dllexport) + #else + #define SOL_FUNC_DEFN_I_ __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DEFN_I_ + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DECL) + #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DEFN) + #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DEFN_I_ + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif +#endif + +// end of sol/detail/build_version.hpp + +// end of sol/version.hpp + +#include <utility> +#include <type_traits> +#include <string_view> + +#if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT) +struct lua_State; +#else +extern "C" { +struct lua_State; +} +#endif // C++ Mangling for Lua vs. Not + +namespace sol { + + enum class type; + + class stateless_reference; + template <bool b> + class basic_reference; + using reference = basic_reference<false>; + using main_reference = basic_reference<true>; + class stateless_stack_reference; + class stack_reference; + + template <typename A> + class basic_bytecode; + + struct lua_value; + + struct proxy_base_tag; + template <typename> + struct proxy_base; + template <typename, typename> + struct table_proxy; + + template <bool, typename> + class basic_table_core; + template <bool b> + using table_core = basic_table_core<b, reference>; + template <bool b> + using main_table_core = basic_table_core<b, main_reference>; + template <bool b> + using stack_table_core = basic_table_core<b, stack_reference>; + template <typename base_type> + using basic_table = basic_table_core<false, base_type>; + using table = table_core<false>; + using global_table = table_core<true>; + using main_table = main_table_core<false>; + using main_global_table = main_table_core<true>; + using stack_table = stack_table_core<false>; + using stack_global_table = stack_table_core<true>; + + template <typename> + struct basic_lua_table; + using lua_table = basic_lua_table<reference>; + using stack_lua_table = basic_lua_table<stack_reference>; + + template <typename T, typename base_type> + class basic_usertype; + template <typename T> + using usertype = basic_usertype<T, reference>; + template <typename T> + using stack_usertype = basic_usertype<T, stack_reference>; + + template <typename base_type> + class basic_metatable; + using metatable = basic_metatable<reference>; + using stack_metatable = basic_metatable<stack_reference>; + + template <typename base_t> + struct basic_environment; + using environment = basic_environment<reference>; + using main_environment = basic_environment<main_reference>; + using stack_environment = basic_environment<stack_reference>; + + template <typename T, bool> + class basic_function; + template <typename T, bool, typename H> + class basic_protected_function; + using unsafe_function = basic_function<reference, false>; + using safe_function = basic_protected_function<reference, false, reference>; + using main_unsafe_function = basic_function<main_reference, false>; + using main_safe_function = basic_protected_function<main_reference, false, reference>; + using stack_unsafe_function = basic_function<stack_reference, false>; + using stack_safe_function = basic_protected_function<stack_reference, false, reference>; + using stack_aligned_unsafe_function = basic_function<stack_reference, true>; + using stack_aligned_safe_function = basic_protected_function<stack_reference, true, reference>; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; + using stack_aligned_function = stack_aligned_safe_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; + using stack_aligned_function = stack_aligned_unsafe_function; +#endif + using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template <typename base_t> + class basic_object_base; + template <typename base_t> + class basic_object; + template <typename base_t> + class basic_userdata; + template <typename base_t> + class basic_lightuserdata; + template <typename base_t> + class basic_coroutine; + template <typename base_t> + class basic_packaged_coroutine; + template <typename base_t> + class basic_thread; + + using object = basic_object<reference>; + using userdata = basic_userdata<reference>; + using lightuserdata = basic_lightuserdata<reference>; + using thread = basic_thread<reference>; + using coroutine = basic_coroutine<reference>; + using packaged_coroutine = basic_packaged_coroutine<reference>; + using main_object = basic_object<main_reference>; + using main_userdata = basic_userdata<main_reference>; + using main_lightuserdata = basic_lightuserdata<main_reference>; + using main_coroutine = basic_coroutine<main_reference>; + using stack_object = basic_object<stack_reference>; + using stack_userdata = basic_userdata<stack_reference>; + using stack_lightuserdata = basic_lightuserdata<stack_reference>; + using stack_thread = basic_thread<stack_reference>; + using stack_coroutine = basic_coroutine<stack_reference>; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + class state_view; + class state; + + template <typename T> + struct as_table_t; + template <typename T> + struct as_container_t; + template <typename T> + struct nested; + template <typename T> + struct light; + template <typename T> + struct user; + template <typename T> + struct as_args_t; + template <typename T> + struct protect_t; + template <typename F, typename... Policies> + struct policy_wrapper; + + template <typename T> + struct usertype_traits; + template <typename T> + struct unique_usertype_traits; + + template <typename... Args> + struct types { + typedef std::make_index_sequence<sizeof...(Args)> indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template <typename T> + struct derive : std::false_type { + typedef types<> type; + }; + + template <typename T> + struct base : std::false_type { + typedef types<> type; + }; + + template <typename T> + struct weak_derive { + static bool value; + }; + + template <typename T> + bool weak_derive<T>::value = false; + + namespace stack { + struct record; + } + +#if SOL_IS_OFF(SOL_USE_BOOST) + template <class T> + class optional; + + template <class T> + class optional<T&>; +#endif + + using check_handler_type = int(lua_State*, int, type, type, const char*); + +} // namespace sol + +#define SOL_BASE_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct base<T> : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() +#define SOL_DERIVED_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct derive<T> : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() + +#endif // SOL_FORWARD_HPP +// end of sol/forward.hpp + +#endif // SOL_SINGLE_INCLUDE_FORWARD_HPP diff --git a/3rdparty/sol2/sol/function.hpp b/3rdparty/sol2/sol/function.hpp deleted file mode 100644 index 57b2e0accd8..00000000000 --- a/3rdparty/sol2/sol/function.hpp +++ /dev/null @@ -1,159 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_HPP -#define SOL_FUNCTION_HPP - -#include "reference.hpp" -#include "stack.hpp" -#include "function_result.hpp" -#include "function_types.hpp" -#include <cstdint> -#include <functional> -#include <memory> - -namespace sol { - template <typename base_t> - class basic_function : public base_t { - private: - void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { - lua_callk(base_t::lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), 0, nullptr); - } - - template<std::size_t... I, typename... Ret> - auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) const { - luacall(n, lua_size<std::tuple<Ret...>>::value); - return stack::pop<std::tuple<Ret...>>(base_t::lua_state()); - } - - template<std::size_t I, typename Ret> - Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) const { - luacall(n, lua_size<Ret>::value); - return stack::pop<Ret>(base_t::lua_state()); - } - - template <std::size_t I> - void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const { - luacall(n, 0); - } - - function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { - int stacksize = lua_gettop(base_t::lua_state()); - int firstreturn = (std::max)(1, stacksize - static_cast<int>(n)); - luacall(n, LUA_MULTRET); - int poststacksize = lua_gettop(base_t::lua_state()); - int returncount = poststacksize - (firstreturn - 1); - return function_result(base_t::lua_state(), firstreturn, returncount); - } - - public: - basic_function() = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_function(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_function<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - stack::check<basic_function>(base_t::lua_state(), -1, type_panic); - } -#endif // Safety - } - basic_function(const basic_function&) = default; - basic_function& operator=(const basic_function&) = default; - basic_function(basic_function&&) = default; - basic_function& operator=(basic_function&&) = default; - basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} - basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_function(lua_State* L, T&& r) : basic_function(L, sol::ref_index(r.registry_index())) {} - basic_function(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<basic_function>(L, index, type_panic); -#endif // Safety - } - basic_function(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<basic_function>(L, -1, type_panic); -#endif // Safety - } - - template<typename... Args> - function_result operator()(Args&&... args) const { - return call<>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) operator()(types<Ret...>, Args&&... args) const { - return call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) const { - base_t::push(); - int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward<Args>(args)...); - return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); - } - }; - - namespace stack { - template<typename Signature> - struct getter<std::function<Signature>> { - typedef meta::bind_traits<Signature> fx_t; - typedef typename fx_t::args_list args_lists; - typedef meta::tuple_types<typename fx_t::return_type> return_types; - - template<typename... Args, typename... Ret> - static std::function<Signature> get_std_func(types<Ret...>, types<Args...>, lua_State* L, int index) { - sol::function f(L, index); - auto fx = [f, L, index](Args&&... args) -> meta::return_type_t<Ret...> { - return f.call<Ret...>(std::forward<Args>(args)...); - }; - return std::move(fx); - } - - template<typename... FxArgs> - static std::function<Signature> get_std_func(types<void>, types<FxArgs...>, lua_State* L, int index) { - sol::function f(L, index); - auto fx = [f, L, index](FxArgs&&... args) -> void { - f(std::forward<FxArgs>(args)...); - }; - return std::move(fx); - } - - template<typename... FxArgs> - static std::function<Signature> get_std_func(types<>, types<FxArgs...> t, lua_State* L, int index) { - return get_std_func(types<void>(), t, L, index); - } - - static std::function<Signature> get(lua_State* L, int index, record& tracking) { - tracking.last = 1; - tracking.used += 1; - type t = type_of(L, index); - if (t == type::none || t == type::lua_nil) { - return nullptr; - } - return get_std_func(return_types(), args_lists(), L, index); - } - }; - } // stack -} // sol - -#endif // SOL_FUNCTION_HPP diff --git a/3rdparty/sol2/sol/function_result.hpp b/3rdparty/sol2/sol/function_result.hpp deleted file mode 100644 index 4e4da1289d1..00000000000 --- a/3rdparty/sol2/sol/function_result.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_RESULT_HPP -#define SOL_FUNCTION_RESULT_HPP - -#include "reference.hpp" -#include "tuple.hpp" -#include "stack.hpp" -#include "proxy_base.hpp" -#include <cstdint> - -namespace sol { - struct function_result : public proxy_base<function_result> { - private: - lua_State* L; - int index; - int returncount; - - public: - function_result() = default; - function_result(lua_State* Ls, int idx = -1, int retnum = 0) : L(Ls), index(idx), returncount(retnum) { - - } - function_result(const function_result&) = default; - function_result& operator=(const function_result&) = default; - function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - } - function_result& operator=(function_result&& o) { - L = o.L; - index = o.index; - returncount = o.returncount; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - return *this; - } - - template<typename T> - decltype(auto) get() const { - return stack::get<T>(L, index); - } - - call_status status() const noexcept { - return call_status::ok; - } - - bool valid() const noexcept { - return status() == call_status::ok || status() == call_status::yielded; - } - - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; - - ~function_result() { - lua_pop(L, returncount); - } - }; -} // sol - -#endif // SOL_FUNCTION_RESULT_HPP diff --git a/3rdparty/sol2/sol/function_types.hpp b/3rdparty/sol2/sol/function_types.hpp deleted file mode 100644 index 7c76b8d6ed0..00000000000 --- a/3rdparty/sol2/sol/function_types.hpp +++ /dev/null @@ -1,342 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_HPP -#define SOL_FUNCTION_TYPES_HPP - -#include "function_types_core.hpp" -#include "function_types_templated.hpp" -#include "function_types_stateless.hpp" -#include "function_types_stateful.hpp" -#include "function_types_overloaded.hpp" -#include "resolve.hpp" -#include "call.hpp" - -namespace sol { - namespace stack { - template<typename... Sigs> - struct pusher<function_sig<Sigs...>> { - template <typename... Sig, typename Fx, typename... Args> - static void select_convertible(std::false_type, types<Sig...>, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; - typedef function_detail::functor_function<clean_fx> F; - set_fx<F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename R, typename... A, typename Fx, typename... Args> - static void select_convertible(std::true_type, types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) { - using fx_ptr_t = R(*)(A...); - fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx)); - select_function(std::true_type(), L, fxptr, std::forward<Args>(args)...); - } - - template <typename R, typename... A, typename Fx, typename... Args> - static void select_convertible(types<R(A...)> t, lua_State* L, Fx&& fx, Args&&... args) { - typedef std::decay_t<meta::unwrap_unqualified_t<Fx>> raw_fx_t; - typedef R(*fx_ptr_t)(A...); - typedef std::is_convertible<raw_fx_t, fx_ptr_t> is_convertible; - select_convertible(is_convertible(), t, L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { - typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig; - select_convertible(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::remove_pointer_t<std::decay_t<Fx>> clean_fx; - typedef function_detail::member_variable<meta::unwrap_unqualified_t<T>, clean_fx> F; - set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t<Fx> dFx; - dFx memfxptr(std::forward<Fx>(fx)); - auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename... Args> - static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_convertible(types<Sigs...>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; - select_reference_member_variable(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx> - static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t<Fx> clean_fx; - typedef function_detail::member_function<meta::unwrap_unqualified_t<T>, clean_fx> F; - set_fx<F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef std::decay_t<Fx> dFx; - dFx memfxptr(std::forward<Fx>(fx)); - auto userptr = detail::ptr(std::forward<T>(obj), std::forward<Args>(args)...); - lua_CFunction freefunc = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, meta::unqualified_t<Fx>>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); - upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename... Args> - static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_variable(std::is_member_object_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename T, typename... Args> - static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { - typedef meta::boolean<meta::is_specialization_of<std::reference_wrapper, meta::unqualified_t<T>>::value || std::is_pointer<T>::value> is_reference; - select_reference_member_function(is_reference(), L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); - } - - template <typename Fx> - static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { - typedef typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type C; - lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, Fx>::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); - stack::push(L, c_closure(freefunc, upvalues)); - } - - template <typename Fx, typename... Args> - static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { - select_member_function(std::is_member_function_pointer<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { - std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...); - lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::call; - - int upvalues = stack::stack_detail::push_as_upvalues(L, target); - stack::push(L, c_closure(freefunc, upvalues)); - } - - static void select_function(std::true_type, lua_State* L, lua_CFunction f) { - stack::push(L, f); - } - - template <typename Fx, typename... Args> - static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function<meta::unqualified_t<Fx>>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static void set_fx(lua_State* L, Args&&... args) { - lua_CFunction freefunc = function_detail::call<meta::unqualified_t<Fx>>; - - stack::push<user<Fx>>(L, std::forward<Args>(args)...); - stack::push(L, c_closure(freefunc, 1)); - } - - template<typename... Args> - static int push(lua_State* L, Args&&... args) { - // Set will always place one thing (function) on the stack - select(L, std::forward<Args>(args)...); - return 1; - } - }; - - template<typename T, typename... Args> - struct pusher<function_arguments<T, Args...>> { - template <std::size_t... I, typename FP> - static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) { - return stack::push<T>(L, detail::forward_get<I>(fp.arguments)...); - } - - static int push(lua_State* L, const function_arguments<T, Args...>& fp) { - return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp); - } - - static int push(lua_State* L, function_arguments<T, Args...>&& fp) { - return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp)); - } - }; - - template<typename Signature> - struct pusher<std::function<Signature>> { - static int push(lua_State* L, std::function<Signature> fx) { - return pusher<function_sig<Signature>>{}.push(L, std::move(fx)); - } - }; - - template<typename Signature> - struct pusher<Signature, std::enable_if_t<std::is_member_pointer<Signature>::value>> { - template <typename F> - static int push(lua_State* L, F&& f) { - return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); - } - }; - - template<typename Signature> - struct pusher<Signature, std::enable_if_t<meta::all<std::is_function<Signature>, meta::neg<std::is_same<Signature, lua_CFunction>>, meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>>>::value>> { - template <typename F> - static int push(lua_State* L, F&& f) { - return pusher<function_sig<>>{}.push(L, std::forward<F>(f)); - } - }; - - template<typename... Functions> - struct pusher<overload_set<Functions...>> { - static int push(lua_State* L, overload_set<Functions...>&& set) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, std::move(set.functions)); - return 1; - } - - static int push(lua_State* L, const overload_set<Functions...>& set) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, set.functions); - return 1; - } - }; - - template <typename T> - struct pusher<protect_t<T>> { - static int push(lua_State* L, protect_t<T>&& pw) { - lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>; - int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value)); - return stack::push(L, c_closure(cf, closures)); - } - - static int push(lua_State* L, const protect_t<T>& pw) { - lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>; - int closures = stack::push<user<protect_t<T>>>(L, pw.value); - return stack::push(L, c_closure(cf, closures)); - } - }; - - template <typename F, typename G> - struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> { - static int push(lua_State* L, property_wrapper<F, G>&& pw) { - return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); - } - static int push(lua_State* L, const property_wrapper<F, G>& pw) { - return stack::push(L, sol::overload(pw.read, pw.write)); - } - }; - - template <typename F> - struct pusher<property_wrapper<F, void>> { - static int push(lua_State* L, property_wrapper<F, void>&& pw) { - return stack::push(L, std::move(pw.read)); - } - static int push(lua_State* L, const property_wrapper<F, void>& pw) { - return stack::push(L, pw.read); - } - }; - - template <typename F> - struct pusher<property_wrapper<void, F>> { - static int push(lua_State* L, property_wrapper<void, F>&& pw) { - return stack::push(L, std::move(pw.write)); - } - static int push(lua_State* L, const property_wrapper<void, F>& pw) { - return stack::push(L, pw.write); - } - }; - - template <typename T> - struct pusher<var_wrapper<T>> { - static int push(lua_State* L, var_wrapper<T>&& vw) { - return stack::push(L, std::move(vw.value)); - } - static int push(lua_State* L, const var_wrapper<T>& vw) { - return stack::push(L, vw.value); - } - }; - - template <typename... Functions> - struct pusher<factory_wrapper<Functions...>> { - static int push(lua_State* L, const factory_wrapper<Functions...>& fw) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, fw.functions); - return 1; - } - - static int push(lua_State* L, factory_wrapper<Functions...>&& fw) { - typedef function_detail::overloaded_function<Functions...> F; - pusher<function_sig<>>{}.set_fx<F>(L, std::move(fw.functions)); - return 1; - } - }; - - template <typename T, typename... Lists> - struct pusher<detail::tagged<T, constructor_list<Lists...>>> { - static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) { - lua_CFunction cf = call_detail::construct<T, Lists...>; - return stack::push(L, cf); - } - }; - - template <typename T, typename... Fxs> - struct pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> { - template <typename C> - static int push(lua_State* L, C&& c) { - lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>; - int closures = stack::push<user<constructor_wrapper<Fxs...>>>(L, std::forward<C>(c)); - return stack::push(L, c_closure(cf, closures)); - } - }; - - template <typename T> - struct pusher<detail::tagged<T, destructor_wrapper<void>>> { - static int push(lua_State* L, destructor_wrapper<void>) { - lua_CFunction cf = detail::usertype_alloc_destroy<T>; - return stack::push(L, cf); - } - }; - - template <typename T, typename Fx> - struct pusher<detail::tagged<T, destructor_wrapper<Fx>>> { - static int push(lua_State* L, destructor_wrapper<Fx> c) { - lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>>; - int closures = stack::push<user<T>>(L, std::move(c)); - return stack::push(L, c_closure(cf, closures)); - } - }; - - } // stack -} // sol - -#endif // SOL_FUNCTION_TYPES_HPP diff --git a/3rdparty/sol2/sol/function_types_core.hpp b/3rdparty/sol2/sol/function_types_core.hpp deleted file mode 100644 index 24169ea7faf..00000000000 --- a/3rdparty/sol2/sol/function_types_core.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_CORE_HPP -#define SOL_FUNCTION_TYPES_CORE_HPP - -#include "stack.hpp" -#include "wrapper.hpp" -#include <memory> - -namespace sol { - namespace function_detail { - template <typename Fx> - inline int call(lua_State* L) { - Fx& fx = stack::get<user<Fx>>(L, upvalue_index(1)); - return fx(L); - } - } // function_detail -} // sol - -#endif // SOL_FUNCTION_TYPES_CORE_HPP diff --git a/3rdparty/sol2/sol/function_types_overloaded.hpp b/3rdparty/sol2/sol/function_types_overloaded.hpp deleted file mode 100644 index cfcfdebec68..00000000000 --- a/3rdparty/sol2/sol/function_types_overloaded.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_OVERLOAD_HPP -#define SOL_FUNCTION_TYPES_OVERLOAD_HPP - -#include "overload.hpp" -#include "call.hpp" -#include "function_types_core.hpp" - -namespace sol { - namespace function_detail { - template <typename... Functions> - struct overloaded_function { - typedef std::tuple<Functions...> overload_list; - typedef std::make_index_sequence<sizeof...(Functions)> indices; - overload_list overloads; - - overloaded_function(overload_list set) - : overloads(std::move(set)) {} - - overloaded_function(Functions... fxs) - : overloads(fxs...) { - - } - - template <typename Fx, std::size_t I, typename... R, typename... Args> - int call(types<Fx>, index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int) { - auto& func = std::get<I>(overloads); - return call_detail::call_wrapped<void, true, false>(L, func); - } - - int operator()(lua_State* L) { - auto mfx = [&](auto&&... args) { return this->call(std::forward<decltype(args)>(args)...); }; - return call_detail::overload_match<Functions...>(mfx, L, 1); - } - }; - } // function_detail -} // sol - -#endif // SOL_FUNCTION_TYPES_OVERLOAD_HPP
\ No newline at end of file diff --git a/3rdparty/sol2/sol/function_types_stateful.hpp b/3rdparty/sol2/sol/function_types_stateful.hpp deleted file mode 100644 index aa79dadb28f..00000000000 --- a/3rdparty/sol2/sol/function_types_stateful.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_STATEFUL_HPP -#define SOL_FUNCTION_TYPES_STATEFUL_HPP - -#include "function_types_core.hpp" - -namespace sol { - namespace function_detail { - template<typename Func> - struct functor_function { - typedef meta::unwrapped_t<meta::unqualified_t<Func>> Function; - Function fx; - - template<typename... Args> - functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward<Args>(args)...) {} - - int call(lua_State* L) { - return call_detail::call_wrapped<void, true, false>(L, fx); - } - - int operator()(lua_State* L) { - auto f = [&](lua_State*) -> int { return this->call(L); }; - return detail::trampoline(L, f); - } - }; - - template<typename T, typename Function> - struct member_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef meta::function_return_t<function_type> return_type; - typedef meta::function_args_t<function_type> args_lists; - function_type invocation; - T member; - - template<typename... Args> - member_function(function_type f, Args&&... args) : invocation(std::move(f)), member(std::forward<Args>(args)...) {} - - int call(lua_State* L) { - return call_detail::call_wrapped<T, true, false, -1>(L, invocation, detail::unwrap(detail::deref(member))); - } - - int operator()(lua_State* L) { - auto f = [&](lua_State*) -> int { return this->call(L); }; - return detail::trampoline(L, f); - } - }; - - template<typename T, typename Function> - struct member_variable { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef typename meta::bind_traits<function_type>::return_type return_type; - typedef typename meta::bind_traits<function_type>::args_list args_lists; - function_type var; - T member; - typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M; - - template<typename... Args> - member_variable(function_type v, Args&&... args) : var(std::move(v)), member(std::forward<Args>(args)...) {} - - int call(lua_State* L) { - M mem = detail::unwrap(detail::deref(member)); - switch (lua_gettop(L)) { - case 0: - return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); - case 1: - return call_detail::call_wrapped<T, false, false, -1>(L, var, mem); - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } - - int operator()(lua_State* L) { - auto f = [&](lua_State*) -> int { return this->call(L); }; - return detail::trampoline(L, f); - } - }; - } // function_detail -} // sol - -#endif // SOL_FUNCTION_TYPES_STATEFUL_HPP diff --git a/3rdparty/sol2/sol/function_types_stateless.hpp b/3rdparty/sol2/sol/function_types_stateless.hpp deleted file mode 100644 index 0b6e9072ddd..00000000000 --- a/3rdparty/sol2/sol/function_types_stateless.hpp +++ /dev/null @@ -1,163 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_STATELESS_HPP -#define SOL_FUNCTION_TYPES_STATELESS_HPP - -#include "stack.hpp" - -namespace sol { - namespace function_detail { - template<typename Function> - struct upvalue_free_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L); - function_type* fx = udata.first; - return call_detail::call_wrapped<void, true, false>(L, fx); - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_member_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member function pointer - // idx n + 1: is the object's void pointer - // We don't need to store the size, because the other side is templated - // with the same member function pointer type - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); - function_type& memfx = memberdata.first; - auto& item = *objdata.first; - return call_detail::call_wrapped<T, true, false, -1>(L, memfx, item); - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_member_variable { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - // idx n + 1: is the object's void pointer - // We don't need to store the size, because the other side is templated - // with the same member function pointer type - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); - auto& mem = *objdata.first; - function_type& var = memberdata.first; - switch (lua_gettop(L)) { - case 0: - return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); - case 1: - return call_detail::call_wrapped<T, false, false, -1>(L, var, mem); - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_this_member_function { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - function_type& memfx = memberdata.first; - return call_detail::call_wrapped<T, false, false>(L, memfx); - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - - template<typename T, typename Function> - struct upvalue_this_member_variable { - typedef std::remove_pointer_t<std::decay_t<Function>> function_type; - typedef lua_bind_traits<function_type> traits_type; - - static int real_call(lua_State* L) { - // Layout: - // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1); - function_type& var = memberdata.first; - switch (lua_gettop(L)) { - case 1: - return call_detail::call_wrapped<T, true, false>(L, var); - case 2: - return call_detail::call_wrapped<T, false, false>(L, var); - default: - return luaL_error(L, "sol: incorrect number of arguments to member variable function"); - } - } - - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); - } - - int operator()(lua_State* L) { - return call(L); - } - }; - } // function_detail -} // sol - -#endif // SOL_FUNCTION_TYPES_STATELESS_HPP diff --git a/3rdparty/sol2/sol/function_types_templated.hpp b/3rdparty/sol2/sol/function_types_templated.hpp deleted file mode 100644 index 80989408ad8..00000000000 --- a/3rdparty/sol2/sol/function_types_templated.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_FUNCTION_TYPES_TEMPLATED_HPP -#define SOL_FUNCTION_TYPES_TEMPLATED_HPP - -#include "call.hpp" - -namespace sol { - namespace function_detail { - template <typename F, F fx> - inline int call_wrapper_variable(std::false_type, lua_State* L) { - typedef meta::bind_traits<meta::unqualified_t<F>> traits_type; - typedef typename traits_type::args_list args_list; - typedef meta::tuple_types<typename traits_type::return_type> return_type; - return stack::call_into_lua(return_type(), args_list(), L, 1, fx); - } - - template <typename R, typename V, V, typename T> - inline int call_set_assignable(std::false_type, T&&, lua_State* L) { - return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); - } - - template <typename R, typename V, V variable, typename T> - inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { - (mem.*variable) = stack::get<R>(L, 2); - return 0; - } - - template <typename R, typename V, V, typename T> - inline int call_set_variable(std::false_type, lua_State* L, T&&) { - return luaL_error(L, "cannot write to a const variable"); - } - - template <typename R, typename V, V variable, typename T> - inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { - return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem)); - } - - template <typename V, V variable> - inline int call_wrapper_variable(std::true_type, lua_State* L) { - typedef meta::bind_traits<meta::unqualified_t<V>> traits_type; - typedef typename traits_type::object_type T; - typedef typename traits_type::return_type R; - auto& mem = stack::get<T>(L, 1); - switch (lua_gettop(L)) { - case 1: { - decltype(auto) r = (mem.*variable); - stack::push_reference(L, std::forward<decltype(r)>(r)); - return 1; } - case 2: - return call_set_variable<R, V, variable>(meta::neg<std::is_const<R>>(), L, mem); - default: - return luaL_error(L, "incorrect number of arguments to member variable function call"); - } - } - - template <typename F, F fx> - inline int call_wrapper_function(std::false_type, lua_State* L) { - return call_wrapper_variable<F, fx>(std::is_member_object_pointer<F>(), L); - } - - template <typename F, F fx> - inline int call_wrapper_function(std::true_type, lua_State* L) { - return call_detail::call_wrapped<void, false, false>(L, fx); - } - - template <typename F, F fx> - int call_wrapper_entry(lua_State* L) { - return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L); - } - - template <typename... Fxs> - struct c_call_matcher { - template <typename Fx, std::size_t I, typename R, typename... Args> - int operator()(types<Fx>, index_value<I>, types<R>, types<Args...>, lua_State* L, int, int) const { - typedef meta::at_in_pack_t<I, Fxs...> target; - return target::call(L); - } - }; - - } // function_detail - - template <typename F, F fx> - inline int c_call(lua_State* L) { -#ifdef __clang__ - return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>); -#else - return detail::static_trampoline<(&function_detail::call_wrapper_entry<F, fx>)>(L); -#endif // fuck you clang :c - } - - template <typename F, F f> - struct wrap { - typedef F type; - - static int call(lua_State* L) { - return c_call<type, f>(L); - } - }; - - template <typename... Fxs> - inline int c_call(lua_State* L) { - if (sizeof...(Fxs) < 2) { - return meta::at_in_pack_t<0, Fxs...>::call(L); - } - else { - return call_detail::overload_match_arity<typename Fxs::type...>(function_detail::c_call_matcher<Fxs...>(), L, lua_gettop(L), 1); - } - } - -} // sol - -#endif // SOL_FUNCTION_TYPES_TEMPLATED_HPP diff --git a/3rdparty/sol2/sol/in_place.hpp b/3rdparty/sol2/sol/in_place.hpp deleted file mode 100644 index 2410fb96791..00000000000 --- a/3rdparty/sol2/sol/in_place.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_IN_PLACE_HPP -#define SOL_IN_PLACE_HPP - -namespace sol { - - namespace detail { - struct in_place_of {}; - template <std::size_t I> - struct in_place_of_i {}; - template <typename T> - struct in_place_of_t {}; - } // detail - - struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; }; - constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); } - template <typename T> - constexpr inline in_place_tag in_place(detail::in_place_of_t<T>) { return in_place_tag(in_place_tag::init()); } - template <std::size_t I> - constexpr inline in_place_tag in_place(detail::in_place_of_i<I>) { return in_place_tag(in_place_tag::init()); } - - using in_place_t = in_place_tag(&)(detail::in_place_of); - template <typename T> - using in_place_type_t = in_place_tag(&)(detail::in_place_of_t<T>); - template <std::size_t I> - using in_place_index_t = in_place_tag(&)(detail::in_place_of_i<I>); - -} // sol - -#endif // SOL_IN_PLACE_HPP diff --git a/3rdparty/sol2/sol/inheritance.hpp b/3rdparty/sol2/sol/inheritance.hpp deleted file mode 100644 index f2583495bc4..00000000000 --- a/3rdparty/sol2/sol/inheritance.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_INHERITANCE_HPP -#define SOL_INHERITANCE_HPP - -#include "types.hpp" -#include <atomic> - -namespace sol { - template <typename... Args> - struct base_list { }; - template <typename... Args> - using bases = base_list<Args...>; - - typedef bases<> base_classes_tag; - const auto base_classes = base_classes_tag(); - - namespace detail { - - template <typename T> - struct has_derived { - static bool value; - }; - - template <typename T> - bool has_derived<T>::value = false; - - inline std::size_t unique_id() { - static std::atomic<std::size_t> x(0); - return ++x; - } - - template <typename T> - struct id_for { - static const std::size_t value; - }; - - template <typename T> - const std::size_t id_for<T>::value = unique_id(); - - inline decltype(auto) base_class_check_key() { - static const auto& key = "class_check"; - return key; - } - - inline decltype(auto) base_class_cast_key() { - static const auto& key = "class_cast"; - return key; - } - - inline decltype(auto) base_class_index_propogation_key() { - static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; - return key; - } - - inline decltype(auto) base_class_new_index_propogation_key() { - static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; - return key; - } - - template <typename T, typename... Bases> - struct inheritance { - static bool type_check_bases(types<>, std::size_t) { - return false; - } - - template <typename Base, typename... Args> - static bool type_check_bases(types<Base, Args...>, std::size_t ti) { - return ti == id_for<Base>::value || type_check_bases(types<Args...>(), ti); - } - - static bool type_check(std::size_t ti) { - return ti == id_for<T>::value || type_check_bases(types<Bases...>(), ti); - } - - static void* type_cast_bases(types<>, T*, std::size_t) { - return nullptr; - } - - template <typename Base, typename... Args> - static void* type_cast_bases(types<Base, Args...>, T* data, std::size_t ti) { - // Make sure to convert to T first, and then dynamic cast to the proper type - return ti != id_for<Base>::value ? type_cast_bases(types<Args...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data)); - } - - static void* type_cast(void* voiddata, std::size_t ti) { - T* data = static_cast<T*>(voiddata); - return static_cast<void*>(ti != id_for<T>::value ? type_cast_bases(types<Bases...>(), data, ti) : data); - } - }; - - using inheritance_check_function = decltype(&inheritance<void>::type_check); - using inheritance_cast_function = decltype(&inheritance<void>::type_cast); - - } // detail -} // sol - -#endif // SOL_INHERITANCE_HPP diff --git a/3rdparty/sol2/sol/load_result.hpp b/3rdparty/sol2/sol/load_result.hpp deleted file mode 100644 index 443b3d765a0..00000000000 --- a/3rdparty/sol2/sol/load_result.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_LOAD_RESULT_HPP -#define SOL_LOAD_RESULT_HPP - -#include "stack.hpp" -#include "function.hpp" -#include "proxy_base.hpp" -#include <cstdint> - -namespace sol { - struct load_result : public proxy_base<load_result> { - private: - lua_State* L; - int index; - int returncount; - int popcount; - load_status err; - - template <typename T> - decltype(auto) tagged_get(types<sol::optional<T>>) const { - if (!valid()) { - return sol::optional<T>(nullopt); - } - return stack::get<sol::optional<T>>(L, index); - } - - template <typename T> - decltype(auto) tagged_get(types<T>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (!valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return stack::get<T>(L, index); - } - - sol::optional<sol::error> tagged_get(types<sol::optional<sol::error>>) const { - if (valid()) { - return nullopt; - } - return sol::error(detail::direct_error, stack::get<std::string>(L, index)); - } - - sol::error tagged_get(types<sol::error>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return sol::error(detail::direct_error, stack::get<std::string>(L, index)); - } - - public: - load_result() = default; - load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) { - - } - load_result(const load_result&) = default; - load_result& operator=(const load_result&) = default; - load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = load_status::syntax; - } - load_result& operator=(load_result&& o) noexcept { - L = o.L; - index = o.index; - returncount = o.returncount; - popcount = o.popcount; - err = o.err; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = load_status::syntax; - return *this; - } - - load_status status() const noexcept { - return err; - } - - bool valid() const noexcept { - return status() == load_status::ok; - } - - template<typename T> - T get() const { - return tagged_get(types<meta::unqualified_t<T>>()); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Args> - decltype(auto) operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - - lua_State* lua_state() const noexcept { return L; }; - int stack_index() const noexcept { return index; }; - - ~load_result() { - stack::remove(L, index, popcount); - } - }; -} // sol - -#endif // SOL_LOAD_RESULT_HPP diff --git a/3rdparty/sol2/sol/object.hpp b/3rdparty/sol2/sol/object.hpp deleted file mode 100644 index 3b69a6675ac..00000000000 --- a/3rdparty/sol2/sol/object.hpp +++ /dev/null @@ -1,154 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_OBJECT_HPP -#define SOL_OBJECT_HPP - -#include "reference.hpp" -#include "stack.hpp" -#include "userdata.hpp" -#include "as_args.hpp" -#include "variadic_args.hpp" -#include "optional.hpp" - -namespace sol { - - template <typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename T> - R make_reference(lua_State* L, T&& value) { - int backpedal = stack::push(L, std::forward<T>(value)); - R r = stack::get<R>(L, -backpedal); - if (should_pop) { - lua_pop(L, backpedal); - } - return r; - } - - template <typename T, typename R = reference, bool should_pop = !std::is_base_of<stack_reference, R>::value, typename... Args> - R make_reference(lua_State* L, Args&&... args) { - int backpedal = stack::push<T>(L, std::forward<Args>(args)...); - R r = stack::get<R>(L, -backpedal); - if (should_pop) { - lua_pop(L, backpedal); - } - return r; - } - - template <typename base_t> - class basic_object : public base_t { - private: - template<typename T> - decltype(auto) as_stack(std::true_type) const { - return stack::get<T>(base_t::lua_state(), base_t::stack_index()); - } - - template<typename T> - decltype(auto) as_stack(std::false_type) const { - base_t::push(); - return stack::pop<T>(base_t::lua_state()); - } - - template<typename T> - bool is_stack(std::true_type) const { - return stack::check<T>(base_t::lua_state(), base_t::stack_index(), no_panic); - } - - template<typename T> - bool is_stack(std::false_type) const { - auto pp = stack::push_pop(*this); - return stack::check<T>(base_t::lua_state(), -1, no_panic); - } - - template <bool invert_and_pop = false> - basic_object(std::integral_constant<bool, invert_and_pop>, lua_State* L, int index = -1) noexcept : base_t(L, index) { - if (invert_and_pop) { - lua_pop(L, -index); - } - } - - public: - basic_object() noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_object(T&& r) : base_t(std::forward<T>(r)) {} - basic_object(lua_nil_t r) : base_t(r) {} - basic_object(const basic_object&) = default; - basic_object(basic_object&&) = default; - basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} - basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} - template <typename Super> - basic_object(const proxy_base<Super>& r) noexcept : basic_object(r.operator basic_object()) {} - template <typename Super> - basic_object(proxy_base<Super>&& r) noexcept : basic_object(r.operator basic_object()) {} - basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} - basic_object(lua_State* L, ref_index index) noexcept : base_t(L, index) {} - template <typename T, typename... Args> - basic_object(lua_State* L, in_place_type_t<T>, Args&&... args) noexcept : basic_object(std::integral_constant<bool, !std::is_base_of<stack_reference, base_t>::value>(), L, -stack::push<T>(L, std::forward<Args>(args)...)) {} - template <typename T, typename... Args> - basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place<T>, std::forward<T>(arg), std::forward<Args>(args)...) {} - basic_object& operator=(const basic_object&) = default; - basic_object& operator=(basic_object&&) = default; - basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } - basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } - template <typename Super> - basic_object& operator=(const proxy_base<Super>& r) { this->operator=(r.operator basic_object()); return *this; } - template <typename Super> - basic_object& operator=(proxy_base<Super>&& r) { this->operator=(r.operator basic_object()); return *this; } - - template<typename T> - decltype(auto) as() const { - return as_stack<T>(std::is_same<base_t, stack_reference>()); - } - - template<typename T> - bool is() const { - if (!base_t::valid()) - return false; - return is_stack<T>(std::is_same<base_t, stack_reference>()); - } - }; - - template <typename T> - object make_object(lua_State* L, T&& value) { - return make_reference<object, true>(L, std::forward<T>(value)); - } - - template <typename T, typename... Args> - object make_object(lua_State* L, Args&&... args) { - return make_reference<T, object, true>(L, std::forward<Args>(args)...); - } - - inline bool operator==(const object& lhs, const lua_nil_t&) { - return !lhs.valid(); - } - - inline bool operator==(const lua_nil_t&, const object& rhs) { - return !rhs.valid(); - } - - inline bool operator!=(const object& lhs, const lua_nil_t&) { - return lhs.valid(); - } - - inline bool operator!=(const lua_nil_t&, const object& rhs) { - return rhs.valid(); - } -} // sol - -#endif // SOL_OBJECT_HPP diff --git a/3rdparty/sol2/sol/optional.hpp b/3rdparty/sol2/sol/optional.hpp deleted file mode 100644 index 16f805e4ebf..00000000000 --- a/3rdparty/sol2/sol/optional.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_OPTIONAL_HPP -#define SOL_OPTIONAL_HPP - -#include "compatibility.hpp" -#include "in_place.hpp" -#if defined(SOL_USE_BOOST) -#include <boost/optional.hpp> -#else -#include "optional_implementation.hpp" -#endif // Boost vs. Better optional - -namespace sol { - -#if defined(SOL_USE_BOOST) - template <typename T> - using optional = boost::optional<T>; - using nullopt_t = boost::none_t; - const nullopt_t nullopt = boost::none; -#endif // Boost vs. Better optional - -} // sol - -#endif // SOL_OPTIONAL_HPP diff --git a/3rdparty/sol2/sol/optional_implementation.hpp b/3rdparty/sol2/sol/optional_implementation.hpp deleted file mode 100644 index 4ffd0f27cd8..00000000000 --- a/3rdparty/sol2/sol/optional_implementation.hpp +++ /dev/null @@ -1,1135 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// 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. - -// Copyright (C) 2011 - 2012 Andrzej Krzemienski. -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal - -# ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP -# define SOL_OPTIONAL_IMPLEMENTATION_HPP - -# include <utility> -# include <type_traits> -# include <initializer_list> -# include <cassert> -# include <functional> -# include <string> -# include <stdexcept> -#ifdef SOL_NO_EXCEPTIONS -#include <cstdlib> -#endif // Exceptions - -# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false - -# if defined __GNUC__ // NOTE: GNUC is also defined for Clang -# if (__GNUC__ >= 5) -# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# endif -# endif -# -# if defined __clang_major__ -# if (__clang_major__ == 3 && __clang_minor__ >= 5) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# elif (__clang_major__ > 3) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# endif -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# endif -# endif -# -# if defined _MSC_VER -# if (_MSC_VER >= 1900) -# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# endif -# endif - -# if defined __clang__ -# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif -# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif - - -# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 -# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr -# else -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 -# define OPTIONAL_CONSTEXPR_INIT_LIST -# endif - -# if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || (defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)) -# define OPTIONAL_HAS_MOVE_ACCESSORS 1 -# else -# define OPTIONAL_HAS_MOVE_ACCESSORS 0 -# endif - -# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr -# if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || ((defined __cplusplus) && (__cplusplus == 201103L)) -# define OPTIONAL_MUTABLE_CONSTEXPR -# else -# define OPTIONAL_MUTABLE_CONSTEXPR constexpr -# endif - -# if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -#pragma warning( push ) -#pragma warning( disable : 4814 ) -#endif - -namespace sol { - - // BEGIN workaround for missing is_trivially_destructible -# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it: it is already there -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - template <typename T> - using is_trivially_destructible = ::std::has_trivial_destructor<T>; -# endif - // END workaround for missing is_trivially_destructible - -# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - - -// workaround for missing traits in GCC and CLANG - template <class T> - struct is_nothrow_move_constructible - { - constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value; - }; - - - template <class T, class U> - struct is_assignable - { - template <class X, class Y> - constexpr static bool has_assign(...) { return false; } - - template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) > - // the comma operator is necessary for the cases where operator= returns void - constexpr static bool has_assign(bool) { return true; } - - constexpr static bool value = has_assign<T, U>(true); - }; - - - template <class T> - struct is_nothrow_move_assignable - { - template <class X, bool has_any_move_assign> - struct has_nothrow_move_assign { - constexpr static bool value = false; - }; - - template <class X> - struct has_nothrow_move_assign<X, true> { - constexpr static bool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>()); - }; - - constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; - }; - // end workaround - - -# endif - - - -// 20.5.4, optional for object types - template <class T> class optional; - - // 20.5.5, optional for lvalue reference types - template <class T> class optional<T&>; - - - // workaround: std utility functions aren't constexpr yet - template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept - { - return static_cast<T&&>(t); - } - - template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept - { - static_assert(!::std::is_lvalue_reference<T>::value, "!!"); - return static_cast<T&&>(t); - } - - template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept - { - return static_cast<typename ::std::remove_reference<T>::type&&>(t); - } - - -#if defined NDEBUG -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) -#else -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) -#endif - - - namespace detail_ - { - - // static_addressof: a constexpr version of addressof - template <typename T> - struct has_overloaded_addressof - { - template <class X> - constexpr static bool has_overload(...) { return false; } - - template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) > - constexpr static bool has_overload(bool) { return true; } - - constexpr static bool value = has_overload<T>(true); - }; - - template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> - constexpr T* static_addressof(T& ref) - { - return &ref; - } - - template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> - T* static_addressof(T& ref) - { - return ::std::addressof(ref); - } - - - // the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A - template <class U> - constexpr U convert(U v) { return v; } - - } // namespace detail_ - - constexpr struct trivial_init_t {} trivial_init{}; - - // 20.5.7, Disengaged state indicator - struct nullopt_t - { - struct init {}; - constexpr explicit nullopt_t(init) {} - }; - constexpr nullopt_t nullopt{ nullopt_t::init() }; - - - // 20.5.8, class bad_optional_access - class bad_optional_access : public ::std::logic_error { - public: - explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {} - explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {} - }; - - - template <class T> - struct alignas(T) optional_base { - char storage_[sizeof(T)]; - bool init_; - - constexpr optional_base() noexcept : storage_(), init_(false) {}; - - explicit optional_base(const T& v) : storage_(), init_(true) { - new (&storage())T(v); - } - - explicit optional_base(T&& v) : storage_(), init_(true) { - new (&storage())T(constexpr_move(v)); - } - - template <class... Args> explicit optional_base(in_place_t, Args&&... args) - : init_(true), storage_() { - new (&storage())T(constexpr_forward<Args>(args)...); - } - - template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> - explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) - : init_(true), storage_() { - new (&storage())T(il, constexpr_forward<Args>(args)...); - } -#if defined __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif - T& storage() { - return *reinterpret_cast<T*>(&storage_[0]); - } - - constexpr const T& storage() const { - return *reinterpret_cast<T const*>(&storage_[0]); - } -#if defined __GNUC__ -#pragma GCC diagnostic pop -#endif - - ~optional_base() { if (init_) { storage().T::~T(); } } - }; - -#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ - // Sorry, GCC 4.x; you're just a piece of shit - template <typename T> - using constexpr_optional_base = optional_base<T>; -#else - template <class T> - struct alignas(T) constexpr_optional_base { - char storage_[sizeof(T)]; - bool init_; - constexpr constexpr_optional_base() noexcept : storage_(), init_(false) {} - - explicit constexpr constexpr_optional_base(const T& v) : storage_(), init_(true) { - new (&storage())T(v); - } - - explicit constexpr constexpr_optional_base(T&& v) : storage_(), init_(true) { - new (&storage())T(constexpr_move(v)); - } - - template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) - : init_(true), storage_() { - new (&storage())T(constexpr_forward<Args>(args)...); - } - - template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) - : init_(true), storage_() { - new (&storage())T(il, constexpr_forward<Args>(args)...); - } - -#if defined __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif - T& storage() { - return (*reinterpret_cast<T*>(&storage_[0])); - } - - constexpr const T& storage() const { - return (*reinterpret_cast<T const*>(&storage_[0])); - } -#if defined __GNUC__ -#pragma GCC diagnostic pop -#endif - - ~constexpr_optional_base() = default; - }; -#endif - - template <class T> - using OptionalBase = typename ::std::conditional< - ::std::is_trivially_destructible<T>::value, - constexpr_optional_base<typename ::std::remove_const<T>::type>, - optional_base<typename ::std::remove_const<T>::type> - >::type; - - - - template <class T> - class optional : private OptionalBase<T> - { - static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T"); - static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T"); - - - constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; } - typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); } - constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); } - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); } - OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); } -# else - T& contained_val() & { return OptionalBase<T>::storage(); } - T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); } -# endif -# else - constexpr const T& contained_val() const { return OptionalBase<T>::storage(); } - T& contained_val() { return OptionalBase<T>::storage(); } -# endif - - void clear() noexcept { - if (initialized()) dataptr()->T::~T(); - OptionalBase<T>::init_ = false; - } - - template <class... Args> - void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...))) - { - assert(!OptionalBase<T>::init_); - ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...); - OptionalBase<T>::init_ = true; - } - - template <class U, class... Args> - void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...))) - { - assert(!OptionalBase<T>::init_); - ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...); - OptionalBase<T>::init_ = true; - } - - public: - typedef T value_type; - - // 20.5.5.1, constructors - constexpr optional() noexcept : OptionalBase<T>() {}; - constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {}; - - optional(const optional& rhs) - : OptionalBase<T>() - { - if (rhs.initialized()) { - ::new (static_cast<void*>(dataptr())) T(*rhs); - OptionalBase<T>::init_ = true; - } - } - - optional(const optional<T&>& rhs) : optional() - { - if (rhs) { - ::new (static_cast<void*>(dataptr())) T(*rhs); - OptionalBase<T>::init_ = true; - } - } - - - optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value) - : OptionalBase<T>() - { - if (rhs.initialized()) { - ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs)); - OptionalBase<T>::init_ = true; - } - } - - constexpr optional(const T& v) : OptionalBase<T>(v) {} - - constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {} - - template <class... Args> - explicit constexpr optional(in_place_t, Args&&... args) - : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {} - - template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args) - : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {} - - // 20.5.4.2, Destructor - ~optional() = default; - - // 20.5.4.3, assignment - optional& operator=(nullopt_t) noexcept - { - clear(); - return *this; - } - - optional& operator=(const optional& rhs) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); - else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; - return *this; - } - - optional& operator=(optional&& rhs) - noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs)); - else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs); - return *this; - } - - template <class U> - auto operator=(U&& v) - -> typename ::std::enable_if - < - ::std::is_same<typename ::std::decay<U>::type, T>::value, - optional& - >::type - { - if (initialized()) { contained_val() = ::std::forward<U>(v); } - else { initialize(::std::forward<U>(v)); } - return *this; - } - - - template <class... Args> - void emplace(Args&&... args) - { - clear(); - initialize(::std::forward<Args>(args)...); - } - - template <class U, class... Args> - void emplace(::std::initializer_list<U> il, Args&&... args) - { - clear(); - initialize<U, Args...>(il, ::std::forward<Args>(args)...); - } - - // 20.5.4.4, Swap - void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>()))) - { - if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); } - else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); } - else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); } - } - - // 20.5.4.5, Observers - - explicit constexpr operator bool() const noexcept { return initialized(); } - - constexpr T const* operator ->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { - assert(initialized()); - return dataptr(); - } - - constexpr T const& operator *() const& { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { - assert(initialized()); - return contained_val(); - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { - assert(initialized()); - return constexpr_move(contained_val()); - } - - constexpr T const& value() const& { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - - OPTIONAL_MUTABLE_CONSTEXPR T& value() & { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - : *(T*)nullptr; -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : std::move(*(T*)nullptr); -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - -# else - - T* operator ->() { - assert(initialized()); - return dataptr(); - } - - constexpr T const& operator *() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - T& operator *() { - assert(initialized()); - return contained_val(); - } - - constexpr T const& value() const { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - - T& value() { - return initialized() ? - contained_val() -#ifdef SOL_NO_EXCEPTIONS - // we can abort here - // but the others are constexpr, so we can't... - : (std::abort(), *(T*)nullptr); -#else - : (throw bad_optional_access("bad optional access"), contained_val()); -#endif - } - -# endif - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - - template <class V> - constexpr T value_or(V&& v) const& - { - return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - template <class V> - OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# else - - template <class V> - T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# endif - -# else - - template <class V> - constexpr T value_or(V&& v) const - { - return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); - } - -# endif - - }; - - - template <class T> - class optional<T&> - { - static_assert(!::std::is_same<T, nullopt_t>::value, "bad T"); - static_assert(!::std::is_same<T, in_place_t>::value, "bad T"); - T* ref; - - public: - - // 20.5.5.1, construction/destruction - constexpr optional() noexcept : ref(nullptr) {} - - constexpr optional(nullopt_t) noexcept : ref(nullptr) {} - - constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} - - optional(T&&) = delete; - - constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} - - explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} - - explicit optional(in_place_t, T&&) = delete; - - ~optional() = default; - - // 20.5.5.2, mutation - optional& operator=(nullopt_t) noexcept { - ref = nullptr; - return *this; - } - - // optional& operator=(const optional& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - // optional& operator=(optional&& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - template <typename U> - auto operator=(U&& rhs) noexcept - -> typename ::std::enable_if - < - ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, - optional& - >::type - { - ref = rhs.ref; - return *this; - } - - template <typename U> - auto operator=(U&& rhs) noexcept - -> typename ::std::enable_if - < - !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, - optional& - >::type - = delete; - - void emplace(T& v) noexcept { - ref = detail_::static_addressof(v); - } - - void emplace(T&&) = delete; - - - void swap(optional<T&>& rhs) noexcept - { - ::std::swap(ref, rhs.ref); - } - - // 20.5.5.3, observers - constexpr T* operator->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); - } - - constexpr T& operator*() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); - } - - constexpr T& value() const { - return ref ? - *ref -#ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; -#else - : throw bad_optional_access("bad optional access"); -#endif - } - - explicit constexpr operator bool() const noexcept { - return ref != nullptr; - } - - template <typename V> - constexpr T& value_or(V&& v) const - { - return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v)); - } - }; - - - template <class T> - class optional<T&&> - { - static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); - }; - - - // 20.5.8, Relational operators - template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y) - { - return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; - } - - template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y) - { - return !(x == y); - } - - template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y) - { - return (!y) ? false : (!x) ? true : *x < *y; - } - - template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y) - { - return (y < x); - } - - template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y) - { - return !(y < x); - } - - template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y) - { - return !(x < y); - } - - - // 20.5.9, Comparison with nullopt - template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept - { - return (!x); - } - - template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept - { - return (!x); - } - - template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept - { - return false; - } - - template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept - { - return (!x); - } - - template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept - { - return true; - } - - template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept - { - return bool(x); - } - - template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept - { - return false; - } - - template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept - { - return true; - } - - template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept - { - return (!x); - } - - - - // 20.5.10, Comparison with T - template <class T> constexpr bool operator==(const optional<T>& x, const T& v) - { - return bool(x) ? *x == v : false; - } - - template <class T> constexpr bool operator==(const T& v, const optional<T>& x) - { - return bool(x) ? v == *x : false; - } - - template <class T> constexpr bool operator!=(const optional<T>& x, const T& v) - { - return bool(x) ? *x != v : true; - } - - template <class T> constexpr bool operator!=(const T& v, const optional<T>& x) - { - return bool(x) ? v != *x : true; - } - - template <class T> constexpr bool operator<(const optional<T>& x, const T& v) - { - return bool(x) ? *x < v : true; - } - - template <class T> constexpr bool operator>(const T& v, const optional<T>& x) - { - return bool(x) ? v > *x : true; - } - - template <class T> constexpr bool operator>(const optional<T>& x, const T& v) - { - return bool(x) ? *x > v : false; - } - - template <class T> constexpr bool operator<(const T& v, const optional<T>& x) - { - return bool(x) ? v < *x : false; - } - - template <class T> constexpr bool operator>=(const optional<T>& x, const T& v) - { - return bool(x) ? *x >= v : false; - } - - template <class T> constexpr bool operator<=(const T& v, const optional<T>& x) - { - return bool(x) ? v <= *x : false; - } - - template <class T> constexpr bool operator<=(const optional<T>& x, const T& v) - { - return bool(x) ? *x <= v : true; - } - - template <class T> constexpr bool operator>=(const T& v, const optional<T>& x) - { - return bool(x) ? v >= *x : true; - } - - - // Comparison of optional<T&> with T - template <class T> constexpr bool operator==(const optional<T&>& x, const T& v) - { - return bool(x) ? *x == v : false; - } - - template <class T> constexpr bool operator==(const T& v, const optional<T&>& x) - { - return bool(x) ? v == *x : false; - } - - template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v) - { - return bool(x) ? *x != v : true; - } - - template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x) - { - return bool(x) ? v != *x : true; - } - - template <class T> constexpr bool operator<(const optional<T&>& x, const T& v) - { - return bool(x) ? *x < v : true; - } - - template <class T> constexpr bool operator>(const T& v, const optional<T&>& x) - { - return bool(x) ? v > *x : true; - } - - template <class T> constexpr bool operator>(const optional<T&>& x, const T& v) - { - return bool(x) ? *x > v : false; - } - - template <class T> constexpr bool operator<(const T& v, const optional<T&>& x) - { - return bool(x) ? v < *x : false; - } - - template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v) - { - return bool(x) ? *x >= v : false; - } - - template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x) - { - return bool(x) ? v <= *x : false; - } - - template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v) - { - return bool(x) ? *x <= v : true; - } - - template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x) - { - return bool(x) ? v >= *x : true; - } - - // Comparison of optional<T const&> with T - template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x == v : false; - } - - template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x) - { - return bool(x) ? v == *x : false; - } - - template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x != v : true; - } - - template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x) - { - return bool(x) ? v != *x : true; - } - - template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x < v : true; - } - - template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x) - { - return bool(x) ? v > *x : true; - } - - template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x > v : false; - } - - template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x) - { - return bool(x) ? v < *x : false; - } - - template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x >= v : false; - } - - template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x) - { - return bool(x) ? v <= *x : false; - } - - template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v) - { - return bool(x) ? *x <= v : true; - } - - template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x) - { - return bool(x) ? v >= *x : true; - } - - - // 20.5.12, Specialized algorithms - template <class T> - void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) { - x.swap(y); - } - - - template <class T> - constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) { - return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v)); - } - - template <class X> - constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) { - return optional<X&>(v.get()); - } - - -} // namespace - -namespace std -{ - template <typename T> - struct hash<sol::optional<T>> { - typedef typename hash<T>::result_type result_type; - typedef sol::optional<T> argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? ::std::hash<T>{}(*arg) : result_type{}; - } - }; - - template <typename T> - struct hash<sol::optional<T&>> { - typedef typename hash<T>::result_type result_type; - typedef sol::optional<T&> argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? ::std::hash<T>{}(*arg) : result_type{}; - } - }; -} - -# if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -#pragma warning( pop ) -#endif - - -# undef TR2_OPTIONAL_REQUIRES -# undef TR2_OPTIONAL_ASSERTED_EXPRESSION - -# endif // SOL_OPTIONAL_IMPLEMENTATION_HPP diff --git a/3rdparty/sol2/sol/overload.hpp b/3rdparty/sol2/sol/overload.hpp deleted file mode 100644 index 316a3322ba3..00000000000 --- a/3rdparty/sol2/sol/overload.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_OVERLOAD_HPP -#define SOL_OVERLOAD_HPP - -#include <utility> - -namespace sol { - template <typename... Functions> - struct overload_set { - std::tuple<Functions...> functions; - template <typename Arg, typename... Args, meta::disable<std::is_same<overload_set, meta::unqualified_t<Arg>>> = meta::enabler> - overload_set (Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - overload_set(const overload_set&) = default; - overload_set(overload_set&&) = default; - overload_set& operator=(const overload_set&) = default; - overload_set& operator=(overload_set&&) = default; - }; - - template <typename... Args> - decltype(auto) overload(Args&&... args) { - return overload_set<std::decay_t<Args>...>(std::forward<Args>(args)...); - } -} - -#endif // SOL_OVERLOAD_HPP
\ No newline at end of file diff --git a/3rdparty/sol2/sol/property.hpp b/3rdparty/sol2/sol/property.hpp deleted file mode 100644 index 703cac925d2..00000000000 --- a/3rdparty/sol2/sol/property.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_PROPERTY_HPP -#define SOL_PROPERTY_HPP - -namespace sol { - - struct no_prop { }; - - template <typename R, typename W> - struct property_wrapper { - typedef std::integral_constant<bool, !std::is_void<R>::value> can_read; - typedef std::integral_constant<bool, !std::is_void<W>::value> can_write; - typedef std::conditional_t<can_read::value, R, no_prop> Read; - typedef std::conditional_t<can_write::value, W, no_prop> Write; - Read read; - Write write; - - template <typename Rx, typename Wx> - property_wrapper(Rx&& r, Wx&& w) : read(std::forward<Rx>(r)), write(std::forward<Wx>(w)) {} - }; - - namespace property_detail { - template <typename R, typename W> - inline decltype(auto) property(std::true_type, R&& read, W&& write) { - return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write)); - } - template <typename W, typename R> - inline decltype(auto) property(std::false_type, W&& write, R&& read) { - return property_wrapper<std::decay_t<R>, std::decay_t<W>>(std::forward<R>(read), std::forward<W>(write)); - } - template <typename R> - inline decltype(auto) property(std::true_type, R&& read) { - return property_wrapper<std::decay_t<R>, void>(std::forward<R>(read), no_prop()); - } - template <typename W> - inline decltype(auto) property(std::false_type, W&& write) { - return property_wrapper<void, std::decay_t<W>>(no_prop(), std::forward<W>(write)); - } - } // property_detail - - template <typename F, typename G> - inline decltype(auto) property(F&& f, G&& g) { - typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; - typedef lua_bind_traits<meta::unqualified_t<G>> right_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward<F>(f), std::forward<G>(g)); - } - - template <typename F> - inline decltype(auto) property(F&& f) { - typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; - return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward<F>(f)); - } - - template <typename F> - inline decltype(auto) readonly_property(F&& f) { - return property_detail::property(std::true_type(), std::forward<F>(f)); - } - - // Allow someone to make a member variable readonly (const) - template <typename R, typename T> - inline auto readonly(R T::* v) { - typedef const R C; - return static_cast<C T::*>(v); - } - - template <typename T> - struct var_wrapper { - T value; - template <typename... Args> - var_wrapper(Args&&... args) : value(std::forward<Args>(args)...) {} - var_wrapper(const var_wrapper&) = default; - var_wrapper(var_wrapper&&) = default; - var_wrapper& operator=(const var_wrapper&) = default; - var_wrapper& operator=(var_wrapper&&) = default; - }; - - template <typename V> - inline auto var(V&& v) { - typedef meta::unqualified_t<V> T; - return var_wrapper<T>(std::forward<V>(v)); - } - -} // sol - -#endif // SOL_PROPERTY_HPP diff --git a/3rdparty/sol2/sol/protected_function.hpp b/3rdparty/sol2/sol/protected_function.hpp deleted file mode 100644 index 0f188a1a677..00000000000 --- a/3rdparty/sol2/sol/protected_function.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_PROTECTED_FUNCTION_HPP -#define SOL_PROTECTED_FUNCTION_HPP - -#include "reference.hpp" -#include "stack.hpp" -#include "protected_function_result.hpp" -#include <cstdint> -#include <algorithm> - -namespace sol { - namespace detail { - inline reference& handler_storage() { - static sol::reference h; - return h; - } - - struct handler { - const reference& target; - int stackindex; - handler(const reference& target) : target(target), stackindex(0) { - if (target.valid()) { - stackindex = lua_gettop(target.lua_state()) + 1; - target.push(); - } - } - bool valid() const { return stackindex != 0; } - ~handler() { - if (valid()) { - lua_remove(target.lua_state(), stackindex); - } - } - }; - } - - template <typename base_t> - class basic_protected_function : public base_t { - public: - static reference& get_default_handler() { - return detail::handler_storage(); - } - - static void set_default_handler(const reference& ref) { - detail::handler_storage() = ref; - } - - static void set_default_handler(reference&& ref) { - detail::handler_storage() = std::move(ref); - } - - private: - call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler& h) const { - return static_cast<call_status>(lua_pcallk(base_t::lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr)); - } - - template<std::size_t... I, typename... Ret> - auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::handler& h) const { - luacall(n, sizeof...(Ret), h); - return stack::pop<std::tuple<Ret...>>(base_t::lua_state()); - } - - template<std::size_t I, typename Ret> - Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler& h) const { - luacall(n, 1, h); - return stack::pop<Ret>(base_t::lua_state()); - } - - template <std::size_t I> - void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler& h) const { - luacall(n, 0, h); - } - - protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler& h) const { - int stacksize = lua_gettop(base_t::lua_state()); - int poststacksize = stacksize; - int firstreturn = 1; - int returncount = 0; - call_status code = call_status::ok; -#ifndef SOL_NO_EXCEPTIONS - auto onexcept = [&](const char* error) { - h.stackindex = 0; - if (h.target.valid()) { - h.target.push(); - stack::push(base_t::lua_state(), error); - lua_call(base_t::lua_state(), 1, 1); - } - else { - stack::push(base_t::lua_state(), error); - } - }; - try { -#endif // No Exceptions - firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid()))); - code = luacall(n, LUA_MULTRET, h); - poststacksize = lua_gettop(base_t::lua_state()) - static_cast<int>(h.valid()); - returncount = poststacksize - (firstreturn - 1); -#ifndef SOL_NO_EXCEPTIONS - } - // Handle C++ errors thrown from C++ functions bound inside of lua - catch (const char* error) { - onexcept(error); - firstreturn = lua_gettop(base_t::lua_state()); - return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); - } - catch (const std::exception& error) { - onexcept(error.what()); - firstreturn = lua_gettop(base_t::lua_state()); - return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); - } - catch (...) { - onexcept("caught (...) unknown error during protected_function call"); - firstreturn = lua_gettop(base_t::lua_state()); - return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); - } -#endif // No Exceptions - return protected_function_result(base_t::lua_state(), firstreturn, returncount, returncount, code); - } - - public: - reference error_handler; - - basic_protected_function() = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_function<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - stack::check<basic_protected_function>(base_t::lua_state(), -1, type_panic); - } -#endif // Safety - } - basic_protected_function(const basic_protected_function&) = default; - basic_protected_function& operator=(const basic_protected_function&) = default; - basic_protected_function(basic_protected_function&&) = default; - basic_protected_function& operator=(basic_protected_function&&) = default; - basic_protected_function(const basic_function<base_t>& b, reference eh = get_default_handler()) : base_t(b), error_handler(std::move(eh)) {} - basic_protected_function(basic_function<base_t>&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} - basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} - basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} - template <typename Super> - basic_protected_function(proxy_base<Super>&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function<base_t>(), std::move(eh)) {} - template <typename Super> - basic_protected_function(const proxy_base<Super>& p, reference eh = get_default_handler()) : basic_protected_function(static_cast<basic_function<base_t>>(p), std::move(eh)) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_protected_function(lua_State* L, T&& r, reference eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {} - basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<basic_protected_function>(L, index, type_panic); -#endif // Safety - } - basic_protected_function(lua_State* L, ref_index index, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<basic_protected_function>(L, -1, type_panic); -#endif // Safety - } - - template<typename... Args> - protected_function_result operator()(Args&&... args) const { - return call<>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) operator()(types<Ret...>, Args&&... args) const { - return call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) const { - detail::handler h(error_handler); - base_t::push(); - int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward<Args>(args)...); - return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); - } - }; -} // sol - -#endif // SOL_FUNCTION_HPP diff --git a/3rdparty/sol2/sol/protected_function_result.hpp b/3rdparty/sol2/sol/protected_function_result.hpp deleted file mode 100644 index 9fce575389a..00000000000 --- a/3rdparty/sol2/sol/protected_function_result.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_PROTECTED_FUNCTION_RESULT_HPP -#define SOL_PROTECTED_FUNCTION_RESULT_HPP - -#include "reference.hpp" -#include "tuple.hpp" -#include "stack.hpp" -#include "proxy_base.hpp" -#include <cstdint> - -namespace sol { - struct protected_function_result : public proxy_base<protected_function_result> { - private: - lua_State* L; - int index; - int returncount; - int popcount; - call_status err; - - template <typename T> - decltype(auto) tagged_get(types<sol::optional<T>>) const { - if (!valid()) { - return sol::optional<T>(nullopt); - } - return stack::get<sol::optional<T>>(L, index); - } - - template <typename T> - decltype(auto) tagged_get(types<T>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (!valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return stack::get<T>(L, index); - } - - optional<error> tagged_get(types<optional<error>>) const { - if (valid()) { - return nullopt; - } - return error(detail::direct_error, stack::get<std::string>(L, index)); - } - - error tagged_get(types<error>) const { -#ifdef SOL_CHECK_ARGUMENTS - if (valid()) { - type_panic(L, index, type_of(L, index), type::none); - } -#endif // Check Argument Safety - return error(detail::direct_error, stack::get<std::string>(L, index)); - } - - public: - protected_function_result() = default; - protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) { - - } - protected_function_result(const protected_function_result&) = default; - protected_function_result& operator=(const protected_function_result&) = default; - protected_function_result(protected_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = call_status::runtime; - } - protected_function_result& operator=(protected_function_result&& o) noexcept { - L = o.L; - index = o.index; - returncount = o.returncount; - popcount = o.popcount; - err = o.err; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but we will be thorough - o.L = nullptr; - o.index = 0; - o.returncount = 0; - o.popcount = 0; - o.err = call_status::runtime; - return *this; - } - - call_status status() const noexcept { - return err; - } - - bool valid() const noexcept { - return status() == call_status::ok || status() == call_status::yielded; - } - - template<typename T> - decltype(auto) get() const { - return tagged_get(types<meta::unqualified_t<T>>()); - } - - lua_State* lua_state() const noexcept { return L; }; - int stack_index() const noexcept { return index; }; - - ~protected_function_result() { - stack::remove(L, index, popcount); - } - }; -} // sol - -#endif // SOL_PROTECTED_FUNCTION_RESULT_HPP diff --git a/3rdparty/sol2/sol/proxy.hpp b/3rdparty/sol2/sol/proxy.hpp deleted file mode 100644 index 5cd8b5e1fc9..00000000000 --- a/3rdparty/sol2/sol/proxy.hpp +++ /dev/null @@ -1,179 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_PROXY_HPP -#define SOL_PROXY_HPP - -#include "traits.hpp" -#include "object.hpp" -#include "function.hpp" -#include "protected_function.hpp" -#include "proxy_base.hpp" - -namespace sol { - template<typename Table, typename Key> - struct proxy : public proxy_base<proxy<Table, Key>> { - private: - typedef meta::condition<meta::is_specialization_of<std::tuple, Key>, Key, std::tuple<meta::condition<std::is_array<meta::unqualified_t<Key>>, Key&, meta::unqualified_t<Key>>>> key_type; - - template<typename T, std::size_t... I> - decltype(auto) tuple_get(std::index_sequence<I...>) const { - return tbl.template traverse_get<T>(std::get<I>(key)...); - } - - template<std::size_t... I, typename T> - void tuple_set(std::index_sequence<I...>, T&& value) { - tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value)); - } - - public: - Table tbl; - key_type key; - - template<typename T> - proxy(Table table, T&& k) : tbl(table), key(std::forward<T>(k)) {} - - template<typename T> - proxy& set(T&& item) { - tuple_set(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>(), std::forward<T>(item)); - return *this; - } - - template<typename... Args> - proxy& set_function(Args&&... args) { - tbl.set_function(key, std::forward<Args>(args)...); - return *this; - } - - template<typename U, meta::enable<meta::neg<is_lua_reference<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> - proxy& operator=(U&& other) { - return set_function(std::forward<U>(other)); - } - - template<typename U, meta::disable<meta::neg<is_lua_reference<meta::unwrap_unqualified_t<U>>>, meta::is_callable<meta::unwrap_unqualified_t<U>>> = meta::enabler> - proxy& operator=(U&& other) { - return set(std::forward<U>(other)); - } - - template<typename T> - decltype(auto) get() const { - return tuple_get<T>(std::make_index_sequence<std::tuple_size<meta::unqualified_t<key_type>>::value>()); - } - - template<typename T> - decltype(auto) get_or(T&& otherwise) const { - typedef decltype(get<T>()) U; - sol::optional<U> option = get<sol::optional<U>>(); - if (option) { - return static_cast<U>(option.value()); - } - return static_cast<U>(std::forward<T>(otherwise)); - } - - template<typename T, typename D> - decltype(auto) get_or(D&& otherwise) const { - sol::optional<T> option = get<sol::optional<T>>(); - if (option) { - return static_cast<T>(option.value()); - } - return static_cast<T>(std::forward<D>(otherwise)); - } - - template <typename K> - decltype(auto) operator[](K&& k) const { - auto keys = meta::tuplefy(key, std::forward<K>(k)); - return proxy<Table, decltype(keys)>(tbl, std::move(keys)); - } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - return get<function>().template call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Args> - decltype(auto) operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - - bool valid() const { - auto pp = stack::push_pop(tbl); - auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); - lua_pop(tbl.lua_state(), p.levels); - return p; - } - }; - - template<typename Table, typename Key, typename T> - inline bool operator==(T&& left, const proxy<Table, Key>& right) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key, typename T> - inline bool operator==(const proxy<Table, Key>& right, T&& left) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key, typename T> - inline bool operator!=(T&& left, const proxy<Table, Key>& right) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key, typename T> - inline bool operator!=(const proxy<Table, Key>& right, T&& left) { - typedef decltype(stack::get<T>(nullptr, 0)) U; - return right.template get<optional<U>>() == left; - } - - template<typename Table, typename Key> - inline bool operator==(lua_nil_t, const proxy<Table, Key>& right) { - return !right.valid(); - } - - template<typename Table, typename Key> - inline bool operator==(const proxy<Table, Key>& right, lua_nil_t) { - return !right.valid(); - } - - template<typename Table, typename Key> - inline bool operator!=(lua_nil_t, const proxy<Table, Key>& right) { - return right.valid(); - } - - template<typename Table, typename Key> - inline bool operator!=(const proxy<Table, Key>& right, lua_nil_t) { - return right.valid(); - } - - namespace stack { - template <typename Table, typename Key> - struct pusher<proxy<Table, Key>> { - static int push(lua_State* L, const proxy<Table, Key>& p) { - sol::reference r = p; - return r.push(L); - } - }; - } // stack -} // sol - -#endif // SOL_PROXY_HPP diff --git a/3rdparty/sol2/sol/proxy_base.hpp b/3rdparty/sol2/sol/proxy_base.hpp deleted file mode 100644 index 959f6e6b281..00000000000 --- a/3rdparty/sol2/sol/proxy_base.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_PROXY_BASE_HPP -#define SOL_PROXY_BASE_HPP - -#include "reference.hpp" -#include "tuple.hpp" -#include "stack.hpp" - -namespace sol { - template <typename Super> - struct proxy_base { - operator std::string() const { - const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); - return super.template get<std::string>(); - } - - template<typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, is_proxy_primitive<meta::unqualified_t<T>>> = meta::enabler> - operator T () const { - const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); - return super.template get<T>(); - } - - template<typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, meta::neg<is_proxy_primitive<meta::unqualified_t<T>>>> = meta::enabler> - operator T& () const { - const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); - return super.template get<T&>(); - } - }; -} // sol - -#endif // SOL_PROXY_BASE_HPP diff --git a/3rdparty/sol2/sol/raii.hpp b/3rdparty/sol2/sol/raii.hpp deleted file mode 100644 index c7b20a69613..00000000000 --- a/3rdparty/sol2/sol/raii.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_RAII_HPP -#define SOL_RAII_HPP - -#include <memory> -#include "traits.hpp" - -namespace sol { - namespace detail { - struct default_construct { - template<typename T, typename... Args> - static void construct(T&& obj, Args&&... args) { - std::allocator<meta::unqualified_t<T>> alloc{}; - alloc.construct(obj, std::forward<Args>(args)...); - } - - template<typename T, typename... Args> - void operator()(T&& obj, Args&&... args) const { - construct(std::forward<T>(obj), std::forward<Args>(args)...); - } - }; - - struct default_destruct { - template<typename T> - static void destroy(T&& obj) { - std::allocator<meta::unqualified_t<T>> alloc{}; - alloc.destroy(obj); - } - - template<typename T> - void operator()(T&& obj) const { - destroy(std::forward<T>(obj)); - } - }; - - struct deleter { - template <typename T> - void operator()(T* p) const { - delete p; - } - }; - - template <typename T, typename Dx, typename... Args> - inline std::unique_ptr<T, Dx> make_unique_deleter(Args&&... args) { - return std::unique_ptr<T, Dx>(new T(std::forward<Args>(args)...)); - } - - template <typename Tag, typename T> - struct tagged { - T value; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, tagged>> = meta::enabler> - tagged(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - } // detail - - template <typename... Args> - struct constructor_list {}; - - template<typename... Args> - using constructors = constructor_list<Args...>; - - const auto default_constructor = constructors<types<>>{}; - - struct no_construction {}; - const auto no_constructor = no_construction{}; - - struct call_construction {}; - const auto call_constructor = call_construction{}; - - template <typename... Functions> - struct constructor_wrapper { - std::tuple<Functions...> functions; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, constructor_wrapper>> = meta::enabler> - constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - - template <typename... Functions> - inline auto initializers(Functions&&... functions) { - return constructor_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); - } - - template <typename... Functions> - struct factory_wrapper { - std::tuple<Functions...> functions; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, factory_wrapper>> = meta::enabler> - factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - - template <typename... Functions> - inline auto factories(Functions&&... functions) { - return factory_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); - } - - template <typename Function> - struct destructor_wrapper { - Function fx; - destructor_wrapper(Function f) : fx(std::move(f)) {} - }; - - template <> - struct destructor_wrapper<void> {}; - - const destructor_wrapper<void> default_destructor{}; - - template <typename Fx> - inline auto destructor(Fx&& fx) { - return destructor_wrapper<std::decay_t<Fx>>(std::forward<Fx>(fx)); - } - -} // sol - -#endif // SOL_RAII_HPP diff --git a/3rdparty/sol2/sol/reference.hpp b/3rdparty/sol2/sol/reference.hpp deleted file mode 100644 index a5f3ebe45b1..00000000000 --- a/3rdparty/sol2/sol/reference.hpp +++ /dev/null @@ -1,191 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_REFERENCE_HPP -#define SOL_REFERENCE_HPP - -#include "types.hpp" -#include "stack_reference.hpp" - -namespace sol { - namespace stack { - template <bool top_level> - struct push_popper_n { - lua_State* L; - int t; - push_popper_n(lua_State* luastate, int x) : L(luastate), t(x) { } - ~push_popper_n() { lua_pop(L, t); } - }; - template <> - struct push_popper_n<true> { - push_popper_n(lua_State*, int) { } - }; - template <bool top_level, typename T> - struct push_popper { - T t; - push_popper(T x) : t(x) { t.push(); } - ~push_popper() { t.pop(); } - }; - template <typename T> - struct push_popper<true, T> { - push_popper(T) {} - ~push_popper() {} - }; - template <bool top_level = false, typename T> - push_popper<top_level, T> push_pop(T&& x) { - return push_popper<top_level, T>(std::forward<T>(x)); - } - template <bool top_level = false> - push_popper_n<top_level> pop_n(lua_State* L, int x) { - return push_popper_n<top_level>(L, x); - } - } // stack - - namespace detail { - struct global_tag { } const global_{}; - } // detail - - class reference { - private: - lua_State* luastate = nullptr; // non-owning - int ref = LUA_NOREF; - - int copy() const noexcept { - if (ref == LUA_NOREF) - return LUA_NOREF; - push(); - return luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - - protected: - reference(lua_State* L, detail::global_tag) noexcept : luastate(L) { - lua_pushglobaltable(lua_state()); - ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - - int stack_index() const noexcept { - return -1; - } - - void deref() const noexcept { - luaL_unref(lua_state(), LUA_REGISTRYINDEX, ref); - } - - public: - reference() noexcept = default; - reference(lua_nil_t) noexcept : reference() {} - reference(const stack_reference& r) noexcept : reference(r.lua_state(), r.stack_index()) {} - reference(stack_reference&& r) noexcept : reference(r.lua_state(), r.stack_index()) {} - reference(lua_State* L, int index = -1) noexcept : luastate(L) { - lua_pushvalue(lua_state(), index); - ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - reference(lua_State* L, ref_index index) noexcept : luastate(L) { - lua_rawgeti(L, LUA_REGISTRYINDEX, index.index); - ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); - } - - ~reference() noexcept { - deref(); - } - - reference(reference&& o) noexcept { - luastate = o.luastate; - ref = o.ref; - - o.luastate = nullptr; - o.ref = LUA_NOREF; - } - - reference& operator=(reference&& o) noexcept { - luastate = o.luastate; - ref = o.ref; - - o.luastate = nullptr; - o.ref = LUA_NOREF; - - return *this; - } - - reference(const reference& o) noexcept { - luastate = o.luastate; - ref = o.copy(); - } - - reference& operator=(const reference& o) noexcept { - luastate = o.luastate; - deref(); - ref = o.copy(); - return *this; - } - - int push() const noexcept { - return push(lua_state()); - } - - int push(lua_State* Ls) const noexcept { - lua_rawgeti(Ls, LUA_REGISTRYINDEX, ref); - return 1; - } - - void pop() const noexcept { - pop(lua_state()); - } - - void pop(lua_State* Ls, int n = 1) const noexcept { - lua_pop(Ls, n); - } - - int registry_index() const noexcept { - return ref; - } - - bool valid() const noexcept { - return !(ref == LUA_NOREF || ref == LUA_REFNIL); - } - - explicit operator bool() const noexcept { - return valid(); - } - - type get_type() const noexcept { - auto pp = stack::push_pop(*this); - int result = lua_type(lua_state(), -1); - return static_cast<type>(result); - } - - lua_State* lua_state() const noexcept { - return luastate; - } - }; - - inline bool operator== (const reference& l, const reference& r) { - auto ppl = stack::push_pop(l); - auto ppr = stack::push_pop(r); - return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; - } - - inline bool operator!= (const reference& l, const reference& r) { - return !operator==(l, r); - } -} // sol - -#endif // SOL_REFERENCE_HPP diff --git a/3rdparty/sol2/sol/resolve.hpp b/3rdparty/sol2/sol/resolve.hpp deleted file mode 100644 index acd372dd772..00000000000 --- a/3rdparty/sol2/sol/resolve.hpp +++ /dev/null @@ -1,173 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_RESOLVE_HPP -#define SOL_RESOLVE_HPP - -#include "traits.hpp" -#include "tuple.hpp" - -namespace sol { - -#ifndef __clang__ - // constexpr is fine for not-clang - - namespace detail { - template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> - inline constexpr auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) { - using Sig = R(Args...); - typedef meta::unqualified_t<F> Fu; - return static_cast<Sig Fu::*>(&Fu::operator()); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline constexpr auto resolve_f(std::true_type, F&& f) - -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { - return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); - } - - template<typename F> - inline constexpr void resolve_f(std::false_type, F&&) { - static_assert(meta::has_deducible_signature<F>::value, - "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) { - return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f)); - } - - template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>> - inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { - return resolve_i(types<R(Args...)>(), std::forward<F>(f)); - } - - template<typename Sig, typename C> - inline constexpr Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { - return mem_func_ptr; - } - - template<typename Sig, typename C> - inline constexpr Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { - return mem_variable_ptr; - } - } // detail - - template<typename... Args, typename R> - inline constexpr auto resolve(R fun_ptr(Args...))->R(*)(Args...) { - return fun_ptr; - } - - template<typename Sig> - inline constexpr Sig* resolve(Sig* fun_ptr) { - return fun_ptr; - } - - template<typename... Args, typename R, typename C> - inline constexpr auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { - return mem_ptr; - } - - template<typename Sig, typename C> - inline constexpr Sig C::* resolve(Sig C::* mem_ptr) { - return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); - } - - template<typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler> - inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { - return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); - } -#else - - // Clang has distinct problems with constexpr arguments, - // so don't use the constexpr versions inside of clang. - - namespace detail { - template<typename R, typename... Args, typename F, typename = std::result_of_t<meta::unqualified_t<F>(Args...)>> - inline auto resolve_i(types<R(Args...)>, F&&)->R(meta::unqualified_t<F>::*)(Args...) { - using Sig = R(Args...); - typedef meta::unqualified_t<F> Fu; - return static_cast<Sig Fu::*>(&Fu::operator()); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline auto resolve_f(std::true_type, F&& f) - -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { - return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); - } - - template<typename F> - inline void resolve_f(std::false_type, F&&) { - static_assert(meta::has_deducible_signature<F>::value, - "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); - } - - template<typename F, typename U = meta::unqualified_t<F>> - inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature<U>(), std::forward<F>(f))) { - return resolve_f(meta::has_deducible_signature<U> {}, std::forward<F>(f)); - } - - template<typename... Args, typename F, typename R = std::result_of_t<F&(Args...)>> - inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { - return resolve_i(types<R(Args...)>(), std::forward<F>(f)); - } - - template<typename Sig, typename C> - inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { - return mem_func_ptr; - } - - template<typename Sig, typename C> - inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { - return mem_variable_ptr; - } - } // detail - - template<typename... Args, typename R> - inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) { - return fun_ptr; - } - - template<typename Sig> - inline Sig* resolve(Sig* fun_ptr) { - return fun_ptr; - } - - template<typename... Args, typename R, typename C> - inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { - return mem_ptr; - } - - template<typename Sig, typename C> - inline Sig C::* resolve(Sig C::* mem_ptr) { - return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); - } - - template<typename... Sig, typename F> - inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { - return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); - } - -#endif - -} // sol - -#endif // SOL_RESOLVE_HPP diff --git a/3rdparty/sol2/sol/simple_usertype_metatable.hpp b/3rdparty/sol2/sol/simple_usertype_metatable.hpp deleted file mode 100644 index 7570a32960b..00000000000 --- a/3rdparty/sol2/sol/simple_usertype_metatable.hpp +++ /dev/null @@ -1,559 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_SIMPLE_USERTYPE_METATABLE_HPP -#define SOL_SIMPLE_USERTYPE_METATABLE_HPP - -#include "usertype_metatable.hpp" -#include "object.hpp" -#include <vector> -#include <unordered_map> -#include <utility> - -namespace sol { - - namespace usertype_detail { - const lua_Integer toplevel_magic = static_cast<lua_Integer>(0x00000001); - - struct variable_wrapper { - virtual int index(lua_State* L) = 0; - virtual int new_index(lua_State* L) = 0; - virtual ~variable_wrapper() {}; - }; - - template <typename T, typename F> - struct callable_binding : variable_wrapper { - F fx; - - template <typename Arg> - callable_binding(Arg&& arg) : fx(std::forward<Arg>(arg)) {} - - virtual int index(lua_State* L) override { - return call_detail::call_wrapped<T, true, true>(L, fx); - } - - virtual int new_index(lua_State* L) override { - return call_detail::call_wrapped<T, false, true>(L, fx); - } - }; - - typedef std::unordered_map<std::string, std::unique_ptr<variable_wrapper>> variable_map; - typedef std::unordered_map<std::string, object> function_map; - - struct simple_map { - const char* metakey; - variable_map variables; - function_map functions; - base_walk indexbaseclasspropogation; - base_walk newindexbaseclasspropogation; - - simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} - }; - - template <typename T> - inline int simple_metatable_newindex(lua_State* L) { - int isnum = 0; - lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum); - if (isnum != 0 && magic == toplevel_magic) { - for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - break; - } - luaL_getmetatable(L, metakey); - int tableindex = lua_gettop(L); - if (type_of(L, tableindex) == type::lua_nil) { - continue; - } - stack::set_field<false, true>(L, stack_reference(L, 2), stack_reference(L, 3), tableindex); - } - lua_settop(L, 0); - return 0; - } - lua_pop(L, 1); - return indexing_fail<false>(L); - } - - template <bool is_index, bool toplevel = false> - inline int simple_core_indexing_call(lua_State* L) { - simple_map& sm = toplevel ? stack::get<user<simple_map>>(L, upvalue_index(1)) : stack::pop<user<simple_map>>(L); - variable_map& variables = sm.variables; - function_map& functions = sm.functions; - static const int keyidx = -2 + static_cast<int>(is_index); - if (toplevel) { - if (stack::get<type>(L, keyidx) != type::string) { - lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3)); - return indexingfunc(L); - } - } - string_detail::string_shim accessor = stack::get<string_detail::string_shim>(L, keyidx); - std::string accessorkey = accessor.c_str(); - auto vit = variables.find(accessorkey); - if (vit != variables.cend()) { - auto& varwrap = *(vit->second); - if (is_index) { - return varwrap.index(L); - } - return varwrap.new_index(L); - } - auto fit = functions.find(accessorkey); - if (fit != functions.cend()) { - auto& func = (fit->second); - return stack::push(L, func); - } - // Check table storage first for a method that works - luaL_getmetatable(L, sm.metakey); - if (type_of(L, -1) != type::lua_nil) { - stack::get_field<false, true>(L, accessor.c_str(), lua_gettop(L)); - if (type_of(L, -1) != type::lua_nil) { - // Woo, we found it? - lua_remove(L, -2); - return 1; - } - lua_pop(L, 1); - } - lua_pop(L, 1); - - int ret = 0; - bool found = false; - // Otherwise, we need to do propagating calls through the bases - if (is_index) { - sm.indexbaseclasspropogation(L, found, ret, accessor); - } - else { - sm.newindexbaseclasspropogation(L, found, ret, accessor); - } - if (found) { - return ret; - } - if (toplevel) { - lua_CFunction indexingfunc = is_index ? stack::get<lua_CFunction>(L, upvalue_index(2)) : stack::get<lua_CFunction>(L, upvalue_index(3)); - return indexingfunc(L); - } - return -1; - } - - inline int simple_real_index_call(lua_State* L) { - return simple_core_indexing_call<true, true>(L); - } - - inline int simple_real_new_index_call(lua_State* L) { - return simple_core_indexing_call<false, true>(L); - } - - inline int simple_index_call(lua_State* L) { - return detail::static_trampoline<(&simple_real_index_call)>(L); - } - - inline int simple_new_index_call(lua_State* L) { - return detail::static_trampoline<(&simple_real_new_index_call)>(L); - } - } - - struct simple_tag {} const simple{}; - - template <typename T> - struct simple_usertype_metatable : usertype_detail::registrar { - public: - usertype_detail::function_map registrations; - usertype_detail::variable_map varmap; - object callconstructfunc; - lua_CFunction indexfunc; - lua_CFunction newindexfunc; - lua_CFunction indexbase; - lua_CFunction newindexbase; - usertype_detail::base_walk indexbaseclasspropogation; - usertype_detail::base_walk newindexbaseclasspropogation; - void* baseclasscheck; - void* baseclasscast; - bool mustindex; - bool secondarymeta; - - template <typename N> - void insert(N&& n, object&& o) { - std::string key = usertype_detail::make_string(std::forward<N>(n)); - auto hint = registrations.find(key); - if (hint == registrations.cend()) { - registrations.emplace_hint(hint, std::move(key), std::move(o)); - return; - } - hint->second = std::move(o); - } - - template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> - void add_function(lua_State* L, N&& n, F&& f) { - insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f)))); - } - - template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler> - void add_function(lua_State* L, N&& n, F&& f) { - object o = make_object(L, std::forward<F>(f)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> - void add(lua_State* L, N&& n, F&& f) { - add_function(L, std::forward<N>(n), std::forward<F>(f)); - } - - template <typename N, typename F, meta::enable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler> - void add(lua_State*, N&& n, F&& f) { - mustindex = true; - secondarymeta = true; - std::string key = usertype_detail::make_string(std::forward<N>(n)); - auto o = std::make_unique<usertype_detail::callable_binding<T, std::decay_t<F>>>(std::forward<F>(f)); - auto hint = varmap.find(key); - if (hint == varmap.cend()) { - varmap.emplace_hint(hint, std::move(key), std::move(o)); - return; - } - hint->second = std::move(o); - } - - template <typename N, typename... Fxs> - void add(lua_State* L, N&& n, constructor_wrapper<Fxs...> c) { - object o(L, in_place<detail::tagged<T, constructor_wrapper<Fxs...>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N, typename... Lists> - void add(lua_State* L, N&& n, constructor_list<Lists...> c) { - object o(L, in_place<detail::tagged<T, constructor_list<Lists...>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N> - void add(lua_State* L, N&& n, destructor_wrapper<void> c) { - object o(L, in_place<detail::tagged<T, destructor_wrapper<void>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename N, typename Fx> - void add(lua_State* L, N&& n, destructor_wrapper<Fx> c) { - object o(L, in_place<detail::tagged<T, destructor_wrapper<Fx>>>, std::move(c)); - if (std::is_same<meta::unqualified_t<N>, call_construction>::value) { - callconstructfunc = std::move(o); - return; - } - insert(std::forward<N>(n), std::move(o)); - } - - template <typename... Bases> - void add(lua_State*, base_classes_tag, bases<Bases...>) { - static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report."); - if (sizeof...(Bases) < 1) { - return; - } - mustindex = true; - (void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... }; - - static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); - static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); - baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check; - baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast; - indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; - newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; - } - - private: - template<std::size_t... I, typename Tuple> - simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args) - : callconstructfunc(lua_nil), - indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>), - indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>), - indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>), - baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(false), secondarymeta(false) { - (void)detail::swallow{ 0, - (add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)... - }; - } - - template<typename... Args> - simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {} - - template<typename... Args> - simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) {} - - template<typename... Args> - simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward<Args>(args)...) {} - - public: - simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>>, decltype(default_constructor), usertype_detail::check_destructor_tag>()) {} - - template<typename Arg, typename... Args, meta::disable_any< - meta::any_same<meta::unqualified_t<Arg>, - usertype_detail::verified_tag, - usertype_detail::add_destructor_tag, - usertype_detail::check_destructor_tag - >, - meta::is_specialization_of<constructors, meta::unqualified_t<Arg>>, - meta::is_specialization_of<constructor_wrapper, meta::unqualified_t<Arg>> - > = meta::enabler> - simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward<Arg>(arg), std::forward<Args>(args)...) {} - - template<typename... Args, typename... CArgs> - simple_usertype_metatable(lua_State* L, constructors<CArgs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - template<typename... Args, typename... Fxs> - simple_usertype_metatable(lua_State* L, constructor_wrapper<Fxs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - virtual int push_um(lua_State* L) override { - return stack::push(L, std::move(*this)); - } - }; - - namespace stack { - template <typename T> - struct pusher<simple_usertype_metatable<T>> { - typedef simple_usertype_metatable<T> umt_t; - - static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { - static int uniqueness = 0; - std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); - // std::to_string doesn't exist in android still, with NDK, so this bullshit - // is necessary - // thanks, Android :v - int appended = snprintf(nullptr, 0, "%d", uniqueness); - std::size_t insertionpoint = uniquegcmetakey.length() - 1; - uniquegcmetakey.append(appended, '\0'); - char* uniquetarget = &uniquegcmetakey[insertionpoint]; - snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); - ++uniqueness; - - const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; - stack::push<user<usertype_detail::simple_map>>(L, metatable_key, uniquegcmetakey, &usertype_traits<T>::metatable()[0], - umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, - std::move(umx.varmap), std::move(umx.registrations) - ); - stack_reference stackvarmap(L, -1); - stack::set_field<true>(L, gcmetakey, stackvarmap); - stackvarmap.pop(); - - stack::get_field<true>(L, gcmetakey); - usertype_detail::simple_map& varmap = stack::pop<light<usertype_detail::simple_map>>(L); - return varmap; - } - - static int push(lua_State* L, umt_t&& umx) { - auto& varmap = make_cleanup(L, umx); - bool hasequals = false; - bool hasless = false; - bool haslessequals = false; - auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { - if (first == name_of(meta_function::equal_to)) { - hasequals = true; - } - else if (first == name_of(meta_function::less_than)) { - hasless = true; - } - else if (first == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - else if (first == name_of(meta_function::index)) { - umx.indexfunc = second.template as<lua_CFunction>(); - } - else if (first == name_of(meta_function::new_index)) { - umx.newindexfunc = second.template as<lua_CFunction>(); - } - switch (i) { - case 0: - if (first == name_of(meta_function::garbage_collect)) { - return; - } - break; - case 1: - if (first == name_of(meta_function::garbage_collect)) { - stack::set_field(L, first, detail::unique_destruct<T>, t.stack_index()); - return; - } - break; - case 2: - default: - break; - } - stack::set_field(L, first, second, t.stack_index()); - }; - for (std::size_t i = 0; i < 3; ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - break; - } - luaL_newmetatable(L, metakey); - stack_reference t(L, -1); - for (auto& kvp : varmap.functions) { - auto& first = std::get<0>(kvp); - auto& second = std::get<1>(kvp); - register_kvp(i, t, first, second); - } - luaL_Reg opregs[4]{}; - int opregsindex = 0; - if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); - usertype_detail::make_reg_op<T, std::less<>, meta::supports_op_less<T>>(opregs, opregsindex, name); - } - if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); - usertype_detail::make_reg_op<T, std::less_equal<>, meta::supports_op_less_equal<T>>(opregs, opregsindex, name); - } - if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); - usertype_detail::make_reg_op<T, std::conditional_t<meta::supports_op_equal<T>::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); - } - t.push(); - luaL_setfuncs(L, opregs, 0); - t.pop(); - - if (umx.baseclasscheck != nullptr) { - stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); - } - if (umx.baseclasscast != nullptr) { - stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); - } - - // Base class propagation features - stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); - stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); - - if (umx.mustindex) { - // use indexing function - stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), t.stack_index()); - stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), t.stack_index()); - } - else { - // Metatable indexes itself - stack::set_field(L, meta_function::index, t, t.stack_index()); - } - // metatable on the metatable - // for call constructor purposes and such - lua_createtable(L, 0, 2 * static_cast<int>(umx.secondarymeta) + static_cast<int>(umx.callconstructfunc.valid())); - stack_reference metabehind(L, -1); - if (umx.callconstructfunc.valid()) { - stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); - } - if (umx.secondarymeta) { - stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc - ), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - - t.pop(); - } - - // Now for the shim-table that actually gets pushed - luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); - stack_reference t(L, -1); - for (auto& kvp : varmap.functions) { - auto& first = std::get<0>(kvp); - auto& second = std::get<1>(kvp); - register_kvp(2, t, first, second); - } - { - lua_createtable(L, 0, 2 + static_cast<int>(umx.callconstructfunc.valid())); - stack_reference metabehind(L, -1); - if (umx.callconstructfunc.valid()) { - stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); - } - // use indexing function - stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex<T>, - usertype_detail::toplevel_magic - ), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, - make_light(varmap), - &usertype_detail::simple_index_call, - &usertype_detail::simple_metatable_newindex<T>, - usertype_detail::toplevel_magic - ), metabehind.stack_index()); - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - } - - // Don't pop the table when we're done; - // return it - return 1; - } - }; - } // stack -} // sol - -#endif // SOL_SIMPLE_USERTYPE_METATABLE_HPP diff --git a/3rdparty/sol2/sol/sol.hpp b/3rdparty/sol2/sol/sol.hpp new file mode 100644 index 00000000000..04fd7e4958d --- /dev/null +++ b/3rdparty/sol2/sol/sol.hpp @@ -0,0 +1,28916 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2022-06-25 08:14:19.151876 UTC +// This header was generated with sol v3.3.0 (revision eba86625) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_HPP +#define SOL_SINGLE_INCLUDE_HPP + +// beginning of sol/sol.hpp + +#ifndef SOL_HPP +#define SOL_HPP + +// beginning of sol/version.hpp + +#include <sol/config.hpp> + +#define SOL_VERSION_MAJOR 3 +#define SOL_VERSION_MINOR 2 +#define SOL_VERSION_PATCH 3 +#define SOL_VERSION_STRING "3.2.3" +#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) + +#define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN +#define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) + +#define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT +#define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) + +#define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) +#define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) +#define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) +#define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) + +#define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) +#define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) + +#define SOL_ON | +#define SOL_OFF ^ +#define SOL_DEFAULT_ON + +#define SOL_DEFAULT_OFF - + +#if defined(SOL_BUILD_CXX_MODE) + #if (SOL_BUILD_CXX_MODE != 0) + #define SOL_BUILD_CXX_MODE_I_ SOL_ON + #else + #define SOL_BUILD_CXX_MODE_I_ SOL_OFF + #endif +#elif defined(__cplusplus) + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_BUILD_C_MODE) + #if (SOL_BUILD_C_MODE != 0) + #define SOL_BUILD_C_MODE_I_ SOL_ON + #else + #define SOL_BUILD_C_MODE_I_ SOL_OFF + #endif +#elif defined(__STDC__) + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if SOL_IS_ON(SOL_BUILD_C_MODE) + #include <stddef.h> + #include <stdint.h> + #include <limits.h> +#else + #include <cstddef> + #include <cstdint> + #include <climits> +#endif + +#if defined(SOL_COMPILER_VCXX) + #if defined(SOL_COMPILER_VCXX != 0) + #define SOL_COMPILER_VCXX_I_ SOL_ON + #else + #define SOL_COMPILER_VCXX_I_ SOL_OFF + #endif +#elif defined(_MSC_VER) + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_GCC) + #if defined(SOL_COMPILER_GCC != 0) + #define SOL_COMPILER_GCC_I_ SOL_ON + #else + #define SOL_COMPILER_GCC_I_ SOL_OFF + #endif +#elif defined(__GNUC__) + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_CLANG) + #if defined(SOL_COMPILER_CLANG != 0) + #define SOL_COMPILER_CLANG_I_ SOL_ON + #else + #define SOL_COMPILER_CLANG_I_ SOL_OFF + #endif +#elif defined(__clang__) + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_EDG) + #if defined(SOL_COMPILER_EDG != 0) + #define SOL_COMPILER_EDG_I_ SOL_ON + #else + #define SOL_COMPILER_EDG_I_ SOL_OFF + #endif +#else + #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_MINGW) + #if (SOL_COMPILER_MINGW != 0) + #define SOL_COMPILER_MINGW_I_ SOL_ON + #else + #define SOL_COMPILER_MINGW_I_ SOL_OFF + #endif +#elif defined(__MINGW32__) + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF +#endif + +#if SIZE_MAX <= 0xFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_ON + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_OFF +#elif SIZE_MAX <= 0xFFFFFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_ON + #define SOL_PLATFORM_X64_I_ SOL_OFF +#else + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_ON +#endif + +#define SOL_PLATFORM_ARM32_I_ SOL_OFF +#define SOL_PLATFORM_ARM64_I_ SOL_OFF + +#if defined(SOL_PLATFORM_WINDOWS) + #if (SOL_PLATFORM_WINDOWS != 0) + #define SOL_PLATFORM_WINDOWS_I_ SOL_ON + #else + #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF + #endif +#elif defined(_WIN32) + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_CYGWIN) + #if (SOL_PLATFORM_CYGWIN != 0) + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #else + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #endif +#elif defined(__CYGWIN__) + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_APPLE) + #if (SOL_PLATFORM_APPLE != 0) + #define SOL_PLATFORM_APPLE_I_ SOL_ON + #else + #define SOL_PLATFORM_APPLE_I_ SOL_OFF + #endif +#elif defined(__APPLE__) + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_UNIX) + #if (SOL_PLATFORM_UNIX != 0) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF + #endif +#elif defined(__unix__) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_LINUX) + #if (SOL_PLATFORM_LINUX != 0) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF + #endif +#elif defined(__LINUX__) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF +#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF + +#if defined(SOL_IN_DEBUG_DETECTED) + #if SOL_IN_DEBUG_DETECTED != 0 + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#elif !defined(NDEBUG) + #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF +#endif // We are in a debug mode of some sort + +#if defined(SOL_NO_EXCEPTIONS) + #if (SOL_NO_EXCEPTIONS != 0) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPUNWIND) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__EXCEPTIONS) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#else + #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_RTTI) + #if (SOL_NO_RTTI != 0) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPRTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__GXX_RTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#else + #define SOL_RTTI_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_THREAD_LOCAL) + #if SOL_NO_THREAD_LOCAL != 0 + #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF + #else + #define SOL_USE_THREAD_LOCAL_I_ SOL_ON + #endif +#else + #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON +#endif // thread_local keyword is bjorked on some platforms + +#if defined(SOL_ALL_SAFETIES_ON) + #if SOL_ALL_SAFETIES_ON != 0 + #define SOL_ALL_SAFETIES_ON_I_ SOL_ON + #else + #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF + #endif +#else + #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_GETTER) + #if SOL_SAFE_GETTER != 0 + #define SOL_SAFE_GETTER_I_ SOL_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_GETTER_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_USERTYPE) + #if SOL_SAFE_USERTYPE != 0 + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_REFERENCES) + #if SOL_SAFE_REFERENCES != 0 + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTIONS) + #if SOL_SAFE_FUNCTIONS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#elif defined (SOL_SAFE_FUNCTION_OBJECTS) + #if SOL_SAFE_FUNCTION_OBJECTS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTION_CALLS) + #if SOL_SAFE_FUNCTION_CALLS != 0 + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_PROXIES) + #if SOL_SAFE_PROXIES != 0 + #define SOL_SAFE_PROXIES_I_ SOL_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_NUMERICS) + #if SOL_SAFE_NUMERICS != 0 + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_STACK_CHECK) + #if SOL_SAFE_STACK_CHECK != 0 + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_CHECK_NUMBER_PRECISION) + #if SOL_NO_CHECK_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) + #if SOL_NO_CHECKING_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_SAFE_NUMERICS) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_STRINGS_ARE_NUMBERS) + #if (SOL_STRINGS_ARE_NUMBERS != 0) + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON + #else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF + #endif +#else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ENABLE_INTEROP) + #if SOL_ENABLE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#elif defined(SOL_USE_INTEROP) + #if SOL_USE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#else + #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_NIL) + #if (SOL_NO_NIL != 0) + #define SOL_NIL_I_ SOL_OFF + #else + #define SOL_NIL_I_ SOL_ON + #endif +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) + #define SOL_NIL_I_ SOL_DEFAULT_OFF +#else + #define SOL_NIL_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USERTYPE_TYPE_BINDING_INFO) + #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON + #else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF + #endif +#else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON +#endif // We should generate a my_type.__type table with lots of class information for usertypes + +#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) + #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) + #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON +#endif // make is_automagical on/off by default + +#if defined(SOL_STD_VARIANT) + #if (SOL_STD_VARIANT != 0) + #define SOL_STD_VARIANT_I_ SOL_ON + #else + #define SOL_STD_VARIANT_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) + #if defined(__has_include) + #if __has_include(<variant>) + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #endif +#endif // make is_automagical on/off by default + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) + #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #endif +#else + #if defined(__cpp_noexcept_function_type) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) + // There is a bug in the VC++ compiler?? + // on /std:c++latest under x86 conditions (VS 15.5.2), + // compiler errors are tossed for noexcept markings being on function types + // that are identical in every other way to their non-noexcept marked types function types... + // VS 2019: There is absolutely a bug. + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON + #endif +#endif // noexcept is part of a function's type + +#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && SOL_STACK_STRING_OPTIMIZATION_SIZE > 0 + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE +#else + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 +#endif + +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_I_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_I_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_I_ 2048 +#endif + +#if defined(SOL_PRINT_ERRORS) + #if (SOL_PRINT_ERRORS != 0) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#endif + +#if defined(SOL_DEFAULT_PASS_ON_ERROR) + #if (SOL_DEFAULT_PASS_ON_ERROR != 0) + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON + #else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUA) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUA) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUA_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUAJIT) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUAJIT) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUAJIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_LUA_HPP) + #if (SOL_NO_LUA_HPP != 0) + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #else + #define SOL_USE_LUA_HPP_I_ SOL_ON + #endif +#elif defined(SOL_USING_CXX_LUA) + #define SOL_USE_LUA_HPP_I_ SOL_OFF +#elif defined(__has_include) + #if __has_include(<lua.hpp>) + #define SOL_USE_LUA_HPP_I_ SOL_ON + #else + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #endif +#else + #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_CONTAINERS_START) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START +#elif defined(SOL_CONTAINERS_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX +#elif defined(SOL_CONTAINER_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX +#else + #define SOL_CONTAINER_START_INDEX_I_ 1 +#endif + +#if defined (SOL_NO_MEMORY_ALIGNMENT) + #if (SOL_NO_MEMORY_ALIGNMENT != 0) + #define SOL_ALIGN_MEMORY_I_ SOL_OFF + #else + #define SOL_ALIGN_MEMORY_I_ SOL_ON + #endif +#else + #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USE_BOOST) + #if (SOL_USE_BOOST != 0) + #define SOL_USE_BOOST_I_ SOL_ON + #else + #define SOL_USE_BOOST_I_ SOL_OFF + #endif +#else + #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USE_UNSAFE_BASE_LOOKUP) + #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON + #else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF + #endif +#else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_INSIDE_UNREAL) + #if (SOL_INSIDE_UNREAL != 0) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF + #endif +#else + #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_COMPAT) + #if (SOL_NO_COMPAT != 0) + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF + #else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON + #endif +#else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) + #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON + #else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF + #endif +#else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON + #else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF + #endif +#else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_MINGW_CCTYPE_IS_POISONED) + #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON + #else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) + // MinGW is off its rocker in some places... + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON +#else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CHAR8_T) + #if (SOL_CHAR8_T != 0) + #define SOL_CHAR8_T_I_ SOL_ON + #else + #define SOL_CHAR8_T_I_ SOL_OFF + #endif +#else + #if defined(__cpp_char8_t) + #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON + #else + #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if SOL_IS_ON(SOL_USE_BOOST) + #include <boost/version.hpp> + + #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr + #else + #define SOL_BOOST_NONE_CONSTEXPR_I_ const + #endif // BOOST_VERSION +#else + // assume boost isn't using a garbage version + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr +#endif + +#if defined(SOL2_CI) + #if (SOL2_CI != 0) + #define SOL2_CI_I_ SOL_ON + #else + #define SOL2_CI_I_ SOL_OFF + #endif +#else + #define SOL2_CI_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_C_ASSERT) + #define SOL_USER_C_ASSERT_I_ SOL_ON +#else + #define SOL_USER_C_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_M_ASSERT) + #define SOL_USER_M_ASSERT_I_ SOL_ON +#else + #define SOL_USER_M_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +// beginning of sol/prologue.hpp + +#if defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." +#endif + +#define SOL_PROLOGUE_I_ 1 + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ ) + + #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) + #else + #include <type_traits> + + #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) + #endif +#endif + +// end of sol/prologue.hpp + +// beginning of sol/epilogue.hpp + +#if !defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue is missing from this translation unit." +#else + #undef SOL_PROLOGUE_I_ +#endif + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #undef _FWD + #undef _MOVE +#endif + +// end of sol/epilogue.hpp + +// beginning of sol/detail/build_version.hpp + +#if defined(SOL_DLL) + #if (SOL_DLL != 0) + #define SOL_DLL_I_ SOL_ON + #else + #define SOL_DLL_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) + #define SOL_DLL_I_ SOL_DEFAULT_ON +#else + #define SOL_DLL_I_ SOL_DEFAULT_OFF +#endif // DLL definition + +#if defined(SOL_HEADER_ONLY) + #if (SOL_HEADER_ONLY != 0) + #define SOL_HEADER_ONLY_I_ SOL_ON + #else + #define SOL_HEADER_ONLY_I_ SOL_OFF + #endif +#else + #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_BUILD) + #if (SOL_BUILD != 0) + #define SOL_BUILD_I_ SOL_ON + #else + #define SOL_BUILD_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_BUILD_I_ SOL_DEFAULT_OFF +#else + #define SOL_BUILD_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_UNITY_BUILD) + #if (SOL_UNITY_BUILD != 0) + #define SOL_UNITY_BUILD_I_ SOL_ON + #else + #define SOL_UNITY_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_C_FUNCTION_LINKAGE) + #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE +#else + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + // C++ + #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" + #else + // normal + #define SOL_C_FUNCTION_LINKAGE_I_ + #endif // C++ or not +#endif // Linkage specification for C functions + +#if defined(SOL_API_LINKAGE) + #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE +#else + #if SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) + // MSVC Compiler; or, Windows, or Cygwin platforms + #if SOL_IS_ON(SOL_BUILD) + // Building the library + #if SOL_IS_ON(SOL_COMPILER_GCC) + // Using GCC + #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) + #else + // Using Clang, MSVC, etc... + #define SOL_API_LINKAGE_I_ __declspec(dllexport) + #endif + #else + #if SOL_IS_ON(SOL_COMPILER_GCC) + #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) + #else + #define SOL_API_LINKAGE_I_ __declspec(dllimport) + #endif + #endif + #else + // extern if building normally on non-MSVC + #define SOL_API_LINKAGE_I_ extern + #endif + #elif SOL_IS_ON(SOL_UNITY_BUILD) + // Built-in library, like how stb typical works + #if SOL_IS_ON(SOL_HEADER_ONLY) + // Header only, so functions are defined "inline" + #define SOL_API_LINKAGE_I_ inline + #else + // Not header only, so seperately compiled files + #define SOL_API_LINKAGE_I_ extern + #endif + #else + // Normal static library + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define SOL_API_LINKAGE_I_ + #else + #define SOL_API_LINKAGE_I_ extern + #endif + #endif // DLL or not +#endif // Build definitions + +#if defined(SOL_PUBLIC_FUNC_DECL) + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL +#else + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DECL_) + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ +#else + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_PUBLIC_FUNC_DEF) + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF +#else + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DEF) + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF +#else + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_FUNC_DECL) + #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_FUNC_DEFN) + #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DEFN_I_ __declspec(dllexport) + #else + #define SOL_FUNC_DEFN_I_ __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DEFN_I_ + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DECL) + #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DEFN) + #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DEFN_I_ + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif +#endif + +// end of sol/detail/build_version.hpp + +// end of sol/version.hpp + +#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE) +#ifdef check +#pragma push_macro("check") +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wconversion" +#if __GNUC__ > 6 +#pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) +#elif SOL_IS_ON(SOL_COMPILER_VCXX) +#pragma warning(push) +#pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS +#endif // clang++ vs. g++ vs. VC++ + +// beginning of sol/forward.hpp + +#ifndef SOL_FORWARD_HPP +#define SOL_FORWARD_HPP + +#include <utility> +#include <type_traits> +#include <string_view> + +#if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT) +struct lua_State; +#else +extern "C" { +struct lua_State; +} +#endif // C++ Mangling for Lua vs. Not + +namespace sol { + + enum class type; + + class stateless_reference; + template <bool b> + class basic_reference; + using reference = basic_reference<false>; + using main_reference = basic_reference<true>; + class stateless_stack_reference; + class stack_reference; + + template <typename A> + class basic_bytecode; + + struct lua_value; + + struct proxy_base_tag; + template <typename> + struct proxy_base; + template <typename, typename> + struct table_proxy; + + template <bool, typename> + class basic_table_core; + template <bool b> + using table_core = basic_table_core<b, reference>; + template <bool b> + using main_table_core = basic_table_core<b, main_reference>; + template <bool b> + using stack_table_core = basic_table_core<b, stack_reference>; + template <typename base_type> + using basic_table = basic_table_core<false, base_type>; + using table = table_core<false>; + using global_table = table_core<true>; + using main_table = main_table_core<false>; + using main_global_table = main_table_core<true>; + using stack_table = stack_table_core<false>; + using stack_global_table = stack_table_core<true>; + + template <typename> + struct basic_lua_table; + using lua_table = basic_lua_table<reference>; + using stack_lua_table = basic_lua_table<stack_reference>; + + template <typename T, typename base_type> + class basic_usertype; + template <typename T> + using usertype = basic_usertype<T, reference>; + template <typename T> + using stack_usertype = basic_usertype<T, stack_reference>; + + template <typename base_type> + class basic_metatable; + using metatable = basic_metatable<reference>; + using stack_metatable = basic_metatable<stack_reference>; + + template <typename base_t> + struct basic_environment; + using environment = basic_environment<reference>; + using main_environment = basic_environment<main_reference>; + using stack_environment = basic_environment<stack_reference>; + + template <typename T, bool> + class basic_function; + template <typename T, bool, typename H> + class basic_protected_function; + using unsafe_function = basic_function<reference, false>; + using safe_function = basic_protected_function<reference, false, reference>; + using main_unsafe_function = basic_function<main_reference, false>; + using main_safe_function = basic_protected_function<main_reference, false, reference>; + using stack_unsafe_function = basic_function<stack_reference, false>; + using stack_safe_function = basic_protected_function<stack_reference, false, reference>; + using stack_aligned_unsafe_function = basic_function<stack_reference, true>; + using stack_aligned_safe_function = basic_protected_function<stack_reference, true, reference>; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; + using stack_aligned_function = stack_aligned_safe_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; + using stack_aligned_function = stack_aligned_unsafe_function; +#endif + using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template <typename base_t> + class basic_object_base; + template <typename base_t> + class basic_object; + template <typename base_t> + class basic_userdata; + template <typename base_t> + class basic_lightuserdata; + template <typename base_t> + class basic_coroutine; + template <typename base_t> + class basic_packaged_coroutine; + template <typename base_t> + class basic_thread; + + using object = basic_object<reference>; + using userdata = basic_userdata<reference>; + using lightuserdata = basic_lightuserdata<reference>; + using thread = basic_thread<reference>; + using coroutine = basic_coroutine<reference>; + using packaged_coroutine = basic_packaged_coroutine<reference>; + using main_object = basic_object<main_reference>; + using main_userdata = basic_userdata<main_reference>; + using main_lightuserdata = basic_lightuserdata<main_reference>; + using main_coroutine = basic_coroutine<main_reference>; + using stack_object = basic_object<stack_reference>; + using stack_userdata = basic_userdata<stack_reference>; + using stack_lightuserdata = basic_lightuserdata<stack_reference>; + using stack_thread = basic_thread<stack_reference>; + using stack_coroutine = basic_coroutine<stack_reference>; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + class state_view; + class state; + + template <typename T> + struct as_table_t; + template <typename T> + struct as_container_t; + template <typename T> + struct nested; + template <typename T> + struct light; + template <typename T> + struct user; + template <typename T> + struct as_args_t; + template <typename T> + struct protect_t; + template <typename F, typename... Policies> + struct policy_wrapper; + + template <typename T> + struct usertype_traits; + template <typename T> + struct unique_usertype_traits; + + template <typename... Args> + struct types { + typedef std::make_index_sequence<sizeof...(Args)> indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template <typename T> + struct derive : std::false_type { + typedef types<> type; + }; + + template <typename T> + struct base : std::false_type { + typedef types<> type; + }; + + template <typename T> + struct weak_derive { + static bool value; + }; + + template <typename T> + bool weak_derive<T>::value = false; + + namespace stack { + struct record; + } + +#if SOL_IS_OFF(SOL_USE_BOOST) + template <class T> + class optional; + + template <class T> + class optional<T&>; +#endif + + using check_handler_type = int(lua_State*, int, type, type, const char*); + +} // namespace sol + +#define SOL_BASE_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct base<T> : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() +#define SOL_DERIVED_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct derive<T> : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() + +#endif // SOL_FORWARD_HPP +// end of sol/forward.hpp + +// beginning of sol/forward_detail.hpp + +#ifndef SOL_FORWARD_DETAIL_HPP +#define SOL_FORWARD_DETAIL_HPP + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +// beginning of sol/base_traits.hpp + +#include <type_traits> + +namespace sol { + namespace detail { + struct unchecked_t { }; + const unchecked_t unchecked = unchecked_t {}; + } // namespace detail + + namespace meta { + using sfinae_yes_t = std::true_type; + using sfinae_no_t = std::false_type; + + template <typename...> + using void_t = void; + + template <typename T> + using unqualified = std::remove_cv<std::remove_reference_t<T>>; + + template <typename T> + using unqualified_t = typename unqualified<T>::type; + + namespace meta_detail { + template <typename T> + struct unqualified_non_alias : unqualified<T> { }; + + template <template <class...> class Test, class, class... Args> + struct is_detected : std::false_type { }; + + template <template <class...> class Test, class... Args> + struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type { }; + } // namespace meta_detail + + template <template <class...> class Trait, class... Args> + using is_detected = typename meta_detail::is_detected<Trait, void, Args...>::type; + + template <template <class...> class Trait, class... Args> + constexpr inline bool is_detected_v = is_detected<Trait, Args...>::value; + + template <std::size_t I> + using index_value = std::integral_constant<std::size_t, I>; + + template <bool> + struct conditional { + template <typename T, typename U> + using type = T; + }; + + template <> + struct conditional<false> { + template <typename T, typename U> + using type = U; + }; + + template <bool B, typename T, typename U> + using conditional_t = typename conditional<B>::template type<T, U>; + + namespace meta_detail { + template <typename T, template <typename...> class Templ> + struct is_specialization_of : std::false_type { }; + template <typename... T, template <typename...> class Templ> + struct is_specialization_of<Templ<T...>, Templ> : std::true_type { }; + } // namespace meta_detail + + template <typename T, template <typename...> class Templ> + using is_specialization_of = meta_detail::is_specialization_of<std::remove_cv_t<T>, Templ>; + + template <typename T, template <typename...> class Templ> + inline constexpr bool is_specialization_of_v = is_specialization_of<std::remove_cv_t<T>, Templ>::value; + + template <typename T> + struct identity { + typedef T type; + }; + + template <typename T> + using identity_t = typename identity<T>::type; + + template <typename T> + using is_builtin_type = std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value>; + + namespace meta_detail { + template <typename T, typename = void> + struct has_internal_marker_impl : std::false_type { }; + template <typename T> + struct has_internal_marker_impl<T, void_t<typename T::SOL_INTERNAL_UNSPECIALIZED_MARKER_>> : std::true_type { }; + + template <typename T> + using has_internal_marker = has_internal_marker_impl<T>; + + template <typename T> + constexpr inline bool has_internal_marker_v = has_internal_marker<T>::value; + } // namespace meta_detail + + } // namespace meta +} // namespace sol + +// end of sol/base_traits.hpp + +#include <tuple> +#include <cstddef> + +namespace sol { + namespace detail { + using swallow = std::initializer_list<int>; + } // namespace detail + + namespace meta { + template <typename T> + using is_tuple = is_specialization_of<T, std::tuple>; + + template <typename T> + constexpr inline bool is_tuple_v = is_tuple<T>::value; + + namespace detail { + template <typename... Args> + struct tuple_types_ { + typedef types<Args...> type; + }; + + template <typename... Args> + struct tuple_types_<std::tuple<Args...>> { + typedef types<Args...> type; + }; + } // namespace detail + + template <typename... Args> + using tuple_types = typename detail::tuple_types_<Args...>::type; + + template <typename Arg> + struct pop_front_type; + + template <typename Arg> + using pop_front_type_t = typename pop_front_type<Arg>::type; + + template <typename... Args> + struct pop_front_type<types<Args...>> { + typedef void front_type; + typedef types<Args...> type; + }; + + template <typename Arg, typename... Args> + struct pop_front_type<types<Arg, Args...>> { + typedef Arg front_type; + typedef types<Args...> type; + }; + + template <std::size_t N, typename Tuple> + using tuple_element = std::tuple_element<N, std::remove_reference_t<Tuple>>; + + template <std::size_t N, typename Tuple> + using tuple_element_t = std::tuple_element_t<N, std::remove_reference_t<Tuple>>; + + template <std::size_t N, typename Tuple> + using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>; + + template <std::size_t N, typename Tuple> + using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>; + + } // namespace meta +} // namespace sol + +// end of sol/tuple.hpp + +// beginning of sol/bind_traits.hpp + +namespace sol { namespace meta { + namespace meta_detail { + template <typename F> + using detect_deducible_signature = decltype(&F::operator()); + } // namespace meta_detail + + template <typename F> + using call_operator_deducible = typename is_detected<meta_detail::detect_deducible_signature, F>::type; + + template <typename F> + constexpr inline bool call_operator_deducible_v = call_operator_deducible<F>::value; + + namespace meta_detail { + + template <std::size_t I, typename T> + struct void_tuple_element : meta::tuple_element<I, T> { }; + + template <std::size_t I> + struct void_tuple_element<I, std::tuple<>> { + typedef void type; + }; + + template <std::size_t I, typename T> + using void_tuple_element_t = typename void_tuple_element<I, T>::type; + + template <bool it_is_noexcept, bool has_c_variadic, typename T, typename R, typename... Args> + struct basic_traits { + private: + using first_type = meta::conditional_t<std::is_void<T>::value, int, T>&; + + public: + inline static constexpr const bool is_noexcept = it_is_noexcept; + inline static constexpr bool is_member_function = std::is_void<T>::value; + inline static constexpr bool has_c_var_arg = has_c_variadic; + inline static constexpr std::size_t arity = sizeof...(Args); + inline static constexpr std::size_t free_arity = sizeof...(Args) + static_cast<std::size_t>(!std::is_void<T>::value); + typedef types<Args...> args_list; + typedef std::tuple<Args...> args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types<R> returns_list; + typedef R(function_type)(Args...); + typedef meta::conditional_t<std::is_void<T>::value, args_list, types<first_type, Args...>> free_args_list; + typedef meta::conditional_t<std::is_void<T>::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef meta::conditional_t<std::is_void<T>::value, R (*)(Args...), R (*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t<free_function_pointer_type> signature_type; + template <std::size_t i> + using arg_at = void_tuple_element_t<i, args_tuple>; + }; + + template <typename Signature, bool b = call_operator_deducible<Signature>::value> + struct fx_traits : public basic_traits<false, false, void, void> { }; + + // Free Functions + template <typename R, typename... Args> + struct fx_traits<R(Args...), false> : public basic_traits<false, false, void, R, Args...> { + typedef R (*function_pointer_type)(Args...); + }; + + template <typename R, typename... Args> + struct fx_traits<R (*)(Args...), false> : public basic_traits<false, false, void, R, Args...> { + typedef R (*function_pointer_type)(Args...); + }; + + template <typename R, typename... Args> + struct fx_traits<R(Args..., ...), false> : public basic_traits<false, true, void, R, Args...> { + typedef R (*function_pointer_type)(Args..., ...); + }; + + template <typename R, typename... Args> + struct fx_traits<R (*)(Args..., ...), false> : public basic_traits<false, true, void, R, Args...> { + typedef R (*function_pointer_type)(Args..., ...); + }; + + // Member Functions + /* C-Style Variadics */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...), false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...); + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...), false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const volatile, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const volatile; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const volatile, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile; + }; + + /* Member Function Qualifiers */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...)&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) &; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...)&, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) &; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const&, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const volatile&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const volatile&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const volatile&, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...)&&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) &&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...)&&, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) &&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const&&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const&&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const&&, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const&&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const volatile&&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const volatile&&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const volatile&&, false> : public basic_traits<false, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&&; + }; + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + + template <typename R, typename... Args> + struct fx_traits<R(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> { + typedef R (*function_pointer_type)(Args...) noexcept; + }; + + template <typename R, typename... Args> + struct fx_traits<R (*)(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> { + typedef R (*function_pointer_type)(Args...) noexcept; + }; + + template <typename R, typename... Args> + struct fx_traits<R(Args..., ...) noexcept, false> : public basic_traits<true, true, void, R, Args...> { + typedef R (*function_pointer_type)(Args..., ...) noexcept; + }; + + template <typename R, typename... Args> + struct fx_traits<R (*)(Args..., ...) noexcept, false> : public basic_traits<true, true, void, R, Args...> { + typedef R (*function_pointer_type)(Args..., ...) noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) noexcept; + }; + + /* Const Volatile */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const volatile noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const volatile noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const volatile noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...)& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) & noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...)& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) & noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const volatile& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const volatile& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const volatile& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...)&& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) && noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...)&& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) && noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const&& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const&& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const&& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const&& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args...) const volatile&& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args...) const volatile&& noexcept; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (T::*)(Args..., ...) const volatile&& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; + }; + +#endif // noexcept is part of a function's type + +#if SOL_IS_ON(SOL_COMPILER_VCXX) && SOL_IS_ON(SOL_PLATFORM_X86) + template <typename R, typename... Args> + struct fx_traits<R __stdcall(Args...), false> : public basic_traits<false, false, void, R, Args...> { + typedef R(__stdcall* function_pointer_type)(Args...); + }; + + template <typename R, typename... Args> + struct fx_traits<R(__stdcall*)(Args...), false> : public basic_traits<false, false, void, R, Args...> { + typedef R(__stdcall* function_pointer_type)(Args...); + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...), false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...); + }; + + /* Const Volatile */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const volatile, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile; + }; + + /* Member Function Qualifiers */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...)&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) &; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const volatile&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...)&&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) &&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const&&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&&; + }; + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const volatile&&, false> : public basic_traits<false, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&&; + }; + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + + template <typename R, typename... Args> + struct fx_traits<R __stdcall(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> { + typedef R(__stdcall* function_pointer_type)(Args...) noexcept; + }; + + template <typename R, typename... Args> + struct fx_traits<R(__stdcall*)(Args...) noexcept, false> : public basic_traits<true, false, void, R, Args...> { + typedef R(__stdcall* function_pointer_type)(Args...) noexcept; + }; + + /* __stdcall cannot be applied to functions with varargs*/ + /*template <typename R, typename... Args> + struct fx_traits<__stdcall R(Args..., ...) noexcept, false> : public basic_traits<true, true, void, R, Args...> { + typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; + }; + + template <typename R, typename... Args> + struct fx_traits<R (__stdcall *)(Args..., ...) noexcept, false> : public basic_traits<true, true, void, R, Args...> { + typedef R(__stdcall* function_pointer_type)(Args..., ...) noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) noexcept; + };*/ + + /* Const Volatile */ + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) const noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const volatile noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...)& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) & noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) & noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) & noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) const& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const& noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const volatile& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile& noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...)&& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) && noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) && noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) && noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const&& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const&& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) const&& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const&& noexcept; + };*/ + + template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args...) const volatile&& noexcept, false> : public basic_traits<true, false, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args...) const volatile&& noexcept; + }; + + /* __stdcall does not work with varargs */ + /*template <typename T, typename R, typename... Args> + struct fx_traits<R (__stdcall T::*)(Args..., ...) const volatile&& noexcept, false> : public basic_traits<true, true, T, R, Args...> { + typedef R (__stdcall T::*function_pointer_type)(Args..., ...) const volatile&& noexcept; + };*/ +#endif // noexcept is part of a function's type +#endif // __stdcall x86 VC++ bug + + template <typename Signature> + struct fx_traits<Signature, true> : public fx_traits<typename fx_traits<decltype(&Signature::operator())>::function_type, false> { }; + + template <typename Signature, bool b = std::is_member_object_pointer<Signature>::value> + struct callable_traits : public fx_traits<std::decay_t<Signature>> { }; + + template <typename R, typename T> + struct callable_traits<R(T::*), true> { + typedef meta::conditional_t<std::is_array_v<R>, std::add_lvalue_reference_t<R>, R> return_type; + typedef return_type Arg; + typedef T object_type; + using signature_type = R(T::*); + inline static constexpr bool is_noexcept = false; + inline static constexpr bool is_member_function = false; + inline static constexpr std::size_t arity = 1; + inline static constexpr std::size_t free_arity = 2; + typedef std::tuple<Arg> args_tuple; + typedef types<Arg> args_list; + typedef types<T, Arg> free_args_list; + typedef meta::tuple_types<return_type> returns_list; + typedef return_type(function_type)(T&, return_type); + typedef return_type (*function_pointer_type)(T&, Arg); + typedef return_type (*free_function_pointer_type)(T&, Arg); + template <std::size_t i> + using arg_at = void_tuple_element_t<i, args_tuple>; + }; + + } // namespace meta_detail + + template <typename Signature> + using bind_traits = meta_detail::callable_traits<Signature>; + + namespace meta_detail { + template <typename, bool> + struct is_probably_stateless_lambda : std::false_type { }; + + template <typename T> + struct is_probably_stateless_lambda<T, true> : std::is_convertible<T, typename bind_traits<T>::function_type*>::type { }; + } // namespace meta_detail + + template <typename T> + using is_probably_stateless_lambda = typename meta_detail::is_probably_stateless_lambda<T, std::is_empty_v<T> && call_operator_deducible_v<T>>::type; + + template <typename T> + inline constexpr bool is_probably_stateless_lambda_v = is_probably_stateless_lambda<T>::value; + + template <typename Signature> + using function_args_t = typename bind_traits<Signature>::args_list; + + template <typename Signature> + using function_signature_t = typename bind_traits<Signature>::signature_type; + + template <typename Signature> + using function_return_t = typename bind_traits<Signature>::return_type; +}} // namespace sol::meta + +// end of sol/bind_traits.hpp + +// beginning of sol/pointer_like.hpp + +#include <utility> +#include <type_traits> +#include <memory> + +namespace sol { + + namespace meta { + namespace meta_detail { + template <typename T> + using is_dereferenceable_test = decltype(*std::declval<T>()); + + template <typename T> + using is_explicitly_dereferenceable_test = decltype(std::declval<T>().operator*()); + } // namespace meta_detail + + template <typename T> + using is_pointer_like = std::integral_constant<bool, + !std::is_array_v<T> && (std::is_pointer_v<T> || is_detected_v<meta_detail::is_explicitly_dereferenceable_test, T>)>; + + template <typename T> + constexpr inline bool is_pointer_like_v = is_pointer_like<T>::value; + } // namespace meta + + namespace detail { + + template <typename T> + auto unwrap(T&& item) -> decltype(std::forward<T>(item)) { + return std::forward<T>(item); + } + + template <typename T> + T& unwrap(std::reference_wrapper<T> arg) { + return arg.get(); + } + + template <typename T> + inline decltype(auto) deref(T&& item) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::is_pointer_like_v<Tu>) { + return *std::forward<T>(item); + } + else { + return std::forward<T>(item); + } + } + + template <typename T> + inline decltype(auto) deref_move_only(T&& item) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::is_pointer_like_v<Tu> && !std::is_pointer_v<Tu> && !std::is_copy_constructible_v<Tu>) { + return *std::forward<T>(item); + } + else { + return std::forward<T>(item); + } + } + + template <typename T> + inline T* ptr(T& val) { + return std::addressof(val); + } + + template <typename T> + inline T* ptr(std::reference_wrapper<T> val) { + return std::addressof(val.get()); + } + + template <typename T> + inline T* ptr(T* val) { + return val; + } + } // namespace detail +} // namespace sol + +// end of sol/pointer_like.hpp + +// beginning of sol/string_view.hpp + +#include <cstddef> +#include <string> +#include <string_view> +#include <functional> + +namespace sol { + template <typename C, typename T = std::char_traits<C>> + using basic_string_view = std::basic_string_view<C, T>; + + typedef std::string_view string_view; + typedef std::wstring_view wstring_view; + typedef std::u16string_view u16string_view; + typedef std::u32string_view u32string_view; + typedef std::hash<std::string_view> string_view_hash; +} // namespace sol + +// end of sol/string_view.hpp + +#include <type_traits> +#include <cstdint> +#include <memory> +#include <functional> +#include <array> +#include <iterator> +#include <iosfwd> +#if SOL_IS_ON(SOL_STD_VARIANT) +#include <variant> +#endif // variant is weird on XCode, thanks XCode + +namespace sol { namespace meta { + template <typename T> + struct unwrapped { + typedef T type; + }; + + template <typename T> + struct unwrapped<std::reference_wrapper<T>> { + typedef T type; + }; + + template <typename T> + using unwrapped_t = typename unwrapped<T>::type; + + template <typename T> + struct unwrap_unqualified : unwrapped<unqualified_t<T>> { }; + + template <typename T> + using unwrap_unqualified_t = typename unwrap_unqualified<T>::type; + + template <typename T> + struct remove_member_pointer; + + template <typename R, typename T> + struct remove_member_pointer<R T::*> { + typedef R type; + }; + + template <typename R, typename T> + struct remove_member_pointer<R T::*const> { + typedef R type; + }; + + template <typename T> + using remove_member_pointer_t = remove_member_pointer<T>; + + template <typename T, typename...> + struct all_same : std::true_type { }; + + template <typename T, typename U, typename... Args> + struct all_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { }; + + template <typename T, typename...> + struct any_same : std::false_type { }; + + template <typename T, typename U, typename... Args> + struct any_same<T, U, Args...> : std::integral_constant<bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { }; + + template <typename T, typename... Args> + constexpr inline bool any_same_v = any_same<T, Args...>::value; + + template <bool B> + using boolean = std::integral_constant<bool, B>; + + template <bool B> + constexpr inline bool boolean_v = boolean<B>::value; + + template <typename T> + using neg = boolean<!T::value>; + + template <typename T> + constexpr inline bool neg_v = neg<T>::value; + + template <typename... Args> + struct all : boolean<true> { }; + + template <typename T, typename... Args> + struct all<T, Args...> : std::conditional_t<T::value, all<Args...>, boolean<false>> { }; + + template <typename... Args> + struct any : boolean<false> { }; + + template <typename T, typename... Args> + struct any<T, Args...> : std::conditional_t<T::value, boolean<true>, any<Args...>> { }; + + template <typename... Args> + constexpr inline bool all_v = all<Args...>::value; + + template <typename... Args> + constexpr inline bool any_v = any<Args...>::value; + + enum class enable_t { _ }; + + constexpr const auto enabler = enable_t::_; + + template <bool value, typename T = void> + using disable_if_t = std::enable_if_t<!value, T>; + + template <typename... Args> + using enable = std::enable_if_t<all<Args...>::value, enable_t>; + + template <typename... Args> + using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>; + + template <typename... Args> + using enable_any = std::enable_if_t<any<Args...>::value, enable_t>; + + template <typename... Args> + using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>; + + template <typename V, typename... Vs> + struct find_in_pack_v : boolean<false> { }; + + template <typename V, typename Vs1, typename... Vs> + struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { }; + + namespace meta_detail { + template <std::size_t I, typename T, typename... Args> + struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { }; + + template <std::size_t I, typename T, typename T1, typename... Args> + struct index_in_pack<I, T, T1, Args...> + : conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { }; + } // namespace meta_detail + + template <typename T, typename... Args> + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; + + template <typename T, typename List> + struct index_in : meta_detail::index_in_pack<0, T, List> { }; + + template <typename T, typename... Args> + struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> { }; + + template <std::size_t I, typename... Args> + struct at_in_pack { }; + + template <std::size_t I, typename... Args> + using at_in_pack_t = typename at_in_pack<I, Args...>::type; + + template <std::size_t I, typename Arg, typename... Args> + struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> { }; + + template <typename Arg, typename... Args> + struct at_in_pack<0, Arg, Args...> { + typedef Arg type; + }; + + namespace meta_detail { + template <typename, typename TI> + using on_even = meta::boolean<(TI::value % 2) == 0>; + + template <typename, typename TI> + using on_odd = meta::boolean<(TI::value % 2) == 1>; + + template <typename, typename> + using on_always = std::true_type; + + template <template <typename...> class When, std::size_t Limit, std::size_t I, template <typename...> class Pred, typename... Ts> + struct count_when_for_pack : std::integral_constant<std::size_t, 0> { }; + template <template <typename...> class When, std::size_t Limit, std::size_t I, template <typename...> class Pred, typename T, typename... Ts> + struct count_when_for_pack<When, Limit, I, Pred, T, Ts...> : conditional_t < sizeof...(Ts) + == 0 + || Limit<2, std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>, + count_when_for_pack<When, Limit - static_cast<std::size_t>(When<T, std::integral_constant<std::size_t, I>>::value), + I + static_cast<std::size_t>(When<T, std::integral_constant<std::size_t, I>>::value&& Pred<T>::value), Pred, Ts...>> { }; + } // namespace meta_detail + + template <template <typename...> class Pred, typename... Ts> + struct count_for_pack : meta_detail::count_when_for_pack<meta_detail::on_always, sizeof...(Ts), 0, Pred, Ts...> { }; + + template <template <typename...> class Pred, typename... Ts> + inline constexpr std::size_t count_for_pack_v = count_for_pack<Pred, Ts...>::value; + + template <template <typename...> class Pred, typename List> + struct count_for; + + template <template <typename...> class Pred, typename... Args> + struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> { }; + + template <std::size_t Limit, template <typename...> class Pred, typename... Ts> + struct count_for_to_pack : meta_detail::count_when_for_pack<meta_detail::on_always, Limit, 0, Pred, Ts...> { }; + + template <std::size_t Limit, template <typename...> class Pred, typename... Ts> + inline constexpr std::size_t count_for_to_pack_v = count_for_to_pack<Limit, Pred, Ts...>::value; + + template <template <typename...> class When, std::size_t Limit, template <typename...> class Pred, typename... Ts> + struct count_when_for_to_pack : meta_detail::count_when_for_pack<When, Limit, 0, Pred, Ts...> { }; + + template <template <typename...> class When, std::size_t Limit, template <typename...> class Pred, typename... Ts> + inline constexpr std::size_t count_when_for_to_pack_v = count_when_for_to_pack<When, Limit, Pred, Ts...>::value; + + template <template <typename...> class Pred, typename... Ts> + using count_even_for_pack = count_when_for_to_pack<meta_detail::on_even, sizeof...(Ts), Pred, Ts...>; + + template <template <typename...> class Pred, typename... Ts> + inline constexpr std::size_t count_even_for_pack_v = count_even_for_pack<Pred, Ts...>::value; + + template <template <typename...> class Pred, typename... Ts> + using count_odd_for_pack = count_when_for_to_pack<meta_detail::on_odd, sizeof...(Ts), Pred, Ts...>; + + template <template <typename...> class Pred, typename... Ts> + inline constexpr std::size_t count_odd_for_pack_v = count_odd_for_pack<Pred, Ts...>::value; + + template <typename... Args> + struct return_type { + typedef std::tuple<Args...> type; + }; + + template <typename T> + struct return_type<T> { + typedef T type; + }; + + template <> + struct return_type<> { + typedef void type; + }; + + template <typename... Args> + using return_type_t = typename return_type<Args...>::type; + + namespace meta_detail { + template <typename> + struct always_true : std::true_type { }; + struct is_invokable_tester { + template <typename Fun, typename... Args> + static always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int); + template <typename...> + static std::false_type test(...); + }; + } // namespace meta_detail + + template <typename T> + struct is_invokable; + template <typename Fun, typename... Args> + struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) { }; + + namespace meta_detail { + + template <typename T, typename = void> + struct is_invocable : std::is_function<std::remove_pointer_t<T>> { }; + + template <typename T> + struct is_invocable<T, + std::enable_if_t<std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value + && std::is_same<decltype(void(&T::operator())), void>::value>> { }; + + template <typename T> + struct is_invocable<T, + std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value + && std::is_destructible<unqualified_t<T>>::value>> { + struct F { + void operator()() {}; + }; + struct Derived : T, F { }; + template <typename U, U> + struct Check; + + template <typename V> + static sfinae_no_t test(Check<void (F::*)(), &V::operator()>*); + + template <typename> + static sfinae_yes_t test(...); + + static constexpr bool value = std::is_same_v<decltype(test<Derived>(0)), sfinae_yes_t>; + }; + + template <typename T> + struct is_invocable<T, + std::enable_if_t<!std::is_final<unqualified_t<T>>::value && std::is_class<unqualified_t<T>>::value + && !std::is_destructible<unqualified_t<T>>::value>> { + struct F { + void operator()() {}; + }; + struct Derived : T, F { + ~Derived() = delete; + }; + template <typename U, U> + struct Check; + + template <typename V> + static sfinae_no_t test(Check<void (F::*)(), &V::operator()>*); + + template <typename> + static sfinae_yes_t test(...); + + static constexpr bool value = std::is_same_v<decltype(test<Derived>(0)), sfinae_yes_t>; + }; + + struct has_begin_end_impl { + template <typename T, typename U = unqualified_t<T>, typename B = decltype(std::declval<U&>().begin()), + typename E = decltype(std::declval<U&>().end())> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_key_type_impl { + template <typename T, typename U = unqualified_t<T>, typename V = typename U::key_type> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_key_comp_impl { + template <typename T, typename V = decltype(std::declval<unqualified_t<T>>().key_comp())> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_load_factor_impl { + template <typename T, typename V = decltype(std::declval<unqualified_t<T>>().load_factor())> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_mapped_type_impl { + template <typename T, typename V = typename unqualified_t<T>::mapped_type> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_value_type_impl { + template <typename T, typename V = typename unqualified_t<T>::value_type> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_iterator_impl { + template <typename T, typename V = typename unqualified_t<T>::iterator> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + struct has_key_value_pair_impl { + template <typename T, typename U = unqualified_t<T>, typename V = typename U::value_type, typename F = decltype(std::declval<V&>().first), + typename S = decltype(std::declval<V&>().second)> + static std::true_type test(int); + + template <typename...> + static std::false_type test(...); + }; + + template <typename T> + struct has_push_back_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().push_back(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>; + }; + + template <typename T> + struct has_insert_with_iterator_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().insert( + std::declval<std::add_rvalue_reference_t<typename C::iterator>>(), std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>; + }; + + template <typename T> + struct has_insert_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().insert(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = !std::is_same_v<decltype(test<T>(0)), sfinae_no_t>; + }; + + template <typename T> + struct has_insert_after_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().insert_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>(), + std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>; + }; + + template <typename T> + struct has_size_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().size())*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>; + }; + + template <typename T> + struct has_max_size_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().max_size())*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>; + }; + + template <typename T> + struct has_to_string_test { + private: + template <typename C> + static sfinae_yes_t test(decltype(std::declval<C>().to_string())*); + template <typename C> + static sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), sfinae_yes_t>; + }; + + template <typename T, typename U, typename = void> + class supports_op_less_test : public std::false_type { }; + template <typename T, typename U> + class supports_op_less_test<T, U, void_t<decltype(std::declval<T&>() < std::declval<U&>())>> + : public std::integral_constant<bool, +#if SOL_IS_ON(SOL_STD_VARIANT) + !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant> +#else + true +#endif + > { + }; + + template <typename T, typename U, typename = void> + class supports_op_equal_test : public std::false_type { }; + template <typename T, typename U> + class supports_op_equal_test<T, U, void_t<decltype(std::declval<T&>() == std::declval<U&>())>> + : public std::integral_constant<bool, +#if SOL_IS_ON(SOL_STD_VARIANT) + !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant> +#else + true +#endif + > { + }; + + template <typename T, typename U, typename = void> + class supports_op_less_equal_test : public std::false_type { }; + template <typename T, typename U> + class supports_op_less_equal_test<T, U, void_t<decltype(std::declval<T&>() <= std::declval<U&>())>> + : public std::integral_constant<bool, +#if SOL_IS_ON(SOL_STD_VARIANT) + !is_specialization_of_v<unqualified_t<T>, std::variant> && !is_specialization_of_v<unqualified_t<U>, std::variant> +#else + true +#endif + > { + }; + + template <typename T, typename U, typename = void> + class supports_op_left_shift_test : public std::false_type { }; + template <typename T, typename U> + class supports_op_left_shift_test<T, U, void_t<decltype(std::declval<T&>() << std::declval<U&>())>> : public std::true_type { }; + + template <typename T, typename = void> + class supports_adl_to_string_test : public std::false_type { }; + template <typename T> + class supports_adl_to_string_test<T, void_t<decltype(to_string(std::declval<const T&>()))>> : public std::true_type { }; + + template <typename T, bool b> + struct is_matched_lookup_impl : std::false_type { }; + template <typename T> + struct is_matched_lookup_impl<T, true> : std::is_same<typename T::key_type, typename T::value_type> { }; + + template <typename T> + using non_void_t = meta::conditional_t<std::is_void_v<T>, ::sol::detail::unchecked_t, T>; + } // namespace meta_detail + + template <typename T, typename U = T> + class supports_op_less : public meta_detail::supports_op_less_test<T, U> { }; + + template <typename T, typename U = T> + class supports_op_equal : public meta_detail::supports_op_equal_test<T, U> { }; + + template <typename T, typename U = T> + class supports_op_less_equal : public meta_detail::supports_op_less_equal_test<T, U> { }; + + template <typename T, typename U = T> + class supports_op_left_shift : public meta_detail::supports_op_left_shift_test<T, U> { }; + + template <typename T> + class supports_adl_to_string : public meta_detail::supports_adl_to_string_test<T> { }; + + template <typename T> + class supports_to_string_member : public meta::boolean<meta_detail::has_to_string_test<meta_detail::non_void_t<T>>::value> { }; + + template <typename T> + using is_invocable = boolean<meta_detail::is_invocable<T>::value>; + + template <typename T> + constexpr inline bool is_invocable_v = is_invocable<T>::value; + + template <typename T> + struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) { }; + + template <typename T> + constexpr inline bool has_begin_end_v = has_begin_end<T>::value; + + template <typename T> + struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) { }; + + template <typename T> + struct has_key_type : decltype(meta_detail::has_key_type_impl::test<T>(0)) { }; + + template <typename T> + struct has_key_comp : decltype(meta_detail::has_key_comp_impl::test<T>(0)) { }; + + template <typename T> + struct has_load_factor : decltype(meta_detail::has_load_factor_impl::test<T>(0)) { }; + + template <typename T> + struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test<T>(0)) { }; + + template <typename T> + struct has_iterator : decltype(meta_detail::has_iterator_impl::test<T>(0)) { }; + + template <typename T> + struct has_value_type : decltype(meta_detail::has_value_type_impl::test<T>(0)) { }; + + template <typename T> + using has_push_back = meta::boolean<meta_detail::has_push_back_test<T>::value>; + + template <typename T> + using has_max_size = meta::boolean<meta_detail::has_max_size_test<T>::value>; + + template <typename T> + using has_insert = meta::boolean<meta_detail::has_insert_test<T>::value>; + + template <typename T> + using has_insert_with_iterator = meta::boolean<meta_detail::has_insert_with_iterator_test<T>::value>; + + template <typename T> + using has_insert_after = meta::boolean<meta_detail::has_insert_after_test<T>::value>; + + template <typename T> + using has_size = meta::boolean<meta_detail::has_size_test<T>::value>; + + template <typename T> + using is_associative = meta::all<has_key_type<T>, has_key_value_pair<T>, has_mapped_type<T>>; + + template <typename T> + using is_lookup = meta::all<has_key_type<T>, has_value_type<T>>; + + template <typename T> + using is_ordered = meta::all<has_key_comp<T>, meta::neg<has_load_factor<T>>>; + + template <typename T> + using is_matched_lookup = meta_detail::is_matched_lookup_impl<T, is_lookup<T>::value>; + + template <typename T> + using is_initializer_list = meta::is_specialization_of<T, std::initializer_list>; + + template <typename T> + constexpr inline bool is_initializer_list_v = is_initializer_list<T>::value; + + template <typename T, typename CharT = char> + using is_string_literal_array_of = boolean<std::is_array_v<T> && std::is_same_v<std::remove_all_extents_t<T>, CharT>>; + + template <typename T, typename CharT = char> + constexpr inline bool is_string_literal_array_of_v = is_string_literal_array_of<T, CharT>::value; + + template <typename T> + using is_string_literal_array = boolean<std::is_array_v<T> && any_same_v<std::remove_all_extents_t<T>, char, +#if SOL_IS_ON(SOL_CHAR8_T) + char8_t, +#endif + char16_t, char32_t, wchar_t>>; + + template <typename T> + constexpr inline bool is_string_literal_array_v = is_string_literal_array<T>::value; + + template <typename T, typename CharT> + struct is_string_of : std::false_type { }; + + template <typename CharT, typename CharTargetT, typename TraitsT, typename AllocT> + struct is_string_of<std::basic_string<CharT, TraitsT, AllocT>, CharTargetT> : std::is_same<CharT, CharTargetT> { }; + + template <typename T, typename CharT> + constexpr inline bool is_string_of_v = is_string_of<T, CharT>::value; + + template <typename T, typename CharT> + struct is_string_view_of : std::false_type { }; + + template <typename CharT, typename CharTargetT, typename TraitsT> + struct is_string_view_of<std::basic_string_view<CharT, TraitsT>, CharTargetT> : std::is_same<CharT, CharTargetT> { }; + + template <typename T, typename CharT> + constexpr inline bool is_string_view_of_v = is_string_view_of<T, CharT>::value; + + template <typename T> + using is_string_like + = meta::boolean<is_specialization_of_v<T, std::basic_string> || is_specialization_of_v<T, std::basic_string_view> || is_string_literal_array_v<T>>; + + template <typename T> + constexpr inline bool is_string_like_v = is_string_like<T>::value; + + template <typename T, typename CharT = char> + using is_string_constructible = meta::boolean< + is_string_literal_array_of_v<T, + CharT> || std::is_same_v<T, const CharT*> || std::is_same_v<T, CharT> || is_string_of_v<T, CharT> || std::is_same_v<T, std::initializer_list<CharT>> || is_string_view_of_v<T, CharT> || std::is_null_pointer_v<T>>; + + template <typename T, typename CharT = char> + constexpr inline bool is_string_constructible_v = is_string_constructible<T, CharT>::value; + + template <typename T> + using is_string_like_or_constructible = meta::boolean<is_string_like_v<T> || is_string_constructible_v<T>>; + + template <typename T> + struct is_pair : std::false_type { }; + + template <typename T1, typename T2> + struct is_pair<std::pair<T1, T2>> : std::true_type { }; + + template <typename T, typename Char> + using is_c_str_of = any<std::is_same<T, const Char*>, std::is_same<T, Char const* const>, std::is_same<T, Char*>, is_string_literal_array_of<T, Char>>; + + template <typename T, typename Char> + constexpr inline bool is_c_str_of_v = is_c_str_of<T, Char>::value; + + template <typename T> + using is_c_str = is_c_str_of<T, char>; + + template <typename T> + constexpr inline bool is_c_str_v = is_c_str<T>::value; + + template <typename T, typename Char> + using is_c_str_or_string_of = any<is_c_str_of<T, Char>, is_string_of<T, Char>>; + + template <typename T, typename Char> + constexpr inline bool is_c_str_or_string_of_v = is_c_str_or_string_of<T, Char>::value; + + template <typename T> + using is_c_str_or_string = is_c_str_or_string_of<T, char>; + + template <typename T> + constexpr inline bool is_c_str_or_string_v = is_c_str_or_string<T>::value; + + template <typename T> + struct is_move_only : all<neg<std::is_reference<T>>, neg<std::is_copy_constructible<unqualified_t<T>>>, std::is_move_constructible<unqualified_t<T>>> { }; + + template <typename T> + using is_not_move_only = neg<is_move_only<T>>; + + namespace meta_detail { + template <typename T> + decltype(auto) force_tuple(T&& x) { + if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::tuple>) { + return std::forward<T>(x); + } + else { + return std::tuple<T>(std::forward<T>(x)); + } + } + } // namespace meta_detail + + template <typename... X> + decltype(auto) tuplefy(X&&... x) { + return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...); + } + + template <typename T, typename = void> + struct iterator_tag { + using type = std::input_iterator_tag; + }; + + template <typename T> + struct iterator_tag<T, conditional_t<false, typename std::iterator_traits<T>::iterator_category, void>> { + using type = typename std::iterator_traits<T>::iterator_category; + }; + +}} // namespace sol::meta + +// end of sol/traits.hpp + +namespace sol { + namespace detail { + const bool default_safe_function_calls = +#if SOL_IS_ON(SOL_SAFE_FUNCTION_CALLS) + true; +#else + false; +#endif + } // namespace detail + + namespace meta { namespace meta_detail { + }} // namespace meta::meta_detail + + namespace stack { namespace stack_detail { + using undefined_method_func = void (*)(stack_reference); + + template <typename T> + void set_undefined_methods_on(stack_reference); + + struct undefined_metatable; + }} // namespace stack::stack_detail +} // namespace sol + +#endif // SOL_FORWARD_DETAIL_HPP +// end of sol/forward_detail.hpp + +// beginning of sol/assert.hpp + +#if SOL_IS_ON(SOL2_CI) + +struct pre_main { + pre_main() { +#ifdef _MSC_VER + _set_abort_behavior(0, _WRITE_ABORT_MSG); +#endif + } +} inline sol2_ci_dont_lock_ci_please = {}; + +#endif // Prevent lockup when doing Continuous Integration + +#if SOL_IS_ON(SOL_USER_C_ASSERT) + #define sol_c_assert(...) SOL_C_ASSERT(__VA_ARGS__) +#else + #if SOL_IS_ON(SOL_DEBUG_BUILD) + #include <exception> + #include <iostream> + #include <cstdlib> + + #define sol_c_assert(...) \ + do { \ + if (!(__VA_ARGS__)) { \ + std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << std::endl; \ + std::terminate(); \ + } \ + } while (false) + #else + #define sol_c_assert(...) \ + do { \ + if (false) { \ + (void)(__VA_ARGS__); \ + } \ + } while (false) + #endif +#endif + +#if SOL_IS_ON(SOL_USER_M_ASSERT) + #define sol_m_assert(message, ...) SOL_M_ASSERT(message, __VA_ARGS__) +#else + #if SOL_IS_ON(SOL_DEBUG_BUILD) + #include <exception> + #include <iostream> + #include <cstdlib> + + #define sol_m_assert(message, ...) \ + do { \ + if (!(__VA_ARGS__)) { \ + std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " << message << std::endl; \ + std::terminate(); \ + } \ + } while (false) + #else + #define sol_m_assert(message, ...) \ + do { \ + if (false) { \ + (void)(__VA_ARGS__); \ + (void)sizeof(message); \ + } \ + } while (false) + #endif +#endif + +// end of sol/assert.hpp + +// beginning of sol/bytecode.hpp + +// beginning of sol/compatibility.hpp + +// beginning of sol/compatibility/lua_version.hpp + +#if SOL_IS_ON(SOL_USE_CXX_LUA) + #include <lua.h> + #include <lualib.h> + #include <lauxlib.h> +#elif SOL_IS_ON(SOL_USE_LUA_HPP) + #include <lua.hpp> +#else + extern "C" { + #include <lua.h> + #include <lauxlib.h> + #include <lualib.h> + } +#endif // C++ Mangling for Lua vs. Not + +#if defined(SOL_LUAJIT) + #if (SOL_LUAJIT != 0) + #define SOL_USE_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_LUAJIT_I_ SOL_OFF + #endif +#elif defined(LUAJIT_VERSION) + #define SOL_USE_LUAJIT_I_ SOL_ON +#else + #define SOL_USE_LUAJIT_I_ SOL_DEFAULT_OFF +#endif // luajit + +#if SOL_IS_ON(SOL_USE_CXX_LUAJIT) + #include <luajit.h> +#elif SOL_IS_ON(SOL_USE_LUAJIT) + extern "C" { + #include <luajit.h> + } +#endif // C++ LuaJIT ... whatever that means + +#if defined(SOL_LUAJIT_VERSION) + #define SOL_LUAJIT_VERSION_I_ SOL_LUAJIT_VERSION +#elif SOL_IS_ON(SOL_USE_LUAJIT) + #define SOL_LUAJIT_VERSION_I_ LUAJIT_VERSION_NUM +#else + #define SOL_LUAJIT_VERSION_I_ 0 +#endif + +#if defined(SOL_LUAJIT_FFI_DISABLED) + #define SOL_LUAJIT_FFI_DISABLED_I_ SOL_ON +#elif defined(LUAJIT_DISABLE_FFI) + #define SOL_LUAJIT_FFI_DISABLED_I_ SOL_ON +#else + #define SOL_LUAJIT_FFI_DISABLED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(MOONJIT_VERSION) + #define SOL_USE_MOONJIT_I_ SOL_ON +#else + #define SOL_USE_MOONJIT_I_ SOL_OFF +#endif + +#if !defined(SOL_LUA_VERSION) + #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 + #define SOL_LUA_VERSION LUA_VERSION_NUM + #elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 + #define SOL_LUA_VERSION LUA_VERSION_NUM + #elif !defined(LUA_VERSION_NUM) || !(LUA_VERSION_NUM) + // Definitely 5.0 + #define SOL_LUA_VERSION 500 + #else + // ??? Not sure, assume latest? + #define SOL_LUA_VERSION 504 + #endif // Lua Version 503, 502, 501 || luajit, 500 +#endif // SOL_LUA_VERSION + +#if defined(SOL_LUA_VERSION) + #define SOL_LUA_VERSION_I_ SOL_LUA_VERSION +#else + #define SOL_LUA_VERSION_I_ 504 +#endif + +#if defined(SOL_EXCEPTIONS_ALWAYS_UNSAFE) + #if (SOL_EXCEPTIONS_ALWAYS_UNSAFE != 0) + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_ON + #endif +#elif defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) + #if (SOL_EXCEPTIONS_SAFE_PROPAGATION != 0) + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_ON + #else + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF + #endif +#elif SOL_LUAJIT_VERSION_I_ >= 20100 + // LuaJIT 2.1.0-beta3 and better have exception support locked in for all platforms (mostly) + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON +#elif SOL_LUAJIT_VERSION_I_ >= 20000 + // LuaJIT 2.0.x have exception support only on x64 builds + #if SOL_IS_ON(SOL_PLATFORM_X64) + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_ON + #else + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_OFF + #endif +#else + // otherwise, there is no exception safety for + // shoving exceptions through Lua and errors should + // always be serialized + #define SOL_PROPAGATE_EXCEPTIONS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_EXCEPTIONS_CATCH_ALL) + #if (SOL_EXCEPTIONS_CATCH_ALL != 0) + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_ON + #else + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_USE_LUAJIT) + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF + #elif SOL_IS_ON(SOL_USE_CXX_LUAJIT) + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF + #elif SOL_IS_ON(SOL_USE_CXX_LUA) + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_OFF + #else + #define SOL_EXCEPTIONS_CATCH_ALL_I_ SOL_DEFAULT_ON + #endif +#endif + +#if defined(SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE) + #if (SOL_LUAJIT_USE_EXCEPTION_TRAMPOLINE != 0) + #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON + #else + #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_OFF + #endif +#else + #if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) && SOL_IS_ON(SOL_USE_LUAJIT) + #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_ON + #else + #define SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_LUAL_STREAM_HAS_CLOSE_FUNCTION) + #if (SOL_LUAL_STREAM_HAS_CLOSE_FUNCTION != 0) + #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON + #else + #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_OFF + #endif +#else + #if SOL_IS_OFF(SOL_USE_LUAJIT) && (SOL_LUA_VERSION > 501) + #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_ON + #else + #define SOL_LUAL_STREAM_USE_CLOSE_FUNCTION_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined (SOL_LUA_BIT32_LIB) + #if SOL_LUA_BIT32_LIB != 0 + #define SOL_LUA_BIT32_LIB_I_ SOL_ON + #else + #define SOL_LUA_BIT32_LIB_I_ SOL_OFF + #endif +#else + // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) + // Lua 5.2, or other versions of Lua with the compat flag, or Lua that is not 5.2 with the specific define (5.4.1 either removed it entirely or broke it) + #if (SOL_LUA_VERSION_I_ == 502) || (defined(LUA_COMPAT_BITLIB) && (LUA_COMPAT_BITLIB != 0)) || (SOL_LUA_VERSION_I_ < 504 && (defined(LUA_COMPAT_5_2) && (LUA_COMPAT_5_2 != 0))) + #define SOL_LUA_BIT32_LIB_I_ SOL_ON + #else + #define SOL_LUA_BIT32_LIB_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined (SOL_LUA_NIL_IN_TABLES) + #if SOL_LUA_NIL_IN_TABLES != 0 + #define SOL_LUA_NIL_IN_TABLES_I_ SOL_ON + #else + #define SOL_LUA_NIL_IN_TABLES_I_ SOL_OFF + #endif +#else + #if defined(LUA_NILINTABLE) && (LUA_NILINTABLE != 0) + #define SOL_LUA_NIL_IN_TABLES_I_ SOL_DEFAULT_ON + #else + #define SOL_LUA_NIL_IN_TABLES_I_ SOL_DEFAULT_OFF + #endif +#endif + +// end of sol/compatibility/lua_version.hpp + +#if SOL_IS_ON(SOL_USE_COMPATIBILITY_LAYER) + +#if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT) +#ifndef COMPAT53_LUA_CPP +#define COMPAT53_LUA_CPP 1 +#endif // Build Lua Compat layer as C++ +#endif +#ifndef COMPAT53_INCLUDE_SOURCE +#define COMPAT53_INCLUDE_SOURCE 1 +#endif // Build Compat Layer Inline + +// beginning of sol/compatibility/compat-5.3.h + +#ifndef KEPLER_PROJECT_COMPAT53_H_ +#define KEPLER_PROJECT_COMPAT53_H_ + +#include <stddef.h> +#include <limits.h> +#include <string.h> +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +extern "C" { +#endif +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +} +#endif + +#ifndef COMPAT53_PREFIX +/* we chose this name because many other lua bindings / libs have +* their own compatibility layer, and that use the compat53 declaration +* frequently, causing all kinds of linker / compiler issues +*/ +# define COMPAT53_PREFIX kp_compat53 +#endif // COMPAT53_PREFIX + +#ifndef COMPAT53_API +# if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE +# if defined(__GNUC__) || defined(__clang__) +# define COMPAT53_API __attribute__((__unused__)) static inline +# else +# define COMPAT53_API static inline +# endif /* Clang/GCC */ +# else /* COMPAT53_INCLUDE_SOURCE */ +/* we are not including source, so everything is extern */ +# define COMPAT53_API extern +# endif /* COMPAT53_INCLUDE_SOURCE */ +#endif /* COMPAT53_PREFIX */ + +#define COMPAT53_CONCAT_HELPER(a, b) a##b +#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) + +/* declarations for Lua 5.1 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 + +/* XXX not implemented: +* lua_arith (new operators) +* lua_upvalueid +* lua_upvaluejoin +* lua_version +* lua_yieldk +*/ + +#ifndef LUA_OK +# define LUA_OK 0 +#endif +#ifndef LUA_OPADD +# define LUA_OPADD 0 +#endif +#ifndef LUA_OPSUB +# define LUA_OPSUB 1 +#endif +#ifndef LUA_OPMUL +# define LUA_OPMUL 2 +#endif +#ifndef LUA_OPDIV +# define LUA_OPDIV 3 +#endif +#ifndef LUA_OPMOD +# define LUA_OPMOD 4 +#endif +#ifndef LUA_OPPOW +# define LUA_OPPOW 5 +#endif +#ifndef LUA_OPUNM +# define LUA_OPUNM 6 +#endif +#ifndef LUA_OPEQ +# define LUA_OPEQ 0 +#endif +#ifndef LUA_OPLT +# define LUA_OPLT 1 +#endif +#ifndef LUA_OPLE +# define LUA_OPLE 2 +#endif + +/* LuaJIT/Lua 5.1 does not have the updated +* error codes for thread status/function returns (but some patched versions do) +* define it only if it's not found +*/ +#if !defined(LUA_ERRGCMM) +/* Use + 2 because in some versions of Lua (Lua 5.1) +* LUA_ERRFILE is defined as (LUA_ERRERR+1) +* so we need to avoid it (LuaJIT might have something at this +* integer value too) +*/ +# define LUA_ERRGCMM (LUA_ERRERR + 2) +#endif /* LUA_ERRGCMM define */ + +#if !defined(MOONJIT_VERSION) +typedef size_t lua_Unsigned; +#endif + +typedef struct luaL_Buffer_53 { + luaL_Buffer b; /* make incorrect code crash! */ + char *ptr; + size_t nelems; + size_t capacity; + lua_State *L2; +} luaL_Buffer_53; +#define luaL_Buffer luaL_Buffer_53 + +/* In PUC-Rio 5.1, userdata is a simple FILE* +* In LuaJIT, it's a struct where the first member is a FILE* +* We can't support the `closef` member +*/ +typedef struct luaL_Stream { + FILE *f; +} luaL_Stream; + +#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) +COMPAT53_API int lua_absindex(lua_State *L, int i); + +#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) +COMPAT53_API void lua_arith(lua_State *L, int op); + +#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) +COMPAT53_API int lua_compare(lua_State *L, int idx1, int idx2, int op); + +#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) +COMPAT53_API void lua_copy(lua_State *L, int from, int to); + +#define lua_getuservalue(L, i) \ + (lua_getfenv((L), (i)), lua_type((L), -1)) +#define lua_setuservalue(L, i) \ + (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i))) + +#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) +COMPAT53_API void lua_len(lua_State *L, int i); + +#define lua_pushstring(L, s) \ + (lua_pushstring((L), (s)), lua_tostring((L), -1)) + +#define lua_pushlstring(L, s, len) \ + ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1)) + +#ifndef luaL_newlibtable +# define luaL_newlibtable(L, l) \ + (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1)) +#endif +#ifndef luaL_newlib +# define luaL_newlib(L, l) \ + (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l))) +#endif + +#ifndef lua_pushglobaltable +# define lua_pushglobaltable(L) \ + lua_pushvalue((L), LUA_GLOBALSINDEX) +#endif +#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) +COMPAT53_API int lua_rawgetp(lua_State *L, int i, const void *p); + +#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) +COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); + +#define lua_rawlen(L, i) lua_objlen((L), (i)) + +#define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL) + +#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) +COMPAT53_API lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); + +#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) +COMPAT53_API void luaL_checkversion(lua_State *L); + +#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) +COMPAT53_API int lua_load(lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); + +#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) +COMPAT53_API int luaL_loadfilex(lua_State *L, const char *filename, const char *mode); + +#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) +COMPAT53_API int luaL_loadbufferx(lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); + +#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) +COMPAT53_API void luaL_checkstack(lua_State *L, int sp, const char *msg); + +#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) +COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char *name); + +#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) +COMPAT53_API lua_Integer luaL_len(lua_State *L, int i); + +#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) +COMPAT53_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); + +#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) +COMPAT53_API void luaL_setmetatable(lua_State *L, const char *tname); + +#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) +COMPAT53_API void *luaL_testudata(lua_State *L, int i, const char *tname); + +#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) +COMPAT53_API void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); + +#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) +COMPAT53_API int luaL_fileresult(lua_State *L, int stat, const char *fname); + +#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult) +COMPAT53_API int luaL_execresult(lua_State *L, int stat); + +#define lua_callk(L, na, nr, ctx, cont) \ + ((void)(ctx), (void)(cont), lua_call((L), (na), (nr))) +#define lua_pcallk(L, na, nr, err, ctx, cont) \ + ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err))) + +#define lua_resume(L, from, nargs) \ + ((void)(from), lua_resume((L), (nargs))) + +#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) +COMPAT53_API void luaL_buffinit(lua_State *L, luaL_Buffer_53 *B); + +#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) +COMPAT53_API char *luaL_prepbuffsize(luaL_Buffer_53 *B, size_t s); + +#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) +COMPAT53_API void luaL_addlstring(luaL_Buffer_53 *B, const char *s, size_t l); + +#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) +COMPAT53_API void luaL_addvalue(luaL_Buffer_53 *B); + +#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) +COMPAT53_API void luaL_pushresult(luaL_Buffer_53 *B); + +#undef luaL_buffinitsize +#define luaL_buffinitsize(L, B, s) \ + (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s))) + +#undef luaL_prepbuffer +#define luaL_prepbuffer(B) \ + luaL_prepbuffsize((B), LUAL_BUFFERSIZE) + +#undef luaL_addchar +#define luaL_addchar(B, c) \ + ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \ + ((B)->ptr[(B)->nelems++] = (c))) + +#undef luaL_addsize +#define luaL_addsize(B, s) \ + ((B)->nelems += (s)) + +#undef luaL_addstring +#define luaL_addstring(B, s) \ + luaL_addlstring((B), (s), strlen((s))) + +#undef luaL_pushresultsize +#define luaL_pushresultsize(B, s) \ + (luaL_addsize((B), (s)), luaL_pushresult((B))) + +#if defined(LUA_COMPAT_APIINTCASTS) +#define lua_pushunsigned(L, n) \ + lua_pushinteger((L), (lua_Integer)(n)) +#define lua_tounsignedx(L, i, is) \ + ((lua_Unsigned)lua_tointegerx((L), (i), (is))) +#define lua_tounsigned(L, i) \ + lua_tounsignedx((L), (i), NULL) +#define luaL_checkunsigned(L, a) \ + ((lua_Unsigned)luaL_checkinteger((L), (a))) +#define luaL_optunsigned(L, a, d) \ + ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d))) +#endif + +#endif /* Lua 5.1 only */ + +/* declarations for Lua 5.1 and 5.2 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 + +typedef int lua_KContext; + +typedef int(*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); + +#define lua_dump(L, w, d, s) \ + ((void)(s), lua_dump((L), (w), (d))) + +#define lua_getfield(L, i, k) \ + (lua_getfield((L), (i), (k)), lua_type((L), -1)) + +#define lua_gettable(L, i) \ + (lua_gettable((L), (i)), lua_type((L), -1)) + +#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) +COMPAT53_API int lua_geti(lua_State *L, int index, lua_Integer i); + +#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) +COMPAT53_API int lua_isinteger(lua_State *L, int index); + +#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53) +COMPAT53_API lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); + +#define lua_numbertointeger(n, p) \ + ((*(p) = (lua_Integer)(n)), 1) + +#define lua_rawget(L, i) \ + (lua_rawget((L), (i)), lua_type((L), -1)) + +#define lua_rawgeti(L, i, n) \ + (lua_rawgeti((L), (i), (n)), lua_type((L), -1)) + +#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) +COMPAT53_API void lua_rotate(lua_State *L, int idx, int n); + +#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) +COMPAT53_API void lua_seti(lua_State *L, int index, lua_Integer i); + +#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) +COMPAT53_API size_t lua_stringtonumber(lua_State *L, const char *s); + +#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) +COMPAT53_API const char *luaL_tolstring(lua_State *L, int idx, size_t *len); + +#define luaL_getmetafield(L, o, e) \ + (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL) + +#define luaL_newmetatable(L, tn) \ + (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0) + +#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) +COMPAT53_API void luaL_requiref(lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +#endif /* Lua 5.1 and Lua 5.2 */ + +/* declarations for Lua 5.2 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 + +/* XXX not implemented: +* lua_isyieldable +* lua_getextraspace +* lua_arith (new operators) +* lua_pushfstring (new formats) +*/ + +#define lua_getglobal(L, n) \ + (lua_getglobal((L), (n)), lua_type((L), -1)) + +#define lua_getuservalue(L, i) \ + (lua_getuservalue((L), (i)), lua_type((L), -1)) + +#define lua_pushlstring(L, s, len) \ + (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))) + +#define lua_rawgetp(L, i, p) \ + (lua_rawgetp((L), (i), (p)), lua_type((L), -1)) + +#define LUA_KFUNCTION(_name) \ + static int (_name)(lua_State *L, int status, lua_KContext ctx); \ + static int (_name ## _52)(lua_State *L) { \ + lua_KContext ctx; \ + int status = lua_getctx(L, &ctx); \ + return (_name)(L, status, ctx); \ + } \ + static int (_name)(lua_State *L, int status, lua_KContext ctx) + +#define lua_pcallk(L, na, nr, err, ctx, cont) \ + lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52) + +#define lua_callk(L, na, nr, ctx, cont) \ + lua_callk((L), (na), (nr), (ctx), cont ## _52) + +#define lua_yieldk(L, nr, ctx, cont) \ + lua_yieldk((L), (nr), (ctx), cont ## _52) + +#ifdef lua_call +# undef lua_call +# define lua_call(L, na, nr) \ + (lua_callk)((L), (na), (nr), 0, NULL) +#endif + +#ifdef lua_pcall +# undef lua_pcall +# define lua_pcall(L, na, nr, err) \ + (lua_pcallk)((L), (na), (nr), (err), 0, NULL) +#endif + +#ifdef lua_yield +# undef lua_yield +# define lua_yield(L, nr) \ + (lua_yieldk)((L), (nr), 0, NULL) +#endif + +#endif /* Lua 5.2 only */ + +/* other Lua versions */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504 + +# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)" + +#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */ + +/* helper macro for defining continuation functions (for every version +* *except* Lua 5.2) */ +#ifndef LUA_KFUNCTION +#define LUA_KFUNCTION(_name) \ + static int (_name)(lua_State *L, int status, lua_KContext ctx) +#endif + +#if defined(COMPAT53_INCLUDE_SOURCE) && COMPAT53_INCLUDE_SOURCE == 1 +// beginning of sol/compatibility/compat-5.3.c.h + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> + +/* don't compile it again if it already is included via compat53.h */ +#ifndef KEPLER_PROJECT_COMPAT53_C_ +#define KEPLER_PROJECT_COMPAT53_C_ + +/* definitions for Lua 5.1 only */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 + +#ifndef COMPAT53_FOPEN_NO_LOCK +#if defined(_MSC_VER) +#define COMPAT53_FOPEN_NO_LOCK 1 +#else /* otherwise */ +#define COMPAT53_FOPEN_NO_LOCK 0 +#endif /* VC++ only so far */ +#endif /* No-lock fopen_s usage if possible */ + +#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK +#include <share.h> +#endif /* VC++ _fsopen for share-allowed file read */ + +#ifndef COMPAT53_HAVE_STRERROR_R +#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || (!defined(__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) +#define COMPAT53_HAVE_STRERROR_R 1 +#else /* none of the defines matched: define to 0 */ +#define COMPAT53_HAVE_STRERROR_R 0 +#endif /* have strerror_r of some form */ +#endif /* strerror_r */ + +#ifndef COMPAT53_HAVE_STRERROR_S +#if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || (defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) +#define COMPAT53_HAVE_STRERROR_S 1 +#else /* not VC++ or C11 */ +#define COMPAT53_HAVE_STRERROR_S 0 +#endif /* strerror_s from VC++ or C11 */ +#endif /* strerror_s */ + +#ifndef COMPAT53_LUA_FILE_BUFFER_SIZE +#define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 +#endif /* Lua File Buffer Size */ + +static char* compat53_strerror(int en, char* buff, size_t sz) { +#if COMPAT53_HAVE_STRERROR_R + /* use strerror_r here, because it's available on these specific platforms */ + if (sz > 0) { + buff[0] = '\0'; + /* we don't care whether the GNU version or the XSI version is used: */ + if (strerror_r(en, buff, sz)) { + /* Yes, we really DO want to ignore the return value! + * GCC makes that extra hard, not even a (void) cast will do. */ + } + if (buff[0] == '\0') { + /* Buffer is unchanged, so we probably have called GNU strerror_r which + * returned a static constant string. Chances are that strerror will + * return the same static constant string and therefore be thread-safe. */ + return strerror(en); + } + } + return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ +#elif COMPAT53_HAVE_STRERROR_S + /* for MSVC and other C11 implementations, use strerror_s since it's + * provided by default by the libraries */ + strerror_s(buff, sz, en); + return buff; +#else + /* fallback, but strerror is not guaranteed to be threadsafe due to modifying + * errno itself and some impls not locking a static buffer for it ... but most + * known systems have threadsafe errno: this might only change if the locale + * is changed out from under someone while this function is being called */ + (void)buff; + (void)sz; + return strerror(en); +#endif +} + +COMPAT53_API int lua_absindex(lua_State* L, int i) { + if (i < 0 && i > LUA_REGISTRYINDEX) + i += lua_gettop(L) + 1; + return i; +} + +static void compat53_call_lua(lua_State* L, char const code[], size_t len, int nargs, int nret) { + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, code, len, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); + } + lua_insert(L, -nargs - 1); + lua_call(L, nargs, nret); +} + +COMPAT53_API void lua_arith(lua_State* L, int op) { + static const char compat53_arith_code[] + = "local op,a,b=...\n" + "if op==0 then return a+b\n" + "elseif op==1 then return a-b\n" + "elseif op==2 then return a*b\n" + "elseif op==3 then return a/b\n" + "elseif op==4 then return a%b\n" + "elseif op==5 then return a^b\n" + "elseif op==6 then return -a\n" + "end\n"; + + if (op < LUA_OPADD || op > LUA_OPUNM) + luaL_error(L, "invalid 'op' argument for lua_arith"); + luaL_checkstack(L, 5, "not enough stack slots"); + if (op == LUA_OPUNM) + lua_pushvalue(L, -1); + lua_pushnumber(L, op); + lua_insert(L, -3); + compat53_call_lua(L, compat53_arith_code, sizeof(compat53_arith_code) - 1, 3, 1); +} + +COMPAT53_API int lua_compare(lua_State* L, int idx1, int idx2, int op) { + static const char compat53_compare_code[] + = "local a,b=...\n" + "return a<=b\n"; + + int result = 0; + switch (op) { + case LUA_OPEQ: + return lua_equal(L, idx1, idx2); + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + case LUA_OPLE: + luaL_checkstack(L, 5, "not enough stack slots"); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + compat53_call_lua(L, compat53_compare_code, sizeof(compat53_compare_code) - 1, 2, 1); + result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + default: + luaL_error(L, "invalid 'op' argument for lua_compare"); + } + return 0; +} + +COMPAT53_API void lua_copy(lua_State* L, int from, int to) { + int abs_to = lua_absindex(L, to); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, from); + lua_replace(L, abs_to); +} + +COMPAT53_API void lua_len(lua_State* L, int i) { + switch (lua_type(L, i)) { + case LUA_TSTRING: + lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); + break; + case LUA_TTABLE: + if (!luaL_callmeta(L, i, "__len")) + lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); + break; + case LUA_TUSERDATA: + if (luaL_callmeta(L, i, "__len")) + break; + /* FALLTHROUGH */ + default: + luaL_error(L, "attempt to get length of a %s value", lua_typename(L, lua_type(L, i))); + } +} + +COMPAT53_API int lua_rawgetp(lua_State* L, int i, const void* p) { + int abs_i = lua_absindex(L, i); + lua_pushlightuserdata(L, (void*)p); + lua_rawget(L, abs_i); + return lua_type(L, -1); +} + +COMPAT53_API void lua_rawsetp(lua_State* L, int i, const void* p) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, (void*)p); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + +COMPAT53_API lua_Number lua_tonumberx(lua_State* L, int i, int* isnum) { + lua_Number n = lua_tonumber(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +COMPAT53_API void luaL_checkversion(lua_State* L) { + (void)L; +} + +COMPAT53_API void luaL_checkstack(lua_State* L, int sp, const char* msg) { + if (!lua_checkstack(L, sp + LUA_MINSTACK)) { + if (msg != NULL) + luaL_error(L, "stack overflow (%s)", msg); + else { + lua_pushliteral(L, "stack overflow"); + lua_error(L); + } + } +} + +COMPAT53_API int luaL_getsubtable(lua_State* L, int i, const char* name) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushstring(L, name); + lua_gettable(L, abs_i); + if (lua_istable(L, -1)) + return 1; + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + +COMPAT53_API lua_Integer luaL_len(lua_State* L, int i) { + lua_Integer res = 0; + int isnum = 0; + luaL_checkstack(L, 1, "not enough stack slots"); + lua_len(L, i); + res = lua_tointegerx(L, -1, &isnum); + lua_pop(L, 1); + if (!isnum) + luaL_error(L, "object length is not an integer"); + return res; +} + +COMPAT53_API void luaL_setfuncs(lua_State* L, const luaL_Reg* l, int nup) { + luaL_checkstack(L, nup + 1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ + } + lua_pop(L, nup); /* remove upvalues */ +} + +COMPAT53_API void luaL_setmetatable(lua_State* L, const char* tname) { + luaL_checkstack(L, 1, "not enough stack slots"); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +COMPAT53_API void* luaL_testudata(lua_State* L, int i, const char* tname) { + void* p = lua_touserdata(L, i); + luaL_checkstack(L, 2, "not enough stack slots"); + if (p == NULL || !lua_getmetatable(L, i)) + return NULL; + else { + int res = 0; + luaL_getmetatable(L, tname); + res = lua_rawequal(L, -1, -2); + lua_pop(L, 2); + if (!res) + p = NULL; + } + return p; +} + +static int compat53_countlevels(lua_State* L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { + li = le; + le *= 2; + } + /* do a binary search */ + while (li < le) { + int m = (li + le) / 2; + if (lua_getstack(L, m, &ar)) + li = m + 1; + else + le = m; + } + return le - 1; +} + +static int compat53_findfield(lua_State* L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + +static int compat53_pushglobalfuncname(lua_State* L, lua_Debug* ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (compat53_findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +static void compat53_pushfuncname(lua_State* L, lua_Debug* ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (compat53_pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + +#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ +#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ + +COMPAT53_API void luaL_traceback(lua_State* L, lua_State* L1, const char* msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = compat53_countlevels(L1); + int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; + if (msg) + lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + compat53_pushfuncname(L, &ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +COMPAT53_API int luaL_fileresult(lua_State* L, int stat, const char* fname) { + const char* serr = NULL; + int en = errno; /* calls to Lua API may change this value */ + char buf[512] = { 0 }; + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + serr = compat53_strerror(en, buf, sizeof(buf)); + if (fname) + lua_pushfstring(L, "%s: %s", fname, serr); + else + lua_pushstring(L, serr); + lua_pushnumber(L, (lua_Number)en); + return 3; + } +} + +static int compat53_checkmode(lua_State* L, const char* mode, const char* modename, int err) { + if (mode && strchr(mode, modename[0]) == NULL) { + lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); + return err; + } + return LUA_OK; +} + +typedef struct { + lua_Reader reader; + void* ud; + int has_peeked_data; + const char* peeked_data; + size_t peeked_data_size; +} compat53_reader_data; + +static const char* compat53_reader(lua_State* L, void* ud, size_t* size) { + compat53_reader_data* data = (compat53_reader_data*)ud; + if (data->has_peeked_data) { + data->has_peeked_data = 0; + *size = data->peeked_data_size; + return data->peeked_data; + } + else + return data->reader(L, data->ud, size); +} + +COMPAT53_API int lua_load(lua_State* L, lua_Reader reader, void* data, const char* source, const char* mode) { + int status = LUA_OK; + compat53_reader_data compat53_data = { reader, data, 1, 0, 0 }; + compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); + if (compat53_data.peeked_data && compat53_data.peeked_data_size && compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ + status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); + else + status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); + if (status != LUA_OK) + return status; + /* we need to call the original 5.1 version of lua_load! */ +#undef lua_load + return lua_load(L, compat53_reader, &compat53_data, source); +#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) +} + +typedef struct { + int n; /* number of pre-read characters */ + FILE* f; /* file being read */ + char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ +} compat53_LoadF; + +static const char* compat53_getF(lua_State* L, void* ud, size_t* size) { + compat53_LoadF* lf = (compat53_LoadF*)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'compat53_getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) + return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + +static int compat53_errfile(lua_State* L, const char* what, int fnameindex) { + char buf[512] = { 0 }; + const char* serr = compat53_strerror(errno, buf, sizeof(buf)); + const char* filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + +static int compat53_skipBOM(compat53_LoadF* lf) { + const char* p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char*)p++) + return c; + lf->buff[lf->n++] = (char)c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int compat53_skipcomment(compat53_LoadF* lf, int* cp) { + int c = *cp = compat53_skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else + return 0; /* no comment */ +} + +COMPAT53_API int luaL_loadfilex(lua_State* L, const char* filename, const char* mode) { + compat53_LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); +#if defined(_MSC_VER) + /* This code is here to stop a deprecation error that stops builds + * if a certain macro is defined. While normally not caring would + * be best, some header-only libraries and builds can't afford to + * dictate this to the user. A quick check shows that fopen_s this + * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, + * possibly even before that so we don't need to do any version + * number checks, since this has been there since forever. */ + + /* TO USER: if you want the behavior of typical fopen_s/fopen, + * which does lock the file on VC++, define the macro used below to 0 */ +#if COMPAT53_FOPEN_NO_LOCK + lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ + if (lf.f == NULL) + return compat53_errfile(L, "open", fnameindex); +#else /* use default locking version */ + if (fopen_s(&lf.f, filename, "r") != 0) + return compat53_errfile(L, "open", fnameindex); +#endif /* Locking vs. No-locking fopen variants */ +#else + lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ + if (lf.f == NULL) + return compat53_errfile(L, "open", fnameindex); +#endif + } + if (compat53_skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ +#if defined(_MSC_VER) + if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) + return compat53_errfile(L, "reopen", fnameindex); +#else + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) + return compat53_errfile(L, "reopen", fnameindex); +#endif + compat53_skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */ + status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) + fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return compat53_errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + +COMPAT53_API int luaL_loadbufferx(lua_State* L, const char* buff, size_t sz, const char* name, const char* mode) { + int status = LUA_OK; + if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { + status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); + } + else { + status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); + } + if (status != LUA_OK) + return status; + return luaL_loadbuffer(L, buff, sz, name); +} + +#if !defined(l_inspectstat) \ + && (defined(unix) || defined(__unix) || defined(__unix__) || defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || (defined(__APPLE__) && defined(__MACH__))) +/* some form of unix; check feature macros in unistd.h for details */ +#include <unistd.h> +/* check posix version; the relevant include files and macros probably + * were available before 2001, but I'm not sure */ +#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L +#include <sys/wait.h> +#define l_inspectstat(stat, what) \ + if (WIFEXITED(stat)) { \ + stat = WEXITSTATUS(stat); \ + } \ + else if (WIFSIGNALED(stat)) { \ + stat = WTERMSIG(stat); \ + what = "signal"; \ + } +#endif +#endif + +/* provide default (no-op) version */ +#if !defined(l_inspectstat) +#define l_inspectstat(stat, what) ((void)0) +#endif + +COMPAT53_API int luaL_execresult(lua_State* L, int stat) { + const char* what = "exit"; + if (stat == -1) + return luaL_fileresult(L, 0, NULL); + else { + l_inspectstat(stat, what); + if (*what == 'e' && stat == 0) + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; + } +} + +COMPAT53_API void luaL_buffinit(lua_State* L, luaL_Buffer_53* B) { + /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ + B->b.p = NULL; + B->b.L = NULL; + B->b.lvl = 0; + /* reuse the buffer from the 5.1-style luaL_Buffer though! */ + B->ptr = B->b.buffer; + B->capacity = LUAL_BUFFERSIZE; + B->nelems = 0; + B->L2 = L; +} + +COMPAT53_API char* luaL_prepbuffsize(luaL_Buffer_53* B, size_t s) { + if (B->capacity - B->nelems < s) { /* needs to grow */ + char* newptr = NULL; + size_t newcap = B->capacity * 2; + if (newcap - B->nelems < s) + newcap = B->nelems + s; + if (newcap < B->capacity) /* overflow */ + luaL_error(B->L2, "buffer too large"); +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504 + newptr = (char*)lua_newuserdatauv(B->L2, newcap, 0); +#else + newptr = (char*)lua_newuserdata(B->L2, newcap); +#endif + memcpy(newptr, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove old buffer */ + B->ptr = newptr; + B->capacity = newcap; + } + return B->ptr + B->nelems; +} + +COMPAT53_API void luaL_addlstring(luaL_Buffer_53* B, const char* s, size_t l) { + memcpy(luaL_prepbuffsize(B, l), s, l); + luaL_addsize(B, l); +} + +COMPAT53_API void luaL_addvalue(luaL_Buffer_53* B) { + size_t len = 0; + const char* s = lua_tolstring(B->L2, -1, &len); + if (!s) + luaL_error(B->L2, "cannot convert value to string"); + if (B->ptr != B->b.buffer) + lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ + luaL_addlstring(B, s, len); + lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); +} + +void luaL_pushresult(luaL_Buffer_53* B) { + lua_pushlstring(B->L2, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove userdata buffer */ +} + +#endif /* Lua 5.1 */ + +/* definitions for Lua 5.1 and Lua 5.2 */ +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 + +COMPAT53_API int lua_geti(lua_State* L, int index, lua_Integer i) { + index = lua_absindex(L, index); + lua_pushinteger(L, i); + lua_gettable(L, index); + return lua_type(L, -1); +} + +COMPAT53_API int lua_isinteger(lua_State* L, int index) { + if (lua_type(L, index) == LUA_TNUMBER) { + lua_Number n = lua_tonumber(L, index); + lua_Integer i = lua_tointeger(L, index); + if (i == n) + return 1; + } + return 0; +} + +COMPAT53_API lua_Integer lua_tointegerx(lua_State* L, int i, int* isnum) { + int ok = 0; + lua_Number n = lua_tonumberx(L, i, &ok); + if (ok) { + if (n == (lua_Integer)n) { + if (isnum) + *isnum = 1; + return (lua_Integer)n; + } + } + if (isnum) + *isnum = 0; + return 0; +} + +static void compat53_reverse(lua_State* L, int a, int b) { + for (; a < b; ++a, --b) { + lua_pushvalue(L, a); + lua_pushvalue(L, b); + lua_replace(L, a); + lua_replace(L, b); + } +} + +COMPAT53_API void lua_rotate(lua_State* L, int idx, int n) { + int n_elems = 0; + idx = lua_absindex(L, idx); + n_elems = lua_gettop(L) - idx + 1; + if (n < 0) + n += n_elems; + if (n > 0 && n < n_elems) { + luaL_checkstack(L, 2, "not enough stack slots available"); + n = n_elems - n; + compat53_reverse(L, idx, idx + n - 1); + compat53_reverse(L, idx + n, idx + n_elems - 1); + compat53_reverse(L, idx, idx + n_elems - 1); + } +} + +COMPAT53_API void lua_seti(lua_State* L, int index, lua_Integer i) { + luaL_checkstack(L, 1, "not enough stack slots available"); + index = lua_absindex(L, index); + lua_pushinteger(L, i); + lua_insert(L, -2); + lua_settable(L, index); +} + +#if !defined(lua_str2number) +#define lua_str2number(s, p) strtod((s), (p)) +#endif + +COMPAT53_API size_t lua_stringtonumber(lua_State* L, const char* s) { + char* endptr; + lua_Number n = lua_str2number(s, &endptr); + if (endptr != s) { + while (*endptr != '\0' && isspace((unsigned char)*endptr)) + ++endptr; + if (*endptr == '\0') { + lua_pushnumber(L, n); + return endptr - s + 1; + } + } + return 0; +} + +COMPAT53_API const char* luaL_tolstring(lua_State* L, int idx, size_t* len) { + if (!luaL_callmeta(L, idx, "__tostring")) { + int t = lua_type(L, idx), tt = 0; + char const* name = NULL; + switch (t) { + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + case LUA_TSTRING: + case LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + if (lua_toboolean(L, idx)) + lua_pushliteral(L, "true"); + else + lua_pushliteral(L, "false"); + break; + default: + tt = luaL_getmetafield(L, idx, "__name"); + name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); + lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_replace(L, -2); + break; + } + } + else { + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + return lua_tolstring(L, -1, len); +} + +COMPAT53_API void luaL_requiref(lua_State* L, const char* modname, lua_CFunction openf, int glb) { + luaL_checkstack(L, 3, "not enough stack slots available"); + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + if (lua_getfield(L, -1, modname) == LUA_TNIL) { + lua_pop(L, 1); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); + } + if (glb) { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } + lua_replace(L, -2); +} + +#endif /* Lua 5.1 and 5.2 */ + +#endif /* KEPLER_PROJECT_COMPAT53_C_ */ + +/********************************************************************* + * This file contains parts of Lua 5.2's and Lua 5.3's source code: + * + * Copyright (C) 1994-2014 Lua.org, PUC-Rio. + * + * 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. + *********************************************************************/ +// end of sol/compatibility/compat-5.3.c.h + +#endif + +#endif /* KEPLER_PROJECT_COMPAT53_H_ */ + +// end of sol/compatibility/compat-5.3.h + +// beginning of sol/compatibility/compat-5.4.h + +#ifndef NOT_KEPLER_PROJECT_COMPAT54_H_ +#define NOT_KEPLER_PROJECT_COMPAT54_H_ + +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +extern "C" { +#endif +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> +#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) +} +#endif + +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504 + +#if !defined(LUA_ERRGCMM) +/* So Lua 5.4 actually removes this, which breaks sol2... + man, this API is quite unstable...! +*/ +# define LUA_ERRGCMM (LUA_ERRERR + 2) +#endif /* LUA_ERRGCMM define */ + +#endif // Lua 5.4 only + +#endif // NOT_KEPLER_PROJECT_COMPAT54_H_// end of sol/compatibility/compat-5.4.h + +#endif + +// end of sol/compatibility.hpp + +#include <vector> +#include <cstdint> +#include <cstddef> + +namespace sol { + + template <typename Allocator = std::allocator<std::byte>> + class basic_bytecode : private std::vector<std::byte, Allocator> { + private: + using base_t = std::vector<std::byte, Allocator>; + + public: + using typename base_t::allocator_type; + using typename base_t::const_iterator; + using typename base_t::const_pointer; + using typename base_t::const_reference; + using typename base_t::const_reverse_iterator; + using typename base_t::difference_type; + using typename base_t::iterator; + using typename base_t::pointer; + using typename base_t::reference; + using typename base_t::reverse_iterator; + using typename base_t::size_type; + using typename base_t::value_type; + + using base_t::base_t; + using base_t::operator=; + + using base_t::data; + using base_t::empty; + using base_t::max_size; + using base_t::size; + + using base_t::at; + using base_t::operator[]; + using base_t::back; + using base_t::front; + + using base_t::begin; + using base_t::cbegin; + using base_t::cend; + using base_t::end; + + using base_t::crbegin; + using base_t::crend; + using base_t::rbegin; + using base_t::rend; + + using base_t::get_allocator; + using base_t::swap; + + using base_t::clear; + using base_t::emplace; + using base_t::emplace_back; + using base_t::erase; + using base_t::insert; + using base_t::pop_back; + using base_t::push_back; + using base_t::reserve; + using base_t::resize; + using base_t::shrink_to_fit; + + string_view as_string_view() const { + return string_view(reinterpret_cast<const char*>(this->data()), this->size()); + } + }; + + template <typename Container> + inline int basic_insert_dump_writer(lua_State*, const void* memory, size_t memory_size, void* userdata_pointer) { + using storage_t = Container; + const std::byte* p_code = static_cast<const std::byte*>(memory); + storage_t& bc = *static_cast<storage_t*>(userdata_pointer); +#if SOL_IS_OFF(SOL_EXCEPTIONS) + bc.insert(bc.cend(), p_code, p_code + memory_size); +#else + try { + bc.insert(bc.cend(), p_code, p_code + memory_size); + } + catch (...) { + return -1; + } +#endif + return 0; + } + + using bytecode = basic_bytecode<>; + + constexpr inline auto bytecode_dump_writer = &basic_insert_dump_writer<bytecode>; + +} // namespace sol + +// end of sol/bytecode.hpp + +// beginning of sol/stack.hpp + +// beginning of sol/trampoline.hpp + +// beginning of sol/types.hpp + +// beginning of sol/error.hpp + +#include <stdexcept> +#include <string> +#include <array> + +namespace sol { + namespace detail { + struct direct_error_tag { }; + const auto direct_error = direct_error_tag {}; + + struct error_result { + int results; + const char* format_string; + std::array<const char*, 4> argument_strings; + + error_result() : results(0), format_string(nullptr) { + } + + error_result(int results_) : results(results_), format_string(nullptr) { + } + + error_result(const char* format_string_, const char* first_message_) : results(0), format_string(format_string_), argument_strings() { + argument_strings[0] = first_message_; + } + }; + + inline int handle_errors(lua_State* L, const error_result& er) { + if (er.format_string == nullptr) { + return er.results; + } + return luaL_error(L, er.format_string, er.argument_strings[0], er.argument_strings[1], er.argument_strings[2], er.argument_strings[3]); + } + } // namespace detail + + class error : public std::runtime_error { + private: + // Because VC++ is upsetting, most of the time! + std::string what_reason; + + public: + error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) { + } + error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) { + } + error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), what_reason(str) { + } + error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), what_reason(std::move(str)) { + } + + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return what_reason.c_str(); + } + }; + +} // namespace sol + +// end of sol/error.hpp + +// beginning of sol/optional.hpp + +// beginning of sol/in_place.hpp + +#include <cstddef> +#include <utility> + +namespace sol { + + using in_place_t = std::in_place_t; + constexpr std::in_place_t in_place {}; + constexpr std::in_place_t in_place_of {}; + + template <typename T> + using in_place_type_t = std::in_place_type_t<T>; + template <typename T> + constexpr std::in_place_type_t<T> in_place_type {}; + + template <size_t I> + using in_place_index_t = std::in_place_index_t<I>; + template <size_t I> + constexpr in_place_index_t<I> in_place_index {}; + +} // namespace sol + +// end of sol/in_place.hpp + +#if SOL_IS_ON(SOL_USE_BOOST) +#include <boost/optional.hpp> +#else +// beginning of sol/optional_implementation.hpp + +#define SOL_TL_OPTIONAL_VERSION_MAJOR 0 +#define SOL_TL_OPTIONAL_VERSION_MINOR 5 + +#include <exception> +#include <functional> +#include <new> +#include <type_traits> +#include <utility> +#include <cstdlib> +#include <optional> + +#if (defined(_MSC_VER) && _MSC_VER == 1900) +#define SOL_TL_OPTIONAL_MSVC2015 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) +#define SOL_TL_OPTIONAL_GCC49 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__)) +#define SOL_TL_OPTIONAL_GCC54 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__)) +#define SOL_TL_OPTIONAL_GCC55 +#endif + +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) +#define SOL_TL_OPTIONAL_NO_CONSTRR + +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>::value +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value + +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value + +#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) +#ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX +#define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX +namespace sol { namespace detail { + template <class T> + struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> { }; +#ifdef _GLIBCXX_VECTOR + template <class T, class A> + struct is_trivially_copy_constructible<std::vector<T, A>> : std::is_trivially_copy_constructible<T> { }; +#endif +}} // namespace sol::detail +#endif + +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible<T>::value +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value +#else +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>::value +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value +#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value +#endif + +#if __cplusplus > 201103L +#define SOL_TL_OPTIONAL_CXX14 +#endif + +#if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49)) +#define SOL_TL_OPTIONAL_11_CONSTEXPR +#else + /// \exclude +#define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr +#endif + +namespace sol { +#ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX +#define SOL_TL_MONOSTATE_INPLACE_MUTEX + /// \brief Used to represent an optional with no data; essentially a bool + class monostate { }; +#endif + + template <class T> + class optional; + + /// \exclude + namespace detail { +#ifndef SOL_TL_TRAITS_MUTEX +#define SOL_TL_TRAITS_MUTEX + // C++14-style aliases for brevity + template <class T> + using remove_const_t = typename std::remove_const<T>::type; + template <class T> + using remove_reference_t = typename std::remove_reference<T>::type; + template <class T> + using decay_t = typename std::decay<T>::type; + template <bool E, class T = void> + using enable_if_t = typename std::enable_if<E, T>::type; + template <bool B, class T, class F> + using conditional_t = typename std::conditional<B, T, F>::type; + + // std::conjunction from C++17 + template <class...> + struct conjunction : std::true_type { }; + template <class B> + struct conjunction<B> : B { }; + template <class B, class... Bs> + struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type { }; + +#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L +#define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND +#endif + +#ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND + template <class T> + struct is_pointer_to_non_const_member_func : std::false_type { }; + template <class T, class Ret, class... Args> + struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type { }; + template <class T, class Ret, class... Args> + struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)&> : std::true_type { }; + template <class T, class Ret, class... Args> + struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type { }; + template <class T, class Ret, class... Args> + struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type { }; + template <class T, class Ret, class... Args> + struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&> : std::true_type { }; + template <class T, class Ret, class... Args> + struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&&> : std::true_type { }; + + template <class T> + struct is_const_or_const_ref : std::false_type { }; + template <class T> + struct is_const_or_const_ref<T const&> : std::true_type { }; + template <class T> + struct is_const_or_const_ref<T const> : std::true_type { }; +#endif + + // std::invoke from C++17 + // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround + template <typename Fn, typename... Args, +#ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND + typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>, +#endif + typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0> + constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...))) + -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) { + return std::mem_fn(f)(std::forward<Args>(args)...); + } + + template <typename Fn, typename... Args, typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>> + constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...))) + -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) { + return std::forward<Fn>(f)(std::forward<Args>(args)...); + } + + // std::invoke_result from C++17 + template <class F, class, class... Us> + struct invoke_result_impl; + + template <class F, class... Us> + struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> { + using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...)); + }; + + template <class F, class... Us> + using invoke_result = invoke_result_impl<F, void, Us...>; + + template <class F, class... Us> + using invoke_result_t = typename invoke_result<F, Us...>::type; +#endif + + // std::void_t from C++17 + template <class...> + struct voider { + using type = void; + }; + template <class... Ts> + using void_t = typename voider<Ts...>::type; + + // Trait for checking if a type is a sol::optional + template <class T> + struct is_optional_impl : std::false_type { }; + template <class T> + struct is_optional_impl<optional<T>> : std::true_type { }; + template <class T> + using is_optional = is_optional_impl<decay_t<T>>; + + // Change void to sol::monostate + template <class U> + using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>; + + template <class F, class U, class = invoke_result_t<F, U>> + using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>; + + // Check if invoking F for some Us returns void + template <class F, class = void, class... U> + struct returns_void_impl; + template <class F, class... U> + struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> : std::is_void<invoke_result_t<F, U...>> { }; + template <class F, class... U> + using returns_void = returns_void_impl<F, void, U...>; + + template <class T, class... U> + using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>; + + template <class T, class... U> + using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>; + + template <class T, class U> + using enable_forward_value = detail::enable_if_t<std::is_constructible<T, U&&>::value && !std::is_same<detail::decay_t<U>, in_place_t>::value + && !std::is_same<optional<T>, detail::decay_t<U>>::value>; + + template <class T, class U, class Other> + using enable_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && !std::is_constructible<T, optional<U>&>::value + && !std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, const optional<U>&>::value + && !std::is_constructible<T, const optional<U>&&>::value && !std::is_convertible<optional<U>&, T>::value + && !std::is_convertible<optional<U>&&, T>::value && !std::is_convertible<const optional<U>&, T>::value + && !std::is_convertible<const optional<U>&&, T>::value>; + + template <class T, class U> + using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value + && !detail::conjunction<std::is_scalar<T>, std::is_same<T, detail::decay_t<U>>>::value && std::is_constructible<T, U>::value + && std::is_assignable<T&, U>::value>; + + template <class T, class U, class Other> + using enable_assign_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && std::is_assignable<T&, Other>::value + && !std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&&>::value + && !std::is_constructible<T, const optional<U>&>::value && !std::is_constructible<T, const optional<U>&&>::value + && !std::is_convertible<optional<U>&, T>::value && !std::is_convertible<optional<U>&&, T>::value + && !std::is_convertible<const optional<U>&, T>::value && !std::is_convertible<const optional<U>&&, T>::value + && !std::is_assignable<T&, optional<U>&>::value && !std::is_assignable<T&, optional<U>&&>::value + && !std::is_assignable<T&, const optional<U>&>::value && !std::is_assignable<T&, const optional<U>&&>::value>; + +#ifdef _MSC_VER + // TODO make a version which works with MSVC + template <class T, class U = T> + struct is_swappable : std::true_type { }; + + template <class T, class U = T> + struct is_nothrow_swappable : std::true_type { }; +#else + // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept + namespace swap_adl_tests { + // if swap ADL finds this then it would call std::swap otherwise (same + // signature) + struct tag { }; + + template <class T> + tag swap(T&, T&); + template <class T, std::size_t N> + tag swap(T (&a)[N], T (&b)[N]); + + // helper functions to test if an unqualified swap is possible, and if it + // becomes std::swap + template <class, class> + std::false_type can_swap(...) noexcept(false); + template <class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))> + std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>()))); + + template <class, class> + std::false_type uses_std(...); + template <class T, class U> + std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int); + + template <class T> + struct is_std_swap_noexcept + : std::integral_constant<bool, std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value> { }; + + template <class T, std::size_t N> + struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> { }; + + template <class T, class U> + struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> { }; + } // namespace swap_adl_tests + + template <class T, class U = T> + struct is_swappable : std::integral_constant<bool, + decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value + && (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value + || (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> { }; + + template <class T, std::size_t N> + struct is_swappable<T[N], T[N]> : std::integral_constant<bool, + decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value + && (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || is_swappable<T, T>::value)> { }; + + template <class T, class U = T> + struct is_nothrow_swappable + : std::integral_constant<bool, + is_swappable<T, U>::value + && ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept<T>::value) + || (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> { }; +#endif + + // The storage base manages the actual storage, and correctly propagates + // trivial destroyion from T. This case is for when T is not trivially + // destructible. + template <class T, bool = ::std::is_trivially_destructible<T>::value> + struct optional_storage_base { + SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) { + } + + template <class... U> + SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) { + } + + ~optional_storage_base() { + if (m_has_value) { + m_value.~T(); + m_has_value = false; + } + } + + struct dummy { }; + union { + dummy m_dummy; + T m_value; + }; + + bool m_has_value; + }; + + // This case is for when T is trivially destructible. + template <class T> + struct optional_storage_base<T, true> { + SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) { + } + + template <class... U> + SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) { + } + + // No destructor, so this class is trivially destructible + + struct dummy { }; + union { + dummy m_dummy; + T m_value; + }; + + bool m_has_value = false; + }; + + // This base class provides some handy member functions which can be used in + // further derived classes + template <class T> + struct optional_operations_base : optional_storage_base<T> { + using optional_storage_base<T>::optional_storage_base; + + void hard_reset() noexcept { + get().~T(); + this->m_has_value = false; + } + + template <class... Args> + void construct(Args&&... args) noexcept { + new (std::addressof(this->m_value)) T(std::forward<Args>(args)...); + this->m_has_value = true; + } + + template <class Opt> + void assign(Opt&& rhs) { + if (this->has_value()) { + if (rhs.has_value()) { + this->m_value = std::forward<Opt>(rhs).get(); + } + else { + this->m_value.~T(); + this->m_has_value = false; + } + } + + else if (rhs.has_value()) { + construct(std::forward<Opt>(rhs).get()); + } + } + + bool has_value() const { + return this->m_has_value; + } + + SOL_TL_OPTIONAL_11_CONSTEXPR T& get() & { + return this->m_value; + } + SOL_TL_OPTIONAL_11_CONSTEXPR const T& get() const& { + return this->m_value; + } + SOL_TL_OPTIONAL_11_CONSTEXPR T&& get() && { + return std::move(this->m_value); + } +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + constexpr const T&& get() const&& { + return std::move(this->m_value); + } +#endif + }; + + // This class manages conditionally having a trivial copy constructor + // This specialization is for when T is trivially copy constructible + template <class T, bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)> + struct optional_copy_base : optional_operations_base<T> { + using optional_operations_base<T>::optional_operations_base; + }; + + // This specialization is for when T is not trivially copy constructible + template <class T> + struct optional_copy_base<T, false> : optional_operations_base<T> { + using base_t = optional_operations_base<T>; + + using base_t::base_t; + + optional_copy_base() = default; + optional_copy_base(const optional_copy_base& rhs) : base_t() { + if (rhs.has_value()) { + this->construct(rhs.get()); + } + else { + this->m_has_value = false; + } + } + + optional_copy_base(optional_copy_base&& rhs) = default; + optional_copy_base& operator=(const optional_copy_base& rhs) = default; + optional_copy_base& operator=(optional_copy_base&& rhs) = default; + }; + +#ifndef SOL_TL_OPTIONAL_GCC49 + template <class T, bool = std::is_trivially_move_constructible<T>::value> + struct optional_move_base : optional_copy_base<T> { + using optional_copy_base<T>::optional_copy_base; + }; +#else + template <class T, bool = false> + struct optional_move_base; +#endif + template <class T> + struct optional_move_base<T, false> : optional_copy_base<T> { + using optional_copy_base<T>::optional_copy_base; + + optional_move_base() = default; + optional_move_base(const optional_move_base& rhs) = default; + + optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value) { + if (rhs.has_value()) { + this->construct(std::move(rhs.get())); + } + else { + this->m_has_value = false; + } + } + optional_move_base& operator=(const optional_move_base& rhs) = default; + optional_move_base& operator=(optional_move_base&& rhs) = default; + }; + + // This class manages conditionally having a trivial copy assignment operator + template <class T, + bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) + && SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)> + struct optional_copy_assign_base : optional_move_base<T> { + using optional_move_base<T>::optional_move_base; + }; + + template <class T> + struct optional_copy_assign_base<T, false> : optional_move_base<T> { + using optional_move_base<T>::optional_move_base; + + optional_copy_assign_base() = default; + optional_copy_assign_base(const optional_copy_assign_base& rhs) = default; + + optional_copy_assign_base(optional_copy_assign_base&& rhs) = default; + optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) { + this->assign(rhs); + return *this; + } + optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default; + }; + +#ifndef SOL_TL_OPTIONAL_GCC49 + template <class T, + bool = std::is_trivially_destructible<T>::value&& std::is_trivially_move_constructible<T>::value&& std::is_trivially_move_assignable<T>::value> + struct optional_move_assign_base : optional_copy_assign_base<T> { + using optional_copy_assign_base<T>::optional_copy_assign_base; + }; +#else + template <class T, bool = false> + struct optional_move_assign_base; +#endif + + template <class T> + struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> { + using optional_copy_assign_base<T>::optional_copy_assign_base; + + optional_move_assign_base() = default; + optional_move_assign_base(const optional_move_assign_base& rhs) = default; + + optional_move_assign_base(optional_move_assign_base&& rhs) = default; + + optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default; + + optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept( + std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<T>::value) { + this->assign(std::move(rhs)); + return *this; + } + }; + + // optional_delete_ctor_base will conditionally delete copy and move + // constructors depending on whether T is copy/move constructible + template <class T, bool EnableCopy = std::is_copy_constructible<T>::value, bool EnableMove = std::is_move_constructible<T>::value> + struct optional_delete_ctor_base { + optional_delete_ctor_base() = default; + optional_delete_ctor_base(const optional_delete_ctor_base&) = default; + optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; + optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; + optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; + }; + + template <class T> + struct optional_delete_ctor_base<T, true, false> { + optional_delete_ctor_base() = default; + optional_delete_ctor_base(const optional_delete_ctor_base&) = default; + optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; + optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; + optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; + }; + + template <class T> + struct optional_delete_ctor_base<T, false, true> { + optional_delete_ctor_base() = default; + optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; + optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; + optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; + optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; + }; + + template <class T> + struct optional_delete_ctor_base<T, false, false> { + optional_delete_ctor_base() = default; + optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; + optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; + optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; + optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; + }; + + // optional_delete_assign_base will conditionally delete copy and move + // constructors depending on whether T is copy/move constructible + assignable + template <class T, bool EnableCopy = (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value), + bool EnableMove = (std::is_move_constructible<T>::value && std::is_move_assignable<T>::value)> + struct optional_delete_assign_base { + optional_delete_assign_base() = default; + optional_delete_assign_base(const optional_delete_assign_base&) = default; + optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; + optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default; + optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default; + }; + + template <class T> + struct optional_delete_assign_base<T, true, false> { + optional_delete_assign_base() = default; + optional_delete_assign_base(const optional_delete_assign_base&) = default; + optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; + optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default; + optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete; + }; + + template <class T> + struct optional_delete_assign_base<T, false, true> { + optional_delete_assign_base() = default; + optional_delete_assign_base(const optional_delete_assign_base&) = default; + optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; + optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete; + optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default; + }; + + template <class T> + struct optional_delete_assign_base<T, false, false> { + optional_delete_assign_base() = default; + optional_delete_assign_base(const optional_delete_assign_base&) = default; + optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; + optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete; + optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete; + }; + + } // namespace detail + + /// \brief A tag type to represent an empty optional + using nullopt_t = std::nullopt_t; + + /// \brief Represents an empty optional + /// \synopsis static constexpr nullopt_t nullopt; + /// + /// *Examples*: + /// ``` + /// sol::optional<int> a = sol::nullopt; + /// void foo (sol::optional<int>); + /// foo(sol::nullopt); //pass an empty optional + /// ``` + using std::nullopt; + + /// @brief An exception for when an optional is accessed through specific methods while it is not engaged. + class bad_optional_access : public std::exception { + public: + /// @brief Default-constructs an optional exception. + bad_optional_access() = default; + /// @brief Returns a pointer to a null-terminated string containing the reason for the exception. + const char* what() const noexcept override { + return "Optional has no value"; + } + }; + + /// An optional object is an object that contains the storage for another + /// object and manages the lifetime of this contained object, if any. The + /// contained object may be initialized after the optional object has been + /// initialized, and may be destroyed before the optional object has been + /// destroyed. The initialization state of the contained object is tracked by + /// the optional object. + template <class T> + class optional : private detail::optional_move_assign_base<T>, + private detail::optional_delete_ctor_base<T>, + private detail::optional_delete_assign_base<T> { + using base = detail::optional_move_assign_base<T>; + + static_assert(!std::is_same<T, in_place_t>::value, "instantiation of optional with in_place_t is ill-formed"); + static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed"); + + public: +#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) + /// \group and_then + /// Carries out some operation which returns an optional on the stored + /// object if there is one. \requires `std::invoke(std::forward<F>(f), + /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be + /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a + /// `std::optional<U>`. The return value is empty if `*this` is empty, + /// otherwise the return value of `std::invoke(std::forward<F>(f), value())` + /// is returned. + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & { + using result = detail::invoke_result_t<F, T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && { + using result = detail::invoke_result_t<F, T&&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &; + template <class F> + constexpr auto and_then(F&& f) const& { + using result = detail::invoke_result_t<F, const T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &&; + template <class F> + constexpr auto and_then(F&& f) const&& { + using result = detail::invoke_result_t<F, const T&&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); + } +#endif +#else + /// \group and_then + /// Carries out some operation which returns an optional on the stored + /// object if there is one. \requires `std::invoke(std::forward<F>(f), + /// value())` returns a `std::optional<U>` for some `U`. + /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), + /// value())`. Returns a `std::optional<U>`. The return value is empty if + /// `*this` is empty, otherwise the return value of + /// `std::invoke(std::forward<F>(f), value())` is returned. + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & { + using result = detail::invoke_result_t<F, T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&&> and_then(F&& f) && { + using result = detail::invoke_result_t<F, T&&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &; + template <class F> + constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& { + using result = detail::invoke_result_t<F, const T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &&; + template <class F> + constexpr detail::invoke_result_t<F, const T&&> and_then(F&& f) const&& { + using result = detail::invoke_result_t<F, const T&&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); + } +#endif +#endif + +#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), + /// value())`. Returns a `std::optional<U>`. The return value is empty if + /// `*this` is empty, otherwise an `optional<U>` is constructed from the + /// return value of `std::invoke(std::forward<F>(f), value())` and is + /// returned. + /// + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { + return optional_map_impl(*this, std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { + return optional_map_impl(std::move(*this), std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) const&; + template <class F> + constexpr auto map(F&& f) const& { + return optional_map_impl(*this, std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) const&&; + template <class F> + constexpr auto map(F&& f) const&& { + return optional_map_impl(std::move(*this), std::forward<F>(f)); + } +#else + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), + /// value())`. Returns a `std::optional<U>`. The return value is empty if + /// `*this` is empty, otherwise an `optional<U>` is constructed from the + /// return value of `std::invoke(std::forward<F>(f), value())` and is + /// returned. + /// + /// \group map + /// \synopsis template <class F> auto map(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & { + return optional_map_impl(*this, std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> auto map(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && { + return optional_map_impl(std::move(*this), std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> auto map(F &&f) const&; + template <class F> + constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& { + return optional_map_impl(*this, std::forward<F>(f)); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group map + /// \synopsis template <class F> auto map(F &&f) const&&; + template <class F> + constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& { + return optional_map_impl(std::move(*this), std::forward<F>(f)); + } +#endif +#endif + + /// \brief Calls `f` if the optional is empty + /// \requires `std::invoke_result_t<F>` must be void or convertible to + /// `optional<T>`. + /// \effects If `*this` has a value, returns `*this`. + /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns + /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`. + /// + /// \group or_else + /// \synopsis template <class F> optional<T> or_else (F &&f) &; + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { + if (has_value()) + return *this; + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { + return has_value() ? *this : std::forward<F>(f)(); + } + + /// \group or_else + /// \synopsis template <class F> optional<T> or_else (F &&f) &&; + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) && { + if (has_value()) + return std::move(*this); + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && { + return has_value() ? std::move(*this) : std::forward<F>(f)(); + } + + /// \group or_else + /// \synopsis template <class F> optional<T> or_else (F &&f) const &; + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) const& { + if (has_value()) + return *this; + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& { + return has_value() ? *this : std::forward<F>(f)(); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \exclude + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) const&& { + if (has_value()) + return std::move(*this); + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) const&& { + return has_value() ? std::move(*this) : std::forward<F>(f)(); + } +#endif + + /// \brief Maps the stored value with `f` if there is one, otherwise returns + /// `u`. + /// + /// \details If there is a value stored, then `f` is called with `**this` + /// and the value is returned. Otherwise `u` is returned. + /// + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) & { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); + } + + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) && { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); + } + + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) const& { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) const&& { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); + } +#endif + + /// \brief Maps the stored value with `f` if there is one, otherwise calls + /// `u` and returns the result. + /// + /// \details If there is a value stored, then `f` is + /// called with `**this` and the value is returned. Otherwise + /// `std::forward<U>(u)()` is returned. + /// + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) &; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); + } + + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) + /// &&; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); + } + + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) + /// const &; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) + /// const &&; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); + } +#endif + + /// \returns `u` if `*this` has a value, otherwise an empty optional. + template <class U> + constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const { + using result = optional<detail::decay_t<U>>; + return has_value() ? result { u } : result { nullopt }; + } + + /// \returns `rhs` if `*this` is empty, otherwise the current value. + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { + return has_value() ? *this : rhs; + } + + /// \group disjunction + constexpr optional disjunction(const optional& rhs) const& { + return has_value() ? *this : rhs; + } + + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { + return has_value() ? std::move(*this) : rhs; + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group disjunction + constexpr optional disjunction(const optional& rhs) const&& { + return has_value() ? std::move(*this) : rhs; + } +#endif + + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { + return has_value() ? *this : std::move(rhs); + } + + /// \group disjunction + constexpr optional disjunction(optional&& rhs) const& { + return has_value() ? *this : std::move(rhs); + } + + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { + return has_value() ? std::move(*this) : std::move(rhs); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group disjunction + constexpr optional disjunction(optional&& rhs) const&& { + return has_value() ? std::move(*this) : std::move(rhs); + } +#endif + + /// Takes the value out of the optional, leaving it empty + /// \group take + optional take() & { + optional ret = *this; + reset(); + return ret; + } + + /// \group take + optional take() const& { + optional ret = *this; + reset(); + return ret; + } + + /// \group take + optional take() && { + optional ret = std::move(*this); + reset(); + return ret; + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group take + optional take() const&& { + optional ret = std::move(*this); + reset(); + return ret; + } +#endif + + using value_type = T; + + /// Constructs an optional that does not contain a value. + /// \group ctor_empty + constexpr optional() noexcept = default; + + /// \group ctor_empty + constexpr optional(nullopt_t) noexcept { + } + + /// Copy constructor + /// + /// If `rhs` contains a value, the stored value is direct-initialized with + /// it. Otherwise, the constructed optional is empty. + SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default; + + /// Move constructor + /// + /// If `rhs` contains a value, the stored value is direct-initialized with + /// it. Otherwise, the constructed optional is empty. + SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; + + /// Constructs the stored value in-place using the given arguments. + /// \group in_place + /// \synopsis template <class... Args> constexpr explicit optional(in_place_t, Args&&... args); + template <class... Args> + constexpr explicit optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args) + : base(in_place, std::forward<Args>(args)...) { + } + + /// \group in_place + /// \synopsis template <class U, class... Args> \n constexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... args); + template <class U, class... Args> + SOL_TL_OPTIONAL_11_CONSTEXPR explicit optional(detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>, + std::initializer_list<U> il, Args&&... args) { + this->construct(il, std::forward<Args>(args)...); + } + +#if 0 // SOL_MODIFICATION + /// Constructs the stored value with `u`. + /// \synopsis template <class U=T> constexpr optional(U &&u); + template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr> + constexpr optional(U&& u) : base(in_place, std::forward<U>(u)) { + } + + /// \exclude + template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr> + constexpr explicit optional(U&& u) : base(in_place, std::forward<U>(u)) { + } +#else + /// Constructs the stored value with `u`. + /// \synopsis template <class U=T> constexpr optional(U &&u); + constexpr optional(T&& u) : base(in_place, std::move(u)) { + } + + /// \exclude + constexpr optional(const T& u) : base(in_place, u) { + } +#endif // sol2 modification + + /// Converting copy constructor. + /// \synopsis template <class U> optional(const optional<U> &rhs); + template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr> + optional(const optional<U>& rhs) { + if (rhs.has_value()) { + this->construct(*rhs); + } + } + + /// \exclude + template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr> + explicit optional(const optional<U>& rhs) { + if (rhs.has_value()) { + this->construct(*rhs); + } + } + + /// Converting move constructor. + /// \synopsis template <class U> optional(optional<U> &&rhs); + template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr> + optional(optional<U>&& rhs) { + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } + } + + /// \exclude + template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr> + explicit optional(optional<U>&& rhs) { + this->construct(std::move(*rhs)); + } + + /// Destroys the stored value if there is one. + ~optional() = default; + + /// Assignment to empty. + /// + /// Destroys the current value if there is one. + optional& operator=(nullopt_t) noexcept { + if (has_value()) { + this->m_value.~T(); + this->m_has_value = false; + } + + return *this; + } + + /// Copy assignment. + /// + /// Copies the value from `rhs` if there is one. Otherwise resets the stored + /// value in `*this`. + optional& operator=(const optional& rhs) = default; + + /// Move assignment. + /// + /// Moves the value from `rhs` if there is one. Otherwise resets the stored + /// value in `*this`. + optional& operator=(optional&& rhs) = default; + + /// Assigns the stored value from `u`, destroying the old value if there was + /// one. + /// \synopsis optional &operator=(U &&u); + template <class U = T, detail::enable_assign_forward<T, U>* = nullptr> + optional& operator=(U&& u) { + if (has_value()) { + this->m_value = std::forward<U>(u); + } + else { + this->construct(std::forward<U>(u)); + } + + return *this; + } + + /// Converting copy assignment operator. + /// + /// Copies the value from `rhs` if there is one. Otherwise resets the stored + /// value in `*this`. + /// \synopsis optional &operator=(const optional<U> & rhs); + template <class U, detail::enable_assign_from_other<T, U, const U&>* = nullptr> + optional& operator=(const optional<U>& rhs) { + if (has_value()) { + if (rhs.has_value()) { + this->m_value = *rhs; + } + else { + this->hard_reset(); + } + } + + if (rhs.has_value()) { + this->construct(*rhs); + } + + return *this; + } + + // TODO check exception guarantee + /// Converting move assignment operator. + /// + /// Moves the value from `rhs` if there is one. Otherwise resets the stored + /// value in `*this`. + /// \synopsis optional &operator=(optional<U> && rhs); + template <class U, detail::enable_assign_from_other<T, U, U>* = nullptr> + optional& operator=(optional<U>&& rhs) { + if (has_value()) { + if (rhs.has_value()) { + this->m_value = std::move(*rhs); + } + else { + this->hard_reset(); + } + } + + if (rhs.has_value()) { + this->construct(std::move(*rhs)); + } + + return *this; + } + + /// Constructs the value in-place, destroying the current one if there is + /// one. + /// \group emplace + template <class... Args> + T& emplace(Args&&... args) { + static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args"); + + *this = nullopt; + this->construct(std::forward<Args>(args)...); + return value(); + } + + /// \group emplace + /// \synopsis template <class U, class... Args> \n T& emplace(std::initializer_list<U> il, Args &&... args); + template <class U, class... Args> + detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> emplace(std::initializer_list<U> il, Args&&... args) { + *this = nullopt; + this->construct(il, std::forward<Args>(args)...); + return value(); + } + + /// Swaps this optional with the other. + /// + /// If neither optionals have a value, nothing happens. + /// If both have a value, the values are swapped. + /// If one has a value, it is moved to the other and the movee is left + /// valueless. + void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&& detail::is_nothrow_swappable<T>::value) { + if (has_value()) { + if (rhs.has_value()) { + using std::swap; + swap(**this, *rhs); + } + else { + new (std::addressof(rhs.m_value)) T(std::move(this->m_value)); + this->m_value.T::~T(); + } + } + else if (rhs.has_value()) { + new (std::addressof(this->m_value)) T(std::move(rhs.m_value)); + rhs.m_value.T::~T(); + } + } + + /// \returns a pointer to the stored value + /// \requires a value is stored + /// \group pointer + /// \synopsis constexpr const T *operator->() const; + constexpr const T* operator->() const { + return std::addressof(this->m_value); + } + + /// \group pointer + /// \synopsis constexpr T *operator->(); + SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() { + return std::addressof(this->m_value); + } + + /// \returns the stored value + /// \requires a value is stored + /// \group deref + /// \synopsis constexpr T &operator*(); + SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() & { + return this->m_value; + } + + /// \group deref + /// \synopsis constexpr const T &operator*() const; + constexpr const T& operator*() const& { + return this->m_value; + } + + /// \exclude + SOL_TL_OPTIONAL_11_CONSTEXPR T&& operator*() && { + return std::move(this->m_value); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \exclude + constexpr const T&& operator*() const&& { + return std::move(this->m_value); + } +#endif + + /// \returns whether or not the optional has a value + /// \group has_value + constexpr bool has_value() const noexcept { + return this->m_has_value; + } + + /// \group has_value + constexpr explicit operator bool() const noexcept { + return this->m_has_value; + } + + /// \returns the contained value if there is one, otherwise throws + /// [bad_optional_access] + /// \group value + /// \synopsis constexpr T &value(); + SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & { + if (has_value()) + return this->m_value; +#if SOL_IS_OFF(SOL_EXCEPTIONS) + std::abort(); +#else + throw bad_optional_access(); +#endif // No exceptions allowed + } + /// \group value + /// \synopsis constexpr const T &value() const; + SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& { + if (has_value()) + return this->m_value; +#if SOL_IS_OFF(SOL_EXCEPTIONS) + std::abort(); +#else + throw bad_optional_access(); +#endif // No exceptions allowed + } + /// \exclude + SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && { + if (has_value()) + return std::move(this->m_value); +#if SOL_IS_OFF(SOL_EXCEPTIONS) + std::abort(); +#else + throw bad_optional_access(); +#endif // No exceptions allowed + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \exclude + SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& { + if (has_value()) + return std::move(this->m_value); +#if SOL_IS_OFF(SOL_EXCEPTIONS) + std::abort(); +#else + throw bad_optional_access(); +#endif // No exceptions allowed + } +#endif + + /// \returns the stored value if there is one, otherwise returns `u` + /// \group value_or + template <class U> + constexpr T value_or(U&& u) const& { + static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be copy constructible and convertible from U"); + return has_value() ? **this : static_cast<T>(std::forward<U>(u)); + } + + /// \group value_or + template <class U> + SOL_TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && { + static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be move constructible and convertible from U"); + return has_value() ? **this : static_cast<T>(std::forward<U>(u)); + } + + /// Destroys the stored value if one exists, making the optional empty + void reset() noexcept { + if (has_value()) { + this->m_value.~T(); + this->m_has_value = false; + } + } + }; // namespace sol + + /// \group relop + /// \brief Compares two optional objects + /// \details If both optionals contain a value, they are compared with `T`s + /// relational operators. Otherwise `lhs` and `rhs` are equal only if they are + /// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs` + /// is not. + template <class T, class U> + inline constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs) { + return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs); + } + /// \group relop + template <class T, class U> + inline constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs) { + return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs); + } + /// \group relop + template <class T, class U> + inline constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs) { + return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs); + } + /// \group relop + template <class T, class U> + inline constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs) { + return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs); + } + /// \group relop + template <class T, class U> + inline constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs) { + return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs); + } + /// \group relop + template <class T, class U> + inline constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs) { + return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs); + } + + /// \group relop_nullopt + /// \brief Compares an optional to a `nullopt` + /// \details Equivalent to comparing the optional to an empty optional + template <class T> + inline constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept { + return !lhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator==(nullopt_t, const optional<T>& rhs) noexcept { + return !rhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator!=(const optional<T>& lhs, nullopt_t) noexcept { + return lhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator!=(nullopt_t, const optional<T>& rhs) noexcept { + return rhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { + return false; + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator<(nullopt_t, const optional<T>& rhs) noexcept { + return rhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator<=(const optional<T>& lhs, nullopt_t) noexcept { + return !lhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { + return true; + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator>(const optional<T>& lhs, nullopt_t) noexcept { + return lhs.has_value(); + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { + return false; + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { + return true; + } + /// \group relop_nullopt + template <class T> + inline constexpr bool operator>=(nullopt_t, const optional<T>& rhs) noexcept { + return !rhs.has_value(); + } + + /// \group relop_t + /// \brief Compares the optional with a value. + /// \details If the optional has a value, it is compared with the other value + /// using `T`s relational operators. Otherwise, the optional is considered + /// less than the value. + template <class T, class U> + inline constexpr bool operator==(const optional<T>& lhs, const U& rhs) { + return lhs.has_value() ? *lhs == rhs : false; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator==(const U& lhs, const optional<T>& rhs) { + return rhs.has_value() ? lhs == *rhs : false; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator!=(const optional<T>& lhs, const U& rhs) { + return lhs.has_value() ? *lhs != rhs : true; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator!=(const U& lhs, const optional<T>& rhs) { + return rhs.has_value() ? lhs != *rhs : true; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator<(const optional<T>& lhs, const U& rhs) { + return lhs.has_value() ? *lhs < rhs : true; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator<(const U& lhs, const optional<T>& rhs) { + return rhs.has_value() ? lhs < *rhs : false; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator<=(const optional<T>& lhs, const U& rhs) { + return lhs.has_value() ? *lhs <= rhs : true; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator<=(const U& lhs, const optional<T>& rhs) { + return rhs.has_value() ? lhs <= *rhs : false; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator>(const optional<T>& lhs, const U& rhs) { + return lhs.has_value() ? *lhs > rhs : false; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator>(const U& lhs, const optional<T>& rhs) { + return rhs.has_value() ? lhs > *rhs : true; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator>=(const optional<T>& lhs, const U& rhs) { + return lhs.has_value() ? *lhs >= rhs : false; + } + /// \group relop_t + template <class T, class U> + inline constexpr bool operator>=(const U& lhs, const optional<T>& rhs) { + return rhs.has_value() ? lhs >= *rhs : true; + } + + /// \synopsis template <class T> \n void swap(optional<T> &lhs, optional<T> &rhs); + template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>* = nullptr, detail::enable_if_t<detail::is_swappable<T>::value>* = nullptr> + void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) { + return lhs.swap(rhs); + } + + namespace detail { + struct i_am_secret { }; + } // namespace detail + + template <class T = detail::i_am_secret, class U, class Ret = detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::decay_t<U>, T>> + inline constexpr optional<Ret> make_optional(U&& v) { + return optional<Ret>(std::forward<U>(v)); + } + + template <class T, class... Args> + inline constexpr optional<T> make_optional(Args&&... args) { + return optional<T>(in_place, std::forward<Args>(args)...); + } + template <class T, class U, class... Args> + inline constexpr optional<T> make_optional(std::initializer_list<U> il, Args&&... args) { + return optional<T>(in_place, il, std::forward<Args>(args)...); + } + +#if __cplusplus >= 201703L + template <class T> + optional(T) -> optional<T>; +#endif + + /// \exclude + namespace detail { +#ifdef SOL_TL_OPTIONAL_CXX14 + template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), + detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr> + constexpr auto optional_map_impl(Opt&& opt, F&& f) { + return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt); + } + + template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), + detail::enable_if_t<std::is_void<Ret>::value>* = nullptr> + auto optional_map_impl(Opt&& opt, F&& f) { + if (opt.has_value()) { + detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)); + return make_optional(monostate {}); + } + + return optional<monostate>(nullopt); + } +#else + template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), + detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr> + + constexpr auto optional_map_impl(Opt&& opt, F&& f) -> optional<Ret> { + return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt); + } + + template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), + detail::enable_if_t<std::is_void<Ret>::value>* = nullptr> + + auto optional_map_impl(Opt&& opt, F&& f) -> optional<monostate> { + if (opt.has_value()) { + detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)); + return monostate {}; + } + + return nullopt; + } +#endif + } // namespace detail + + /// Specialization for when `T` is a reference. `optional<T&>` acts similarly + /// to a `T*`, but provides more operations and shows intent more clearly. + /// + /// *Examples*: + /// + /// ``` + /// int i = 42; + /// sol::optional<int&> o = i; + /// *o == 42; //true + /// i = 12; + /// *o = 12; //true + /// &*o == &i; //true + /// ``` + /// + /// Assignment has rebind semantics rather than assign-through semantics: + /// + /// ``` + /// int j = 8; + /// o = j; + /// + /// &*o == &j; //true + /// ``` + template <class T> + class optional<T&> { + public: +#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) + /// \group and_then + /// Carries out some operation which returns an optional on the stored + /// object if there is one. \requires `std::invoke(std::forward<F>(f), + /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be + /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a + /// `std::optional<U>`. The return value is empty if `*this` is empty, + /// otherwise the return value of `std::invoke(std::forward<F>(f), value())` + /// is returned. + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & { + using result = detail::invoke_result_t<F, T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && { + using result = detail::invoke_result_t<F, T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &; + template <class F> + constexpr auto and_then(F&& f) const& { + using result = detail::invoke_result_t<F, const T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &&; + template <class F> + constexpr auto and_then(F&& f) const&& { + using result = detail::invoke_result_t<F, const T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } +#endif +#else + /// \group and_then + /// Carries out some operation which returns an optional on the stored + /// object if there is one. \requires `std::invoke(std::forward<F>(f), + /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be + /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a + /// `std::optional<U>`. The return value is empty if `*this` is empty, + /// otherwise the return value of `std::invoke(std::forward<F>(f), value())` + /// is returned. + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & { + using result = detail::invoke_result_t<F, T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) && { + using result = detail::invoke_result_t<F, T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &; + template <class F> + constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& { + using result = detail::invoke_result_t<F, const T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group and_then + /// \synopsis template <class F> \n constexpr auto and_then(F &&f) const &&; + template <class F> + constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const&& { + using result = detail::invoke_result_t<F, const T&>; + static_assert(detail::is_optional<result>::value, "F must return an optional"); + + return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); + } +#endif +#endif + +#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), + /// value())`. Returns a `std::optional<U>`. The return value is empty if + /// `*this` is empty, otherwise an `optional<U>` is constructed from the + /// return value of `std::invoke(std::forward<F>(f), value())` and is + /// returned. + /// + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { + return detail::optional_map_impl(*this, std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { + return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) const&; + template <class F> + constexpr auto map(F&& f) const& { + return detail::optional_map_impl(*this, std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> constexpr auto map(F &&f) const&&; + template <class F> + constexpr auto map(F&& f) const&& { + return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); + } +#else + /// \brief Carries out some operation on the stored object if there is one. + /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), + /// value())`. Returns a `std::optional<U>`. The return value is empty if + /// `*this` is empty, otherwise an `optional<U>` is constructed from the + /// return value of `std::invoke(std::forward<F>(f), value())` and is + /// returned. + /// + /// \group map + /// \synopsis template <class F> auto map(F &&f) &; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & { + return detail::optional_map_impl(*this, std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> auto map(F &&f) &&; + template <class F> + SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && { + return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); + } + + /// \group map + /// \synopsis template <class F> auto map(F &&f) const&; + template <class F> + constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& { + return detail::optional_map_impl(*this, std::forward<F>(f)); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group map + /// \synopsis template <class F> auto map(F &&f) const&&; + template <class F> + constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& { + return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); + } +#endif +#endif + + /// \brief Calls `f` if the optional is empty + /// \requires `std::invoke_result_t<F>` must be void or convertible to + /// `optional<T>`. \effects If `*this` has a value, returns `*this`. + /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns + /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`. + /// + /// \group or_else + /// \synopsis template <class F> optional<T> or_else (F &&f) &; + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { + if (has_value()) + return *this; + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { + return has_value() ? *this : std::forward<F>(f)(); + } + + /// \group or_else + /// \synopsis template <class F> optional<T> or_else (F &&f) &&; + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) && { + if (has_value()) + return std::move(*this); + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && { + return has_value() ? std::move(*this) : std::forward<F>(f)(); + } + + /// \group or_else + /// \synopsis template <class F> optional<T> or_else (F &&f) const &; + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) const& { + if (has_value()) + return *this; + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& { + return has_value() ? *this : std::forward<F>(f)(); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \exclude + template <class F, detail::enable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) const&& { + if (has_value()) + return std::move(*this); + + std::forward<F>(f)(); + return nullopt; + } + + /// \exclude + template <class F, detail::disable_if_ret_void<F>* = nullptr> + optional<T> or_else(F&& f) const&& { + return has_value() ? std::move(*this) : std::forward<F>(f)(); + } +#endif + + /// \brief Maps the stored value with `f` if there is one, otherwise returns + /// `u`. + /// + /// \details If there is a value stored, then `f` is called with `**this` + /// and the value is returned. Otherwise `u` is returned. + /// + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) & { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); + } + + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) && { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); + } + + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) const& { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group map_or + template <class F, class U> + U map_or(F&& f, U&& u) const&& { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); + } +#endif + + /// \brief Maps the stored value with `f` if there is one, otherwise calls + /// `u` and returns the result. + /// + /// \details If there is a value stored, then `f` is + /// called with `**this` and the value is returned. Otherwise + /// `std::forward<U>(u)()` is returned. + /// + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) &; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); + } + + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) + /// &&; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); + } + + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) + /// const &; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& { + return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group map_or_else + /// \synopsis template <class F, class U> \n auto map_or_else(F &&f, U &&u) + /// const &&; + template <class F, class U> + detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& { + return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); + } +#endif + + /// \returns `u` if `*this` has a value, otherwise an empty optional. + template <class U> + constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const { + using result = optional<detail::decay_t<U>>; + return has_value() ? result { u } : result { nullopt }; + } + + /// \returns `rhs` if `*this` is empty, otherwise the current value. + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { + return has_value() ? *this : rhs; + } + + /// \group disjunction + constexpr optional disjunction(const optional& rhs) const& { + return has_value() ? *this : rhs; + } + + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { + return has_value() ? std::move(*this) : rhs; + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group disjunction + constexpr optional disjunction(const optional& rhs) const&& { + return has_value() ? std::move(*this) : rhs; + } +#endif + + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { + return has_value() ? *this : std::move(rhs); + } + + /// \group disjunction + constexpr optional disjunction(optional&& rhs) const& { + return has_value() ? *this : std::move(rhs); + } + + /// \group disjunction + SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { + return has_value() ? std::move(*this) : std::move(rhs); + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group disjunction + constexpr optional disjunction(optional&& rhs) const&& { + return has_value() ? std::move(*this) : std::move(rhs); + } +#endif + + /// Takes the value out of the optional, leaving it empty + /// \group take + optional take() & { + optional ret = *this; + reset(); + return ret; + } + + /// \group take + optional take() const& { + optional ret = *this; + reset(); + return ret; + } + + /// \group take + optional take() && { + optional ret = std::move(*this); + reset(); + return ret; + } + +#ifndef SOL_TL_OPTIONAL_NO_CONSTRR + /// \group take + optional take() const&& { + optional ret = std::move(*this); + reset(); + return ret; + } +#endif + + using value_type = T&; + + /// Constructs an optional that does not contain a value. + /// \group ctor_empty + constexpr optional() noexcept : m_value(nullptr) { + } + + /// \group ctor_empty + constexpr optional(nullopt_t) noexcept : m_value(nullptr) { + } + + /// Copy constructor + /// + /// If `rhs` contains a value, the stored value is direct-initialized with + /// it. Otherwise, the constructed optional is empty. + SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default; + + /// Move constructor + /// + /// If `rhs` contains a value, the stored value is direct-initialized with + /// it. Otherwise, the constructed optional is empty. + SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; + + /// Constructs the stored value with `u`. + /// \synopsis template <class U=T> constexpr optional(U &&u); + template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr> + constexpr optional(U&& u) : m_value(std::addressof(u)) { + static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue"); + } + + /// \exclude + template <class U> + constexpr explicit optional(const optional<U>& rhs) : optional(*rhs) { + } + + /// No-op + ~optional() = default; + + /// Assignment to empty. + /// + /// Destroys the current value if there is one. + optional& operator=(nullopt_t) noexcept { + m_value = nullptr; + return *this; + } + + /// Copy assignment. + /// + /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise + /// resets the stored value in `*this`. + optional& operator=(const optional& rhs) = default; + + /// Rebinds this optional to `u`. + /// + /// \requires `U` must be an lvalue reference. + /// \synopsis optional &operator=(U &&u); + template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr> + optional& operator=(U&& u) { + static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue"); + m_value = std::addressof(u); + return *this; + } + + /// Converting copy assignment operator. + /// + /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise + /// resets the stored value in `*this`. + template <class U> + optional& operator=(const optional<U>& rhs) { + m_value = std::addressof(rhs.value()); + return *this; + } + + /// Constructs the value in-place, destroying the current one if there is + /// one. + /// + /// \group emplace + T& emplace(T& arg) noexcept { + m_value = &arg; + return **this; + } + + /// Swaps this optional with the other. + /// + /// If neither optionals have a value, nothing happens. + /// If both have a value, the values are swapped. + /// If one has a value, it is moved to the other and the movee is left + /// valueless. + void swap(optional& rhs) noexcept { + std::swap(m_value, rhs.m_value); + } + + /// \returns a pointer to the stored value + /// \requires a value is stored + /// \group pointer + /// \synopsis constexpr const T *operator->() const; + constexpr const T* operator->() const { + return m_value; + } + + /// \group pointer + /// \synopsis constexpr T *operator->(); + SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() { + return m_value; + } + + /// \returns the stored value + /// \requires a value is stored + /// \group deref + /// \synopsis constexpr T &operator*(); + SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() { + return *m_value; + } + + /// \group deref + /// \synopsis constexpr const T &operator*() const; + constexpr const T& operator*() const { + return *m_value; + } + + /// \returns whether or not the optional has a value + /// \group has_value + constexpr bool has_value() const noexcept { + return m_value != nullptr; + } + + /// \group has_value + constexpr explicit operator bool() const noexcept { + return m_value != nullptr; + } + + /// \returns the contained value if there is one, otherwise throws + /// [bad_optional_access] + /// \group value + /// synopsis constexpr T &value(); + SOL_TL_OPTIONAL_11_CONSTEXPR T& value() { + if (has_value()) + return *m_value; +#if SOL_IS_OFF(SOL_EXCEPTIONS) + std::abort(); +#else + throw bad_optional_access(); +#endif // No exceptions allowed + } + /// \group value + /// \synopsis constexpr const T &value() const; + SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const { + if (has_value()) + return *m_value; +#if SOL_IS_OFF(SOL_EXCEPTIONS) + std::abort(); +#else + throw bad_optional_access(); +#endif // No exceptions allowed + } + + /// \returns the stored value if there is one, otherwise returns `u` + /// \group value_or + template <class U> + constexpr T& value_or(U&& u) const { + static_assert(std::is_convertible<U&&, T&>::value, "T must be convertible from U"); + return has_value() ? const_cast<T&>(**this) : static_cast<T&>(std::forward<U>(u)); + } + + /// Destroys the stored value if one exists, making the optional empty + void reset() noexcept { + m_value = nullptr; + } + + private: + T* m_value; + }; + +} // namespace sol + +namespace std { + // TODO SFINAE + template <class T> + struct hash<::sol::optional<T>> { + ::std::size_t operator()(const ::sol::optional<T>& o) const { + if (!o.has_value()) + return 0; + + return ::std::hash<::sol::detail::remove_const_t<T>>()(*o); + } + }; +} // namespace std + +// end of sol/optional_implementation.hpp + +#endif // Boost vs. Better optional + +#include <optional> + +namespace sol { + +#if SOL_IS_ON(SOL_USE_BOOST) + template <typename T> + using optional = boost::optional<T>; + using nullopt_t = boost::none_t; + SOL_BOOST_NONE_CONSTEXPR_I_ nullopt_t nullopt = boost::none; +#endif // Boost vs. Better optional + + namespace meta { + template <typename T> + using is_optional = any<is_specialization_of<T, optional>, is_specialization_of<T, std::optional>>; + + template <typename T> + constexpr inline bool is_optional_v = is_optional<T>::value; + } // namespace meta + + namespace detail { + template <typename T> + struct associated_nullopt { + inline static constexpr std::nullopt_t value = std::nullopt; + }; + +#if SOL_IS_ON(SOL_USE_BOOST) + template <typename T> + struct associated_nullopt<boost::optional<T>> { + inline static SOL_BOOST_NONE_CONSTEXPR_I_ boost::none_t value = boost::none; + }; +#endif // Boost nullopt + +#if SOL_IS_ON(SOL_USE_BOOST) + template <typename T> + inline SOL_BOOST_NONE_CONSTEXPR_I_ auto associated_nullopt_v = associated_nullopt<T>::value; +#else + template <typename T> + inline constexpr auto associated_nullopt_v = associated_nullopt<T>::value; +#endif // Boost continues to lag behind, to not many people's surprise... + } // namespace detail +} // namespace sol + +#if SOL_IS_ON(SOL_USE_BOOST) +#undef SOL_BOOST_NONE_CONSTEXPR_I_ +#endif + +// end of sol/optional.hpp + +// beginning of sol/raii.hpp + +#include <memory> + +namespace sol { + namespace detail { + struct default_construct { + template <typename T, typename... Args> + static void construct(T&& obj, Args&&... args) { + typedef meta::unqualified_t<T> Tu; + std::allocator<Tu> alloc {}; + std::allocator_traits<std::allocator<Tu>>::construct(alloc, std::forward<T>(obj), std::forward<Args>(args)...); + } + + template <typename T, typename... Args> + void operator()(T&& obj, Args&&... args) const { + construct(std::forward<T>(obj), std::forward<Args>(args)...); + } + }; + + struct default_destroy { + template <typename T> + static void destroy(T&& obj) { + std::allocator<meta::unqualified_t<T>> alloc {}; + alloc.destroy(obj); + } + + template <typename T> + void operator()(T&& obj) const { + destroy(std::forward<T>(obj)); + } + }; + + struct deleter { + template <typename T> + void operator()(T* p) const { + delete p; + } + }; + + struct state_deleter { + void operator()(lua_State* L) const { + lua_close(L); + } + }; + + template <typename T, typename Dx, typename... Args> + inline std::unique_ptr<T, Dx> make_unique_deleter(Args&&... args) { + return std::unique_ptr<T, Dx>(new T(std::forward<Args>(args)...)); + } + + template <typename Tag, typename T> + struct tagged { + private: + T value_; + + public: + template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, tagged>> = meta::enabler> + tagged(Arg&& arg, Args&&... args) : value_(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + + T& value() & { + return value_; + } + + T const& value() const& { + return value_; + } + + T&& value() && { + return std::move(value_); + } + }; + } // namespace detail + + template <typename... Args> + struct constructor_list { }; + + template <typename... Args> + using constructors = constructor_list<Args...>; + + const auto default_constructor = constructors<types<>> {}; + + struct no_construction { }; + const auto no_constructor = no_construction {}; + + struct call_construction { }; + const auto call_constructor = call_construction {}; + + template <typename... Functions> + struct constructor_wrapper { + std::tuple<Functions...> functions; + template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, constructor_wrapper>> = meta::enabler> + constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + }; + + template <typename... Functions> + inline auto initializers(Functions&&... functions) { + return constructor_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); + } + + template <typename... Functions> + struct factory_wrapper { + std::tuple<Functions...> functions; + template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, factory_wrapper>> = meta::enabler> + factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + }; + + template <typename... Functions> + inline auto factories(Functions&&... functions) { + return factory_wrapper<std::decay_t<Functions>...>(std::forward<Functions>(functions)...); + } + + template <typename Function> + struct destructor_wrapper { + Function fx; + destructor_wrapper(Function f) : fx(std::move(f)) { + } + }; + + template <> + struct destructor_wrapper<void> { }; + + const destructor_wrapper<void> default_destructor {}; + + template <typename Fx> + inline auto destructor(Fx&& fx) { + return destructor_wrapper<std::decay_t<Fx>>(std::forward<Fx>(fx)); + } + +} // namespace sol + +// end of sol/raii.hpp + +// beginning of sol/policies.hpp + +#include <array> + +namespace sol { + namespace detail { + struct policy_base_tag { }; + } // namespace detail + + template <int Target, int... In> + struct static_stack_dependencies : detail::policy_base_tag { }; + typedef static_stack_dependencies<-1, 1> self_dependency; + template <int... In> + struct returns_self_with : detail::policy_base_tag { }; + typedef returns_self_with<> returns_self; + + struct stack_dependencies : detail::policy_base_tag { + int target; + std::array<int, 64> stack_indices; + std::size_t len; + + template <typename... Args> + stack_dependencies(int stack_target, Args&&... args) : target(stack_target), stack_indices(), len(sizeof...(Args)) { + std::size_t i = 0; + (void)detail::swallow { int(), (stack_indices[i++] = static_cast<int>(std::forward<Args>(args)), int())... }; + } + + int& operator[](std::size_t i) { + return stack_indices[i]; + } + + const int& operator[](std::size_t i) const { + return stack_indices[i]; + } + + std::size_t size() const { + return len; + } + }; + + template <typename F, typename... Policies> + struct policy_wrapper { + typedef std::index_sequence_for<Policies...> indices; + + F value; + std::tuple<Policies...> policies; + + template <typename Fx, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<Fx>, policy_wrapper>>> = meta::enabler> + policy_wrapper(Fx&& fx, Args&&... args) : value(std::forward<Fx>(fx)), policies(std::forward<Args>(args)...) { + } + + policy_wrapper(const policy_wrapper&) = default; + policy_wrapper& operator=(const policy_wrapper&) = default; + policy_wrapper(policy_wrapper&&) = default; + policy_wrapper& operator=(policy_wrapper&&) = default; + }; + + template <typename F, typename... Args> + auto policies(F&& f, Args&&... args) { + return policy_wrapper<std::decay_t<F>, std::decay_t<Args>...>(std::forward<F>(f), std::forward<Args>(args)...); + } + + namespace detail { + template <typename T> + using is_policy = meta::is_specialization_of<T, policy_wrapper>; + + template <typename T> + inline constexpr bool is_policy_v = is_policy<T>::value; + } // namespace detail +} // namespace sol + +// end of sol/policies.hpp + +// beginning of sol/ebco.hpp + +#include <type_traits> +#include <utility> +#include <memory> + +namespace sol { namespace detail { + + template <typename T, std::size_t tag = 0, typename = void> + struct ebco { + T m_value; + + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : m_value(v) {}; + ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : m_value(std::move(v)) {}; + ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) { + m_value = v; + return *this; + } + ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) { + m_value = std::move(v); + return *this; + }; + template <typename Arg, typename... Args, + typename = std::enable_if_t< + !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, + ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>> + ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>) + : m_value(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + + T& value() & noexcept { + return m_value; + } + + T const& value() const& noexcept { + return m_value; + } + + T&& value() && noexcept { + return std::move(m_value); + } + }; + + template <typename T, std::size_t tag> + struct ebco<T, tag, std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T { + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco(const T& v) noexcept(std::is_nothrow_copy_constructible_v<T>) : T(v) {}; + ebco(T&& v) noexcept(std::is_nothrow_move_constructible_v<T>) : T(std::move(v)) {}; + template <typename Arg, typename... Args, + typename = std::enable_if_t< + !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, + ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T> && (sizeof...(Args) > 0 || !std::is_convertible_v<Arg, T>)>> + ebco(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Arg, Args...>) : T(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco& operator=(const T& v) noexcept(std::is_nothrow_copy_assignable_v<T>) { + static_cast<T&>(*this) = v; + return *this; + } + ebco& operator=(T&& v) noexcept(std::is_nothrow_move_assignable_v<T>) { + static_cast<T&>(*this) = std::move(v); + return *this; + }; + + T& value() & noexcept { + return static_cast<T&>(*this); + } + + T const& value() const& noexcept { + return static_cast<T const&>(*this); + } + + T&& value() && noexcept { + return std::move(static_cast<T&>(*this)); + } + }; + + template <typename T, std::size_t tag> + struct ebco<T&, tag> { + private: + T* m_ref; + + public: + ebco() = default; + ebco(const ebco&) = default; + ebco(ebco&&) = default; + ebco(T& v) noexcept : m_ref(std::addressof(v)) {}; + + ebco& operator=(const ebco&) = default; + ebco& operator=(ebco&&) = default; + ebco& operator=(T& v) noexcept { + m_ref = std::addressof(v); + return *this; + } + + T& value() const noexcept { + return *(const_cast<ebco<T&, tag>&>(*this).m_ref); + } + }; + + template <typename T, std::size_t tag> + struct ebco<T&&, tag> { + T&& ref; + + ebco() = default; + ebco(const ebco&) = delete; + ebco(ebco&&) = default; + ebco(T&& v) noexcept : ref(v) {}; + + ebco& operator=(const ebco&) = delete; + ebco& operator=(ebco&&) = delete; + + T& value() & noexcept { + return ref; + } + + const T& value() const& noexcept { + return ref; + } + + T&& value() && noexcept { + return std::move(ref); + } + }; + +}} // namespace sol::detail + +// end of sol/ebco.hpp + +#include <array> +#include <initializer_list> +#include <string> +#include <string_view> +#include <optional> +#include <memory> +#if SOL_IS_ON(SOL_STD_VARIANT) +#include <variant> +#endif // variant shenanigans (thanks, Mac OSX) + +namespace sol { + namespace d { + // shortest possible hidden detail namespace + // when types are transcribed, this saves + // quite a bit of space, actually. + // it's a little unfortunate, but here we are? + template <typename T> + struct u { }; + } // namespace d + + namespace detail { +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + typedef int (*lua_CFunction_noexcept)(lua_State* L) noexcept; +#else + typedef int (*lua_CFunction_noexcept)(lua_State* L); +#endif // noexcept function type for lua_CFunction + + template <typename T> + struct implicit_wrapper { + T& value; + + implicit_wrapper(T* value_) : value(*value_) { + } + + implicit_wrapper(T& value_) : value(value_) { + } + + operator T&() { + return value; + } + + operator T*() { + return std::addressof(value); + } + }; + + struct yield_tag_t { }; + inline constexpr yield_tag_t yield_tag {}; + } // namespace detail + + struct lua_nil_t { }; + inline constexpr lua_nil_t lua_nil {}; + inline bool operator==(lua_nil_t, lua_nil_t) { + return true; + } + inline bool operator!=(lua_nil_t, lua_nil_t) { + return false; + } +#if SOL_IS_ON(SOL_NIL) + using nil_t = lua_nil_t; + inline constexpr const nil_t& nil = lua_nil; +#endif + + namespace detail { + struct non_lua_nil_t { }; + } // namespace detail + + struct metatable_key_t { }; + inline constexpr metatable_key_t metatable_key {}; + + struct global_tag_t { + } inline constexpr global_tag {}; + + struct env_key_t { }; + inline constexpr env_key_t env_key {}; + + struct no_metatable_t { }; + inline constexpr no_metatable_t no_metatable {}; + + template <typename T> + struct yielding_t { + T func; + + yielding_t() = default; + yielding_t(const yielding_t&) = default; + yielding_t(yielding_t&&) = default; + yielding_t& operator=(const yielding_t&) = default; + yielding_t& operator=(yielding_t&&) = default; + template <typename Arg, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<Arg>, yielding_t>>, + meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<Arg>>>> = meta::enabler> + yielding_t(Arg&& arg) : func(std::forward<Arg>(arg)) { + } + template <typename Arg0, typename Arg1, typename... Args> + yielding_t(Arg0&& arg0, Arg1&& arg1, Args&&... args) : func(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...) { + } + }; + + template <typename F> + inline yielding_t<std::decay_t<F>> yielding(F&& f) { + return yielding_t<std::decay_t<F>>(std::forward<F>(f)); + } + + typedef std::remove_pointer_t<lua_CFunction> lua_CFunction_ref; + + template <typename T> + struct non_null { }; + + template <typename... Args> + struct function_sig { }; + + struct upvalue_index { + int index; + upvalue_index(int idx) : index(lua_upvalueindex(idx)) { + } + + operator int() const { + return index; + } + }; + + struct raw_index { + int index; + raw_index(int i) : index(i) { + } + + operator int() const { + return index; + } + }; + + struct absolute_index { + int index; + absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) { + } + + operator int() const { + return index; + } + }; + + struct ref_index { + int index; + ref_index(int idx) : index(idx) { + } + + operator int() const { + return index; + } + }; + + struct stack_count { + int count; + + stack_count(int cnt) : count(cnt) { + } + }; + + struct lightuserdata_value { + void* value; + lightuserdata_value(void* data) : value(data) { + } + operator void*() const { + return value; + } + }; + + struct userdata_value { + private: + void* m_value; + + public: + userdata_value(void* data) : m_value(data) { + } + + void* value() const { + return m_value; + } + + operator void*() const { + return value(); + } + }; + + template <typename T> + struct light { + private: + static_assert(!std::is_void_v<T>, "the type for light will never be void"); + T* m_value; + + public: + light(T& x) : m_value(std::addressof(x)) { + } + light(T* x) : m_value(x) { + } + explicit light(void* x) : m_value(static_cast<T*>(x)) { + } + + T* value() const { + return m_value; + } + + operator T*() const { + return m_value; + } + operator T&() const { + return *m_value; + } + + void* void_value() const { + return m_value; + } + }; + + template <typename T> + auto make_light(T& l) { + typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L; + return light<L>(l); + } + + template <typename T> + struct user : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using base_t::base_t; + + using base_t::value; + + operator std::add_pointer_t<std::remove_reference_t<T>>() { + return std::addressof(this->base_t::value()); + } + + operator std::add_pointer_t<std::add_const_t<std::remove_reference_t<T>>>() const { + return std::addressof(this->base_t::value()); + } + + operator std::add_lvalue_reference_t<T>() { + return this->base_t::value(); + } + + operator std::add_const_t<std::add_lvalue_reference_t<T>>&() const { + return this->base_t::value(); + } + }; + + template <typename T> + auto make_user(T&& u) { + typedef meta::unwrapped_t<meta::unqualified_t<T>> U; + return user<U>(std::forward<T>(u)); + } + + template <typename T> + struct metatable_registry_key : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using base_t::base_t; + + using base_t::value; + }; + + template <typename T> + auto meta_registry_key(T&& key) { + typedef meta::unqualified_t<T> K; + return metatable_registry_key<K>(std::forward<T>(key)); + } + + template <typename... Upvalues> + struct closure { + lua_CFunction c_function; + std::tuple<Upvalues...> upvalues; + closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward<Upvalues>(targetupvalues)...) { + } + }; + + template <> + struct closure<> { + lua_CFunction c_function; + int upvalues; + closure(lua_CFunction f, int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) { + } + }; + + typedef closure<> c_closure; + + template <typename... Args> + closure<Args...> make_closure(lua_CFunction f, Args&&... args) { + return closure<Args...>(f, std::forward<Args>(args)...); + } + + template <typename Sig, typename... Ps> + struct function_arguments { + std::tuple<Ps...> arguments; + template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, function_arguments>> = meta::enabler> + function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + }; + + template <typename Sig = function_sig<>, typename... Args> + auto as_function(Args&&... args) { + return function_arguments<Sig, std::decay_t<Args>...>(std::forward<Args>(args)...); + } + + template <typename Sig = function_sig<>, typename... Args> + auto as_function_reference(Args&&... args) { + return function_arguments<Sig, Args...>(std::forward<Args>(args)...); + } + + template <typename T> + struct as_table_t : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + as_table_t() = default; + as_table_t(const as_table_t&) = default; + as_table_t(as_table_t&&) = default; + as_table_t& operator=(const as_table_t&) = default; + as_table_t& operator=(as_table_t&&) = default; + as_table_t(const meta::unqualified_t<T>& obj) noexcept(std::is_nothrow_constructible_v<base_t, const meta::unqualified_t<T>&>) : base_t(obj) { + } + as_table_t(meta::unqualified_t<T>&& obj) noexcept(std::is_nothrow_constructible_v<base_t, meta::unqualified_t<T>&&>) : base_t(std::move(obj)) { + } + template <typename Arg, typename... Args, + std::enable_if_t< + !std::is_same_v<as_table_t, meta::unqualified_t<Arg>> && !std::is_same_v<meta::unqualified_t<T>, meta::unqualified_t<Arg>>>* = nullptr> + as_table_t(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<base_t, Arg, Args...>) + : base_t(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + + using base_t::value; + + operator std::add_lvalue_reference_t<T>() { + return this->base_t::value(); + } + + operator std::add_const_t<std::add_lvalue_reference_t<T>>() const { + return this->base_t::value(); + } + }; + + template <typename T> + struct nested : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using nested_type = T; + + nested() = default; + nested(const nested&) = default; + nested(nested&&) = default; + nested& operator=(const nested&) = default; + nested& operator=(nested&&) = default; + nested(const meta::unqualified_t<T>& obj) noexcept(std::is_nothrow_constructible_v<base_t, const meta::unqualified_t<T>&>) : base_t(obj) { + } + nested(meta::unqualified_t<T>&& obj) noexcept(std::is_nothrow_constructible_v<base_t, meta::unqualified_t<T>&&>) : base_t(std::move(obj)) { + } + template <typename Arg, typename... Args, + std::enable_if_t< + !std::is_same_v<nested, meta::unqualified_t<Arg>> && !std::is_same_v<meta::unqualified_t<T>, meta::unqualified_t<Arg>>>* = nullptr> + nested(Arg&& arg, Args&&... args) noexcept(std::is_nothrow_constructible_v<base_t, Arg, Args...>) + : base_t(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + + using base_t::value; + + operator std::add_lvalue_reference_t<T>() { + return this->base_t::value(); + } + + operator std::add_const_t<std::add_lvalue_reference_t<T>>() const { + return this->base_t::value(); + } + }; + + struct nested_tag_t { }; + constexpr inline nested_tag_t nested_tag {}; + + template <typename T> + as_table_t<T> as_table_ref(T&& container) { + return as_table_t<T>(std::forward<T>(container)); + } + + template <typename T> + as_table_t<meta::unqualified_t<T>> as_table(T&& container) { + return as_table_t<meta::unqualified_t<T>>(std::forward<T>(container)); + } + + template <typename T> + nested<T> as_nested_ref(T&& container) { + return nested<T>(std::forward<T>(container)); + } + + template <typename T> + nested<meta::unqualified_t<T>> as_nested(T&& container) { + return nested<meta::unqualified_t<T>>(std::forward<T>(container)); + } + + template <typename T> + struct as_container_t : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using type = T; + + as_container_t() = default; + as_container_t(const as_container_t&) = default; + as_container_t(as_container_t&&) = default; + as_container_t& operator=(const as_container_t&) = default; + as_container_t& operator=(as_container_t&&) = default; + + using base_t::base_t; + + using base_t::value; + + operator std::add_lvalue_reference_t<T>() { + return value(); + } + }; + + template <typename T> + auto as_container(T&& value) { + return as_container_t<T>(std::forward<T>(value)); + } + + template <typename T> + struct push_invoke_t : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + push_invoke_t() = default; + push_invoke_t(const push_invoke_t&) = default; + push_invoke_t(push_invoke_t&&) = default; + push_invoke_t& operator=(const push_invoke_t&) = default; + push_invoke_t& operator=(push_invoke_t&&) = default; + + using base_t::base_t; + + using base_t::value; + }; + + template <typename Fx> + auto push_invoke(Fx&& fx) { + return push_invoke_t<Fx>(std::forward<Fx>(fx)); + } + + template <typename T> + struct forward_as_value_t : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + forward_as_value_t() = default; + forward_as_value_t(const forward_as_value_t&) = default; + forward_as_value_t(forward_as_value_t&&) = default; + forward_as_value_t& operator=(const forward_as_value_t&) = default; + forward_as_value_t& operator=(forward_as_value_t&&) = default; + + using base_t::base_t; + + using base_t::value; + }; + + template <typename T> + auto pass_as_value(T& value_ref_) { + return forward_as_value_t<T>(value_ref_); + } + + struct override_value_t { }; + constexpr inline override_value_t override_value = override_value_t(); + struct update_if_empty_t { }; + constexpr inline update_if_empty_t update_if_empty = update_if_empty_t(); + struct create_if_nil_t { }; + constexpr inline create_if_nil_t create_if_nil = create_if_nil_t(); + + namespace detail { + enum insert_mode { none = 0x0, update_if_empty = 0x01, override_value = 0x02, create_if_nil = 0x04 }; + + template <typename T, typename...> + using is_insert_mode = std::integral_constant<bool, + std::is_same_v<T, override_value_t> || std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, create_if_nil_t>>; + + template <typename T, typename...> + using is_not_insert_mode = meta::neg<is_insert_mode<T>>; + } // namespace detail + + struct this_state { + lua_State* L; + + this_state(lua_State* Ls) : L(Ls) { + } + + operator lua_State*() const noexcept { + return lua_state(); + } + + lua_State* operator->() const noexcept { + return lua_state(); + } + + lua_State* lua_state() const noexcept { + return L; + } + }; + + struct this_main_state { + lua_State* L; + + this_main_state(lua_State* Ls) : L(Ls) { + } + + operator lua_State*() const noexcept { + return lua_state(); + } + + lua_State* operator->() const noexcept { + return lua_state(); + } + + lua_State* lua_state() const noexcept { + return L; + } + }; + + struct new_table { + int sequence_hint = 0; + int map_hint = 0; + + new_table() = default; + new_table(const new_table&) = default; + new_table(new_table&&) = default; + new_table& operator=(const new_table&) = default; + new_table& operator=(new_table&&) = default; + + new_table(int sequence_hint_, int map_hint_ = 0) noexcept : sequence_hint(sequence_hint_), map_hint(map_hint_) { + } + }; + + const new_table create = {}; + + enum class lib : unsigned char { + // print, assert, and other base functions + base, + // require and other package functions + package, + // coroutine functions and utilities + coroutine, + // string library + string, + // functionality from the OS + os, + // all things math + math, + // the table manipulator and observer functions + table, + // the debug library + debug, + // the bit library: different based on which you're using + bit32, + // input/output library + io, + // LuaJIT only + ffi, + // LuaJIT only + jit, + // library for handling utf8: new to Lua + utf8, + // do not use + count + }; + + enum class call_syntax { dot = 0, colon = 1 }; + + enum class load_mode { + any = 0, + text = 1, + binary = 2, + }; + + enum class call_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + handler = LUA_ERRERR, + gc = LUA_ERRGCMM, + syntax = LUA_ERRSYNTAX, + file = LUA_ERRFILE, + }; + + enum class thread_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + handler = LUA_ERRERR, + dead = -1, + }; + + enum class load_status : int { + ok = LUA_OK, + syntax = LUA_ERRSYNTAX, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + file = LUA_ERRFILE, + }; + + enum class gc_mode : int { + incremental = 0, + generational = 1, + default_value = incremental, + }; + + enum class type : int { + none = LUA_TNONE, + lua_nil = LUA_TNIL, +#if SOL_IS_ON(SOL_NIL) + nil = lua_nil, +#endif // Objective C/C++ Keyword that's found in OSX SDK and OBJC -- check for all forms to protect + string = LUA_TSTRING, + number = LUA_TNUMBER, + thread = LUA_TTHREAD, + boolean = LUA_TBOOLEAN, + function = LUA_TFUNCTION, + userdata = LUA_TUSERDATA, + lightuserdata = LUA_TLIGHTUSERDATA, + table = LUA_TTABLE, + poly = -0xFFFF + }; + + inline const std::string& to_string(call_status c) { + static const std::array<std::string, 10> names { { "ok", + "yielded", + "runtime", + "memory", + "handler", + "gc", + "syntax", + "file", + "CRITICAL_EXCEPTION_FAILURE", + "CRITICAL_INDETERMINATE_STATE_FAILURE" } }; + switch (c) { + case call_status::ok: + return names[0]; + case call_status::yielded: + return names[1]; + case call_status::runtime: + return names[2]; + case call_status::memory: + return names[3]; + case call_status::handler: + return names[4]; + case call_status::gc: + return names[5]; + case call_status::syntax: + return names[6]; + case call_status::file: + return names[7]; + } + if (static_cast<std::ptrdiff_t>(c) == -1) { + // One of the many cases where a critical exception error has occurred + return names[8]; + } + return names[9]; + } + + inline bool is_indeterminate_call_failure(call_status c) { + switch (c) { + case call_status::ok: + case call_status::yielded: + case call_status::runtime: + case call_status::memory: + case call_status::handler: + case call_status::gc: + case call_status::syntax: + case call_status::file: + return false; + } + return true; + } + + inline const std::string& to_string(load_status c) { + static const std::array<std::string, 7> names { + { "ok", "memory", "gc", "syntax", "file", "CRITICAL_EXCEPTION_FAILURE", "CRITICAL_INDETERMINATE_STATE_FAILURE" } + }; + switch (c) { + case load_status::ok: + return names[0]; + case load_status::memory: + return names[1]; + case load_status::gc: + return names[2]; + case load_status::syntax: + return names[3]; + case load_status::file: + return names[4]; + } + if (static_cast<int>(c) == -1) { + // One of the many cases where a critical exception error has occurred + return names[5]; + } + return names[6]; + } + + inline const std::string& to_string(load_mode c) { + static const std::array<std::string, 3> names { { + "bt", + "t", + "b", + } }; + return names[static_cast<std::size_t>(c)]; + } + + enum class meta_function : unsigned { + construct, + index, + new_index, + mode, + call, + call_function = call, + metatable, + to_string, + length, + unary_minus, + addition, + subtraction, + multiplication, + division, + modulus, + power_of, + involution = power_of, + concatenation, + equal_to, + less_than, + less_than_or_equal_to, + garbage_collect, + floor_division, + bitwise_left_shift, + bitwise_right_shift, + bitwise_not, + bitwise_and, + bitwise_or, + bitwise_xor, + pairs, + ipairs, + next, + type, + type_info, + call_construct, + storage, + gc_names, + static_index, + static_new_index, + }; + + typedef meta_function meta_method; + + inline const std::array<std::string, 37>& meta_function_names() { + static const std::array<std::string, 37> names = { { "new", + "__index", + "__newindex", + "__mode", + "__call", + "__metatable", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", + + "__idiv", + "__shl", + "__shr", + "__bnot", + "__band", + "__bor", + "__bxor", + + "__pairs", + "__ipairs", + "next", + + "__type", + "__typeinfo", + "__sol.call_new", + "__sol.storage", + "__sol.gc_names", + "__sol.static_index", + "__sol.static_new_index" } }; + return names; + } + + inline const std::string& to_string(meta_function mf) { + return meta_function_names()[static_cast<std::size_t>(mf)]; + } + + inline type type_of(lua_State* L, int index) { + return static_cast<type>(lua_type(L, index)); + } + + inline std::string type_name(lua_State* L, type t) { + return lua_typename(L, static_cast<int>(t)); + } + + template <typename T> + struct is_stateless_lua_reference + : std::integral_constant<bool, + (std::is_base_of_v<stateless_stack_reference, T> || std::is_base_of_v<stateless_reference, T>)&&( + !std::is_base_of_v<stack_reference, T> && !std::is_base_of_v<reference, T> && !std::is_base_of_v<main_reference, T>)> { }; + + template <typename T> + inline constexpr bool is_stateless_lua_reference_v = is_stateless_lua_reference<T>::value; + + template <typename T> + struct is_lua_reference + : std::integral_constant<bool, + std::is_base_of_v<reference, + T> || std::is_base_of_v<main_reference, T> || std::is_base_of_v<stack_reference, T> || std::is_base_of_v<stateless_stack_reference, T> || std::is_base_of_v<stateless_reference, T>> { + }; + + template <typename T> + inline constexpr bool is_lua_reference_v = is_lua_reference<T>::value; + + template <typename T> + struct is_lua_reference_or_proxy : std::integral_constant<bool, is_lua_reference_v<T> || meta::is_specialization_of_v<T, table_proxy>> { }; + + template <typename T> + inline constexpr bool is_lua_reference_or_proxy_v = is_lua_reference_or_proxy<T>::value; + + template <typename T> + struct is_transparent_argument + : std::integral_constant<bool, + std::is_same_v<meta::unqualified_t<T>, + this_state> || std::is_same_v<meta::unqualified_t<T>, this_main_state> || std::is_same_v<meta::unqualified_t<T>, this_environment> || std::is_same_v<meta::unqualified_t<T>, variadic_args>> { + }; + + template <typename T> + constexpr inline bool is_transparent_argument_v = is_transparent_argument<T>::value; + + template <typename T> + struct is_variadic_arguments : meta::any<std::is_same<T, variadic_args>, meta::is_optional<T>> { }; + + template <typename T> + struct is_container + : std::integral_constant<bool, + !std::is_same_v<state_view, + T> && !std::is_same_v<state, T> && !meta::is_initializer_list_v<T> && !meta::is_string_like_v<T> && !meta::is_string_literal_array_v<T> && !is_transparent_argument_v<T> && !is_lua_reference_v<T> && (meta::has_begin_end_v<T> || std::is_array_v<T>)> { + }; + + template <typename T> + constexpr inline bool is_container_v = is_container<T>::value; + + template <typename T> + struct is_to_stringable : meta::any<meta::supports_to_string_member<meta::unqualified_t<T>>, meta::supports_adl_to_string<meta::unqualified_t<T>>, + meta::supports_op_left_shift<std::ostream, meta::unqualified_t<T>>> { }; + + template <typename T> + inline constexpr bool is_to_stringable_v = is_to_stringable<T>::value; + + template <typename T> + struct is_callable : std::true_type { }; + + template <typename T> + inline constexpr bool is_callable_v = is_callable<T>::value; + + namespace detail { + template <typename T, typename = void> + struct lua_type_of : std::integral_constant<type, type::userdata> { }; + + template <typename C, typename T, typename A> + struct lua_type_of<std::basic_string<C, T, A>> : std::integral_constant<type, type::string> { }; + + template <typename C, typename T> + struct lua_type_of<basic_string_view<C, T>> : std::integral_constant<type, type::string> { }; + + template <std::size_t N> + struct lua_type_of<char[N]> : std::integral_constant<type, type::string> { }; + + template <std::size_t N> + struct lua_type_of<wchar_t[N]> : std::integral_constant<type, type::string> { }; + +#if SOL_IS_ON(SOL_CHAR8_T) + template <std::size_t N> + struct lua_type_of<char8_t[N]> : std::integral_constant<type, type::string> { }; +#endif + + template <std::size_t N> + struct lua_type_of<char16_t[N]> : std::integral_constant<type, type::string> { }; + + template <std::size_t N> + struct lua_type_of<char32_t[N]> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<char> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<wchar_t> : std::integral_constant<type, type::string> { }; + +#if SOL_IS_ON(SOL_CHAR8_T) + template <> + struct lua_type_of<char8_t> : std::integral_constant<type, type::string> { }; +#endif + + template <> + struct lua_type_of<char16_t> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<char32_t> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<const char*> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<const wchar_t*> : std::integral_constant<type, type::string> { }; + +#if SOL_IS_ON(SOL_CHAR8_T) + template <> + struct lua_type_of<const char8_t*> : std::integral_constant<type, type::string> { }; +#endif + + template <> + struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> { }; + + template <> + struct lua_type_of<bool> : std::integral_constant<type, type::boolean> { }; + + template <> + struct lua_type_of<lua_nil_t> : std::integral_constant<type, type::lua_nil> { }; + + template <> + struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> { }; + + template <> + struct lua_type_of<lua_value> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<detail::non_lua_nil_t> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> { }; + + template <> + struct lua_type_of<error> : std::integral_constant<type, type::string> { }; + + template <bool b, typename Base> + struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> { }; + + template <typename Base> + struct lua_type_of<basic_lua_table<Base>> : std::integral_constant<type, type::table> { }; + + template <typename Base> + struct lua_type_of<basic_metatable<Base>> : std::integral_constant<type, type::table> { }; + + template <typename T, typename Base> + struct lua_type_of<basic_usertype<T, Base>> : std::integral_constant<type, type::table> { }; + + template <> + struct lua_type_of<metatable_key_t> : std::integral_constant<type, type::table> { }; + + template <typename B> + struct lua_type_of<basic_environment<B>> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<env_key_t> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<new_table> : std::integral_constant<type, type::table> { }; + + template <typename T> + struct lua_type_of<as_table_t<T>> : std::integral_constant<type, type::table> { }; + + template <typename T> + struct lua_type_of<std::initializer_list<T>> : std::integral_constant<type, type::table> { }; + + template <bool b> + struct lua_type_of<basic_reference<b>> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> { }; + + template <typename Base> + struct lua_type_of<basic_object<Base>> : std::integral_constant<type, type::poly> { }; + + template <typename... Args> + struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> { }; + + template <typename A, typename B> + struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<void*> : std::integral_constant<type, type::lightuserdata> { }; + + template <> + struct lua_type_of<const void*> : std::integral_constant<type, type::lightuserdata> { }; + + template <> + struct lua_type_of<lightuserdata_value> : std::integral_constant<type, type::lightuserdata> { }; + + template <> + struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> { }; + + template <typename T> + struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> { }; + + template <typename T> + struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> { }; + + template <typename Base> + struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> { }; + + template <typename Base> + struct lua_type_of<basic_userdata<Base>> : std::integral_constant<type, type::userdata> { }; + + template <> + struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> { }; + + template <> + struct lua_type_of<std::remove_pointer_t<lua_CFunction>> : std::integral_constant<type, type::function> { }; + + template <typename Base, bool aligned> + struct lua_type_of<basic_function<Base, aligned>> : std::integral_constant<type, type::function> { }; + + template <typename Base, bool aligned, typename Handler> + struct lua_type_of<basic_protected_function<Base, aligned, Handler>> : std::integral_constant<type, type::function> { }; + + template <typename Base> + struct lua_type_of<basic_coroutine<Base>> : std::integral_constant<type, type::function> { }; + + template <typename Base> + struct lua_type_of<basic_thread<Base>> : std::integral_constant<type, type::thread> { }; + + template <typename Signature> + struct lua_type_of<std::function<Signature>> : std::integral_constant<type, type::function> { }; + + template <typename T> + struct lua_type_of<optional<T>> : std::integral_constant<type, type::poly> { }; + + template <typename T> + struct lua_type_of<std::optional<T>> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<variadic_args> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<variadic_results> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<stack_count> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<this_state> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<this_main_state> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<this_environment> : std::integral_constant<type, type::poly> { }; + + template <> + struct lua_type_of<type> : std::integral_constant<type, type::poly> { }; + +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + template <typename T> + struct lua_type_of<T*> : std::integral_constant<type, std::is_function_v<T> ? type::function : type::userdata> { }; +#else + template <typename T> + struct lua_type_of<T*> : std::integral_constant<type, type::userdata> { }; +#endif + + template <typename T> + struct lua_type_of<T, std::enable_if_t<std::is_arithmetic_v<T> || std::is_same_v<T, lua_Number> || std::is_same_v<T, lua_Integer>>> + : std::integral_constant<type, type::number> { }; + + template <typename T> + struct lua_type_of<T, std::enable_if_t<std::is_function_v<T>>> : std::integral_constant<type, type::function> { }; + + template <typename T> + struct lua_type_of<T, std::enable_if_t<std::is_enum_v<T>>> : std::integral_constant<type, type::number> { }; + + template <> + struct lua_type_of<meta_function> : std::integral_constant<type, type::string> { }; + +#if SOL_IS_ON(SOL_STD_VARIANT) + template <typename... Tn> + struct lua_type_of<std::variant<Tn...>> : std::integral_constant<type, type::poly> { }; +#endif // std::variant deployment sucks on Clang + + template <typename T> + struct lua_type_of<nested<T>> : meta::conditional_t<::sol::is_container_v<T>, std::integral_constant<type, type::table>, lua_type_of<T>> { }; + + template <typename C, C v, template <typename...> class V, typename... Args> + struct accumulate : std::integral_constant<C, v> { }; + + template <typename C, C v, template <typename...> class V, typename T, typename... Args> + struct accumulate<C, v, V, T, Args...> : accumulate<C, v + V<T>::value, V, Args...> { }; + + template <typename C, C v, template <typename...> class V, typename List> + struct accumulate_list; + + template <typename C, C v, template <typename...> class V, typename... Args> + struct accumulate_list<C, v, V, types<Args...>> : accumulate<C, v, V, Args...> { }; + } // namespace detail + + template <typename T> + struct lua_type_of : detail::lua_type_of<T> { + typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; + }; + + template <typename T> + inline constexpr type lua_type_of_v = lua_type_of<T>::value; + + template <typename T> + struct lua_size : std::integral_constant<int, 1> { + typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; + }; + + template <typename A, typename B> + struct lua_size<std::pair<A, B>> : std::integral_constant<int, lua_size<A>::value + lua_size<B>::value> { }; + + template <typename... Args> + struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> { }; + + template <typename T> + inline constexpr int lua_size_v = lua_size<T>::value; + + namespace detail { + // MSVC's decltype detection is broken, which breaks other + // parts of the code. So we add more workarounds. The moment it's fixed, + // we take it away and break everyone that doesn't upgrade. + template <typename T> + using is_msvc_callable_rigged = meta::any<meta::is_specialization_of<T, push_invoke_t>, meta::is_specialization_of<T, as_table_t>, + meta::is_specialization_of<T, forward_as_value_t>, meta::is_specialization_of<T, as_container_t>, meta::is_specialization_of<T, nested>, + meta::is_specialization_of<T, yielding_t>>; + + template <typename T> + inline constexpr bool is_msvc_callable_rigged_v = is_msvc_callable_rigged<T>::value; + } // namespace detail + + template <typename T> + struct is_lua_primitive + : std::integral_constant<bool, + type::userdata + != lua_type_of_v< + T> || ((type::userdata == lua_type_of_v<T>)&&meta::meta_detail::has_internal_marker_v<lua_type_of<T>> && !meta::meta_detail::has_internal_marker_v<lua_size<T>>) + || is_lua_reference_or_proxy_v<T> || meta::is_specialization_of_v<T, std::tuple> || meta::is_specialization_of_v<T, std::pair>> { }; + + template <typename T> + constexpr inline bool is_lua_primitive_v = is_lua_primitive<T>::value; + + template <typename T> + struct is_value_semantic_for_function +#if SOL_IS_ON(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + : std::true_type { + }; +#else + : std::false_type { + }; +#endif + + template <typename T> + constexpr inline bool is_value_semantic_for_function_v = is_value_semantic_for_function<T>::value; + + template <typename T> + struct is_main_threaded : std::is_base_of<main_reference, T> { }; + + template <typename T> + inline constexpr bool is_main_threaded_v = is_main_threaded<T>::value; + + template <typename T> + struct is_stack_based : std::is_base_of<stack_reference, T> { }; + template <> + struct is_stack_based<variadic_args> : std::true_type { }; + template <> + struct is_stack_based<unsafe_function_result> : std::true_type { }; + template <> + struct is_stack_based<protected_function_result> : std::true_type { }; + template <> + struct is_stack_based<stack_proxy> : std::true_type { }; + template <> + struct is_stack_based<stack_proxy_base> : std::true_type { }; + template <> + struct is_stack_based<stack_count> : std::true_type { }; + + template <typename T> + constexpr inline bool is_stack_based_v = is_stack_based<T>::value; + + template <typename T> + struct is_lua_primitive<T*> : std::true_type { }; + template <> + struct is_lua_primitive<unsafe_function_result> : std::true_type { }; + template <> + struct is_lua_primitive<protected_function_result> : std::true_type { }; + template <typename T> + struct is_lua_primitive<std::reference_wrapper<T>> : std::true_type { }; + template <typename T> + struct is_lua_primitive<user<T>> : std::true_type { }; + template <typename T> + struct is_lua_primitive<light<T>> : is_lua_primitive<T*> { }; + template <typename T> + struct is_lua_primitive<optional<T>> : std::true_type { }; + template <typename T> + struct is_lua_primitive<std::optional<T>> : std::true_type { }; + template <typename T> + struct is_lua_primitive<as_table_t<T>> : std::true_type { }; + template <typename T> + struct is_lua_primitive<nested<T>> : std::true_type { }; + template <> + struct is_lua_primitive<userdata_value> : std::true_type { }; + template <> + struct is_lua_primitive<lightuserdata_value> : std::true_type { }; + template <> + struct is_lua_primitive<stack_proxy> : std::true_type { }; + template <> + struct is_lua_primitive<stack_proxy_base> : std::true_type { }; + template <typename T> + struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> { }; + + template <typename T> + struct is_lua_index : std::is_integral<T> { }; + template <> + struct is_lua_index<raw_index> : std::true_type { }; + template <> + struct is_lua_index<absolute_index> : std::true_type { }; + template <> + struct is_lua_index<ref_index> : std::true_type { }; + template <> + struct is_lua_index<upvalue_index> : std::true_type { }; + + template <typename Signature> + struct lua_bind_traits : meta::bind_traits<Signature> { + private: + typedef meta::bind_traits<Signature> base_t; + + public: + typedef std::integral_constant<bool, meta::count_for<is_variadic_arguments, typename base_t::args_list>::value != 0> runtime_variadics_t; + static const std::size_t true_arity = base_t::arity; + static const std::size_t arity = detail::accumulate_list<std::size_t, 0, lua_size, typename base_t::args_list>::value + - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; + static const std::size_t true_free_arity = base_t::free_arity; + static const std::size_t free_arity = detail::accumulate_list<std::size_t, 0, lua_size, typename base_t::free_args_list>::value + - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; + }; + + template <typename T> + struct is_table : std::false_type { }; + template <bool x, typename T> + struct is_table<basic_table_core<x, T>> : std::true_type { }; + template <typename T> + struct is_table<basic_lua_table<T>> : std::true_type { }; + + template <typename T> + inline constexpr bool is_table_v = is_table<T>::value; + + template <typename T> + struct is_global_table : std::false_type { }; + template <typename T> + struct is_global_table<basic_table_core<true, T>> : std::true_type { }; + + template <typename T> + inline constexpr bool is_global_table_v = is_global_table<T>::value; + + template <typename T> + struct is_stack_table : std::false_type { }; + template <bool x, typename T> + struct is_stack_table<basic_table_core<x, T>> : std::integral_constant<bool, std::is_base_of_v<stack_reference, T>> { }; + template <typename T> + struct is_stack_table<basic_lua_table<T>> : std::integral_constant<bool, std::is_base_of_v<stack_reference, T>> { }; + + template <typename T> + inline constexpr bool is_stack_table_v = is_stack_table<T>::value; + + template <typename T> + struct is_function : std::false_type { }; + template <typename T, bool aligned> + struct is_function<basic_function<T, aligned>> : std::true_type { }; + template <typename T, bool aligned, typename Handler> + struct is_function<basic_protected_function<T, aligned, Handler>> : std::true_type { }; + + template <typename T> + using is_lightuserdata = meta::is_specialization_of<T, basic_lightuserdata>; + + template <typename T> + inline constexpr bool is_lightuserdata_v = is_lightuserdata<T>::value; + + template <typename T> + using is_userdata = meta::is_specialization_of<T, basic_userdata>; + + template <typename T> + inline constexpr bool is_userdata_v = is_userdata<T>::value; + + template <typename T> + using is_environment = std::integral_constant<bool, is_userdata_v<T> || is_table_v<T> || meta::is_specialization_of_v<T, basic_environment>>; + + template <typename T> + inline constexpr bool is_environment_v = is_environment<T>::value; + + template <typename T> + using is_table_like = std::integral_constant<bool, is_table_v<T> || is_environment_v<T> || is_userdata_v<T>>; + + template <typename T> + inline constexpr bool is_table_like_v = is_table_like<T>::value; + + template <typename T> + struct is_automagical + : std::integral_constant<bool, + (SOL_IS_ON(SOL_DEFAULT_AUTOMAGICAL_USERTYPES)) + || (std::is_array_v< + meta::unqualified_t<T>> || (!std::is_same_v<meta::unqualified_t<T>, state> && !std::is_same_v<meta::unqualified_t<T>, state_view>))> { + }; + + template <typename T> + inline type type_of() { + return lua_type_of<meta::unqualified_t<T>>::value; + } + + namespace detail { + template <typename T> + struct is_non_factory_constructor : std::false_type { }; + + template <typename... Args> + struct is_non_factory_constructor<constructors<Args...>> : std::true_type { }; + + template <typename... Args> + struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type { }; + + template <> + struct is_non_factory_constructor<no_construction> : std::true_type { }; + + template <typename T> + inline constexpr bool is_non_factory_constructor_v = is_non_factory_constructor<T>::value; + + template <typename T> + struct is_constructor : is_non_factory_constructor<T> { }; + + template <typename... Args> + struct is_constructor<factory_wrapper<Args...>> : std::true_type { }; + + template <typename T> + struct is_constructor<protect_t<T>> : is_constructor<meta::unqualified_t<T>> { }; + + template <typename F, typename... Policies> + struct is_constructor<policy_wrapper<F, Policies...>> : is_constructor<meta::unqualified_t<F>> { }; + + template <typename T> + inline constexpr bool is_constructor_v = is_constructor<T>::value; + + template <typename... Args> + using any_is_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; + + template <typename... Args> + inline constexpr bool any_is_constructor_v = any_is_constructor<Args...>::value; + + template <typename T> + struct is_destructor : std::false_type { }; + + template <typename Fx> + struct is_destructor<destructor_wrapper<Fx>> : std::true_type { }; + + template <typename... Args> + using any_is_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>; + + template <typename... Args> + inline constexpr bool any_is_destructor_v = any_is_destructor<Args...>::value; + } // namespace detail + + template <typename T> + using is_lua_c_function = meta::any<std::is_same<lua_CFunction, T>, std::is_same<detail::lua_CFunction_noexcept, T>, std::is_same<lua_CFunction_ref, T>>; + + template <typename T> + inline constexpr bool is_lua_c_function_v = is_lua_c_function<T>::value; + + enum class automagic_flags : unsigned { + none = 0x000u, + default_constructor = 0x001, + destructor = 0x002u, + pairs_operator = 0x004u, + to_string_operator = 0x008u, + call_operator = 0x010u, + less_than_operator = 0x020u, + less_than_or_equal_to_operator = 0x040u, + length_operator = 0x080u, + equal_to_operator = 0x100u, + all = default_constructor | destructor | pairs_operator | to_string_operator | call_operator | less_than_operator | less_than_or_equal_to_operator + | length_operator | equal_to_operator + }; + + inline constexpr automagic_flags operator|(automagic_flags left, automagic_flags right) noexcept { + return static_cast<automagic_flags>( + static_cast<std::underlying_type_t<automagic_flags>>(left) | static_cast<std::underlying_type_t<automagic_flags>>(right)); + } + + inline constexpr automagic_flags operator&(automagic_flags left, automagic_flags right) noexcept { + return static_cast<automagic_flags>( + static_cast<std::underlying_type_t<automagic_flags>>(left) & static_cast<std::underlying_type_t<automagic_flags>>(right)); + } + + inline constexpr automagic_flags& operator|=(automagic_flags& left, automagic_flags right) noexcept { + left = left | right; + return left; + } + + inline constexpr automagic_flags& operator&=(automagic_flags& left, automagic_flags right) noexcept { + left = left & right; + return left; + } + + template <typename Left, typename Right> + constexpr bool has_flag(Left left, Right right) noexcept { + return (left & right) == right; + } + + template <typename Left, typename Right> + constexpr bool has_any_flag(Left left, Right right) noexcept { + return (left & right) != static_cast<Left>(static_cast<std::underlying_type_t<Left>>(0)); + } + + template <typename Left, typename Right> + constexpr auto clear_flags(Left left, Right right) noexcept { + return static_cast<Left>(static_cast<std::underlying_type_t<Left>>(left) & ~static_cast<std::underlying_type_t<Right>>(right)); + } + + struct automagic_enrollments { + bool default_constructor = true; + bool destructor = true; + bool pairs_operator = true; + bool to_string_operator = true; + bool call_operator = true; + bool less_than_operator = true; + bool less_than_or_equal_to_operator = true; + bool length_operator = true; + bool equal_to_operator = true; + }; + + template <automagic_flags compile_time_defaults = automagic_flags::all> + struct constant_automagic_enrollments : public automagic_enrollments { }; + +} // namespace sol + +// end of sol/types.hpp + +#include <exception> +#include <cstring> + +#if SOL_IS_ON(SOL_PRINT_ERRORS) +#include <iostream> +#endif + +namespace sol { + // must push a single object to be the error object + // NOTE: the VAST MAJORITY of all Lua libraries -- C or otherwise -- expect a string for the type of error + // break this convention at your own risk + using exception_handler_function = int (*)(lua_State*, optional<const std::exception&>, string_view); + + namespace detail { + inline const char (&default_exception_handler_name())[11] { + static const char name[11] = "sol.\xE2\x98\xA2\xE2\x98\xA2"; + return name; + } + + // must push at least 1 object on the stack + inline int default_exception_handler(lua_State* L, optional<const std::exception&>, string_view what) { +#if SOL_IS_ON(SOL_PRINT_ERRORS) + std::cerr << "[sol2] An exception occurred: "; + std::cerr.write(what.data(), static_cast<std::streamsize>(what.size())); + std::cerr << std::endl; +#endif + lua_pushlstring(L, what.data(), what.size()); + return 1; + } + + inline int call_exception_handler(lua_State* L, optional<const std::exception&> maybe_ex, string_view what) { + lua_getglobal(L, default_exception_handler_name()); + type t = static_cast<type>(lua_type(L, -1)); + if (t != type::lightuserdata) { + lua_pop(L, 1); + return default_exception_handler(L, std::move(maybe_ex), std::move(what)); + } + void* vfunc = lua_touserdata(L, -1); + lua_pop(L, 1); + if (vfunc == nullptr) { + return default_exception_handler(L, std::move(maybe_ex), std::move(what)); + } + exception_handler_function exfunc = reinterpret_cast<exception_handler_function>(vfunc); + return exfunc(L, std::move(maybe_ex), std::move(what)); + } + +#if SOL_IS_OFF(SOL_EXCEPTIONS) + template <lua_CFunction f> + int static_trampoline(lua_State* L) noexcept { + return f(L); + } + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + template <lua_CFunction_noexcept f> + int static_trampoline_noexcept(lua_State* L) noexcept { + return f(L); + } +#else + template <lua_CFunction f> + int static_trampoline_noexcept(lua_State* L) noexcept { + return f(L); + } +#endif + + template <typename Fx, typename... Args> + int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept { + return f(L, std::forward<Args>(args)...); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) noexcept { + return trampoline(L, f); + } +#else + + inline int lua_cfunction_trampoline(lua_State* L, lua_CFunction f) { +#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) + return f(L); +#else + try { + return f(L); + } + catch (const char* cs) { + call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs)); + } + catch (const std::string& s) { + call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size())); + } + catch (const std::exception& e) { + call_exception_handler(L, optional<const std::exception&>(e), e.what()); + } +#if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) + // LuaJIT cannot have the catchall when the safe propagation is on + // but LuaJIT will swallow all C++ errors + // if we don't at least catch std::exception ones + catch (...) { + call_exception_handler(L, optional<const std::exception&>(nullopt), "caught (...) exception"); + } +#endif // LuaJIT cannot have the catchall, but we must catch std::exceps for it + return lua_error(L); +#endif // Safe exceptions + } + + template <lua_CFunction f> + int static_trampoline(lua_State* L) { + return lua_cfunction_trampoline(L, f); + } + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + template <lua_CFunction_noexcept f> + int static_trampoline_noexcept(lua_State* L) noexcept { + return f(L); + } +#else + template <lua_CFunction f> + int static_trampoline_noexcept(lua_State* L) noexcept { + return f(L); + } +#endif + + template <typename Fx, typename... Args> + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + if constexpr (meta::bind_traits<meta::unqualified_t<Fx>>::is_noexcept) { + return f(L, std::forward<Args>(args)...); + } + else { +#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) + return f(L, std::forward<Args>(args)...); +#else + try { + return f(L, std::forward<Args>(args)...); + } + catch (const char* cs) { + call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(cs)); + } + catch (const std::string& s) { + call_exception_handler(L, optional<const std::exception&>(nullopt), string_view(s.c_str(), s.size())); + } + catch (const std::exception& e) { + call_exception_handler(L, optional<const std::exception&>(e), e.what()); + } +#if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) + // LuaJIT cannot have the catchall when the safe propagation is on + // but LuaJIT will swallow all C++ errors + // if we don't at least catch std::exception ones + catch (...) { + call_exception_handler(L, optional<const std::exception&>(nullopt), "caught (...) exception"); + } +#endif + return lua_error(L); +#endif + } + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#endif // Exceptions vs. No Exceptions + + template <typename F, F fx> + inline int typed_static_trampoline(lua_State* L) { +#if 0 + // TODO: you must evaluate the get/check_get of every + // argument, to ensure it doesn't throw + // (e.g., for the sol_lua_check_access extension point!) + // This incluudes properly noexcept-ing all the above + // trampolines / safety nets + if constexpr (meta::bind_traits<F>::is_noexcept) { + return static_trampoline_noexcept<fx>(L); + } + else +#endif + { return static_trampoline<fx>(L); } + } + } // namespace detail + + inline void set_default_exception_handler(lua_State* L, exception_handler_function exf = &detail::default_exception_handler) { + static_assert(sizeof(void*) >= sizeof(exception_handler_function), + "void* storage is too small to transport the exception handler: please file a bug on the sol2 issue tracker to get this looked at!"); + void* storage; + std::memcpy(&storage, &exf, sizeof(exception_handler_function)); + lua_pushlightuserdata(L, storage); + lua_setglobal(L, detail::default_exception_handler_name()); + } +} // namespace sol + +// end of sol/trampoline.hpp + +// beginning of sol/stack_core.hpp + +// beginning of sol/inheritance.hpp + +// beginning of sol/usertype_traits.hpp + +// beginning of sol/demangle.hpp + +#include <string> +#include <array> +#include <cctype> +#if SOL_IS_ON(SOL_MINGW_CCTYPE_IS_POISONED) +extern "C" { +#include <ctype.h> +} +#endif // MinGW is on some stuff +#include <locale> + +namespace sol { namespace detail { + inline constexpr std::array<string_view, 9> removals { { "{anonymous}", + "(anonymous namespace)", + "public:", + "private:", + "protected:", + "struct ", + "class ", + "`anonymous-namespace'", + "`anonymous namespace'" } }; + +#if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + inline std::string ctti_get_type_name_from_sig(std::string name) { + // cardinal sins from MINGW + using namespace std; + std::size_t start = name.find_first_of('['); + start = name.find_first_of('=', start); + std::size_t end = name.find_last_of(']'); + if (end == std::string::npos) + end = name.size(); + if (start == std::string::npos) + start = 0; + if (start < name.size() - 1) + start += 1; + name = name.substr(start, end - start); + start = name.rfind("seperator_mark"); + if (start != std::string::npos) { + name.erase(start - 2, name.length()); + } + while (!name.empty() && isblank(name.front())) + name.erase(name.begin()); + while (!name.empty() && isblank(name.back())) + name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } + + template <typename T, class seperator_mark = int> + inline std::string ctti_get_type_name() { + return ctti_get_type_name_from_sig(__PRETTY_FUNCTION__); + } +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + inline std::string ctti_get_type_name_from_sig(std::string name) { + std::size_t start = name.find("get_type_name"); + if (start == std::string::npos) + start = 0; + else + start += 13; + if (start < name.size() - 1) + start += 1; + std::size_t end = name.find_last_of('>'); + if (end == std::string::npos) + end = name.size(); + name = name.substr(start, end - start); + if (name.find("struct", 0) == 0) + name.replace(0, 6, "", 0); + if (name.find("class", 0) == 0) + name.replace(0, 5, "", 0); + while (!name.empty() && isblank(name.front())) + name.erase(name.begin()); + while (!name.empty() && isblank(name.back())) + name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } + + template <typename T> + std::string ctti_get_type_name() { + return ctti_get_type_name_from_sig(__FUNCSIG__); + } +#else +#error Compiler not supported for demangling +#endif // compilers + + template <typename T> + std::string demangle_once() { + std::string realname = ctti_get_type_name<T>(); + return realname; + } + + inline std::string short_demangle_from_type_name(std::string realname) { + // This isn't the most complete but it'll do for now...? + static const std::array<std::string, 10> ops = { + { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" } + }; + int level = 0; + std::size_t idx = 0; + for (idx = static_cast<std::size_t>(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { + if (level == 0 && realname[idx] == ':') { + break; + } + bool isleft = realname[idx] == '<'; + bool isright = realname[idx] == '>'; + if (!isleft && !isright) + continue; + bool earlybreak = false; + for (const auto& op : ops) { + std::size_t nisop = realname.rfind(op, idx); + if (nisop == std::string::npos) + continue; + std::size_t nisopidx = idx - op.size() + 1; + if (nisop == nisopidx) { + idx = static_cast<std::size_t>(nisopidx); + earlybreak = true; + } + break; + } + if (earlybreak) { + continue; + } + level += isleft ? -1 : 1; + } + if (idx > 0) { + realname.erase(0, realname.length() < static_cast<std::size_t>(idx) ? realname.length() : idx + 1); + } + return realname; + } + + template <typename T> + std::string short_demangle_once() { + std::string realname = ctti_get_type_name<T>(); + return short_demangle_from_type_name(realname); + } + + template <typename T> + const std::string& demangle() { + static const std::string d = demangle_once<T>(); + return d; + } + + template <typename T> + const std::string& short_demangle() { + static const std::string d = short_demangle_once<T>(); + return d; + } +}} // namespace sol::detail + +// end of sol/demangle.hpp + +namespace sol { + + template <typename T> + struct usertype_traits { + static const std::string& name() { + static const std::string& n = detail::short_demangle<T>(); + return n; + } + static const std::string& qualified_name() { + static const std::string& q_n = detail::demangle<T>(); + return q_n; + } + static const std::string& metatable() { + static const std::string m = std::string("sol.").append(detail::demangle<T>()); + return m; + } + static const std::string& user_metatable() { + static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user"); + return u_m; + } + static const std::string& user_gc_metatable() { + static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB"); + return u_g_m; + } + static const std::string& gc_table() { + static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB"); + return g_t; + } + }; + +} // namespace sol + +// end of sol/usertype_traits.hpp + +// beginning of sol/unique_usertype_traits.hpp + +#include <memory> + +namespace sol { + + namespace detail { + template <typename T> + struct unique_fallback { + using SOL_INTERNAL_UNSPECIALIZED_MARKER_ = int; + }; + + template <typename T> + struct unique_fallback<std::shared_ptr<T>> { + private: + using pointer = typename std::pointer_traits<std::shared_ptr<T>>::element_type*; + + public: + // rebind is non-void + // if and only if unique usertype + // is cast-capable + template <typename X> + using rebind_actual_type = std::shared_ptr<X>; + + static bool is_null(lua_State*, const std::shared_ptr<T>& p) noexcept { + return p == nullptr; + } + + static pointer get(lua_State*, const std::shared_ptr<T>& p) noexcept { + return p.get(); + } + }; + + template <typename T, typename D> + struct unique_fallback<std::unique_ptr<T, D>> { + private: + using pointer = typename std::unique_ptr<T, D>::pointer; + + public: + static bool is_null(lua_State*, const std::unique_ptr<T, D>& p) noexcept { + return p == nullptr; + } + + static pointer get(lua_State*, const std::unique_ptr<T, D>& p) noexcept { + return p.get(); + } + }; + } // namespace detail + + namespace meta { namespace meta_detail { + template <typename T, typename = void> + struct unique_actual_type; + + template <typename T> + struct unique_actual_type<T, meta::void_t<typename T::actual_type>> { + using type = typename T::actual_type; + }; + + template <typename T, typename... Rest, template <typename...> class Templ> + struct unique_actual_type<Templ<T, Rest...>> { + using type = T; + }; + + }} // namespace meta::meta_detail + + template <typename T> + using unique_usertype_actual_t = typename meta::meta_detail::unique_actual_type<unique_usertype_traits<T>>::type; + + namespace meta { namespace meta_detail { + template <typename T> + using value_test_t = decltype(T::value); + + template <typename T> + using type_test_t = typename T::type; + + template <typename T> + using type_element_type_t = typename T::element_type; + + template <typename T, typename = void> + struct unique_element_type { + using type = typename std::pointer_traits<typename unique_actual_type<T>::type>::element_type; + }; + + template <typename T> + struct unique_element_type<T, std::enable_if_t<meta::is_detected_v<type_element_type_t, T>>> { + using type = typename T::element_type; + }; + + template <typename T> + struct unique_element_type<T, std::enable_if_t<meta::is_detected_v<type_test_t, T>>> { + using type = typename T::type; + }; + + template <typename T, typename = void> + struct unique_valid : std::integral_constant<bool, !has_internal_marker_v<T>> { }; + + template <typename T> + struct unique_valid<T, meta::void_t<decltype(T::value)>> : std::integral_constant<bool, T::value> { }; + }} // namespace meta::meta_detail + + template <typename T> + using unique_usertype_element_t = typename meta::meta_detail::unique_element_type<unique_usertype_traits<T>>::type; + + template <typename T, typename Element = void> + using unique_usertype_rebind_actual_t = typename unique_usertype_traits<T>::template rebind_actual_type<Element>; + + template <typename T> + struct unique_usertype_traits : public detail::unique_fallback<T> { }; + + template <typename T> + struct is_unique_usertype : std::integral_constant<bool, meta::meta_detail::unique_valid<unique_usertype_traits<T>>::value> { }; + + template <typename T> + inline constexpr bool is_unique_usertype_v = is_unique_usertype<T>::value; + + namespace meta { namespace meta_detail { + template <typename T> + using adl_sol_lua_check_access_test_t + = decltype(sol_lua_check_access(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>())); + + template <typename T> + inline constexpr bool is_adl_sol_lua_check_access_v = meta::is_detected_v<adl_sol_lua_check_access_test_t, T>; + + template <typename T> + using unique_usertype_get_with_state_test_t + = decltype(unique_usertype_traits<T>::get(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<T>>())); + + template <typename T> + inline constexpr bool unique_usertype_get_with_state_v = meta::is_detected_v<unique_usertype_get_with_state_test_t, T>; + + template <typename T> + using unique_usertype_is_null_with_state_test_t + = decltype(unique_usertype_traits<T>::is_null(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<T>>())); + + template <typename T> + inline constexpr bool unique_usertype_is_null_with_state_v = meta::is_detected_v<unique_usertype_is_null_with_state_test_t, T>; + }} // namespace meta::meta_detail + + namespace detail { + template <typename T> + constexpr bool unique_is_null_noexcept() noexcept { + if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<std::remove_cv_t<T>>) { + return noexcept( + unique_usertype_traits<T>::is_null(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>())); + } + else { + return noexcept(unique_usertype_traits<T>::is_null(std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>())); + } + } + + template <typename T> + bool unique_is_null(lua_State* L_, T& value_) noexcept(unique_is_null_noexcept<std::remove_cv_t<T>>()) { + using Tu = std::remove_cv_t<T>; + if constexpr (meta::meta_detail::unique_usertype_is_null_with_state_v<Tu>) { + return unique_usertype_traits<Tu>::is_null(L_, value_); + } + else { + return unique_usertype_traits<Tu>::is_null(value_); + } + } + + template <typename T> + constexpr bool unique_get_noexcept() noexcept { + if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<std::remove_cv_t<T>>) { + return noexcept( + unique_usertype_traits<T>::get(static_cast<lua_State*>(nullptr), std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>())); + } + else { + return noexcept(unique_usertype_traits<T>::get(std::declval<unique_usertype_actual_t<std::remove_cv_t<T>>>())); + } + } + + template <typename T> + auto unique_get(lua_State* L_, T& value_) noexcept(unique_get_noexcept<std::remove_cv_t<T>>()) { + using Tu = std::remove_cv_t<T>; + if constexpr (meta::meta_detail::unique_usertype_get_with_state_v<Tu>) { + return unique_usertype_traits<Tu>::get(L_, value_); + } + else { + return unique_usertype_traits<Tu>::get(value_); + } + } + } // namespace detail + + namespace meta { namespace meta_detail { + template <typename T, typename Element = void> + using is_rebind_actual_type_test_t = typename T::template rebind_actual_type<Element>; + + template <typename T, typename Element = void> + using is_rebind_actual_type = meta::is_detected<is_rebind_actual_type_test_t, T, Element>; + + template <typename T, typename Element = void> + inline constexpr bool is_rebind_actual_type_v = is_rebind_actual_type<T, Element>::value; + + template <typename T, typename Element, bool = is_rebind_actual_type_v<T, Element>> + struct is_actual_type_rebindable_for_test : std::false_type { }; + + template <typename T, typename Element> + struct is_actual_type_rebindable_for_test<T, Element, true> + : std::integral_constant<bool, !std::is_void_v<typename T::template rebind_actual_type<Element>>> { }; + }} // namespace meta::meta_detail + + template <typename T, typename Element = void> + using is_actual_type_rebindable_for = typename meta::meta_detail::is_actual_type_rebindable_for_test<unique_usertype_traits<T>, Element>::type; + + template <typename T, typename Element = void> + inline constexpr bool is_actual_type_rebindable_for_v = is_actual_type_rebindable_for<T, Element>::value; + +} // namespace sol + +// end of sol/unique_usertype_traits.hpp + +namespace sol { + template <typename... Args> + struct base_list { }; + template <typename... Args> + using bases = base_list<Args...>; + + typedef bases<> base_classes_tag; + const auto base_classes = base_classes_tag(); + + template <typename... Args> + struct is_to_stringable<base_list<Args...>> : std::false_type { }; + + namespace detail { + + inline decltype(auto) base_class_check_key() { + static const auto& key = "class_check"; + return key; + } + + inline decltype(auto) base_class_cast_key() { + static const auto& key = "class_cast"; + return key; + } + + inline decltype(auto) base_class_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; + return key; + } + + inline decltype(auto) base_class_new_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; + return key; + } + + template <typename T> + struct inheritance { + typedef typename base<T>::type bases_t; + + static bool type_check_bases(types<>, const string_view&) { + return false; + } + + template <typename Base, typename... Args> + static bool type_check_bases(types<Base, Args...>, const string_view& ti) { + return ti == usertype_traits<Base>::qualified_name() || type_check_bases(types<Args...>(), ti); + } + + static bool type_check(const string_view& ti) { + return ti == usertype_traits<T>::qualified_name() || type_check_bases(bases_t(), ti); + } + + template <typename... Bases> + static bool type_check_with(const string_view& ti) { + return ti == usertype_traits<T>::qualified_name() || type_check_bases(types<Bases...>(), ti); + } + + static void* type_cast_bases(types<>, T*, const string_view&) { + return nullptr; + } + + template <typename Base, typename... Args> + static void* type_cast_bases(types<Base, Args...>, T* data, const string_view& ti) { + // Make sure to convert to T first, and then dynamic cast to the proper type + return ti != usertype_traits<Base>::qualified_name() ? type_cast_bases(types<Args...>(), data, ti) + : static_cast<void*>(static_cast<Base*>(data)); + } + + static void* type_cast(void* voiddata, const string_view& ti) { + T* data = static_cast<T*>(voiddata); + return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(bases_t(), data, ti) : data); + } + + template <typename... Bases> + static void* type_cast_with(void* voiddata, const string_view& ti) { + T* data = static_cast<T*>(voiddata); + return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(types<Bases...>(), data, ti) : data); + } + + template <typename U> + static bool type_unique_cast_bases(types<>, void*, void*, const string_view&) { + return 0; + } + + template <typename U, typename Base, typename... Args> + static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) { + using uu_traits = unique_usertype_traits<U>; + using base_ptr = typename uu_traits::template rebind_actual_type<Base>; + string_view base_ti = usertype_traits<Base>::qualified_name(); + if (base_ti == ti) { + if (target_data != nullptr) { + U* source = static_cast<U*>(source_data); + base_ptr* target = static_cast<base_ptr*>(target_data); + // perform proper derived -> base conversion + *target = *source; + } + return 2; + } + return type_unique_cast_bases<U>(types<Args...>(), source_data, target_data, ti); + } + + template <typename U> + static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { + if constexpr (is_actual_type_rebindable_for_v<U>) { + using rebound_actual_type = unique_usertype_rebind_actual_t<U>; + using maybe_bases_or_empty = meta::conditional_t<std::is_void_v<rebound_actual_type>, types<>, bases_t>; + string_view this_rebind_ti = usertype_traits<rebound_actual_type>::qualified_name(); + if (rebind_ti != this_rebind_ti) { + // this is not even of the same unique type + return 0; + } + string_view this_ti = usertype_traits<T>::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases<U>(maybe_bases_or_empty(), source_data, target_data, ti); + } + else { + (void)rebind_ti; + string_view this_ti = usertype_traits<T>::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti); + } + } + + template <typename U, typename... Bases> + static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { + using uc_bases_t = types<Bases...>; + if constexpr (is_actual_type_rebindable_for_v<U>) { + using rebound_actual_type = unique_usertype_rebind_actual_t<U>; + using cond_bases_t = meta::conditional_t<std::is_void_v<rebound_actual_type>, types<>, uc_bases_t>; + string_view this_rebind_ti = usertype_traits<rebound_actual_type>::qualified_name(); + if (rebind_ti != this_rebind_ti) { + // this is not even of the same unique type + return 0; + } + string_view this_ti = usertype_traits<T>::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases<U>(cond_bases_t(), source_data, target_data, ti); + } + else { + (void)rebind_ti; + string_view this_ti = usertype_traits<T>::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases<U>(types<>(), source_data, target_data, ti); + } + } + }; + + using inheritance_check_function = decltype(&inheritance<void>::type_check); + using inheritance_cast_function = decltype(&inheritance<void>::type_cast); + using inheritance_unique_cast_function = decltype(&inheritance<void>::type_unique_cast<void>); + } // namespace detail +} // namespace sol + +// end of sol/inheritance.hpp + +// beginning of sol/error_handler.hpp + +#include <cstdio> + +namespace sol { + + namespace detail { + constexpr const char* not_a_number = "not a numeric type"; + constexpr const char* not_a_number_or_number_string = "not a numeric type or numeric string"; + constexpr const char* not_a_number_integral = "not a numeric type that fits exactly an integer (number maybe has significant decimals)"; + constexpr const char* not_a_number_or_number_string_integral + = "not a numeric type or a numeric string that fits exactly an integer (e.g. number maybe has significant decimals)"; + + constexpr const char* not_enough_stack_space = "not enough space left on Lua stack"; + constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number"; + constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number"; + constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string"; + constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function"; + constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol2 userdata"; + constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees"; + constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment"; + constexpr const char* protected_function_error = "caught (...) unknown error during protected_function call"; + + inline void accumulate_and_mark(const std::string& n, std::string& aux_message, int& marker) { + if (marker > 0) { + aux_message += ", "; + } + aux_message += n; + ++marker; + } + } // namespace detail + + inline std::string associated_type_name(lua_State* L, int index, type t) { + switch (t) { + case type::poly: + return "anything"; + case type::userdata: { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 2, "not enough space to push get the type name"); +#endif // make sure stack doesn't overflow + if (lua_getmetatable(L, index) == 0) { + break; + } + lua_pushlstring(L, "__name", 6); + lua_rawget(L, -2); + size_t sz; + const char* name = lua_tolstring(L, -1, &sz); + std::string tn(name, static_cast<std::string::size_type>(sz)); + lua_pop(L, 2); + return tn; + } + default: + break; + } + return lua_typename(L, static_cast<int>(t)); + } + + inline int push_type_panic_string(lua_State* L, int index, type expected, type actual, string_view message, string_view aux_message) noexcept { + const char* err = message.size() == 0 + ? (aux_message.size() == 0 ? "stack index %d, expected %s, received %s" : "stack index %d, expected %s, received %s: %s") + : "stack index %d, expected %s, received %s: %s %s"; + const char* type_name = expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)); + { + std::string actual_name = associated_type_name(L, index, actual); + lua_pushfstring(L, err, index, type_name, actual_name.c_str(), message.data(), aux_message.data()); + } + return 1; + } + + inline int type_panic_string(lua_State* L, int index, type expected, type actual, string_view message = "") noexcept(false) { + push_type_panic_string(L, index, expected, actual, message, ""); + return lua_error(L); + } + + inline int type_panic_c_str(lua_State* L, int index, type expected, type actual, const char* message = nullptr) noexcept(false) { + push_type_panic_string(L, index, expected, actual, message == nullptr ? "" : message, ""); + return lua_error(L); + } + + struct type_panic_t { + int operator()(lua_State* L, int index, type expected, type actual) const noexcept(false) { + return type_panic_c_str(L, index, expected, actual, nullptr); + } + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + return type_panic_c_str(L, index, expected, actual, message.data()); + } + }; + + const type_panic_t type_panic = {}; + + struct constructor_handler { + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + push_type_panic_string(L, index, expected, actual, message, "(type check failed in constructor)"); + return lua_error(L); + } + }; + + template <typename F = void> + struct argument_handler { + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + push_type_panic_string(L, index, expected, actual, message, "(bad argument to variable or function call)"); + return lua_error(L); + } + }; + + template <typename R, typename... Args> + struct argument_handler<types<R, Args...>> { + int operator()(lua_State* L, int index, type expected, type actual, string_view message) const noexcept(false) { + { + std::string aux_message = "(bad argument into '"; + aux_message += detail::demangle<R>(); + aux_message += "("; + int marker = 0; + (void)detail::swallow { int(), (detail::accumulate_and_mark(detail::demangle<Args>(), aux_message, marker), int())... }; + aux_message += ")')"; + push_type_panic_string(L, index, expected, actual, message, aux_message); + } + return lua_error(L); + } + }; + + // Specify this function as the handler for lua::check if you know there's nothing wrong + inline int no_panic(lua_State*, int, type, type, const char* = nullptr) noexcept { + return 0; + } + + inline void type_error(lua_State* L, int expected, int actual) noexcept(false) { + luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); + } + + inline void type_error(lua_State* L, type expected, type actual) noexcept(false) { + type_error(L, static_cast<int>(expected), static_cast<int>(actual)); + } + + inline void type_assert(lua_State* L, int index, type expected, type actual) noexcept(false) { + if (expected != type::poly && expected != actual) { + type_panic_c_str(L, index, expected, actual, nullptr); + } + } + + inline void type_assert(lua_State* L, int index, type expected) { + type actual = type_of(L, index); + type_assert(L, index, expected, actual); + } + +} // namespace sol + +// end of sol/error_handler.hpp + +// beginning of sol/reference.hpp + +// beginning of sol/stack_reference.hpp + +namespace sol { + namespace detail { + inline bool xmovable(lua_State* leftL, lua_State* rightL) { + if (rightL == nullptr || leftL == nullptr || leftL == rightL) { + return false; + } + const void* leftregistry = lua_topointer(leftL, LUA_REGISTRYINDEX); + const void* rightregistry = lua_topointer(rightL, LUA_REGISTRYINDEX); + return leftregistry == rightregistry; + } + } // namespace detail + + class stateless_stack_reference { + private: + friend class stack_reference; + + int m_index = 0; + + int registry_index() const noexcept { + return LUA_NOREF; + } + + public: + stateless_stack_reference() noexcept = default; + stateless_stack_reference(lua_nil_t) noexcept : stateless_stack_reference() {}; + stateless_stack_reference(lua_State* L_, int index_) noexcept : stateless_stack_reference(absolute_index(L_, index_)) { + } + stateless_stack_reference(lua_State*, absolute_index index_) noexcept : stateless_stack_reference(index_) { + } + stateless_stack_reference(lua_State*, raw_index index_) noexcept : stateless_stack_reference(index_) { + } + stateless_stack_reference(absolute_index index_) noexcept : m_index(index_) { + } + stateless_stack_reference(raw_index index_) noexcept : m_index(index_) { + } + stateless_stack_reference(lua_State*, ref_index) noexcept = delete; + stateless_stack_reference(ref_index) noexcept = delete; + stateless_stack_reference(const reference&) noexcept = delete; + stateless_stack_reference(const stateless_stack_reference&) noexcept = default; + stateless_stack_reference(stateless_stack_reference&& o) noexcept = default; + stateless_stack_reference& operator=(stateless_stack_reference&&) noexcept = default; + stateless_stack_reference& operator=(const stateless_stack_reference&) noexcept = default; + + int push(lua_State* L_) const noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push a single reference value"); +#endif // make sure stack doesn't overflow + lua_pushvalue(L_, m_index); + return 1; + } + + void pop(lua_State* L_, int pop_count = 1) const noexcept { + lua_pop(L_, pop_count); + } + + int stack_index() const noexcept { + return m_index; + } + + const void* pointer(lua_State* L_) const noexcept { + const void* pointer_id = lua_topointer(L_, stack_index()); + return pointer_id; + } + + type get_type(lua_State* L_) const noexcept { + int untyped_value = lua_type(L_, stack_index()); + return static_cast<type>(untyped_value); + } + + bool valid(lua_State* L) const noexcept { + type t = get_type(L); + return t != type::lua_nil && t != type::none; + } + + void reset(lua_State*) noexcept { + m_index = 0; + } + + void reset(lua_State* L_, int index_) noexcept { + m_index = absolute_index(L_, index_); + } + + void abandon(lua_State* = nullptr) noexcept { + m_index = 0; + } + + stateless_stack_reference copy(lua_State* L_) const noexcept { + return stateless_stack_reference(L_, raw_index(m_index)); + } + + void copy_assign(lua_State*, const stateless_stack_reference& right) noexcept { + m_index = right.m_index; + } + + bool equals(lua_State* L_, const stateless_stack_reference& r) const noexcept { + return lua_compare(L_, this->stack_index(), r.stack_index(), LUA_OPEQ) == 1; + } + + bool equals(lua_State* L_, lua_nil_t) const noexcept { + return valid(L_); + } + }; + + class stack_reference : public stateless_stack_reference { + private: + lua_State* luastate = nullptr; + + public: + stack_reference() noexcept = default; + stack_reference(lua_nil_t) noexcept : stack_reference() {}; + stack_reference(lua_State* L, lua_nil_t) noexcept : stateless_stack_reference(L, 0), luastate(L) { + } + stack_reference(lua_State* L, int i) noexcept : stateless_stack_reference(L, i), luastate(L) { + } + stack_reference(lua_State* L, absolute_index i) noexcept : stateless_stack_reference(L, i), luastate(L) { + } + stack_reference(lua_State* L, raw_index i) noexcept : stateless_stack_reference(L, i), luastate(L) { + } + stack_reference(lua_State* L, ref_index i) noexcept = delete; + stack_reference(lua_State* L, const reference& r) noexcept = delete; + stack_reference(lua_State* L, const stack_reference& r) noexcept : luastate(L) { + if (!r.valid()) { + m_index = 0; + return; + } + int i = r.stack_index(); + if (detail::xmovable(lua_state(), r.lua_state())) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, "not enough Lua stack space to push a single reference value"); +#endif // make sure stack doesn't overflow + lua_pushvalue(r.lua_state(), r.stack_index()); + lua_xmove(r.lua_state(), luastate, 1); + i = absolute_index(luastate, -1); + } + m_index = i; + } + stack_reference(stack_reference&& o) noexcept = default; + stack_reference& operator=(stack_reference&&) noexcept = default; + stack_reference(const stack_reference&) noexcept = default; + stack_reference& operator=(const stack_reference&) noexcept = default; + + int push() const noexcept { + return push(lua_state()); + } + + int push(lua_State* L_) const noexcept { + return stateless_stack_reference::push(L_); + } + + void pop() const noexcept { + pop(lua_state()); + } + + void pop(lua_State* L_, int pop_count_ = 1) const noexcept { + stateless_stack_reference::pop(L_, pop_count_); + } + + const void* pointer() const noexcept { + return stateless_stack_reference::pointer(lua_state()); + } + + type get_type() const noexcept { + return stateless_stack_reference::get_type(lua_state()); + } + + lua_State* lua_state() const noexcept { + return luastate; + } + + bool valid() const noexcept { + return stateless_stack_reference::valid(lua_state()); + } + + void abandon() { + stateless_stack_reference::abandon(lua_state()); + } + }; + + inline bool operator==(const stack_reference& l, const stack_reference& r) { + return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 1; + } + + inline bool operator!=(const stack_reference& l, const stack_reference& r) { + return !operator==(l, r); + } + + inline bool operator==(const stack_reference& lhs, const lua_nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const lua_nil_t&, const stack_reference& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const stack_reference& lhs, const lua_nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const lua_nil_t&, const stack_reference& rhs) { + return rhs.valid(); + } + + inline bool operator==(const stateless_stack_reference& l, const stateless_stack_reference& r) { + return l.stack_index() == r.stack_index(); + } + + inline bool operator!=(const stateless_stack_reference& l, const stateless_stack_reference& r) { + return l.stack_index() != r.stack_index(); + } + + struct stateless_stack_reference_equals { + using is_transparent = std::true_type; + + stateless_stack_reference_equals(lua_State* L_) noexcept : m_L(L_) { + } + + lua_State* lua_state() const noexcept { + return m_L; + } + + bool operator()(const stateless_stack_reference& lhs, const stateless_stack_reference& rhs) const { + return lhs.equals(lua_state(), rhs); + } + + bool operator()(lua_nil_t lhs, const stateless_stack_reference& rhs) const { + return rhs.equals(lua_state(), lhs); + } + + bool operator()(const stateless_stack_reference& lhs, lua_nil_t rhs) const { + return lhs.equals(lua_state(), rhs); + } + + private: + lua_State* m_L; + }; + + struct stack_reference_equals { + using is_transparent = std::true_type; + + bool operator()(const lua_nil_t& lhs, const stack_reference& rhs) const { + return lhs == rhs; + } + + bool operator()(const stack_reference& lhs, const lua_nil_t& rhs) const { + return lhs == rhs; + } + + bool operator()(const stack_reference& lhs, const stack_reference& rhs) const { + return lhs == rhs; + } + }; + + struct stateless_stack_reference_hash { + using argument_type = stateless_stack_reference; + using result_type = std::size_t; + using is_transparent = std::true_type; + + stateless_stack_reference_hash(lua_State* L_) noexcept : m_L(L_) { + } + + lua_State* lua_state() const noexcept { + return m_L; + } + + result_type operator()(const argument_type& lhs) const noexcept { + std::hash<const void*> h; + return h(lhs.pointer(lua_state())); + } + + private: + lua_State* m_L; + }; + + struct stack_reference_hash { + using argument_type = stack_reference; + using result_type = std::size_t; + using is_transparent = std::true_type; + + result_type operator()(const argument_type& lhs) const noexcept { + std::hash<const void*> h; + return h(lhs.pointer()); + } + }; +} // namespace sol + +// end of sol/stack_reference.hpp + +#include <functional> + +namespace sol { + namespace detail { + inline const char (&default_main_thread_name())[9] { + static const char name[9] = "sol.\xF0\x9F\x93\x8C"; + return name; + } + } // namespace detail + + namespace stack { + inline void remove(lua_State* L_, int rawindex, int count) { + if (count < 1) + return; + int top = lua_gettop(L_); + if (top < 1) { + return; + } + if (rawindex == -count || top == rawindex) { + // Slice them right off the top + lua_pop(L_, static_cast<int>(count)); + return; + } + + // Remove each item one at a time using stack operations + // Probably slower, maybe, haven't benchmarked, + // but necessary + int index = lua_absindex(L_, rawindex); + if (index < 0) { + index = lua_gettop(L_) + (index + 1); + } + int last = index + count; + for (int i = index; i < last; ++i) { + lua_remove(L_, index); + } + } + + struct push_popper_at { + lua_State* L; + int index; + int count; + push_popper_at(lua_State* L_, int index_ = -1, int count_ = 1) : L(L_), index(index_), count(count_) { + } + ~push_popper_at() { + remove(L, index, count); + } + }; + + template <bool top_level> + struct push_popper_n { + lua_State* L; + int pop_count; + push_popper_n(lua_State* L_, int pop_count_) : L(L_), pop_count(pop_count_) { + } + push_popper_n(const push_popper_n&) = delete; + push_popper_n(push_popper_n&&) = default; + push_popper_n& operator=(const push_popper_n&) = delete; + push_popper_n& operator=(push_popper_n&&) = default; + ~push_popper_n() { + lua_pop(L, pop_count); + } + }; + + template <> + struct push_popper_n<true> { + push_popper_n(lua_State*, int) { + } + }; + + template <bool, typename T, typename = void> + struct push_popper { + using Tu = meta::unqualified_t<T>; + T m_object; + int m_index; + + push_popper(T object_) noexcept : m_object(object_), m_index(lua_absindex(m_object.lua_state(), -m_object.push())) { + } + + int index_of(const Tu&) const noexcept { + return m_index; + } + + ~push_popper() { + m_object.pop(); + } + }; + + template <typename T, typename C> + struct push_popper<true, T, C> { + using Tu = meta::unqualified_t<T>; + + push_popper(T) noexcept { + } + + int index_of(const Tu&) const noexcept { + return -1; + } + + ~push_popper() { + } + }; + + template <typename T> + struct push_popper<false, T, std::enable_if_t<is_stack_based_v<meta::unqualified_t<T>>>> { + using Tu = meta::unqualified_t<T>; + + push_popper(T) noexcept { + } + + int index_of(const Tu& object_) const noexcept { + return object_.stack_index(); + } + + ~push_popper() { + } + }; + + template <bool, typename T, typename = void> + struct stateless_push_popper { + using Tu = meta::unqualified_t<T>; + lua_State* m_L; + T m_object; + int m_index; + + stateless_push_popper(lua_State* L_, T object_) noexcept : m_L(L_), m_object(object_), m_index(lua_absindex(m_L, -m_object.push(m_L))) { + } + + int index_of(const Tu&) const noexcept { + return m_index; + } + + ~stateless_push_popper() { + m_object.pop(m_L); + } + }; + + template <typename T, typename C> + struct stateless_push_popper<true, T, C> { + using Tu = meta::unqualified_t<T>; + + stateless_push_popper(lua_State*, T) noexcept { + } + + int index_of(lua_State*, const Tu&) const noexcept { + return -1; + } + + ~stateless_push_popper() { + } + }; + + template <typename T> + struct stateless_push_popper<false, T, std::enable_if_t<is_stack_based_v<meta::unqualified_t<T>>>> { + using Tu = meta::unqualified_t<T>; + lua_State* m_L; + + stateless_push_popper(lua_State* L_, T) noexcept : m_L(L_) { + } + + int index_of(const Tu& object_) const noexcept { + return object_.stack_index(); + } + + ~stateless_push_popper() { + } + }; + + template <bool top_level = false, typename T> + push_popper<top_level, T> push_pop(T&& x) { + return push_popper<top_level, T>(std::forward<T>(x)); + } + + template <bool top_level = false, typename T> + stateless_push_popper<top_level, T> push_pop(lua_State* L_, T&& object_) { + return stateless_push_popper<top_level, T>(L_, std::forward<T>(object_)); + } + + template <typename T> + push_popper_at push_pop_at(T&& object_) { + int push_count = object_.push(); + lua_State* L = object_.lua_state(); + return push_popper_at(L, lua_absindex(L, -push_count), push_count); + } + + template <bool top_level = false> + push_popper_n<top_level> pop_n(lua_State* L_, int pop_count_) { + return push_popper_n<top_level>(L_, pop_count_); + } + } // namespace stack + + inline lua_State* main_thread(lua_State* L_, lua_State* backup_if_unsupported_ = nullptr) { +#if SOL_LUA_VERSION_I_ < 502 + if (L_ == nullptr) + return backup_if_unsupported_; + lua_getglobal(L_, detail::default_main_thread_name()); + auto pp = stack::pop_n(L_, 1); + if (type_of(L_, -1) == type::thread) { + return lua_tothread(L_, -1); + } + return backup_if_unsupported_; +#else + if (L_ == nullptr) + return backup_if_unsupported_; + lua_rawgeti(L_, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); + lua_State* Lmain = lua_tothread(L_, -1); + lua_pop(L_, 1); + return Lmain; +#endif // Lua 5.2+ has the main thread unqualified_getter + } + + namespace detail { + struct no_safety_tag { + } inline constexpr no_safety {}; + + template <bool b> + inline lua_State* pick_main_thread(lua_State* L_, lua_State* backup_if_unsupported = nullptr) { + (void)L_; + (void)backup_if_unsupported; + if (b) { + return main_thread(L_, backup_if_unsupported); + } + return L_; + } + } // namespace detail + + class stateless_reference { + private: + template <bool o_main_only> + friend class basic_reference; + + int ref = LUA_NOREF; + + int copy_ref(lua_State* L_) const noexcept { + if (ref == LUA_NOREF) + return LUA_NOREF; + push(L_); + return luaL_ref(L_, LUA_REGISTRYINDEX); + } + + lua_State* copy_assign_ref(lua_State* L_, lua_State* rL, const stateless_reference& r) { + if (valid(L_)) { + deref(L_); + } + ref = r.copy_ref(L_); + return rL; + } + + lua_State* move_assign(lua_State* L_, lua_State* rL, stateless_reference&& r) { + if (valid(L_)) { + deref(L_); + } + ref = r.ref; + r.ref = LUA_NOREF; + return rL; + } + + protected: + int stack_index() const noexcept { + return -1; + } + + stateless_reference(lua_State* L_, global_tag_t) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); +#endif // make sure stack doesn't overflow + lua_pushglobaltable(L_); + ref = luaL_ref(L_, LUA_REGISTRYINDEX); + } + + stateless_reference(int raw_ref_index) noexcept : ref(raw_ref_index) { + } + + public: + stateless_reference() noexcept = default; + stateless_reference(lua_nil_t) noexcept : stateless_reference() { + } + stateless_reference(const stack_reference& r) noexcept : stateless_reference(r.lua_state(), r.stack_index()) { + } + stateless_reference(stack_reference&& r) noexcept : stateless_reference(r.lua_state(), r.stack_index()) { + } + stateless_reference(lua_State* L_, const stateless_reference& r) noexcept { + if (r.ref == LUA_REFNIL) { + ref = LUA_REFNIL; + return; + } + if (r.ref == LUA_NOREF || L_ == nullptr) { + ref = LUA_NOREF; + return; + } + ref = r.copy_ref(L_); + } + + stateless_reference(lua_State* L_, stateless_reference&& r) noexcept { + if (r.ref == LUA_REFNIL) { + ref = LUA_REFNIL; + return; + } + if (r.ref == LUA_NOREF || L_ == nullptr) { + ref = LUA_NOREF; + return; + } + ref = r.ref; + r.ref = LUA_NOREF; + } + + stateless_reference(lua_State* L_, const stack_reference& r) noexcept { + if (L_ == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) { + ref = LUA_NOREF; + return; + } + if (r.get_type() == type::lua_nil) { + ref = LUA_REFNIL; + return; + } + if (L_ != r.lua_state() && !detail::xmovable(L_, r.lua_state())) { + return; + } + r.push(L_); + ref = luaL_ref(L_, LUA_REGISTRYINDEX); + } + + stateless_reference(lua_State* L_, const stateless_stack_reference& r) noexcept : stateless_reference(L_, r.stack_index()) { + } + + stateless_reference(lua_State* L_, int index = -1) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); +#endif // make sure stack doesn't overflow + lua_pushvalue(L_, index); + ref = luaL_ref(L_, LUA_REGISTRYINDEX); + } + stateless_reference(lua_State* L_, absolute_index index_) noexcept : stateless_reference(L_, index_.index) { + } + stateless_reference(lua_State* L_, ref_index index_) noexcept { + lua_rawgeti(L_, LUA_REGISTRYINDEX, index_.index); + ref = luaL_ref(L_, LUA_REGISTRYINDEX); + } + stateless_reference(lua_State*, lua_nil_t) noexcept { + } + + ~stateless_reference() noexcept = default; + + stateless_reference(const stateless_reference& o) noexcept = delete; + stateless_reference& operator=(const stateless_reference& r) noexcept = delete; + + stateless_reference(stateless_reference&& o) noexcept : ref(o.ref) { + o.ref = LUA_NOREF; + } + + stateless_reference& operator=(stateless_reference&& o) noexcept { + ref = o.ref; + o.ref = LUA_NOREF; + return *this; + } + + int push(lua_State* L_) const noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); +#endif // make sure stack doesn't overflow + lua_rawgeti(L_, LUA_REGISTRYINDEX, ref); + return 1; + } + + void pop(lua_State* L_, int n = 1) const noexcept { + lua_pop(L_, n); + } + + int registry_index() const noexcept { + return ref; + } + + void reset(lua_State* L_) noexcept { + if (valid(L_)) { + deref(L_); + } + ref = LUA_NOREF; + } + + void reset(lua_State* L_, int index_) noexcept { + reset(L_); +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); +#endif // make sure stack doesn't overflow + lua_pushvalue(L_, index_); + ref = luaL_ref(L_, LUA_REGISTRYINDEX); + } + + bool valid(lua_State*) const noexcept { + return !(ref == LUA_NOREF || ref == LUA_REFNIL); + } + + const void* pointer(lua_State* L_) const noexcept { + int si = push(L_); + const void* vp = lua_topointer(L_, -si); + lua_pop(L_, si); + return vp; + } + + type get_type(lua_State* L_) const noexcept { + int p = push(L_); + int result = lua_type(L_, -1); + pop(L_, p); + return static_cast<type>(result); + } + + void abandon(lua_State* = nullptr) { + ref = LUA_NOREF; + } + + void deref(lua_State* L_) const noexcept { + luaL_unref(L_, LUA_REGISTRYINDEX, ref); + } + + stateless_reference copy(lua_State* L_) const noexcept { + if (!valid(L_)) { + return {}; + } + return stateless_reference(copy_ref(L_)); + } + + void copy_assign(lua_State* L_, const stateless_reference& right) noexcept { + if (valid(L_)) { + deref(L_); + } + if (!right.valid(L_)) { + return; + } + ref = right.copy_ref(L_); + } + + bool equals(lua_State* L_, const stateless_reference& r) const noexcept { + auto ppl = stack::push_pop(L_, *this); + auto ppr = stack::push_pop(L_, r); + return lua_compare(L_, -1, -2, LUA_OPEQ) == 1; + } + + bool equals(lua_State* L_, const stateless_stack_reference& r) const noexcept { + auto ppl = stack::push_pop(L_, *this); + return lua_compare(L_, -1, r.stack_index(), LUA_OPEQ) == 1; + } + + bool equals(lua_State* L_, lua_nil_t) const noexcept { + return valid(L_); + } + }; + + template <bool main_only = false> + class basic_reference : public stateless_reference { + private: + template <bool o_main_only> + friend class basic_reference; + lua_State* luastate = nullptr; // non-owning + + template <bool r_main_only> + void copy_assign_complex(const basic_reference<r_main_only>& r) { + if (valid()) { + deref(); + } + if (r.ref == LUA_REFNIL) { + luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); + ref = LUA_REFNIL; + return; + } + if (r.ref == LUA_NOREF) { + luastate = r.luastate; + ref = LUA_NOREF; + return; + } + if (detail::xmovable(lua_state(), r.lua_state())) { + r.push(lua_state()); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + return; + } + luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); + ref = r.copy_ref(); + } + + template <bool r_main_only> + void move_assign(basic_reference<r_main_only>&& r) { + if (valid()) { + deref(); + } + if (r.ref == LUA_REFNIL) { + luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); + ref = LUA_REFNIL; + return; + } + if (r.ref == LUA_NOREF) { + luastate = r.luastate; + ref = LUA_NOREF; + return; + } + if (detail::xmovable(lua_state(), r.lua_state())) { + r.push(lua_state()); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + return; + } + + luastate = detail::pick_main_thread < main_only && !r_main_only > (r.lua_state(), r.lua_state()); + ref = r.ref; + r.ref = LUA_NOREF; + r.luastate = nullptr; + } + + protected: + basic_reference(lua_State* L_, global_tag_t) noexcept : basic_reference(detail::pick_main_thread<main_only>(L_, L_), global_tag, global_tag) { + } + + basic_reference(lua_State* L_, global_tag_t, global_tag_t) noexcept : stateless_reference(L_, global_tag), luastate(L_) { + } + + basic_reference(lua_State* oL, const basic_reference<!main_only>& o) noexcept : stateless_reference(oL, o), luastate(oL) { + } + + void deref() const noexcept { + return stateless_reference::deref(lua_state()); + } + + int copy_ref() const noexcept { + return copy_ref(lua_state()); + } + + int copy_ref(lua_State* L_) const noexcept { + return stateless_reference::copy_ref(L_); + } + + public: + basic_reference() noexcept = default; + basic_reference(lua_nil_t) noexcept : basic_reference() { + } + basic_reference(const stack_reference& r) noexcept : basic_reference(r.lua_state(), r.stack_index()) { + } + basic_reference(stack_reference&& r) noexcept : basic_reference(r.lua_state(), r.stack_index()) { + } + template <bool r_main_only> + basic_reference(lua_State* L_, const basic_reference<r_main_only>& r) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { + if (r.ref == LUA_REFNIL) { + ref = LUA_REFNIL; + return; + } + if (r.ref == LUA_NOREF || lua_state() == nullptr) { + ref = LUA_NOREF; + return; + } + if (detail::xmovable(lua_state(), r.lua_state())) { + r.push(lua_state()); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + return; + } + ref = r.copy_ref(); + } + + template <bool r_main_only> + basic_reference(lua_State* L_, basic_reference<r_main_only>&& r) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { + if (r.ref == LUA_REFNIL) { + ref = LUA_REFNIL; + return; + } + if (r.ref == LUA_NOREF || lua_state() == nullptr) { + ref = LUA_NOREF; + return; + } + if (detail::xmovable(lua_state(), r.lua_state())) { + r.push(lua_state()); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + return; + } + ref = r.ref; + r.ref = LUA_NOREF; + r.luastate = nullptr; + } + + basic_reference(lua_State* L_, const stack_reference& r) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { + if (lua_state() == nullptr || r.lua_state() == nullptr || r.get_type() == type::none) { + ref = LUA_NOREF; + return; + } + if (r.get_type() == type::lua_nil) { + ref = LUA_REFNIL; + return; + } + if (lua_state() != r.lua_state() && !detail::xmovable(lua_state(), r.lua_state())) { + return; + } + r.push(lua_state()); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + } + basic_reference(lua_State* L_, int index = -1) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { + // use L_ to stick with that state's execution stack +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); +#endif // make sure stack doesn't overflow + lua_pushvalue(L_, index); + ref = luaL_ref(L_, LUA_REGISTRYINDEX); + } + basic_reference(lua_State* L_, ref_index index) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { + lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, index.index); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + } + basic_reference(lua_State* L_, lua_nil_t) noexcept : luastate(detail::pick_main_thread<main_only>(L_, L_)) { + } + + ~basic_reference() noexcept { + if (lua_state() == nullptr || ref == LUA_NOREF) + return; + deref(); + } + + basic_reference(const basic_reference& o) noexcept : stateless_reference(o.copy_ref()), luastate(o.lua_state()) { + } + + basic_reference(basic_reference&& o) noexcept : stateless_reference(std::move(o)), luastate(o.lua_state()) { + o.luastate = nullptr; + } + + basic_reference(const basic_reference<!main_only>& o) noexcept + : basic_reference(detail::pick_main_thread<main_only>(o.lua_state(), o.lua_state()), o) { + } + + basic_reference(basic_reference<!main_only>&& o) noexcept + : stateless_reference(std::move(o)), luastate(detail::pick_main_thread<main_only>(o.lua_state(), o.lua_state())) { + o.luastate = nullptr; + o.ref = LUA_NOREF; + } + + basic_reference& operator=(basic_reference&& r) noexcept { + move_assign(std::move(r)); + return *this; + } + + basic_reference& operator=(const basic_reference& r) noexcept { + copy_assign_complex(r); + return *this; + } + + basic_reference& operator=(basic_reference<!main_only>&& r) noexcept { + move_assign(std::move(r)); + return *this; + } + + basic_reference& operator=(const basic_reference<!main_only>& r) noexcept { + copy_assign_complex(r); + return *this; + } + + basic_reference& operator=(const lua_nil_t&) noexcept { + reset(); + return *this; + } + + template <typename Super> + basic_reference& operator=(proxy_base<Super>&& r); + + template <typename Super> + basic_reference& operator=(const proxy_base<Super>& r); + + int push() const noexcept { + return push(lua_state()); + } + + void reset() noexcept { + stateless_reference::reset(luastate); + luastate = nullptr; + } + + int push(lua_State* L_) const noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, "not enough Lua stack space to push this reference value"); +#endif // make sure stack doesn't overflow + if (lua_state() == nullptr) { + lua_pushnil(L_); + return 1; + } + lua_rawgeti(lua_state(), LUA_REGISTRYINDEX, ref); + if (L_ != lua_state()) { + lua_xmove(lua_state(), L_, 1); + } + return 1; + } + + void pop() const noexcept { + pop(lua_state()); + } + + void pop(lua_State* L_, int n = 1) const noexcept { + stateless_reference::pop(L_, n); + } + + int registry_index() const noexcept { + return stateless_reference::registry_index(); + } + + bool valid() const noexcept { + return stateless_reference::valid(lua_state()); + } + + bool valid(lua_State* L_) const noexcept { + return stateless_reference::valid(L_); + } + + const void* pointer() const noexcept { + return stateless_reference::pointer(lua_state()); + } + + explicit operator bool() const noexcept { + return valid(); + } + + type get_type() const noexcept { + return stateless_reference::get_type(lua_state()); + } + + lua_State* lua_state() const noexcept { + return luastate; + } + }; + + template <bool lb, bool rb> + inline bool operator==(const basic_reference<lb>& l, const basic_reference<rb>& r) noexcept { + auto ppl = stack::push_pop(l); + auto ppr = stack::push_pop(r); + return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; + } + + template <bool lb, bool rb> + inline bool operator!=(const basic_reference<lb>& l, const basic_reference<rb>& r) noexcept { + return !operator==(l, r); + } + + template <bool lb> + inline bool operator==(const basic_reference<lb>& l, const stack_reference& r) noexcept { + auto ppl = stack::push_pop(l); + return lua_compare(l.lua_state(), -1, r.stack_index(), LUA_OPEQ) == 1; + } + + template <bool lb> + inline bool operator!=(const basic_reference<lb>& l, const stack_reference& r) noexcept { + return !operator==(l, r); + } + + template <bool rb> + inline bool operator==(const stack_reference& l, const basic_reference<rb>& r) noexcept { + auto ppr = stack::push_pop(r); + return lua_compare(l.lua_state(), -1, r.stack_index(), LUA_OPEQ) == 1; + } + + template <bool rb> + inline bool operator!=(const stack_reference& l, const basic_reference<rb>& r) noexcept { + return !operator==(l, r); + } + + template <bool lb> + inline bool operator==(const basic_reference<lb>& lhs, const lua_nil_t&) noexcept { + return !lhs.valid(); + } + + template <bool rb> + inline bool operator==(const lua_nil_t&, const basic_reference<rb>& rhs) noexcept { + return !rhs.valid(); + } + + template <bool lb> + inline bool operator!=(const basic_reference<lb>& lhs, const lua_nil_t&) noexcept { + return lhs.valid(); + } + + template <bool rb> + inline bool operator!=(const lua_nil_t&, const basic_reference<rb>& rhs) noexcept { + return rhs.valid(); + } + + inline bool operator==(const stateless_reference& l, const stateless_reference& r) noexcept { + return l.registry_index() == r.registry_index(); + } + + inline bool operator!=(const stateless_reference& l, const stateless_reference& r) noexcept { + return l.registry_index() != r.registry_index(); + } + + inline bool operator==(const stateless_reference& lhs, const lua_nil_t&) noexcept { + return lhs.registry_index() == LUA_REFNIL; + } + + inline bool operator==(const lua_nil_t&, const stateless_reference& rhs) noexcept { + return rhs.registry_index() == LUA_REFNIL; + } + + inline bool operator!=(const stateless_reference& lhs, const lua_nil_t&) noexcept { + return lhs.registry_index() != LUA_REFNIL; + } + + inline bool operator!=(const lua_nil_t&, const stateless_reference& rhs) noexcept { + return rhs.registry_index() != LUA_REFNIL; + } + + struct stateless_reference_equals : public stateless_stack_reference_equals { + using is_transparent = std::true_type; + + stateless_reference_equals(lua_State* L_) noexcept : stateless_stack_reference_equals(L_) { + } + + bool operator()(const lua_nil_t& lhs, const stateless_reference& rhs) const noexcept { + return rhs.equals(lua_state(), lhs); + } + + bool operator()(const stateless_reference& lhs, const lua_nil_t& rhs) const noexcept { + return lhs.equals(lua_state(), rhs); + } + + bool operator()(const stateless_reference& lhs, const stateless_reference& rhs) const noexcept { + return lhs.equals(lua_state(), rhs); + } + }; + + struct reference_equals : public stack_reference_equals { + using is_transparent = std::true_type; + + template <bool rb> + bool operator()(const lua_nil_t& lhs, const basic_reference<rb>& rhs) const noexcept { + return lhs == rhs; + } + + template <bool lb> + bool operator()(const basic_reference<lb>& lhs, const lua_nil_t& rhs) const noexcept { + return lhs == rhs; + } + + template <bool lb, bool rb> + bool operator()(const basic_reference<lb>& lhs, const basic_reference<rb>& rhs) const noexcept { + return lhs == rhs; + } + + template <bool lb> + bool operator()(const basic_reference<lb>& lhs, const stack_reference& rhs) const noexcept { + return lhs == rhs; + } + + template <bool rb> + bool operator()(const stack_reference& lhs, const basic_reference<rb>& rhs) const noexcept { + return lhs == rhs; + } + }; + + struct stateless_reference_hash : public stateless_stack_reference_hash { + using argument_type = stateless_reference; + using result_type = std::size_t; + using is_transparent = std::true_type; + + stateless_reference_hash(lua_State* L_) noexcept : stateless_stack_reference_hash(L_) { + } + + result_type operator()(const stateless_reference& lhs) const noexcept { + std::hash<const void*> h; + return h(lhs.pointer(lua_state())); + } + }; + + struct reference_hash : public stack_reference_hash { + using argument_type = reference; + using result_type = std::size_t; + using is_transparent = std::true_type; + + template <bool lb> + result_type operator()(const basic_reference<lb>& lhs) const noexcept { + std::hash<const void*> h; + return h(lhs.pointer()); + } + }; +} // namespace sol + +// end of sol/reference.hpp + +// beginning of sol/tie.hpp + +namespace sol { + + namespace detail { + template <typename T> + struct is_speshul : std::false_type { }; + } // namespace detail + + template <typename T> + struct tie_size : std::tuple_size<T> { }; + + template <typename T> + struct is_tieable : std::integral_constant<bool, (::sol::tie_size<T>::value > 0)> { }; + + template <typename... Tn> + struct tie_t : public std::tuple<std::add_lvalue_reference_t<Tn>...> { + private: + typedef std::tuple<std::add_lvalue_reference_t<Tn>...> base_t; + + template <typename T> + void set(std::false_type, T&& target) { + std::get<0>(*this) = std::forward<T>(target); + } + + template <typename T> + void set(std::true_type, T&& target) { + typedef tie_size<meta::unqualified_t<T>> value_size; + typedef tie_size<std::tuple<Tn...>> tie_size; + typedef meta::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; + typedef std::make_index_sequence<indices_size::value> indices; + set_extra(detail::is_speshul<meta::unqualified_t<T>>(), indices(), std::forward<T>(target)); + } + + template <std::size_t... I, typename T> + void set_extra(std::true_type, std::index_sequence<I...>, T&& target) { + using std::get; + (void)detail::swallow { 0, (get<I>(static_cast<base_t&>(*this)) = get<I>(types<Tn...>(), target), 0)..., 0 }; + } + + template <std::size_t... I, typename T> + void set_extra(std::false_type, std::index_sequence<I...>, T&& target) { + using std::get; + (void)detail::swallow { 0, (get<I>(static_cast<base_t&>(*this)) = get<I>(target), 0)..., 0 }; + } + + public: + using base_t::base_t; + + template <typename T> + tie_t& operator=(T&& value) { + typedef is_tieable<meta::unqualified_t<T>> tieable; + set(tieable(), std::forward<T>(value)); + return *this; + } + }; + + template <typename... Tn> + struct tie_size<tie_t<Tn...>> : std::tuple_size<std::tuple<Tn...>> { }; + + namespace adl_barrier_detail { + template <typename... Tn> + inline tie_t<std::remove_reference_t<Tn>...> tie(Tn&&... argn) { + return tie_t<std::remove_reference_t<Tn>...>(std::forward<Tn>(argn)...); + } + } // namespace adl_barrier_detail + + using namespace adl_barrier_detail; + +} // namespace sol + +// end of sol/tie.hpp + +// beginning of sol/stack_guard.hpp + +#include <functional> + +namespace sol { + namespace detail { + inline void stack_fail(int, int) { +#if SOL_IS_ON(SOL_EXCEPTIONS) + throw error(detail::direct_error, "imbalanced stack after operation finish"); +#else + // Lol, what do you want, an error printout? :3c + // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so + // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. +#endif // No Exceptions + } + } // namespace detail + + struct stack_guard { + lua_State* L; + int top; + std::function<void(int, int)> on_mismatch; + + stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) { + } + stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) { + } + bool check_stack(int modification = 0) const { + int bottom = lua_gettop(L) + modification; + if (top == bottom) { + return true; + } + on_mismatch(top, bottom); + return false; + } + ~stack_guard() { + check_stack(); + } + }; +} // namespace sol + +// end of sol/stack_guard.hpp + +#include <vector> +#include <bitset> +#include <forward_list> +#include <string> +#include <limits> +#include <algorithm> +#include <sstream> +#include <optional> +#include <type_traits> + +namespace sol { + namespace detail { + struct with_function_tag { }; + struct as_reference_tag { }; + template <typename T> + struct as_pointer_tag { }; + template <typename T> + struct as_value_tag { }; + template <typename T> + struct as_unique_tag { }; + template <typename T> + struct as_table_tag { }; + + template <typename Tag> + inline constexpr bool is_tagged_v + = meta::is_specialization_of_v<Tag, + detail:: + as_pointer_tag> || meta::is_specialization_of_v<Tag, as_value_tag> || meta::is_specialization_of_v<Tag, as_unique_tag> || meta::is_specialization_of_v<Tag, as_table_tag> || std::is_same_v<Tag, as_reference_tag> || std::is_same_v<Tag, with_function_tag>; + + using lua_reg_table = luaL_Reg[64]; + + using unique_destructor = void (*)(void*); + using unique_tag = detail::inheritance_unique_cast_function; + + inline void* alloc_newuserdata(lua_State* L, std::size_t bytesize) { +#if SOL_LUA_VERSION_I_ >= 504 + return lua_newuserdatauv(L, bytesize, 1); +#else + return lua_newuserdata(L, bytesize); +#endif + } + + constexpr std::uintptr_t align(std::size_t alignment, std::uintptr_t ptr, std::size_t& space) { + // this handles arbitrary alignments... + // make this into a power-of-2-only? + // actually can't: this is a C++14-compatible framework, + // power of 2 alignment is C++17 + std::uintptr_t offby = static_cast<std::uintptr_t>(ptr % alignment); + std::uintptr_t padding = (alignment - offby) % alignment; + ptr += padding; + space -= padding; + return ptr; + } + + inline void* align(std::size_t alignment, void* ptr, std::size_t& space) { + return reinterpret_cast<void*>(align(alignment, reinterpret_cast<std::uintptr_t>(ptr), space)); + } + + constexpr std::uintptr_t align_one(std::size_t alignment, std::size_t size, std::uintptr_t ptr) { + std::size_t space = (std::numeric_limits<std::size_t>::max)(); + return align(alignment, ptr, space) + size; + } + + template <typename... Args> + constexpr std::size_t aligned_space_for(std::uintptr_t ptr) { + std::uintptr_t end = ptr; + ((end = align_one(alignof(Args), sizeof(Args), end)), ...); + return static_cast<std::size_t>(end - ptr); + } + + template <typename... Args> + constexpr std::size_t aligned_space_for() { + static_assert(sizeof...(Args) > 0); + + constexpr std::size_t max_arg_alignment = (std::max)({ alignof(Args)... }); + if constexpr (max_arg_alignment <= alignof(std::max_align_t)) { + // If all types are `good enough`, simply calculate alignment in case of the worst allocator + std::size_t worst_required_size = 0; + for (std::size_t ptr = 0; ptr < max_arg_alignment; ptr++) { + worst_required_size = (std::max)(worst_required_size, aligned_space_for<Args...>(ptr)); + } + return worst_required_size; + } + else { + // For over-aligned types let's assume that every Arg in Args starts at the worst aligned address + return (aligned_space_for<Args>(0x1) + ...); + } + } + + inline void* align_usertype_pointer(void* ptr) { + using use_align = std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of<void*>::value > 1) +#endif + >; + if (!use_align::value) { + return ptr; + } + std::size_t space = (std::numeric_limits<std::size_t>::max)(); + return align(std::alignment_of<void*>::value, ptr, space); + } + + template <bool pre_aligned = false, bool pre_shifted = false> + void* align_usertype_unique_destructor(void* ptr) { + using use_align = std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of<unique_destructor>::value > 1) +#endif + >; + if (!pre_aligned) { + ptr = align_usertype_pointer(ptr); + } + if (!pre_shifted) { + ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(void*)); + } + if (!use_align::value) { + return static_cast<void*>(static_cast<void**>(ptr) + 1); + } + std::size_t space = (std::numeric_limits<std::size_t>::max)(); + return align(std::alignment_of<unique_destructor>::value, ptr, space); + } + + template <bool pre_aligned = false, bool pre_shifted = false> + void* align_usertype_unique_tag(void* ptr) { + using use_align = std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of<unique_tag>::value > 1) +#endif + >; + if (!pre_aligned) { + ptr = align_usertype_unique_destructor(ptr); + } + if (!pre_shifted) { + ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_destructor)); + } + if (!use_align::value) { + return ptr; + } + std::size_t space = (std::numeric_limits<std::size_t>::max)(); + return align(std::alignment_of<unique_tag>::value, ptr, space); + } + + template <typename T, bool pre_aligned = false, bool pre_shifted = false> + void* align_usertype_unique(void* ptr) { + typedef std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of_v<T> > 1) +#endif + > + use_align; + if (!pre_aligned) { + ptr = align_usertype_unique_tag(ptr); + } + if (!pre_shifted) { + ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_tag)); + } + if (!use_align::value) { + return ptr; + } + std::size_t space = (std::numeric_limits<std::size_t>::max)(); + return align(std::alignment_of_v<T>, ptr, space); + } + + template <typename T> + void* align_user(void* ptr) { + typedef std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of_v<T> > 1) +#endif + > + use_align; + if (!use_align::value) { + return ptr; + } + std::size_t space = (std::numeric_limits<std::size_t>::max)(); + return align(std::alignment_of_v<T>, ptr, space); + } + + template <typename T> + T** usertype_allocate_pointer(lua_State* L) { + typedef std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of<T*>::value > 1) +#endif + > + use_align; + if (!use_align::value) { + T** pointerpointer = static_cast<T**>(alloc_newuserdata(L, sizeof(T*))); + return pointerpointer; + } + constexpr std::size_t initial_size = aligned_space_for<T*>(); + + std::size_t allocated_size = initial_size; + void* unadjusted = alloc_newuserdata(L, initial_size); + void* adjusted = align(std::alignment_of<T*>::value, unadjusted, allocated_size); + if (adjusted == nullptr) { + // trash allocator can burn in hell + lua_pop(L, 1); + // luaL_error(L, "if you are the one that wrote this allocator you should feel bad for doing a + // worse job than malloc/realloc and should go read some books, yeah?"); + luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T*>().data()); + } + return static_cast<T**>(adjusted); + } + + inline bool attempt_alloc(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t value_align, + std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) { + void* adjusted = alloc_newuserdata(L, allocated_size); + pointer_adjusted = align(ptr_align, adjusted, allocated_size); + if (pointer_adjusted == nullptr) { + lua_pop(L, 1); + return false; + } + // subtract size of what we're going to allocate there + allocated_size -= ptr_size; + adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + ptr_size); + data_adjusted = align(value_align, adjusted, allocated_size); + if (data_adjusted == nullptr) { + lua_pop(L, 1); + return false; + } + return true; + } + + inline bool attempt_alloc_unique(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t real_align, + std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& id_adjusted, void*& data_adjusted) { + void* adjusted = alloc_newuserdata(L, allocated_size); + pointer_adjusted = align(ptr_align, adjusted, allocated_size); + if (pointer_adjusted == nullptr) { + lua_pop(L, 1); + return false; + } + allocated_size -= ptr_size; + + adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + ptr_size); + dx_adjusted = align(std::alignment_of_v<unique_destructor>, adjusted, allocated_size); + if (dx_adjusted == nullptr) { + lua_pop(L, 1); + return false; + } + allocated_size -= sizeof(unique_destructor); + + adjusted = static_cast<void*>(static_cast<char*>(dx_adjusted) + sizeof(unique_destructor)); + + id_adjusted = align(std::alignment_of_v<unique_tag>, adjusted, allocated_size); + if (id_adjusted == nullptr) { + lua_pop(L, 1); + return false; + } + allocated_size -= sizeof(unique_tag); + + adjusted = static_cast<void*>(static_cast<char*>(id_adjusted) + sizeof(unique_tag)); + data_adjusted = align(real_align, adjusted, allocated_size); + if (data_adjusted == nullptr) { + lua_pop(L, 1); + return false; + } + return true; + } + + template <typename T> + T* usertype_allocate(lua_State* L) { + typedef std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of<T*>::value > 1 || std::alignment_of_v<T> > 1) +#endif + > + use_align; + if (!use_align::value) { + T** pointerpointer = static_cast<T**>(alloc_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& pointerreference = *pointerpointer; + T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1); + pointerreference = allocationtarget; + return allocationtarget; + } + + constexpr std::size_t initial_size = aligned_space_for<T*, T>(); + + void* pointer_adjusted; + void* data_adjusted; + bool result + = attempt_alloc(L, std::alignment_of_v<T*>, sizeof(T*), std::alignment_of_v<T>, initial_size, pointer_adjusted, data_adjusted); + if (!result) { + if (pointer_adjusted == nullptr) { + luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str()); + } + else { + luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str()); + } + return nullptr; + } + + T** pointerpointer = reinterpret_cast<T**>(pointer_adjusted); + T*& pointerreference = *pointerpointer; + T* allocationtarget = reinterpret_cast<T*>(data_adjusted); + pointerreference = allocationtarget; + return allocationtarget; + } + + template <typename T, typename Real> + Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) { + typedef std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of<T*>::value > 1 || std::alignment_of<unique_tag>::value > 1 || std::alignment_of<unique_destructor>::value > 1 + || std::alignment_of<Real>::value > 1) +#endif + > + use_align; + if (!use_align::value) { + pref = static_cast<T**>(alloc_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(unique_tag) + sizeof(Real))); + dx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1)); + id = static_cast<unique_tag*>(static_cast<void*>(dx + 1)); + Real* mem = static_cast<Real*>(static_cast<void*>(id + 1)); + return mem; + } + + constexpr std::size_t initial_size = aligned_space_for<T*, unique_destructor, unique_tag, Real>(); + + void* pointer_adjusted; + void* dx_adjusted; + void* id_adjusted; + void* data_adjusted; + bool result = attempt_alloc_unique(L, + std::alignment_of_v<T*>, + sizeof(T*), + std::alignment_of_v<Real>, + initial_size, + pointer_adjusted, + dx_adjusted, + id_adjusted, + data_adjusted); + if (!result) { + if (pointer_adjusted == nullptr) { + luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str()); + } + else if (dx_adjusted == nullptr) { + luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle<T>().c_str()); + } + else { + luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str()); + } + return nullptr; + } + + pref = static_cast<T**>(pointer_adjusted); + dx = static_cast<detail::unique_destructor*>(dx_adjusted); + id = static_cast<unique_tag*>(id_adjusted); + Real* mem = static_cast<Real*>(data_adjusted); + return mem; + } + + template <typename T> + T* user_allocate(lua_State* L) { + typedef std::integral_constant<bool, +#if SOL_IS_OFF(SOL_ALIGN_MEMORY) + false +#else + (std::alignment_of_v<T> > 1) +#endif + > + use_align; + if (!use_align::value) { + T* pointer = static_cast<T*>(alloc_newuserdata(L, sizeof(T))); + return pointer; + } + + constexpr std::size_t initial_size = aligned_space_for<T>(); + + std::size_t allocated_size = initial_size; + void* unadjusted = alloc_newuserdata(L, allocated_size); + void* adjusted = align(std::alignment_of_v<T>, unadjusted, allocated_size); + if (adjusted == nullptr) { + lua_pop(L, 1); + luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data()); + } + return static_cast<T*>(adjusted); + } + + template <typename T> + int usertype_alloc_destroy(lua_State* L) noexcept { + void* memory = lua_touserdata(L, 1); + memory = align_usertype_pointer(memory); + T** pdata = static_cast<T**>(memory); + T* data = *pdata; + std::allocator<T> alloc {}; + std::allocator_traits<std::allocator<T>>::destroy(alloc, data); + return 0; + } + + template <typename T> + int unique_destroy(lua_State* L) noexcept { + void* memory = lua_touserdata(L, 1); + memory = align_usertype_unique_destructor(memory); + unique_destructor& dx = *static_cast<unique_destructor*>(memory); + memory = align_usertype_unique_tag<true>(memory); + (dx)(memory); + return 0; + } + + template <typename T> + int user_alloc_destroy(lua_State* L) noexcept { + void* memory = lua_touserdata(L, 1); + void* aligned_memory = align_user<T>(memory); + T* typed_memory = static_cast<T*>(aligned_memory); + std::allocator<T> alloc; + std::allocator_traits<std::allocator<T>>::destroy(alloc, typed_memory); + return 0; + } + + template <typename T, typename Real> + void usertype_unique_alloc_destroy(void* memory) { + void* aligned_memory = align_usertype_unique<Real, true>(memory); + Real* typed_memory = static_cast<Real*>(aligned_memory); + std::allocator<Real> alloc; + std::allocator_traits<std::allocator<Real>>::destroy(alloc, typed_memory); + } + + template <typename T> + int cannot_destroy(lua_State* L) { + return luaL_error(L, + "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= " + "delete' and thusly this type is being destroyed without properly destroying, invoking undefined " + "behavior: please bind a usertype and specify a custom destructor to define the behavior properly", + detail::demangle<T>().data()); + } + + template <typename T> + void reserve(T&, std::size_t) { + } + + template <typename T, typename Al> + void reserve(std::vector<T, Al>& vec, std::size_t hint) { + vec.reserve(hint); + } + + template <typename T, typename Tr, typename Al> + void reserve(std::basic_string<T, Tr, Al>& str, std::size_t hint) { + str.reserve(hint); + } + + inline bool property_always_true(meta_function) { + return true; + } + + struct properties_enrollment_allowed { + int& times_through; + std::bitset<64>& properties; + automagic_enrollments& enrollments; + + properties_enrollment_allowed(int& times_through_, std::bitset<64>& properties_, automagic_enrollments& enrollments_) + : times_through(times_through_), properties(properties_), enrollments(enrollments_) { + } + + bool operator()(meta_function mf) const { + bool p = properties[static_cast<std::size_t>(mf)]; + if (times_through > 0) { + return p; + } + switch (mf) { + case meta_function::length: + return enrollments.length_operator && !p; + case meta_function::pairs: + return enrollments.pairs_operator && !p; + case meta_function::call: + return enrollments.call_operator && !p; + case meta_function::less_than: + return enrollments.less_than_operator && !p; + case meta_function::less_than_or_equal_to: + return enrollments.less_than_or_equal_to_operator && !p; + case meta_function::equal_to: + return enrollments.equal_to_operator && !p; + default: + break; + } + return !p; + } + }; + + struct indexed_insert { + lua_reg_table& registration_table; + int& index; + + indexed_insert(lua_reg_table& registration_table_, int& index_ref_) : registration_table(registration_table_), index(index_ref_) { + } + void operator()(meta_function meta_function_name_, lua_CFunction c_function_) { + registration_table[index] = luaL_Reg { to_string(meta_function_name_).c_str(), c_function_ }; + ++index; + } + }; + } // namespace detail + + namespace stack { + + template <typename T, bool global = false, bool raw = false, typename = void> + struct field_getter; + template <typename T, typename P, bool global = false, bool raw = false, typename = void> + struct probe_field_getter; + + template <typename T, bool global = false, bool raw = false, typename = void> + struct field_setter; + + template <typename T, typename = void> + struct unqualified_getter; + template <typename T, typename = void> + struct qualified_getter; + + template <typename T, typename = void> + struct qualified_interop_getter; + template <typename T, typename = void> + struct unqualified_interop_getter; + + template <typename T, typename = void> + struct popper; + + template <typename T, typename = void> + struct unqualified_pusher; + + template <typename T, type t, typename = void> + struct unqualified_checker; + template <typename T, type t, typename = void> + struct qualified_checker; + + template <typename T, typename = void> + struct unqualified_check_getter; + template <typename T, typename = void> + struct qualified_check_getter; + + struct probe { + bool success; + int levels; + + probe(bool s, int l) : success(s), levels(l) { + } + + operator bool() const { + return success; + }; + }; + + struct record { + int last; + int used; + + record() noexcept : last(), used() { + } + void use(int count) noexcept { + last = count; + used += count; + } + }; + + namespace stack_detail { + template <typename Function> + Function* get_function_pointer(lua_State*, int, record&) noexcept; + template <typename Function, typename Handler> + bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept; + } // namespace stack_detail + + } // namespace stack + + namespace meta { namespace meta_detail { + template <typename T> + using adl_sol_lua_get_test_t = decltype(sol_lua_get(types<T>(), static_cast<lua_State*>(nullptr), -1, std::declval<stack::record&>())); + + template <typename T> + using adl_sol_lua_interop_get_test_t + = decltype(sol_lua_interop_get(types<T>(), static_cast<lua_State*>(nullptr), -1, static_cast<void*>(nullptr), std::declval<stack::record&>())); + + template <typename T> + using adl_sol_lua_check_test_t = decltype(sol_lua_check(types<T>(), static_cast<lua_State*>(nullptr), -1, &no_panic, std::declval<stack::record&>())); + + template <typename T> + using adl_sol_lua_interop_check_test_t + = decltype(sol_lua_interop_check(types<T>(), static_cast<lua_State*>(nullptr), -1, type::none, &no_panic, std::declval<stack::record&>())); + + template <typename T> + using adl_sol_lua_check_get_test_t + = decltype(sol_lua_check_get(types<T>(), static_cast<lua_State*>(nullptr), -1, &no_panic, std::declval<stack::record&>())); + + template <typename... Args> + using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast<lua_State*>(nullptr), std::declval<Args>()...)); + + template <typename T, typename... Args> + using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(types<T>(), static_cast<lua_State*>(nullptr), std::declval<Args>()...)); + + template <typename T> + inline constexpr bool is_adl_sol_lua_get_v = meta::is_detected_v<adl_sol_lua_get_test_t, T>; + + template <typename T> + inline constexpr bool is_adl_sol_lua_interop_get_v = meta::is_detected_v<adl_sol_lua_interop_get_test_t, T>; + + template <typename T> + inline constexpr bool is_adl_sol_lua_check_v = meta::is_detected_v<adl_sol_lua_check_test_t, T>; + + template <typename T> + inline constexpr bool is_adl_sol_lua_interop_check_v = meta::is_detected_v<adl_sol_lua_interop_check_test_t, T>; + + template <typename T> + inline constexpr bool is_adl_sol_lua_check_get_v = meta::is_detected_v<adl_sol_lua_check_get_test_t, T>; + + template <typename... Args> + inline constexpr bool is_adl_sol_lua_push_v = meta::is_detected_v<adl_sol_lua_push_test_t, Args...>; + + template <typename T, typename... Args> + inline constexpr bool is_adl_sol_lua_push_exact_v = meta::is_detected_v<adl_sol_lua_push_exact_test_t, T, Args...>; + }} // namespace meta::meta_detail + + namespace stack { + namespace stack_detail { + constexpr const char* not_enough_stack_space = "not enough space left on Lua stack"; + constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number"; + constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number"; + constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string"; + constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function"; + constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol2 userdata"; + constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees"; + constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment"; + + template <typename T> + struct strip { + typedef T type; + }; + template <typename T> + struct strip<std::reference_wrapper<T>> { + typedef T& type; + }; + template <typename T> + struct strip<user<T>> { + typedef T& type; + }; + template <typename T> + struct strip<non_null<T>> { + typedef T type; + }; + template <typename T> + using strip_t = typename strip<T>::type; + + template <typename C> + static int get_size_hint(C& c) { + return static_cast<int>(c.size()); + } + + template <typename V, typename Al> + static int get_size_hint(const std::forward_list<V, Al>&) { + // forward_list makes me sad + return static_cast<int>(32); + } + + template <typename T> + decltype(auto) unchecked_unqualified_get(lua_State* L, int index, record& tracking) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<Tu>) { + return sol_lua_get(types<Tu>(), L, index, tracking); + } + else { + unqualified_getter<Tu> g {}; + return g.get(L, index, tracking); + } + } + + template <typename T> + decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { + if constexpr (meta::meta_detail::is_adl_sol_lua_get_v<T>) { + return sol_lua_get(types<T>(), L, index, tracking); + } + else { + qualified_getter<T> g {}; + return g.get(L, index, tracking); + } + } + + template <typename T> + decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<Tu>) { + return sol_lua_interop_get(types<Tu>(), L, index, unadjusted_pointer, tracking); + } + else { + (void)L; + (void)index; + (void)unadjusted_pointer; + (void)tracking; + using Ti = stack_detail::strip_t<Tu>; + return std::pair<bool, Ti*> { false, nullptr }; + } + } + + template <typename T> + decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) { + if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v<T>) { + return sol_lua_interop_get(types<T>(), L, index, unadjusted_pointer, tracking); + } + else { + return unqualified_interop_get<T>(L, index, unadjusted_pointer, tracking); + } + } + + template <typename T, typename Handler> + bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<Tu>) { + return sol_lua_interop_check(types<Tu>(), L, index, index_type, std::forward<Handler>(handler), tracking); + } + else { + (void)L; + (void)index; + (void)index_type; + (void)handler; + (void)tracking; + return false; + } + } + + template <typename T, typename Handler> + bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { + if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v<T>) { + return sol_lua_interop_check(types<T>(), L, index, index_type, std::forward<Handler>(handler), tracking); + } + else { + return unqualified_interop_check<T>(L, index, index_type, std::forward<Handler>(handler), tracking); + } + } + + using undefined_method_func = void (*)(stack_reference); + + struct undefined_metatable { + lua_State* L; + const char* key; + undefined_method_func on_new_table; + + undefined_metatable(lua_State* l, const char* k, undefined_method_func umf) : L(l), key(k), on_new_table(umf) { + } + + void operator()() const { + if (luaL_newmetatable(L, key) == 1) { + on_new_table(stack_reference(L, -1)); + } + lua_setmetatable(L, -2); + } + }; + } // namespace stack_detail + + inline bool maybe_indexable(lua_State* L, int index = -1) { + type t = type_of(L, index); + return t == type::userdata || t == type::table; + } + + inline int top(lua_State* L) { + return lua_gettop(L); + } + + inline bool is_main_thread(lua_State* L) { + int ismainthread = lua_pushthread(L); + lua_pop(L, 1); + return ismainthread == 1; + } + + inline void coroutine_create_guard(lua_State* L) { + if (is_main_thread(L)) { + return; + } + int stacksize = lua_gettop(L); + if (stacksize < 1) { + return; + } + if (type_of(L, 1) != type::function) { + return; + } + // well now we're screwed... + // we can clean the stack and pray it doesn't destroy anything? + lua_pop(L, stacksize); + } + + inline void clear(lua_State* L, int table_index) { + lua_pushnil(L); + while (lua_next(L, table_index) != 0) { + // remove value + lua_pop(L, 1); + // duplicate key to protect form rawset + lua_pushvalue(L, -1); + // push new value + lua_pushnil(L); + // table_index%[key] = nil + lua_rawset(L, table_index); + } + } + + inline void clear(reference& r) { + auto pp = push_pop<false>(r); + int stack_index = pp.index_of(r); + clear(r.lua_state(), stack_index); + } + + inline void clear(stack_reference& r) { + clear(r.lua_state(), r.stack_index()); + } + + inline void clear(lua_State* L_, stateless_reference& r) { + r.push(L_); + int stack_index = absolute_index(L_, -1); + clear(L_, stack_index); + r.pop(L_); + } + + inline void clear(lua_State* L_, stateless_stack_reference& r) { + clear(L_, r.stack_index()); + } + + template <typename T, typename... Args> + int push(lua_State* L, T&& t, Args&&... args) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, T, Args...>) { + return sol_lua_push(types<T>(), L, std::forward<T>(t), std::forward<Args>(args)...); + } + else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, T, Args...>) { + return sol_lua_push(types<Tu>(), L, std::forward<T>(t), std::forward<Args>(args)...); + } + else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<T, Args...>) { + return sol_lua_push(L, std::forward<T>(t), std::forward<Args>(args)...); + } + else { + unqualified_pusher<Tu> p {}; + return p.push(L, std::forward<T>(t), std::forward<Args>(args)...); + } + } + + // overload allows to use a pusher of a specific type, but pass in any kind of args + template <typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>> + int push(lua_State* L, Arg&& arg, Args&&... args) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<T, Arg, Args...>) { + return sol_lua_push(types<T>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v<Tu, Arg, Args...>) { + return sol_lua_push(types<Tu>(), L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v<Arg, Args...> && !detail::is_tagged_v<Tu>) { + return sol_lua_push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + else { + unqualified_pusher<Tu> p {}; + return p.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + } + + template <typename T, typename... Args> + int push_userdata(lua_State* L, T&& t, Args&&... args) { + using U = meta::unqualified_t<T>; + using Tr = meta::conditional_t<std::is_pointer_v<U>, + detail::as_pointer_tag<std::remove_pointer_t<U>>, + meta::conditional_t<is_unique_usertype_v<U>, detail::as_unique_tag<U>, detail::as_value_tag<U>>>; + return stack::push<Tr>(L, std::forward<T>(t), std::forward<Args>(args)...); + } + + template <typename T, typename Arg, typename... Args> + int push_userdata(lua_State* L, Arg&& arg, Args&&... args) { + using U = meta::unqualified_t<T>; + using Tr = meta::conditional_t<std::is_pointer_v<U>, + detail::as_pointer_tag<std::remove_pointer_t<U>>, + meta::conditional_t<is_unique_usertype_v<U>, detail::as_unique_tag<U>, detail::as_value_tag<U>>>; + return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + + namespace stack_detail { + + template <typename T, typename Arg, typename... Args> + int push_reference(lua_State* L, Arg&& arg, Args&&... args) { + // clang-format off + using use_reference_tag = + meta::all< + meta::neg<is_value_semantic_for_function<T>> +#if SOL_IS_OFF(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + , std::is_lvalue_reference<T>, + meta::neg<std::is_const<std::remove_reference_t<T>>>, + meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, + meta::neg<is_unique_usertype<meta::unqualified_t<T>>> +#endif + >; + // clang-format on + using Tr = meta::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>; + return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + + } // namespace stack_detail + + template <typename T, typename... Args> + int push_reference(lua_State* L, T&& t, Args&&... args) { + return stack_detail::push_reference<T>(L, std::forward<T>(t), std::forward<Args>(args)...); + } + + template <typename T, typename Arg, typename... Args> + int push_reference(lua_State* L, Arg&& arg, Args&&... args) { + return stack_detail::push_reference<T>(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + + inline int multi_push(lua_State*) { + // do nothing + return 0; + } + + template <typename T, typename... Args> + int multi_push(lua_State* L, T&& t, Args&&... args) { + int pushcount = push(L, std::forward<T>(t)); + void(detail::swallow { (pushcount += stack::push(L, std::forward<Args>(args)), 0)... }); + return pushcount; + } + + inline int multi_push_reference(lua_State*) { + // do nothing + return 0; + } + + template <typename T, typename... Args> + int multi_push_reference(lua_State* L, T&& t, Args&&... args) { + int pushcount = stack::push_reference(L, std::forward<T>(t)); + void(detail::swallow { (pushcount += stack::push_reference(L, std::forward<Args>(args)), 0)... }); + return pushcount; + } + + template <typename T, typename Handler> + bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<Tu>) { + return sol_lua_check(types<Tu>(), L, index, std::forward<Handler>(handler), tracking); + } + else { + unqualified_checker<Tu, lua_type_of_v<Tu>> c{}; + return c.check(L, index, std::forward<Handler>(handler), tracking); + } + } + + template <typename T, typename Handler> + bool unqualified_check(lua_State* L, int index, Handler&& handler) { + record tracking {}; + return unqualified_check<T>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename T> + bool unqualified_check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + auto handler = &no_panic; + return unqualified_check<T>(L, index, handler); + } + + template <typename T, typename Handler> + bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + if constexpr (meta::meta_detail::is_adl_sol_lua_check_v<T>) { + return sol_lua_check(types<T>(), L, index, std::forward<Handler>(handler), tracking); + } + else { + using Tu = meta::unqualified_t<T>; + qualified_checker<T, lua_type_of_v<Tu>> c{}; + return c.check(L, index, std::forward<Handler>(handler), tracking); + } + } + + template <typename T, typename Handler> + bool check(lua_State* L, int index, Handler&& handler) { + record tracking {}; + return check<T>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename T> + bool check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + auto handler = &no_panic; + return check<T>(L, index, handler); + } + + template <typename T, typename Handler> + bool check_usertype(lua_State* L, int index, type, Handler&& handler, record& tracking) { + using Tu = meta::unqualified_t<T>; + using detail_t = meta::conditional_t<std::is_pointer_v<T>, detail::as_pointer_tag<Tu>, detail::as_value_tag<Tu>>; + return check<detail_t>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename T, typename Handler> + bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) { + using Tu = meta::unqualified_t<T>; + using detail_t = meta::conditional_t<std::is_pointer_v<T>, detail::as_pointer_tag<Tu>, detail::as_value_tag<Tu>>; + return check<detail_t>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename T, typename Handler> + bool check_usertype(lua_State* L, int index, Handler&& handler) { + record tracking {}; + return check_usertype<T>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename T> + bool check_usertype(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + auto handler = &no_panic; + return check_usertype<T>(L, index, handler); + } + + template <typename T, typename Handler> + decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler, record& tracking) { + using Tu = meta::unqualified_t<T>; + if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) { + return sol_lua_check_get(types<T>(), L, index, std::forward<Handler>(handler), tracking); + } + else if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<Tu>) { + return sol_lua_check_get(types<Tu>(), L, index, std::forward<Handler>(handler), tracking); + } + else { + unqualified_check_getter<Tu> cg {}; + return cg.get(L, index, std::forward<Handler>(handler), tracking); + } + } + + template <typename T, typename Handler> + decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler) { + record tracking {}; + return unqualified_check_get<T>(L, index, handler, tracking); + } + + template <typename T> + decltype(auto) unqualified_check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + auto handler = &no_panic; + return unqualified_check_get<T>(L, index, handler); + } + + template <typename T, typename Handler> + decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { + if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v<T>) { + return sol_lua_check_get(types<T>(), L, index, std::forward<Handler>(handler), tracking); + } + else { + qualified_check_getter<T> cg {}; + return cg.get(L, index, std::forward<Handler>(handler), tracking); + } + } + + template <typename T, typename Handler> + decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { + record tracking {}; + return check_get<T>(L, index, handler, tracking); + } + + template <typename T> + decltype(auto) check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + auto handler = &no_panic; + return check_get<T>(L, index, handler); + } + + namespace stack_detail { + + template <typename Handler> + bool check_types(lua_State*, int, Handler&&, record&) { + return true; + } + + template <typename T, typename... Args, typename Handler> + bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) { + if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking)) + return false; + return check_types<Args...>(L, firstargument, std::forward<Handler>(handler), tracking); + } + + template <typename... Args, typename Handler> + bool check_types(types<Args...>, lua_State* L, int index, Handler&& handler, record& tracking) { + return check_types<Args...>(L, index, std::forward<Handler>(handler), tracking); + } + + } // namespace stack_detail + + template <typename... Args, typename Handler> + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack_detail::check_types<Args...>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename... Args, typename Handler> + bool multi_check(lua_State* L, int index, Handler&& handler) { + record tracking {}; + return multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking); + } + + template <typename... Args> + bool multi_check(lua_State* L, int index) { + return multi_check<Args...>(L, index); + } + + template <typename T> + auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get<T>(L, index, tracking)) { +#if SOL_IS_ON(SOL_SAFE_GETTER) + static constexpr bool is_op = meta::is_optional_v<T>; + if constexpr (is_op) { + return stack_detail::unchecked_unqualified_get<T>(L, index, tracking); + } + else { + if (is_lua_reference<T>::value) { + return stack_detail::unchecked_unqualified_get<T>(L, index, tracking); + } + auto op = unqualified_check_get<T>(L, index, type_panic_c_str, tracking); + return *std::move(op); + } +#else + return stack_detail::unchecked_unqualified_get<T>(L, index, tracking); +#endif + } + + template <typename T> + decltype(auto) unqualified_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + record tracking {}; + return unqualified_get<T>(L, index, tracking); + } + + template <typename T> + auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) { +#if SOL_IS_ON(SOL_SAFE_GETTER) + static constexpr bool is_op = meta::is_optional_v<T>; + if constexpr (is_op) { + return stack_detail::unchecked_get<T>(L, index, tracking); + } + else { + if (is_lua_reference<T>::value) { + return stack_detail::unchecked_get<T>(L, index, tracking); + } + auto op = check_get<T>(L, index, type_panic_c_str, tracking); + return *std::move(op); + } +#else + return stack_detail::unchecked_get<T>(L, index, tracking); +#endif + } + + template <typename T> + decltype(auto) get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { + record tracking {}; + return get<T>(L, index, tracking); + } + + template <typename T> + decltype(auto) get_usertype(lua_State* L, int index, record& tracking) { + using UT = meta::conditional_t<std::is_pointer<T>::value, detail::as_pointer_tag<std::remove_pointer_t<T>>, detail::as_value_tag<T>>; + return get<UT>(L, index, tracking); + } + + template <typename T> + decltype(auto) get_usertype(lua_State* L, int index = -lua_size_v<meta::unqualified_t<T>>) { + record tracking {}; + return get_usertype<T>(L, index, tracking); + } + + template <typename T> + decltype(auto) pop(lua_State* L) { + return popper<T> {}.pop(L); + } + + template <bool global = false, bool raw = false, typename Key> + void get_field(lua_State* L, Key&& key) { + field_getter<meta::unqualified_t<Key>, global, raw> {}.get(L, std::forward<Key>(key)); + } + + template <bool global = false, bool raw = false, typename Key> + void get_field(lua_State* L, Key&& key, int tableindex) { + field_getter<meta::unqualified_t<Key>, global, raw> {}.get(L, std::forward<Key>(key), tableindex); + } + + template <bool global = false, typename Key> + void raw_get_field(lua_State* L, Key&& key) { + get_field<global, true>(L, std::forward<Key>(key)); + } + + template <bool global = false, typename Key> + void raw_get_field(lua_State* L, Key&& key, int tableindex) { + get_field<global, true>(L, std::forward<Key>(key), tableindex); + } + + template <bool global = false, bool raw = false, typename C = detail::non_lua_nil_t, typename Key> + probe probe_get_field(lua_State* L, Key&& key) { + return probe_field_getter<meta::unqualified_t<Key>, C, global, raw> {}.get(L, std::forward<Key>(key)); + } + + template <bool global = false, bool raw = false, typename C = detail::non_lua_nil_t, typename Key> + probe probe_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_field_getter<meta::unqualified_t<Key>, C, global, raw> {}.get(L, std::forward<Key>(key), tableindex); + } + + template <bool global = false, typename C = detail::non_lua_nil_t, typename Key> + probe probe_raw_get_field(lua_State* L, Key&& key) { + return probe_get_field<global, true, C>(L, std::forward<Key>(key)); + } + + template <bool global = false, typename C = detail::non_lua_nil_t, typename Key> + probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_get_field<global, true, C>(L, std::forward<Key>(key), tableindex); + } + + template <bool global = false, bool raw = false, typename Key, typename Value> + void set_field(lua_State* L, Key&& key, Value&& value) { + field_setter<meta::unqualified_t<Key>, global, raw> {}.set(L, std::forward<Key>(key), std::forward<Value>(value)); + } + + template <bool global = false, bool raw = false, typename Key, typename Value> + void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + field_setter<meta::unqualified_t<Key>, global, raw> {}.set(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); + } + + template <bool global = false, typename Key, typename Value> + void raw_set_field(lua_State* L, Key&& key, Value&& value) { + set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value)); + } + + template <bool global = false, typename Key, typename Value> + void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); + } + + template <typename T, typename F> + void modify_unique_usertype_as(const stack_reference& obj, F&& f) { + void* raw = lua_touserdata(obj.lua_state(), obj.stack_index()); + void* ptr_memory = detail::align_usertype_pointer(raw); + void* uu_memory = detail::align_usertype_unique<T>(raw); + T& uu = *static_cast<T*>(uu_memory); + f(uu); + *static_cast<void**>(ptr_memory) = static_cast<void*>(detail::unique_get(obj.lua_state(), uu)); + } + + template <typename F> + void modify_unique_usertype(const stack_reference& obj, F&& f) { + using bt = meta::bind_traits<meta::unqualified_t<F>>; + using T = typename bt::template arg_at<0>; + using Tu = meta::unqualified_t<T>; + modify_unique_usertype_as<Tu>(obj, std::forward<F>(f)); + } + + namespace stack_detail { + template <typename T, typename Handler> + decltype(auto) check_get_arg(lua_State* L_, int index_, Handler&& handler_, record& tracking_) { + if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v<T>) { + sol_lua_check_access(types<meta::unqualified_t<T>>(), L_, index_, tracking_); + } + return check_get<T>(L_, index_, std::forward<Handler>(handler_), tracking_); + } + + template <typename T> + decltype(auto) unchecked_get_arg(lua_State* L_, int index_, record& tracking_) { + if constexpr (meta::meta_detail::is_adl_sol_lua_check_access_v<T>) { + sol_lua_check_access(types<meta::unqualified_t<T>>(), L_, index_, tracking_); + } + return unchecked_get<T>(L_, index_, tracking_); + } + } // namespace stack_detail + + } // namespace stack + + namespace detail { + + template <typename T> + lua_CFunction make_destructor(std::true_type) { + if constexpr (is_unique_usertype_v<T>) { + return &unique_destroy<T>; + } + else if constexpr (!std::is_pointer_v<T>) { + return &usertype_alloc_destroy<T>; + } + else { + return &cannot_destroy<T>; + } + } + + template <typename T> + lua_CFunction make_destructor(std::false_type) { + return &cannot_destroy<T>; + } + + template <typename T> + lua_CFunction make_destructor() { + return make_destructor<T>(std::is_destructible<T>()); + } + + struct no_comp { + template <typename A, typename B> + bool operator()(A&&, B&&) const { + return false; + } + }; + + template <typename T> + int is_check(lua_State* L) { + return stack::push(L, stack::check<T>(L, 1, &no_panic)); + } + + template <typename T> + int member_default_to_string(std::true_type, lua_State* L) { + decltype(auto) ts = stack::get<T>(L, 1).to_string(); + return stack::push(L, std::forward<decltype(ts)>(ts)); + } + + template <typename T> + int member_default_to_string(std::false_type, lua_State* L) { + return luaL_error(L, + "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member " + "function, or operator<<(ostream&, ...) present", + detail::demangle<T>().data()); + } + + template <typename T> + int adl_default_to_string(std::true_type, lua_State* L) { + using namespace std; + decltype(auto) ts = to_string(stack::get<T>(L, 1)); + return stack::push(L, std::forward<decltype(ts)>(ts)); + } + + template <typename T> + int adl_default_to_string(std::false_type, lua_State* L) { + return member_default_to_string<T>(meta::supports_to_string_member<T>(), L); + } + + template <typename T> + int oss_default_to_string(std::true_type, lua_State* L) { + std::ostringstream oss; + oss << stack::unqualified_get<T>(L, 1); + return stack::push(L, oss.str()); + } + + template <typename T> + int oss_default_to_string(std::false_type, lua_State* L) { + return adl_default_to_string<T>(meta::supports_adl_to_string<T>(), L); + } + + template <typename T> + int default_to_string(lua_State* L) { + return oss_default_to_string<T>(meta::supports_op_left_shift<std::ostream, T>(), L); + } + + template <typename T> + int default_size(lua_State* L) { + decltype(auto) self = stack::unqualified_get<T>(L, 1); + return stack::push(L, self.size()); + } + + template <typename T, typename Op> + int comparsion_operator_wrap(lua_State* L) { + if constexpr (std::is_void_v<T>) { + return stack::push(L, false); + } + else { + auto maybel = stack::unqualified_check_get<T>(L, 1); + if (!maybel) { + return stack::push(L, false); + } + auto mayber = stack::unqualified_check_get<T>(L, 2); + if (!mayber) { + return stack::push(L, false); + } + decltype(auto) l = *maybel; + decltype(auto) r = *mayber; + if constexpr (std::is_same_v<no_comp, Op>) { + std::equal_to<> op; + return stack::push(L, op(detail::ptr(l), detail::ptr(r))); + } + else { + if constexpr (std::is_same_v<std::equal_to<>, Op> // clang-format hack + || std::is_same_v<std::less_equal<>, Op> // + || std::is_same_v<std::less_equal<>, Op>) { // + if (detail::ptr(l) == detail::ptr(r)) { + return stack::push(L, true); + } + } + Op op; + return stack::push(L, op(detail::deref(l), detail::deref(r))); + } + } + } + + template <typename T, typename IFx, typename Fx> + void insert_default_registrations(IFx&& ifx, Fx&& fx); + + template <typename T, bool, bool> + struct get_is_primitive : is_lua_primitive<T> { }; + + template <typename T> + struct get_is_primitive<T, true, false> + : meta::neg<std::is_reference<decltype(sol_lua_get(types<T>(), nullptr, -1, std::declval<stack::record&>()))>> { }; + + template <typename T> + struct get_is_primitive<T, false, true> + : meta::neg<std::is_reference<decltype(sol_lua_get(types<meta::unqualified_t<T>>(), nullptr, -1, std::declval<stack::record&>()))>> { }; + + template <typename T> + struct get_is_primitive<T, true, true> : get_is_primitive<T, true, false> { }; + + } // namespace detail + + template <typename T> + struct is_proxy_primitive + : detail::get_is_primitive<T, meta::meta_detail::is_adl_sol_lua_get_v<T>, meta::meta_detail::is_adl_sol_lua_get_v<meta::unqualified_t<T>>> { }; + +} // namespace sol + +// end of sol/stack_core.hpp + +// beginning of sol/stack_check.hpp + +// beginning of sol/stack_check_unqualified.hpp + +#include <memory> +#include <functional> +#include <utility> +#include <cmath> +#include <optional> +#if SOL_IS_ON(SOL_STD_VARIANT) +#include <variant> +#endif // variant shenanigans + +namespace sol { namespace stack { + template <typename Handler> + bool loose_table_check(lua_State* L_, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L_, index); + if (t == type::table) { + return true; + } + if (t != type::userdata) { + handler(L_, index, type::table, t, "value is not a table or a userdata that can behave like one"); + return false; + } + return true; + } + + namespace stack_detail { + inline bool impl_check_metatable(lua_State* L_, int index, const std::string& metakey, bool poptable) { + luaL_getmetatable(L_, &metakey[0]); + const type expectedmetatabletype = static_cast<type>(lua_type(L_, -1)); + if (expectedmetatabletype != type::lua_nil) { + if (lua_rawequal(L_, -1, index) == 1) { + lua_pop(L_, 1 + static_cast<int>(poptable)); + return true; + } + } + lua_pop(L_, 1); + return false; + } + + template <typename T, bool poptable = true> + inline bool check_metatable(lua_State* L_, int index = -2) { + return impl_check_metatable(L_, index, usertype_traits<T>::metatable(), poptable); + } + + template <type expected, int (*check_func)(lua_State*, int)> + struct basic_check { + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = check_func(L_, index) == 1; + if (!success) { + // expected type, actual type + handler(L_, index, expected, type_of(L_, index), ""); + } + return success; + } + }; + } // namespace stack_detail + + template <typename T, typename> + struct unqualified_interop_checker { + template <typename Handler> + static bool check(lua_State*, int, type, Handler&&, record&) { + return false; + } + }; + + template <typename T, typename> + struct qualified_interop_checker { + template <typename Handler> + static bool check(lua_State* L_, int index, type index_type, Handler&& handler, record& tracking) { + return stack_detail::unqualified_interop_check<T>(L_, index, index_type, std::forward<Handler>(handler), tracking); + } + }; + + template <typename T, type expected, typename> + struct unqualified_checker { + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + if constexpr (std::is_same_v<T, bool>) { + tracking.use(1); + bool success = lua_isboolean(L_, index) == 1; + if (!success) { + // expected type, actual type + handler(L_, index, expected, type_of(L_, index), ""); + } + return success; + } + else if constexpr (meta::any_same_v<T, + char +#if SOL_IS_ON(SOL_CHAR8_T) + , + char8_t +#endif + , + char16_t, + char32_t>) { + return stack::check<std::basic_string<T>>(L_, index, std::forward<Handler>(handler), tracking); + } + else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) { + tracking.use(1); +#if SOL_LUA_VERSION_I_ >= 503 + // Lua 5.3 and greater checks for numeric precision +#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS) + // imprecise, sloppy conversions + int isnum = 0; + lua_tointegerx(L_, index, &isnum); + const bool success = isnum != 0; + if (!success) { + // expected type, actual type + handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string_integral); + } +#elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) + // this check is precise, do not convert + if (lua_isinteger(L_, index) == 1) { + return true; + } + const bool success = false; + if (!success) { + // expected type, actual type + handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_integral); + } +#else + // Numerics are neither safe nor string-convertible + type t = type_of(L_, index); + const bool success = t == type::number; +#endif + if (!success) { + // expected type, actual type + handler(L_, index, type::number, type_of(L_, index), detail::not_a_number); + } + return success; +#else + // Lua 5.2 and below checks +#if SOL_IS_OFF(SOL_STRINGS_ARE_NUMBERS) + // must pre-check, because it will convert + type t = type_of(L_, index); + if (t != type::number) { + // expected type, actual type + handler(L_, index, type::number, t, detail::not_a_number); + return false; + } +#endif // Do not allow strings to be numbers + +#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) + int isnum = 0; + const lua_Number v = lua_tonumberx(L_, index, &isnum); + const bool success = isnum != 0 && static_cast<lua_Number>(llround(v)) == v; +#else + const bool success = true; +#endif // Safe numerics and number precision checking + if (!success) { + // Use defines to provide a better error message! +#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS) + handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string); +#elif SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) + handler(L_, index, type::number, t, detail::not_a_number_or_number_string); +#else + handler(L_, index, type::number, t, detail::not_a_number); +#endif + } + return success; +#endif + } + else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) { + tracking.use(1); +#if SOL_IS_ON(SOL_STRINGS_ARE_NUMBERS) + bool success = lua_isnumber(L_, index) == 1; + if (!success) { + // expected type, actual type + handler(L_, index, type::number, type_of(L_, index), detail::not_a_number_or_number_string); + } + return success; +#else + type t = type_of(L_, index); + bool success = t == type::number; + if (!success) { + // expected type, actual type + handler(L_, index, type::number, t, detail::not_a_number); + } + return success; +#endif // Strings are Numbers + } + else if constexpr (meta::any_same_v<T, type, this_state, this_main_state, this_environment, variadic_args>) { + (void)L_; + (void)index; + (void)handler; + tracking.use(0); + return true; + } + else if constexpr (is_unique_usertype_v<T>) { + using element = unique_usertype_element_t<T>; + using actual = unique_usertype_actual_t<T>; + const type indextype = type_of(L_, index); + tracking.use(1); + if (indextype != type::userdata) { + handler(L_, index, type::userdata, indextype, "value is not a userdata"); + return false; + } + if (lua_getmetatable(L_, index) == 0) { + return true; + } + int metatableindex = lua_gettop(L_); + if (stack_detail::check_metatable<d::u<element>>(L_, metatableindex)) { + void* memory = lua_touserdata(L_, index); + memory = detail::align_usertype_unique_destructor(memory); + detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory); + bool success = &detail::usertype_unique_alloc_destroy<element, actual> == pdx; + if (!success) { + memory = detail::align_usertype_unique_tag<true>(memory); +#if 0 + // New version, one day +#else + const char*& name_tag = *static_cast<const char**>(memory); + success = usertype_traits<T>::qualified_name() == name_tag; +#endif + if (!success) { + handler(L_, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype"); + } + } + return success; + } + lua_pop(L_, 1); + handler(L_, index, type::userdata, indextype, "unrecognized userdata (not pushed by sol?)"); + return false; + } + else if constexpr (meta::any_same_v<T, lua_nil_t, std::nullopt_t, nullopt_t>) { + bool success = lua_isnil(L_, index); + if (success) { + tracking.use(1); + return success; + } + tracking.use(0); + success = lua_isnone(L_, index); + if (!success) { + // expected type, actual type + handler(L_, index, expected, type_of(L_, index), ""); + } + return success; + } + else if constexpr (std::is_same_v<T, env_key_t>) { + tracking.use(1); + type t = type_of(L_, index); + if (t == type::table || t == type::none || t == type::lua_nil || t == type::userdata) { + return true; + } + handler(L_, index, type::table, t, "value cannot not have a valid environment"); + return true; + } + else if constexpr (std::is_same_v<T, detail::non_lua_nil_t>) { + return !stack::unqualified_check<lua_nil_t>(L_, index, std::forward<Handler>(handler), tracking); + } + else if constexpr (meta::is_specialization_of_v<T, basic_lua_table>) { + tracking.use(1); + type t = type_of(L_, index); + if (t != type::table) { + handler(L_, index, type::table, t, "value is not a table"); + return false; + } + return true; + } + else if constexpr (meta::is_specialization_of_v<T, basic_bytecode>) { + tracking.use(1); + type t = type_of(L_, index); + if (t != type::function) { + handler(L_, index, type::function, t, "value is not a function that can be dumped"); + return false; + } + return true; + } + else if constexpr (meta::is_specialization_of_v<T, basic_environment>) { + tracking.use(1); + if (lua_getmetatable(L_, index) == 0) { + return true; + } + type t = type_of(L_, -1); + if (t == type::table || t == type::none || t == type::lua_nil) { + lua_pop(L_, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L_, 1); + handler(L_, index, type::table, t, "value does not have a valid metatable"); + return false; + } + return true; + } + else if constexpr (std::is_same_v<T, metatable_key_t>) { + tracking.use(1); + if (lua_getmetatable(L_, index) == 0) { + return true; + } + type t = type_of(L_, -1); + if (t == type::table || t == type::none || t == type::lua_nil) { + lua_pop(L_, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L_, 1); + handler(L_, index, expected, t, "value does not have a valid metatable"); + return false; + } + return true; + } + else if constexpr (std::is_same_v<T, luaL_Stream*> || std::is_same_v<T, luaL_Stream>) { + if (lua_getmetatable(L_, index) == 0) { + type t = type_of(L_, index); + handler(L_, index, expected, t, "value is not a valid luaL_Stream (has no metatable/is not a valid value)"); + return false; + } + luaL_getmetatable(L_, LUA_FILEHANDLE); + if (type_of(L_, index) != type::table) { + type t = type_of(L_, index); + lua_pop(L_, 1); + handler(L_, + index, + expected, + t, + "value is not a valid luaL_Stream (there is no metatable for luaL_Stream -- did you forget to " + "my_lua_state.open_libraries(sol::lib::state) or equivalent?)"); + return false; + } + int is_stream_table = lua_compare(L_, -1, -2, LUA_OPEQ); + lua_pop(L_, 2); + if (is_stream_table == 0) { + type t = type_of(L_, index); + handler(L_, index, expected, t, "value is not a valid luaL_Stream (incorrect metatable)"); + return false; + } + return true; + } + else if constexpr (meta::is_optional_v<T>) { + using ValueType = typename T::value_type; + (void)handler; + type t = type_of(L_, index); + if (t == type::none) { + tracking.use(0); + return true; + } + if (t == type::lua_nil) { + tracking.use(1); + return true; + } + return stack::unqualified_check<ValueType>(L_, index, &no_panic, tracking); + } +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) { + return stack_detail::check_function_pointer<std::remove_pointer_t<T>>(L_, index, std::forward<Handler>(handler), tracking); + } +#endif + else if constexpr (expected == type::userdata) { + if constexpr (meta::any_same_v<T, userdata_value> || meta::is_specialization_of_v<T, basic_userdata>) { + tracking.use(1); + type t = type_of(L_, index); + bool success = t == type::userdata; + if (!success) { + // expected type, actual type + handler(L_, index, type::userdata, t, ""); + } + return success; + } + else if constexpr (meta::is_specialization_of_v<T, user>) { + unqualified_checker<lightuserdata_value, type::userdata> c; + (void)c; + return c.check(L_, index, std::forward<Handler>(handler), tracking); + } + else { + if constexpr (std::is_pointer_v<T>) { + return check_usertype<T>(L_, index, std::forward<Handler>(handler), tracking); + } + else if constexpr (meta::is_specialization_of_v<T, std::reference_wrapper>) { + using T_internal = typename T::type; + return stack::check<T_internal>(L_, index, std::forward<Handler>(handler), tracking); + } + else { + return check_usertype<T>(L_, index, std::forward<Handler>(handler), tracking); + } + } + } + else if constexpr (expected == type::poly) { + tracking.use(1); + bool success = is_lua_reference_v<T> || !lua_isnone(L_, index); + if (!success) { + // expected type, actual type + handler(L_, index, type::poly, type_of(L_, index), ""); + } + return success; + } + else if constexpr (expected == type::lightuserdata) { + tracking.use(1); + type t = type_of(L_, index); + bool success = t == type::userdata || t == type::lightuserdata; + if (!success) { + // expected type, actual type + handler(L_, index, type::lightuserdata, t, ""); + } + return success; + } + else if constexpr (expected == type::function) { + if constexpr (meta::any_same_v<T, lua_CFunction, std::remove_pointer_t<lua_CFunction>, c_closure>) { + tracking.use(1); + bool success = lua_iscfunction(L_, index) == 1; + if (!success) { + // expected type, actual type + handler(L_, index, expected, type_of(L_, index), ""); + } + return success; + } + else { + tracking.use(1); + type t = type_of(L_, index); + if (t == type::lua_nil || t == type::none || t == type::function) { + // allow for lua_nil to be returned + return true; + } + if (t != type::userdata && t != type::table) { + handler(L_, index, type::function, t, "must be a function or table or a userdata"); + return false; + } + // Do advanced check for call-style userdata? + static const auto& callkey = to_string(meta_function::call); + if (lua_getmetatable(L_, index) == 0) { + // No metatable, no __call key possible + handler(L_, index, type::function, t, "value is not a function and does not have overriden metatable"); + return false; + } + if (lua_isnoneornil(L_, -1)) { + lua_pop(L_, 1); + handler(L_, index, type::function, t, "value is not a function and does not have valid metatable"); + return false; + } + lua_getfield(L_, -1, &callkey[0]); + if (lua_isnoneornil(L_, -1)) { + lua_pop(L_, 2); + handler(L_, index, type::function, t, "value's metatable does not have __call overridden in metatable, cannot call this type"); + return false; + } + // has call, is definitely a function + lua_pop(L_, 2); + return true; + } + } + else if constexpr (expected == type::table) { + return stack::loose_table_check(L_, index, std::forward<Handler>(handler), tracking); + } + else { + tracking.use(1); + const type indextype = type_of(L_, index); + bool success = expected == indextype; + if (!success) { + // expected type, actual type, message + handler(L_, index, expected, indextype, ""); + } + return success; + } + } + }; + + template <typename T> + struct unqualified_checker<non_null<T>, type::userdata> : unqualified_checker<T, lua_type_of_v<T>> { }; + + template <typename T> + struct unqualified_checker<detail::as_value_tag<T>, type::userdata> { + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L_, index); + return check(types<T>(), L_, index, indextype, std::forward<Handler>(handler), tracking); + } + + template <typename U, typename Handler> + static bool check(types<U>, lua_State* L_, int index, type indextype, Handler&& handler, record& tracking) { + if constexpr ( + std::is_same_v<T, + lightuserdata_value> || std::is_same_v<T, userdata_value> || std::is_same_v<T, userdata> || std::is_same_v<T, lightuserdata>) { + tracking.use(1); + if (indextype != type::userdata) { + handler(L_, index, type::userdata, indextype, "value is not a valid userdata"); + return false; + } + return true; + } + else { +#if SOL_IS_ON(SOL_USE_INTEROP) + if (stack_detail::interop_check<U>(L_, index, indextype, handler, tracking)) { + return true; + } +#endif // interop extensibility + tracking.use(1); +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + if (lua_iscfunction(L_, index) != 0) { + // a potential match... + return true; + } +#endif + if (indextype != type::userdata) { + handler(L_, index, type::userdata, indextype, "value is not a valid userdata"); + return false; + } + if (lua_getmetatable(L_, index) == 0) { + return true; + } + int metatableindex = lua_gettop(L_); + if (stack_detail::check_metatable<U>(L_, metatableindex)) + return true; + if (stack_detail::check_metatable<U*>(L_, metatableindex)) + return true; + if (stack_detail::check_metatable<d::u<U>>(L_, metatableindex)) + return true; + if (stack_detail::check_metatable<as_container_t<U>>(L_, metatableindex)) + return true; + bool success = false; + bool has_derived = derive<T>::value || weak_derive<T>::value; + if (has_derived) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L_, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + auto pn = stack::pop_n(L_, 1); + lua_pushstring(L_, &detail::base_class_check_key()[0]); + lua_rawget(L_, metatableindex); + if (type_of(L_, -1) != type::lua_nil) { + void* basecastdata = lua_touserdata(L_, -1); + detail::inheritance_check_function ic = reinterpret_cast<detail::inheritance_check_function>(basecastdata); + success = ic(usertype_traits<T>::qualified_name()); + } + } + lua_pop(L_, 1); + if (!success) { + handler(L_, index, type::userdata, indextype, "value at this index does not properly reflect the desired type"); + return false; + } + return true; + } + } + }; + + template <typename T> + struct unqualified_checker<detail::as_pointer_tag<T>, type::userdata> { + template <typename Handler> + static bool check(lua_State* L_, int index, type indextype, Handler&& handler, record& tracking) { + if (indextype == type::lua_nil) { + tracking.use(1); + return true; + } + return check_usertype<std::remove_pointer_t<T>>(L_, index, std::forward<Handler>(handler), tracking); + } + + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L_, index); + return check(L_, index, indextype, std::forward<Handler>(handler), tracking); + } + }; + + template <typename... Args> + struct unqualified_checker<std::tuple<Args...>, type::poly> { + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + return stack::multi_check<Args...>(L_, index, std::forward<Handler>(handler), tracking); + } + }; + + template <typename A, typename B> + struct unqualified_checker<std::pair<A, B>, type::poly> { + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + return stack::multi_check<A, B>(L_, index, std::forward<Handler>(handler), tracking); + } + }; + +#if SOL_IS_ON(SOL_STD_VARIANT) + + template <typename... Tn> + struct unqualified_checker<std::variant<Tn...>, type::poly> { + typedef std::variant<Tn...> V; + typedef std::variant_size<V> V_size; + typedef std::integral_constant<bool, V_size::value == 0> V_is_empty; + + template <typename Handler> + static bool is_one(std::integral_constant<std::size_t, 0>, lua_State* L_, int index, Handler&& handler, record& tracking) { + if constexpr (V_is_empty::value) { + if (lua_isnone(L_, index)) { + return true; + } + } + tracking.use(1); + handler(L_, index, type::poly, type_of(L_, index), "value does not fit any type present in the variant"); + return false; + } + + template <std::size_t I, typename Handler> + static bool is_one(std::integral_constant<std::size_t, I>, lua_State* L_, int index, Handler&& handler, record& tracking) { + typedef std::variant_alternative_t<I - 1, V> T; + record temp_tracking = tracking; + if (stack::check<T>(L_, index, &no_panic, temp_tracking)) { + tracking = temp_tracking; + return true; + } + return is_one(std::integral_constant<std::size_t, I - 1>(), L_, index, std::forward<Handler>(handler), tracking); + } + + template <typename Handler> + static bool check(lua_State* L_, int index, Handler&& handler, record& tracking) { + return is_one(std::integral_constant<std::size_t, V_size::value>(), L_, index, std::forward<Handler>(handler), tracking); + } + }; + +#endif // variant shenanigans + +}} // namespace sol::stack + +// end of sol/stack_check_unqualified.hpp + +// beginning of sol/stack_check_qualified.hpp + +namespace sol { namespace stack { + + template <typename X, type expected, typename> + struct qualified_checker { + template <typename Handler> + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + using no_cv_X = meta::unqualified_t<X>; + if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<no_cv_X>) { + using element = unique_usertype_element_t<no_cv_X>; + if constexpr (is_actual_type_rebindable_for_v<no_cv_X>) { + using rebound_actual_type = unique_usertype_rebind_actual_t<no_cv_X>; + // we have a unique pointer type that can be + // rebound to a base/derived type + const type indextype = type_of(L, index); + tracking.use(1); + if (indextype != type::userdata) { + handler(L, index, type::userdata, indextype, "value is not a userdata"); + return false; + } + void* memory = lua_touserdata(L, index); + memory = detail::align_usertype_unique_destructor(memory); + detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory); + if (&detail::usertype_unique_alloc_destroy<element, no_cv_X> == pdx) { + return true; + } + if constexpr (derive<element>::value) { + memory = detail::align_usertype_unique_tag<true, false>(memory); + detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory); + string_view ti = usertype_traits<element>::qualified_name(); + string_view rebind_ti = usertype_traits<rebound_actual_type>::qualified_name(); + if (ic(nullptr, nullptr, ti, rebind_ti) != 0) { + return true; + } + } + handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype"); + return false; + } + else { + return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking); + } + } + else if constexpr (!std::is_reference_v<X> && is_container_v<no_cv_X>) { + if (type_of(L, index) == type::userdata) { + return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking); + } + else { + return stack::unqualified_check<nested<X>>(L, index, std::forward<Handler>(handler), tracking); + } + } + else if constexpr (!std::is_reference_v<X> && meta::is_specialization_of_v<X, nested>) { + using NestedX = typename meta::unqualified_t<X>::nested_type; + return stack::check<NestedX>(L, index, ::std::forward<Handler>(handler), tracking); + } + else { + return stack::unqualified_check<X>(L, index, std::forward<Handler>(handler), tracking); + } + } + }; +}} // namespace sol::stack + +// end of sol/stack_check_qualified.hpp + +// end of sol/stack_check.hpp + +// beginning of sol/stack_get.hpp + +// beginning of sol/stack_get_unqualified.hpp + +// beginning of sol/overload.hpp + +#include <utility> + +namespace sol { + template <typename... Functions> + struct overload_set { + std::tuple<Functions...> functions; + template <typename Arg, typename... Args, meta::disable<std::is_same<overload_set, meta::unqualified_t<Arg>>> = meta::enabler> + overload_set(Arg&& arg, Args&&... args) : functions(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + overload_set(const overload_set&) = default; + overload_set(overload_set&&) = default; + overload_set& operator=(const overload_set&) = default; + overload_set& operator=(overload_set&&) = default; + }; + + template <typename... Args> + decltype(auto) overload(Args&&... args) { + return overload_set<std::decay_t<Args>...>(std::forward<Args>(args)...); + } +} // namespace sol + +// end of sol/overload.hpp + +// beginning of sol/unicode.hpp + +#include <array> +#include <cstring> + +namespace sol { + // Everything here was lifted pretty much straight out of + // ogonek, because fuck figuring it out= + namespace unicode { + enum class error_code { + ok = 0, + invalid_code_point, + invalid_code_unit, + invalid_leading_surrogate, + invalid_trailing_surrogate, + sequence_too_short, + overlong_sequence, + }; + + inline const string_view& to_string(error_code ec) { + static const string_view storage[7] = { "ok", + "invalid code points", + "invalid code unit", + "invalid leading surrogate", + "invalid trailing surrogate", + "sequence too short", + "overlong sequence" }; + return storage[static_cast<std::size_t>(ec)]; + } + + template <typename It> + struct decoded_result { + error_code error; + char32_t codepoint; + It next; + }; + + template <typename C> + struct encoded_result { + error_code error; + std::size_t code_units_size; + std::array<C, 4> code_units; + }; + + struct unicode_detail { + // codepoint related + static constexpr char32_t last_code_point = 0x10FFFF; + + static constexpr char32_t first_lead_surrogate = 0xD800; + static constexpr char32_t last_lead_surrogate = 0xDBFF; + + static constexpr char32_t first_trail_surrogate = 0xDC00; + static constexpr char32_t last_trail_surrogate = 0xDFFF; + + static constexpr char32_t first_surrogate = first_lead_surrogate; + static constexpr char32_t last_surrogate = last_trail_surrogate; + + static constexpr bool is_lead_surrogate(char32_t u) { + return u >= first_lead_surrogate && u <= last_lead_surrogate; + } + static constexpr bool is_trail_surrogate(char32_t u) { + return u >= first_trail_surrogate && u <= last_trail_surrogate; + } + static constexpr bool is_surrogate(char32_t u) { + return u >= first_surrogate && u <= last_surrogate; + } + + // utf8 related + static constexpr auto last_1byte_value = 0x7Fu; + static constexpr auto last_2byte_value = 0x7FFu; + static constexpr auto last_3byte_value = 0xFFFFu; + + static constexpr auto start_2byte_mask = 0x80u; + static constexpr auto start_3byte_mask = 0xE0u; + static constexpr auto start_4byte_mask = 0xF0u; + + static constexpr auto continuation_mask = 0xC0u; + static constexpr auto continuation_signature = 0x80u; + + static constexpr bool is_invalid(unsigned char b) { + return b == 0xC0 || b == 0xC1 || b > 0xF4; + } + + static constexpr bool is_continuation(unsigned char b) { + return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature; + } + + static constexpr bool is_overlong(char32_t u, std::size_t bytes) { + return u <= unicode_detail::last_1byte_value || (u <= unicode_detail::last_2byte_value && bytes > 2) + || (u <= unicode_detail::last_3byte_value && bytes > 3); + } + + static constexpr int sequence_length(unsigned char b) { + return (b & start_2byte_mask) == 0 ? 1 + : (b & start_3byte_mask) != start_3byte_mask ? 2 + : (b & start_4byte_mask) != start_4byte_mask ? 3 + : 4; + } + + static constexpr char32_t decode(unsigned char b0, unsigned char b1) { + return (static_cast<char32_t>((b0 & 0x1Fu) << 6u) | static_cast<char32_t>(b1 & 0x3Fu)); + } + static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2) { + return static_cast<char32_t>((b0 & 0x0Fu) << 12u) | static_cast<char32_t>((b1 & 0x3Fu) << 6u) | static_cast<char32_t>(b2 & 0x3Fu); + } + static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) { + return static_cast<char32_t>(static_cast<char32_t>((b0 & 0x07u) << 18u) | static_cast<char32_t>((b1 & 0x3F) << 12) + | static_cast<char32_t>((b2 & 0x3Fu) << 6u) | static_cast<char32_t>(b3 & 0x3Fu)); + } + + // utf16 related + static constexpr char32_t last_bmp_value = 0xFFFF; + static constexpr char32_t normalizing_value = 0x10000; + static constexpr int lead_surrogate_bitmask = 0xFFC00; + static constexpr int trail_surrogate_bitmask = 0x3FF; + static constexpr int lead_shifted_bits = 10; + static constexpr char32_t replacement = 0xFFFD; + + static char32_t combine_surrogates(char16_t lead, char16_t trail) { + auto hi = lead - first_lead_surrogate; + auto lo = trail - first_trail_surrogate; + return normalizing_value + ((hi << lead_shifted_bits) | lo); + } + }; + + inline encoded_result<char> code_point_to_utf8(char32_t codepoint) { + encoded_result<char> er; + er.error = error_code::ok; + if (codepoint <= unicode_detail::last_1byte_value) { + er.code_units_size = 1; + er.code_units = std::array<char, 4> { { static_cast<char>(codepoint) } }; + } + else if (codepoint <= unicode_detail::last_2byte_value) { + er.code_units_size = 2; + er.code_units = std::array<char, 4> { { + static_cast<char>(0xC0 | ((codepoint & 0x7C0) >> 6)), + static_cast<char>(0x80 | (codepoint & 0x3F)), + } }; + } + else if (codepoint <= unicode_detail::last_3byte_value) { + er.code_units_size = 3; + er.code_units = std::array<char, 4> { { + static_cast<char>(0xE0 | ((codepoint & 0xF000) >> 12)), + static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)), + static_cast<char>(0x80 | (codepoint & 0x3F)), + } }; + } + else { + er.code_units_size = 4; + er.code_units = std::array<char, 4> { { + static_cast<char>(0xF0 | ((codepoint & 0x1C0000) >> 18)), + static_cast<char>(0x80 | ((codepoint & 0x3F000) >> 12)), + static_cast<char>(0x80 | ((codepoint & 0xFC0) >> 6)), + static_cast<char>(0x80 | (codepoint & 0x3F)), + } }; + } + return er; + } + + inline encoded_result<char16_t> code_point_to_utf16(char32_t codepoint) { + encoded_result<char16_t> er; + + if (codepoint <= unicode_detail::last_bmp_value) { + er.code_units_size = 1; + er.code_units = std::array<char16_t, 4> { { static_cast<char16_t>(codepoint) } }; + er.error = error_code::ok; + } + else { + auto normal = codepoint - unicode_detail::normalizing_value; + auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits); + auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask); + er.code_units = std::array<char16_t, 4> { { static_cast<char16_t>(lead), static_cast<char16_t>(trail) } }; + er.code_units_size = 2; + er.error = error_code::ok; + } + return er; + } + + inline encoded_result<char32_t> code_point_to_utf32(char32_t codepoint) { + encoded_result<char32_t> er; + er.code_units_size = 1; + er.code_units[0] = codepoint; + er.error = error_code::ok; + return er; + } + + template <typename It> + inline decoded_result<It> utf8_to_code_point(It it, It last) { + decoded_result<It> dr; + if (it == last) { + dr.next = it; + dr.error = error_code::sequence_too_short; + return dr; + } + + unsigned char b0 = static_cast<unsigned char>(*it); + std::size_t length = static_cast<std::size_t>(unicode_detail::sequence_length(b0)); + + if (length == 1) { + dr.codepoint = static_cast<char32_t>(b0); + dr.error = error_code::ok; + ++it; + dr.next = it; + return dr; + } + + if (unicode_detail::is_invalid(b0) || unicode_detail::is_continuation(b0)) { + dr.error = error_code::invalid_code_unit; + dr.next = it; + return dr; + } + + ++it; + std::array<unsigned char, 4> b; + b[0] = b0; + for (std::size_t i = 1; i < length; ++i) { + b[i] = static_cast<unsigned char>(*it); + if (!unicode_detail::is_continuation(b[i])) { + dr.error = error_code::invalid_code_unit; + dr.next = it; + return dr; + } + ++it; + } + + char32_t decoded; + switch (length) { + case 2: + decoded = unicode_detail::decode(b[0], b[1]); + break; + case 3: + decoded = unicode_detail::decode(b[0], b[1], b[2]); + break; + default: + decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]); + break; + } + + if (unicode_detail::is_overlong(decoded, length)) { + dr.error = error_code::overlong_sequence; + return dr; + } + if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) { + dr.error = error_code::invalid_code_point; + return dr; + } + + // then everything is fine + dr.codepoint = decoded; + dr.error = error_code::ok; + dr.next = it; + return dr; + } + + template <typename It> + inline decoded_result<It> utf16_to_code_point(It it, It last) { + decoded_result<It> dr; + if (it == last) { + dr.next = it; + dr.error = error_code::sequence_too_short; + return dr; + } + + char16_t lead = static_cast<char16_t>(*it); + + if (!unicode_detail::is_surrogate(lead)) { + ++it; + dr.codepoint = static_cast<char32_t>(lead); + dr.next = it; + dr.error = error_code::ok; + return dr; + } + if (!unicode_detail::is_lead_surrogate(lead)) { + dr.error = error_code::invalid_leading_surrogate; + dr.next = it; + return dr; + } + + ++it; + auto trail = *it; + if (!unicode_detail::is_trail_surrogate(trail)) { + dr.error = error_code::invalid_trailing_surrogate; + dr.next = it; + return dr; + } + + dr.codepoint = unicode_detail::combine_surrogates(lead, trail); + dr.next = ++it; + dr.error = error_code::ok; + return dr; + } + + template <typename It> + inline decoded_result<It> utf32_to_code_point(It it, It last) { + decoded_result<It> dr; + if (it == last) { + dr.next = it; + dr.error = error_code::sequence_too_short; + return dr; + } + dr.codepoint = static_cast<char32_t>(*it); + dr.next = ++it; + dr.error = error_code::ok; + return dr; + } + } // namespace unicode +} // namespace sol +// end of sol/unicode.hpp + +#include <memory> +#include <functional> +#include <utility> +#include <cstdlib> +#include <cmath> +#include <string_view> +#if SOL_IS_ON(SOL_STD_VARIANT) +#include <variant> +#endif // Apple clang screwed up + +namespace sol { namespace stack { + + namespace stack_detail { + template <typename Ch> + struct count_code_units_utf { + std::size_t needed_size; + + count_code_units_utf() : needed_size(0) { + } + + void operator()(const unicode::encoded_result<Ch> er) { + needed_size += er.code_units_size; + } + }; + + template <typename Ch, typename ErCh> + struct copy_code_units_utf { + Ch* target_; + + copy_code_units_utf(Ch* target) : target_(target) { + } + + void operator()(const unicode::encoded_result<ErCh> er) { + std::memcpy(target_, er.code_units.data(), er.code_units_size * sizeof(ErCh)); + target_ += er.code_units_size; + } + }; + + template <typename Ch, typename F> + inline void convert(const char* strb, const char* stre, F&& f) { + char32_t cp = 0; + for (const char* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf8_to_code_point(strtarget, stre); + if (dr.error != unicode::error_code::ok) { + cp = unicode::unicode_detail::replacement; + ++strtarget; + } + else { + cp = dr.codepoint; + strtarget = dr.next; + } + if constexpr (std::is_same_v<Ch, char32_t>) { + auto er = unicode::code_point_to_utf32(cp); + f(er); + } + else { + auto er = unicode::code_point_to_utf16(cp); + f(er); + } + } + } + + template <typename BaseCh, typename S> + inline S get_into(lua_State* L, int index, record& tracking) { + using Ch = typename S::value_type; + tracking.use(1); + size_t len; + auto utf8p = lua_tolstring(L, index, &len); + if (len < 1) + return S(); + const char* strb = utf8p; + const char* stre = utf8p + len; + stack_detail::count_code_units_utf<BaseCh> count_units; + convert<BaseCh>(strb, stre, count_units); + S r(count_units.needed_size, static_cast<Ch>(0)); + r.resize(count_units.needed_size); + Ch* target = &r[0]; + stack_detail::copy_code_units_utf<Ch, BaseCh> copy_units(target); + convert<BaseCh>(strb, stre, copy_units); + return r; + } + } // namespace stack_detail + + template <typename T, typename> + struct unqualified_getter { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + if constexpr (std::is_same_v<T, bool>) { + tracking.use(1); + return lua_toboolean(L, index) != 0; + } + else if constexpr (std::is_enum_v<T>) { + tracking.use(1); + return static_cast<T>(lua_tointegerx(L, index, nullptr)); + } + else if constexpr (std::is_integral_v<T> || std::is_same_v<T, lua_Integer>) { + tracking.use(1); +#if SOL_LUA_VERSION_I_ >= 503 + if (lua_isinteger(L, index) != 0) { + return static_cast<T>(lua_tointeger(L, index)); + } +#endif + return static_cast<T>(llround(lua_tonumber(L, index))); + } + else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) { + tracking.use(1); + return static_cast<T>(lua_tonumber(L, index)); + } + else if constexpr (is_lua_reference_v<T>) { + if constexpr (is_global_table_v<T>) { + tracking.use(1); + return T(L, global_tag); + } + else { + tracking.use(1); + return T(L, index); + } + } + else if constexpr (is_unique_usertype_v<T>) { + using actual = unique_usertype_actual_t<T>; + + tracking.use(1); + void* memory = lua_touserdata(L, index); + void* aligned_memory = detail::align_usertype_unique<actual>(memory); + actual* typed_memory = static_cast<actual*>(aligned_memory); + return *typed_memory; + } + else if constexpr (meta::is_optional_v<T>) { + using ValueType = typename T::value_type; + return unqualified_check_getter<ValueType>::template get_using<T>(L, index, &no_panic, tracking); + } + else if constexpr (std::is_same_v<T, luaL_Stream*>) { + luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index)); + return pstream; + } + else if constexpr (std::is_same_v<T, luaL_Stream>) { + luaL_Stream* pstream = static_cast<luaL_Stream*>(lua_touserdata(L, index)); + return *pstream; + } +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + else if constexpr (std::is_function_v<T> || (std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>)) { + return stack_detail::get_function_pointer<std::remove_pointer_t<T>>(L, index, tracking); + } +#endif + else { + return stack_detail::unchecked_unqualified_get<detail::as_value_tag<T>>(L, index, tracking); + } + } + }; + + template <typename X, typename> + struct qualified_getter { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + using Tu = meta::unqualified_t<X>; + static constexpr bool is_userdata_of_some_kind + = !std::is_reference_v< + X> && is_container_v<Tu> && std::is_default_constructible_v<Tu> && !is_lua_primitive_v<Tu> && !is_transparent_argument_v<Tu>; + if constexpr (is_userdata_of_some_kind) { + if (type_of(L, index) == type::userdata) { + return static_cast<Tu>(stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking)); + } + else { + return stack_detail::unchecked_unqualified_get<sol::nested<Tu>>(L, index, tracking); + } + } + else if constexpr (!std::is_reference_v<X> && is_unique_usertype_v<Tu> && !is_actual_type_rebindable_for_v<Tu>) { + using element = unique_usertype_element_t<Tu>; + using actual = unique_usertype_actual_t<Tu>; + tracking.use(1); + void* memory = lua_touserdata(L, index); + memory = detail::align_usertype_unique_destructor(memory); + detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory); + if (&detail::usertype_unique_alloc_destroy<element, Tu> == pdx) { + memory = detail::align_usertype_unique_tag<true, false>(memory); + memory = detail::align_usertype_unique<actual, true, false>(memory); + actual* mem = static_cast<actual*>(memory); + return static_cast<actual>(*mem); + } + actual r {}; + if constexpr (!derive<element>::value) { +#if SOL_IS_ON(SOL_DEBUG_BUILD) + // In debug mode we would rather abort you for this grave failure rather + // than let you deref a null pointer and fuck everything over + std::abort(); +#endif + return static_cast<actual>(std::move(r)); + } + else { + memory = detail::align_usertype_unique_tag<true, false>(memory); + detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory); + memory = detail::align_usertype_unique<actual, true, false>(memory); + string_view ti = usertype_traits<element>::qualified_name(); + int cast_operation; + if constexpr (is_actual_type_rebindable_for_v<Tu>) { + using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>; + string_view rebind_ti = usertype_traits<rebound_actual_type>::qualified_name(); + cast_operation = ic(memory, &r, ti, rebind_ti); + } + else { + string_view rebind_ti(""); + cast_operation = ic(memory, &r, ti, rebind_ti); + } + switch (cast_operation) { + case 1: { + // it's a perfect match, + // alias memory directly + actual* mem = static_cast<actual*>(memory); + return static_cast<actual>(*mem); + } + case 2: + // it's a base match, return the + // aliased creation + return static_cast<actual>(std::move(r)); + default: + // uh oh.. + break; + } +#if SOL_IS_ON(SOL_DEBUG_BUILD) + // In debug mode we would rather abort you for this grave failure rather + // than let you deref a null pointer and fuck everything over + std::abort(); +#endif + return static_cast<actual>(r); + } + } + else { + return stack_detail::unchecked_unqualified_get<Tu>(L, index, tracking); + } + } + }; + + template <typename T> + struct unqualified_getter<as_table_t<T>> { + using Tu = meta::unqualified_t<T>; + + template <typename V> + static void push_back_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) { + cont.push_back(stack::get<V>(L, -lua_size<V>::value)); + } + + template <typename V> + static void push_back_at_end(std::false_type, types<V> t, lua_State* L, T& cont, std::size_t idx) { + insert_at_end(meta::has_insert<Tu>(), t, L, cont, idx); + } + + template <typename V> + static void insert_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) { + using std::cend; + cont.insert(cend(cont), stack::get<V>(L, -lua_size<V>::value)); + } + + template <typename V> + static void insert_at_end(std::false_type, types<V>, lua_State* L, T& cont, std::size_t idx) { + cont[idx] = stack::get<V>(L, -lua_size<V>::value); + } + + static bool max_size_check(std::false_type, T&, std::size_t) { + return false; + } + + static bool max_size_check(std::true_type, T& cont, std::size_t idx) { + return idx >= cont.max_size(); + } + + static T get(lua_State* L, int relindex, record& tracking) { + return get(meta::is_associative<Tu>(), L, relindex, tracking); + } + + static T get(std::false_type, lua_State* L, int relindex, record& tracking) { + typedef typename Tu::value_type V; + return get(types<V>(), L, relindex, tracking); + } + + template <typename V> + static T get(types<V> t, lua_State* L, int relindex, record& tracking) { + tracking.use(1); + + // the W4 flag is really great, + // so great that it can tell my for loops (twice nested) + // below never actually terminate + // without hitting where the gotos have infested + + // so now I would get the error W4XXX unreachable + // me that the return cont at the end of this function + // which is fair until other compilers complain + // that there isn't a return and that based on + // SOME MAGICAL FORCE + // control flow falls off the end of a non-void function + // so it needs to be there for the compilers that are + // too flimsy to analyze the basic blocks... + // (I'm sure I should file a bug but those compilers are already + // in the wild; it doesn't matter if I fix them, + // someone else is still going to get some old-ass compiler + // and then bother me about the unclean build for the 30th + // time) + + // "Why not an IIFE?" + // Because additional lambdas / functions which serve as + // capture-all-and-then-invoke bloat binary sizes + // by an actually detectable amount + // (one user uses sol2 pretty heavily and 22 MB of binary size + // was saved by reducing reliance on lambdas in templates) + + // This would really be solved by having break N; + // be a real, proper thing... + // but instead, we have to use labels and gotos + // and earn the universal vitriol of the dogmatic + // programming community + + // all in all: W4 is great!~ + + int index = lua_absindex(L, relindex); + T cont; + std::size_t idx = 0; +#if SOL_LUA_VERSION_I_ >= 503 + // This method is HIGHLY performant over regular table iteration + // thanks to the Lua API changes in 5.3 + // Questionable in 5.4 + for (lua_Integer i = 0;; i += lua_size<V>::value) { + if (max_size_check(meta::has_max_size<Tu>(), cont, idx)) { + // see above comment + goto done; + } + bool isnil = false; + for (int vi = 0; vi < lua_size<V>::value; ++vi) { +#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600 +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushinteger(L, static_cast<lua_Integer>(i + vi)); + if (lua_keyin(L, index) == 0) { + // it's time to stop + isnil = true; + } + else { + // we have a key, have to get the value + lua_geti(L, index, i + vi); + } +#else + type vt = static_cast<type>(lua_geti(L, index, i + vi)); + isnil = vt == type::none || vt == type::lua_nil; +#endif + if (isnil) { + if (i == 0) { + break; + } +#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600 + lua_pop(L, vi); +#else + lua_pop(L, (vi + 1)); +#endif + // see above comment + goto done; + } + } + if (isnil) { +#if SOL_IS_ON(SOL_LUA_NIL_IN_TABLES) && SOL_LUA_VERSION_I_ >= 600 +#else + lua_pop(L, lua_size<V>::value); +#endif + continue; + } + + push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx); + ++idx; + lua_pop(L, lua_size<V>::value); + } +#else + // Zzzz slower but necessary thanks to the lower version API and missing functions qq + for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { + if (idx >= cont.max_size()) { + // see above comment + goto done; + } +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 2, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + bool isnil = false; + for (int vi = 0; vi < lua_size<V>::value; ++vi) { + lua_pushinteger(L, i); + lua_gettable(L, index); + type vt = type_of(L, -1); + isnil = vt == type::lua_nil; + if (isnil) { + if (i == 0) { + break; + } + lua_pop(L, (vi + 1)); + // see above comment + goto done; + } + } + if (isnil) + continue; + push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx); + ++idx; + } +#endif + done: + return cont; + } + + static T get(std::true_type, lua_State* L, int index, record& tracking) { + typedef typename Tu::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + return get(types<K, V>(), L, index, tracking); + } + + template <typename K, typename V> + static T get(types<K, V>, lua_State* L, int relindex, record& tracking) { + tracking.use(1); + +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 3, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + + T associative; + int index = lua_absindex(L, relindex); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + decltype(auto) key = stack::check_get<K>(L, -2); + if (!key) { + lua_pop(L, 1); + continue; + } + associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1)); + lua_pop(L, 1); + } + return associative; + } + }; + + template <typename T, typename Al> + struct unqualified_getter<as_table_t<std::forward_list<T, Al>>> { + typedef std::forward_list<T, Al> C; + + static C get(lua_State* L, int relindex, record& tracking) { + return get(meta::has_key_value_pair<C>(), L, relindex, tracking); + } + + static C get(std::true_type, lua_State* L, int index, record& tracking) { + typedef typename T::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + return get(types<K, V>(), L, index, tracking); + } + + static C get(std::false_type, lua_State* L, int relindex, record& tracking) { + typedef typename C::value_type V; + return get(types<V>(), L, relindex, tracking); + } + + template <typename V> + static C get(types<V>, lua_State* L, int relindex, record& tracking) { + tracking.use(1); +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 3, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + + int index = lua_absindex(L, relindex); + C cont; + auto at = cont.cbefore_begin(); + std::size_t idx = 0; +#if SOL_LUA_VERSION_I_ >= 503 + // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 + for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { + if (idx >= cont.max_size()) { + goto done; + } + bool isnil = false; + for (int vi = 0; vi < lua_size<V>::value; ++vi) { + type t = static_cast<type>(lua_geti(L, index, i + vi)); + isnil = t == type::lua_nil; + if (isnil) { + if (i == 0) { + break; + } + lua_pop(L, (vi + 1)); + goto done; + } + } + if (isnil) + continue; + at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value)); + ++idx; + } +#else + // Zzzz slower but necessary thanks to the lower version API and missing functions qq + for (lua_Integer i = 0;; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { + if (idx >= cont.max_size()) { + goto done; + } + bool isnil = false; + for (int vi = 0; vi < lua_size<V>::value; ++vi) { + lua_pushinteger(L, i); + lua_gettable(L, index); + type t = type_of(L, -1); + isnil = t == type::lua_nil; + if (isnil) { + if (i == 0) { + break; + } + lua_pop(L, (vi + 1)); + goto done; + } + } + if (isnil) + continue; + at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value)); + ++idx; + } +#endif + done: + return cont; + } + + template <typename K, typename V> + static C get(types<K, V>, lua_State* L, int relindex, record& tracking) { + tracking.use(1); + +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 3, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + + C associative; + auto at = associative.cbefore_begin(); + int index = lua_absindex(L, relindex); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + decltype(auto) key = stack::check_get<K>(L, -2); + if (!key) { + lua_pop(L, 1); + continue; + } + at = associative.emplace_after(at, std::forward<decltype(*key)>(*key), stack::get<V>(L, -1)); + lua_pop(L, 1); + } + return associative; + } + }; + + template <typename T> + struct unqualified_getter<nested<T>> { + static T get(lua_State* L, int index, record& tracking) { + using Tu = meta::unqualified_t<T>; + if constexpr (is_container_v<Tu>) { + if constexpr (meta::is_associative<Tu>::value) { + typedef typename T::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + unqualified_getter<as_table_t<T>> g{}; + return g.get(types<K, nested<V>>(), L, index, tracking); + } + else { + typedef typename T::value_type V; + unqualified_getter<as_table_t<T>> g{}; + return g.get(types<nested<V>>(), L, index, tracking); + } + } + else { + unqualified_getter<Tu> g{}; + return g.get(L, index, tracking); + } + } + }; + + template <typename T> + struct unqualified_getter<as_container_t<T>> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return stack::unqualified_get<T>(L, index, tracking); + } + }; + + template <typename T> + struct unqualified_getter<as_container_t<T>*> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return stack::unqualified_get<T*>(L, index, tracking); + } + }; + + template <> + struct unqualified_getter<userdata_value> { + static userdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return userdata_value(lua_touserdata(L, index)); + } + }; + + template <> + struct unqualified_getter<lightuserdata_value> { + static lightuserdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lightuserdata_value(lua_touserdata(L, index)); + } + }; + + template <typename T> + struct unqualified_getter<light<T>> { + static light<T> get(lua_State* L, int index, record& tracking) { + tracking.use(1); + void* memory = lua_touserdata(L, index); + return light<T>(static_cast<T*>(memory)); + } + }; + + template <typename T> + struct unqualified_getter<user<T>> { + static std::add_lvalue_reference_t<T> get(lua_State* L, int index, record& tracking) { + tracking.use(1); + void* memory = lua_touserdata(L, index); + memory = detail::align_user<T>(memory); + return *static_cast<std::remove_reference_t<T>*>(memory); + } + }; + + template <typename T> + struct unqualified_getter<user<T*>> { + static T* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + void* memory = lua_touserdata(L, index); + memory = detail::align_user<T*>(memory); + return static_cast<T*>(memory); + } + }; + + template <> + struct unqualified_getter<type> { + static type get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast<type>(lua_type(L, index)); + } + }; + + template <> + struct unqualified_getter<std::string> { + static std::string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + std::size_t len; + auto str = lua_tolstring(L, index, &len); + return std::string(str, len); + } + }; + + template <> + struct unqualified_getter<const char*> { + static const char* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz; + return lua_tolstring(L, index, &sz); + } + }; + + template <> + struct unqualified_getter<char> { + static char get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + return len > 0 ? str[0] : '\0'; + } + }; + + template <typename Traits> + struct unqualified_getter<basic_string_view<char, Traits>> { + static string_view get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz; + const char* str = lua_tolstring(L, index, &sz); + return basic_string_view<char, Traits>(str, sz); + } + }; + + template <typename Traits, typename Al> + struct unqualified_getter<std::basic_string<wchar_t, Traits, Al>> { + using S = std::basic_string<wchar_t, Traits, Al>; + static S get(lua_State* L, int index, record& tracking) { + using Ch = meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t>; + return stack_detail::get_into<Ch, S>(L, index, tracking); + } + }; + + template <typename Traits, typename Al> + struct unqualified_getter<std::basic_string<char16_t, Traits, Al>> { + static std::basic_string<char16_t, Traits, Al> get(lua_State* L, int index, record& tracking) { + return stack_detail::get_into<char16_t, std::basic_string<char16_t, Traits, Al>>(L, index, tracking); + } + }; + + template <typename Traits, typename Al> + struct unqualified_getter<std::basic_string<char32_t, Traits, Al>> { + static std::basic_string<char32_t, Traits, Al> get(lua_State* L, int index, record& tracking) { + return stack_detail::get_into<char32_t, std::basic_string<char32_t, Traits, Al>>(L, index, tracking); + } + }; + + template <> + struct unqualified_getter<char16_t> { + static char16_t get(lua_State* L, int index, record& tracking) { + string_view utf8 = stack::get<string_view>(L, index, tracking); + const char* strb = utf8.data(); + const char* stre = utf8.data() + utf8.size(); + char32_t cp = 0; + auto dr = unicode::utf8_to_code_point(strb, stre); + if (dr.error != unicode::error_code::ok) { + cp = unicode::unicode_detail::replacement; + } + else { + cp = dr.codepoint; + } + auto er = unicode::code_point_to_utf16(cp); + return er.code_units[0]; + } + }; + + template <> + struct unqualified_getter<char32_t> { + static char32_t get(lua_State* L, int index, record& tracking) { + string_view utf8 = stack::get<string_view>(L, index, tracking); + const char* strb = utf8.data(); + const char* stre = utf8.data() + utf8.size(); + char32_t cp = 0; + auto dr = unicode::utf8_to_code_point(strb, stre); + if (dr.error != unicode::error_code::ok) { + cp = unicode::unicode_detail::replacement; + } + else { + cp = dr.codepoint; + } + auto er = unicode::code_point_to_utf32(cp); + return er.code_units[0]; + } + }; + + template <> + struct unqualified_getter<wchar_t> { + static wchar_t get(lua_State* L, int index, record& tracking) { + typedef meta::conditional_t<sizeof(wchar_t) == 2, char16_t, char32_t> Ch; + unqualified_getter<Ch> g; + (void)g; + auto c = g.get(L, index, tracking); + return static_cast<wchar_t>(c); + } + }; + + template <> + struct unqualified_getter<meta_function> { + static meta_function get(lua_State* L, int index, record& tracking) { + tracking.use(1); + const char* name = unqualified_getter<const char*> {}.get(L, index, tracking); + const auto& mfnames = meta_function_names(); + for (std::size_t i = 0; i < mfnames.size(); ++i) + if (mfnames[i] == name) + return static_cast<meta_function>(i); + return meta_function::construct; + } + }; + + template <> + struct unqualified_getter<lua_nil_t> { + static lua_nil_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return lua_nil; + } + }; + + template <> + struct unqualified_getter<std::nullptr_t> { + static std::nullptr_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullptr; + } + }; + + template <> + struct unqualified_getter<nullopt_t> { + static nullopt_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullopt; + } + }; + + template <> + struct unqualified_getter<this_state> { + static this_state get(lua_State* L, int, record& tracking) { + tracking.use(0); + return this_state(L); + } + }; + + template <> + struct unqualified_getter<this_main_state> { + static this_main_state get(lua_State* L, int, record& tracking) { + tracking.use(0); + return this_main_state(main_thread(L, L)); + } + }; + + template <> + struct unqualified_getter<lua_CFunction> { + static lua_CFunction get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tocfunction(L, index); + } + }; + + template <> + struct unqualified_getter<c_closure> { + static c_closure get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return c_closure(lua_tocfunction(L, index), -1); + } + }; + + template <> + struct unqualified_getter<error> { + static error get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz = 0; + const char* err = lua_tolstring(L, index, &sz); + if (err == nullptr) { + return error(detail::direct_error, ""); + } + return error(detail::direct_error, std::string(err, sz)); + } + }; + + template <> + struct unqualified_getter<void*> { + static void* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_touserdata(L, index); + } + }; + + template <> + struct unqualified_getter<const void*> { + static const void* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_touserdata(L, index); + } + }; + + template <typename T> + struct unqualified_getter<detail::as_value_tag<T>> { + static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { + void* memory = lua_touserdata(L, index); +#if SOL_IS_ON(SOL_USE_INTEROP) + auto ugr = stack_detail::interop_get<T>(L, index, memory, tracking); + if (ugr.first) { + return ugr.second; + } +#endif // interop extensibility + tracking.use(1); + void* rawdata = detail::align_usertype_pointer(memory); + void** pudata = static_cast<void**>(rawdata); + void* udata = *pudata; + return get_no_lua_nil_from(L, udata, index, tracking); + } + + static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) { + bool has_derived = derive<T>::value || weak_derive<T>::value; + if (has_derived) { + if (lua_getmetatable(L, index) == 1) { + lua_getfield(L, -1, &detail::base_class_cast_key()[0]); + if (type_of(L, -1) != type::lua_nil) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_cast_function ic = reinterpret_cast<detail::inheritance_cast_function>(basecastdata); + // use the casting function to properly adjust the pointer for the desired T + udata = ic(udata, usertype_traits<T>::qualified_name()); + } + lua_pop(L, 2); + } + } + if constexpr (std::is_function_v<T>) { + T* func = reinterpret_cast<T*>(udata); + return func; + } + else { + T* obj = static_cast<T*>(udata); + return obj; + } + } + + static T& get(lua_State* L, int index, record& tracking) { + return *get_no_lua_nil(L, index, tracking); + } + }; + + template <typename T> + struct unqualified_getter<detail::as_pointer_tag<T>> { + static T* get(lua_State* L, int index, record& tracking) { + type t = type_of(L, index); + if (t == type::lua_nil) { + tracking.use(1); + return nullptr; + } + unqualified_getter<detail::as_value_tag<T>> g{}; + return g.get_no_lua_nil(L, index, tracking); + } + }; + + template <typename T> + struct unqualified_getter<non_null<T*>> { + static T* get(lua_State* L, int index, record& tracking) { + unqualified_getter<detail::as_value_tag<T>> g{}; + return g.get_no_lua_nil(L, index, tracking); + } + }; + + template <typename T> + struct unqualified_getter<T&> { + static T& get(lua_State* L, int index, record& tracking) { + unqualified_getter<detail::as_value_tag<T>> g{}; + return g.get(L, index, tracking); + } + }; + + template <typename T> + struct unqualified_getter<std::reference_wrapper<T>> { + static T& get(lua_State* L, int index, record& tracking) { + unqualified_getter<T&> g{}; + return g.get(L, index, tracking); + } + }; + + template <typename T> + struct unqualified_getter<T*> { + static T* get(lua_State* L, int index, record& tracking) { +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + if constexpr (std::is_function_v<T>) { + return stack_detail::get_function_pointer<T>(L, index, tracking); + } + else { + unqualified_getter<detail::as_pointer_tag<T>> g{}; + return g.get(L, index, tracking); + } +#else + unqualified_getter<detail::as_pointer_tag<T>> g{}; + return g.get(L, index, tracking); +#endif + } + }; + + template <typename... Tn> + struct unqualified_getter<std::tuple<Tn...>> { + typedef std::tuple<decltype(stack::get<Tn>(nullptr, 0))...> R; + + template <typename... Args> + static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) { + // Fuck you too, VC++ + return R { std::forward<Args>(args)... }; + } + + template <std::size_t I, std::size_t... Ix, typename... Args> + static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, Args&&... args) { + // Fuck you too, VC++ + typedef std::tuple_element_t<I, std::tuple<Tn...>> T; + return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<Args>(args)..., stack::get<T>(L, index + tracking.used, tracking)); + } + + static R get(lua_State* L, int index, record& tracking) { + return apply(std::make_index_sequence<sizeof...(Tn)>(), L, index, tracking); + } + }; + + template <typename A, typename B> + struct unqualified_getter<std::pair<A, B>> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))> { stack::get<A>(L, index, tracking), + stack::get<B>(L, index + tracking.used, tracking) }; + } + }; + +#if SOL_IS_ON(SOL_STD_VARIANT) + + template <typename... Tn> + struct unqualified_getter<std::variant<Tn...>> { + using V = std::variant<Tn...>; + + static V get_one(std::integral_constant<std::size_t, std::variant_size_v<V>>, lua_State* L, int index, record& tracking) { + (void)L; + (void)index; + (void)tracking; + if constexpr (std::variant_size_v<V> == 0) { + return V(); + } + else { + // using T = std::variant_alternative_t<0, V>; + std::abort(); + // return V(std::in_place_index<0>, stack::get<T>(L, index, tracking)); + } + } + + template <std::size_t I> + static V get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, record& tracking) { + typedef std::variant_alternative_t<I, V> T; + record temp_tracking = tracking; + if (stack::check<T>(L, index, &no_panic, temp_tracking)) { + tracking = temp_tracking; + return V(std::in_place_index<I>, stack::get<T>(L, index)); + } + return get_one(std::integral_constant<std::size_t, I + 1>(), L, index, tracking); + } + + static V get(lua_State* L, int index, record& tracking) { + return get_one(std::integral_constant<std::size_t, 0>(), L, index, tracking); + } + }; +#endif // variant + +}} // namespace sol::stack + +// end of sol/stack_get_unqualified.hpp + +// beginning of sol/stack_get_qualified.hpp + +namespace sol { namespace stack { + + // There are no more enable_ifs that can be used here, + // so this is just for posterity, I guess? + // maybe I'll fill this file in later. + +}} // namespace sol::stack + +// end of sol/stack_get_qualified.hpp + +// end of sol/stack_get.hpp + +// beginning of sol/stack_check_get.hpp + +// beginning of sol/stack_check_get_unqualified.hpp + +#include <cstdlib> +#include <cmath> +#include <optional> +#if SOL_IS_ON(SOL_STD_VARIANT) +#include <variant> +#endif // variant shenanigans (thanks, Mac OSX) + +namespace sol { namespace stack { + template <typename T, typename> + struct unqualified_check_getter { + typedef decltype(stack_detail::unchecked_unqualified_get<T>(nullptr, -1, std::declval<record&>())) R; + + template <typename Optional, typename Handler> + static Optional get_using(lua_State* L, int index, Handler&& handler, record& tracking) { + if constexpr (!meta::meta_detail::is_adl_sol_lua_check_v<T> && !meta::meta_detail::is_adl_sol_lua_get_v<T>) { + if constexpr (is_lua_reference_v<T>) { + if constexpr (is_global_table_v<T>) { + (void)L; + (void)index; + (void)handler; + tracking.use(1); + return true; + } + else { + // actually check if it's none here, otherwise + // we'll have a none object inside an optional! + bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, &no_panic); + if (!success) { + // expected type, actual type + tracking.use(static_cast<int>(success)); + handler(L, index, type::poly, type_of(L, index), ""); + return detail::associated_nullopt_v<Optional>; + } + return stack_detail::unchecked_get<T>(L, index, tracking); + } + } + else if constexpr ((std::is_integral_v<T> || std::is_same_v<T, lua_Integer>)&&!std::is_same_v<T, bool>) { +#if SOL_LUA_VERSION_I_ >= 503 + if (lua_isinteger(L, index) != 0) { + tracking.use(1); + return static_cast<T>(lua_tointeger(L, index)); + } +#endif + int isnum = 0; + const lua_Number value = lua_tonumberx(L, index, &isnum); + if (isnum != 0) { +#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) + const auto integer_value = llround(value); + if (static_cast<lua_Number>(integer_value) == value) { + tracking.use(1); + return static_cast<T>(integer_value); + } +#else + tracking.use(1); + return static_cast<T>(value); +#endif + } + const type t = type_of(L, index); + tracking.use(static_cast<int>(t != type::none)); + handler(L, index, type::number, t, "not an integer"); + return detail::associated_nullopt_v<Optional>; + } + else if constexpr (std::is_floating_point_v<T> || std::is_same_v<T, lua_Number>) { + int isnum = 0; + lua_Number value = lua_tonumberx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast<int>(t != type::none)); + handler(L, index, type::number, t, "not a valid floating point number"); + return detail::associated_nullopt_v<Optional>; + } + tracking.use(1); + return static_cast<T>(value); + } + else if constexpr (std::is_enum_v<T> && !meta::any_same_v<T, meta_function, type>) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast<int>(t != type::none)); + handler(L, index, type::number, t, "not a valid enumeration value"); + return detail::associated_nullopt_v<Optional>; + } + tracking.use(1); + return static_cast<T>(value); + } + else { + if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) { + tracking.use(static_cast<int>(!lua_isnone(L, index))); + return detail::associated_nullopt_v<Optional>; + } + return stack_detail::unchecked_unqualified_get<T>(L, index, tracking); + } + } + else { + if (!unqualified_check<T>(L, index, std::forward<Handler>(handler))) { + tracking.use(static_cast<int>(!lua_isnone(L, index))); + return detail::associated_nullopt_v<Optional>; + } + return stack_detail::unchecked_unqualified_get<T>(L, index, tracking); + } + } + + template <typename Handler> + static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) { + return get_using<optional<R>>(L, index, std::forward<Handler>(handler), tracking); + } + }; + +#if SOL_IS_ON(SOL_STD_VARIANT) + template <typename... Tn, typename C> + struct unqualified_check_getter<std::variant<Tn...>, C> { + typedef std::variant<Tn...> V; + typedef std::variant_size<V> V_size; + typedef std::integral_constant<bool, V_size::value == 0> V_is_empty; + + template <typename Handler> + static optional<V> get_empty(std::true_type, lua_State*, int, Handler&&, record&) { + return nullopt; + } + + template <typename Handler> + static optional<V> get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record&) { + // This should never be reached... + // please check your code and understand what you did to bring yourself here + // maybe file a bug report, or 5 + handler( + L, index, type::poly, type_of(L, index), "this variant code should never be reached: if it has, you have done something so terribly wrong"); + return nullopt; + } + + template <typename Handler> + static optional<V> get_one(std::integral_constant<std::size_t, 0>, lua_State* L, int index, Handler&& handler, record& tracking) { + return get_empty(V_is_empty(), L, index, std::forward<Handler>(handler), tracking); + } + + template <std::size_t I, typename Handler> + static optional<V> get_one(std::integral_constant<std::size_t, I>, lua_State* L, int index, Handler&& handler, record& tracking) { + typedef std::variant_alternative_t<I - 1, V> T; + if (stack::check<T>(L, index, &no_panic, tracking)) { + return V(std::in_place_index<I - 1>, stack::get<T>(L, index)); + } + return get_one(std::integral_constant<std::size_t, I - 1>(), L, index, std::forward<Handler>(handler), tracking); + } + + template <typename Handler> + static optional<V> get(lua_State* L, int index, Handler&& handler, record& tracking) { + return get_one(std::integral_constant<std::size_t, V_size::value>(), L, index, std::forward<Handler>(handler), tracking); + } + }; +#endif // standard variant +}} // namespace sol::stack + +// end of sol/stack_check_get_unqualified.hpp + +// beginning of sol/stack_check_get_qualified.hpp + +namespace sol { namespace stack { + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + + namespace stack_detail { + template <typename OptionalType, typename T, typename Handler> + OptionalType get_optional(lua_State* L, int index, Handler&& handler, record& tracking) { + using Tu = meta::unqualified_t<T>; + + if constexpr (is_lua_reference_v<T>) { + if constexpr (is_global_table_v<Tu>) { + (void)L; + (void)index; + (void)handler; + tracking.use(1); + return true; + } + else { + // actually check if it's none here, otherwise + // we'll have a none object inside an optional! + bool success = lua_isnoneornil(L, index) == 0 && stack::check<T>(L, index, &no_panic); + if (!success) { + // expected type, actual type + tracking.use(static_cast<int>(success)); + handler(L, index, type::poly, type_of(L, index), ""); + return {}; + } + return OptionalType(stack_detail::unchecked_get<T>(L, index, tracking)); + } + } + else if constexpr (!std::is_reference_v<T> && is_unique_usertype_v<Tu> && !is_actual_type_rebindable_for_v<Tu>) { + // we can take shortcuts here to save on separate checking, and just return nullopt! + using element = unique_usertype_element_t<Tu>; + using actual = unique_usertype_actual_t<Tu>; + tracking.use(1); + void* memory = lua_touserdata(L, index); + memory = detail::align_usertype_unique_destructor(memory); + detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory); + if (&detail::usertype_unique_alloc_destroy<element, Tu> == pdx) { + memory = detail::align_usertype_unique_tag<true, false>(memory); + memory = detail::align_usertype_unique<actual, true, false>(memory); + actual* mem = static_cast<actual*>(memory); + return static_cast<actual>(*mem); + } + if constexpr (!derive<element>::value) { + return OptionalType(); + } + else { + memory = detail::align_usertype_unique_tag<true, false>(memory); + detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory); + memory = detail::align_usertype_unique<actual, true, false>(memory); + string_view ti = usertype_traits<element>::qualified_name(); + int cast_operation; + actual r {}; + if constexpr (is_actual_type_rebindable_for_v<Tu>) { + using rebound_actual_type = unique_usertype_rebind_actual_t<Tu, void>; + string_view rebind_ti = usertype_traits<rebound_actual_type>::qualified_name(); + cast_operation = ic(memory, &r, ti, rebind_ti); + } + else { + string_view rebind_ti(""); + cast_operation = ic(memory, &r, ti, rebind_ti); + } + switch (cast_operation) { + case 1: { + // it's a perfect match, + // alias memory directly + actual* mem = static_cast<actual*>(memory); + return OptionalType(*mem); + } + case 2: + // it's a base match, return the + // aliased creation + return OptionalType(std::move(r)); + default: + break; + } + return OptionalType(); + } + } + else { + if (!check<T>(L, index, std::forward<Handler>(handler))) { + tracking.use(static_cast<int>(!lua_isnone(L, index))); + return OptionalType(); + } + return OptionalType(stack_detail::unchecked_get<T>(L, index, tracking)); + } + } + } // namespace stack_detail + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic pop +#endif + + template <typename T, typename> + struct qualified_check_getter { + typedef decltype(stack_detail::unchecked_get<T>(nullptr, -1, std::declval<record&>())) R; + + template <typename Handler> + optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack_detail::get_optional<optional<R>, T>(L, index, std::forward<Handler>(handler), tracking); + } + }; + + template <typename Optional> + struct qualified_getter<Optional, std::enable_if_t<meta::is_optional_v<Optional>>> { + static Optional get(lua_State* L, int index, record& tracking) { + using T = typename meta::unqualified_t<Optional>::value_type; + return stack_detail::get_optional<Optional, T>(L, index, &no_panic, tracking); + } + }; + +}} // namespace sol::stack + +// end of sol/stack_check_get_qualified.hpp + +// end of sol/stack_check_get.hpp + +// beginning of sol/stack_push.hpp + +#include <memory> +#include <type_traits> +#include <cassert> +#include <limits> +#include <cmath> +#include <string_view> +#if SOL_IS_ON(SOL_STD_VARIANT) +#include <variant> +#endif // Can use variant + +// beginning of sol/debug.hpp + +#include <iostream> + +namespace sol { namespace detail { namespace debug { + inline std::string dump_types(lua_State* L) { + std::string visual; + std::size_t size = lua_gettop(L) + 1; + for (std::size_t i = 1; i < size; ++i) { + if (i != 1) { + visual += " | "; + } + visual += type_name(L, stack::get<type>(L, static_cast<int>(i))); + } + return visual; + } + + inline void print_stack(lua_State* L) { + std::cout << dump_types(L) << std::endl; + } + + inline void print_section(const std::string& message, lua_State* L) { + std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl; + } +}}} // namespace sol::detail::debug + +// end of sol/debug.hpp + +namespace sol { namespace stack { + namespace stack_detail { + template <typename T> + inline bool integer_value_fits(const T& value) { + // We check if we can rely on casts or a lack of padding bits to satisfy + // the requirements here + // If it lacks padding bits, we can jump back and forth between lua_Integer and whatever type without + // loss of information + constexpr bool is_same_signedness + = (std::is_signed_v<T> && std::is_signed_v<lua_Integer>) || (std::is_unsigned_v<T> && std::is_unsigned_v<lua_Integer>); + constexpr bool probaby_fits_within_lua_Integer = sizeof(T) == sizeof(lua_Integer) +#if SOL_IS_ON(SOL_ALL_INTEGER_VALUES_FIT) + && ((std::has_unique_object_representations_v<T> && std::has_unique_object_representations_v<lua_Integer>) ? true : is_same_signedness) +#else + && is_same_signedness +#endif + ; + if constexpr (sizeof(T) < sizeof(lua_Integer) || probaby_fits_within_lua_Integer) { + (void)value; + return true; + } + else { + auto u_min = static_cast<std::intmax_t>((std::numeric_limits<lua_Integer>::min)()); + auto u_max = static_cast<std::uintmax_t>((std::numeric_limits<lua_Integer>::max)()); + auto t_min = static_cast<std::intmax_t>((std::numeric_limits<T>::min)()); + auto t_max = static_cast<std::uintmax_t>((std::numeric_limits<T>::max)()); + return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max)); + } + } + + template <typename T> + int msvc_is_ass_with_if_constexpr_push_enum(std::true_type, lua_State* L, const T& value) { + if constexpr (meta::any_same_v<std::underlying_type_t<T>, + char +#if SOL_IS_ON(SOL_CHAR8_T) + , + char8_t +#endif + , + char16_t, + char32_t>) { + if constexpr (std::is_signed_v<T>) { + return stack::push(L, static_cast<std::int_least32_t>(value)); + } + else { + return stack::push(L, static_cast<std::uint_least32_t>(value)); + } + } + else { + return stack::push(L, static_cast<std::underlying_type_t<T>>(value)); + } + } + + template <typename T> + int msvc_is_ass_with_if_constexpr_push_enum(std::false_type, lua_State*, const T&) { + return 0; + } + } // namespace stack_detail + + inline int push_environment_of(lua_State* L, int target_index = -1) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_environment); +#endif // make sure stack doesn't overflow +#if SOL_LUA_VERSION_I_ < 502 + // Use lua_getfenv + lua_getfenv(L, target_index); +#else + + if (lua_iscfunction(L, target_index) != 0) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, 1); + if (maybe_upvalue_name != nullptr) { + // it worked, take this one + return 1; + } + } + // Nominally, we search for the `"_ENV"` value. + // If we don't find it.... uh, well. We've got a problem? + for (int upvalue_index = 1;; ++upvalue_index) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, upvalue_index); + if (maybe_upvalue_name == nullptr) { + push(L, lua_nil); + break; + } + + string_view upvalue_name(maybe_upvalue_name); + if (upvalue_name == "_ENV") { + // Keep this one! + break; + } + // Discard what we received, loop back around + lua_pop(L, 1); + } +#endif + return 1; + } + + template <typename T> + int push_environment_of(const T& target) { + lua_State* target_L = target.lua_state(); + int target_index = absolute_index(target_L, -target.push()); + int env_count = push_environment_of(target_L, target_index); + sol_c_assert(env_count == 1); + lua_rotate(target_L, target_index, 1); + lua_pop(target_L, 1); + return env_count; + } + + template <typename T> + struct unqualified_pusher<detail::as_value_tag<T>> { + template <typename F, typename... Args> + static int push_fx(lua_State* L, F&& f, Args&&... args) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata); +#endif // make sure stack doesn't overflow + // Basically, we store all user-data like this: + // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new + // data in the first sizeof(T*) bytes, and then however many bytes it takes to + // do the actual object. Things that are std::ref or plain T* are stored as + // just the sizeof(T*), and nothing else. + T* obj = detail::usertype_allocate<T>(L); + f(); + std::allocator<T> alloc {}; + std::allocator_traits<std::allocator<T>>::construct(alloc, obj, std::forward<Args>(args)...); + return 1; + } + + template <typename K, typename... Args> + static int push_keyed(lua_State* L, K&& k, Args&&... args) { + stack_detail::undefined_metatable fx(L, &k[0], &stack::stack_detail::set_undefined_methods_on<T>); + return push_fx(L, fx, std::forward<Args>(args)...); + } + + template <typename Arg, typename... Args> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + if constexpr (std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>) { + (void)arg; + return push_fx(L, std::forward<Args>(args)...); + } + else { + return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...); + } + } + + static int push(lua_State* L) { + return push_keyed(L, usertype_traits<T>::metatable()); + } + }; + + template <typename T> + struct unqualified_pusher<detail::as_pointer_tag<T>> { + typedef meta::unqualified_t<T> U; + + template <typename F> + static int push_fx(lua_State* L, F&& f, T* obj) { + if (obj == nullptr) + return stack::push(L, lua_nil); +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata); +#endif // make sure stack doesn't overflow + T** pref = detail::usertype_allocate_pointer<T>(L); + f(); + *pref = obj; + return 1; + } + + template <typename K> + static int push_keyed(lua_State* L, K&& k, T* obj) { + stack_detail::undefined_metatable fx(L, &k[0], &stack::stack_detail::set_undefined_methods_on<U*>); + return push_fx(L, fx, obj); + } + + template <typename Arg, typename... Args> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + if constexpr (std::is_same_v<meta::unqualified_t<Arg>, detail::with_function_tag>) { + (void)arg; + return push_fx(L, std::forward<Args>(args)...); + } + else { + return push_keyed(L, usertype_traits<U*>::metatable(), std::forward<Arg>(arg), std::forward<Args>(args)...); + } + } + }; + + template <> + struct unqualified_pusher<detail::as_reference_tag> { + template <typename T> + static int push(lua_State* L, T&& obj) { + return stack::push(L, detail::ptr(obj)); + } + }; + + namespace stack_detail { + template <typename T> + struct uu_pusher { + using element = unique_usertype_element_t<T>; + using actual = unique_usertype_actual_t<T>; + + template <typename Arg, typename... Args> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + if constexpr (std::is_base_of_v<actual, meta::unqualified_t<Arg>>) { + if (detail::unique_is_null(L, arg)) { + return stack::push(L, lua_nil); + } + return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + else { + return push_deep(L, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + } + + template <typename... Args> + static int push_deep(lua_State* L, Args&&... args) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata); +#endif // make sure stack doesn't overflow + element** pointer_to_memory = nullptr; + detail::unique_destructor* fx = nullptr; + detail::unique_tag* id = nullptr; + actual* typed_memory = detail::usertype_unique_allocate<element, actual>(L, pointer_to_memory, fx, id); + if (luaL_newmetatable(L, &usertype_traits<d::u<std::remove_cv_t<element>>>::metatable()[0]) == 1) { + detail::lua_reg_table registration_table {}; + int index = 0; + detail::indexed_insert insert_callable(registration_table, index); + detail::insert_default_registrations<element>(insert_callable, detail::property_always_true); + registration_table[index] = { to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() }; + luaL_setfuncs(L, registration_table, 0); + } + lua_setmetatable(L, -2); + *fx = detail::usertype_unique_alloc_destroy<element, actual>; + *id = &detail::inheritance<element>::template type_unique_cast<actual>; + detail::default_construct::construct(typed_memory, std::forward<Args>(args)...); + *pointer_to_memory = detail::unique_get<T>(L, *typed_memory); + return 1; + } + }; + } // namespace stack_detail + + template <typename T> + struct unqualified_pusher<detail::as_unique_tag<T>> { + template <typename... Args> + static int push(lua_State* L, Args&&... args) { + stack_detail::uu_pusher<T> p; + (void)p; + return p.push(L, std::forward<Args>(args)...); + } + }; + + template <typename T, typename> + struct unqualified_pusher { + template <typename... Args> + static int push(lua_State* L, Args&&... args) { + using Tu = meta::unqualified_t<T>; + if constexpr (is_lua_reference_v<Tu>) { + using int_arr = int[]; + int_arr p { (std::forward<Args>(args).push(L))... }; + return p[0]; + } + else if constexpr (std::is_same_v<Tu, bool>) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushboolean(L, std::forward<Args>(args)...); + return 1; + } + else if constexpr (std::is_integral_v<Tu> || std::is_same_v<Tu, lua_Integer>) { + const Tu& value(std::forward<Args>(args)...); +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_integral); +#endif // make sure stack doesn't overflow +#if SOL_LUA_VERSION_I_ >= 503 + if (stack_detail::integer_value_fits<Tu>(value)) { + lua_pushinteger(L, static_cast<lua_Integer>(value)); + return 1; + } +#endif // Lua 5.3 and above +#if SOL_IS_ON(SOL_NUMBER_PRECISION_CHECKS) + if (static_cast<T>(llround(static_cast<lua_Number>(value))) != value) { +#if SOL_IS_OFF(SOL_EXCEPTIONS) + // Is this really worth it? + sol_m_assert(false, "integer value will be misrepresented in lua"); + lua_pushinteger(L, static_cast<lua_Integer>(value)); + return 1; +#else + throw error(detail::direct_error, "integer value will be misrepresented in lua"); +#endif // No Exceptions + } +#endif // Safe Numerics and Number Precision Check + lua_pushnumber(L, static_cast<lua_Number>(value)); + return 1; + } + else if constexpr (std::is_floating_point_v<Tu> || std::is_same_v<Tu, lua_Number>) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_floating); +#endif // make sure stack doesn't overflow + lua_pushnumber(L, std::forward<Args>(args)...); + return 1; + } + else if constexpr (std::is_same_v<Tu, luaL_Stream*>) { + luaL_Stream* source { std::forward<Args>(args)... }; + luaL_Stream* stream = static_cast<luaL_Stream*>(detail::alloc_newuserdata(L, sizeof(luaL_Stream))); + stream->f = source->f; +#if SOL_IS_ON(SOL_LUAL_STREAM_USE_CLOSE_FUNCTION) + stream->closef = source->closef; +#endif // LuaJIT and Lua 5.1 and below do not have + return 1; + } + else if constexpr (std::is_same_v<Tu, luaL_Stream>) { + luaL_Stream& source(std::forward<Args>(args)...); + luaL_Stream* stream = static_cast<luaL_Stream*>(detail::alloc_newuserdata(L, sizeof(luaL_Stream))); + stream->f = source.f; +#if SOL_IS_ON(SOL_LUAL_STREAM_USE_CLOSE_FUNCTION) + stream->closef = source.closef; +#endif // LuaJIT and Lua 5.1 and below do not have + return 1; + } + else if constexpr (std::is_enum_v<Tu>) { + return stack_detail::msvc_is_ass_with_if_constexpr_push_enum(std::true_type(), L, std::forward<Args>(args)...); + } + else if constexpr (std::is_pointer_v<Tu>) { + return stack::push<detail::as_pointer_tag<std::remove_pointer_t<T>>>(L, std::forward<Args>(args)...); + } + else if constexpr (is_unique_usertype_v<Tu>) { + return stack::push<detail::as_unique_tag<T>>(L, std::forward<Args>(args)...); + } + else { + return stack::push<detail::as_value_tag<T>>(L, std::forward<Args>(args)...); + } + } + }; + + template <typename T> + struct unqualified_pusher<std::reference_wrapper<T>> { + static int push(lua_State* L, const std::reference_wrapper<T>& t) { + return stack::push(L, std::addressof(detail::deref(t.get()))); + } + }; + + template <typename T> + struct unqualified_pusher<detail::as_table_tag<T>> { + using has_kvp = meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>; + + static int push(lua_State* L, const T& tablecont) { + return push(has_kvp(), std::false_type(), L, tablecont); + } + + static int push(lua_State* L, const T& tablecont, nested_tag_t) { + return push(has_kvp(), std::true_type(), L, tablecont); + } + + static int push(std::true_type, lua_State* L, const T& tablecont) { + return push(has_kvp(), std::true_type(), L, tablecont); + } + + static int push(std::false_type, lua_State* L, const T& tablecont) { + return push(has_kvp(), std::false_type(), L, tablecont); + } + + template <bool is_nested> + static int push(std::true_type, std::integral_constant<bool, is_nested>, lua_State* L, const T& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont)); + lua_createtable(L, static_cast<int>(cont.size()), 0); + int tableindex = lua_gettop(L); + for (const auto& pair : cont) { + if (is_nested) { + set_field(L, pair.first, as_nested_ref(pair.second), tableindex); + } + else { + set_field(L, pair.first, pair.second, tableindex); + } + } + return 1; + } + + template <bool is_nested> + static int push(std::false_type, std::integral_constant<bool, is_nested>, lua_State* L, const T& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont)); + lua_createtable(L, stack_detail::get_size_hint(cont), 0); + int tableindex = lua_gettop(L); + std::size_t index = 1; + for (const auto& i : cont) { +#if SOL_LUA_VERSION_I_ >= 503 + int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i); + for (int pi = 0; pi < p; ++pi) { + lua_seti(L, tableindex, static_cast<lua_Integer>(index++)); + } +#else +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushinteger(L, static_cast<lua_Integer>(index)); + int p = is_nested ? stack::push(L, as_nested_ref(i)) : stack::push(L, i); + if (p == 1) { + ++index; + lua_settable(L, tableindex); + } + else { + int firstindex = tableindex + 1 + 1; + for (int pi = 0; pi < p; ++pi) { + stack::push(L, index); +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushvalue(L, firstindex); + lua_settable(L, tableindex); + ++index; + ++firstindex; + } + lua_pop(L, 1 + p); + } +#endif // Lua Version 5.3 and others + } + // TODO: figure out a better way to do this...? + // set_field(L, -1, cont.size()); + return 1; + } + }; + + template <typename T> + struct unqualified_pusher<as_table_t<T>> { + static int push(lua_State* L, const as_table_t<T>& value_) { + using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>; + if constexpr (is_container_v<inner_t>) { + return stack::push<detail::as_table_tag<T>>(L, value_.value()); + } + else { + return stack::push(L, value_.value()); + } + } + + static int push(lua_State* L, const T& value_) { + using inner_t = std::remove_pointer_t<meta::unwrap_unqualified_t<T>>; + if constexpr (is_container_v<inner_t>) { + return stack::push<detail::as_table_tag<T>>(L, value_); + } + else { + return stack::push(L, value_); + } + } + }; + + template <typename T> + struct unqualified_pusher<nested<T>> { + static int push(lua_State* L, const T& nested_value) noexcept { + using Tu = meta::unwrap_unqualified_t<T>; + using inner_t = std::remove_pointer_t<Tu>; + if constexpr (is_container_v<inner_t>) { + return stack::push<detail::as_table_tag<T>>(L, nested_value, nested_tag); + } + else { + return stack::push<Tu>(L, nested_value); + } + } + + static int push(lua_State* L, const nested<T>& nested_wrapper_) noexcept { + using Tu = meta::unwrap_unqualified_t<T>; + using inner_t = std::remove_pointer_t<Tu>; + if constexpr (is_container_v<inner_t>) { + return stack::push<detail::as_table_tag<T>>(L, nested_wrapper_.value(), nested_tag); + } + else { + return stack::push<Tu>(L, nested_wrapper_.value()); + } + } + }; + + template <typename T> + struct unqualified_pusher<std::initializer_list<T>> { + static int push(lua_State* L, const std::initializer_list<T>& il) noexcept { + unqualified_pusher<detail::as_table_tag<std::initializer_list<T>>> p {}; + return p.push(L, il); + } + }; + + template <> + struct unqualified_pusher<lua_nil_t> { + static int push(lua_State* L, lua_nil_t) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushnil(L); + return 1; + } + }; + + template <> + struct unqualified_pusher<stack_count> { + static int push(lua_State*, stack_count st) noexcept { + return st.count; + } + }; + + template <> + struct unqualified_pusher<metatable_key_t> { + static int push(lua_State* L, metatable_key_t) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, to_string(meta_function::metatable).c_str(), 4); + return 1; + } + }; + + template <> + struct unqualified_pusher<std::remove_pointer_t<lua_CFunction>> { + static int push(lua_State* L, lua_CFunction func, int n = 0) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template <> + struct unqualified_pusher<lua_CFunction> { + static int push(lua_State* L, lua_CFunction func, int n = 0) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushcclosure(L, func, n); + return 1; + } + }; + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + template <> + struct unqualified_pusher<std::remove_pointer_t<detail::lua_CFunction_noexcept>> { + static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template <> + struct unqualified_pusher<detail::lua_CFunction_noexcept> { + static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushcclosure(L, func, n); + return 1; + } + }; +#endif // noexcept function type + + template <> + struct unqualified_pusher<c_closure> { + static int push(lua_State* L, c_closure cc) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushcclosure(L, cc.c_function, cc.upvalues); + return 1; + } + }; + + template <typename Arg, typename... Args> + struct unqualified_pusher<closure<Arg, Args...>> { + template <std::size_t... I, typename T> + static int push(std::index_sequence<I...>, lua_State* L, T&& c) { + using f_tuple = decltype(std::forward<T>(c).upvalues); + int pushcount = multi_push(L, std::get<I>(std::forward<f_tuple>(std::forward<T>(c).upvalues))...); + return stack::push(L, c_closure(c.c_function, pushcount)); + } + + template <typename T> + static int push(lua_State* L, T&& c) { + return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c)); + } + }; + + template <> + struct unqualified_pusher<void*> { + static int push(lua_State* L, void* userdata) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template <> + struct unqualified_pusher<const void*> { + static int push(lua_State* L, const void* userdata) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushlightuserdata(L, const_cast<void*>(userdata)); + return 1; + } + }; + + template <> + struct unqualified_pusher<lightuserdata_value> { + static int push(lua_State* L, lightuserdata_value userdata) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template <typename T> + struct unqualified_pusher<light<T>> { + static int push(lua_State* L, light<T> l) noexcept { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushlightuserdata(L, static_cast<void*>(l.value())); + return 1; + } + }; + + template <typename T> + struct unqualified_pusher<user<T>> { + template <bool with_meta = true, typename Key, typename... Args> + static int push_with(lua_State* L, Key&& name, Args&&... args) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata); +#endif // make sure stack doesn't overflow + // A dumb pusher + T* data = detail::user_allocate<T>(L); + if (with_meta) { + // Make sure we have a plain GC set for this data +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + if (luaL_newmetatable(L, name) != 0) { + lua_CFunction cdel = detail::user_alloc_destroy<T>; + lua_pushcclosure(L, cdel, 0); + lua_setfield(L, -2, "__gc"); + } + lua_setmetatable(L, -2); + } + std::allocator<T> alloc {}; + std::allocator_traits<std::allocator<T>>::construct(alloc, data, std::forward<Args>(args)...); + return 1; + } + + template <typename Arg, typename... Args> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + if constexpr (std::is_same_v<meta::unqualified_t<Arg>, metatable_key_t>) { + const auto name = &arg[0]; + return push_with<true>(L, name, std::forward<Args>(args)...); + } + else if constexpr (std::is_same_v<meta::unqualified_t<Arg>, no_metatable_t>) { + (void)arg; + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; + return push_with<false>(L, name, std::forward<Args>(args)...); + } + else { + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; + return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...); + } + } + + static int push(lua_State* L, const user<T>& u) { + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, user<T>&& u) { + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; + return push_with(L, name, std::move(u.value())); + } + + static int push(lua_State* L, no_metatable_t, const user<T>& u) { + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; + return push_with<false>(L, name, u.value()); + } + + static int push(lua_State* L, no_metatable_t, user<T>&& u) { + const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; + return push_with<false>(L, name, std::move(u.value())); + } + }; + + template <> + struct unqualified_pusher<userdata_value> { + static int push(lua_State* L, userdata_value data) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_userdata); +#endif // make sure stack doesn't overflow + void** ud = detail::usertype_allocate_pointer<void>(L); + *ud = data.value(); + return 1; + } + }; + + template <> + struct unqualified_pusher<const char*> { + static int push_sized(lua_State* L, const char* str, std::size_t len) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, str, len); + return 1; + } + + static int push(lua_State* L, const char* str) { + if (str == nullptr) + return stack::push(L, lua_nil); + return push_sized(L, str, std::char_traits<char>::length(str)); + } + + static int push(lua_State* L, const char* strb, const char* stre) { + return push_sized(L, strb, static_cast<std::size_t>(stre - strb)); + } + + static int push(lua_State* L, const char* str, std::size_t len) { + return push_sized(L, str, len); + } + }; + + template <> + struct unqualified_pusher<char*> { + static int push_sized(lua_State* L, const char* str, std::size_t len) { + unqualified_pusher<const char*> p {}; + (void)p; + return p.push_sized(L, str, len); + } + + static int push(lua_State* L, const char* str) { + unqualified_pusher<const char*> p {}; + (void)p; + return p.push(L, str); + } + + static int push(lua_State* L, const char* strb, const char* stre) { + unqualified_pusher<const char*> p {}; + (void)p; + return p.push(L, strb, stre); + } + + static int push(lua_State* L, const char* str, std::size_t len) { + unqualified_pusher<const char*> p {}; + (void)p; + return p.push(L, str, len); + } + }; + + template <size_t N> + struct unqualified_pusher<char[N]> { + static int push(lua_State* L, const char (&str)[N]) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, str, std::char_traits<char>::length(str)); + return 1; + } + + static int push(lua_State* L, const char (&str)[N], std::size_t sz) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, str, sz); + return 1; + } + }; + + template <> + struct unqualified_pusher<char> { + static int push(lua_State* L, char c) { + const char str[2] = { c, '\0' }; + return stack::push(L, static_cast<const char*>(str), 1u); + } + }; + +#if SOL_IS_ON(SOL_CHAR8_T) + template <> + struct unqualified_pusher<const char8_t*> { + static int push_sized(lua_State* L, const char8_t* str, std::size_t len) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, reinterpret_cast<const char*>(str), len); + return 1; + } + + static int push(lua_State* L, const char8_t* str) { + if (str == nullptr) + return stack::push(L, lua_nil); + return push_sized(L, str, std::char_traits<char>::length(reinterpret_cast<const char*>(str))); + } + + static int push(lua_State* L, const char8_t* strb, const char8_t* stre) { + return push_sized(L, strb, static_cast<std::size_t>(stre - strb)); + } + + static int push(lua_State* L, const char8_t* str, std::size_t len) { + return push_sized(L, str, len); + } + }; + + template <> + struct unqualified_pusher<char8_t*> { + static int push_sized(lua_State* L, const char8_t* str, std::size_t len) { + unqualified_pusher<const char8_t*> p {}; + (void)p; + return p.push_sized(L, str, len); + } + + static int push(lua_State* L, const char8_t* str) { + unqualified_pusher<const char8_t*> p {}; + (void)p; + return p.push(L, str); + } + + static int push(lua_State* L, const char8_t* strb, const char8_t* stre) { + unqualified_pusher<const char8_t*> p {}; + (void)p; + return p.push(L, strb, stre); + } + + static int push(lua_State* L, const char8_t* str, std::size_t len) { + unqualified_pusher<const char8_t*> p {}; + (void)p; + return p.push(L, str, len); + } + }; + + template <size_t N> + struct unqualified_pusher<char8_t[N]> { + static int push(lua_State* L, const char8_t (&str)[N]) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + const char* str_as_char = reinterpret_cast<const char*>(static_cast<const char8_t*>(str)); + lua_pushlstring(L, str_as_char, std::char_traits<char>::length(str_as_char)); + return 1; + } + + static int push(lua_State* L, const char8_t (&str)[N], std::size_t sz) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, str, sz); + return 1; + } + }; + + template <> + struct unqualified_pusher<char8_t> { + static int push(lua_State* L, char8_t c) { + const char8_t str[2] = { c, '\0' }; + return stack::push(L, static_cast<const char8_t*>(str), 1u); + } + }; +#endif // char8_t + + template <typename Ch, typename Traits, typename Al> + struct unqualified_pusher<std::basic_string<Ch, Traits, Al>> { + static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& str) { + if constexpr (!std::is_same_v<Ch, char>) { + return stack::push(L, str.data(), str.size()); + } + else { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + } + + static int push(lua_State* L, const std::basic_string<Ch, Traits, Al>& str, std::size_t sz) { + if constexpr (!std::is_same_v<Ch, char>) { + return stack::push(L, str.data(), sz); + } + else { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_string); +#endif // make sure stack doesn't overflow + lua_pushlstring(L, str.c_str(), sz); + return 1; + } + } + }; + + template <typename Ch, typename Traits> + struct unqualified_pusher<basic_string_view<Ch, Traits>> { + static int push(lua_State* L, const basic_string_view<Ch, Traits>& sv) { + return stack::push(L, sv.data(), sv.length()); + } + + static int push(lua_State* L, const basic_string_view<Ch, Traits>& sv, std::size_t n) { + return stack::push(L, sv.data(), n); + } + }; + + template <> + struct unqualified_pusher<meta_function> { + static int push(lua_State* L, meta_function m) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_meta_function_name); +#endif // make sure stack doesn't overflow + const std::string& str = to_string(m); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + }; + + template <> + struct unqualified_pusher<absolute_index> { + static int push(lua_State* L, absolute_index ai) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushvalue(L, ai); + return 1; + } + }; + + template <> + struct unqualified_pusher<raw_index> { + static int push(lua_State* L, raw_index ri) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushvalue(L, ri); + return 1; + } + }; + + template <> + struct unqualified_pusher<ref_index> { + static int push(lua_State* L, ref_index ri) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_rawgeti(L, LUA_REGISTRYINDEX, ri); + return 1; + } + }; + + template <> + struct unqualified_pusher<const wchar_t*> { + static int push(lua_State* L, const wchar_t* wstr) { + return push(L, wstr, std::char_traits<wchar_t>::length(wstr)); + } + + static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { + return push(L, wstr, wstr + sz); + } + + static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { + if constexpr (sizeof(wchar_t) == 2) { + const char16_t* sb = reinterpret_cast<const char16_t*>(strb); + const char16_t* se = reinterpret_cast<const char16_t*>(stre); + return stack::push(L, sb, se); + } + else { + const char32_t* sb = reinterpret_cast<const char32_t*>(strb); + const char32_t* se = reinterpret_cast<const char32_t*>(stre); + return stack::push(L, sb, se); + } + } + }; + + template <> + struct unqualified_pusher<wchar_t*> { + static int push(lua_State* L, const wchar_t* str) { + unqualified_pusher<const wchar_t*> p {}; + (void)p; + return p.push(L, str); + } + + static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { + unqualified_pusher<const wchar_t*> p {}; + (void)p; + return p.push(L, strb, stre); + } + + static int push(lua_State* L, const wchar_t* str, std::size_t len) { + unqualified_pusher<const wchar_t*> p {}; + (void)p; + return p.push(L, str, len); + } + }; + + template <> + struct unqualified_pusher<const char16_t*> { + static int convert_into(lua_State* L, char* start, std::size_t, const char16_t* strb, const char16_t* stre) { + char* target = start; + char32_t cp = 0; + for (const char16_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf16_to_code_point(strtarget, stre); + if (dr.error != unicode::error_code::ok) { + cp = unicode::unicode_detail::replacement; + } + else { + cp = dr.codepoint; + } + auto er = unicode::code_point_to_utf8(cp); + const char* utf8data = er.code_units.data(); + std::memcpy(target, utf8data, er.code_units_size); + target += er.code_units_size; + strtarget = dr.next; + } + + return stack::push(L, start, target); + } + + static int push(lua_State* L, const char16_t* u16str) { + return push(L, u16str, std::char_traits<char16_t>::length(u16str)); + } + + static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { + return push(L, u16str, u16str + sz); + } + + static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { + char sbo[SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_]; + // if our max string space is small enough, use SBO + // right off the bat + std::size_t max_possible_code_units = static_cast<std::size_t>(static_cast<std::size_t>(stre - strb) * static_cast<std::size_t>(4)); + if (max_possible_code_units <= SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) { + return convert_into(L, sbo, max_possible_code_units, strb, stre); + } + // otherwise, we must manually count/check size + std::size_t needed_size = 0; + for (const char16_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf16_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf8(dr.codepoint); + needed_size += er.code_units_size; + strtarget = dr.next; + } + if (needed_size < SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) { + return convert_into(L, sbo, needed_size, strb, stre); + } + std::string u8str("", 0); + u8str.resize(needed_size); + char* target = const_cast<char*>(u8str.data()); + return convert_into(L, target, needed_size, strb, stre); + } + }; + + template <> + struct unqualified_pusher<char16_t*> { + static int push(lua_State* L, const char16_t* str) { + unqualified_pusher<const char16_t*> p {}; + (void)p; + return p.push(L, str); + } + + static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { + unqualified_pusher<const char16_t*> p {}; + (void)p; + return p.push(L, strb, stre); + } + + static int push(lua_State* L, const char16_t* str, std::size_t len) { + unqualified_pusher<const char16_t*> p {}; + (void)p; + return p.push(L, str, len); + } + }; + + template <> + struct unqualified_pusher<const char32_t*> { + static int convert_into(lua_State* L, char* start, std::size_t, const char32_t* strb, const char32_t* stre) { + char* target = start; + char32_t cp = 0; + for (const char32_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf32_to_code_point(strtarget, stre); + if (dr.error != unicode::error_code::ok) { + cp = unicode::unicode_detail::replacement; + } + else { + cp = dr.codepoint; + } + auto er = unicode::code_point_to_utf8(cp); + const char* data = er.code_units.data(); + std::memcpy(target, data, er.code_units_size); + target += er.code_units_size; + strtarget = dr.next; + } + return stack::push(L, start, target); + } + + static int push(lua_State* L, const char32_t* u32str) { + return push(L, u32str, u32str + std::char_traits<char32_t>::length(u32str)); + } + + static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { + return push(L, u32str, u32str + sz); + } + + static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { + char sbo[SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_]; + // if our max string space is small enough, use SBO + // right off the bat + std::size_t max_possible_code_units = static_cast<std::size_t>(static_cast<std::size_t>(stre - strb) * static_cast<std::size_t>(4)); + if (max_possible_code_units <= SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) { + return convert_into(L, sbo, max_possible_code_units, strb, stre); + } + // otherwise, we must manually count/check size + std::size_t needed_size = 0; + for (const char32_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf32_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf8(dr.codepoint); + needed_size += er.code_units_size; + strtarget = dr.next; + } + if (needed_size < SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_) { + return convert_into(L, sbo, needed_size, strb, stre); + } + std::string u8str("", 0); + u8str.resize(needed_size); + char* target = const_cast<char*>(u8str.data()); + return convert_into(L, target, needed_size, strb, stre); + } + }; + + template <> + struct unqualified_pusher<char32_t*> { + static int push(lua_State* L, const char32_t* str) { + unqualified_pusher<const char32_t*> p {}; + (void)p; + return p.push(L, str); + } + + static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { + unqualified_pusher<const char32_t*> p {}; + (void)p; + return p.push(L, strb, stre); + } + + static int push(lua_State* L, const char32_t* str, std::size_t len) { + unqualified_pusher<const char32_t*> p {}; + (void)p; + return p.push(L, str, len); + } + }; + + template <size_t N> + struct unqualified_pusher<wchar_t[N]> { + static int push(lua_State* L, const wchar_t (&str)[N]) { + return push(L, str, std::char_traits<wchar_t>::length(str)); + } + + static int push(lua_State* L, const wchar_t (&str)[N], std::size_t sz) { + const wchar_t* str_ptr = static_cast<const wchar_t*>(str); + return stack::push<const wchar_t*>(L, str_ptr, str_ptr + sz); + } + }; + + template <size_t N> + struct unqualified_pusher<char16_t[N]> { + static int push(lua_State* L, const char16_t (&str)[N]) { + return push(L, str, std::char_traits<char16_t>::length(str)); + } + + static int push(lua_State* L, const char16_t (&str)[N], std::size_t sz) { + const char16_t* str_ptr = static_cast<const char16_t*>(str); + return stack::push<const char16_t*>(L, str_ptr, str_ptr + sz); + } + }; + + template <size_t N> + struct unqualified_pusher<char32_t[N]> { + static int push(lua_State* L, const char32_t (&str)[N]) { + return push(L, str, std::char_traits<char32_t>::length(str)); + } + + static int push(lua_State* L, const char32_t (&str)[N], std::size_t sz) { + const char32_t* str_ptr = static_cast<const char32_t*>(str); + return stack::push<const char32_t*>(L, str_ptr, str_ptr + sz); + } + }; + + template <> + struct unqualified_pusher<wchar_t> { + static int push(lua_State* L, wchar_t c) { + const wchar_t str[2] = { c, '\0' }; + return stack::push(L, static_cast<const wchar_t*>(str), 1u); + } + }; + + template <> + struct unqualified_pusher<char16_t> { + static int push(lua_State* L, char16_t c) { + const char16_t str[2] = { c, '\0' }; + return stack::push(L, static_cast<const char16_t*>(str), 1u); + } + }; + + template <> + struct unqualified_pusher<char32_t> { + static int push(lua_State* L, char32_t c) { + const char32_t str[2] = { c, '\0' }; + return stack::push(L, static_cast<const char32_t*>(str), 1u); + } + }; + + template <typename... Args> + struct unqualified_pusher<std::tuple<Args...>> { + template <std::size_t... I, typename T> + static int push(std::index_sequence<I...>, lua_State* L, T&& t) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, static_cast<int>(sizeof...(I)), detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + int pushcount = 0; + (void)detail::swallow { 0, (pushcount += stack::push(L, std::get<I>(std::forward<T>(t))), 0)... }; + return pushcount; + } + + template <typename T> + static int push(lua_State* L, T&& t) { + return push(std::index_sequence_for<Args...>(), L, std::forward<T>(t)); + } + }; + + template <typename A, typename B> + struct unqualified_pusher<std::pair<A, B>> { + template <typename T> + static int push(lua_State* L, T&& t) { + int pushcount = stack::push(L, std::get<0>(std::forward<T>(t))); + pushcount += stack::push(L, std::get<1>(std::forward<T>(t))); + return pushcount; + } + }; + + template <typename T> + struct unqualified_pusher<T, std::enable_if_t<meta::is_optional_v<T>>> { + using ValueType = typename meta::unqualified_t<T>::value_type; + + template <typename Optional> + static int push(lua_State* L, Optional&& op) { + using QualifiedValueType = meta::conditional_t<std::is_lvalue_reference_v<Optional>, ValueType&, ValueType&&>; + if (!op) { + return stack::push(L, nullopt); + } + return stack::push(L, static_cast<QualifiedValueType>(op.value())); + } + }; + + template <typename T> + struct unqualified_pusher<forward_as_value_t<T>> { + static int push(lua_State* L, const forward_as_value_t<T>& value_) { + return stack::push<T>(L, value_.value()); + } + + static int push(lua_State* L, forward_as_value_t<T>&& value_) { + return stack::push<T>(L, std::move(value_).value()); + } + }; + + template <> + struct unqualified_pusher<nullopt_t> { + static int push(lua_State* L, nullopt_t) noexcept { + return stack::push(L, lua_nil); + } + }; + + template <> + struct unqualified_pusher<std::nullptr_t> { + static int push(lua_State* L, std::nullptr_t) noexcept { + return stack::push(L, lua_nil); + } + }; + + template <> + struct unqualified_pusher<this_state> { + static int push(lua_State*, const this_state&) noexcept { + return 0; + } + }; + + template <> + struct unqualified_pusher<this_main_state> { + static int push(lua_State*, const this_main_state&) noexcept { + return 0; + } + }; + + template <> + struct unqualified_pusher<new_table> { + static int push(lua_State* L, const new_table& nt) { + lua_createtable(L, nt.sequence_hint, nt.map_hint); + return 1; + } + }; + + template <typename Allocator> + struct unqualified_pusher<basic_bytecode<Allocator>> { + template <typename T> + static int push(lua_State* L, T&& bc, const char* bytecode_name) { + const auto first = bc.data(); + const auto bcsize = bc.size(); + // pushes either the function, or an error + // if it errors, shit goes south, and people can test that upstream + (void)luaL_loadbuffer( + L, reinterpret_cast<const char*>(first), static_cast<std::size_t>(bcsize * (sizeof(*first) / sizeof(const char))), bytecode_name); + return 1; + } + + template <typename T> + static int push(lua_State* L, T&& bc) { + return push(L, std::forward<bc>(bc), "bytecode"); + } + }; + +#if SOL_IS_ON(SOL_STD_VARIANT) + namespace stack_detail { + + struct push_function { + lua_State* L; + + push_function(lua_State* L_) noexcept : L(L_) { + } + + template <typename T> + int operator()(T&& value) const { + return stack::push<T>(L, std::forward<T>(value)); + } + }; + + } // namespace stack_detail + + template <typename... Tn> + struct unqualified_pusher<std::variant<Tn...>> { + static int push(lua_State* L, const std::variant<Tn...>& v) { + return std::visit(stack_detail::push_function(L), v); + } + + static int push(lua_State* L, std::variant<Tn...>&& v) { + return std::visit(stack_detail::push_function(L), std::move(v)); + } + }; +#endif // Variant because Clang is terrible + +}} // namespace sol::stack + +// end of sol/stack_push.hpp + +// beginning of sol/stack_pop.hpp + +#include <utility> +#include <tuple> + +namespace sol { namespace stack { + template <typename T, typename> + struct popper { + inline static decltype(auto) pop(lua_State* L) { + if constexpr (is_stack_based_v<meta::unqualified_t<T>>) { + static_assert(!is_stack_based_v<meta::unqualified_t<T>>, + "You cannot pop something that lives solely on the stack: it will not remain on the stack when popped and thusly will go out of " + "scope!"); + } + else { + record tracking {}; + decltype(auto) r = get<T>(L, -lua_size<T>::value, tracking); + lua_pop(L, tracking.used); + return r; + } + } + }; +}} // namespace sol::stack + +// end of sol/stack_pop.hpp + +// beginning of sol/stack_field.hpp + +namespace sol { namespace stack { + + namespace stack_detail { + template <typename T, bool global, bool raw> + inline constexpr bool is_get_direct_tableless_v = (global && !raw && meta::is_c_str_or_string_v<T>); + + template <typename T, bool global, bool raw> + inline constexpr bool is_get_direct_v = (is_get_direct_tableless_v<T, global, raw>) // cf-hack + || (!global && !raw && (meta::is_c_str_or_string_v<T> || meta::is_string_of_v<T, char>)) // cf-hack + || (!global && raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>)) +#if SOL_LUA_VERSION_I_ >= 503 + || (!global && !raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>)) +#endif // integer keys 5.3 or better +#if SOL_LUA_VERSION_I_ >= 502 + || (!global && raw && std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>) +#endif // void pointer keys 5.2 or better + ; + + template <typename T, bool global, bool raw> + inline constexpr bool is_set_direct_tableless_v = (global && !raw && meta::is_c_str_or_string_v<T>); + + template <typename T, bool global, bool raw> + inline constexpr bool is_set_direct_v = (is_set_direct_tableless_v<T, global, raw>) // cf-hack + || (!global && !raw && (meta::is_c_str_or_string_v<T> || meta::is_string_of_v<T, char>)) // cf-hack + || (!global && raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>)) // cf-hack +#if SOL_LUA_VERSION_I_ >= 503 + || (!global && !raw && (std::is_integral_v<T> && !std::is_same_v<T, bool>)) +#endif // integer keys 5.3 or better +#if SOL_LUA_VERSION_I_ >= 502 + || (!global && raw && (std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>)) +#endif // void pointer keys 5.2 or better + ; + } // namespace stack_detail + + template <typename T, bool global, bool raw, typename> + struct field_getter { + static inline constexpr int default_table_index + = meta::conditional_t<stack_detail::is_get_direct_v<T, global, raw>, std::integral_constant<int, -1>, std::integral_constant<int, -2>>::value; + + template <typename Key> + void get(lua_State* L, Key&& key, int tableindex = default_table_index) { + if constexpr (std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, override_value_t> || std::is_same_v<T, create_if_nil_t>) { + (void)L; + (void)key; + (void)tableindex; + } + else if constexpr (std::is_same_v<T, env_key_t>) { + (void)key; +#if SOL_LUA_VERSION_I_ < 502 + // Use lua_setfenv + lua_getfenv(L, tableindex); +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + if (lua_getupvalue(L, tableindex, 1) == nullptr) { + push(L, lua_nil); + } +#endif + } + else if constexpr (std::is_same_v<T, metatable_key_t>) { + (void)key; + if (lua_getmetatable(L, tableindex) == 0) + push(L, lua_nil); + } + else if constexpr (raw) { + if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) { + lua_rawgeti(L, tableindex, static_cast<lua_Integer>(key)); + } +#if SOL_LUA_VERSION_I_ >= 502 + else if constexpr (std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>) { + lua_rawgetp(L, tableindex, key); + } +#endif // Lua 5.2.x+ + else { + push(L, std::forward<Key>(key)); + lua_rawget(L, tableindex); + } + } + else { + if constexpr (meta::is_c_str_or_string_v<T>) { + if constexpr (global) { + (void)tableindex; + lua_getglobal(L, &key[0]); + } + else { + lua_getfield(L, tableindex, &key[0]); + } + } + else if constexpr (std::is_same_v<T, meta_function>) { + const auto& real_key = to_string(key); + lua_getfield(L, tableindex, &real_key[0]); + } +#if SOL_LUA_VERSION_I_ >= 503 + else if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) { + lua_geti(L, tableindex, static_cast<lua_Integer>(key)); + } +#endif // Lua 5.3.x+ + else { + push(L, std::forward<Key>(key)); + lua_gettable(L, tableindex); + } + } + } + }; + + template <typename... Args, bool b, bool raw, typename C> + struct field_getter<std::tuple<Args...>, b, raw, C> { + template <std::size_t... I, typename Keys> + void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { + get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex); + void(detail::swallow { (get_field<false, raw>(L, std::get<I>(std::forward<Keys>(keys))), 0)... }); + reference saved(L, -1); + lua_pop(L, static_cast<int>(sizeof...(I))); + saved.push(); + } + + template <typename Keys> + void get(lua_State* L, Keys&& keys) { + apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), lua_absindex(L, -1)); + } + + template <typename Keys> + void get(lua_State* L, Keys&& keys, int tableindex) { + apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), tableindex); + } + }; + + template <typename A, typename B, bool b, bool raw, typename C> + struct field_getter<std::pair<A, B>, b, raw, C> { + template <typename Keys> + void get(lua_State* L, Keys&& keys, int tableindex) { + get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex); + get_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys))); + reference saved(L, -1); + lua_pop(L, static_cast<int>(2)); + saved.push(); + } + + template <typename Keys> + void get(lua_State* L, Keys&& keys) { + get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys))); + get_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys))); + reference saved(L, -1); + lua_pop(L, static_cast<int>(2)); + saved.push(); + } + }; + + template <typename T, bool global, bool raw, typename> + struct field_setter { + static constexpr int default_table_index + = meta::conditional_t<stack_detail::is_set_direct_v<T, global, raw>, std::integral_constant<int, -2>, std::integral_constant<int, -3>>::value; + + template <typename Key, typename Value> + void set(lua_State* L, Key&& key, Value&& value, int tableindex = default_table_index) { + if constexpr (std::is_same_v<T, update_if_empty_t> || std::is_same_v<T, override_value_t>) { + (void)L; + (void)key; + (void)value; + (void)tableindex; + } + else if constexpr (std::is_same_v<T, metatable_key_t>) { + (void)key; + push(L, std::forward<Value>(value)); + lua_setmetatable(L, tableindex); + } + else if constexpr (raw) { + if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) { + push(L, std::forward<Value>(value)); + lua_rawseti(L, tableindex, static_cast<lua_Integer>(key)); + } +#if SOL_LUA_VERSION_I_ >= 502 + else if constexpr (std::is_pointer_v<T> && std::is_void_v<std::remove_pointer_t<T>>) { + push(L, std::forward<Value>(value)); + lua_rawsetp(L, tableindex, std::forward<Key>(key)); + } +#endif // Lua 5.2.x + else { + push(L, std::forward<Key>(key)); + push(L, std::forward<Value>(value)); + lua_rawset(L, tableindex); + } + } + else { + if constexpr (meta::is_c_str_or_string_v<T>) { + if constexpr (global) { + push(L, std::forward<Value>(value)); + lua_setglobal(L, &key[0]); + (void)tableindex; + } + else { + push(L, std::forward<Value>(value)); + lua_setfield(L, tableindex, &key[0]); + } + } +#if SOL_LUA_VERSION_I_ >= 503 + else if constexpr (std::is_integral_v<T> && !std::is_same_v<bool, T>) { + push(L, std::forward<Value>(value)); + lua_seti(L, tableindex, static_cast<lua_Integer>(key)); + } +#endif // Lua 5.3.x + else { + push(L, std::forward<Key>(key)); + push(L, std::forward<Value>(value)); + lua_settable(L, tableindex); + } + } + } + }; + + template <typename... Args, bool b, bool raw, typename C> + struct field_setter<std::tuple<Args...>, b, raw, C> { + template <bool g, std::size_t I, typename Keys, typename Value> + void apply(std::index_sequence<I>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + I < 1 ? set_field<g, raw>(L, std::get<I>(std::forward<Keys>(keys)), std::forward<Value>(value), tableindex) + : set_field<g, raw>(L, std::get<I>(std::forward<Keys>(keys)), std::forward<Value>(value)); + } + + template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value> + void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + I0 < 1 ? get_field<g, raw>(L, std::get<I0>(std::forward<Keys>(keys)), tableindex) + : get_field<g, raw>(L, std::get<I0>(std::forward<Keys>(keys)), -1); + apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1); + } + + template <bool g, std::size_t I0, std::size_t... I, typename Keys, typename Value> + void top_apply(std::index_sequence<I0, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + apply<g>(std::index_sequence<I0, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); + lua_pop(L, static_cast<int>(sizeof...(I))); + } + + template <typename Keys, typename Value> + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { + top_apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); + } + }; + + template <typename A, typename B, bool b, bool raw, typename C> + struct field_setter<std::pair<A, B>, b, raw, C> { + template <typename Keys, typename Value> + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { + get_field<b, raw>(L, std::get<0>(std::forward<Keys>(keys)), tableindex); + set_field<false, raw>(L, std::get<1>(std::forward<Keys>(keys)), std::forward<Value>(value), lua_gettop(L)); + lua_pop(L, 1); + } + }; +}} // namespace sol::stack + +// end of sol/stack_field.hpp + +// beginning of sol/stack_probe.hpp + +namespace sol { namespace stack { + template <typename T, typename P, bool b, bool raw, typename> + struct probe_field_getter { + template <typename Key> + probe get(lua_State* L, Key&& key, int tableindex = -2) { + if constexpr (!b) { + if (!maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + } + get_field<b, raw>(L, std::forward<Key>(key), tableindex); + return probe(check<P>(L), 1); + } + }; + + template <typename A, typename B, typename P, bool b, bool raw, typename C> + struct probe_field_getter<std::pair<A, B>, P, b, raw, C> { + template <typename Keys> + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field<b, raw>(L, std::get<0>(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, 1); + } + get_field<false, raw>(L, std::get<1>(keys), tableindex); + return probe(check<P>(L), 2); + } + }; + + template <typename... Args, typename P, bool b, bool raw, typename C> + struct probe_field_getter<std::tuple<Args...>, P, b, raw, C> { + template <std::size_t I, typename Keys> + probe apply(std::index_sequence<I>, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field<(I < 1) && b, raw>(L, std::get<I>(keys), tableindex); + return probe(check<P>(L), sofar); + } + + template <std::size_t I, std::size_t I1, std::size_t... In, typename Keys> + probe apply(std::index_sequence<I, I1, In...>, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I<1 && b, raw>(L, std::get<I>(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, sofar); + } + return apply(std::index_sequence<I1, In...>(), sofar + 1, L, std::forward<Keys>(keys), -1); + } + + template <typename Keys> + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if constexpr (!b) { + if (!maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex); + } + else { + return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex); + } + } + }; +}} // namespace sol::stack + +// end of sol/stack_probe.hpp + +#include <cstring> +#include <array> + +namespace sol { + namespace detail { + using typical_chunk_name_t = char[SOL_ID_SIZE_I_]; + using typical_file_chunk_name_t = char[SOL_FILE_ID_SIZE_I_]; + + inline const std::string& default_chunk_name() { + static const std::string name = ""; + return name; + } + + template <std::size_t N> + const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) { + if (chunkname.empty()) { + auto it = code.cbegin(); + auto e = code.cend(); + std::size_t i = 0; + static const std::size_t n = N - 4; + for (i = 0; i < n && it != e; ++i, ++it) { + basechunkname[i] = *it; + } + if (it != e) { + for (std::size_t c = 0; c < 3; ++i, ++c) { + basechunkname[i] = '.'; + } + } + basechunkname[i] = '\0'; + return &basechunkname[0]; + } + else { + return chunkname.c_str(); + } + } + + inline void clear_entries(stack_reference r) { + stack::push(r.lua_state(), lua_nil); + while (lua_next(r.lua_state(), -2)) { + absolute_index key(r.lua_state(), -2); + auto pn = stack::pop_n(r.lua_state(), 1); + stack::set_field<false, true>(r.lua_state(), key, lua_nil, r.stack_index()); + } + } + + inline void clear_entries(const reference& registry_reference) { + auto pp = stack::push_pop(registry_reference); + stack_reference ref(registry_reference.lua_state(), -1); + clear_entries(ref); + } + } // namespace detail + + namespace stack { + namespace stack_detail { + template <typename T> + inline int push_as_upvalues(lua_State* L, T& item) { + typedef std::decay_t<T> TValue; + static const std::size_t itemsize = sizeof(TValue); + static const std::size_t voidsize = sizeof(void*); + static const std::size_t voidsizem1 = voidsize - 1; + static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; + typedef std::array<void*, data_t_count> data_t; + + data_t data { {} }; + std::memcpy(&data[0], std::addressof(item), itemsize); + int pushcount = 0; + for (const auto& v : data) { + lua_pushlightuserdata(L, v); + pushcount += 1; + } + return pushcount; + } + + template <typename T> + inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 2) { + static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); + typedef std::array<void*, data_t_count> data_t; + data_t voiddata { {} }; + for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { + voiddata[i] = lua_touserdata(L, upvalue_index(index++)); + } + return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index); + } + + template <typename T> + inline std::pair<T, int> get_as_upvalues_using_function(lua_State* L, int function_index = -1) { + static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); + typedef std::array<void*, data_t_count> data_t; + function_index = lua_absindex(L, function_index); + int index = 0; + data_t voiddata { {} }; + for (std::size_t d = 0; d < sizeof(T); d += sizeof(void*)) { + // first upvalue is nullptr to respect environment shenanigans + // So +2 instead of +1 + const char* upvalue_name = lua_getupvalue(L, function_index, index + 2); + if (upvalue_name == nullptr) { + // We should freak out here... + break; + } + voiddata[index] = lua_touserdata(L, -1); + ++index; + } + lua_pop(L, index); + return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index); + } + + template <bool checked, typename Handler, typename Fx, typename... Args> + static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, Handler&&, record&, Fx&& fx, Args&&... args) { + return std::forward<Fx>(fx)(std::forward<Args>(args)...); + } + + template <bool checked, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename Handler, typename Fx, typename... FxArgs> + static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L_, int start_index_, Handler&& handler_, + record& tracking_, Fx&& fx_, FxArgs&&... fxargs_) { +#if SOL_IS_ON(SOL_PROPAGATE_EXCEPTIONS) + // We can save performance/time by letting errors unwind produced arguments + // rather than checking everything once, and then potentially re-doing work + if constexpr (checked) { + return eval<checked>(types<Args...>(), + std::index_sequence<Is...>(), + L_, + start_index_, + std::forward<Handler>(handler_), + tracking_, + std::forward<Fx>(fx_), + std::forward<FxArgs>(fxargs_)..., + *stack_detail::check_get_arg<Arg>(L_, start_index_ + tracking_.used, handler_, tracking_)); + } + else +#endif + { + return eval<checked>(types<Args...>(), + std::index_sequence<Is...>(), + L_, + start_index_, + std::forward<Handler>(handler_), + tracking_, + std::forward<Fx>(fx_), + std::forward<FxArgs>(fxargs_)..., + stack_detail::unchecked_get_arg<Arg>(L_, start_index_ + tracking_.used, tracking_)); + } + } + + template <bool checkargs = detail::default_safe_function_calls, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs> + inline decltype(auto) call(types<R>, types<Args...> argument_types_, std::index_sequence<I...> argument_indices_, lua_State* L_, + int start_index_, Fx&& fx_, FxArgs&&... args_) { + static_assert(meta::all_v<meta::is_not_move_only<Args>...>, + "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take " + "a reference and std::move it manually if this was your intention."); + argument_handler<types<R, Args...>> handler {}; + record tracking {}; +#if SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) + if constexpr (checkargs) { + multi_check<Args...>(L_, start_index_, handler); + } +#endif + if constexpr (std::is_void_v<R>) { + eval<checkargs>( + argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...); + } + else { + return eval<checkargs>( + argument_types_, argument_indices_, L_, start_index_, handler, tracking, std::forward<Fx>(fx_), std::forward<FxArgs>(args_)...); + } + } + + template <typename T> + void raw_table_set(lua_State* L, T&& arg, int tableindex = -2) { + int push_count = push(L, std::forward<T>(arg)); + sol_c_assert(push_count == 1); + std::size_t unique_index = static_cast<std::size_t>(luaL_len(L, tableindex) + 1u); + lua_rawseti(L, tableindex, unique_index); + } + + } // namespace stack_detail + + template <typename T> + int set_ref(lua_State* L, T&& arg, int tableindex = -2) { + int push_count = push(L, std::forward<T>(arg)); + sol_c_assert(push_count == 1); + return luaL_ref(L, tableindex); + } + + template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs> + inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + using args_indices = std::make_index_sequence<sizeof...(Args)>; + if constexpr (std::is_void_v<R>) { + stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); + } + else { + return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); + } + } + + template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs> + inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + if constexpr (std::is_void_v<R>) { + call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); + } + else { + return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); + } + } + + template <bool check_args = detail::default_safe_function_calls, typename R, typename... Args, typename Fx, typename... FxArgs> + inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + using expected_count_t = meta::count_for_pack<lua_size, Args...>; + if constexpr (std::is_void_v<R>) { + call<check_args>(tr, + ta, + L, + (std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)), + std::forward<Fx>(fx), + std::forward<FxArgs>(args)...); + } + else { + return call<check_args>(tr, + ta, + L, + (std::max)(static_cast<int>(lua_gettop(L) - expected_count_t::value), static_cast<int>(0)), + std::forward<Fx>(fx), + std::forward<FxArgs>(args)...); + } + } + + template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Ret0, typename... Ret, typename... Args, + typename Fx, typename... FxArgs> + inline int call_into_lua(types<Ret0, Ret...> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + if constexpr (std::is_void_v<Ret0>) { + call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); + if constexpr (clean_stack) { + lua_settop(L, 0); + } + return 0; + } + else { + (void)tr; + decltype(auto) r + = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); + using R = meta::unqualified_t<decltype(r)>; + using is_stack = meta::any<is_stack_based<R>, std::is_same<R, absolute_index>, std::is_same<R, ref_index>, std::is_same<R, raw_index>>; + if constexpr (clean_stack && !is_stack::value) { + lua_settop(L, 0); + } + return push_reference(L, std::forward<decltype(r)>(r)); + } + } + + template <bool check_args = detail::default_safe_function_calls, bool clean_stack = true, typename Fx, typename... FxArgs> + inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + using traits_type = lua_bind_traits<meta::unqualified_t<Fx>>; + using args_list = typename traits_type::args_list; + using returns_list = typename traits_type::returns_list; + return call_into_lua<check_args, clean_stack>(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); + } + + inline call_syntax get_call_syntax(lua_State* L, const string_view& key, int index) { + if (lua_gettop(L) < 1) { + return call_syntax::dot; + } + luaL_getmetatable(L, key.data()); + auto pn = pop_n(L, 1); + if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { + return call_syntax::dot; + } + return call_syntax::colon; + } + + inline void script( + lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); + if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + } + + inline void script( + lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); + if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + } + + inline void script_file(lua_State* L, const std::string& filename, load_mode mode = load_mode::any) { + if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + } + + inline void luajit_exception_handler(lua_State* L, int (*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { +#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE) + if (L == nullptr) { + return; + } +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushlightuserdata(L, (void*)handler); + auto pn = pop_n(L, 1); + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); +#else + (void)L; + (void)handler; +#endif + } + + inline void luajit_exception_off(lua_State* L) { +#if SOL_IS_ON(SOL_USE_LUAJIT_EXCEPTION_TRAMPOLINE) + if (L == nullptr) { + return; + } + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); +#else + (void)L; +#endif + } + } // namespace stack +} // namespace sol + +// end of sol/stack.hpp + +// beginning of sol/object.hpp + +// beginning of sol/make_reference.hpp + +namespace sol { + + template <typename R = reference, bool should_pop = !is_stack_based_v<R>, typename T> + R make_reference(lua_State* L, T&& value) { + int backpedal = stack::push(L, std::forward<T>(value)); + R r = stack::get<R>(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template <typename T, typename R = reference, bool should_pop = !is_stack_based_v<R>, typename... Args> + R make_reference(lua_State* L, Args&&... args) { + int backpedal = stack::push<T>(L, std::forward<Args>(args)...); + R r = stack::get<R>(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template <typename R = reference, bool should_pop = !is_stack_based_v<R>, typename T> + R make_reference_userdata(lua_State* L, T&& value) { + int backpedal = stack::push_userdata(L, std::forward<T>(value)); + R r = stack::get<R>(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template <typename T, typename R = reference, bool should_pop = !is_stack_based_v<R>, typename... Args> + R make_reference_userdata(lua_State* L, Args&&... args) { + int backpedal = stack::push_userdata<T>(L, std::forward<Args>(args)...); + R r = stack::get<R>(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + +} // namespace sol + +// end of sol/make_reference.hpp + +// beginning of sol/object_base.hpp + +namespace sol { + + template <typename ref_t> + class basic_object_base : public ref_t { + private: + using base_t = ref_t; + + template <typename T> + decltype(auto) as_stack(std::true_type) const { + return stack::get<T>(base_t::lua_state(), base_t::stack_index()); + } + + template <typename T> + decltype(auto) as_stack(std::false_type) const { + base_t::push(); + return stack::pop<T>(base_t::lua_state()); + } + + template <typename T> + bool is_stack(std::true_type) const { + return stack::check<T>(base_t::lua_state(), base_t::stack_index(), &no_panic); + } + + template <typename T> + bool is_stack(std::false_type) const { + int r = base_t::registry_index(); + if (r == LUA_REFNIL) + return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; + if (r == LUA_NOREF) + return false; + auto pp = stack::push_pop(*this); + return stack::check<T>(base_t::lua_state(), -1, &no_panic); + } + + public: + basic_object_base() noexcept = default; + basic_object_base(const basic_object_base&) = default; + basic_object_base(basic_object_base&&) = default; + basic_object_base& operator=(const basic_object_base&) = default; + basic_object_base& operator=(basic_object_base&&) = default; + template <typename T, typename... Args, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object_base>>> = meta::enabler> + basic_object_base(T&& arg, Args&&... args) : base_t(std::forward<T>(arg), std::forward<Args>(args)...) { + } + + template <typename T> + decltype(auto) as() const { + return as_stack<T>(is_stack_based<base_t>()); + } + + template <typename T> + bool is() const { + return is_stack<T>(is_stack_based<base_t>()); + } + }; +} // namespace sol + +// end of sol/object_base.hpp + +namespace sol { + + template <typename base_type> + class basic_object : public basic_object_base<base_type> { + private: + typedef basic_object_base<base_type> base_t; + + template <bool invert_and_pop = false> + basic_object(std::integral_constant<bool, invert_and_pop>, lua_State* L_, int index_ = -1) noexcept : base_t(L_, index_) { + if (invert_and_pop) { + lua_pop(L_, -index_); + } + } + + protected: + basic_object(detail::no_safety_tag, lua_nil_t n) : base_t(n) { + } + basic_object(detail::no_safety_tag, lua_State* L_, int index_) : base_t(L_, index_) { + } + basic_object(detail::no_safety_tag, lua_State* L_, ref_index index_) : base_t(L_, index_) { + } + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_type, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_object(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward<T>(r)) { + } + + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_object(detail::no_safety_tag, lua_State* L_, T&& r) noexcept : base_t(L_, std::forward<T>(r)) { + } + + public: + basic_object() noexcept = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_object>>, meta::neg<std::is_same<base_type, stack_reference>>, + is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_object(T&& r) : base_t(std::forward<T>(r)) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_object(lua_State* L_, T&& r) : base_t(L_, std::forward<T>(r)) { + } + basic_object(lua_State* L_, global_tag_t t) : base_t(L_, t) { + } + basic_object(lua_nil_t r) : base_t(r) { + } + basic_object(const basic_object&) = default; + basic_object(basic_object&&) = default; + basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) { + } + basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) { + } + template <typename Super> + basic_object(const proxy_base<Super>& r) noexcept : basic_object(r.operator basic_object()) { + } + template <typename Super> + basic_object(proxy_base<Super>&& r) noexcept : basic_object(r.operator basic_object()) { + } + basic_object(lua_State* L_, lua_nil_t r) noexcept : base_t(L_, r) { + } + basic_object(lua_State* L_, int index_ = -1) noexcept : base_t(L_, index_) { + } + basic_object(lua_State* L_, absolute_index index_) noexcept : base_t(L_, index_) { + } + basic_object(lua_State* L_, raw_index index_) noexcept : base_t(L_, index_) { + } + basic_object(lua_State* L_, ref_index index_) noexcept : base_t(L_, index_) { + } + template <typename T, typename... Args> + basic_object(lua_State* L_, in_place_type_t<T>, Args&&... args) noexcept + : basic_object(std::integral_constant<bool, !is_stack_based<base_t>::value>(), L_, -stack::push<T>(L_, std::forward<Args>(args)...)) { + } + template <typename T, typename... Args> + basic_object(lua_State* L_, in_place_t, T&& arg, Args&&... args) noexcept + : basic_object(L_, in_place_type<T>, std::forward<T>(arg), std::forward<Args>(args)...) { + } + basic_object& operator=(const basic_object&) = default; + basic_object& operator=(basic_object&&) = default; + basic_object& operator=(const base_type& b) { + base_t::operator=(b); + return *this; + } + basic_object& operator=(base_type&& b) { + base_t::operator=(std::move(b)); + return *this; + } + template <typename Super> + basic_object& operator=(const proxy_base<Super>& r) { + this->operator=(r.operator basic_object()); + return *this; + } + template <typename Super> + basic_object& operator=(proxy_base<Super>&& r) { + this->operator=(r.operator basic_object()); + return *this; + } + }; + + template <typename T> + object make_object(lua_State* L_, T&& value) { + return make_reference<object, true>(L_, std::forward<T>(value)); + } + + template <typename T, typename... Args> + object make_object(lua_State* L_, Args&&... args) { + return make_reference<T, object, true>(L_, std::forward<Args>(args)...); + } + + template <typename T> + object make_object_userdata(lua_State* L_, T&& value) { + return make_reference_userdata<object, true>(L_, std::forward<T>(value)); + } + + template <typename T, typename... Args> + object make_object_userdata(lua_State* L_, Args&&... args) { + return make_reference_userdata<T, object, true>(L_, std::forward<Args>(args)...); + } +} // namespace sol + +// end of sol/object.hpp + +// beginning of sol/function.hpp + +// beginning of sol/unsafe_function.hpp + +// beginning of sol/function_result.hpp + +// beginning of sol/protected_function_result.hpp + +// beginning of sol/proxy_base.hpp + +namespace sol { + struct proxy_base_tag { }; + + namespace detail { + template <typename T> + using proxy_key_t = meta::conditional_t<meta::is_specialization_of_v<meta::unqualified_t<T>, std::tuple>, T, + std::tuple<meta::conditional_t<std::is_array_v<meta::unqualified_t<T>>, std::remove_reference_t<T>&, meta::unqualified_t<T>>>>; + } + + template <typename Super> + struct proxy_base : public proxy_base_tag { + lua_State* lua_state() const { + const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); + return super.lua_state(); + } + + operator std::string() const { + const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); + return super.template get<std::string>(); + } + + template <typename T, meta::enable<meta::neg<meta::is_string_constructible<T>>, is_proxy_primitive<meta::unqualified_t<T>>> = meta::enabler> + operator T() const { + const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); + return super.template get<T>(); + } + + template <typename T, + meta::enable<meta::neg<meta::is_string_constructible<T>>, meta::neg<is_proxy_primitive<meta::unqualified_t<T>>>> = meta::enabler> + operator T&() const { + const Super& super = *static_cast<const Super*>(static_cast<const void*>(this)); + return super.template get<T&>(); + } + }; + +} // namespace sol + +// end of sol/proxy_base.hpp + +// beginning of sol/stack_iterator.hpp + +#include <limits> +#include <iterator> + +namespace sol { + template <typename proxy_t, bool is_const> + struct stack_iterator { + typedef meta::conditional_t<is_const, const proxy_t, proxy_t> reference; + typedef meta::conditional_t<is_const, const proxy_t*, proxy_t*> pointer; + typedef proxy_t value_type; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + lua_State* L; + int index; + int stacktop; + proxy_t sp; + + stack_iterator() : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()), sp() { + } + stack_iterator(const stack_iterator<proxy_t, true>& r) : L(r.L), index(r.index), stacktop(r.stacktop), sp(r.sp) { + } + stack_iterator(lua_State* luastate, int idx, int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) { + } + + reference operator*() { + return proxy_t(L, index); + } + + reference operator*() const { + return proxy_t(L, index); + } + + pointer operator->() { + sp = proxy_t(L, index); + return &sp; + } + + pointer operator->() const { + const_cast<proxy_t&>(sp) = proxy_t(L, index); + return &sp; + } + + stack_iterator& operator++() { + ++index; + return *this; + } + + stack_iterator operator++(int) { + auto r = *this; + this->operator++(); + return r; + } + + stack_iterator& operator--() { + --index; + return *this; + } + + stack_iterator operator--(int) { + auto r = *this; + this->operator--(); + return r; + } + + stack_iterator& operator+=(difference_type idx) { + index += static_cast<int>(idx); + return *this; + } + + stack_iterator& operator-=(difference_type idx) { + index -= static_cast<int>(idx); + return *this; + } + + difference_type operator-(const stack_iterator& r) const { + return index - r.index; + } + + stack_iterator operator+(difference_type idx) const { + stack_iterator r = *this; + r += idx; + return r; + } + + reference operator[](difference_type idx) const { + return proxy_t(L, index + static_cast<int>(idx)); + } + + bool operator==(const stack_iterator& r) const { + if (stacktop == (std::numeric_limits<int>::max)()) { + return r.index == r.stacktop; + } + else if (r.stacktop == (std::numeric_limits<int>::max)()) { + return index == stacktop; + } + return index == r.index; + } + + bool operator!=(const stack_iterator& r) const { + return !(this->operator==(r)); + } + + bool operator<(const stack_iterator& r) const { + return index < r.index; + } + + bool operator>(const stack_iterator& r) const { + return index > r.index; + } + + bool operator<=(const stack_iterator& r) const { + return index <= r.index; + } + + bool operator>=(const stack_iterator& r) const { + return index >= r.index; + } + }; + + template <typename proxy_t, bool is_const> + inline stack_iterator<proxy_t, is_const> operator+( + typename stack_iterator<proxy_t, is_const>::difference_type n, const stack_iterator<proxy_t, is_const>& r) { + return r + n; + } +} // namespace sol + +// end of sol/stack_iterator.hpp + +// beginning of sol/stack_proxy.hpp + +// beginning of sol/stack_proxy_base.hpp + +namespace sol { + struct stack_proxy_base : public proxy_base<stack_proxy_base> { + private: + lua_State* m_L; + int m_index; + + public: + stack_proxy_base() : m_L(nullptr), m_index(0) { + } + stack_proxy_base(lua_State* L_, int index_) : m_L(L_), m_index(index_) { + } + + template <typename T> + decltype(auto) get() const { + return stack::get<T>(m_L, stack_index()); + } + + template <typename T> + bool is() const { + return stack::check<T>(m_L, stack_index()); + } + + template <typename T> + decltype(auto) as() const { + return get<T>(); + } + + type get_type() const noexcept { + return type_of(lua_state(), stack_index()); + } + + int push() const { + return push(m_L); + } + + int push(lua_State* L_) const { + lua_pushvalue(L_, m_index); + return 1; + } + + lua_State* lua_state() const { + return m_L; + } + int stack_index() const { + return m_index; + } + }; + + namespace stack { + template <> + struct unqualified_getter<stack_proxy_base> { + static stack_proxy_base get(lua_State* L_, int index_ = -1) { + return stack_proxy_base(L_, index_); + } + }; + + template <> + struct unqualified_pusher<stack_proxy_base> { + static int push(lua_State*, const stack_proxy_base& proxy_reference) { + return proxy_reference.push(); + } + }; + } // namespace stack + +} // namespace sol + +// end of sol/stack_proxy_base.hpp + +namespace sol { + struct stack_proxy : public stack_proxy_base { + public: + stack_proxy() : stack_proxy_base() { + } + stack_proxy(lua_State* L, int index) : stack_proxy_base(L, index) { + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args); + + template <typename... Args> + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward<Args>(args)...); + } + }; + + namespace stack { + template <> + struct unqualified_getter<stack_proxy> { + static stack_proxy get(lua_State* L, int index, record& tracking) { + tracking.use(0); + return stack_proxy(L, index); + } + }; + + template <> + struct unqualified_pusher<stack_proxy> { + static int push(lua_State*, const stack_proxy& ref) { + return ref.push(); + } + }; + } // namespace stack +} // namespace sol + +// end of sol/stack_proxy.hpp + +#include <cstdint> + +namespace sol { + struct protected_function_result : public proxy_base<protected_function_result> { + private: + lua_State* L; + int index; + int returncount; + int popcount; + call_status err; + + public: + typedef stack_proxy reference_type; + typedef stack_proxy value_type; + typedef stack_proxy* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef stack_iterator<stack_proxy, false> iterator; + typedef stack_iterator<stack_proxy, true> const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + protected_function_result() noexcept : protected_function_result(nullptr) {} + protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept + : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) { + } + + // We do not want anyone to copy these around willy-nilly + // Will likely break people, but also will probably get rid of quiet bugs that have + // been lurking. (E.g., Vanilla Lua will just quietly discard over-pops and under-pops: + // LuaJIT and other Lua engines will implode and segfault at random later times.) + protected_function_result(const protected_function_result&) = delete; + protected_function_result& operator=(const protected_function_result&) = delete; + + protected_function_result(protected_function_result&& o) noexcept + : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.abandon(); + } + protected_function_result& operator=(protected_function_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.abandon(); + return *this; + } + + protected_function_result(const unsafe_function_result& o) = delete; + protected_function_result& operator=(const unsafe_function_result& o) = delete; + protected_function_result(unsafe_function_result&& o) noexcept; + protected_function_result& operator=(unsafe_function_result&& o) noexcept; + + call_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + + template <typename T> + decltype(auto) get(int index_offset = 0) const { + using UT = meta::unqualified_t<T>; + int target = index + index_offset; + if constexpr (meta::is_optional_v<UT>) { + using ValueType = typename UT::value_type; + if constexpr (std::is_same_v<ValueType, error>) { + if (valid()) { + return UT(); + } + return UT(error(detail::direct_error, stack::get<std::string>(L, target))); + } + else { + if (!valid()) { + return UT(); + } + return stack::get<UT>(L, target); + } + } + else { + if constexpr (std::is_same_v<T, error>) { +#if SOL_IS_ON(SOL_SAFE_PROXIES) + if (valid()) { + type t = type_of(L, target); + type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is an error)"); + } +#endif // Check Argument Safety + return error(detail::direct_error, stack::get<std::string>(L, target)); + } + else { +#if SOL_IS_ON(SOL_SAFE_PROXIES) + if (!valid()) { + type t = type_of(L, target); + type_panic_c_str(L, target, t, type::none, "bad get from protected_function_result (is not an error)"); + } +#endif // Check Argument Safety + return stack::get<T>(L, target); + } + } + } + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic pop +#endif + + type get_type(int index_offset = 0) const noexcept { + return type_of(L, index + static_cast<int>(index_offset)); + } + + stack_proxy operator[](difference_type index_offset) const { + return stack_proxy(L, index + static_cast<int>(index_offset)); + } + + iterator begin() { + return iterator(L, index, stack_index() + return_count()); + } + iterator end() { + return iterator(L, stack_index() + return_count(), stack_index() + return_count()); + } + const_iterator begin() const { + return const_iterator(L, index, stack_index() + return_count()); + } + const_iterator end() const { + return const_iterator(L, stack_index() + return_count(), stack_index() + return_count()); + } + const_iterator cbegin() const { + return begin(); + } + const_iterator cend() const { + return end(); + } + + reverse_iterator rbegin() { + return std::reverse_iterator<iterator>(begin()); + } + reverse_iterator rend() { + return std::reverse_iterator<iterator>(end()); + } + const_reverse_iterator rbegin() const { + return std::reverse_iterator<const_iterator>(begin()); + } + const_reverse_iterator rend() const { + return std::reverse_iterator<const_iterator>(end()); + } + const_reverse_iterator crbegin() const { + return std::reverse_iterator<const_iterator>(cbegin()); + } + const_reverse_iterator crend() const { + return std::reverse_iterator<const_iterator>(cend()); + } + + lua_State* lua_state() const noexcept { + return L; + }; + int stack_index() const noexcept { + return index; + }; + int return_count() const noexcept { + return returncount; + }; + int pop_count() const noexcept { + return popcount; + }; + void abandon() noexcept { + // L = nullptr; + index = 0; + returncount = 0; + popcount = 0; + err = call_status::runtime; + } + ~protected_function_result() { + if (L == nullptr) + return; + stack::remove(L, index, popcount); + } + }; + + namespace stack { + template <> + struct unqualified_pusher<protected_function_result> { + static int push(lua_State* L, const protected_function_result& pfr) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, static_cast<int>(pfr.pop_count()), detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + int p = 0; + for (int i = 0; i < pfr.pop_count(); ++i) { + lua_pushvalue(L, i + pfr.stack_index()); + ++p; + } + return p; + } + }; + } // namespace stack +} // namespace sol + +// end of sol/protected_function_result.hpp + +// beginning of sol/unsafe_function_result.hpp + +#include <cstdint> + +namespace sol { + struct unsafe_function_result : public proxy_base<unsafe_function_result> { + private: + lua_State* L; + int index; + int returncount; + + public: + typedef stack_proxy reference_type; + typedef stack_proxy value_type; + typedef stack_proxy* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef stack_iterator<stack_proxy, false> iterator; + typedef stack_iterator<stack_proxy, true> const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + unsafe_function_result() noexcept : unsafe_function_result(nullptr) {} + unsafe_function_result(lua_State* Ls, int idx = -1, int retnum = 0) noexcept : L(Ls), index(idx), returncount(retnum) { + } + + // We do not want anyone to copy these around willy-nilly + // Will likely break people, but also will probably get rid of quiet bugs that have + // been lurking. (E.g., Vanilla Lua will just quietly discard over-pops and under-pops: + // LuaJIT and other Lua engines will implode and segfault at random later times.) + unsafe_function_result(const unsafe_function_result&) = delete; + unsafe_function_result& operator=(const unsafe_function_result&) = delete; + + unsafe_function_result(unsafe_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.abandon(); + } + unsafe_function_result& operator=(unsafe_function_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.abandon(); + return *this; + } + + unsafe_function_result(const protected_function_result& o) = delete; + unsafe_function_result& operator=(const protected_function_result& o) = delete; + unsafe_function_result(protected_function_result&& o) noexcept; + unsafe_function_result& operator=(protected_function_result&& o) noexcept; + + template <typename T> + decltype(auto) get(difference_type index_offset = 0) const { + return stack::get<T>(L, index + static_cast<int>(index_offset)); + } + + type get_type(difference_type index_offset = 0) const noexcept { + return type_of(L, index + static_cast<int>(index_offset)); + } + + stack_proxy operator[](difference_type index_offset) const { + return stack_proxy(L, index + static_cast<int>(index_offset)); + } + + iterator begin() { + return iterator(L, index, stack_index() + return_count()); + } + iterator end() { + return iterator(L, stack_index() + return_count(), stack_index() + return_count()); + } + const_iterator begin() const { + return const_iterator(L, index, stack_index() + return_count()); + } + const_iterator end() const { + return const_iterator(L, stack_index() + return_count(), stack_index() + return_count()); + } + const_iterator cbegin() const { + return begin(); + } + const_iterator cend() const { + return end(); + } + + reverse_iterator rbegin() { + return std::reverse_iterator<iterator>(begin()); + } + reverse_iterator rend() { + return std::reverse_iterator<iterator>(end()); + } + const_reverse_iterator rbegin() const { + return std::reverse_iterator<const_iterator>(begin()); + } + const_reverse_iterator rend() const { + return std::reverse_iterator<const_iterator>(end()); + } + const_reverse_iterator crbegin() const { + return std::reverse_iterator<const_iterator>(cbegin()); + } + const_reverse_iterator crend() const { + return std::reverse_iterator<const_iterator>(cend()); + } + + call_status status() const noexcept { + return call_status::ok; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + lua_State* lua_state() const { + return L; + }; + int stack_index() const { + return index; + }; + int return_count() const { + return returncount; + }; + void abandon() noexcept { + // L = nullptr; + index = 0; + returncount = 0; + } + ~unsafe_function_result() { + if (L != nullptr) { + lua_pop(L, returncount); + } + } + }; + + namespace stack { + template <> + struct unqualified_pusher<unsafe_function_result> { + static int push(lua_State* L, const unsafe_function_result& fr) { + int p = 0; + for (int i = 0; i < fr.return_count(); ++i) { + lua_pushvalue(L, i + fr.stack_index()); + ++p; + } + return p; + } + }; + } // namespace stack +} // namespace sol + +// end of sol/unsafe_function_result.hpp + +#include <cstdint> + +namespace sol { + + namespace detail { + template <> + struct is_speshul<unsafe_function_result> : std::true_type { }; + template <> + struct is_speshul<protected_function_result> : std::true_type { }; + + template <std::size_t I, typename... Args, typename T> + stack_proxy get(types<Args...>, meta::index_value<0>, meta::index_value<I>, const T& fr) { + return stack_proxy(fr.lua_state(), fr.stack_index() + static_cast<int>(I)); + } + + template <std::size_t I, std::size_t N, typename Arg, typename... Args, typename T, meta::enable<meta::boolean<(N > 0)>> = meta::enabler> + stack_proxy get(types<Arg, Args...>, meta::index_value<N>, meta::index_value<I>, const T& fr) { + return get(types<Args...>(), meta::index_value<N - 1>(), meta::index_value<I + lua_size<Arg>::value>(), fr); + } + } // namespace detail + + template <> + struct tie_size<unsafe_function_result> : std::integral_constant<std::size_t, SIZE_MAX> { }; + + template <> + struct tie_size<protected_function_result> : std::integral_constant<std::size_t, SIZE_MAX> { }; + + template <std::size_t I> + stack_proxy get(const unsafe_function_result& fr) { + return stack_proxy(fr.lua_state(), fr.stack_index() + static_cast<int>(I)); + } + + template <std::size_t I, typename... Args> + stack_proxy get(types<Args...> t, const unsafe_function_result& fr) { + return detail::get(t, meta::index_value<I>(), meta::index_value<0>(), fr); + } + + template <std::size_t I> + stack_proxy get(const protected_function_result& fr) { + return stack_proxy(fr.lua_state(), fr.stack_index() + static_cast<int>(I)); + } + + template <std::size_t I, typename... Args> + stack_proxy get(types<Args...> t, const protected_function_result& fr) { + return detail::get(t, meta::index_value<I>(), meta::index_value<0>(), fr); + } +} // namespace sol + +// end of sol/function_result.hpp + +// beginning of sol/function_types.hpp + +// beginning of sol/function_types_core.hpp + +// beginning of sol/wrapper.hpp + +namespace sol { + + namespace detail { + template <typename T> + using array_return_type = meta::conditional_t<std::is_array<T>::value, std::add_lvalue_reference_t<T>, T>; + } + + template <typename F, typename = void> + struct wrapper { + typedef lua_bind_traits<meta::unqualified_t<F>> traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template <typename... Args> + static decltype(auto) call(F& f, Args&&... args) { + return f(std::forward<Args>(args)...); + } + + struct caller { + template <typename... Args> + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward<Args>(args)...); + } + }; + }; + + template <typename F> + struct wrapper<F, std::enable_if_t<std::is_function<std::remove_pointer_t<meta::unqualified_t<F>>>::value>> { + typedef lua_bind_traits<std::remove_pointer_t<meta::unqualified_t<F>>> traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template <F fx, typename... Args> + static decltype(auto) invoke(Args&&... args) { + return fx(std::forward<Args>(args)...); + } + + template <typename... Args> + static decltype(auto) call(F& fx, Args&&... args) { + return fx(std::forward<Args>(args)...); + } + + struct caller { + template <typename... Args> + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward<Args>(args)...); + } + }; + + template <F fx> + struct invoker { + template <typename... Args> + decltype(auto) operator()(Args&&... args) const { + return invoke<fx>(std::forward<Args>(args)...); + } + }; + }; + + template <typename F> + struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> { + typedef lua_bind_traits<meta::unqualified_t<F>> traits_type; + typedef typename traits_type::object_type object_type; + typedef typename traits_type::return_type return_type; + typedef typename traits_type::args_list args_list; + typedef types<object_type&, return_type> free_args_list; + typedef typename traits_type::returns_list returns_list; + + template <F fx> + static auto call(object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> { + return mem.*fx; + } + + template <F fx, typename Arg, typename... Args> + static decltype(auto) invoke(object_type& mem, Arg&& arg, Args&&...) { + return mem.*fx = std::forward<Arg>(arg); + } + + template <typename Fx> + static auto call(Fx&& fx, object_type& mem) -> detail::array_return_type<decltype(mem.*fx)> { + return mem.*fx; + } + + template <typename Fx, typename Arg, typename... Args> + static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { + using actual_type = meta::unqualified_t<detail::array_return_type<decltype(mem.*fx)>>; + if constexpr (std::is_array_v<actual_type>) { + using std::cbegin; + using std::cend; + auto first = cbegin(arg); + auto last = cend(arg); + for (std::size_t i = 0; first != last; ++i, ++first) { + (mem.*fx)[i] = *first; + } + } + else { + (mem.*fx) = std::forward<Arg>(arg); + } + } + + struct caller { + template <typename Fx, typename... Args> + decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { + return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); + } + }; + + template <F fx> + struct invoker { + template <typename... Args> + decltype(auto) operator()(Args&&... args) const { + return invoke<fx>(std::forward<Args>(args)...); + } + }; + }; + + template <typename F, typename R, typename O, typename... FArgs> + struct member_function_wrapper { + typedef O object_type; + typedef lua_bind_traits<F> traits_type; + typedef typename traits_type::args_list args_list; + typedef types<object_type&, FArgs...> free_args_list; + typedef meta::tuple_types<R> returns_list; + + template <F fx, typename... Args> + static R invoke(O& mem, Args&&... args) { + return (mem.*fx)(std::forward<Args>(args)...); + } + + template <typename Fx, typename... Args> + static R call(Fx&& fx, O& mem, Args&&... args) { + return (mem.*fx)(std::forward<Args>(args)...); + } + + struct caller { + template <typename Fx, typename... Args> + decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { + return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); + } + }; + + template <F fx> + struct invoker { + template <typename... Args> + decltype(auto) operator()(O& mem, Args&&... args) const { + return invoke<fx>(mem, std::forward<Args>(args)...); + } + }; + }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...)> : public member_function_wrapper<R (O::*)(Args...), R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const> : public member_function_wrapper<R (O::*)(Args...) const, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const volatile> : public member_function_wrapper<R (O::*)(Args...) const volatile, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...)&> : public member_function_wrapper<R (O::*)(Args...)&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const&> : public member_function_wrapper<R (O::*)(Args...) const&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const volatile&> : public member_function_wrapper<R (O::*)(Args...) const volatile&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...)&> : public member_function_wrapper<R (O::*)(Args..., ...)&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const&> : public member_function_wrapper<R (O::*)(Args..., ...) const&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const volatile&> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) &&> : public member_function_wrapper<R (O::*)(Args...)&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const&&> : public member_function_wrapper<R (O::*)(Args...) const&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const volatile&&> : public member_function_wrapper<R (O::*)(Args...) const volatile&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) &&> : public member_function_wrapper<R (O::*)(Args..., ...)&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const&&> : public member_function_wrapper<R (O::*)(Args..., ...) const&, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const volatile&&> : public member_function_wrapper<R (O::*)(Args..., ...) const volatile&, R, O, Args...> { }; + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + // noexcept has become a part of a function's type + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) noexcept> : public member_function_wrapper<R (O::*)(Args...) noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const noexcept> : public member_function_wrapper<R (O::*)(Args...) const noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const volatile noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...)& noexcept> : public member_function_wrapper<R (O::*)(Args...)& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const& noexcept> : public member_function_wrapper<R (O::*)(Args...) const& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const volatile& noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...)& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...)& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const volatile& noexcept> + : public member_function_wrapper<R (O::*)(Args..., ...) const volatile& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...)&& noexcept> : public member_function_wrapper<R (O::*)(Args...)& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const&& noexcept> : public member_function_wrapper<R (O::*)(Args...) const& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args...) const volatile&& noexcept> : public member_function_wrapper<R (O::*)(Args...) const volatile& noexcept, R, O, Args...> { + }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...)&& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...)& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const&& noexcept> : public member_function_wrapper<R (O::*)(Args..., ...) const& noexcept, R, O, Args...> { }; + + template <typename R, typename O, typename... Args> + struct wrapper<R (O::*)(Args..., ...) const volatile&& noexcept> + : public member_function_wrapper<R (O::*)(Args..., ...) const volatile& noexcept, R, O, Args...> { }; + +#endif // noexcept is part of a function's type + +} // namespace sol + +// end of sol/wrapper.hpp + +#include <memory> + +namespace sol { namespace function_detail { + template <typename Fx, int start = 1, bool is_yielding = false> + int call(lua_State* L) { + Fx& fx = stack::get<user<Fx>>(L, upvalue_index(start)); + int nr = fx(L); + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } +}} // namespace sol::function_detail + +// end of sol/function_types_core.hpp + +// beginning of sol/function_types_templated.hpp + +// beginning of sol/call.hpp + +// beginning of sol/property.hpp + +#include <type_traits> +#include <utility> + +namespace sol { + namespace detail { + struct no_prop { }; + } // namespace detail + + template <typename R, typename W> + struct property_wrapper : detail::ebco<R, 0>, detail::ebco<W, 1> { + private: + using read_base_t = detail::ebco<R, 0>; + using write_base_t = detail::ebco<W, 1>; + + public: + template <typename Rx, typename Wx> + property_wrapper(Rx&& r, Wx&& w) : read_base_t(std::forward<Rx>(r)), write_base_t(std::forward<Wx>(w)) { + } + + W& write() { + return write_base_t::value(); + } + + const W& write() const { + return write_base_t::value(); + } + + R& read() { + return read_base_t::value(); + } + + const R& read() const { + return read_base_t::value(); + } + }; + + template <typename F, typename G> + inline decltype(auto) property(F&& f, G&& g) { + typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; + typedef lua_bind_traits<meta::unqualified_t<G>> right_traits; + if constexpr (left_traits::free_arity < right_traits::free_arity) { + return property_wrapper<std::decay_t<F>, std::decay_t<G>>(std::forward<F>(f), std::forward<G>(g)); + } + else { + return property_wrapper<std::decay_t<G>, std::decay_t<F>>(std::forward<G>(g), std::forward<F>(f)); + } + } + + template <typename F> + inline decltype(auto) property(F&& f) { + typedef lua_bind_traits<meta::unqualified_t<F>> left_traits; + if constexpr (left_traits::free_arity < 2) { + return property_wrapper<std::decay_t<F>, detail::no_prop>(std::forward<F>(f), detail::no_prop()); + } + else { + return property_wrapper<detail::no_prop, std::decay_t<F>>(detail::no_prop(), std::forward<F>(f)); + } + } + + template <typename F> + inline decltype(auto) readonly_property(F&& f) { + return property_wrapper<std::decay_t<F>, detail::no_prop>(std::forward<F>(f), detail::no_prop()); + } + + template <typename F> + inline decltype(auto) writeonly_property(F&& f) { + return property_wrapper<detail::no_prop, std::decay_t<F>>(detail::no_prop(), std::forward<F>(f)); + } + + template <typename T> + struct readonly_wrapper : detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using base_t::base_t; + + operator T&() { + return base_t::value(); + } + operator const T&() const { + return base_t::value(); + } + }; + + // Allow someone to make a member variable readonly (const) + template <typename R, typename T> + inline auto readonly(R T::*v) { + return readonly_wrapper<meta::unqualified_t<decltype(v)>>(v); + } + + template <typename T> + struct var_wrapper : detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using base_t::base_t; + }; + + template <typename V> + inline auto var(V&& v) { + typedef std::decay_t<V> T; + return var_wrapper<T>(std::forward<V>(v)); + } + + namespace meta { + template <typename T> + using is_member_object = std::integral_constant<bool, std::is_member_object_pointer_v<T> || is_specialization_of_v<T, readonly_wrapper>>; + + template <typename T> + inline constexpr bool is_member_object_v = is_member_object<T>::value; + + template <typename T> + using is_member_object_or_function = std::integral_constant<bool, is_member_object_v<T> || std::is_member_pointer_v<T>>; + + template <typename T> + inline constexpr bool is_member_object_or_function_v = is_member_object_or_function<T>::value; + } // namespace meta + +} // namespace sol + +// end of sol/property.hpp + +// beginning of sol/protect.hpp + +#include <utility> + +namespace sol { + + template <typename T> + struct protect_t { + T value; + + template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler> + protect_t(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) { + } + + protect_t(const protect_t&) = default; + protect_t(protect_t&&) = default; + protect_t& operator=(const protect_t&) = default; + protect_t& operator=(protect_t&&) = default; + }; + + template <typename T> + auto protect(T&& value) { + return protect_t<std::decay_t<T>>(std::forward<T>(value)); + } + +} // namespace sol + +// end of sol/protect.hpp + +namespace sol { + namespace u_detail { + + } // namespace u_detail + + namespace policy_detail { + template <int I, int... In> + inline void handle_policy(static_stack_dependencies<I, In...>, lua_State* L, int&) { + if constexpr (sizeof...(In) == 0) { + (void)L; + return; + } + else { + absolute_index ai(L, I); + if (type_of(L, ai) != type::userdata) { + return; + } + lua_createtable(L, static_cast<int>(sizeof...(In)), 0); + stack_reference deps(L, -1); + auto per_dep = [&L, &deps](int i) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushvalue(L, i); + luaL_ref(L, deps.stack_index()); + }; + (void)per_dep; + (void)detail::swallow { int(), (per_dep(In), int())... }; + lua_setuservalue(L, ai); + } + } + + template <int... In> + inline void handle_policy(returns_self_with<In...>, lua_State* L, int& pushed) { + pushed = stack::push(L, raw_index(1)); + handle_policy(static_stack_dependencies<-1, In...>(), L, pushed); + } + + inline void handle_policy(const stack_dependencies& sdeps, lua_State* L, int&) { + absolute_index ai(L, sdeps.target); + if (type_of(L, ai) != type::userdata) { + return; + } + lua_createtable(L, static_cast<int>(sdeps.size()), 0); + stack_reference deps(L, -1); +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, static_cast<int>(sdeps.size()), detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + for (std::size_t i = 0; i < sdeps.size(); ++i) { + lua_pushvalue(L, sdeps.stack_indices[i]); + luaL_ref(L, deps.stack_index()); + } + lua_setuservalue(L, ai); + } + + template <typename P, meta::disable<std::is_base_of<detail::policy_base_tag, meta::unqualified_t<P>>> = meta::enabler> + inline void handle_policy(P&& p, lua_State* L, int& pushed) { + pushed = std::forward<P>(p)(L, pushed); + } + } // namespace policy_detail + + namespace function_detail { + inline int no_construction_error(lua_State* L) { + return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); + } + } // namespace function_detail + + namespace call_detail { + + template <typename R, typename W> + inline auto& pick(std::true_type, property_wrapper<R, W>& f) { + return f.read(); + } + + template <typename R, typename W> + inline auto& pick(std::false_type, property_wrapper<R, W>& f) { + return f.write(); + } + + template <typename T, typename List> + struct void_call : void_call<T, meta::function_args_t<List>> { }; + + template <typename T, typename... Args> + struct void_call<T, types<Args...>> { + static void call(Args...) { + } + }; + + template <typename T, bool checked, bool clean_stack> + struct constructor_match { + T* obj_; + reference* obj_lua_ref_; + stack::stack_detail::undefined_metatable* p_umf_; + + constructor_match(T* obj_ptr, reference& obj_lua_ref, stack::stack_detail::undefined_metatable& umf) + : obj_(obj_ptr), obj_lua_ref_(&obj_lua_ref), p_umf_(&umf) { + } + + template <typename Fx, std::size_t I, typename... R, typename... Args> + int operator()(types<Fx>, meta::index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start) const { + detail::default_construct func {}; + int result = stack::call_into_lua<checked, clean_stack>(r, a, L, start, func, this->obj_); + // construct userdata table + // SPECIFICALLY, after we've created it successfully. + // If the constructor exits for any reason we have to break things down... + if constexpr (clean_stack) { + obj_lua_ref_->push(); + (*this->p_umf_)(); + obj_lua_ref_->pop(); + } + else { + (*this->p_umf_)(); + } + return result; + } + }; + + namespace overload_detail { + template <std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence<M...>, Match&&, lua_State* L, int, int, Args&&...) { + return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); + } + + template <typename Fx, typename... Fxs, std::size_t I, std::size_t... In, std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, + int fxarity, int start, Args&&... args) { + typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits; + typedef meta::tuple_types<typename traits::return_type> return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) { + return overload_match_arity(types<Fxs...>(), + std::index_sequence<In...>(), + std::index_sequence<M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + else { + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types<Fxs...>(), + std::index_sequence<In...>(), + std::index_sequence<traits::free_arity, M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + } + stack::record tracking {}; + if (!stack::stack_detail::check_types(args_list(), L, start, &no_panic, tracking)) { + return overload_match_arity(types<Fxs...>(), + std::index_sequence<In...>(), + std::index_sequence<M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); + } + } + + template <std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity_single( + types<>, std::index_sequence<>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence<M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + + template <typename Fx, std::size_t I, std::size_t... M, typename Match, typename... Args> + inline int overload_match_arity_single( + types<Fx>, std::index_sequence<I>, std::index_sequence<M...>, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits; + typedef meta::tuple_types<typename traits::return_type> return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence<M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types<>(), + std::index_sequence<>(), + std::index_sequence<traits::free_arity, M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + } + return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); + } + + template <typename Fx, typename Fx1, typename... Fxs, std::size_t I, std::size_t I1, std::size_t... In, std::size_t... M, typename Match, + typename... Args> + inline int overload_match_arity_single(types<Fx, Fx1, Fxs...>, std::index_sequence<I, I1, In...>, std::index_sequence<M...>, Match&& matchfx, + lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits<meta::unwrap_unqualified_t<Fx>> traits; + typedef meta::tuple_types<typename traits::return_type> return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if constexpr (!traits::runtime_variadics_t::value + && meta::find_in_pack_v<meta::index_value<traits::free_arity>, meta::index_value<M>...>::value) { + return overload_match_arity(types<Fx1, Fxs...>(), + std::index_sequence<I1, In...>(), + std::index_sequence<M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + else { + if constexpr (!traits::runtime_variadics_t::value) { + if (traits::free_arity != fxarity) { + return overload_match_arity(types<Fx1, Fxs...>(), + std::index_sequence<I1, In...>(), + std::index_sequence<traits::free_arity, M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + } + stack::record tracking {}; + if (!stack::stack_detail::check_types(args_list(), L, start, &no_panic, tracking)) { + return overload_match_arity(types<Fx1, Fxs...>(), + std::index_sequence<I1, In...>(), + std::index_sequence<M...>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + return matchfx(types<Fx>(), meta::index_value<I>(), return_types(), args_list(), L, fxarity, start, std::forward<Args>(args)...); + } + } + } // namespace overload_detail + + template <typename... Functions, typename Match, typename... Args> + inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_detail::overload_match_arity_single(types<Functions...>(), + std::make_index_sequence<sizeof...(Functions)>(), + std::index_sequence<>(), + std::forward<Match>(matchfx), + L, + fxarity, + start, + std::forward<Args>(args)...); + } + + template <typename... Functions, typename Match, typename... Args> + inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { + int fxarity = lua_gettop(L) - (start - 1); + return overload_match_arity<Functions...>(std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + + template <typename T, typename... TypeLists, typename Match, typename... Args> + inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + // use same overload resolution matching as all other parts of the framework + return overload_match_arity<decltype(void_call<T, TypeLists>::call)...>( + std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...); + } + + template <typename T, bool checked, bool clean_stack, typename... TypeLists> + inline int construct_trampolined(lua_State* L) { + static const auto& meta = usertype_traits<T>::metatable(); + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot; + argcount -= static_cast<int>(syntax); + + T* obj = detail::usertype_allocate<T>(L); + reference userdataref(L, -1); + stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>); + + // put userdata at the first index + lua_insert(L, 1); + construct_match<T, TypeLists...>(constructor_match<T, checked, clean_stack>(obj, userdataref, umf), L, argcount, 1 + static_cast<int>(syntax)); + + userdataref.push(); + return 1; + } + + template <typename T, bool checked, bool clean_stack, typename... TypeLists> + inline int construct(lua_State* L) { + return detail::static_trampoline<&construct_trampolined<T, checked, clean_stack, TypeLists...>>(L); + } + + template <typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename = void> + struct agnostic_lua_call_wrapper { + template <typename Fx, typename... Args> + static int call(lua_State* L, Fx&& f, Args&&... args) { + using uFx = meta::unqualified_t<Fx>; + static constexpr bool is_ref = is_lua_reference_v<uFx>; + if constexpr (is_ref) { + if constexpr (is_index) { + return stack::push(L, std::forward<Fx>(f), std::forward<Args>(args)...); + } + else { + std::forward<Fx>(f) = stack::unqualified_get<F>(L, boost + (is_variable ? 3 : 1)); + return 0; + } + } + else { + using wrap = wrapper<uFx>; + using traits_type = typename wrap::traits_type; + using fp_t = typename traits_type::function_pointer_type; + constexpr bool is_function_pointer_convertible = std::is_class_v<uFx> && std::is_convertible_v<std::decay_t<Fx>, fp_t>; + if constexpr (is_function_pointer_convertible) { + fp_t fx = f; + return agnostic_lua_call_wrapper<fp_t, is_index, is_variable, checked, boost, clean_stack> {}.call( + L, fx, std::forward<Args>(args)...); + } + else { + using returns_list = typename wrap::returns_list; + using args_list = typename wrap::free_args_list; + using caller = typename wrap::caller; + return stack::call_into_lua<checked, clean_stack>( + returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f), std::forward<Args>(args)...); + } + } + } + }; + + template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<var_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> { + template <typename F> + static int call(lua_State* L, F&& f) { + if constexpr (is_index) { + constexpr bool is_stack = is_stack_based_v<meta::unqualified_t<decltype(detail::unwrap(f.value()))>>; + if constexpr (clean_stack && !is_stack) { + lua_settop(L, 0); + } + return stack::push_reference(L, detail::unwrap(f.value())); + } + else { + if constexpr (std::is_const_v<meta::unwrapped_t<T>>) { + (void)f; + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using R = meta::unwrapped_t<T>; + if constexpr (std::is_assignable_v<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>) { + detail::unwrap(f.value()) = stack::unqualified_get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1)); + if (clean_stack) { + lua_settop(L, 0); + } + return 0; + } + else { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + } + } + } + }; + + template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<lua_CFunction_ref, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, lua_CFunction_ref f) { + return f(L); + } + }; + + template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, lua_CFunction f) { + return f(L); + } + }; + +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<detail::lua_CFunction_noexcept, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, detail::lua_CFunction_noexcept f) { + return f(L); + } + }; +#endif // noexcept function types + + template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<detail::no_prop, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, const detail::no_prop&) { + return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); + } + }; + + template <bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, const no_construction&) { + return function_detail::no_construction_error(L); + } + }; + + template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State*, const bases<Args...>&) { + // Uh. How did you even call this, lul + return 0; + } + }; + + template <typename T, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct agnostic_lua_call_wrapper<std::reference_wrapper<T>, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, std::reference_wrapper<T> f) { + agnostic_lua_call_wrapper<T, is_index, is_variable, checked, boost, clean_stack> alcw {}; + return alcw.call(L, f.get()); + } + }; + + template <typename T, typename F, bool is_index, bool is_variable, bool checked = detail::default_safe_function_calls, int boost = 0, + bool clean_stack = true, typename = void> + struct lua_call_wrapper { + template <typename Fx, typename... Args> + static int call(lua_State* L, Fx&& fx, Args&&... args) { + if constexpr (std::is_member_function_pointer_v<F>) { + using wrap = wrapper<F>; + using object_type = typename wrap::object_type; + if constexpr (sizeof...(Args) < 1) { + using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>; + static_assert(std::is_base_of_v<object_type, Ta>, + "It seems like you might have accidentally bound a class type with a member function method that does not correspond to the " + "class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one class \"T\" " + "but then bind member methods from a complete unrelated class. Check things over!"); +#if SOL_IS_ON(SOL_SAFE_USERTYPE) + auto maybeo = stack::check_get<Ta*>(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + return luaL_error(L, + "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are " + "preceeded by the " + "actual object with '.' syntax)"); + } + object_type* o = static_cast<object_type*>(maybeo.value()); + return call(L, std::forward<Fx>(fx), *o); +#else + object_type& o = static_cast<object_type&>(*stack::unqualified_get<non_null<Ta*>>(L, 1)); + return call(L, std::forward<Fx>(fx), o); +#endif // Safety + } + else { + using returns_list = typename wrap::returns_list; + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + return stack::call_into_lua<checked, clean_stack>( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + else if constexpr (std::is_member_object_pointer_v<F>) { + using wrap = wrapper<F>; + using object_type = typename wrap::object_type; + if constexpr (is_index) { + if constexpr (sizeof...(Args) < 1) { + using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>; + static_assert(std::is_base_of_v<object_type, Ta>, + "It seems like you might have accidentally bound a class type with a member function method that does not correspond " + "to the class. For example, there could be a small type in your new_usertype<T>(...) binding, where you specify one " + "class \"T\" but then bind member methods from a complete unrelated class. Check things over!"); +#if SOL_IS_ON(SOL_SAFE_USERTYPE) + auto maybeo = stack::check_get<Ta*>(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); + } + object_type* o = static_cast<object_type*>(maybeo.value()); + return call(L, std::forward<Fx>(fx), *o); +#else + object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); + return call(L, std::forward<Fx>(fx), o); +#endif // Safety + } + else { + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + return stack::call_into_lua<checked, clean_stack>(returns_list(), + types<>(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward<Fx>(fx), + std::forward<Args>(args)...); + } + } + else { + using traits_type = lua_bind_traits<F>; + using return_type = typename traits_type::return_type; + constexpr bool ret_is_const = std::is_const_v<std::remove_reference_t<return_type>>; + if constexpr (ret_is_const) { + (void)fx; + (void)detail::swallow { 0, (static_cast<void>(args), 0)... }; + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using u_return_type = meta::unqualified_t<return_type>; + constexpr bool is_assignable = std::is_copy_assignable_v<u_return_type> || std::is_array_v<u_return_type>; + if constexpr (!is_assignable) { + (void)fx; + (void)detail::swallow { 0, ((void)args, 0)... }; + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + else { + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + if constexpr (sizeof...(Args) > 0) { + return stack::call_into_lua<checked, clean_stack>(types<void>(), + args_list(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward<Fx>(fx), + std::forward<Args>(args)...); + } + else { + using Ta = meta::conditional_t<std::is_void_v<T>, object_type, T>; +#if SOL_IS_ON(SOL_SAFE_USERTYPE) + auto maybeo = stack::check_get<Ta*>(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); + } + return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + } + object_type* po = static_cast<object_type*>(maybeo.value()); + object_type& o = *po; +#else + object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1)); +#endif // Safety + + return stack::call_into_lua<checked, clean_stack>( + types<void>(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), o); + } + } + } + } + } + else { + agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost, clean_stack> alcw {}; + return alcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + }; + + template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, readonly_wrapper<F>, is_index, is_variable, checked, boost, clean_stack, C> { + using traits_type = lua_bind_traits<F>; + using wrap = wrapper<F>; + using object_type = typename wrap::object_type; + + static int call(lua_State* L, readonly_wrapper<F>&& rw) { + if constexpr (!is_index) { + (void)rw; + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + else { + lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw; + return lcw.call(L, std::move(rw.value())); + } + } + + static int call(lua_State* L, readonly_wrapper<F>&& rw, object_type& o) { + if constexpr (!is_index) { + (void)o; + return call(L, std::move(rw)); + } + else { + lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw; + return lcw.call(L, rw.value(), o); + } + } + + static int call(lua_State* L, const readonly_wrapper<F>& rw) { + if constexpr (!is_index) { + (void)rw; + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + else { + lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw; + return lcw.call(L, rw.value()); + } + } + + static int call(lua_State* L, const readonly_wrapper<F>& rw, object_type& o) { + if constexpr (!is_index) { + (void)o; + return call(L, rw); + } + else { + lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw; + return lcw.call(L, rw.value(), o); + } + } + }; + + template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, constructor_list<Args...>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef constructor_list<Args...> F; + + static int call(lua_State* L, F&) { + const auto& meta = usertype_traits<T>::metatable(); + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1) : call_syntax::dot; + argcount -= static_cast<int>(syntax); + + T* obj = detail::usertype_allocate<T>(L); + reference userdataref(L, -1); + stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>); + + // put userdata at the first index + lua_insert(L, 1); + // Because of the way constructors work, + // we have to kill the data, but only if the cosntructor is successfulyl invoked... + // if it's not successfully invoked and we panic, + // we cannot actually deallcoate/delete the data. + construct_match<T, Args...>( + constructor_match<T, checked, clean_stack>(obj, userdataref, umf), L, argcount, boost + 1 + 1 + static_cast<int>(syntax)); + + userdataref.push(); + return 1; + } + }; + + template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef constructor_wrapper<Cxs...> F; + + struct onmatch { + template <typename Fx, std::size_t I, typename... R, typename... Args> + int operator()(types<Fx>, meta::index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) { + const auto& meta = usertype_traits<T>::metatable(); + T* obj = detail::usertype_allocate<T>(L); + reference userdataref(L, -1); + stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>); + umf(); + + auto& func = std::get<I>(f.functions); + // put userdata at the first index + lua_insert(L, 1); + stack::call_into_lua<checked, clean_stack>(r, a, L, boost + 1 + start, func, detail::implicit_wrapper<T>(obj)); + + userdataref.push(); + return 1; + } + }; + + static int call(lua_State* L, F& f) { + call_syntax syntax = stack::get_call_syntax(L, usertype_traits<T>::user_metatable(), 1); + int syntaxval = static_cast<int>(syntax); + int argcount = lua_gettop(L) - syntaxval; + return construct_match<T, meta::pop_front_type_t<meta::function_args_t<Cxs>>...>(onmatch(), L, argcount, 1 + syntaxval, f); + } + }; + + template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, destructor_wrapper<Fx>, is_index, is_variable, checked, boost, clean_stack, C> { + + template <typename F> + static int call(lua_State* L, F&& f) { + if constexpr (std::is_void_v<Fx>) { + return detail::usertype_alloc_destroy<T>(L); + } + else { + using uFx = meta::unqualified_t<Fx>; + lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, std::forward<F>(f).fx); + } + } + }; + + template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef overload_set<Fs...> F; + + struct on_match { + template <typename Fx, std::size_t I, typename... R, typename... Args> + int operator()(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { + auto& f = std::get<I>(fx.functions); + return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost> {}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, factory_wrapper<Fs...>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef factory_wrapper<Fs...> F; + + struct on_match { + template <typename Fx, std::size_t I, typename... R, typename... Args> + int operator()(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, F& fx) { + auto& f = std::get<I>(fx.functions); + return lua_call_wrapper<T, Fx, is_index, is_variable, checked, boost, clean_stack> {}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity<Fs...>(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx); + } + }; + + template <typename T, typename R, typename W, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, property_wrapper<R, W>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef meta::conditional_t<is_index, R, W> P; + typedef meta::unqualified_t<P> U; + typedef wrapper<U> wrap; + typedef lua_bind_traits<U> traits_type; + typedef meta::unqualified_t<typename traits_type::template arg_at<0>> object_type; + + template <typename F, typename... Args> + static int call(lua_State* L, F&& f, Args&&... args) { + constexpr bool is_specialized = meta::any<std::is_same<U, detail::no_prop>, + meta::is_specialization_of<U, var_wrapper>, + meta::is_specialization_of<U, constructor_wrapper>, + meta::is_specialization_of<U, constructor_list>, + std::is_member_pointer<U>>::value; + if constexpr (is_specialized) { + if constexpr (is_index) { + decltype(auto) p = f.read(); + lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, p, std::forward<Args>(args)...); + } + else { + decltype(auto) p = f.write(); + lua_call_wrapper<T, meta::unqualified_t<decltype(p)>, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, p, std::forward<Args>(args)...); + } + } + else { + constexpr bool non_class_object_type = meta::any<std::is_void<object_type>, + meta::boolean<lua_type_of<meta::unwrap_unqualified_t<object_type>>::value != type::userdata>>::value; + if constexpr (non_class_object_type) { + // The type being void means we don't have any arguments, so it might be a free functions? + using args_list = typename traits_type::free_args_list; + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + if constexpr (is_index) { + decltype(auto) pf = f.read(); + return stack::call_into_lua<checked, clean_stack>( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf); + } + else { + decltype(auto) pf = f.write(); + return stack::call_into_lua<checked, clean_stack>( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf); + } + } + else { + using args_list = meta::pop_front_type_t<typename traits_type::free_args_list>; + using Ta = T; + using Oa = std::remove_pointer_t<object_type>; +#if SOL_IS_ON(SOL_SAFE_USERTYPE) + auto maybeo = stack::check_get<Ta*>(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); + } + Oa* o = static_cast<Oa*>(maybeo.value()); +#else + Oa* o = static_cast<Oa*>(stack::get<non_null<Ta*>>(L, 1)); +#endif // Safety + using returns_list = typename wrap::returns_list; + using caller = typename wrap::caller; + if constexpr (is_index) { + decltype(auto) pf = f.read(); + return stack::call_into_lua<checked, clean_stack>( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper<Oa>(*o)); + } + else { + decltype(auto) pf = f.write(); + return stack::call_into_lua<checked, clean_stack>( + returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), pf, detail::implicit_wrapper<Oa>(*o)); + } + } + } + } + }; + + template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef protect_t<V> F; + + template <typename... Args> + static int call(lua_State* L, F& fx, Args&&... args) { + return lua_call_wrapper<T, V, is_index, is_variable, true, boost, clean_stack> {}.call(L, fx.value, std::forward<Args>(args)...); + } + }; + + template <typename T, typename F, typename... Policies, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, policy_wrapper<F, Policies...>, is_index, is_variable, checked, boost, clean_stack, C> { + typedef policy_wrapper<F, Policies...> P; + + template <std::size_t... In> + static int call(std::index_sequence<In...>, lua_State* L, P& fx) { + int pushed = lua_call_wrapper<T, F, is_index, is_variable, checked, boost, false, C> {}.call(L, fx.value); + (void)detail::swallow { int(), (policy_detail::handle_policy(std::get<In>(fx.policies), L, pushed), int())... }; + return pushed; + } + + static int call(lua_State* L, P& fx) { + typedef typename P::indices indices; + return call(indices(), L, fx); + } + }; + + template <typename T, typename Y, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, yielding_t<Y>, is_index, is_variable, checked, boost, clean_stack, C> { + template <typename F> + static int call(lua_State* L, F&& f) { + return lua_call_wrapper<T, meta::unqualified_t<Y>, is_index, is_variable, checked, boost, clean_stack> {}.call(L, f.func); + } + }; + + template <typename T, typename Sig, typename P, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C> + struct lua_call_wrapper<T, function_arguments<Sig, P>, is_index, is_variable, checked, boost, clean_stack, C> { + static int call(lua_State* L, const function_arguments<Sig, P>& f) { + lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, std::get<0>(f.arguments)); + } + + static int call(lua_State* L, function_arguments<Sig, P>& f) { + lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, std::get<0>(f.arguments)); + } + + static int call(lua_State* L, function_arguments<Sig, P>&& f) { + lua_call_wrapper<T, meta::unqualified_t<P>, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, std::get<0>(std::move(f.arguments))); + } + }; + + template <typename T, bool is_index, bool is_variable, int boost = 0, bool checked = detail::default_safe_function_calls, bool clean_stack = true, + typename Fx, typename... Args> + inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { + using uFx = meta::unqualified_t<Fx>; + if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) { + using real_fx = meta::unqualified_t<decltype(std::forward<Fx>(fx).func)>; + lua_call_wrapper<T, real_fx, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, std::forward<Fx>(fx).func, std::forward<Args>(args)...); + } + else { + lua_call_wrapper<T, uFx, is_index, is_variable, checked, boost, clean_stack> lcw {}; + return lcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + + template <typename T, bool is_index, bool is_variable, typename F, int start = 1, bool checked = detail::default_safe_function_calls, + bool clean_stack = true> + inline int call_user(lua_State* L) { + auto& fx = stack::unqualified_get<user<F>>(L, upvalue_index(start)); + using uFx = meta::unqualified_t<F>; + int nr = call_wrapped<T, is_index, is_variable, 0, checked, clean_stack>(L, fx); + if constexpr (meta::is_specialization_of_v<uFx, yielding_t>) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + template <typename T, typename = void> + struct is_var_bind : std::false_type { }; + + template <typename T> + struct is_var_bind<T, std::enable_if_t<std::is_member_object_pointer<T>::value>> : std::true_type { }; + + template <typename T> + struct is_var_bind<T, std::enable_if_t<is_lua_reference_or_proxy<T>::value>> : std::true_type { }; + + template <> + struct is_var_bind<detail::no_prop> : std::true_type { }; + + template <typename R, typename W> + struct is_var_bind<property_wrapper<R, W>> : std::true_type { }; + + template <typename T> + struct is_var_bind<var_wrapper<T>> : std::true_type { }; + + template <typename T> + struct is_var_bind<readonly_wrapper<T>> : is_var_bind<meta::unqualified_t<T>> { }; + + template <typename F, typename... Policies> + struct is_var_bind<policy_wrapper<F, Policies...>> : is_var_bind<meta::unqualified_t<F>> { }; + } // namespace call_detail + + template <typename T> + struct is_variable_binding : call_detail::is_var_bind<meta::unqualified_t<T>> { }; + + template <typename T> + using is_var_wrapper = meta::is_specialization_of<T, var_wrapper>; + + template <typename T> + struct is_function_binding : meta::neg<is_variable_binding<T>> { }; + +} // namespace sol + +// end of sol/call.hpp + +namespace sol { + namespace function_detail { + template <typename F, F fx> + inline int call_wrapper_variable(std::false_type, lua_State* L) { + typedef meta::bind_traits<meta::unqualified_t<F>> traits_type; + typedef typename traits_type::args_list args_list; + typedef meta::tuple_types<typename traits_type::return_type> return_type; + return stack::call_into_lua(return_type(), args_list(), L, 1, fx); + } + + template <typename R, typename V, V, typename T> + inline int call_set_assignable(std::false_type, T&&, lua_State* L) { + return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); + } + + template <typename R, typename V, V variable, typename T> + inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { + (mem.*variable) = stack::get<R>(L, 2); + return 0; + } + + template <typename R, typename V, V, typename T> + inline int call_set_variable(std::false_type, lua_State* L, T&&) { + return luaL_error(L, "cannot write to a const variable"); + } + + template <typename R, typename V, V variable, typename T> + inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { + return call_set_assignable<R, V, variable>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, std::forward<T>(mem)); + } + + template <typename V, V variable> + inline int call_wrapper_variable(std::true_type, lua_State* L) { + typedef meta::bind_traits<meta::unqualified_t<V>> traits_type; + typedef typename traits_type::object_type T; + typedef typename traits_type::return_type R; + auto& mem = stack::get<T>(L, 1); + switch (lua_gettop(L)) { + case 1: { + decltype(auto) r = (mem.*variable); + stack::push_reference(L, std::forward<decltype(r)>(r)); + return 1; + } + case 2: + return call_set_variable<R, V, variable>(meta::neg<std::is_const<R>>(), L, mem); + default: + return luaL_error(L, "incorrect number of arguments to member variable function call"); + } + } + + template <typename F, F fx> + inline int call_wrapper_function(std::false_type, lua_State* L) { + return call_wrapper_variable<F, fx>(std::is_member_object_pointer<F>(), L); + } + + template <typename F, F fx> + inline int call_wrapper_function(std::true_type, lua_State* L) { + return call_detail::call_wrapped<void, false, false>(L, fx); + } + + template <typename F, F fx> + int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits<F>::is_noexcept) { + return call_wrapper_function<F, fx>(std::is_member_function_pointer<meta::unqualified_t<F>>(), L); + } + + template <typename... Fxs> + struct c_call_matcher { + template <typename Fx, std::size_t I, typename R, typename... Args> + int operator()(types<Fx>, meta::index_value<I>, types<R>, types<Args...>, lua_State* L, int, int) const { + typedef meta::at_in_pack_t<I, Fxs...> target; + return target::call(L); + } + }; + + template <typename F, F fx> + inline int c_call_raw(std::true_type, lua_State* L) { + return fx(L); + } + + template <typename F, F fx> + inline int c_call_raw(std::false_type, lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, function_detail::call_wrapper_entry<F, fx>); +#else + return detail::typed_static_trampoline<decltype(&function_detail::call_wrapper_entry<F, fx>), (&function_detail::call_wrapper_entry<F, fx>)>(L); +#endif // fuck you clang :c + } + + } // namespace function_detail + + template <typename F, F fx> + inline int c_call(lua_State* L) { + typedef meta::unqualified_t<F> Fu; + typedef std::integral_constant<bool, + std::is_same<Fu, lua_CFunction>::value +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + || std::is_same<Fu, detail::lua_CFunction_noexcept>::value +#endif + > + is_raw; + return function_detail::c_call_raw<F, fx>(is_raw(), L); + } + + template <typename F, F f> + struct wrap { + typedef F type; + + static int call(lua_State* L) noexcept(noexcept(c_call<type, f>(L))) { + return c_call<type, f>(L); + } + }; + + template <typename... Fxs> + inline int c_call(lua_State* L) { + if constexpr (sizeof...(Fxs) < 2) { + using target = meta::at_in_pack_t<0, Fxs...>; + return target::call(L); + } + else { + return call_detail::overload_match_arity<typename Fxs::type...>(function_detail::c_call_matcher<Fxs...>(), L, lua_gettop(L), 1); + } + } + +} // namespace sol + +// end of sol/function_types_templated.hpp + +// beginning of sol/function_types_stateless.hpp + +namespace sol { namespace function_detail { + template <typename Function> + struct upvalue_free_function { + using function_type = std::remove_pointer_t<std::decay_t<Function>>; + using traits_type = meta::bind_traits<function_type>; + + static int real_call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L); + function_type* fx = udata.first; + return call_detail::call_wrapped<void, true, false>(L, fx); + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + }; + + template <typename T, typename Function> + struct upvalue_member_function { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef lua_bind_traits<function_type> traits_type; + + static int real_call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + // Layout: + // idx 1...n: verbatim data of member function pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + function_type& memfx = stack::get<user<function_type>>(L, upvalue_index(2)); + auto& item = *static_cast<T*>(stack::get<void*>(L, upvalue_index(3))); + return call_detail::call_wrapped<T, true, false, -1>(L, memfx, item); + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + return call(L); + } + }; + + template <typename T, typename Function> + struct upvalue_member_variable { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef lua_bind_traits<function_type> traits_type; + + static int real_call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + // Layout: + // idx 1...n: verbatim data of member variable pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); + auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); + auto& mem = *objdata.first; + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); + case 1: + return call_detail::call_wrapped<T, false, false, -1>(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + return call(L); + } + }; + + template <typename T, typename Function> + struct upvalue_member_variable<T, readonly_wrapper<Function>> { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef lua_bind_traits<function_type> traits_type; + + static int real_call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + // Layout: + // idx 1...n: verbatim data of member variable pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); + auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second); + auto& mem = *objdata.first; + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped<T, true, false, -1>(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + return call(L); + } + }; + + template <typename T, typename Function> + struct upvalue_this_member_function { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef lua_bind_traits<function_type> traits_type; + + static int real_call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + // Layout: + // idx 1...n: verbatim data of member variable pointer + function_type& memfx = stack::get<user<function_type>>(L, upvalue_index(2)); + return call_detail::call_wrapped<T, false, false>(L, memfx); + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + return call(L); + } + }; + + template <typename T, typename Function> + struct upvalue_this_member_variable { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + + static int real_call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + return call_detail::call_wrapped<T, true, false>(L, var); + case 2: + return call_detail::call_wrapped<T, false, false>(L, var); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_CLANG) + // apparent regression in clang 18 - llvm/llvm-project#91362 +#else + noexcept(std::is_nothrow_copy_assignable_v<T>) +#endif + { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { + return call(L); + } + }; + + template <typename T, typename Function> + struct upvalue_this_member_variable<T, readonly_wrapper<Function>> { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef lua_bind_traits<function_type> traits_type; + + static int real_call(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + return call_detail::call_wrapped<T, true, false>(L, var); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + template <bool is_yielding, bool no_trampoline> + static int call(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_CLANG) + // apparent regression in clang 18 - llvm/llvm-project#91362 +#else + noexcept(std::is_nothrow_copy_assignable_v<T>) +#endif + { + int nr; + if constexpr (no_trampoline) { + nr = real_call(L); + } + else { + nr = detail::typed_static_trampoline<decltype(&real_call), (&real_call)>(L); + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { + return call(L); + } + }; +}} // namespace sol::function_detail + +// end of sol/function_types_stateless.hpp + +// beginning of sol/function_types_stateful.hpp + +namespace sol { namespace function_detail { + template <typename Func, bool is_yielding, bool no_trampoline> + struct functor_function { + typedef std::decay_t<meta::unwrap_unqualified_t<Func>> function_type; + function_type invocation; + + template <typename... Args> + functor_function(function_type f, Args&&... args) noexcept(std::is_nothrow_constructible_v<function_type, function_type, Args...>) + : invocation(std::move(f), std::forward<Args>(args)...) { + } + + static int call(lua_State* L, functor_function& self) noexcept(noexcept(call_detail::call_wrapped<void, true, false>(L, self.invocation))) { + int nr = call_detail::call_wrapped<void, true, false>(L, self.invocation); + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) noexcept(noexcept(call_detail::call_wrapped<void, true, false>(L, invocation))) { + if constexpr (no_trampoline) { + return call(L, *this); + } + else { + return detail::trampoline(L, &call, *this); + } + } + }; + + template <typename T, typename Function, bool is_yielding, bool no_trampoline> + struct member_function { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef meta::function_return_t<function_type> return_type; + typedef meta::function_args_t<function_type> args_lists; + using traits_type = meta::bind_traits<function_type>; + function_type invocation; + T member; + + template <typename... Args> + member_function(function_type f, Args&&... args) noexcept( + std::is_nothrow_constructible_v<function_type, function_type>&& std::is_nothrow_constructible_v<T, Args...>) + : invocation(std::move(f)), member(std::forward<Args>(args)...) { + } + + static int call(lua_State* L, member_function& self) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + int nr = call_detail::call_wrapped<T, true, false, -1>(L, self.invocation, detail::unwrap(detail::deref(self.member))); + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) +#if SOL_IS_ON(SOL_COMPILER_VCXX) + // MSVC is broken, what a surprise... +#else + noexcept(traits_type::is_noexcept) +#endif + { + if constexpr (no_trampoline) { + return call(L, *this); + } + else { + return detail::trampoline(L, &call, *this); + } + } + }; + + template <typename T, typename Function, bool is_yielding, bool no_trampoline> + struct member_variable { + typedef std::remove_pointer_t<std::decay_t<Function>> function_type; + typedef typename meta::bind_traits<function_type>::return_type return_type; + typedef typename meta::bind_traits<function_type>::args_list args_lists; + function_type var; + T member; + typedef std::add_lvalue_reference_t<meta::unwrapped_t<std::remove_reference_t<decltype(detail::deref(member))>>> M; + + template <typename... Args> + member_variable(function_type v, Args&&... args) noexcept( + std::is_nothrow_constructible_v<function_type, function_type>&& std::is_nothrow_constructible_v<T, Args...>) + : var(std::move(v)), member(std::forward<Args>(args)...) { + } + + static int call(lua_State* L, member_variable& self) noexcept(std::is_nothrow_copy_assignable_v<T>) { + int nr; + { + M mem = detail::unwrap(detail::deref(self.member)); + switch (lua_gettop(L)) { + case 0: + nr = call_detail::call_wrapped<T, true, false, -1>(L, self.var, mem); + break; + case 1: + nr = call_detail::call_wrapped<T, false, false, -1>(L, self.var, mem); + break; + default: + nr = luaL_error(L, "sol: incorrect number of arguments to member variable function"); + break; + } + } + if (is_yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + int operator()(lua_State* L) noexcept(std::is_nothrow_copy_assignable_v<T>) { + if constexpr (no_trampoline) { + return call(L, *this); + } + else { + return detail::trampoline(L, &call, *this); + } + } + }; +}} // namespace sol::function_detail + +// end of sol/function_types_stateful.hpp + +// beginning of sol/function_types_overloaded.hpp + +namespace sol { namespace function_detail { + template <int start_skew, typename... Functions> + struct overloaded_function { + typedef std::tuple<Functions...> overload_list; + typedef std::make_index_sequence<sizeof...(Functions)> indices; + overload_list overloads; + + overloaded_function(overload_list set) : overloads(std::move(set)) { + } + + overloaded_function(Functions... fxs) : overloads(fxs...) { + } + + template <typename Fx, std::size_t I, typename... R, typename... Args> + static int call(types<Fx>, meta::index_value<I>, types<R...>, types<Args...>, lua_State* L, int, int, overload_list& ol) { + auto& func = std::get<I>(ol); + int nr = call_detail::call_wrapped<void, true, false, start_skew>(L, func); + return nr; + } + + struct on_success { + template <typename... Args> + int operator()(Args&&... args) const { + return call(std::forward<Args>(args)...); + } + }; + + int operator()(lua_State* L) { + on_success call_obj {}; + return call_detail::overload_match<Functions...>(call_obj, L, 1 + start_skew, overloads); + } + }; +}} // namespace sol::function_detail + +// end of sol/function_types_overloaded.hpp + +// beginning of sol/resolve.hpp + +namespace sol { + +#ifndef __clang__ + // constexpr is fine for not-clang + + namespace detail { + template <typename R, typename... Args, typename F, typename = std::invoke_result_t<meta::unqualified_t<F>, Args...>> + inline constexpr auto resolve_i(types<R(Args...)>, F&&) -> R (meta::unqualified_t<F>::*)(Args...) { + using Sig = R(Args...); + typedef meta::unqualified_t<F> Fu; + return static_cast<Sig Fu::*>(&Fu::operator()); + } + + template <typename F, typename U = meta::unqualified_t<F>> + inline constexpr auto resolve_f(std::true_type, F&& f) + -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { + return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); + } + + template <typename F> + inline constexpr void resolve_f(std::false_type, F&&) { + static_assert(meta::call_operator_deducible_v<F>, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + } + + template <typename F, typename U = meta::unqualified_t<F>> + inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::call_operator_deducible<U>(), std::forward<F>(f))) { + return resolve_f(meta::call_operator_deducible<U> {}, std::forward<F>(f)); + } + + template <typename... Args, typename F, typename R = std::invoke_result_t<F&, Args...>> + inline constexpr auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { + return resolve_i(types<R(Args...)>(), std::forward<F>(f)); + } + + template <typename Sig, typename C> + inline constexpr Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) { + return mem_func_ptr; + } + + template <typename Sig, typename C> + inline constexpr Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) { + return mem_variable_ptr; + } + } // namespace detail + + template <typename... Args, typename R> + inline constexpr auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) { + return fun_ptr; + } + + template <typename Sig> + inline constexpr Sig* resolve(Sig* fun_ptr) { + return fun_ptr; + } + + template <typename... Args, typename R, typename C> + inline constexpr auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) { + return mem_ptr; + } + + template <typename Sig, typename C> + inline constexpr Sig C::*resolve(Sig C::*mem_ptr) { + return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); + } + + template <typename... Sig, typename F, meta::disable<std::is_function<meta::unqualified_t<F>>> = meta::enabler> + inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { + return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); + } +#else + + // Clang has distinct problems with constexpr arguments, + // so don't use the constexpr versions inside of clang. + + namespace detail { + template <typename R, typename... Args, typename F, typename = std::invoke_result_t<meta::unqualified_t<F>, Args...>> + inline auto resolve_i(types<R(Args...)>, F&&) -> R (meta::unqualified_t<F>::*)(Args...) { + using Sig = R(Args...); + typedef meta::unqualified_t<F> Fu; + return static_cast<Sig Fu::*>(&Fu::operator()); + } + + template <typename F, typename U = meta::unqualified_t<F>> + inline auto resolve_f(std::true_type, F&& f) + -> decltype(resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f))) { + return resolve_i(types<meta::function_signature_t<decltype(&U::operator())>>(), std::forward<F>(f)); + } + + template <typename F> + inline void resolve_f(std::false_type, F&&) { + static_assert(meta::call_operator_deducible_v<F>, "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + } + + template <typename F, typename U = meta::unqualified_t<F>> + inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::call_operator_deducible<U>(), std::forward<F>(f))) { + return resolve_f(meta::call_operator_deducible<U> {}, std::forward<F>(f)); + } + + template <typename... Args, typename F, typename R = std::invoke_result_t<F&, Args...>> + inline auto resolve_i(types<Args...>, F&& f) -> decltype(resolve_i(types<R(Args...)>(), std::forward<F>(f))) { + return resolve_i(types<R(Args...)>(), std::forward<F>(f)); + } + + template <typename Sig, typename C> + inline Sig C::*resolve_v(std::false_type, Sig C::*mem_func_ptr) { + return mem_func_ptr; + } + + template <typename Sig, typename C> + inline Sig C::*resolve_v(std::true_type, Sig C::*mem_variable_ptr) { + return mem_variable_ptr; + } + } // namespace detail + + template <typename... Args, typename R> + inline auto resolve(R fun_ptr(Args...)) -> R (*)(Args...) { + return fun_ptr; + } + + template <typename Sig> + inline Sig* resolve(Sig* fun_ptr) { + return fun_ptr; + } + + template <typename... Args, typename R, typename C> + inline auto resolve(R (C::*mem_ptr)(Args...)) -> R (C::*)(Args...) { + return mem_ptr; + } + + template <typename Sig, typename C> + inline Sig C::*resolve(Sig C::*mem_ptr) { + return detail::resolve_v(std::is_member_object_pointer<Sig C::*>(), mem_ptr); + } + + template <typename... Sig, typename F> + inline auto resolve(F&& f) -> decltype(detail::resolve_i(types<Sig...>(), std::forward<F>(f))) { + return detail::resolve_i(types<Sig...>(), std::forward<F>(f)); + } + +#endif + +} // namespace sol + +// end of sol/resolve.hpp + +namespace sol { + namespace function_detail { + template <typename T> + struct class_indicator { + using type = T; + }; + + struct call_indicator { }; + + template <bool yielding> + int lua_c_wrapper(lua_State* L) { + lua_CFunction cf = lua_tocfunction(L, lua_upvalueindex(2)); + int nr = cf(L); + if constexpr (yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + template <bool yielding> + int lua_c_noexcept_wrapper(lua_State* L) noexcept { + detail::lua_CFunction_noexcept cf = reinterpret_cast<detail::lua_CFunction_noexcept>(lua_tocfunction(L, lua_upvalueindex(2))); + int nr = cf(L); + if constexpr (yielding) { + return lua_yield(L, nr); + } + else { + return nr; + } + } + + struct c_function_invocation { }; + + template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args> + void select(lua_State* L, Fx&& fx, Args&&... args); + + template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args> + void select_set_fx(lua_State* L, Args&&... args) { + lua_CFunction freefunc = no_trampoline ? function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding> + : detail::static_trampoline<function_detail::call<meta::unqualified_t<Fx>, 2, is_yielding>>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<Fx>>(L, std::forward<Args>(args)...); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template <bool is_yielding, bool no_trampoline, typename R, typename... A, typename Fx, typename... Args> + void select_convertible(types<R(A...)>, lua_State* L, Fx&& fx, Args&&... args) { + using dFx = std::decay_t<meta::unwrap_unqualified_t<Fx>>; + using fx_ptr_t = R (*)(A...); + constexpr bool is_convertible = std::is_convertible_v<dFx, fx_ptr_t>; + if constexpr (is_convertible) { + fx_ptr_t fxptr = detail::unwrap(std::forward<Fx>(fx)); + select<is_yielding, no_trampoline>(L, std::move(fxptr), std::forward<Args>(args)...); + } + else { + using F = function_detail::functor_function<dFx, false, true>; + select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + + template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args> + void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { + typedef meta::function_signature_t<meta::unwrap_unqualified_t<Fx>> Sig; + select_convertible<is_yielding, no_trampoline>(types<Sig>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + + template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args> + void select_member_variable(lua_State* L, Fx&& fx, Args&&... args) { + using uFx = meta::unqualified_t<Fx>; + if constexpr (sizeof...(Args) < 1) { + using C = typename meta::bind_traits<uFx>::object_type; + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable<C, Fx>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + else if constexpr (sizeof...(Args) < 2) { + using Tu = typename meta::meta_detail::unqualified_non_alias<Args...>::type; + constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>; + if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) { + lua_CFunction freefunc + = &function_detail::upvalue_this_member_variable<typename Tu::type, Fx>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + else if constexpr (is_reference) { + typedef std::decay_t<Fx> dFx; + dFx memfxptr(std::forward<Fx>(fx)); + auto userptr = detail::ptr(std::forward<Args>(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_variable<std::decay_t<decltype(*userptr)>, + meta::unqualified_t<Fx>>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, static_cast<void const*>(userptr)); + stack::push(L, c_closure(freefunc, upvalues)); + } + else { + using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>; + using F = function_detail::member_variable<Tu, clean_fx, is_yielding, no_trampoline>; + select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + else { + using C = typename meta::bind_traits<uFx>::object_type; + using clean_fx = std::remove_pointer_t<std::decay_t<Fx>>; + using F = function_detail::member_variable<C, clean_fx, is_yielding, no_trampoline>; + select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + + template <bool is_yielding, bool no_trampoline, typename Fx, typename T, typename... Args> + void select_member_function_with(lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + using dFx = std::decay_t<Fx>; + using Tu = meta::unqualified_t<T>; + if constexpr (meta::is_specialization_of_v<Tu, function_detail::class_indicator>) { + (void)obj; + using C = typename Tu::type; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + stack::push(L, c_closure(freefunc, upvalues)); + } + else { + constexpr bool is_reference = meta::is_specialization_of_v<Tu, std::reference_wrapper> || std::is_pointer_v<Tu>; + if constexpr (is_reference) { + auto userptr = detail::ptr(std::forward<T>(obj)); + lua_CFunction freefunc + = &function_detail::upvalue_member_function<std::decay_t<decltype(*userptr)>, dFx>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + upvalues += stack::push(L, lightuserdata_value(static_cast<void*>(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + else { + using F = function_detail::member_function<Tu, dFx, is_yielding, no_trampoline>; + select_set_fx<is_yielding, no_trampoline, F>(L, std::forward<Fx>(fx), std::forward<T>(obj), std::forward<Args>(args)...); + } + } + } + + template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args> + void select_member_function(lua_State* L, Fx&& fx, Args&&... args) { + using dFx = std::decay_t<Fx>; + if constexpr (sizeof...(Args) < 1) { + using C = typename meta::bind_traits<meta::unqualified_t<Fx>>::object_type; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function<C, dFx>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<dFx>>(L, std::forward<Fx>(fx)); + stack::push(L, c_closure(freefunc, upvalues)); + } + else { + select_member_function_with<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + + template <bool is_yielding, bool no_trampoline, typename Fx, typename... Args> + void select(lua_State* L, Fx&& fx, Args&&... args) { + using uFx = meta::unqualified_t<Fx>; + if constexpr (is_lua_reference_v<uFx>) { + // TODO: hoist into lambda in this case for yielding??? + stack::push(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + else if constexpr (is_lua_c_function_v<uFx>) { + if constexpr (no_trampoline) { + if (is_yielding) { + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push(L, std::forward<Fx>(fx)); +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) { + detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<true>; + lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues); + } + else +#endif + { + lua_CFunction cf = &function_detail::lua_c_wrapper<true>; + lua_pushcclosure(L, cf, upvalues); + } + } + else { + lua_pushcclosure(L, std::forward<Fx>(fx), 0); + } + } + else { + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push(L, std::forward<Fx>(fx)); +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + if constexpr (std::is_nothrow_invocable_r_v<int, uFx, lua_State*>) { + detail::lua_CFunction_noexcept cf = &lua_c_noexcept_wrapper<is_yielding>; + lua_pushcclosure(L, reinterpret_cast<lua_CFunction>(cf), upvalues); + } + else { + lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>; + lua_pushcclosure(L, cf, upvalues); + } +#else + lua_CFunction cf = &function_detail::lua_c_wrapper<is_yielding>; + lua_pushcclosure(L, cf, upvalues); +#endif + } + } + else if constexpr (std::is_function_v<std::remove_pointer_t<uFx>>) { + std::decay_t<Fx> target(std::forward<Fx>(fx), std::forward<Args>(args)...); + lua_CFunction freefunc = &function_detail::upvalue_free_function<Fx>::template call<is_yielding, no_trampoline>; + + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, target); + stack::push(L, c_closure(freefunc, upvalues)); + } + else if constexpr (std::is_member_function_pointer_v<uFx>) { + select_member_function<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + else if constexpr (meta::is_member_object_v<uFx>) { + select_member_variable<is_yielding, no_trampoline>(L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + else { + select_convertible<is_yielding, no_trampoline>(types<>(), L, std::forward<Fx>(fx), std::forward<Args>(args)...); + } + } + } // namespace function_detail + + namespace stack { + template <typename... Sigs> + struct unqualified_pusher<function_sig<Sigs...>> { + template <bool is_yielding, typename Arg0, typename... Args> + static int push_yielding(lua_State* L, Arg0&& arg0, Args&&... args) { + if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, std::function>) { + if constexpr (is_yielding) { + return stack::push<meta::unqualified_t<Arg0>>(L, detail::yield_tag, std::forward<Arg0>(arg0), std::forward<Args>(args)...); + } + else { + return stack::push(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...); + } + } + else { + function_detail::select<is_yielding, false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...); + return 1; + } + } + + template <typename Arg0, typename... Args> + static int push(lua_State* L, Arg0&& arg0, Args&&... args) { + if constexpr (std::is_same_v<meta::unqualified_t<Arg0>, detail::yield_tag_t>) { + push_yielding<true>(L, std::forward<Args>(args)...); + } + else if constexpr (meta::is_specialization_of_v<meta::unqualified_t<Arg0>, yielding_t>) { + push_yielding<true>(L, std::forward<Arg0>(arg0).func, std::forward<Args>(args)...); + } + else { + push_yielding<false>(L, std::forward<Arg0>(arg0), std::forward<Args>(args)...); + } + return 1; + } + }; + + template <typename T> + struct unqualified_pusher<yielding_t<T>> { + template <typename... Args> + static int push(lua_State* L, const yielding_t<T>& f, Args&&... args) { + if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) { + return stack::push<T>(L, detail::yield_tag, f.func, std::forward<Args>(args)...); + } + else { + function_detail::select<true, false>(L, f.func, std::forward<Args>(args)...); + return 1; + } + } + + template <typename... Args> + static int push(lua_State* L, yielding_t<T>&& f, Args&&... args) { + if constexpr (meta::is_specialization_of_v<meta::unqualified_t<T>, std::function>) { + return stack::push<T>(L, detail::yield_tag, std::move(f.func), std::forward<Args>(args)...); + } + else { + function_detail::select<true, false>(L, std::move(f.func), std::forward<Args>(args)...); + return 1; + } + } + }; + + template <typename T, typename... Args> + struct unqualified_pusher<function_arguments<T, Args...>> { + template <std::size_t... I, typename FP> + static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) { + return stack::push<T>(L, std::get<I>(std::forward<FP>(fp).arguments)...); + } + + static int push(lua_State* L, const function_arguments<T, Args...>& fp) { + return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp); + } + + static int push(lua_State* L, function_arguments<T, Args...>&& fp) { + return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp)); + } + }; + + template <typename Signature> + struct unqualified_pusher<std::function<Signature>> { + using TargetFunctor = function_detail::functor_function<std::function<Signature>, false, true>; + + static int push(lua_State* L, detail::yield_tag_t, const std::function<Signature>& fx) { + if (fx) { + function_detail::select_set_fx<true, false, TargetFunctor>(L, fx); + return 1; + } + return stack::push(L, lua_nil); + } + + static int push(lua_State* L, detail::yield_tag_t, std::function<Signature>&& fx) { + if (fx) { + function_detail::select_set_fx<true, false, TargetFunctor>(L, std::move(fx)); + return 1; + } + return stack::push(L, lua_nil); + } + + static int push(lua_State* L, const std::function<Signature>& fx) { + if (fx) { + function_detail::select_set_fx<false, false, TargetFunctor>(L, fx); + return 1; + } + return stack::push(L, lua_nil); + } + + static int push(lua_State* L, std::function<Signature>&& fx) { + if (fx) { + function_detail::select_set_fx<false, false, TargetFunctor>(L, std::move(fx)); + return 1; + } + return stack::push(L, lua_nil); + } + }; + + template <typename Signature> + struct unqualified_pusher<Signature, std::enable_if_t<meta::is_member_object_or_function_v<Signature>>> { + template <typename... Args> + static int push(lua_State* L, Args&&... args) { + function_detail::select<false, false>(L, std::forward<Args>(args)...); + return 1; + } + }; + + template <typename Signature> + struct unqualified_pusher<Signature, + std::enable_if_t<meta::all<std::is_function<std::remove_pointer_t<Signature>>, meta::neg<std::is_same<Signature, lua_CFunction>>, + meta::neg<std::is_same<Signature, std::remove_pointer_t<lua_CFunction>>> +#if SOL_IS_ON(SOL_USE_NOEXCEPT_FUNCTION_TYPE) + , + meta::neg<std::is_same<Signature, detail::lua_CFunction_noexcept>>, + meta::neg<std::is_same<Signature, std::remove_pointer_t<detail::lua_CFunction_noexcept>>> +#endif // noexcept function types + >::value>> { + template <typename F> + static int push(lua_State* L, F&& f) { + function_detail::select<false, true>(L, std::forward<F>(f)); + return 1; + } + }; + + template <typename... Functions> + struct unqualified_pusher<overload_set<Functions...>> { + static int push(lua_State* L, overload_set<Functions...>&& set) { + using F = function_detail::overloaded_function<0, Functions...>; + function_detail::select_set_fx<false, false, F>(L, std::move(set.functions)); + return 1; + } + + static int push(lua_State* L, const overload_set<Functions...>& set) { + using F = function_detail::overloaded_function<0, Functions...>; + function_detail::select_set_fx<false, false, F>(L, set.functions); + return 1; + } + }; + + template <typename T> + struct unqualified_pusher<protect_t<T>> { + static int push(lua_State* L, protect_t<T>&& pw) { + lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<protect_t<T>>>(L, std::move(pw.value)); + return stack::push(L, c_closure(cf, upvalues)); + } + + static int push(lua_State* L, const protect_t<T>& pw) { + lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<protect_t<T>>>(L, pw.value); + return stack::push(L, c_closure(cf, upvalues)); + } + }; + + template <typename F, typename G> + struct unqualified_pusher<property_wrapper<F, G>> { + static int push(lua_State* L, property_wrapper<F, G>&& pw) { + if constexpr (std::is_void_v<F>) { + return stack::push(L, std::move(pw.write())); + } + else if constexpr (std::is_void_v<G>) { + return stack::push(L, std::move(pw.read())); + } + else { + return stack::push(L, overload(std::move(pw.read()), std::move(pw.write()))); + } + } + + static int push(lua_State* L, const property_wrapper<F, G>& pw) { + if constexpr (std::is_void_v<F>) { + return stack::push(L, pw.write); + } + else if constexpr (std::is_void_v<G>) { + return stack::push(L, pw.read); + } + else { + return stack::push(L, overload(pw.read, pw.write)); + } + } + }; + + template <typename T> + struct unqualified_pusher<var_wrapper<T>> { + static int push(lua_State* L, var_wrapper<T>&& vw) { + return stack::push(L, std::move(vw.value())); + } + static int push(lua_State* L, const var_wrapper<T>& vw) { + return stack::push(L, vw.value()); + } + }; + + template <typename... Functions> + struct unqualified_pusher<factory_wrapper<Functions...>> { + static int push(lua_State* L, const factory_wrapper<Functions...>& fw) { + using F = function_detail::overloaded_function<0, Functions...>; + function_detail::select_set_fx<false, false, F>(L, fw.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper<Functions...>&& fw) { + using F = function_detail::overloaded_function<0, Functions...>; + function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions)); + return 1; + } + + static int push(lua_State* L, const factory_wrapper<Functions...>& fw, function_detail::call_indicator) { + using F = function_detail::overloaded_function<1, Functions...>; + function_detail::select_set_fx<false, false, F>(L, fw.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper<Functions...>&& fw, function_detail::call_indicator) { + using F = function_detail::overloaded_function<1, Functions...>; + function_detail::select_set_fx<false, false, F>(L, std::move(fw.functions)); + return 1; + } + }; + + template <> + struct unqualified_pusher<no_construction> { + static int push(lua_State* L, no_construction) { + lua_CFunction cf = &function_detail::no_construction_error; + return stack::push(L, cf); + } + + static int push(lua_State* L, no_construction c, function_detail::call_indicator) { + return push(L, c); + } + }; + + template <typename T> + struct unqualified_pusher<detail::tagged<T, no_construction>> { + static int push(lua_State* L, detail::tagged<T, no_construction>) { + lua_CFunction cf = &function_detail::no_construction_error; + return stack::push(L, cf); + } + + static int push(lua_State* L, no_construction, function_detail::call_indicator) { + lua_CFunction cf = &function_detail::no_construction_error; + return stack::push(L, cf); + } + }; + + template <typename T, typename... Lists> + struct unqualified_pusher<detail::tagged<T, constructor_list<Lists...>>> { + static int push(lua_State* L, detail::tagged<T, constructor_list<Lists...>>) { + lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>; + return stack::push(L, cf); + } + + static int push(lua_State* L, constructor_list<Lists...>) { + lua_CFunction cf = call_detail::construct<T, detail::default_safe_function_calls, true, Lists...>; + return stack::push(L, cf); + } + }; + + template <typename L0, typename... Lists> + struct unqualified_pusher<constructor_list<L0, Lists...>> { + typedef constructor_list<L0, Lists...> cl_t; + static int push(lua_State* L, cl_t cl) { + typedef typename meta::bind_traits<L0>::return_type T; + return stack::push<detail::tagged<T, cl_t>>(L, cl); + } + }; + + template <typename T, typename... Fxs> + struct unqualified_pusher<detail::tagged<T, constructor_wrapper<Fxs...>>> { + static int push(lua_State* L, detail::tagged<T, constructor_wrapper<Fxs...>>&& c) { + return push(L, std::move(c.value())); + } + + static int push(lua_State* L, const detail::tagged<T, const constructor_wrapper<Fxs...>>& c) { + return push(L, c.value()); + } + + static int push(lua_State* L, constructor_wrapper<Fxs...>&& c) { + lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, std::move(c)); + return stack::push(L, c_closure(cf, upvalues)); + } + + static int push(lua_State* L, const constructor_wrapper<Fxs...>& c) { + lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<constructor_wrapper<Fxs...>>>(L, c); + return stack::push(L, c_closure(cf, upvalues)); + } + }; + + template <typename F, typename... Fxs> + struct unqualified_pusher<constructor_wrapper<F, Fxs...>> { + static int push(lua_State* L, const constructor_wrapper<F, Fxs...>& c) { + typedef typename meta::bind_traits<F>::template arg_at<0> arg0; + typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T; + return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, c); + } + + static int push(lua_State* L, constructor_wrapper<F, Fxs...>&& c) { + typedef typename meta::bind_traits<F>::template arg_at<0> arg0; + typedef meta::unqualified_t<std::remove_pointer_t<arg0>> T; + return stack::push<detail::tagged<T, constructor_wrapper<F, Fxs...>>>(L, std::move(c)); + } + }; + + template <typename T> + struct unqualified_pusher<detail::tagged<T, destructor_wrapper<void>>> { + static int push(lua_State* L, destructor_wrapper<void>) { + lua_CFunction cf = detail::usertype_alloc_destroy<T>; + return stack::push(L, cf); + } + }; + + template <typename T, typename Fx> + struct unqualified_pusher<detail::tagged<T, destructor_wrapper<Fx>>> { + static int push(lua_State* L, destructor_wrapper<Fx>&& c) { + lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c)); + return stack::push(L, c_closure(cf, upvalues)); + } + + static int push(lua_State* L, const destructor_wrapper<Fx>& c) { + lua_CFunction cf = call_detail::call_user<T, false, false, destructor_wrapper<Fx>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c); + return stack::push(L, c_closure(cf, upvalues)); + } + }; + + template <typename Fx> + struct unqualified_pusher<destructor_wrapper<Fx>> { + static int push(lua_State* L, destructor_wrapper<Fx>&& c) { + lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, std::move(c)); + return stack::push(L, c_closure(cf, upvalues)); + } + + static int push(lua_State* L, const destructor_wrapper<Fx>& c) { + lua_CFunction cf = call_detail::call_user<void, false, false, destructor_wrapper<Fx>, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<destructor_wrapper<Fx>>>(L, c); + return stack::push(L, c_closure(cf, upvalues)); + } + }; + + template <typename F, typename... Policies> + struct unqualified_pusher<policy_wrapper<F, Policies...>> { + using P = policy_wrapper<F, Policies...>; + + static int push(lua_State* L, const P& p) { + lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<P>>(L, p); + return stack::push(L, c_closure(cf, upvalues)); + } + + static int push(lua_State* L, P&& p) { + lua_CFunction cf = call_detail::call_user<void, false, false, P, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<P>>(L, std::move(p)); + return stack::push(L, c_closure(cf, upvalues)); + } + }; + + template <typename T, typename F, typename... Policies> + struct unqualified_pusher<detail::tagged<T, policy_wrapper<F, Policies...>>> { + using P = policy_wrapper<F, Policies...>; + using Tagged = detail::tagged<T, P>; + + static int push(lua_State* L, const Tagged& p) { + lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<P>>(L, p.value()); + return stack::push(L, c_closure(cf, upvalues)); + } + + static int push(lua_State* L, Tagged&& p) { + lua_CFunction cf = call_detail::call_user<T, false, false, P, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push<user<P>>(L, std::move(p.value())); + return stack::push(L, c_closure(cf, upvalues)); + } + }; + + template <typename T> + struct unqualified_pusher<push_invoke_t<T>> { + static int push(lua_State* L, push_invoke_t<T>&& pi) { + if constexpr (std::is_invocable_v<std::add_rvalue_reference_t<T>, lua_State*>) { + return stack::push(L, std::move(pi.value())(L)); + } + else { + return stack::push(L, std::move(pi.value())()); + } + } + + static int push(lua_State* L, const push_invoke_t<T>& pi) { + if constexpr (std::is_invocable_v<const T, lua_State*>) { + return stack::push(L, pi.value()(L)); + } + else { + return stack::push(L, pi.value()()); + } + } + }; + + namespace stack_detail { + template <typename Function, typename Handler> + bool check_function_pointer(lua_State* L, int index, Handler&& handler, record& tracking) noexcept { +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + tracking.use(1); + bool success = lua_iscfunction(L, index) == 1; + if (success) { + // there must be at LEAST 2 upvalues; otherwise, we didn't serialize it. + const char* upvalue_name = lua_getupvalue(L, index, 2); + lua_pop(L, 1); + success = upvalue_name != nullptr; + } + if (!success) { + // expected type, actual type + handler( + L, index, type::function, type_of(L, index), "type must be a Lua C Function gotten from a function pointer serialized by sol2"); + } + return success; +#else + (void)L; + (void)index; + (void)handler; + (void)tracking; + return false; +#endif + } + + template <typename Function> + Function* get_function_pointer(lua_State* L, int index, record& tracking) noexcept { +#if SOL_IS_ON(SOL_GET_FUNCTION_POINTER_UNSAFE) + tracking.use(1); + auto udata = stack::stack_detail::get_as_upvalues_using_function<Function*>(L, index); + Function* fx = udata.first; + return fx; +#else + (void)L; + (void)index; + (void)tracking; + static_assert(meta::meta_detail::always_true<Function>::value, +#if SOL_IS_DEFAULT_OFF(SOL_GET_FUNCTION_POINTER_UNSAFE) + "You are attempting to retrieve a function pointer type. " + "This is inherently unsafe in sol2. In order to do this, you must turn on the " + "SOL_GET_FUNCTION_POINTER_UNSAFE configuration macro, as detailed in the documentation. " + "Please be careful!" +#else + "You are attempting to retrieve a function pointer type. " + "You explicitly turned off the ability to do this by defining " + "SOL_GET_FUNCTION_POINTER_UNSAFE or similar to be off. " + "Please reconsider this!" +#endif + ); + return nullptr; +#endif + } + } // namespace stack_detail + } // namespace stack +} // namespace sol + +// end of sol/function_types.hpp + +// beginning of sol/dump_handler.hpp + +#include <cstdint> +#include <exception> + +namespace sol { + + class dump_error : public error { + private: + int m_ec; + + public: + dump_error(int error_code_) : error("dump returned non-zero error of " + std::to_string(error_code_)), m_ec(error_code_) { + } + + int error_code() const { + return m_ec; + } + }; + + inline int dump_pass_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) { + (void)L_; + (void)writer_function; + (void)userdata_pointer_; + (void)strip; + return result_code; + } + + inline int dump_panic_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) { + (void)L_; + (void)writer_function; + (void)userdata_pointer_; + (void)strip; + return luaL_error(L_, "a non-zero error code (%d) was returned by the lua_Writer for the dump function", result_code); + } + + inline int dump_throw_on_error(lua_State* L_, int result_code, lua_Writer writer_function, void* userdata_pointer_, bool strip) { +#if SOL_IS_OFF(SOL_EXCEPTIONS) + return dump_panic_on_error(L_, result_code, writer_function, userdata_pointer_, strip); +#else + (void)L_; + (void)writer_function; + (void)userdata_pointer_; + (void)strip; + throw dump_error(result_code); +#endif // no exceptions stuff + } + +} // namespace sol + +// end of sol/dump_handler.hpp + +#include <cstdint> + +namespace sol { + template <typename ref_t, bool aligned = false> + class basic_function : public basic_object<ref_t> { + private: + using base_t = basic_object<ref_t>; + + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { + lua_call(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount)); + } + + template <std::size_t... I, typename... Ret> + auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) const { + luacall(n, lua_size<std::tuple<Ret...>>::value); + return stack::pop<std::tuple<Ret...>>(lua_state()); + } + + template <std::size_t I, typename Ret, meta::enable<meta::neg<std::is_void<Ret>>> = meta::enabler> + Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) const { + luacall(n, lua_size<Ret>::value); + return stack::pop<Ret>(lua_state()); + } + + template <std::size_t I> + void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const { + luacall(n, 0); + } + + unsafe_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { + int stacksize = lua_gettop(lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast<int>(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(lua_state()); + int returncount = poststacksize - (firstreturn - 1); + return unsafe_function_result(lua_state(), firstreturn, returncount); + } + + public: + using base_t::lua_state; + + basic_function() = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_function>>, meta::neg<std::is_same<base_t, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_function(T&& r) noexcept : base_t(std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_function<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_function>(lua_state(), -1, handler); + } +#endif // Safety + } + basic_function(const basic_function&) = default; + basic_function& operator=(const basic_function&) = default; + basic_function(basic_function&&) = default; + basic_function& operator=(basic_function&&) = default; + basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) { + } + basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) { + } + basic_function(lua_nil_t n) : base_t(n) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_function(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_function>(lua_state(), -1, handler); +#endif // Safety + } + basic_function(lua_State* L, int index = -1) : base_t(L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_function>(L, index, handler); +#endif // Safety + } + basic_function(lua_State* L, ref_index index) : base_t(L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_function>(lua_state(), -1, handler); +#endif // Safety + } + + template <typename Fx> + int dump(lua_Writer writer, void* userdata, bool strip, Fx&& on_error) const { + this->push(); + auto ppn = stack::push_popper_n<false>(this->lua_state(), 1); + int r = lua_dump(this->lua_state(), writer, userdata, strip ? 1 : 0); + if (r != 0) { + return on_error(this->lua_state(), r, writer, userdata, strip); + } + return r; + } + + int dump(lua_Writer writer, void* userdata, bool strip = false) const { + return dump(writer, userdata, strip, &dump_throw_on_error); + } + + template <typename Container = bytecode> + Container dump() const { + Container bc; + (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_panic_on_error); + return bc; + } + + template <typename Container = bytecode, typename Fx> + Container dump(Fx&& on_error) const { + Container bc; + (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error)); + return bc; + } + + template <typename... Args> + unsafe_function_result operator()(Args&&... args) const { + return call<>(std::forward<Args>(args)...); + } + + template <typename... Ret, typename... Args> + decltype(auto) operator()(types<Ret...>, Args&&... args) const { + return call<Ret...>(std::forward<Args>(args)...); + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args) const { + if (!aligned) { + base_t::push(); + } + int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); + return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), static_cast<std::ptrdiff_t>(pushcount)); + } + }; +} // namespace sol + +// end of sol/unsafe_function.hpp + +// beginning of sol/protected_function.hpp + +// beginning of sol/protected_handler.hpp + +#include <cstdint> + +namespace sol { namespace detail { + inline const char (&default_handler_name())[9] { + static const char name[9] = "sol.\xF0\x9F\x94\xA9"; + return name; + } + + template <bool ShouldPush, typename Target = reference> + struct protected_handler { + lua_State* m_L; + const Target& target; + int stack_index; + + protected_handler(std::false_type, lua_State* L_, const Target& target_) : m_L(L_), target(target_), stack_index(0) { + if (ShouldPush) { + stack_index = lua_gettop(L_) + 1; + target.push(L_); + } + } + + protected_handler(std::true_type, lua_State* L_, const Target& target_) : m_L(L_), target(target_), stack_index(0) { + if (ShouldPush) { + stack_index = target.stack_index(); + } + } + + protected_handler(lua_State* L_, const Target& target_) : protected_handler(meta::boolean<is_stack_based_v<Target>>(), L_, target_) { + } + + bool valid() const noexcept { + return ShouldPush; + } + + ~protected_handler() { + if constexpr (!is_stack_based_v<Target>) { + if (stack_index != 0) { + lua_remove(m_L, stack_index); + } + } + } + }; + + template <typename Base, typename T> + inline basic_function<Base> force_cast(T& p) { + return p; + } + + template <typename Reference, bool IsMainReference = false> + inline Reference get_default_handler(lua_State* L_) { + if (is_stack_based_v<Reference> || L_ == nullptr) + return Reference(L_, lua_nil); + L_ = IsMainReference ? main_thread(L_, L_) : L_; + lua_getglobal(L_, default_handler_name()); + auto pp = stack::pop_n(L_, 1); + return Reference(L_, -1); + } + + template <typename T> + inline void set_default_handler(lua_State* L, const T& ref) { + if (L == nullptr) { + return; + } + if (!ref.valid()) { +#if SOL_IS_ON(SOL_SAFE_STACK_CHECK) + luaL_checkstack(L, 1, detail::not_enough_stack_space_generic); +#endif // make sure stack doesn't overflow + lua_pushnil(L); + lua_setglobal(L, default_handler_name()); + } + else { + ref.push(L); + lua_setglobal(L, default_handler_name()); + } + } +}} // namespace sol::detail + +// end of sol/protected_handler.hpp + +#include <cstdint> +#include <algorithm> + +namespace sol { + + namespace detail { + template <bool ShouldPush_, typename Handler_> + inline void handle_protected_exception( + lua_State* L_, optional<const std::exception&> maybe_ex, const char* error, detail::protected_handler<ShouldPush_, Handler_>& handler_) { + handler_.stack_index = 0; + if (ShouldPush_) { + handler_.target.push(L_); + detail::call_exception_handler(L_, maybe_ex, error); + lua_call(L_, 1, 1); + } + else { + detail::call_exception_handler(L_, maybe_ex, error); + } + } + } // namespace detail + + template <typename Reference, bool Aligned = false, typename Handler = reference> + class basic_protected_function : public basic_object<Reference> { + private: + using base_t = basic_object<Reference>; + using handler_t = Handler; + inline static constexpr bool is_stack_handler_v = is_stack_based_v<handler_t>; + + basic_protected_function(std::true_type, const basic_protected_function& other_) noexcept + : base_t(other_), m_error_handler(other_.m_error_handler.copy(lua_state())) { + } + + basic_protected_function(std::false_type, const basic_protected_function& other_) noexcept : base_t(other_), m_error_handler(other_.m_error_handler) { + } + + public: + basic_protected_function() = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, + meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)), m_error_handler(get_default_handler(r.lua_state())) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_function<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_protected_function>(lua_state(), -1, handler); + } +#endif // Safety + } + basic_protected_function(const basic_protected_function& other_) noexcept + : basic_protected_function(meta::boolean<is_stateless_lua_reference_v<Handler>>(), other_) { + } + basic_protected_function& operator=(const basic_protected_function& other_) { + base_t::operator=(other_); + if constexpr (is_stateless_lua_reference_v<Handler>) { + m_error_handler.copy_assign(lua_state(), other_.m_error_handler); + } + else { + m_error_handler = other_.m_error_handler; + } + return *this; + } + basic_protected_function(basic_protected_function&&) = default; + basic_protected_function& operator=(basic_protected_function&&) = default; + basic_protected_function(const basic_function<base_t>& b) : basic_protected_function(b, get_default_handler(b.lua_state())) { + } + basic_protected_function(basic_function<base_t>&& b) : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) { + } + basic_protected_function(const basic_function<base_t>& b, handler_t eh) : base_t(b), m_error_handler(std::move(eh)) { + } + basic_protected_function(basic_function<base_t>&& b, handler_t eh) : base_t(std::move(b)), m_error_handler(std::move(eh)) { + } + basic_protected_function(const stack_reference& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { + } + basic_protected_function(stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) { + } + basic_protected_function(const stack_reference& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { + } + basic_protected_function(stack_reference&& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) { + } + + template <typename Super> + basic_protected_function(const proxy_base<Super>& p) : basic_protected_function(p, get_default_handler(p.lua_state())) { + } + template <typename Super> + basic_protected_function(proxy_base<Super>&& p) : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) { + } + template <typename Proxy, typename HandlerReference, + meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>, + meta::neg<is_lua_index<meta::unqualified_t<HandlerReference>>>> = meta::enabler> + basic_protected_function(Proxy&& p, HandlerReference&& eh) + : basic_protected_function(detail::force_cast<base_t>(p), make_reference<handler_t>(p.lua_state(), std::forward<HandlerReference>(eh))) { + } + + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_protected_function(lua_State* L_, T&& r) : basic_protected_function(L_, std::forward<T>(r), get_default_handler(L_)) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_protected_function(lua_State* L_, T&& r, handler_t eh) : base_t(L_, std::forward<T>(r)), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_protected_function>(lua_state(), -1, handler); +#endif // Safety + } + + basic_protected_function(lua_nil_t n) : base_t(n), m_error_handler(n) { + } + + basic_protected_function(lua_State* L_, int index_ = -1) : basic_protected_function(L_, index_, get_default_handler(L_)) { + } + basic_protected_function(lua_State* L_, int index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_protected_function>(L_, index_, handler); +#endif // Safety + } + basic_protected_function(lua_State* L_, absolute_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) { + } + basic_protected_function(lua_State* L_, absolute_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_protected_function>(L_, index_, handler); +#endif // Safety + } + basic_protected_function(lua_State* L_, raw_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) { + } + basic_protected_function(lua_State* L_, raw_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_protected_function>(L_, index_, handler); +#endif // Safety + } + basic_protected_function(lua_State* L_, ref_index index_) : basic_protected_function(L_, index_, get_default_handler(L_)) { + } + basic_protected_function(lua_State* L_, ref_index index_, handler_t eh) : base_t(L_, index_), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_protected_function>(lua_state(), -1, handler); +#endif // Safety + } + + using base_t::lua_state; + + template <typename Fx> + int dump(lua_Writer writer, void* userdata_pointer_, bool strip, Fx&& on_error) const { + this->push(); + auto ppn = stack::push_popper_n<false>(this->lua_state(), 1); + int r = lua_dump(this->lua_state(), writer, userdata_pointer_, strip ? 1 : 0); + if (r != 0) { + return on_error(this->lua_state(), r, writer, userdata_pointer_, strip); + } + return r; + } + + int dump(lua_Writer writer, void* userdata_pointer_, bool strip = false) const { + return dump(writer, userdata_pointer_, strip, &dump_pass_on_error); + } + + template <typename Container = bytecode> + Container dump() const { + Container bc; + (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, &dump_throw_on_error); + return bc; + } + + template <typename Container = bytecode, typename Fx> + Container dump(Fx&& on_error) const { + Container bc; + (void)dump(static_cast<lua_Writer>(&basic_insert_dump_writer<Container>), static_cast<void*>(&bc), false, std::forward<Fx>(on_error)); + return bc; + } + + template <typename... Args> + protected_function_result operator()(Args&&... args) const { + return call<>(std::forward<Args>(args)...); + } + + template <typename... Ret, typename... Args> + decltype(auto) operator()(types<Ret...>, Args&&... args) const { + return call<Ret...>(std::forward<Args>(args)...); + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args) const { + if constexpr (!Aligned) { + // we do not expect the function to already be on the stack: push it + if (m_error_handler.valid(lua_state())) { + detail::protected_handler<true, handler_t> h(lua_state(), m_error_handler); + base_t::push(); + int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); + return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); + } + else { + detail::protected_handler<false, handler_t> h(lua_state(), m_error_handler); + base_t::push(); + int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); + return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); + } + } + else { + // the function is already on the stack at the right location + if (m_error_handler.valid()) { + // the handler will be pushed onto the stack manually, + // since it's not already on the stack this means we need to push our own + // function on the stack too and swap things to be in-place + if constexpr (!is_stack_handler_v) { + // so, we need to remove the function at the top and then dump the handler out ourselves + base_t::push(); + } + detail::protected_handler<true, handler_t> h(lua_state(), m_error_handler); + if constexpr (!is_stack_handler_v) { + lua_replace(lua_state(), -3); + h.stack_index = lua_absindex(lua_state(), -2); + } + int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); + return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); + } + else { + detail::protected_handler<false, handler_t> h(lua_state(), m_error_handler); + int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); + return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); + } + } + } + + ~basic_protected_function() { + if constexpr (is_stateless_lua_reference_v<handler_t>) { + this->m_error_handler.reset(lua_state()); + } + } + + static handler_t get_default_handler(lua_State* L_) { + return detail::get_default_handler<handler_t, is_main_threaded_v<base_t>>(L_); + } + + template <typename T> + static void set_default_handler(const T& ref) { + detail::set_default_handler(ref.lua_state(), ref); + } + + auto get_error_handler() const noexcept { + if constexpr (is_stateless_lua_reference_v<handler_t>) { + if constexpr (is_stack_based_v<handler_t>) { + return stack_reference(lua_state(), m_error_handler.stack_index()); + } + else { + return basic_reference<is_main_threaded_v<base_t>>(lua_state(), ref_index(m_error_handler.registry_index())); + } + } + else { + return m_error_handler; + } + } + + template <typename ErrorHandler_> + void set_error_handler(ErrorHandler_&& error_handler_) noexcept { + static_assert(!is_stack_based_v<handler_t> || is_stack_based_v<ErrorHandler_>, + "A stack-based error handler can only be set from a parameter that is also stack-based."); + if constexpr (std::is_rvalue_reference_v<ErrorHandler_>) { + m_error_handler = std::forward<ErrorHandler_>(error_handler_); + } + else { + m_error_handler.copy_assign(lua_state(), std::forward<ErrorHandler_>(error_handler_)); + } + } + + void abandon () noexcept { + this->m_error_handler.abandon(); + base_t::abandon(); + } + + private: + handler_t m_error_handler; + + template <bool b> + call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t result_count_, detail::protected_handler<b, handler_t>& h) const { + return static_cast<call_status>(lua_pcall(lua_state(), static_cast<int>(argcount), static_cast<int>(result_count_), h.stack_index)); + } + + template <std::size_t... I, bool b, typename... Ret> + auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { + luacall(n, sizeof...(Ret), h); + return stack::pop<std::tuple<Ret...>>(lua_state()); + } + + template <std::size_t I, bool b, typename Ret> + Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { + luacall(n, 1, h); + return stack::pop<Ret>(lua_state()); + } + + template <std::size_t I, bool b> + void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { + luacall(n, 0, h); + } + + template <bool b> + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::protected_handler<b, handler_t>& h) const { + int stacksize = lua_gettop(lua_state()); + int poststacksize = stacksize; + int firstreturn = 1; + int returncount = 0; + call_status code = call_status::ok; +#if SOL_IS_ON(SOL_EXCEPTIONS) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) + try { +#endif // No Exceptions + firstreturn = (std::max)(1, static_cast<int>(stacksize - n - static_cast<int>(h.valid() && !is_stack_handler_v))); + code = luacall(n, LUA_MULTRET, h); + poststacksize = lua_gettop(lua_state()) - static_cast<int>(h.valid() && !is_stack_handler_v); + returncount = poststacksize - (firstreturn - 1); +#if SOL_IS_ON(SOL_EXCEPTIONS) && SOL_IS_OFF(SOL_PROPAGATE_EXCEPTIONS) + } + // Handle C++ errors thrown from C++ functions bound inside of lua + catch (const char* error) { + detail::handle_protected_exception(lua_state(), optional<const std::exception&>(nullopt), error, h); + firstreturn = lua_gettop(lua_state()); + return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (const std::string& error) { + detail::handle_protected_exception(lua_state(), optional<const std::exception&>(nullopt), error.c_str(), h); + firstreturn = lua_gettop(lua_state()); + return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (const std::exception& error) { + detail::handle_protected_exception(lua_state(), optional<const std::exception&>(error), error.what(), h); + firstreturn = lua_gettop(lua_state()); + return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); + } +#if SOL_IS_ON(SOL_EXCEPTIONS_CATCH_ALL) + // LuaJIT cannot have the catchall when the safe propagation is on + // but LuaJIT will swallow all C++ errors + // if we don't at least catch std::exception ones + catch (...) { + detail::handle_protected_exception(lua_state(), optional<const std::exception&>(nullopt), detail::protected_function_error, h); + firstreturn = lua_gettop(lua_state()); + return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime); + } +#endif // Always catch edge case +#else + // do not handle exceptions: they can be propogated into C++ and keep all type information / rich information +#endif // Exceptions vs. No Exceptions + return protected_function_result(lua_state(), firstreturn, returncount, returncount, code); + } + }; +} // namespace sol + +// end of sol/protected_function.hpp + +#include <functional> + +namespace sol { + template <typename... Ret, typename... Args> + decltype(auto) stack_proxy::call(Args&&... args) { + stack_function sf(this->lua_state(), this->stack_index()); + return sf.template call<Ret...>(std::forward<Args>(args)...); + } + + inline protected_function_result::protected_function_result(unsafe_function_result&& o) noexcept + : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()), popcount(o.return_count()), err(o.status()) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.abandon(); + } + + inline protected_function_result& protected_function_result::operator=(unsafe_function_result&& o) noexcept { + L = o.lua_state(); + index = o.stack_index(); + returncount = o.return_count(); + popcount = o.return_count(); + err = o.status(); + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.abandon(); + return *this; + } + + inline unsafe_function_result::unsafe_function_result(protected_function_result&& o) noexcept + : L(o.lua_state()), index(o.stack_index()), returncount(o.return_count()) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.abandon(); + } + inline unsafe_function_result& unsafe_function_result::operator=(protected_function_result&& o) noexcept { + L = o.lua_state(); + index = o.stack_index(); + returncount = o.return_count(); + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.abandon(); + return *this; + } + + namespace detail { + template <typename... R> + struct std_shim { + unsafe_function lua_func_; + + std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) { + } + + template <typename... Args> + meta::return_type_t<R...> operator()(Args&&... args) { + return lua_func_.call<R...>(std::forward<Args>(args)...); + } + }; + + template <> + struct std_shim<void> { + unsafe_function lua_func_; + + std_shim(unsafe_function lua_func) : lua_func_(std::move(lua_func)) { + } + + template <typename... Args> + void operator()(Args&&... args) { + lua_func_.call<void>(std::forward<Args>(args)...); + } + }; + } // namespace detail + + namespace stack { + template <typename Signature> + struct unqualified_getter<std::function<Signature>> { + typedef meta::bind_traits<Signature> fx_t; + typedef typename fx_t::args_list args_lists; + typedef meta::tuple_types<typename fx_t::return_type> return_types; + + template <typename... R> + static std::function<Signature> get_std_func(types<R...>, lua_State* L, int index) { + detail::std_shim<R...> fx(unsafe_function(L, index)); + return fx; + } + + static std::function<Signature> get(lua_State* L, int index, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::none || t == type::lua_nil) { + return nullptr; + } + return get_std_func(return_types(), L, index); + } + }; + + template <typename Allocator> + struct unqualified_getter<basic_bytecode<Allocator>> { + static basic_bytecode<Allocator> get(lua_State* L, int index, record& tracking) { + tracking.use(1); + stack_function sf(L, index); + return sf.dump(&dump_panic_on_error); + } + }; + } // namespace stack + +} // namespace sol + +// end of sol/function.hpp + +// beginning of sol/usertype.hpp + +// beginning of sol/usertype_core.hpp + +// beginning of sol/deprecate.hpp + +#ifndef SOL_DEPRECATED +#ifdef _MSC_VER +#define SOL_DEPRECATED __declspec(deprecated) +#elif __GNUC__ +#define SOL_DEPRECATED __attribute__((deprecated)) +#else +#define SOL_DEPRECATED [[deprecated]] +#endif // compilers +#endif // SOL_DEPRECATED + +namespace sol { namespace detail { + template <typename T> + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; +}} // namespace sol::detail + +// end of sol/deprecate.hpp + +// beginning of sol/usertype_container_launch.hpp + +// beginning of sol/usertype_container.hpp + +namespace sol { + + template <typename T> + struct usertype_container; + + namespace container_detail { + + template <typename T> + struct has_clear_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::clear)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_empty_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::empty)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_erase_after_test { + private: + template <typename C> + static meta::sfinae_yes_t test( + decltype(std::declval<C>().erase_after(std::declval<std::add_rvalue_reference_t<typename C::const_iterator>>()))*); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T, typename = void> + struct has_find_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::value_type>>()))*); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_find_test<T, std::enable_if_t<meta::is_lookup<T>::value>> { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(std::declval<C>().find(std::declval<std::add_rvalue_reference_t<typename C::key_type>>()))*); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_erase_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(std::declval<C>().erase(std::declval<typename C::iterator>()))*); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_erase_key_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(std::declval<C>().erase(std::declval<typename C::key_type>()))*); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_find_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::find)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_index_of_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::index_of)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_insert_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::insert)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_erase_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::erase)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_index_set_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::index_set)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_index_get_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::index_get)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_set_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::set)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_get_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::get)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_at_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::at)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_pairs_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::pairs)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_ipairs_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::ipairs)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_next_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::next)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_add_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::add)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + struct has_traits_size_test { + private: + template <typename C> + static meta::sfinae_yes_t test(decltype(&C::size)); + template <typename C> + static meta::sfinae_no_t test(...); + + public: + static constexpr bool value = std::is_same_v<decltype(test<T>(0)), meta::sfinae_yes_t>; + }; + + template <typename T> + using has_clear = meta::boolean<has_clear_test<T>::value>; + + template <typename T> + using has_empty = meta::boolean<has_empty_test<T>::value>; + + template <typename T> + using has_find = meta::boolean<has_find_test<T>::value>; + + template <typename T> + using has_erase = meta::boolean<has_erase_test<T>::value>; + + template <typename T> + using has_erase_key = meta::boolean<has_erase_key_test<T>::value>; + + template <typename T> + using has_erase_after = meta::boolean<has_erase_after_test<T>::value>; + + template <typename T> + using has_traits_get = meta::boolean<has_traits_get_test<T>::value>; + + template <typename T> + using has_traits_at = meta::boolean<has_traits_at_test<T>::value>; + + template <typename T> + using has_traits_set = meta::boolean<has_traits_set_test<T>::value>; + + template <typename T> + using has_traits_index_get = meta::boolean<has_traits_index_get_test<T>::value>; + + template <typename T> + using has_traits_index_set = meta::boolean<has_traits_index_set_test<T>::value>; + + template <typename T> + using has_traits_pairs = meta::boolean<has_traits_pairs_test<T>::value>; + + template <typename T> + using has_traits_ipairs = meta::boolean<has_traits_ipairs_test<T>::value>; + + template <typename T> + using has_traits_next = meta::boolean<has_traits_next_test<T>::value>; + + template <typename T> + using has_traits_add = meta::boolean<has_traits_add_test<T>::value>; + + template <typename T> + using has_traits_size = meta::boolean<has_traits_size_test<T>::value>; + + template <typename T> + using has_traits_clear = has_clear<T>; + + template <typename T> + using has_traits_empty = has_empty<T>; + + template <typename T> + using has_traits_find = meta::boolean<has_traits_find_test<T>::value>; + + template <typename T> + using has_traits_index_of = meta::boolean<has_traits_index_of_test<T>::value>; + + template <typename T> + using has_traits_insert = meta::boolean<has_traits_insert_test<T>::value>; + + template <typename T> + using has_traits_erase = meta::boolean<has_traits_erase_test<T>::value>; + + template <typename T> + struct is_forced_container : is_container<T> { }; + + template <typename T> + struct is_forced_container<as_container_t<T>> : std::true_type { }; + + template <typename T> + struct container_decay { + typedef T type; + }; + + template <typename T> + struct container_decay<as_container_t<T>> { + typedef T type; + }; + + template <typename T> + using container_decay_t = typename container_decay<meta::unqualified_t<T>>::type; + + template <typename T> + decltype(auto) get_key(std::false_type, T&& t) { + return std::forward<T>(t); + } + + template <typename T> + decltype(auto) get_key(std::true_type, T&& t) { + return t.first; + } + + template <typename T> + decltype(auto) get_value(std::false_type, T&& t) { + return std::forward<T>(t); + } + + template <typename T> + decltype(auto) get_value(std::true_type, T&& t) { + return t.second; + } + + template <typename X, typename = void> + struct usertype_container_default { + private: + typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T; + + public: + typedef lua_nil_t iterator; + typedef lua_nil_t value_type; + + static int at(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'at(index)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int get(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'get(key)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int index_get(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'container[key]' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int set(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'set(key, value)' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int index_set(lua_State* L_) { + return luaL_error( + L_, "sol: cannot call 'container[key] = value' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int add(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'add' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int insert(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'insert' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int find(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'find' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int index_of(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'index_of' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int size(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int clear(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'clear' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int empty(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'empty' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int erase(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'erase' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int next(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'next' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int pairs(lua_State* L_) { + return luaL_error(L_, "sol: cannot call '__pairs/pairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static int ipairs(lua_State* L_) { + return luaL_error(L_, "sol: cannot call '__ipairs' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + } + + static iterator begin(lua_State* L_, T&) { + luaL_error(L_, "sol: cannot call 'being' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + return lua_nil; + } + + static iterator end(lua_State* L_, T&) { + luaL_error(L_, "sol: cannot call 'end' on type '%s': it is not recognized as a container", detail::demangle<T>().c_str()); + return lua_nil; + } + }; + + template <typename X> + struct usertype_container_default<X, + std::enable_if_t<meta::all<is_forced_container<meta::unqualified_t<X>>, meta::has_value_type<meta::unqualified_t<container_decay_t<X>>>, + meta::has_iterator<meta::unqualified_t<container_decay_t<X>>>>::value>> { + private: + using T = std::remove_pointer_t<meta::unwrap_unqualified_t<container_decay_t<X>>>; + + private: + using deferred_uc = usertype_container<X>; + using is_associative = meta::is_associative<T>; + using is_lookup = meta::is_lookup<T>; + using is_ordered = meta::is_ordered<T>; + using is_matched_lookup = meta::is_matched_lookup<T>; + using iterator = typename T::iterator; + using value_type = typename T::value_type; + typedef meta::conditional_t<is_matched_lookup::value, std::pair<value_type, value_type>, + meta::conditional_t<is_associative::value || is_lookup::value, value_type, std::pair<std::ptrdiff_t, value_type>>> + KV; + typedef typename KV::first_type K; + typedef typename KV::second_type V; + typedef meta::conditional_t<is_matched_lookup::value, std::ptrdiff_t, K> next_K; + typedef decltype(*std::declval<iterator&>()) iterator_return; + typedef meta::conditional_t<is_associative::value || is_matched_lookup::value, std::add_lvalue_reference_t<V>, + meta::conditional_t<is_lookup::value, V, iterator_return>> + captured_type; + typedef typename meta::iterator_tag<iterator>::type iterator_category; + typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator; + typedef meta::conditional_t<is_input_iterator::value, V, decltype(detail::deref_move_only(std::declval<captured_type>()))> push_type; + typedef std::is_copy_assignable<V> is_copyable; + typedef meta::neg<meta::any<std::is_const<V>, std::is_const<std::remove_reference_t<iterator_return>>, meta::neg<is_copyable>>> is_writable; + typedef meta::unqualified_t<decltype(get_key(is_associative(), std::declval<std::add_lvalue_reference_t<value_type>>()))> key_type; + typedef meta::all<std::is_integral<K>, meta::neg<meta::any<is_associative, is_lookup>>> is_linear_integral; + + struct iter { + reference keep_alive; + T& source; + iterator it; + std::size_t index; + + iter(lua_State* L_, int stack_index, T& source_, iterator it_) : keep_alive(sol::main_thread(L_, L_), stack_index), source(source_), it(std::move(it_)), index(0) { + } + + ~iter() { + } + }; + + static auto& get_src(lua_State* L_) { +#if SOL_IS_ON(SOL_SAFE_USERTYPE) + auto p = stack::unqualified_check_get<T*>(L_, 1); + if (!p) { + luaL_error(L_, + "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", + detail::demangle<T>().c_str()); + } + if (p.value() == nullptr) { + luaL_error( + L_, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str()); + } + return *p.value(); +#else + return stack::unqualified_get<T>(L_, 1); +#endif // Safe getting with error + } + + static detail::error_result at_category(std::input_iterator_tag, lua_State* L_, T& self, std::ptrdiff_t pos) { + pos += deferred_uc::index_adjustment(L_, self); + if (pos < 0) { + return stack::push(L_, lua_nil); + } + auto it = deferred_uc::begin(L_, self); + auto e = deferred_uc::end(L_, self); + if (it == e) { + return stack::push(L_, lua_nil); + } + while (pos > 0) { + --pos; + ++it; + if (it == e) { + return stack::push(L_, lua_nil); + } + } + return get_associative(is_associative(), L_, it); + } + + static detail::error_result at_category(std::random_access_iterator_tag, lua_State* L_, T& self, std::ptrdiff_t pos) { + std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L_, self)); + pos += deferred_uc::index_adjustment(L_, self); + if (pos < 0 || pos >= len) { + return stack::push(L_, lua_nil); + } + auto it = std::next(deferred_uc::begin(L_, self), pos); + return get_associative(is_associative(), L_, it); + } + + static detail::error_result at_start(lua_State* L_, T& self, std::ptrdiff_t pos) { + return at_category(iterator_category(), L_, self, pos); + } + + template <typename Iter> + static detail::error_result get_associative(std::true_type, lua_State* L_, Iter& it) { + decltype(auto) v = *it; + return stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(v.second)); + } + + template <typename Iter> + static detail::error_result get_associative(std::false_type, lua_State* L_, Iter& it) { + return stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(*it)); + } + + static detail::error_result get_category(std::input_iterator_tag, lua_State* L_, T& self, K& key) { + key = static_cast<K>(key + deferred_uc::index_adjustment(L_, self)); + if (key < 0) { + return stack::push(L_, lua_nil); + } + auto it = deferred_uc::begin(L_, self); + auto e = deferred_uc::end(L_, self); + if (it == e) { + return stack::push(L_, lua_nil); + } + while (key > 0) { + --key; + ++it; + if (it == e) { + return stack::push(L_, lua_nil); + } + } + return get_associative(is_associative(), L_, it); + } + + static detail::error_result get_category(std::random_access_iterator_tag, lua_State* L_, T& self, K& key) { + std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L_, self)); + key = static_cast<K>(static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + if (key < 0 || key >= len) { + return stack::push(L_, lua_nil); + } + auto it = std::next(deferred_uc::begin(L_, self), key); + return get_associative(is_associative(), L_, it); + } + + static detail::error_result get_it(std::true_type, lua_State* L_, T& self, K& key) { + return get_category(iterator_category(), L_, self, key); + } + + static detail::error_result get_comparative(std::true_type, lua_State* L_, T& self, K& key) { + auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); }; + auto e = deferred_uc::end(L_, self); + auto it = std::find_if(deferred_uc::begin(L_, self), e, std::ref(fx)); + if (it == e) { + return stack::push(L_, lua_nil); + } + return get_associative(is_associative(), L_, it); + } + + static detail::error_result get_comparative(std::false_type, lua_State*, T&, K&) { + return detail::error_result("cannot get this key on '%s': no suitable way to increment iterator and compare to key value '%s'", + detail::demangle<T>().data(), + detail::demangle<K>().data()); + } + + static detail::error_result get_it(std::false_type, lua_State* L_, T& self, K& key) { + return get_comparative(meta::supports_op_equal<K, key_type>(), L_, self, key); + } + + static detail::error_result set_associative(std::true_type, iterator& it, stack_object value) { + decltype(auto) v = *it; + v.second = value.as<V>(); + return {}; + } + + static detail::error_result set_associative(std::false_type, iterator& it, stack_object value) { + decltype(auto) v = *it; + v = value.as<V>(); + return {}; + } + + static detail::error_result set_writable(std::true_type, lua_State*, T&, iterator& it, stack_object value) { + return set_associative(is_associative(), it, std::move(value)); + } + + static detail::error_result set_writable(std::false_type, lua_State*, T&, iterator&, stack_object) { + return detail::error_result( + "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data()); + } + + static detail::error_result set_category(std::input_iterator_tag, lua_State* L_, T& self, stack_object okey, stack_object value) { + decltype(auto) key = okey.as<K>(); + key = static_cast<K>(static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + auto e = deferred_uc::end(L_, self); + auto it = deferred_uc::begin(L_, self); + auto backit = it; + for (; key > 0 && it != e; --key, ++it) { + backit = it; + } + if (it == e) { + if (key == 0) { + return add_copyable(is_copyable(), L_, self, std::move(value), meta::has_insert_after<T>::value ? backit : it); + } + return detail::error_result("out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); + } + return set_writable(is_writable(), L_, self, it, std::move(value)); + } + + static detail::error_result set_category(std::random_access_iterator_tag, lua_State* L_, T& self, stack_object okey, stack_object value) { + decltype(auto) key = okey.as<K>(); + key = static_cast<K>(static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + if (key < 0) { + return detail::error_result("sol: out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str()); + } + std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L_, self)); + if (key == len) { + return add_copyable(is_copyable(), L_, self, std::move(value)); + } + else if (key >= len) { + return detail::error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); + } + auto it = std::next(deferred_uc::begin(L_, self), key); + return set_writable(is_writable(), L_, self, it, std::move(value)); + } + + static detail::error_result set_comparative(std::true_type, lua_State* L_, T& self, stack_object okey, stack_object value) { + decltype(auto) key = okey.as<K>(); + if (!is_writable::value) { + return detail::error_result( + "cannot perform a 'set': '%s's iterator reference is not writable (non-copy-assignable or const)", detail::demangle<T>().data()); + } + auto fx = [&](const value_type& r) -> bool { return key == get_key(is_associative(), r); }; + auto e = deferred_uc::end(L_, self); + auto it = std::find_if(deferred_uc::begin(L_, self), e, std::ref(fx)); + if (it == e) { + return {}; + } + return set_writable(is_writable(), L_, self, it, std::move(value)); + } + + static detail::error_result set_comparative(std::false_type, lua_State*, T&, stack_object, stack_object) { + return detail::error_result("cannot set this value on '%s': no suitable way to increment iterator or compare to '%s' key", + detail::demangle<T>().data(), + detail::demangle<K>().data()); + } + + template <typename Iter> + static detail::error_result set_associative_insert(std::true_type, lua_State*, T& self, Iter& it, K& key, stack_object value) { + if constexpr (meta::has_insert_with_iterator<T>::value) { + self.insert(it, value_type(key, value.as<V>())); + return {}; + } + else if constexpr (meta::has_insert<T>::value) { + self.insert(value_type(key, value.as<V>())); + return {}; + } + else { + (void)self; + (void)it; + (void)key; + return detail::error_result( + "cannot call 'set' on '%s': there is no 'insert' function on this associative type", detail::demangle<T>().c_str()); + } + } + + template <typename Iter> + static detail::error_result set_associative_insert(std::false_type, lua_State*, T& self, Iter& it, K& key, stack_object) { + if constexpr (meta::has_insert_with_iterator<T>::value) { + self.insert(it, key); + return {}; + } + else if constexpr (meta::has_insert<T>::value) { + self.insert(key); + return {}; + } + else { + (void)self; + (void)it; + (void)key; + return detail::error_result( + "cannot call 'set' on '%s': there is no 'insert' function on this non-associative type", detail::demangle<T>().c_str()); + } + } + + static detail::error_result set_associative_find(std::true_type, lua_State* L_, T& self, stack_object okey, stack_object value) { + decltype(auto) key = okey.as<K>(); + auto it = self.find(key); + if (it == deferred_uc::end(L_, self)) { + return set_associative_insert(is_associative(), L_, self, it, key, std::move(value)); + } + return set_writable(is_writable(), L_, self, it, std::move(value)); + } + + static detail::error_result set_associative_find(std::false_type, lua_State* L_, T& self, stack_object key, stack_object value) { + return set_comparative(meta::supports_op_equal<K, key_type>(), L_, self, std::move(key), std::move(value)); + } + + static detail::error_result set_it(std::true_type, lua_State* L_, T& self, stack_object key, stack_object value) { + return set_category(iterator_category(), L_, self, std::move(key), std::move(value)); + } + + static detail::error_result set_it(std::false_type, lua_State* L_, T& self, stack_object key, stack_object value) { + return set_associative_find(meta::all<has_find<T>, meta::any<is_associative, is_lookup>>(), L_, self, std::move(key), std::move(value)); + } + + template <bool idx_of = false> + static detail::error_result find_has_associative_lookup(std::true_type, lua_State* L_, T& self) { + if constexpr (!is_ordered::value && idx_of) { + (void)L_; + (void)self; + return detail::error_result("cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle<T>().data()); + } + else { + decltype(auto) key = stack::unqualified_get<K>(L_, 2); + auto it = self.find(key); + if (it == deferred_uc::end(L_, self)) { + return stack::push(L_, lua_nil); + } + if constexpr (idx_of) { + auto dist = std::distance(deferred_uc::begin(L_, self), it); + dist -= deferred_uc::index_adjustment(L_, self); + return stack::push(L_, dist); + } + else { + return get_associative(is_associative(), L_, it); + } + } + } + + template <bool idx_of = false> + static detail::error_result find_has_associative_lookup(std::false_type, lua_State* L_, T& self) { + if constexpr (!is_ordered::value && idx_of) { + (void)L_; + (void)self; + return detail::error_result("cannot perform an 'index_of': '%s's is not an ordered container", detail::demangle<T>().data()); + } + else { + decltype(auto) value = stack::unqualified_get<V>(L_, 2); + auto it = self.find(value); + if (it == deferred_uc::end(L_, self)) { + return stack::push(L_, lua_nil); + } + if constexpr (idx_of) { + auto dist = std::distance(deferred_uc::begin(L_, self), it); + dist -= deferred_uc::index_adjustment(L_, self); + return stack::push(L_, dist); + } + else { + return get_associative(is_associative(), L_, it); + } + } + } + + template <bool idx_of = false> + static detail::error_result find_has(std::true_type, lua_State* L_, T& self) { + return find_has_associative_lookup<idx_of>(meta::any<is_lookup, is_associative>(), L_, self); + } + + template <typename Iter> + static detail::error_result find_associative_lookup(std::true_type, lua_State* L_, T&, Iter& it, std::size_t) { + return get_associative(is_associative(), L_, it); + } + + template <typename Iter> + static detail::error_result find_associative_lookup(std::false_type, lua_State* L_, T& self, Iter&, std::size_t idx) { + idx = static_cast<std::size_t>(static_cast<std::ptrdiff_t>(idx) - deferred_uc::index_adjustment(L_, self)); + return stack::push(L_, idx); + } + + template <bool = false> + static detail::error_result find_comparative(std::false_type, lua_State*, T&) { + return detail::error_result("cannot call 'find' on '%s': there is no 'find' function and the value_type is not equality comparable", + detail::demangle<T>().c_str()); + } + + template <bool idx_of = false> + static detail::error_result find_comparative(std::true_type, lua_State* L_, T& self) { + decltype(auto) value = stack::unqualified_get<V>(L_, 2); + auto it = deferred_uc::begin(L_, self); + auto e = deferred_uc::end(L_, self); + std::size_t idx = 0; + for (;; ++it, ++idx) { + if (it == e) { + return stack::push(L_, lua_nil); + } + if (value == get_value(is_associative(), *it)) { + break; + } + } + return find_associative_lookup(meta::all<meta::boolean<!idx_of>, meta::any<is_lookup, is_associative>>(), L_, self, it, idx); + } + + template <bool idx_of = false> + static detail::error_result find_has(std::false_type, lua_State* L_, T& self) { + return find_comparative<idx_of>(meta::supports_op_equal<V>(), L_, self); + } + + template <typename Iter> + static detail::error_result add_insert_after(std::false_type, lua_State* L_, T& self, stack_object value, Iter&) { + return add_insert_after(std::false_type(), L_, self, value); + } + + static detail::error_result add_insert_after(std::false_type, lua_State*, T&, stack_object) { + return detail::error_result("cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", detail::demangle<T>().data()); + } + + template <typename Iter> + static detail::error_result add_insert_after(std::true_type, lua_State*, T& self, stack_object value, Iter& pos) { + self.insert_after(pos, value.as<V>()); + return {}; + } + + static detail::error_result add_insert_after(std::true_type, lua_State* L_, T& self, stack_object value) { + auto backit = self.before_begin(); + { + auto e = deferred_uc::end(L_, self); + for (auto it = deferred_uc::begin(L_, self); it != e; ++backit, ++it) { } + } + return add_insert_after(std::true_type(), L_, self, value, backit); + } + + template <typename Iter> + static detail::error_result add_insert(std::true_type, lua_State*, T& self, stack_object value, Iter& pos) { + self.insert(pos, value.as<V>()); + return {}; + } + + static detail::error_result add_insert(std::true_type, lua_State* L_, T& self, stack_object value) { + auto pos = deferred_uc::end(L_, self); + return add_insert(std::true_type(), L_, self, value, pos); + } + + template <typename Iter> + static detail::error_result add_insert(std::false_type, lua_State* L_, T& self, stack_object value, Iter& pos) { + return add_insert_after(meta::has_insert_after<T>(), L_, self, std::move(value), pos); + } + + static detail::error_result add_insert(std::false_type, lua_State* L_, T& self, stack_object value) { + return add_insert_after(meta::has_insert_after<T>(), L_, self, std::move(value)); + } + + template <typename Iter> + static detail::error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value, Iter&) { + self.push_back(value.as<V>()); + return {}; + } + + static detail::error_result add_push_back(std::true_type, lua_State*, T& self, stack_object value) { + self.push_back(value.as<V>()); + return {}; + } + + template <typename Iter> + static detail::error_result add_push_back(std::false_type, lua_State* L_, T& self, stack_object value, Iter& pos) { + return add_insert( + std::integral_constant < bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L_, self, value, pos); + } + + static detail::error_result add_push_back(std::false_type, lua_State* L_, T& self, stack_object value) { + return add_insert( + std::integral_constant < bool, meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), L_, self, value); + } + + template <typename Iter> + static detail::error_result add_associative(std::true_type, lua_State* L_, T& self, stack_object key, Iter& pos) { + if constexpr (meta::has_insert_with_iterator<T>::value) { + self.insert(pos, value_type(key.as<K>(), stack::unqualified_get<V>(L_, 3))); + return {}; + } + else if constexpr (meta::has_insert<T>::value) { + self.insert(value_type(key.as<K>(), stack::unqualified_get<V>(L_, 3))); + return {}; + } + else { + (void)L_; + (void)self; + (void)key; + (void)pos; + return detail::error_result( + "cannot call 'insert' on '%s': there is no 'insert' function on this associative type", detail::demangle<T>().c_str()); + } + } + + static detail::error_result add_associative(std::true_type, lua_State* L_, T& self, stack_object key) { + auto pos = deferred_uc::end(L_, self); + return add_associative(std::true_type(), L_, self, std::move(key), pos); + } + + template <typename Iter> + static detail::error_result add_associative(std::false_type, lua_State* L_, T& self, stack_object value, Iter& pos) { + return add_push_back(meta::has_push_back<T>(), L_, self, value, pos); + } + + static detail::error_result add_associative(std::false_type, lua_State* L_, T& self, stack_object value) { + return add_push_back(meta::has_push_back<T>(), L_, self, value); + } + + template <typename Iter> + static detail::error_result add_copyable(std::true_type, lua_State* L_, T& self, stack_object value, Iter& pos) { + return add_associative(is_associative(), L_, self, std::move(value), pos); + } + + static detail::error_result add_copyable(std::true_type, lua_State* L_, T& self, stack_object value) { + return add_associative(is_associative(), L_, self, value); + } + + template <typename Iter> + static detail::error_result add_copyable(std::false_type, lua_State* L_, T& self, stack_object value, Iter&) { + return add_copyable(std::false_type(), L_, self, std::move(value)); + } + + static detail::error_result add_copyable(std::false_type, lua_State*, T&, stack_object) { + return detail::error_result("cannot call 'add' on '%s': value_type is non-copyable", detail::demangle<T>().data()); + } + + static detail::error_result insert_lookup(std::true_type, lua_State* L_, T& self, stack_object, stack_object value) { + // TODO: should we warn or error about someone calling insert on an ordered / lookup container with no associativity? + return add_copyable(std::true_type(), L_, self, std::move(value)); + } + + static detail::error_result insert_lookup(std::false_type, lua_State* L_, T& self, stack_object where, stack_object value) { + auto it = deferred_uc::begin(L_, self); + auto key = where.as<K>(); + key = static_cast<K>(static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + std::advance(it, key); + self.insert(it, value.as<V>()); + return {}; + } + + static detail::error_result insert_after_has(std::true_type, lua_State* L_, T& self, stack_object where, stack_object value) { + auto key = where.as<K>(); + auto backit = self.before_begin(); + { + key = static_cast<K>(static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + auto e = deferred_uc::end(L_, self); + for (auto it = deferred_uc::begin(L_, self); key > 0; ++backit, ++it, --key) { + if (backit == e) { + return detail::error_result("sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); + } + } + } + self.insert_after(backit, value.as<V>()); + return {}; + } + + static detail::error_result insert_after_has(std::false_type, lua_State*, T&, stack_object, stack_object) { + return detail::error_result( + "cannot call 'insert' on '%s': no suitable or similar functionality detected on this container", detail::demangle<T>().data()); + } + + static detail::error_result insert_has(std::true_type, lua_State* L_, T& self, stack_object key, stack_object value) { + return insert_lookup(meta::any<is_associative, is_lookup>(), L_, self, std::move(key), std::move(value)); + } + + static detail::error_result insert_has(std::false_type, lua_State* L_, T& self, stack_object where, stack_object value) { + return insert_after_has(meta::has_insert_after<T>(), L_, self, where, value); + } + + static detail::error_result insert_copyable(std::true_type, lua_State* L_, T& self, stack_object key, stack_object value) { + return insert_has(std::integral_constant < bool, + meta::has_insert<T>::value || meta::has_insert_with_iterator<T>::value > (), + L_, + self, + std::move(key), + std::move(value)); + } + + static detail::error_result insert_copyable(std::false_type, lua_State*, T&, stack_object, stack_object) { + return detail::error_result("cannot call 'insert' on '%s': value_type is non-copyable", detail::demangle<T>().data()); + } + + static detail::error_result erase_integral(std::true_type, lua_State* L_, T& self, K& key) { + auto it = deferred_uc::begin(L_, self); + key = (static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + std::advance(it, key); + self.erase(it); + + return {}; + } + + static detail::error_result erase_integral(std::false_type, lua_State* L_, T& self, const K& key) { + auto fx = [&](const value_type& r) -> bool { return key == r; }; + auto e = deferred_uc::end(L_, self); + auto it = std::find_if(deferred_uc::begin(L_, self), e, std::ref(fx)); + if (it == e) { + return {}; + } + self.erase(it); + + return {}; + } + + static detail::error_result erase_associative_lookup(std::true_type, lua_State*, T& self, const K& key) { + self.erase(key); + return {}; + } + + static detail::error_result erase_associative_lookup(std::false_type, lua_State* L_, T& self, K& key) { + return erase_integral(std::is_integral<K>(), L_, self, key); + } + + static detail::error_result erase_after_has(std::true_type, lua_State* L_, T& self, K& key) { + auto backit = self.before_begin(); + { + key = static_cast<K>(static_cast<std::ptrdiff_t>(key) + deferred_uc::index_adjustment(L_, self)); + auto e = deferred_uc::end(L_, self); + for (auto it = deferred_uc::begin(L_, self); key > 0; ++backit, ++it, --key) { + if (backit == e) { + return detail::error_result("sol: out of bounds for erase on '%s'", detail::demangle<T>().c_str()); + } + } + } + self.erase_after(backit); + return {}; + } + + static detail::error_result erase_after_has(std::false_type, lua_State*, T&, const K&) { + return detail::error_result("sol: cannot call erase on '%s'", detail::demangle<T>().c_str()); + } + + static detail::error_result erase_key_has(std::true_type, lua_State* L_, T& self, K& key) { + return erase_associative_lookup(meta::any<is_associative, is_lookup>(), L_, self, key); + } + + static detail::error_result erase_key_has(std::false_type, lua_State* L_, T& self, K& key) { + return erase_after_has(has_erase_after<T>(), L_, self, key); + } + + static detail::error_result erase_has(std::true_type, lua_State* L_, T& self, K& key) { + return erase_associative_lookup(meta::any<is_associative, is_lookup>(), L_, self, key); + } + + static detail::error_result erase_has(std::false_type, lua_State* L_, T& self, K& key) { + return erase_key_has(has_erase_key<T>(), L_, self, key); + } + + static auto size_has(std::false_type, lua_State* L_, T& self) { + return std::distance(deferred_uc::begin(L_, self), deferred_uc::end(L_, self)); + } + + static auto size_has(std::true_type, lua_State*, T& self) { + return self.size(); + } + + static void clear_has(std::true_type, lua_State*, T& self) { + self.clear(); + } + + static void clear_has(std::false_type, lua_State* L_, T&) { + luaL_error(L_, "sol: cannot call clear on '%s'", detail::demangle<T>().c_str()); + } + + static bool empty_has(std::true_type, lua_State*, T& self) { + return self.empty(); + } + + static bool empty_has(std::false_type, lua_State* L_, T& self) { + return deferred_uc::begin(L_, self) == deferred_uc::end(L_, self); + } + + static detail::error_result get_associative_find(std::true_type, lua_State* L_, T& self, K& key) { + auto it = self.find(key); + if (it == deferred_uc::end(L_, self)) { + stack::push(L_, lua_nil); + return {}; + } + return get_associative(std::true_type(), L_, it); + } + + static detail::error_result get_associative_find(std::false_type, lua_State* L_, T& self, K& key) { + return get_it(is_linear_integral(), L_, self, key); + } + + static detail::error_result get_start(lua_State* L_, T& self, K& key) { + return get_associative_find(std::integral_constant < bool, is_associative::value&& has_find<T>::value > (), L_, self, key); + } + + static detail::error_result set_start(lua_State* L_, T& self, stack_object key, stack_object value) { + return set_it(is_linear_integral(), L_, self, std::move(key), std::move(value)); + } + + static std::size_t size_start(lua_State* L_, T& self) { + return static_cast<std::size_t>(size_has(meta::has_size<T>(), L_, self)); + } + + static void clear_start(lua_State* L_, T& self) { + clear_has(has_clear<T>(), L_, self); + } + + static bool empty_start(lua_State* L_, T& self) { + return empty_has(has_empty<T>(), L_, self); + } + + static detail::error_result erase_start(lua_State* L_, T& self, K& key) { + return erase_has(has_erase<T>(), L_, self, key); + } + + template <bool ip> + static int next_associative(std::true_type, lua_State* L_) { + iter& i = stack::unqualified_get<user<iter>>(L_, 1); + auto& source = i.source; + auto& it = i.it; + if (it == deferred_uc::end(L_, source)) { + return stack::push(L_, lua_nil); + } + int p; + if constexpr (ip) { + ++i.index; + p = stack::push_reference(L_, i.index); + } + else { + p = stack::push_reference(L_, it->first); + } + p += stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(it->second)); + std::advance(it, 1); + return p; + } + + template <bool> + static int next_associative(std::false_type, lua_State* L_) { + iter& i = stack::unqualified_get<user<iter>>(L_, 1); + auto& source = i.source; + auto& it = i.it; + next_K k = stack::unqualified_get<next_K>(L_, 2); + if (it == deferred_uc::end(L_, source)) { + return stack::push(L_, lua_nil); + } + int p; + if constexpr (std::is_integral_v<next_K>) { + p = stack::push_reference(L_, k + 1); + } + else { + p = stack::stack_detail::push_reference(L_, k + 1); + } + p += stack::stack_detail::push_reference<push_type>(L_, detail::deref_move_only(*it)); + std::advance(it, 1); + return p; + } + + template <bool ip> + static int next_iter(lua_State* L_) { + typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc; + return next_associative<ip>(is_assoc(), L_); + } + + template <bool ip> + static int pairs_associative(std::true_type, lua_State* L_) { + auto& src = get_src(L_); + stack::push(L_, next_iter<ip>); + stack::push<user<iter>>(L_, L_, 1, src, deferred_uc::begin(L_, src)); + stack::push(L_, lua_nil); + return 3; + } + + template <bool ip> + static int pairs_associative(std::false_type, lua_State* L_) { + auto& src = get_src(L_); + stack::push(L_, next_iter<ip>); + stack::push<user<iter>>(L_, L_, 1, src, deferred_uc::begin(L_, src)); + stack::push(L_, 0); + return 3; + } + + public: + static int at(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er; + { + std::ptrdiff_t pos = stack::unqualified_get<std::ptrdiff_t>(L_, 2); + er = at_start(L_, self, pos); + } + return handle_errors(L_, er); + } + + static int get(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er; + { + decltype(auto) key = stack::unqualified_get<K>(L_); + er = get_start(L_, self, key); + } + return handle_errors(L_, er); + } + + static int index_get(lua_State* L_) { + return get(L_); + } + + static int set(lua_State* L_) { + stack_object value = stack_object(L_, raw_index(3)); + if constexpr (is_linear_integral::value) { + // for non-associative containers, + // erasure only happens if it is the + // last index in the container + auto key = stack::get<K>(L_, 2); + auto self_size = deferred_uc::size(L_); + if (key == static_cast<K>(self_size)) { + if (type_of(L_, 3) == type::lua_nil) { + return erase(L_); + } + } + } + else { + if (type_of(L_, 3) == type::lua_nil) { + return erase(L_); + } + } + auto& self = get_src(L_); + detail::error_result er = set_start(L_, self, stack_object(L_, raw_index(2)), std::move(value)); + return handle_errors(L_, er); + } + + static int index_set(lua_State* L_) { + return set(L_); + } + + static int add(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er = add_copyable(is_copyable(), L_, self, stack_object(L_, raw_index(2))); + return handle_errors(L_, er); + } + + static int insert(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er = insert_copyable(is_copyable(), L_, self, stack_object(L_, raw_index(2)), stack_object(L_, raw_index(3))); + return handle_errors(L_, er); + } + + static int find(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er = find_has(has_find<T>(), L_, self); + return handle_errors(L_, er); + } + + static int index_of(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er = find_has<true>(has_find<T>(), L_, self); + return handle_errors(L_, er); + } + + static iterator begin(lua_State*, T& self) { + if constexpr (meta::has_begin_end_v<T>) { + return self.begin(); + } + else { + using std::begin; + return begin(self); + } + } + + static iterator end(lua_State*, T& self) { + if constexpr (meta::has_begin_end_v<T>) { + return self.end(); + } + else { + using std::end; + return end(self); + } + } + + static int size(lua_State* L_) { + auto& self = get_src(L_); + std::size_t r = size_start(L_, self); + return stack::push(L_, r); + } + + static int clear(lua_State* L_) { + auto& self = get_src(L_); + clear_start(L_, self); + return 0; + } + + static int erase(lua_State* L_) { + auto& self = get_src(L_); + detail::error_result er; + { + decltype(auto) key = stack::unqualified_get<K>(L_, 2); + er = erase_start(L_, self, key); + } + return handle_errors(L_, er); + } + + static int empty(lua_State* L_) { + auto& self = get_src(L_); + return stack::push(L_, empty_start(L_, self)); + } + + static std::ptrdiff_t index_adjustment(lua_State*, T&) { + return static_cast<std::ptrdiff_t>((SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_)); + } + + static int pairs(lua_State* L_) { + typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc; + return pairs_associative<false>(is_assoc(), L_); + } + + static int ipairs(lua_State* L_) { + typedef meta::any<is_associative, meta::all<is_lookup, meta::neg<is_matched_lookup>>> is_assoc; + return pairs_associative<true>(is_assoc(), L_); + } + + static int next(lua_State* L_) { + return stack::push(L_, next_iter<false>); + } + }; + + template <typename X> + struct usertype_container_default<X, std::enable_if_t<std::is_array<std::remove_pointer_t<meta::unwrap_unqualified_t<X>>>::value>> { + private: + typedef std::remove_pointer_t<meta::unwrap_unqualified_t<X>> T; + typedef usertype_container<X> deferred_uc; + + public: + typedef std::remove_extent_t<T> value_type; + typedef value_type* iterator; + + private: + struct iter { + reference keep_alive; + T& source; + iterator it; + + iter(lua_State* L_, int stack_index, T& source, iterator it) noexcept + : keep_alive(sol::main_thread(L_, L_), stack_index), source(source), it(std::move(it)) { + } + + ~iter() { + + } + }; + + static auto& get_src(lua_State* L_) { + auto p = stack::unqualified_check_get<T*>(L_, 1); +#if SOL_IS_ON(SOL_SAFE_USERTYPE) + if (!p) { + luaL_error(L_, + "sol: 'self' is not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", + detail::demangle<T>().c_str()); + } + if (p.value() == nullptr) { + luaL_error( + L_, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a '%s' type)", detail::demangle<T>().c_str()); + } +#endif // Safe getting with error + return *p.value(); + } + + static int find(std::true_type, lua_State* L_) { + T& self = get_src(L_); + decltype(auto) value = stack::unqualified_get<value_type>(L_, 2); + std::size_t N = std::extent<T>::value; + for (std::size_t idx = 0; idx < N; ++idx) { + using v_t = std::add_const_t<decltype(self[idx])>; + v_t v = self[idx]; + if (v == value) { + idx = static_cast<std::size_t>(static_cast<std::ptrdiff_t>(idx) - deferred_uc::index_adjustment(L_, self)); + return stack::push(L_, idx); + } + } + return stack::push(L_, lua_nil); + } + + static int find(std::false_type, lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'find' on '%s': no supported comparison operator for the value type", detail::demangle<T>().c_str()); + } + + static int next_iter(lua_State* L_) { + iter& i = stack::unqualified_get<user<iter>>(L_, 1); + auto& source = i.source; + auto& it = i.it; + std::size_t k = stack::unqualified_get<std::size_t>(L_, 2); + if (it == deferred_uc::end(L_, source)) { + return 0; + } + int p; + p = stack::push(L_, k + 1); + p += stack::push_reference(L_, detail::deref_move_only(*it)); + std::advance(it, 1); + return p; + } + + public: + static int clear(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'clear' on type '%s': cannot remove all items from a fixed array", detail::demangle<T>().c_str()); + } + + static int erase(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'erase' on type '%s': cannot remove an item from fixed arrays", detail::demangle<T>().c_str()); + } + + static int add(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'add' on type '%s': cannot add to fixed arrays", detail::demangle<T>().c_str()); + } + + static int insert(lua_State* L_) { + return luaL_error(L_, "sol: cannot call 'insert' on type '%s': cannot insert new entries into fixed arrays", detail::demangle<T>().c_str()); + } + + static int at(lua_State* L_) { + return get(L_); + } + + static int get(lua_State* L_) { + T& self = get_src(L_); + std::ptrdiff_t idx = stack::unqualified_get<std::ptrdiff_t>(L_, 2); + idx += deferred_uc::index_adjustment(L_, self); + if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value) || idx < 0) { + return stack::push(L_, lua_nil); + } + return stack::push_reference(L_, detail::deref_move_only(self[idx])); + } + + static int index_get(lua_State* L_) { + return get(L_); + } + + static int set(lua_State* L_) { + T& self = get_src(L_); + std::ptrdiff_t idx = stack::unqualified_get<std::ptrdiff_t>(L_, 2); + idx += deferred_uc::index_adjustment(L_, self); + if (idx >= static_cast<std::ptrdiff_t>(std::extent<T>::value)) { + return luaL_error(L_, "sol: index out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str()); + } + if (idx < 0) { + return luaL_error(L_, "sol: index out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str()); + } + self[idx] = stack::unqualified_get<value_type>(L_, 3); + return 0; + } + + static int index_set(lua_State* L_) { + return set(L_); + } + + static int index_of(lua_State* L_) { + return find(L_); + } + + static int find(lua_State* L_) { + return find(meta::supports_op_equal<value_type, value_type>(), L_); + } + + static int size(lua_State* L_) { + return stack::push(L_, std::extent<T>::value); + } + + static int empty(lua_State* L_) { + return stack::push(L_, std::extent<T>::value > 0); + } + + static int pairs(lua_State* L_) { + auto& src = get_src(L_); + stack::push(L_, next_iter); + stack::push<user<iter>>(L_, L_, 1, src, deferred_uc::begin(L_, src)); + stack::push(L_, 0); + return 3; + } + + static int ipairs(lua_State* L_) { + return pairs(L_); + } + + static int next(lua_State* L_) { + return stack::push(L_, next_iter); + } + + static std::ptrdiff_t index_adjustment(lua_State*, T&) { + return (SOL_CONTAINER_START_INDEX_I_) == 0 ? 0 : -(SOL_CONTAINER_START_INDEX_I_); + } + + static iterator begin(lua_State*, T& self) { + return std::addressof(self[0]); + } + + static iterator end(lua_State*, T& self) { + return std::addressof(self[0]) + std::extent<T>::value; + } + }; + + template <typename X> + struct usertype_container_default<usertype_container<X>> : usertype_container_default<X> { }; + } // namespace container_detail + + template <typename T> + struct usertype_container : container_detail::usertype_container_default<T> { }; + +} // namespace sol + +// end of sol/usertype_container.hpp + +#include <unordered_map> + +namespace sol { + + namespace container_detail { + template <typename X> + struct u_c_launch { + using T = std::remove_pointer_t<meta::unqualified_t<X>>; + using uc = usertype_container<T>; + using default_uc = usertype_container_default<T>; + + static inline int real_index_get_traits(std::true_type, lua_State* L) { + return uc::index_get(L); + } + + static inline int real_index_get_traits(std::false_type, lua_State* L) { + return default_uc::index_get(L); + } + + static inline int real_index_call(lua_State* L) { + static const std::unordered_map<string_view, lua_CFunction> calls { + { "at", &real_at_call }, + { "get", &real_get_call }, + { "set", &real_set_call }, + { "size", &real_length_call }, + { "add", &real_add_call }, + { "empty", &real_empty_call }, + { "insert", &real_insert_call }, + { "clear", &real_clear_call }, + { "find", &real_find_call }, + { "index_of", &real_index_of_call }, + { "erase", &real_erase_call }, + { "pairs", &pairs_call }, + { "next", &next_call }, + }; + auto maybenameview = stack::unqualified_check_get<string_view>(L, 2); + if (maybenameview) { + const string_view& name = *maybenameview; + auto it = calls.find(name); + if (it != calls.cend()) { + return stack::push(L, it->second); + } + } + return real_index_get_traits(container_detail::has_traits_index_get<uc>(), L); + } + + static inline int real_at_traits(std::true_type, lua_State* L) { + return uc::at(L); + } + + static inline int real_at_traits(std::false_type, lua_State* L) { + return default_uc::at(L); + } + + static inline int real_at_call(lua_State* L) { + return real_at_traits(container_detail::has_traits_at<uc>(), L); + } + + static inline int real_get_traits(std::true_type, lua_State* L) { + return uc::get(L); + } + + static inline int real_get_traits(std::false_type, lua_State* L) { + return default_uc::get(L); + } + + static inline int real_get_call(lua_State* L) { + return real_get_traits(container_detail::has_traits_get<uc>(), L); + } + + static inline int real_set_traits(std::true_type, lua_State* L) { + return uc::set(L); + } + + static inline int real_set_traits(std::false_type, lua_State* L) { + return default_uc::set(L); + } + + static inline int real_set_call(lua_State* L) { + return real_set_traits(container_detail::has_traits_set<uc>(), L); + } + + static inline int real_index_set_traits(std::true_type, lua_State* L) { + return uc::index_set(L); + } + + static inline int real_index_set_traits(std::false_type, lua_State* L) { + return default_uc::index_set(L); + } + + static inline int real_new_index_call(lua_State* L) { + return real_index_set_traits(container_detail::has_traits_index_set<uc>(), L); + } + + static inline int real_pairs_traits(std::true_type, lua_State* L) { + return uc::pairs(L); + } + + static inline int real_pairs_traits(std::false_type, lua_State* L) { + return default_uc::pairs(L); + } + + static inline int real_pairs_call(lua_State* L) { + return real_pairs_traits(container_detail::has_traits_pairs<uc>(), L); + } + + static inline int real_ipairs_traits(std::true_type, lua_State* L) { + return uc::ipairs(L); + } + + static inline int real_ipairs_traits(std::false_type, lua_State* L) { + return default_uc::ipairs(L); + } + + static inline int real_ipairs_call(lua_State* L) { + return real_ipairs_traits(container_detail::has_traits_ipairs<uc>(), L); + } + + static inline int real_next_traits(std::true_type, lua_State* L) { + return uc::next(L); + } + + static inline int real_next_traits(std::false_type, lua_State* L) { + return default_uc::next(L); + } + + static inline int real_next_call(lua_State* L) { + return real_next_traits(container_detail::has_traits_next<uc>(), L); + } + + static inline int real_size_traits(std::true_type, lua_State* L) { + return uc::size(L); + } + + static inline int real_size_traits(std::false_type, lua_State* L) { + return default_uc::size(L); + } + + static inline int real_length_call(lua_State* L) { + return real_size_traits(container_detail::has_traits_size<uc>(), L); + } + + static inline int real_add_traits(std::true_type, lua_State* L) { + return uc::add(L); + } + + static inline int real_add_traits(std::false_type, lua_State* L) { + return default_uc::add(L); + } + + static inline int real_add_call(lua_State* L) { + return real_add_traits(container_detail::has_traits_add<uc>(), L); + } + + static inline int real_insert_traits(std::true_type, lua_State* L) { + return uc::insert(L); + } + + static inline int real_insert_traits(std::false_type, lua_State* L) { + return default_uc::insert(L); + } + + static inline int real_insert_call(lua_State* L) { + return real_insert_traits(container_detail::has_traits_insert<uc>(), L); + } + + static inline int real_clear_traits(std::true_type, lua_State* L) { + return uc::clear(L); + } + + static inline int real_clear_traits(std::false_type, lua_State* L) { + return default_uc::clear(L); + } + + static inline int real_clear_call(lua_State* L) { + return real_clear_traits(container_detail::has_traits_clear<uc>(), L); + } + + static inline int real_empty_traits(std::true_type, lua_State* L) { + return uc::empty(L); + } + + static inline int real_empty_traits(std::false_type, lua_State* L) { + return default_uc::empty(L); + } + + static inline int real_empty_call(lua_State* L) { + return real_empty_traits(container_detail::has_traits_empty<uc>(), L); + } + + static inline int real_erase_traits(std::true_type, lua_State* L) { + return uc::erase(L); + } + + static inline int real_erase_traits(std::false_type, lua_State* L) { + return default_uc::erase(L); + } + + static inline int real_erase_call(lua_State* L) { + return real_erase_traits(container_detail::has_traits_erase<uc>(), L); + } + + static inline int real_find_traits(std::true_type, lua_State* L) { + return uc::find(L); + } + + static inline int real_find_traits(std::false_type, lua_State* L) { + return default_uc::find(L); + } + + static inline int real_find_call(lua_State* L) { + return real_find_traits(container_detail::has_traits_find<uc>(), L); + } + + static inline int real_index_of_call(lua_State* L) { + if constexpr (container_detail::has_traits_index_of<uc>()) { + return uc::index_of(L); + } + else { + return default_uc::index_of(L); + } + } + + static inline int add_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_add_call), (&real_add_call)>(L); + } + + static inline int erase_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_erase_call), (&real_erase_call)>(L); + } + + static inline int insert_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_insert_call), (&real_insert_call)>(L); + } + + static inline int clear_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_clear_call), (&real_clear_call)>(L); + } + + static inline int empty_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_empty_call), (&real_empty_call)>(L); + } + + static inline int find_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_find_call), (&real_find_call)>(L); + } + + static inline int index_of_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_index_of_call), (&real_index_of_call)>(L); + } + + static inline int length_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_length_call), (&real_length_call)>(L); + } + + static inline int pairs_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L); + } + + static inline int ipairs_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_ipairs_call), (&real_ipairs_call)>(L); + } + + static inline int next_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_next_call), (&real_next_call)>(L); + } + + static inline int at_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_at_call), (&real_at_call)>(L); + } + + static inline int get_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_get_call), (&real_get_call)>(L); + } + + static inline int set_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_set_call), (&real_set_call)>(L); + } + + static inline int index_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L); + } + + static inline int new_index_call(lua_State* L) { + return detail::typed_static_trampoline<decltype(&real_new_index_call), (&real_new_index_call)>(L); + } + }; + } // namespace container_detail + + namespace stack { + namespace stack_detail { + template <typename T, bool is_shim = false> + struct metatable_setup { + lua_State* L; + + metatable_setup(lua_State* L) : L(L) { + } + + void operator()() { + using meta_usertype_container + = container_detail::u_c_launch<meta::conditional_t<is_shim, as_container_t<std::remove_pointer_t<T>>, std::remove_pointer_t<T>>>; + static const char* metakey + = is_shim ? &usertype_traits<as_container_t<std::remove_pointer_t<T>>>::metatable()[0] : &usertype_traits<T>::metatable()[0]; + static const std::array<luaL_Reg, 20> reg = { { + // clang-format off + { "__pairs", &meta_usertype_container::pairs_call }, + { "__ipairs", &meta_usertype_container::ipairs_call }, + { "__len", &meta_usertype_container::length_call }, + { "__index", &meta_usertype_container::index_call }, + { "__newindex", &meta_usertype_container::new_index_call }, + { "pairs", &meta_usertype_container::pairs_call }, + { "next", &meta_usertype_container::next_call }, + { "at", &meta_usertype_container::at_call }, + { "get", &meta_usertype_container::get_call }, + { "set", &meta_usertype_container::set_call }, + { "size", &meta_usertype_container::length_call }, + { "empty", &meta_usertype_container::empty_call }, + { "clear", &meta_usertype_container::clear_call }, + { "insert", &meta_usertype_container::insert_call }, + { "add", &meta_usertype_container::add_call }, + { "find", &meta_usertype_container::find_call }, + { "index_of", &meta_usertype_container::index_of_call }, + { "erase", &meta_usertype_container::erase_call }, + std::is_pointer<T>::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy<T> }, + { nullptr, nullptr } + // clang-format on + } }; + + if (luaL_newmetatable(L, metakey) == 1) { + luaL_setfuncs(L, reg.data(), 0); + } + lua_setmetatable(L, -2); + } + }; + } // namespace stack_detail + + template <typename T> + struct unqualified_pusher<as_container_t<T>> { + using C = meta::unqualified_t<T>; + + static int push_lvalue(std::true_type, lua_State* L, const C& cont) { + stack_detail::metatable_setup<C*, true> fx(L); + return stack::push<detail::as_pointer_tag<const C>>(L, detail::with_function_tag(), fx, detail::ptr(cont)); + } + + static int push_lvalue(std::false_type, lua_State* L, const C& cont) { + stack_detail::metatable_setup<C, true> fx(L); + return stack::push<detail::as_value_tag<C>>(L, detail::with_function_tag(), fx, cont); + } + + static int push_rvalue(std::true_type, lua_State* L, C&& cont) { + stack_detail::metatable_setup<C, true> fx(L); + return stack::push<detail::as_value_tag<C>>(L, detail::with_function_tag(), fx, std::move(cont)); + } + + static int push_rvalue(std::false_type, lua_State* L, const C& cont) { + return push_lvalue(std::is_lvalue_reference<T>(), L, cont); + } + + static int push(lua_State* L, const as_container_t<T>& as_cont) { + return push_lvalue(std::is_lvalue_reference<T>(), L, as_cont.value()); + } + + static int push(lua_State* L, as_container_t<T>&& as_cont) { + return push_rvalue(meta::all<std::is_rvalue_reference<T>, meta::neg<std::is_lvalue_reference<T>>>(), L, std::forward<T>(as_cont.value())); + } + }; + + template <typename T> + struct unqualified_pusher<as_container_t<T*>> { + using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>; + + static int push(lua_State* L, T* cont) { + stack_detail::metatable_setup<C> fx(L); + return stack::push<detail::as_pointer_tag<T>>(L, detail::with_function_tag(), fx, cont); + } + }; + + template <typename T> + struct unqualified_pusher<T, std::enable_if_t<is_container_v<T>>> { + using C = T; + + template <typename... Args> + static int push(lua_State* L, Args&&... args) { + stack_detail::metatable_setup<C> fx(L); + return stack::push<detail::as_value_tag<T>>(L, detail::with_function_tag(), fx, std::forward<Args>(args)...); + } + }; + + template <typename T> + struct unqualified_pusher<T*, std::enable_if_t<is_container_v<T>>> { + using C = std::add_pointer_t<meta::unqualified_t<std::remove_pointer_t<T>>>; + + static int push(lua_State* L, T* cont) { + stack_detail::metatable_setup<C> fx(L); + return stack::push<detail::as_pointer_tag<T>>(L, detail::with_function_tag(), fx, cont); + } + }; + } // namespace stack + +} // namespace sol + +// end of sol/usertype_container_launch.hpp + +#include <sstream> +#include <type_traits> + +namespace sol { + namespace u_detail { + constexpr const lua_Integer toplevel_magic = static_cast<lua_Integer>(0xCCC2CCC1); + + constexpr const int environment_index = 1; + constexpr const int usertype_storage_index = 2; + constexpr const int usertype_storage_base_index = 3; + constexpr const int exact_function_index = 4; + constexpr const int magic_index = 5; + + constexpr const int simple_usertype_storage_index = 2; + constexpr const int index_function_index = 3; + constexpr const int new_index_function_index = 4; + + constexpr const int base_walking_failed_index = -32467; + constexpr const int lookup_failed_index = -42469; + + enum class submetatable_type { + // must be sequential + value, + reference, + unique, + const_reference, + const_value, + // must be LAST! + named + }; + + inline auto make_string_view(string_view s) { + return s; + } + +#if SOL_IS_ON(SOL_CHAR8_T) + inline auto make_string_view(const char8_t* s) { + return string_view(reinterpret_cast<const char*>(s)); + } +#endif + + inline auto make_string_view(call_construction) { + return string_view(to_string(meta_function::call_function)); + } + + inline auto make_string_view(meta_function mf) { + return string_view(to_string(mf)); + } + + inline auto make_string_view(base_classes_tag) { + return string_view(detail::base_class_cast_key()); + } + + template <typename Arg> + inline std::string make_string(Arg&& arg) { + string_view s = make_string_view(arg); + return std::string(s.data(), s.size()); + } + + inline int is_indexer(string_view s) { + if (s == to_string(meta_function::index)) { + return 1; + } + else if (s == to_string(meta_function::new_index)) { + return 2; + } + return 0; + } + + inline int is_indexer(meta_function mf) { + if (mf == meta_function::index) { + return 1; + } + else if (mf == meta_function::new_index) { + return 2; + } + return 0; + } + + inline int is_indexer(call_construction) { + return 0; + } + } // namespace u_detail + + namespace detail { + + template <typename T, typename IFx, typename Fx> + inline void insert_default_registrations(IFx&& ifx, Fx&& fx) { + (void)ifx; + (void)fx; + if constexpr (is_automagical<T>::value) { + if (fx(meta_function::less_than)) { + if constexpr (meta::supports_op_less<T>::value) { + lua_CFunction f = &comparsion_operator_wrap<T, std::less<>>; + ifx(meta_function::less_than, f); + } + } + if (fx(meta_function::less_than_or_equal_to)) { + if constexpr (meta::supports_op_less_equal<T>::value) { + lua_CFunction f = &comparsion_operator_wrap<T, std::less_equal<>>; + ifx(meta_function::less_than_or_equal_to, f); + } + } + if (fx(meta_function::equal_to)) { + if constexpr (meta::supports_op_equal<T>::value) { + lua_CFunction f = &comparsion_operator_wrap<T, std::equal_to<>>; + ifx(meta_function::equal_to, f); + } + else { + lua_CFunction f = &comparsion_operator_wrap<T, no_comp>; + ifx(meta_function::equal_to, f); + } + } + if (fx(meta_function::pairs)) { + ifx(meta_function::pairs, &container_detail::u_c_launch<as_container_t<T>>::pairs_call); + } + if (fx(meta_function::length)) { + if constexpr (meta::has_size<const T>::value || meta::has_size<T>::value) { + auto f = &default_size<T>; + ifx(meta_function::length, f); + } + } + if (fx(meta_function::to_string)) { + if constexpr (is_to_stringable_v<T>) { + if constexpr (!meta::is_probably_stateless_lambda_v<T> && !std::is_member_pointer_v<T>) { + auto f = &detail::static_trampoline<&default_to_string<T>>; + ifx(meta_function::to_string, f); + } + } + } + if (fx(meta_function::call_function)) { + if constexpr (is_callable_v<T>) { + if constexpr (meta::call_operator_deducible_v<T>) { + auto f = &c_call<decltype(&T::operator()), &T::operator()>; + ifx(meta_function::call_function, f); + } + } + } + } + } + } // namespace detail + + namespace stack { namespace stack_detail { + template <typename X> + void set_undefined_methods_on(stack_reference t) { + using T = std::remove_pointer_t<X>; + + lua_State* L = t.lua_state(); + + t.push(); + + detail::lua_reg_table l {}; + int index = 0; + detail::indexed_insert insert_fx(l, index); + detail::insert_default_registrations<T>(insert_fx, detail::property_always_true); + if constexpr (!std::is_pointer_v<X>) { + l[index] = luaL_Reg { to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<T>() }; + } + luaL_setfuncs(L, l, 0); + + // __type table + lua_createtable(L, 0, 2); + const std::string& name = detail::demangle<T>(); + lua_pushlstring(L, name.c_str(), name.size()); + lua_setfield(L, -2, "name"); + lua_CFunction is_func = &detail::is_check<T>; + lua_pushcclosure(L, is_func, 0); + lua_setfield(L, -2, "is"); + lua_setfield(L, t.stack_index(), to_string(meta_function::type).c_str()); + + t.pop(); + } + }} // namespace stack::stack_detail +} // namespace sol + +// end of sol/usertype_core.hpp + +// beginning of sol/usertype_storage.hpp + +#include <bitset> +#include <unordered_map> +#include <memory> + +namespace sol { namespace u_detail { + + struct usertype_storage_base; + template <typename T> + struct usertype_storage; + + optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L_, int index); + usertype_storage_base& get_usertype_storage_base(lua_State* L_, const char* gcmetakey); + template <typename T> + optional<usertype_storage<T>&> maybe_get_usertype_storage(lua_State* L_); + template <typename T> + usertype_storage<T>& get_usertype_storage(lua_State* L_); + + using index_call_function = int(lua_State*, void*); + using change_indexing_mem_func = void (usertype_storage_base::*)( + lua_State*, submetatable_type, void*, stateless_stack_reference&, lua_CFunction, lua_CFunction, lua_CFunction, lua_CFunction); + + struct index_call_storage { + index_call_function* index; + index_call_function* new_index; + void* binding_data; + }; + + struct new_index_call_storage : index_call_storage { + void* new_binding_data; + }; + + struct binding_base { + virtual void* data() = 0; + virtual ~binding_base() { + } + }; + + template <typename K, typename Fq, typename T = void> + struct binding : binding_base { + using uF = meta::unqualified_t<Fq>; + using F = meta::conditional_t<meta::is_c_str_of_v<uF, char> +#if SOL_IS_ON(SOL_CHAR8_T) + || meta::is_c_str_of_v<uF, char8_t> +#endif + || meta::is_c_str_of_v<uF, char16_t> || meta::is_c_str_of_v<uF, char32_t> || meta::is_c_str_of_v<uF, wchar_t>, + std::add_pointer_t<std::add_const_t<std::remove_all_extents_t<Fq>>>, std::decay_t<Fq>>; + F data_; + + template <typename... Args> + binding(Args&&... args) : data_(std::forward<Args>(args)...) { + } + + virtual void* data() override { + return static_cast<void*>(std::addressof(data_)); + } + + template <bool is_index = true, bool is_variable = false> + static inline int call_with_(lua_State* L_, void* target) { + constexpr int boost = !detail::is_non_factory_constructor<F>::value && std::is_same<K, call_construction>::value ? 1 : 0; + auto& f = *static_cast<F*>(target); + return call_detail::call_wrapped<T, is_index, is_variable, boost>(L_, f); + } + + template <bool is_index = true, bool is_variable = false> + static inline int call_(lua_State* L_) { + void* f = stack::get<void*>(L_, upvalue_index(usertype_storage_index)); + return call_with_<is_index, is_variable>(L_, f); + } + + template <bool is_index = true, bool is_variable = false> + static inline int call(lua_State* L_) { + int r = detail::typed_static_trampoline<decltype(&call_<is_index, is_variable>), (&call_<is_index, is_variable>)>(L_); + if constexpr (meta::is_specialization_of_v<uF, yielding_t>) { + return lua_yield(L_, r); + } + else { + return r; + } + } + + template <bool is_index = true, bool is_variable = false> + static inline int index_call_with_(lua_State* L_, void* target) { + if constexpr (!is_variable) { + if constexpr (is_lua_c_function_v<std::decay_t<F>>) { + auto& f = *static_cast<std::decay_t<F>*>(target); + return stack::push(L_, f); + } + else { + // set up upvalues + // for a chained call + int upvalues = 0; + upvalues += stack::push(L_, nullptr); + upvalues += stack::push(L_, target); + auto cfunc = &call<is_index, is_variable>; + return stack::push(L_, c_closure(cfunc, upvalues)); + } + } + else { + constexpr int boost = !detail::is_non_factory_constructor<F>::value && std::is_same<K, call_construction>::value ? 1 : 0; + auto& f = *static_cast<F*>(target); + return call_detail::call_wrapped<T, is_index, is_variable, boost>(L_, f); + } + } + + template <bool is_index = true, bool is_variable = false> + static inline int index_call_(lua_State* L_) { + void* f = stack::get<void*>(L_, upvalue_index(usertype_storage_index)); + return index_call_with_<is_index, is_variable>(L_, f); + } + + template <bool is_index = true, bool is_variable = false> + static inline int index_call(lua_State* L_) { + int r = detail::typed_static_trampoline<decltype(&index_call_<is_index, is_variable>), (&index_call_<is_index, is_variable>)>(L_); + if constexpr (meta::is_specialization_of_v<uF, yielding_t>) { + return lua_yield(L_, r); + } + else { + return r; + } + } + }; + + inline int index_fail(lua_State* L_) { + if (lua_getmetatable(L_, 1) == 1) { + int metatarget = lua_gettop(L_); + stack::get_field<false, true>(L_, stack_reference(L_, raw_index(2)), metatarget); + return 1; + } + // With runtime extensibility, we can't + // hard-error things. They have to + // return nil, like regular table types + return stack::push(L_, lua_nil); + } + + inline int index_target_fail(lua_State* L_, void*) { + return index_fail(L_); + } + + inline int new_index_fail(lua_State* L_) { + return luaL_error(L_, "sol: cannot set (new_index) into this object: no defined new_index operation on usertype"); + } + + inline int new_index_target_fail(lua_State* L_, void*) { + return new_index_fail(L_); + } + + struct string_for_each_metatable_func { + bool is_destruction = false; + bool is_index = false; + bool is_new_index = false; + bool is_static_index = false; + bool is_static_new_index = false; + bool poison_indexing = false; + bool is_unqualified_lua_CFunction = false; + bool is_unqualified_lua_reference = false; + std::string* p_key = nullptr; + reference* p_binding_ref = nullptr; + lua_CFunction call_func = nullptr; + index_call_storage* p_ics = nullptr; + usertype_storage_base* p_usb = nullptr; + void* p_derived_usb = nullptr; + lua_CFunction idx_call = nullptr, new_idx_call = nullptr, meta_idx_call = nullptr, meta_new_idx_call = nullptr; + change_indexing_mem_func change_indexing; + + void operator()(lua_State* L_, submetatable_type smt_, stateless_reference& fast_index_table_) { + std::string& key = *p_key; + usertype_storage_base& usb = *p_usb; + index_call_storage& ics = *p_ics; + + if (smt_ == submetatable_type::named) { + // do not override __call or + // other specific meta functions on named metatable: + // we need that for call construction + // and other amenities + return; + } + int fast_index_table_push = fast_index_table_.push(L_); + stateless_stack_reference t(L_, -fast_index_table_push); + if (poison_indexing) { + (usb.*change_indexing)(L_, smt_, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call); + } + if (is_destruction + && (smt_ == submetatable_type::reference || smt_ == submetatable_type::const_reference || smt_ == submetatable_type::named + || smt_ == submetatable_type::unique)) { + // gc does not apply to us here + // for reference types (raw T*, std::ref) + // for the named metatable itself, + // or for unique_usertypes, which do their own custom destroyion + t.pop(L_); + return; + } + if (is_index || is_new_index || is_static_index || is_static_new_index) { + // do not serialize the new_index and index functions here directly + // we control those... + t.pop(L_); + return; + } + if (is_unqualified_lua_CFunction) { + stack::set_field<false, true>(L_, key, call_func, t.stack_index()); + } + else if (is_unqualified_lua_reference) { + reference& binding_ref = *p_binding_ref; + stack::set_field<false, true>(L_, key, binding_ref, t.stack_index()); + } + else { + stack::set_field<false, true>(L_, key, make_closure(call_func, nullptr, ics.binding_data), t.stack_index()); + } + t.pop(L_); + } + }; + + struct lua_reference_func { + reference key; + reference value; + + void operator()(lua_State* L_, submetatable_type smt_, stateless_reference& fast_index_table_) { + if (smt_ == submetatable_type::named) { + return; + } + int fast_index_table_push = fast_index_table_.push(L_); + stateless_stack_reference t(L_, -fast_index_table_push); + stack::set_field<false, true>(L_, key, value, t.stack_index()); + t.pop(L_); + } + }; + + struct update_bases_func { + detail::inheritance_check_function base_class_check_func; + detail::inheritance_cast_function base_class_cast_func; + lua_CFunction idx_call, new_idx_call, meta_idx_call, meta_new_idx_call; + usertype_storage_base* p_usb; + void* p_derived_usb; + change_indexing_mem_func change_indexing; + + void operator()(lua_State* L_, submetatable_type smt_, stateless_reference& fast_index_table_) { + int fast_index_table_push = fast_index_table_.push(L_); + stateless_stack_reference t(L_, -fast_index_table_push); + stack::set_field(L_, detail::base_class_check_key(), reinterpret_cast<void*>(base_class_check_func), t.stack_index()); + stack::set_field(L_, detail::base_class_cast_key(), reinterpret_cast<void*>(base_class_cast_func), t.stack_index()); + // change indexing, forcefully + (p_usb->*change_indexing)(L_, smt_, p_derived_usb, t, idx_call, new_idx_call, meta_idx_call, meta_new_idx_call); + t.pop(L_); + } + }; + + struct binding_data_equals { + void* binding_data; + + binding_data_equals(void* b) : binding_data(b) { + } + + bool operator()(const std::unique_ptr<binding_base>& ptr) const { + return binding_data == ptr->data(); + } + }; + + struct usertype_storage_base { + public: + lua_State* m_L; + std::vector<std::unique_ptr<binding_base>> storage; + std::vector<std::unique_ptr<char[]>> string_keys_storage; + std::unordered_map<string_view, index_call_storage> string_keys; + std::unordered_map<stateless_reference, stateless_reference, stateless_reference_hash, stateless_reference_equals> auxiliary_keys; + stateless_reference value_index_table; + stateless_reference reference_index_table; + stateless_reference unique_index_table; + stateless_reference const_reference_index_table; + stateless_reference const_value_index_table; + stateless_reference named_index_table; + stateless_reference type_table; + stateless_reference gc_names_table; + stateless_reference named_metatable; + new_index_call_storage base_index; + new_index_call_storage static_base_index; + bool is_using_index; + bool is_using_new_index; + std::bitset<64> properties; + + usertype_storage_base(lua_State* L_) + : m_L(L_) + , storage() + , string_keys_storage() + , string_keys() + , auxiliary_keys(0, stateless_reference_hash(L_), stateless_reference_equals(L_)) + , value_index_table() + , reference_index_table() + , unique_index_table() + , const_reference_index_table() + , const_value_index_table() + , named_index_table() + , type_table(make_reference<stateless_reference>(L_, create)) + , gc_names_table(make_reference<stateless_reference>(L_, create)) + , named_metatable(make_reference<stateless_reference>(L_, create)) + , base_index() + , static_base_index() + , is_using_index(false) + , is_using_new_index(false) + , properties() { + base_index.binding_data = nullptr; + base_index.index = index_target_fail; + base_index.new_index = new_index_target_fail; + base_index.new_binding_data = nullptr; + static_base_index.binding_data = nullptr; + static_base_index.index = index_target_fail; + static_base_index.new_binding_data = this; + static_base_index.new_index = new_index_target_set; + } + + template <typename Fx> + void for_each_table(lua_State* L_, Fx&& fx) { + for (int i = 0; i < 6; ++i) { + submetatable_type smt = static_cast<submetatable_type>(i); + stateless_reference* p_fast_index_table = nullptr; + switch (smt) { + case submetatable_type::const_value: + p_fast_index_table = &this->const_value_index_table; + break; + case submetatable_type::reference: + p_fast_index_table = &this->reference_index_table; + break; + case submetatable_type::unique: + p_fast_index_table = &this->unique_index_table; + break; + case submetatable_type::const_reference: + p_fast_index_table = &this->const_reference_index_table; + break; + case submetatable_type::named: + p_fast_index_table = &this->named_index_table; + break; + case submetatable_type::value: + default: + p_fast_index_table = &this->value_index_table; + break; + } + fx(L_, smt, *p_fast_index_table); + } + } + + void add_entry(string_view sv, index_call_storage ics) { + string_keys_storage.emplace_back(new char[sv.size()]); + std::unique_ptr<char[]>& sv_storage = string_keys_storage.back(); + std::memcpy(sv_storage.get(), sv.data(), sv.size()); + string_view stored_sv(sv_storage.get(), sv.size()); + string_keys.insert_or_assign(std::move(stored_sv), std::move(ics)); + } + + template <typename T, typename... Bases> + void update_bases(lua_State* L_, bases<Bases...>) { + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), + "The size of this data pointer is too small to fit the inheritance checking function: Please file " + "a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), + "The size of this data pointer is too small to fit the inheritance checking function: Please file " + "a bug report."); + static_assert(!meta::any_same<T, Bases...>::value, "base classes cannot list the original class as part of the bases"); + if constexpr (sizeof...(Bases) > 0) { + (void)detail::swallow { 0, ((weak_derive<Bases>::value = true), 0)... }; + + void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this)); + + update_bases_func for_each_fx; + for_each_fx.base_class_check_func = &detail::inheritance<T>::template type_check_with<Bases...>; + for_each_fx.base_class_cast_func = &detail::inheritance<T>::template type_cast_with<Bases...>; + for_each_fx.idx_call = &usertype_storage<T>::template index_call_with_bases<false, Bases...>; + for_each_fx.new_idx_call = &usertype_storage<T>::template index_call_with_bases<true, Bases...>; + for_each_fx.meta_idx_call = &usertype_storage<T>::template meta_index_call_with_bases<false, Bases...>; + for_each_fx.meta_new_idx_call = &usertype_storage<T>::template meta_index_call_with_bases<true, Bases...>; + for_each_fx.p_usb = this; + for_each_fx.p_derived_usb = derived_this; + for_each_fx.change_indexing = &usertype_storage_base::change_indexing; + for_each_fx.p_derived_usb = derived_this; + this->for_each_table(L_, for_each_fx); + } + else { + (void)L_; + } + } + + void clear() { + if (value_index_table.valid(m_L)) { + stack::clear(m_L, value_index_table); + } + if (reference_index_table.valid(m_L)) { + stack::clear(m_L, reference_index_table); + } + if (unique_index_table.valid(m_L)) { + stack::clear(m_L, unique_index_table); + } + if (const_reference_index_table.valid(m_L)) { + stack::clear(m_L, const_reference_index_table); + } + if (const_value_index_table.valid(m_L)) { + stack::clear(m_L, const_value_index_table); + } + if (named_index_table.valid(m_L)) { + stack::clear(m_L, named_index_table); + } + if (type_table.valid(m_L)) { + stack::clear(m_L, type_table); + } + if (gc_names_table.valid(m_L)) { + stack::clear(m_L, gc_names_table); + } + if (named_metatable.valid(m_L)) { + auto pp = stack::push_pop(m_L, named_metatable); + int named_metatable_index = pp.index_of(named_metatable); + if (lua_getmetatable(m_L, named_metatable_index) == 1) { + stack::clear(m_L, absolute_index(m_L, -1)); + } + stack::clear(m_L, named_metatable); + } + + value_index_table.reset(m_L); + reference_index_table.reset(m_L); + unique_index_table.reset(m_L); + const_reference_index_table.reset(m_L); + const_value_index_table.reset(m_L); + named_index_table.reset(m_L); + type_table.reset(m_L); + gc_names_table.reset(m_L); + named_metatable.reset(m_L); + + storage.clear(); + string_keys.clear(); + auxiliary_keys.clear(); + string_keys_storage.clear(); + } + + template <bool is_new_index, typename Base> + static void base_walk_index(lua_State* L_, usertype_storage_base& self, bool& keep_going, int& base_result) { + using bases = typename base<Base>::type; + if (!keep_going) { + return; + } + (void)L_; + (void)self; +#if SOL_IS_ON(SOL_USE_UNSAFE_BASE_LOOKUP) + usertype_storage_base& base_storage = get_usertype_storage<Base>(L_); + base_result = self_index_call<is_new_index, true>(bases(), L_, base_storage); +#else + optional<usertype_storage<Base>&> maybe_base_storage = maybe_get_usertype_storage<Base>(L_); + if (static_cast<bool>(maybe_base_storage)) { + base_result = self_index_call<is_new_index, true>(bases(), L_, *maybe_base_storage); + keep_going = base_result == base_walking_failed_index; + } +#endif // Fast versus slow, safe base lookup + } + + template <bool is_new_index = false, bool base_walking = false, bool from_named_metatable = false, typename... Bases> + static inline int self_index_call(types<Bases...>, lua_State* L, usertype_storage_base& self) { + if constexpr (!from_named_metatable || !is_new_index) { + type k_type = stack::get<type>(L, 2); + if (k_type == type::string) { + index_call_storage* target = nullptr; + string_view k = stack::get<string_view>(L, 2); + { + auto it = self.string_keys.find(k); + if (it != self.string_keys.cend()) { + target = &it->second; + } + } + if (target != nullptr) { + // let the target decide what to do, unless it's named... + if constexpr (is_new_index) { + return (target->new_index)(L, target->binding_data); + } + else { + return (target->index)(L, target->binding_data); + } + } + } + else if (k_type != type::lua_nil && k_type != type::none) { + stateless_reference* target = nullptr; + { + stack_reference k = stack::get<stack_reference>(L, 2); + auto it = self.auxiliary_keys.find(k); + if (it != self.auxiliary_keys.cend()) { + target = &it->second; + } + } + if (target != nullptr) { + if constexpr (is_new_index) { + // set value and return + target->reset(L, 3); + return 0; + } + else { + // push target to return + // what we found + return stack::push(L, *target); + } + } + } + } + + // retrieve bases and walk through them. + bool keep_going = true; + int base_result; + (void)keep_going; + (void)base_result; + (void)detail::swallow { 1, (base_walk_index<is_new_index, Bases>(L, self, keep_going, base_result), 1)... }; + if constexpr (sizeof...(Bases) > 0) { + if (!keep_going) { + return base_result; + } + } + if constexpr (base_walking) { + // if we're JUST base-walking then don't index-fail, just + // return the false bits + return base_walking_failed_index; + } + else if constexpr (from_named_metatable) { + if constexpr (is_new_index) { + return self.static_base_index.new_index(L, self.static_base_index.new_binding_data); + } + else { + return self.static_base_index.index(L, self.static_base_index.binding_data); + } + } + else { + if constexpr (is_new_index) { + return self.base_index.new_index(L, self.base_index.new_binding_data); + } + else { + return self.base_index.index(L, self.base_index.binding_data); + } + } + } + + void change_indexing(lua_State* L_, submetatable_type submetatable_, void* derived_this_, stateless_stack_reference& t_, lua_CFunction index_, + lua_CFunction new_index_, lua_CFunction meta_index_, lua_CFunction meta_new_index_) { + usertype_storage_base& this_base = *this; + void* base_this = static_cast<void*>(&this_base); + + this->is_using_index |= true; + this->is_using_new_index |= true; + if (submetatable_ == submetatable_type::named) { + stack::set_field(L_, metatable_key, named_index_table, t_.stack_index()); + stateless_stack_reference stack_metametatable(L_, -named_metatable.push(L_)); + stack::set_field<false, true>(L_, + meta_function::index, + make_closure(meta_index_, nullptr, derived_this_, base_this, nullptr, toplevel_magic), + stack_metametatable.stack_index()); + stack::set_field<false, true>(L_, + meta_function::new_index, + make_closure(meta_new_index_, nullptr, derived_this_, base_this, nullptr, toplevel_magic), + stack_metametatable.stack_index()); + stack_metametatable.pop(L_); + } + else { + stack::set_field<false, true>( + L_, meta_function::index, make_closure(index_, nullptr, derived_this_, base_this, nullptr, toplevel_magic), t_.stack_index()); + stack::set_field<false, true>( + L_, meta_function::new_index, make_closure(new_index_, nullptr, derived_this_, base_this, nullptr, toplevel_magic), t_.stack_index()); + } + } + + template <typename T = void, typename Key, typename Value> + void set(lua_State* L, Key&& key, Value&& value); + + static int new_index_target_set(lua_State* L, void* target) { + usertype_storage_base& self = *static_cast<usertype_storage_base*>(target); + self.set(L, reference(L, raw_index(2)), reference(L, raw_index(3))); + return 0; + } + + ~usertype_storage_base() { + value_index_table.reset(m_L); + reference_index_table.reset(m_L); + unique_index_table.reset(m_L); + const_reference_index_table.reset(m_L); + const_value_index_table.reset(m_L); + named_index_table.reset(m_L); + type_table.reset(m_L); + gc_names_table.reset(m_L); + named_metatable.reset(m_L); + + auto auxiliary_first = auxiliary_keys.cbegin(); + auto auxiliary_last = auxiliary_keys.cend(); + while (auxiliary_first != auxiliary_last) { + // save a copy to what we're going to destroy + auto auxiliary_target = auxiliary_first; + // move the iterator up by 1 + ++auxiliary_first; + // extract the node and destroy the key + auto extracted_node = auxiliary_keys.extract(auxiliary_target); + extracted_node.key().reset(m_L); + extracted_node.mapped().reset(m_L); + // continue if auxiliary_first hasn't been exhausted + } + } + }; + + template <typename T> + struct usertype_storage : usertype_storage_base { + + using usertype_storage_base::usertype_storage_base; + + template <bool is_new_index, bool from_named_metatable> + static inline int index_call_(lua_State* L) { + using bases = typename base<T>::type; + usertype_storage_base& self = stack::get<light<usertype_storage_base>>(L, upvalue_index(usertype_storage_index)); + return self_index_call<is_new_index, false, from_named_metatable>(bases(), L, self); + } + + template <bool is_new_index, bool from_named_metatable, typename... Bases> + static inline int index_call_with_bases_(lua_State* L) { + using bases = types<Bases...>; + usertype_storage_base& self = stack::get<light<usertype_storage_base>>(L, upvalue_index(usertype_storage_index)); + return self_index_call<is_new_index, false, from_named_metatable>(bases(), L, self); + } + + template <bool is_new_index> + static inline int index_call(lua_State* L) { + return detail::static_trampoline<&index_call_<is_new_index, false>>(L); + } + + template <bool is_new_index, typename... Bases> + static inline int index_call_with_bases(lua_State* L) { + return detail::static_trampoline<&index_call_with_bases_<is_new_index, false, Bases...>>(L); + } + + template <bool is_new_index> + static inline int meta_index_call(lua_State* L) { + return detail::static_trampoline<&index_call_<is_new_index, true>>(L); + } + + template <bool is_new_index, typename... Bases> + static inline int meta_index_call_with_bases(lua_State* L) { + return detail::static_trampoline<&index_call_with_bases_<is_new_index, true, Bases...>>(L); + } + + template <typename Key, typename Value> + inline void set(lua_State* L, Key&& key, Value&& value); + }; + + template <typename T, typename Key, typename Value> + void usertype_storage_base::set(lua_State* L, Key&& key, Value&& value) { + using ValueU = meta::unwrap_unqualified_t<Value>; + using KeyU = meta::unwrap_unqualified_t<Key>; + using Binding = binding<KeyU, ValueU, T>; + using is_var_bind = is_variable_binding<ValueU>; + if constexpr (std::is_same_v<KeyU, call_construction>) { + (void)key; + std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value)); + Binding& b = *p_binding; + this->storage.push_back(std::move(p_binding)); + + this->named_index_table.push(L); + absolute_index metametatable_index(L, -1); + std::string_view call_metamethod_name = to_string(meta_function::call); + lua_pushlstring(L, call_metamethod_name.data(), call_metamethod_name.size()); + stack::push(L, nullptr); + stack::push(L, b.data()); + lua_CFunction target_func = &b.template call<false, false>; + lua_pushcclosure(L, target_func, 2); + lua_rawset(L, metametatable_index); + this->named_index_table.pop(L); + } + else if constexpr (std::is_same_v<KeyU, base_classes_tag>) { + (void)key; + this->update_bases<T>(L, std::forward<Value>(value)); + } + else if constexpr ((meta::is_string_like_or_constructible<KeyU>::value || std::is_same_v<KeyU, meta_function>)) { + std::string s = u_detail::make_string(std::forward<Key>(key)); + auto storage_it = this->storage.end(); + auto string_it = this->string_keys.find(s); + if (string_it != this->string_keys.cend()) { + const auto& binding_data = string_it->second.binding_data; + storage_it = std::find_if(this->storage.begin(), this->storage.end(), binding_data_equals(binding_data)); + this->string_keys.erase(string_it); + } + + std::unique_ptr<Binding> p_binding = std::make_unique<Binding>(std::forward<Value>(value)); + Binding& b = *p_binding; + if (storage_it != this->storage.cend()) { + *storage_it = std::move(p_binding); + } + else { + this->storage.push_back(std::move(p_binding)); + } + + bool is_index = (s == to_string(meta_function::index)); + bool is_new_index = (s == to_string(meta_function::new_index)); + bool is_static_index = (s == to_string(meta_function::static_index)); + bool is_static_new_index = (s == to_string(meta_function::static_new_index)); + bool is_destruction = s == to_string(meta_function::garbage_collect); + bool poison_indexing = (!is_using_index || !is_using_new_index) && (is_var_bind::value || is_index || is_new_index); + void* derived_this = static_cast<void*>(static_cast<usertype_storage<T>*>(this)); + index_call_storage ics; + ics.binding_data = b.data(); + ics.index = is_index || is_static_index ? &Binding::template call_with_<true, is_var_bind::value> + : &Binding::template index_call_with_<true, is_var_bind::value>; + ics.new_index = is_new_index || is_static_new_index ? &Binding::template call_with_<false, is_var_bind::value> + : &Binding::template index_call_with_<false, is_var_bind::value>; + + string_for_each_metatable_func for_each_fx; + for_each_fx.is_destruction = is_destruction; + for_each_fx.is_index = is_index; + for_each_fx.is_new_index = is_new_index; + for_each_fx.is_static_index = is_static_index; + for_each_fx.is_static_new_index = is_static_new_index; + for_each_fx.poison_indexing = poison_indexing; + for_each_fx.p_key = &s; + for_each_fx.p_ics = &ics; + if constexpr (is_lua_c_function_v<ValueU>) { + for_each_fx.is_unqualified_lua_CFunction = true; + for_each_fx.call_func = *static_cast<lua_CFunction*>(ics.binding_data); + } + else if constexpr (is_lua_reference_or_proxy_v<ValueU>) { + for_each_fx.is_unqualified_lua_reference = true; + for_each_fx.p_binding_ref = static_cast<reference*>(ics.binding_data); + } + else { + for_each_fx.call_func = &b.template call<false, is_var_bind::value>; + } + for_each_fx.p_usb = this; + for_each_fx.p_derived_usb = derived_this; + for_each_fx.idx_call = &usertype_storage<T>::template index_call<false>; + for_each_fx.new_idx_call = &usertype_storage<T>::template index_call<true>; + for_each_fx.meta_idx_call = &usertype_storage<T>::template meta_index_call<false>; + for_each_fx.meta_new_idx_call = &usertype_storage<T>::template meta_index_call<true>; + for_each_fx.change_indexing = &usertype_storage_base::change_indexing; + // set base index and base new_index + // functions here + if (is_index) { + this->base_index.index = ics.index; + this->base_index.binding_data = ics.binding_data; + } + if (is_new_index) { + this->base_index.new_index = ics.new_index; + this->base_index.new_binding_data = ics.binding_data; + } + if (is_static_index) { + this->static_base_index.index = ics.index; + this->static_base_index.binding_data = ics.binding_data; + } + if (is_static_new_index) { + this->static_base_index.new_index = ics.new_index; + this->static_base_index.new_binding_data = ics.binding_data; + } + this->for_each_table(L, for_each_fx); + this->add_entry(s, std::move(ics)); + } + else { + // the reference-based implementation might compare poorly and hash + // poorly in some cases... + if constexpr (is_lua_reference_v<KeyU> && is_lua_reference_v<ValueU>) { + if (key.get_type() == type::string) { + stack::push(L, key); + std::string string_key = stack::pop<std::string>(L); + this->set<T>(L, string_key, std::forward<Value>(value)); + } + else { + lua_reference_func ref_additions_fx { key, value }; + + this->for_each_table(L, ref_additions_fx); + this->auxiliary_keys.insert_or_assign(std::forward<Key>(key), std::forward<Value>(value)); + } + } + else { + reference ref_key = make_reference(L, std::forward<Key>(key)); + reference ref_value = make_reference(L, std::forward<Value>(value)); + lua_reference_func ref_additions_fx { ref_key, ref_value }; + + this->for_each_table(L, ref_additions_fx); + this->auxiliary_keys.insert_or_assign(std::move(ref_key), std::move(ref_value)); + } + } + } + + template <typename T> + template <typename Key, typename Value> + void usertype_storage<T>::set(lua_State* L, Key&& key, Value&& value) { + static_cast<usertype_storage_base&>(*this).set<T>(L, std::forward<Key>(key), std::forward<Value>(value)); + } + + template <typename T> + inline void clear_usertype_registry_names(lua_State* L) { + using u_traits = usertype_traits<T>; + using u_const_traits = usertype_traits<const T>; + using u_unique_traits = usertype_traits<d::u<T>>; + using u_ref_traits = usertype_traits<T*>; + using u_const_ref_traits = usertype_traits<T const*>; + + stack_reference registry(L, raw_index(LUA_REGISTRYINDEX)); + registry.push(); + // eliminate all named entries for this usertype + // in the registry (luaL_newmetatable does + // [name] = new table + // in registry upon creation + stack::set_field(L, &u_traits::metatable()[0], lua_nil, registry.stack_index()); + stack::set_field(L, &u_const_traits::metatable()[0], lua_nil, registry.stack_index()); + stack::set_field(L, &u_const_ref_traits::metatable()[0], lua_nil, registry.stack_index()); + stack::set_field(L, &u_ref_traits::metatable()[0], lua_nil, registry.stack_index()); + stack::set_field(L, &u_unique_traits::metatable()[0], lua_nil, registry.stack_index()); + registry.pop(); + } + + template <typename T> + inline int destroy_usertype_storage(lua_State* L) noexcept { + clear_usertype_registry_names<T>(L); + return detail::user_alloc_destroy<usertype_storage<T>>(L); + } + + template <typename T> + inline usertype_storage<T>& create_usertype_storage(lua_State* L) { + const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; + + // Make sure userdata's memory is properly in lua first, + // otherwise all the light userdata we make later will become invalid + int usertype_storage_push_count = stack::push<user<usertype_storage<T>>>(L, no_metatable, L); + stack_reference usertype_storage_ref(L, -usertype_storage_push_count); + + // create and push onto the stack a table to use as metatable for this GC + // we create a metatable to attach to the regular gc_table + // so that the destructor is called for the usertype storage + int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1)); + stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count); + // set the destroyion routine on the metatable + stack::set_field(L, meta_function::garbage_collect, &destroy_usertype_storage<T>, usertype_storage_metatable.stack_index()); + // set the metatable on the usertype storage userdata + stack::set_field(L, metatable_key, usertype_storage_metatable, usertype_storage_ref.stack_index()); + usertype_storage_metatable.pop(); + + // set the usertype storage and its metatable + // into the global table... + stack::set_field<true>(L, gcmetakey, usertype_storage_ref); + usertype_storage_ref.pop(); + + // then retrieve the lua-stored version so we have a well-pinned + // reference that does not die + stack::get_field<true>(L, gcmetakey); + usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L); + return target_umt; + } + + inline optional<usertype_storage_base&> maybe_as_usertype_storage_base(lua_State* L, int index) { + if (type_of(L, index) != type::lightuserdata) { + return nullopt; + } + usertype_storage_base& base_storage = *static_cast<usertype_storage_base*>(stack::get<void*>(L, index)); + return base_storage; + } + + inline optional<usertype_storage_base&> maybe_get_usertype_storage_base_inside(lua_State* L, int index) { + // okay, maybe we're looking at a table that is nested? + if (type_of(L, index) != type::table) { + return nullopt; + } + stack::get_field(L, meta_function::storage, index); + auto maybe_storage_base = maybe_as_usertype_storage_base(L, -1); + lua_pop(L, 1); + return maybe_storage_base; + } + + inline optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, int index) { + // If we can get the index directly as this type, go for it + auto maybe_already_is_usertype_storage_base = maybe_as_usertype_storage_base(L, index); + if (maybe_already_is_usertype_storage_base) { + return maybe_already_is_usertype_storage_base; + } + return maybe_get_usertype_storage_base_inside(L, index); + } + + inline optional<usertype_storage_base&> maybe_get_usertype_storage_base(lua_State* L, const char* gcmetakey) { + stack::get_field<true>(L, gcmetakey); + auto maybe_storage = maybe_as_usertype_storage_base(L, lua_gettop(L)); + lua_pop(L, 1); + return maybe_storage; + } + + inline usertype_storage_base& get_usertype_storage_base(lua_State* L, const char* gcmetakey) { + stack::get_field<true>(L, gcmetakey); + stack::record tracking; + usertype_storage_base& target_umt = stack::stack_detail::unchecked_unqualified_get<user<usertype_storage_base>>(L, -1, tracking); + lua_pop(L, 1); + return target_umt; + } + + template <typename T> + inline optional<usertype_storage<T>&> maybe_get_usertype_storage(lua_State* L) { + const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; + stack::get_field<true>(L, gcmetakey); + int target = lua_gettop(L); + if (!stack::check<user<usertype_storage<T>>>(L, target)) { + return nullopt; + } + usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L); + return target_umt; + } + + template <typename T> + inline usertype_storage<T>& get_usertype_storage(lua_State* L) { + const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; + stack::get_field<true>(L, gcmetakey); + usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L); + return target_umt; + } + + template <typename T> + inline void clear_usertype_storage(lua_State* L) { + using u_traits = usertype_traits<T>; + + const char* gcmetakey = &u_traits::gc_table()[0]; + stack::get_field<true>(L, gcmetakey); + if (!stack::check<user<usertype_storage<T>>>(L)) { + lua_pop(L, 1); + return; + } + usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L); + target_umt.clear(); + + clear_usertype_registry_names<T>(L); + + stack::set_field<true>(L, gcmetakey, lua_nil); + } + + template <typename T, automagic_flags enrollment_flags> + inline int register_usertype(lua_State* L_, automagic_enrollments enrollments_ = {}) { + using u_traits = usertype_traits<T>; + using u_const_traits = usertype_traits<const T>; + using u_unique_traits = usertype_traits<d::u<T>>; + using u_ref_traits = usertype_traits<T*>; + using u_const_ref_traits = usertype_traits<T const*>; + using uts = usertype_storage<T>; + + // always have __new_index point to usertype_storage method + // have __index always point to regular fast-lookup + // meta_method table + // if __new_index is invoked, runtime-swap + // to slow __index if necessary + // (no speed penalty because function calls + // are all read-only -- only depend on __index + // to retrieve function and then call happens VIA Lua) + + // __type entry: + // table contains key -> value lookup, + // where key is entry in metatable + // and value is type information as a string as + // best as we can give it + + // name entry: + // string that contains raw class name, + // as defined from C++ + + // is entry: + // checks if argument supplied is of type T + + // __storage entry: + // a light userdata pointing to the storage + // mostly to enable this new abstraction + // to not require the type name `T` + // to get at the C++ usertype storage within + + // we then let typical definitions potentially override these intrinsics + // it's the user's fault if they override things or screw them up: + // these names have been reserved and documented since sol2 + + // STEP 0: tell the old usertype (if it exists) + // to fuck off + clear_usertype_storage<T>(L_); + + // STEP 1: Create backing store for usertype storage + // Pretty much the most important step. + // STEP 2: Create Lua tables used for fast method indexing. + // This is done inside of the storage table's constructor + usertype_storage<T>& storage = create_usertype_storage<T>(L_); + usertype_storage_base& base_storage = storage; + void* light_storage = static_cast<void*>(&storage); + void* light_base_storage = static_cast<void*>(&base_storage); + + // STEP 3: set up GC escape hatch table entirely + storage.gc_names_table.push(L_); + stateless_stack_reference gnt(L_, -1); + stack::set_field(L_, submetatable_type::named, &u_traits::gc_table()[0], gnt.stack_index()); + stack::set_field(L_, submetatable_type::const_value, &u_const_traits::metatable()[0], gnt.stack_index()); + stack::set_field(L_, submetatable_type::const_reference, &u_const_ref_traits::metatable()[0], gnt.stack_index()); + stack::set_field(L_, submetatable_type::reference, &u_ref_traits::metatable()[0], gnt.stack_index()); + stack::set_field(L_, submetatable_type::unique, &u_unique_traits::metatable()[0], gnt.stack_index()); + stack::set_field(L_, submetatable_type::value, &u_traits::metatable()[0], gnt.stack_index()); + gnt.pop(L_); + + // STEP 4: add some useful information to the type table + stateless_stack_reference stacked_type_table(L_, -storage.type_table.push(L_)); + stack::set_field(L_, "name", detail::demangle<T>(), stacked_type_table.stack_index()); + stack::set_field(L_, "is", &detail::is_check<T>, stacked_type_table.stack_index()); + stacked_type_table.pop(L_); + + // STEP 5: create and hook up metatable, + // add intrinsics + // this one is the actual meta-handling table, + // the next one will be the one for + int for_each_backing_metatable_calls = 0; + auto for_each_backing_metatable = [&](lua_State* L_, submetatable_type smt_, stateless_reference& fast_index_table_) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + switch (smt_) { + case submetatable_type::const_value: + metakey = &u_const_traits::metatable()[0]; + break; + case submetatable_type::reference: + metakey = &u_ref_traits::metatable()[0]; + break; + case submetatable_type::unique: + metakey = &u_unique_traits::metatable()[0]; + break; + case submetatable_type::const_reference: + metakey = &u_const_ref_traits::metatable()[0]; + break; + case submetatable_type::named: + metakey = &u_traits::user_metatable()[0]; + break; + case submetatable_type::value: + default: + metakey = &u_traits::metatable()[0]; + break; + } + + luaL_newmetatable(L_, metakey); + if (smt_ == submetatable_type::named) { + // the named table itself + // gets the associated name value + storage.named_metatable.reset(L_, -1); + lua_pop(L_, 1); + // but the thing we perform the methods on + // is still the metatable of the named + // table + lua_createtable(L_, 0, 6); + } + stateless_stack_reference t(L_, -1); + fast_index_table_.reset(L_, t.stack_index()); + stack::set_field<false, true>(L_, meta_function::type, storage.type_table, t.stack_index()); + // destructible? serialize default destructor here + // otherwise, not destructible: serialize a "hey you messed up" + switch (smt_) { + case submetatable_type::const_reference: + case submetatable_type::reference: + case submetatable_type::named: + break; + case submetatable_type::unique: + if constexpr (std::is_destructible_v<T>) { + stack::set_field<false, true>(L_, meta_function::garbage_collect, &detail::unique_destroy<T>, t.stack_index()); + } + else { + stack::set_field<false, true>(L_, meta_function::garbage_collect, &detail::cannot_destroy<T>, t.stack_index()); + } + break; + case submetatable_type::value: + case submetatable_type::const_value: + default: + if constexpr (std::is_destructible_v<T>) { + stack::set_field<false, true>(L_, meta_function::garbage_collect, detail::make_destructor<T>(), t.stack_index()); + } + else { + stack::set_field<false, true>(L_, meta_function::garbage_collect, &detail::cannot_destroy<T>, t.stack_index()); + } + break; + } + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), + "The size of this data pointer is too small to fit the inheritance checking function: file a bug " + "report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), + "The size of this data pointer is too small to fit the inheritance checking function: file a bug " + "report."); + stack::set_field<false, true>(L_, detail::base_class_check_key(), reinterpret_cast<void*>(&detail::inheritance<T>::type_check), t.stack_index()); + stack::set_field<false, true>(L_, detail::base_class_cast_key(), reinterpret_cast<void*>(&detail::inheritance<T>::type_cast), t.stack_index()); + + auto prop_fx = detail::properties_enrollment_allowed(for_each_backing_metatable_calls, storage.properties, enrollments_); + auto insert_fx = [&L_, &t, &storage](meta_function mf, lua_CFunction reg) { + stack::set_field<false, true>(L_, mf, reg, t.stack_index()); + storage.properties[static_cast<std::size_t>(mf)] = true; + }; + detail::insert_default_registrations<T>(insert_fx, prop_fx); + + // There are no variables, so serialize the fast function stuff + // be sure to reset the index stuff to the non-fast version + // if the user ever adds something later! + if (smt_ == submetatable_type::named) { + // add escape hatch storage pointer and gc names + stack::set_field<false, true>(L_, meta_function::storage, light_base_storage, t.stack_index()); + stack::set_field<false, true>(L_, meta_function::gc_names, storage.gc_names_table, t.stack_index()); + + // fancy new_indexing when using the named table + { + absolute_index named_metatable_index(L_, -storage.named_metatable.push(L_)); + stack::set_field<false, true>(L_, metatable_key, t, named_metatable_index); + storage.named_metatable.pop(L_); + } + stack_reference stack_metametatable(L_, -storage.named_index_table.push(L_)); + stack::set_field<false, true>(L_, + meta_function::index, + make_closure(uts::template meta_index_call<false>, nullptr, light_storage, light_base_storage, nullptr, toplevel_magic), + stack_metametatable.stack_index()); + stack::set_field<false, true>(L_, + meta_function::new_index, + make_closure(uts::template meta_index_call<true>, nullptr, light_storage, light_base_storage, nullptr, toplevel_magic), + stack_metametatable.stack_index()); + stack_metametatable.pop(); + } + else { + // otherwise just plain for index, + // and elaborated for new_index + stack::set_field<false, true>(L_, meta_function::index, t, t.stack_index()); + stack::set_field<false, true>(L_, + meta_function::new_index, + make_closure(uts::template index_call<true>, nullptr, light_storage, light_base_storage, nullptr, toplevel_magic), + t.stack_index()); + storage.is_using_new_index = true; + } + + ++for_each_backing_metatable_calls; + fast_index_table_.reset(L_, t.stack_index()); + t.pop(L_); + }; + + storage.for_each_table(L_, for_each_backing_metatable); + + // can only use set AFTER we initialize all the metatables + if constexpr (std::is_default_constructible_v<T> && has_flag(enrollment_flags, automagic_flags::default_constructor)) { + if (enrollments_.default_constructor) { + storage.set(L_, meta_function::construct, constructors<T()>()); + } + } + + // return the named metatable we want names linked into + storage.named_metatable.push(L_); + return 1; + } +}} // namespace sol::u_detail + +// end of sol/usertype_storage.hpp + +// beginning of sol/usertype_proxy.hpp + +namespace sol { + template <typename Table, typename Key> + struct usertype_proxy : public proxy_base<usertype_proxy<Table, Key>> { + private: + using key_type = detail::proxy_key_t<Key>; + + template <typename T, std::size_t... I> + decltype(auto) tuple_get(std::index_sequence<I...>) const& { + return tbl.template traverse_get<T>(std::get<I>(key)...); + } + + template <typename T, std::size_t... I> + decltype(auto) tuple_get(std::index_sequence<I...>) && { + return tbl.template traverse_get<T>(std::get<I>(std::move(key))...); + } + + template <std::size_t... I, typename T> + void tuple_set(std::index_sequence<I...>, T&& value) & { + if constexpr (sizeof...(I) > 1) { + tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value)); + } + else { + tbl.set(std::get<I>(key)..., std::forward<T>(value)); + } + } + + template <std::size_t... I, typename T> + void tuple_set(std::index_sequence<I...>, T&& value) && { + if constexpr (sizeof...(I) > 1) { + tbl.traverse_set(std::get<I>(std::move(key))..., std::forward<T>(value)); + } + else { + tbl.set(std::get<I>(std::move(key))..., std::forward<T>(value)); + } + } + + public: + Table tbl; + key_type key; + + template <typename T> + usertype_proxy(Table table, T&& k) : tbl(table), key(std::forward<T>(k)) { + } + + template <typename T> + usertype_proxy& set(T&& item) & { + using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>; + tuple_set(idx_seq(), std::forward<T>(item)); + return *this; + } + + template <typename T> + usertype_proxy&& set(T&& item) && { + using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>; + std::move(*this).tuple_set(idx_seq(), std::forward<T>(item)); + return std::move(*this); + } + + template <typename T> + usertype_proxy& operator=(T&& other) & { + return set(std::forward<T>(other)); + } + + template <typename T> + usertype_proxy&& operator=(T&& other) && { + return std::move(*this).set(std::forward<T>(other)); + } + + template <typename T> + usertype_proxy& operator=(std::initializer_list<T> other) & { + return set(std::move(other)); + } + + template <typename T> + usertype_proxy&& operator=(std::initializer_list<T> other) && { + return std::move(*this).set(std::move(other)); + } + + template <typename T> + decltype(auto) get() const& { + using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>; + return tuple_get<T>(idx_seq()); + } + + template <typename T> + decltype(auto) get() && { + using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>; + return std::move(*this).template tuple_get<T>(idx_seq()); + } + + template <typename K> + decltype(auto) operator[](K&& k) const& { + auto keys = meta::tuplefy(key, std::forward<K>(k)); + return usertype_proxy<Table, decltype(keys)>(tbl, std::move(keys)); + } + + template <typename K> + decltype(auto) operator[](K&& k) & { + auto keys = meta::tuplefy(key, std::forward<K>(k)); + return usertype_proxy<Table, decltype(keys)>(tbl, std::move(keys)); + } + + template <typename K> + decltype(auto) operator[](K&& k) && { + auto keys = meta::tuplefy(std::move(key), std::forward<K>(k)); + return usertype_proxy<Table, decltype(keys)>(tbl, std::move(keys)); + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args) { +#if !defined(__clang__) && defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 191200000 + // MSVC is ass sometimes + return get<function>().call<Ret...>(std::forward<Args>(args)...); +#else + return get<function>().template call<Ret...>(std::forward<Args>(args)...); +#endif + } + + template <typename... Args> + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward<Args>(args)...); + } + + bool valid() const { + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); + lua_pop(lua_state(), p.levels); + return p; + } + + int push() const noexcept { + return push(this->lua_state()); + } + + int push(lua_State* L) const noexcept { + return get<reference>().push(L); + } + + type get_type() const { + type t = type::none; + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); + if (p) { + t = type_of(lua_state(), -1); + } + lua_pop(lua_state(), p.levels); + return t; + } + + lua_State* lua_state() const { + return tbl.lua_state(); + } + }; +} // namespace sol + +// end of sol/usertype_proxy.hpp + +// beginning of sol/metatable.hpp + +// beginning of sol/table_core.hpp + +// beginning of sol/table_proxy.hpp + +namespace sol { + + template <typename Table, typename Key> + struct table_proxy : public proxy_base<table_proxy<Table, Key>> { + private: + using key_type = detail::proxy_key_t<Key>; + + template <typename T, std::size_t... I> + decltype(auto) tuple_get(std::index_sequence<I...>) const& { + return tbl.template traverse_get<T>(std::get<I>(key)...); + } + + template <typename T, std::size_t... I> + decltype(auto) tuple_get(std::index_sequence<I...>) && { + return tbl.template traverse_get<T>(std::get<I>(std::move(key))...); + } + + template <std::size_t... I, typename T> + void tuple_set(std::index_sequence<I...>, T&& value) & { + tbl.traverse_set(std::get<I>(key)..., std::forward<T>(value)); + } + + template <std::size_t... I, typename T> + void tuple_set(std::index_sequence<I...>, T&& value) && { + tbl.traverse_set(std::get<I>(std::move(key))..., std::forward<T>(value)); + } + + auto setup_table(std::true_type) { + auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>, global_table>>(lua_state(), key, tbl.stack_index()); + lua_pop(lua_state(), p.levels); + return p; + } + + bool is_valid(std::false_type) { + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field<std::is_same_v<meta::unqualified_t<Table>, global_table>>(lua_state(), key, lua_gettop(lua_state())); + lua_pop(lua_state(), p.levels); + return p; + } + + public: + Table tbl; + key_type key; + + template <typename T> + table_proxy(Table table, T&& k) : tbl(table), key(std::forward<T>(k)) { + } + + template <typename T> + table_proxy& set(T&& item) & { + tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item)); + return *this; + } + + template <typename T> + table_proxy&& set(T&& item) && { + std::move(*this).tuple_set(std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>(), std::forward<T>(item)); + return std::move(*this); + } + + template <typename... Args> + table_proxy& set_function(Args&&... args) & { + tbl.set_function(key, std::forward<Args>(args)...); + return *this; + } + + template <typename... Args> + table_proxy&& set_function(Args&&... args) && { + tbl.set_function(std::move(key), std::forward<Args>(args)...); + return std::move(*this); + } + + template <typename T> + table_proxy& operator=(T&& other) & { + using Tu = meta::unwrap_unqualified_t<T>; + if constexpr (!is_lua_reference_or_proxy_v<Tu> && meta::is_invocable_v<Tu>) { + return set_function(std::forward<T>(other)); + } + else { + return set(std::forward<T>(other)); + } + } + + template <typename T> + table_proxy&& operator=(T&& other) && { + using Tu = meta::unwrap_unqualified_t<T>; + if constexpr (!is_lua_reference_or_proxy_v<Tu> && meta::is_invocable_v<Tu> && !detail::is_msvc_callable_rigged_v<T>) { + return std::move(*this).set_function(std::forward<T>(other)); + } + else { + return std::move(*this).set(std::forward<T>(other)); + } + } + + template <typename T> + table_proxy& operator=(std::initializer_list<T> other) & { + return set(std::move(other)); + } + + template <typename T> + table_proxy&& operator=(std::initializer_list<T> other) && { + return std::move(*this).set(std::move(other)); + } + + template <typename T> + bool is() const { + typedef decltype(get<T>()) U; + optional<U> option = this->get<optional<U>>(); + return option.has_value(); + } + + template <typename T> + decltype(auto) get() const& { + using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>; + return tuple_get<T>(idx_seq()); + } + + template <typename T> + decltype(auto) get() && { + using idx_seq = std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<key_type>>>; + return std::move(*this).template tuple_get<T>(idx_seq()); + } + + template <typename T> + decltype(auto) get_or(T&& otherwise) const { + typedef decltype(get<T>()) U; + optional<U> option = get<optional<U>>(); + if (option) { + return static_cast<U>(option.value()); + } + return static_cast<U>(std::forward<T>(otherwise)); + } + + template <typename T, typename D> + decltype(auto) get_or(D&& otherwise) const { + optional<T> option = get<optional<T>>(); + if (option) { + return static_cast<T>(option.value()); + } + return static_cast<T>(std::forward<D>(otherwise)); + } + + template <typename T> + decltype(auto) get_or_create() { + return get_or_create<T>(new_table()); + } + + template <typename T, typename Otherwise> + decltype(auto) get_or_create(Otherwise&& other) { + if (!this->valid()) { + this->set(std::forward<Otherwise>(other)); + } + return get<T>(); + } + + template <typename K> + decltype(auto) operator[](K&& k) const& { + auto keys = meta::tuplefy(key, std::forward<K>(k)); + return table_proxy<Table, decltype(keys)>(tbl, std::move(keys)); + } + + template <typename K> + decltype(auto) operator[](K&& k) & { + auto keys = meta::tuplefy(key, std::forward<K>(k)); + return table_proxy<Table, decltype(keys)>(tbl, std::move(keys)); + } + + template <typename K> + decltype(auto) operator[](K&& k) && { + auto keys = meta::tuplefy(std::move(key), std::forward<K>(k)); + return table_proxy<Table, decltype(keys)>(tbl, std::move(keys)); + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args) { + lua_State* L = this->lua_state(); + push(L); + int idx = lua_gettop(L); + stack_aligned_function func(L, idx); + return func.call<Ret...>(std::forward<Args>(args)...); + } + + template <typename... Args> + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward<Args>(args)...); + } + + bool valid() const { + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); + lua_pop(lua_state(), p.levels); + return p; + } + + int push() const noexcept { + return push(this->lua_state()); + } + + int push(lua_State* L) const noexcept { + if constexpr (std::is_same_v<meta::unqualified_t<Table>, global_table> || is_stack_table_v<meta::unqualified_t<Table>>) { + auto pp = stack::push_pop<true>(tbl); + int tableindex = pp.index_of(tbl); + int top_index = lua_gettop(L); + stack::get_field<true>(lua_state(), key, tableindex); + lua_replace(L, top_index + 1); + lua_settop(L, top_index + 1); + } + else { + auto pp = stack::push_pop<false>(tbl); + int tableindex = pp.index_of(tbl); + int aftertableindex = lua_gettop(L); + stack::get_field<false>(lua_state(), key, tableindex); + lua_replace(L, tableindex); + lua_settop(L, aftertableindex + 1); + } + return 1; + } + + type get_type() const { + type t = type::none; + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field<std::is_same<meta::unqualified_t<Table>, global_table>::value>(lua_state(), key, lua_gettop(lua_state())); + if (p) { + t = type_of(lua_state(), -1); + } + lua_pop(lua_state(), p.levels); + return t; + } + + lua_State* lua_state() const { + return tbl.lua_state(); + } + + table_proxy& force() { + if (!this->valid()) { + this->set(new_table()); + } + return *this; + } + }; + + template <typename Table, typename Key, typename T> + inline bool operator==(T&& left, const table_proxy<Table, Key>& right) { + using G = decltype(stack::get<T>(nullptr, 0)); + return right.template get<optional<G>>() == left; + } + + template <typename Table, typename Key, typename T> + inline bool operator==(const table_proxy<Table, Key>& right, T&& left) { + using G = decltype(stack::get<T>(nullptr, 0)); + return right.template get<optional<G>>() == left; + } + + template <typename Table, typename Key, typename T> + inline bool operator!=(T&& left, const table_proxy<Table, Key>& right) { + using G = decltype(stack::get<T>(nullptr, 0)); + return right.template get<optional<G>>() != left; + } + + template <typename Table, typename Key, typename T> + inline bool operator!=(const table_proxy<Table, Key>& right, T&& left) { + using G = decltype(stack::get<T>(nullptr, 0)); + return right.template get<optional<G>>() != left; + } + + template <typename Table, typename Key> + inline bool operator==(lua_nil_t, const table_proxy<Table, Key>& right) { + return !right.valid(); + } + + template <typename Table, typename Key> + inline bool operator==(const table_proxy<Table, Key>& right, lua_nil_t) { + return !right.valid(); + } + + template <typename Table, typename Key> + inline bool operator!=(lua_nil_t, const table_proxy<Table, Key>& right) { + return right.valid(); + } + + template <typename Table, typename Key> + inline bool operator!=(const table_proxy<Table, Key>& right, lua_nil_t) { + return right.valid(); + } + + template <bool b> + template <typename Super> + basic_reference<b>& basic_reference<b>::operator=(proxy_base<Super>&& r) { + basic_reference<b> v = r; + this->operator=(std::move(v)); + return *this; + } + + template <bool b> + template <typename Super> + basic_reference<b>& basic_reference<b>::operator=(const proxy_base<Super>& r) { + basic_reference<b> v = r; + this->operator=(std::move(v)); + return *this; + } + + namespace stack { + template <typename Table, typename Key> + struct unqualified_pusher<table_proxy<Table, Key>> { + static int push(lua_State* L, const table_proxy<Table, Key>& p) { + return p.push(L); + } + }; + } // namespace stack +} // namespace sol + +// end of sol/table_proxy.hpp + +// beginning of sol/table_iterator.hpp + +#include <iterator> + +namespace sol { + + template <typename reference_type> + class basic_table_iterator { + public: + typedef object key_type; + typedef object mapped_type; + typedef std::pair<object, object> value_type; + typedef std::input_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + private: + std::pair<object, object> kvp; + reference_type ref; + int tableidx = 0; + int keyidx = 0; + std::ptrdiff_t idx = 0; + + public: + basic_table_iterator() noexcept : keyidx(-1), idx(-1) { + } + + basic_table_iterator(reference_type x) noexcept : ref(std::move(x)) { + ref.push(); + tableidx = lua_gettop(ref.lua_state()); + stack::push(ref.lua_state(), lua_nil); + this->operator++(); + if (idx == -1) { + return; + } + --idx; + } + + basic_table_iterator& operator++() noexcept { + if (idx == -1) + return *this; + + if (lua_next(ref.lua_state(), tableidx) == 0) { + idx = -1; + keyidx = -1; + return *this; + } + ++idx; + kvp.first = object(ref.lua_state(), -2); + kvp.second = object(ref.lua_state(), -1); + lua_pop(ref.lua_state(), 1); + // leave key on the stack + keyidx = lua_gettop(ref.lua_state()); + return *this; + } + + basic_table_iterator operator++(int) noexcept { + auto saved = *this; + this->operator++(); + return saved; + } + + reference operator*() const noexcept { + return const_cast<reference>(kvp); + } + + bool operator==(const basic_table_iterator& right) const noexcept { + return idx == right.idx; + } + + bool operator!=(const basic_table_iterator& right) const noexcept { + return idx != right.idx; + } + + ~basic_table_iterator() { + if (keyidx != -1) { + stack::remove(ref.lua_state(), keyidx, 1); + } + if (ref.lua_state() != nullptr && ref.valid()) { + stack::remove(ref.lua_state(), tableidx, 1); + } + } + }; + +} // namespace sol + +// end of sol/table_iterator.hpp + +// beginning of sol/pairs_iterator.hpp + +// beginning of sol/stack/detail/pairs.hpp + +#include <optional> + +namespace sol { namespace stack { namespace stack_detail { + + inline bool maybe_push_lua_next_function(lua_State* L_) { + stack::get_field<true, false>(L_, "next"); + bool is_next = stack::check<protected_function>(L_); + if (is_next) { + return true; + } + stack::get_field<true, false>(L_, "table"); + stack::record tracking{}; + if (!stack::loose_table_check(L_, -1, &no_panic, tracking)) { + return false; + } + lua_getfield(L_, -1, "next"); + bool is_table_next_func = stack::check<protected_function>(L_, -1); + if (is_table_next_func) { + return true; + } + lua_pop(L_, 1); + return false; + } + + inline std::optional<protected_function> find_lua_next_function(lua_State* L_) { + if (maybe_push_lua_next_function(L_)) { + return stack::pop<protected_function>(L_); + } + return std::nullopt; + } + + inline int c_lua_next(lua_State* L_) noexcept { + stack_reference table_stack_ref(L_, raw_index(1)); + stateless_stack_reference key_stack_ref(L_, raw_index(2)); + int result = lua_next(table_stack_ref.lua_state(), table_stack_ref.stack_index()); + if (result == 0) { + stack::push(L_, lua_nil); + return 1; + } + return 2; + } + + inline int readonly_pairs(lua_State* L_) noexcept { + int pushed = 0; + if (!maybe_push_lua_next_function(L_)) { + // we do not have the "next" function in the global namespace + // from the "table" global entiry, use our own + pushed += stack::push(L_, &c_lua_next); + } + else { + pushed += 1; + } + int metatable_exists = lua_getmetatable(L_, 1); + sol_c_assert(metatable_exists == 1); + const auto& index_key = to_string(sol::meta_function::index); + lua_getfield(L_, lua_gettop(L_), index_key.c_str()); + lua_remove(L_, -2); + pushed += 1; + pushed += stack::push(L_, lua_nil); + return pushed; + } + +}}} // sol::stack::stack_detail + +// end of sol/stack/detail/pairs.hpp + +namespace sol { + + struct pairs_sentinel { }; + + class pairs_iterator { + private: + inline static constexpr int empty_key_index = -1; + + public: + using key_type = object; + using mapped_type = object; + using value_type = std::pair<object, object>; + using iterator_category = std::input_iterator_tag; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using const_pointer = value_type const*; + using reference = value_type&; + using const_reference = const value_type&; + + pairs_iterator() noexcept + : m_L(nullptr) + , m_next_function_ref(lua_nil) + , m_table_ref(lua_nil) + , m_cached_key_value_pair({ lua_nil, lua_nil }) + , m_key_index(empty_key_index) + , m_iteration_index(0) { + } + + pairs_iterator(const pairs_iterator&) = delete; + pairs_iterator& operator=(const pairs_iterator&) = delete; + + pairs_iterator(pairs_iterator&& right) noexcept + : m_L(right.m_L) + , m_next_function_ref(std::move(right.m_next_function_ref)) + , m_table_ref(std::move(right.m_table_ref)) + , m_cached_key_value_pair(std::move(right.m_cached_key_value_pair)) + , m_key_index(right.m_key_index) + , m_iteration_index(right.m_iteration_index) { + right.m_key_index = empty_key_index; + } + + pairs_iterator& operator=(pairs_iterator&& right) noexcept { + m_L = right.m_L; + m_next_function_ref = std::move(right.m_next_function_ref); + m_table_ref = std::move(right.m_table_ref); + m_cached_key_value_pair = std::move(right.m_cached_key_value_pair); + m_key_index = right.m_key_index; + m_iteration_index = right.m_iteration_index; + right.m_key_index = empty_key_index; + return *this; + } + + template <typename Source> + pairs_iterator(const Source& source_) noexcept : m_L(source_.lua_state()), m_key_index(empty_key_index), m_iteration_index(0) { + if (m_L == nullptr || !source_.valid()) { + m_key_index = empty_key_index; + return; + } + int source_index = -source_.push(m_L); + int abs_source_index = lua_absindex(m_L, source_index); + int metatable_exists = lua_getmetatable(m_L, abs_source_index); + lua_remove(m_L, abs_source_index); + if (metatable_exists == 1) { + // just has a metatable, but does it have __pairs ? + stack_reference metatable(m_L, raw_index(abs_source_index)); + stack::get_field<is_global_table_v<Source>, true>(m_L, meta_function::pairs, metatable.stack_index()); + optional<protected_function> maybe_pairs_function = stack::pop<optional<protected_function>>(m_L); + if (maybe_pairs_function.has_value()) { + protected_function& pairs_function = *maybe_pairs_function; + protected_function_result next_fn_and_table_and_first_key = pairs_function(source_); + if (next_fn_and_table_and_first_key.valid()) { + m_next_function_ref = next_fn_and_table_and_first_key.get<protected_function>(0); + m_table_ref = next_fn_and_table_and_first_key.get<sol::reference>(1); + m_key_index = next_fn_and_table_and_first_key.stack_index() - 1; + // remove next function and table + lua_remove(m_L, m_key_index); + lua_remove(m_L, m_key_index); + next_fn_and_table_and_first_key.abandon(); + lua_remove(m_L, abs_source_index); + this->operator++(); + m_iteration_index = 0; + return; + } + } + } + + { + auto maybe_next = stack::stack_detail::find_lua_next_function(m_L); + if (maybe_next.has_value()) { + m_next_function_ref = std::move(*maybe_next); + m_table_ref = source_; + + stack::push(m_L, lua_nil); + m_key_index = lua_gettop(m_L); + this->operator++(); + m_iteration_index = 0; + return; + } + } + + // okay, so none of the above worked and now we need to create + // a shim / polyfill instead + stack::push(m_L, &stack::stack_detail::c_lua_next); + m_next_function_ref = stack::pop<protected_function>(m_L); + m_table_ref = source_; + stack::push(m_L, lua_nil); + m_key_index = lua_gettop(m_L); + this->operator++(); + m_iteration_index = 0; + } + + pairs_iterator& operator++() { + if (m_key_index == empty_key_index) { + return *this; + } + { + sol::protected_function_result next_results = m_next_function_ref(m_table_ref, stack_reference(m_L, m_key_index)); + if (!next_results.valid()) { + // TODO: abort, or throw an error? + m_clear(); + m_key_index = empty_key_index; + return *this; + } + int next_results_count = next_results.return_count(); + if (next_results_count < 2) { + // iteration is over! + next_results.abandon(); + lua_settop(m_L, m_key_index - 1); + m_key_index = empty_key_index; + ++m_iteration_index; + return *this; + } + else { + lua_remove(m_L, m_key_index); + m_key_index = next_results.stack_index() - 1; + m_cached_key_value_pair.first = stack::get<object>(m_L, m_key_index); + m_cached_key_value_pair.second = stack::get<object>(m_L, m_key_index + 1); + lua_settop(m_L, m_key_index); + next_results.abandon(); + } + } + ++m_iteration_index; + return *this; + } + + std::ptrdiff_t index() const { + return static_cast<std::ptrdiff_t>(m_iteration_index); + } + + const_reference operator*() const noexcept { + return m_cached_key_value_pair; + } + + reference operator*() noexcept { + return m_cached_key_value_pair; + } + + friend bool operator==(const pairs_iterator& left, const pairs_iterator& right) noexcept { + return left.m_table_ref == right.m_table_ref && left.m_iteration_index == right.m_iteration_index; + } + + friend bool operator!=(const pairs_iterator& left, const pairs_iterator& right) noexcept { + return left.m_table_ref != right.m_table_ref || left.m_iteration_index != right.m_iteration_index; + } + + friend bool operator==(const pairs_iterator& left, const pairs_sentinel&) noexcept { + return left.m_key_index == empty_key_index; + } + + friend bool operator!=(const pairs_iterator& left, const pairs_sentinel&) noexcept { + return left.m_key_index != empty_key_index; + } + + friend bool operator==(const pairs_sentinel&, const pairs_iterator& left) noexcept { + return left.m_key_index == empty_key_index; + } + + friend bool operator!=(const pairs_sentinel&, const pairs_iterator& left) noexcept { + return left.m_key_index != empty_key_index; + } + + ~pairs_iterator() { + if (m_key_index != empty_key_index) { + m_clear(); + } + } + + private: + void m_clear() noexcept { + lua_remove(m_L, m_key_index); + } + + lua_State* m_L; + protected_function m_next_function_ref; + sol::reference m_table_ref; + std::pair<object, object> m_cached_key_value_pair; + int m_key_index; + int m_iteration_index; + }; + + template <typename Source> + class basic_pairs_range { + private: + using source_t = std::add_lvalue_reference_t<Source>; + source_t m_source; + + public: + using iterator = pairs_iterator; + using const_iterator = pairs_iterator; + + basic_pairs_range(source_t source_) noexcept : m_source(source_) { + } + + iterator begin() noexcept { + return iterator(m_source); + } + + iterator begin() const noexcept { + return iterator(m_source); + } + + const_iterator cbegin() const noexcept { + return const_iterator(m_source); + } + + pairs_sentinel end() noexcept { + return {}; + } + + pairs_sentinel end() const noexcept { + return {}; + } + + pairs_sentinel cend() const noexcept { + return {}; + } + }; +} // namespace sol + +// end of sol/pairs_iterator.hpp + +namespace sol { + namespace detail { + template <std::size_t n> + struct clean { + lua_State* L; + clean(lua_State* luastate) : L(luastate) { + } + ~clean() { + lua_pop(L, static_cast<int>(n)); + } + }; + + struct ref_clean { + lua_State* L; + int& pop_count; + + ref_clean(lua_State* L_, int& pop_count_) noexcept : L(L_), pop_count(pop_count_) { + } + ~ref_clean() { + lua_pop(L, static_cast<int>(pop_count)); + } + }; + + inline int fail_on_newindex(lua_State* L_) { + return luaL_error(L_, "sol: cannot modify the elements of an enumeration table"); + } + + } // namespace detail + + template <bool top_level, typename ref_t> + class basic_table_core : public basic_object<ref_t> { + private: + using base_t = basic_object<ref_t>; + + friend class state; + friend class state_view; + template <typename, typename> + friend class basic_usertype; + template <typename> + friend class basic_metatable; + + template <typename T> + using is_get_direct_tableless = meta::boolean<stack::stack_detail::is_get_direct_tableless_v<T, top_level, false>>; + + template <typename T> + using is_raw_get_direct_tableless = std::false_type; + + template <typename T> + using is_set_direct_tableless = meta::boolean<stack::stack_detail::is_set_direct_tableless_v<T, top_level, false>>; + + template <typename T> + using is_raw_set_direct_tableless = std::false_type; + + template <bool raw, typename... Ret, typename... Keys> + decltype(auto) tuple_get(int table_index, Keys&&... keys) const { + if constexpr (sizeof...(Ret) < 2) { + return traverse_get_single_maybe_tuple<raw, Ret...>(table_index, std::forward<Keys>(keys)...); + } + else { + using multi_ret = decltype(stack::pop<std::tuple<Ret...>>(nullptr)); + return multi_ret(traverse_get_single_maybe_tuple<raw, Ret>(table_index, std::forward<Keys>(keys))...); + } + } + + template <bool raw, typename Ret, size_t... I, typename Key> + decltype(auto) traverse_get_single_tuple(int table_index, std::index_sequence<I...>, Key&& key) const { + return traverse_get_single<raw, Ret>(table_index, std::get<I>(std::forward<Key>(key))...); + } + + template <bool raw, typename Ret, typename Key> + decltype(auto) traverse_get_single_maybe_tuple(int table_index, Key&& key) const { + if constexpr (meta::is_tuple_v<meta::unqualified_t<Key>>) { + return traverse_get_single_tuple<raw, Ret>( + table_index, std::make_index_sequence<std::tuple_size_v<meta::unqualified_t<Key>>>(), std::forward<Key>(key)); + } + else { + return traverse_get_single<raw, Ret>(table_index, std::forward<Key>(key)); + } + } + + template <bool raw, typename Ret, typename... Keys> + decltype(auto) traverse_get_single(int table_index, Keys&&... keys) const { + constexpr static bool global = (meta::count_for_to_pack_v < 1, is_get_direct_tableless, meta::unqualified_t<Keys>... >> 0); + if constexpr (meta::is_optional_v<meta::unqualified_t<Ret>>) { + int popcount = 0; + detail::ref_clean c(base_t::lua_state(), popcount); + return traverse_get_deep_optional<global, raw, detail::insert_mode::none, Ret>(popcount, table_index, std::forward<Keys>(keys)...); + } + else { + detail::clean<sizeof...(Keys) - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>> c(base_t::lua_state()); + return traverse_get_deep<global, raw, detail::insert_mode::none, Ret>(table_index, std::forward<Keys>(keys)...); + } + } + + template <bool raw, typename Pairs, std::size_t... I> + void tuple_set(std::index_sequence<I...>, Pairs&& pairs) { + constexpr static bool global = (meta::count_even_for_pack_v < is_set_direct_tableless, + meta::unqualified_t<decltype(std::get<I * 2>(std::forward<Pairs>(pairs)))>... >> 0); + auto pp = stack::push_pop<global>(*this); + int table_index = pp.index_of(*this); + lua_State* L = base_t::lua_state(); + (void)table_index; + (void)L; + void(detail::swallow { (stack::set_field<(top_level), raw>( + L, std::get<I * 2>(std::forward<Pairs>(pairs)), std::get<I * 2 + 1>(std::forward<Pairs>(pairs)), table_index), + 0)... }); + } + + template <bool global, bool raw, detail::insert_mode mode, typename T, typename Key, typename... Keys> + decltype(auto) traverse_get_deep(int table_index, Key&& key, Keys&&... keys) const { + if constexpr (std::is_same_v<meta::unqualified_t<Key>, create_if_nil_t>) { + (void)key; + return traverse_get_deep<false, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil), T>( + table_index, std::forward<Keys>(keys)...); + } + else { + lua_State* L = base_t::lua_state(); + stack::get_field<global, raw>(L, std::forward<Key>(key), table_index); + if constexpr (sizeof...(Keys) > 0) { + if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) { + type t = type_of(L, -1); + if (t == type::lua_nil || t == type::none) { + lua_pop(L, 1); + stack::push(L, new_table(0, 0)); + } + } + return traverse_get_deep<false, raw, mode, T>(lua_gettop(L), std::forward<Keys>(keys)...); + } + else { + if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) { + type t = type_of(L, -1); + if ((t == type::lua_nil || t == type::none) && (is_table_like_v<T>)) { + lua_pop(L, 1); + stack::push(L, new_table(0, 0)); + } + } + return stack::get<T>(L); + } + } + } + + template <bool global, bool raw, detail::insert_mode mode, typename T, typename Key, typename... Keys> + decltype(auto) traverse_get_deep_optional(int& popcount, int table_index, Key&& key, Keys&&... keys) const { + if constexpr (std::is_same_v<meta::unqualified_t<Key>, create_if_nil_t>) { + constexpr detail::insert_mode new_mode = static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil); + (void)key; + return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...); + } + else if constexpr (std::is_same_v<meta::unqualified_t<Key>, update_if_empty_t>) { + constexpr detail::insert_mode new_mode = static_cast<detail::insert_mode>(mode | detail::insert_mode::update_if_empty); + (void)key; + return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...); + } + else if constexpr (std::is_same_v<meta::unqualified_t<Key>, override_value_t>) { + constexpr detail::insert_mode new_mode = static_cast<detail::insert_mode>(mode | detail::insert_mode::override_value); + (void)key; + return traverse_get_deep_optional<global, raw, new_mode, T>(popcount, table_index, std::forward<Keys>(keys)...); + } + else { + if constexpr (sizeof...(Keys) > 0) { + lua_State* L = base_t::lua_state(); + auto p = stack::probe_get_field<global, raw>(L, std::forward<Key>(key), table_index); + popcount += p.levels; + if (!p.success) { + if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) { + lua_pop(L, 1); + constexpr bool is_seq = meta::count_for_to_pack_v < 1, std::is_integral, Keys... >> 0; + stack::push(L, new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq))); + stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index); + } + else { + return T(nullopt); + } + } + return traverse_get_deep_optional<false, raw, mode, T>(popcount, lua_gettop(L), std::forward<Keys>(keys)...); + } + else { + using R = decltype(stack::get<T>(nullptr)); + using value_type = typename meta::unqualified_t<R>::value_type; + lua_State* L = base_t::lua_state(); + auto p = stack::probe_get_field<global, raw, value_type>(L, key, table_index); + popcount += p.levels; + if (!p.success) { + if constexpr ((mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) { + lua_pop(L, 1); + stack::push(L, new_table(0, 0)); + stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index); + if (stack::check<value_type>(L, lua_gettop(L), &no_panic)) { + return stack::get<T>(L); + } + } + return R(nullopt); + } + return stack::get<T>(L); + } + } + } + + template <bool global, bool raw, detail::insert_mode mode, typename Key, typename... Keys> + void traverse_set_deep(int table_index, Key&& key, Keys&&... keys) const { + using KeyU = meta::unqualified_t<Key>; + if constexpr (std::is_same_v<KeyU, update_if_empty_t>) { + (void)key; + traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::update_if_empty)>( + table_index, std::forward<Keys>(keys)...); + } + else if constexpr (std::is_same_v<KeyU, create_if_nil_t>) { + (void)key; + traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::create_if_nil)>( + table_index, std::forward<Keys>(keys)...); + } + else if constexpr (std::is_same_v<KeyU, override_value_t>) { + (void)key; + traverse_set_deep<global, raw, static_cast<detail::insert_mode>(mode | detail::insert_mode::override_value)>( + table_index, std::forward<Keys>(keys)...); + } + else { + lua_State* L = base_t::lua_state(); + if constexpr (sizeof...(Keys) == 1) { + if constexpr ((mode & detail::insert_mode::update_if_empty) == detail::insert_mode::update_if_empty) { + auto p = stack::probe_get_field<global, raw>(L, key, table_index); + lua_pop(L, p.levels); + if (!p.success) { + stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index); + } + } + else { + stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index); + } + } + else { + if constexpr (mode != detail::insert_mode::none) { + stack::get_field<global, raw>(L, key, table_index); + type vt = type_of(L, -1); + if constexpr ((mode & detail::insert_mode::update_if_empty) == detail::insert_mode::update_if_empty + || (mode & detail::insert_mode::create_if_nil) == detail::insert_mode::create_if_nil) { + if (vt == type::lua_nil || vt == type::none) { + constexpr bool is_seq = meta::count_for_to_pack_v < 1, std::is_integral, Keys... >> 0; + lua_pop(L, 1); + stack::push(L, new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq))); + stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index); + } + } + else { + if (vt != type::table) { + constexpr bool is_seq = meta::count_for_to_pack_v < 1, std::is_integral, Keys... >> 0; + lua_pop(L, 1); + stack::push(L, new_table(static_cast<int>(is_seq), static_cast<int>(!is_seq))); + stack::set_field<global, raw>(L, std::forward<Key>(key), stack_reference(L, -1), table_index); + } + } + } + else { + stack::get_field<global, raw>(L, std::forward<Key>(key), table_index); + } + traverse_set_deep<false, raw, mode>(lua_gettop(L), std::forward<Keys>(keys)...); + } + } + } + + protected: + basic_table_core(detail::no_safety_tag, lua_nil_t n) : base_t(n) { + } + basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) { + } + basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) { + } + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<ref_t, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward<T>(r)) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_table_core(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward<T>(r)) { + } + + public: + using iterator = basic_table_iterator<ref_t>; + using const_iterator = iterator; + + using base_t::lua_state; + + basic_table_core() noexcept = default; + basic_table_core(const basic_table_core&) = default; + basic_table_core(basic_table_core&&) = default; + basic_table_core& operator=(const basic_table_core&) = default; + basic_table_core& operator=(basic_table_core&&) = default; + + basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) { + } + + basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) { + } + + template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_table_core(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + constructor_handler handler {}; + stack::check<basic_table_core>(lua_state(), table_index, handler); +#endif // Safety + } + + basic_table_core(lua_State* L, const new_table& nt) : base_t(L, -stack::push(L, nt)) { + if (!is_stack_based<meta::unqualified_t<ref_t>>::value) { + lua_pop(L, 1); + } + } + + basic_table_core(lua_State* L, int index = -1) : basic_table_core(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_table_core>(L, index, handler); +#endif // Safety + } + + basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + constructor_handler handler {}; + stack::check<basic_table_core>(lua_state(), table_index, handler); +#endif // Safety + } + + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<ref_t, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_table<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + constructor_handler handler {}; + stack::check<basic_table_core>(lua_state(), table_index, handler); + } +#endif // Safety + } + + basic_table_core(lua_nil_t r) noexcept : basic_table_core(detail::no_safety, r) { + } + + basic_table_core(lua_State* L, global_tag_t t) noexcept : base_t(L, t) { + } + + iterator begin() const { + if (this->get_type() == type::table) { + return iterator(*this); + } + return iterator(); + } + + iterator end() const { + return iterator(); + } + + const_iterator cbegin() const { + return begin(); + } + + const_iterator cend() const { + return end(); + } + + basic_pairs_range<basic_table_core> pairs() noexcept { + return basic_pairs_range<basic_table_core>(*this); + } + + basic_pairs_range<const basic_table_core> pairs() const noexcept { + return basic_pairs_range<const basic_table_core>(*this); + } + + void clear() { + auto pp = stack::push_pop<false>(*this); + int table_index = pp.index_of(*this); + stack::clear(lua_state(), table_index); + } + + template <typename... Ret, typename... Keys> + decltype(auto) get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + constexpr static bool global = meta::all<meta::boolean<top_level>, is_get_direct_tableless<meta::unqualified_t<Keys>>...>::value; + auto pp = stack::push_pop<global>(*this); + int table_index = pp.index_of(*this); + return tuple_get<false, Ret...>(table_index, std::forward<Keys>(keys)...); + } + + template <typename T, typename Key> + decltype(auto) get_or(Key&& key, T&& otherwise) const { + typedef decltype(get<T>("")) U; + optional<U> option = get<optional<U>>(std::forward<Key>(key)); + if (option) { + return static_cast<U>(option.value()); + } + return static_cast<U>(std::forward<T>(otherwise)); + } + + template <typename T, typename Key, typename D> + decltype(auto) get_or(Key&& key, D&& otherwise) const { + optional<T> option = get<optional<T>>(std::forward<Key>(key)); + if (option) { + return static_cast<T>(option.value()); + } + return static_cast<T>(std::forward<D>(otherwise)); + } + + template <typename T, typename... Keys> + decltype(auto) traverse_get(Keys&&... keys) const { + static_assert(sizeof...(Keys) > 0, "must pass at least 1 key to get"); + constexpr static bool global = (meta::count_for_to_pack_v < 1, is_get_direct_tableless, meta::unqualified_t<Keys>... >> 0); + auto pp = stack::push_pop<global>(*this); + int table_index = pp.index_of(*this); + return traverse_get_single<false, T>(table_index, std::forward<Keys>(keys)...); + } + + template <typename... Keys> + basic_table_core& traverse_set(Keys&&... keys) { + static_assert(sizeof...(Keys) > 1, "must pass at least 1 key and 1 value to set"); + constexpr static bool global + = (meta::count_when_for_to_pack_v < detail::is_not_insert_mode, 1, is_set_direct_tableless, meta::unqualified_t<Keys>... >> 0); + auto pp = stack::push_pop<global>(*this); + int table_index = pp.index_of(*this); + lua_State* L = base_t::lua_state(); + auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>)); + traverse_set_deep<top_level, false, detail::insert_mode::none>(table_index, std::forward<Keys>(keys)...); + return *this; + } + + template <typename... Args> + basic_table_core& set(Args&&... args) { + if constexpr (sizeof...(Args) == 2) { + traverse_set(std::forward<Args>(args)...); + } + else { + tuple_set<false>(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); + } + return *this; + } + + template <typename... Ret, typename... Keys> + decltype(auto) raw_get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + constexpr static bool global = (meta::count_for_to_pack_v < 1, is_raw_get_direct_tableless, meta::unqualified_t<Keys>... >> 0); + auto pp = stack::push_pop<global>(*this); + int table_index = pp.index_of(*this); + return tuple_get<true, Ret...>(table_index, std::forward<Keys>(keys)...); + } + + template <typename T, typename Key> + decltype(auto) raw_get_or(Key&& key, T&& otherwise) const { + typedef decltype(raw_get<T>("")) U; + optional<U> option = raw_get<optional<U>>(std::forward<Key>(key)); + if (option) { + return static_cast<U>(option.value()); + } + return static_cast<U>(std::forward<T>(otherwise)); + } + + template <typename T, typename Key, typename D> + decltype(auto) raw_get_or(Key&& key, D&& otherwise) const { + optional<T> option = raw_get<optional<T>>(std::forward<Key>(key)); + if (option) { + return static_cast<T>(option.value()); + } + return static_cast<T>(std::forward<D>(otherwise)); + } + + template <typename T, typename... Keys> + decltype(auto) traverse_raw_get(Keys&&... keys) const { + constexpr static bool global = (meta::count_for_to_pack_v < 1, is_raw_get_direct_tableless, meta::unqualified_t<Keys>... >> 0); + auto pp = stack::push_pop<global>(*this); + int table_index = pp.index_of(*this); + return traverse_get_single<true, T>(table_index, std::forward<Keys>(keys)...); + } + + template <typename... Keys> + basic_table_core& traverse_raw_set(Keys&&... keys) { + constexpr static bool global = (meta::count_for_to_pack_v < 1, is_raw_set_direct_tableless, meta::unqualified_t<Keys>... >> 0); + auto pp = stack::push_pop<global>(*this); + lua_State* L = base_t::lua_state(); + auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2 - meta::count_for_pack_v<detail::is_insert_mode, meta::unqualified_t<Keys>...>)); + traverse_set_deep<top_level, true, false>(std::forward<Keys>(keys)...); + return *this; + } + + template <typename... Args> + basic_table_core& raw_set(Args&&... args) { + tuple_set<true>(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); + return *this; + } + + template <typename Class, typename Key> + usertype<Class> new_usertype(Key&& key); + + template <typename Class, typename Key, automagic_flags enrollment_flags> + usertype<Class> new_usertype(Key&& key, constant_automagic_enrollments<enrollment_flags> enrollment); + + template <typename Class, typename Key> + usertype<Class> new_usertype(Key&& key, automagic_enrollments enrollment); + + template <typename Class, typename Key, typename Arg, typename... Args, + typename = std::enable_if_t<!std::is_base_of_v<automagic_enrollments, meta::unqualified_t<Arg>>>> + usertype<Class> new_usertype(Key&& key, Arg&& arg, Args&&... args); + + template <bool read_only = true, typename... Args> + table new_enum(const string_view& name, Args&&... args) { + table target = create_with(std::forward<Args>(args)...); + if constexpr (read_only) { + // Need to create a special iterator to handle this + table x + = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target, meta_function::pairs, stack::stack_detail::readonly_pairs); + table shim = create_named(name, metatable_key, x); + return shim; + } + else { + set(name, target); + return target; + } + } + + template <typename T, bool read_only = true> + table new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) { + table target = create(static_cast<int>(items.size()), static_cast<int>(0)); + for (const auto& kvp : items) { + target.set(kvp.first, kvp.second); + } + if constexpr (read_only) { + table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target); + table shim = create_named(name, metatable_key, x); + return shim; + } + else { + set(name, target); + return target; + } + } + + template <typename Key = object, typename Value = object, typename Fx> + void for_each(Fx&& fx) const { + lua_State* L = base_t::lua_state(); + if constexpr (std::is_invocable_v<Fx, Key, Value>) { + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + stack::push(L, lua_nil); + while (lua_next(L, table_index)) { + Key key(L, -2); + Value value(L, -1); + auto pn = stack::pop_n(L, 1); + fx(key, value); + } + } + else { + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + stack::push(L, lua_nil); + while (lua_next(L, table_index)) { + Key key(L, -2); + Value value(L, -1); + auto pn = stack::pop_n(L, 1); + std::pair<Key&, Value&> keyvalue(key, value); + fx(keyvalue); + } + } + } + + size_t size() const { + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + lua_State* L = base_t::lua_state(); + lua_len(L, table_index); + return stack::pop<size_t>(L); + } + + bool empty() const { + return cbegin() == cend(); + } + + template <typename T> + auto operator[](T&& key) & { + return table_proxy<basic_table_core&, detail::proxy_key_t<T>>(*this, std::forward<T>(key)); + } + + template <typename T> + auto operator[](T&& key) const& { + return table_proxy<const basic_table_core&, detail::proxy_key_t<T>>(*this, std::forward<T>(key)); + } + + template <typename T> + auto operator[](T&& key) && { + return table_proxy<basic_table_core, detail::proxy_key_t<T>>(std::move(*this), std::forward<T>(key)); + } + + template <typename Sig, typename Key, typename... Args> + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename Key, typename... Args> + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename... Args> + basic_table_core& add(Args&&... args) { + auto pp = stack::push_pop(*this); + int table_index = pp.index_of(*this); + lua_State* L = base_t::lua_state(); + (void)detail::swallow { 0, (stack::stack_detail::raw_table_set(L, std::forward<Args>(args), table_index), 0)... }; + return *this; + } + + private: + template <typename R, typename... Args, typename Fx, typename Key, typename = std::invoke_result_t<Fx, Args...>> + void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) { + set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx)); + } + + template <typename Fx, typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward<Key>(key), std::forward<Fx>(fx)); + } + + template <typename Fx, typename Key, typename... Args, + meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...)); + } + + template <typename... Sig, typename... Args, typename Key> + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...)); + } + + public: + static inline table create(lua_State* L, int narr = 0, int nrec = 0) { + lua_createtable(L, narr, nrec); + table result(L); + lua_pop(L, 1); + return result; + } + + template <typename Key, typename Value, typename... Args> + static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + lua_createtable(L, narr, nrec); + table result(L); + result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); + lua_pop(L, 1); + return result; + } + + template <typename... Args> + static inline table create_with(lua_State* L, Args&&... args) { + static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); + constexpr int narr = static_cast<int>(meta::count_odd_for_pack_v<std::is_integral, Args...>); + return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...); + } + + table create(int narr = 0, int nrec = 0) { + return create(base_t::lua_state(), narr, nrec); + } + + template <typename Key, typename Value, typename... Args> + table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); + } + + template <typename Name> + table create(Name&& name, int narr = 0, int nrec = 0) { + table x = create(base_t::lua_state(), narr, nrec); + this->set(std::forward<Name>(name), x); + return x; + } + + template <typename Name, typename Key, typename Value, typename... Args> + table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); + this->set(std::forward<Name>(name), x); + return x; + } + + template <typename... Args> + table create_with(Args&&... args) { + return create_with(base_t::lua_state(), std::forward<Args>(args)...); + } + + template <typename Name, typename... Args> + table create_named(Name&& name, Args&&... args) { + static const int narr = static_cast<int>(meta::count_even_for_pack_v<std::is_integral, Args...>); + return create(std::forward<Name>(name), narr, (sizeof...(Args) / 2) - narr, std::forward<Args>(args)...); + } + }; +} // namespace sol + +// end of sol/table_core.hpp + +namespace sol { + + template <typename base_type> + class basic_metatable : public basic_table<base_type> { + typedef basic_table<base_type> base_t; + friend class state; + friend class state_view; + + protected: + basic_metatable(detail::no_safety_tag, lua_nil_t n) : base_t(n) { + } + basic_metatable(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) { + } + basic_metatable(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) { + } + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_metatable(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward<T>(r)) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_metatable(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward<T>(r)) { + } + + template <typename R, typename... Args, typename Fx, typename Key, typename = std::invoke_result_t<Fx, Args...>> + void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) { + set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx)); + } + + template <typename Fx, typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward<Key>(key), std::forward<Fx>(fx)); + } + + template <typename Fx, typename Key, typename... Args, + meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...)); + } + + template <typename... Sig, typename... Args, typename Key> + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...)); + } + + public: + using base_t::lua_state; + + basic_metatable() noexcept = default; + basic_metatable(const basic_metatable&) = default; + basic_metatable(basic_metatable&&) = default; + basic_metatable& operator=(const basic_metatable&) = default; + basic_metatable& operator=(basic_metatable&&) = default; + basic_metatable(const stack_reference& r) : basic_metatable(r.lua_state(), r.stack_index()) { + } + basic_metatable(stack_reference&& r) : basic_metatable(r.lua_state(), r.stack_index()) { + } + template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_metatable(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_metatable>(lua_state(), -1, handler); +#endif // Safety + } + basic_metatable(lua_State* L, int index = -1) : basic_metatable(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_metatable>(L, index, handler); +#endif // Safety + } + basic_metatable(lua_State* L, ref_index index) : basic_metatable(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_metatable>(lua_state(), -1, handler); +#endif // Safety + } + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_metatable>>, meta::neg<std::is_same<base_type, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_metatable(T&& r) noexcept : basic_metatable(detail::no_safety, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_table<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_metatable>(base_t::lua_state(), -1, handler); + } +#endif // Safety + } + basic_metatable(lua_nil_t r) noexcept : basic_metatable(detail::no_safety, r) { + } + + template <typename Key, typename Value> + basic_metatable<base_type>& set(Key&& key, Value&& value); + + template <typename Sig, typename Key, typename... Args> + basic_metatable& set_function(Key&& key, Args&&... args) { + set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename Key, typename... Args> + basic_metatable& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + void unregister() { + using ustorage_base = u_detail::usertype_storage_base; + + lua_State* L = this->lua_state(); + + auto pp = stack::push_pop(*this); + int top = lua_gettop(L); + + stack_reference mt(L, -1); + stack::get_field(L, meta_function::gc_names, mt.stack_index()); + if (type_of(L, -1) != type::table) { + lua_settop(L, top); + return; + } + stack_reference gc_names_table(L, -1); + stack::get_field(L, meta_function::storage, mt.stack_index()); + if (type_of(L, -1) != type::lightuserdata) { + lua_settop(L, top); + return; + } + ustorage_base& base_storage = *static_cast<ustorage_base*>(stack::get<void*>(L, -1)); + std::array<string_view, 6> registry_traits; + for (std::size_t i = 0; i < registry_traits.size(); ++i) { + u_detail::submetatable_type smt = static_cast<u_detail::submetatable_type>(i); + stack::get_field<false, true>(L, smt, gc_names_table.stack_index()); + registry_traits[i] = stack::get<string_view>(L, -1); + } + + // get the registry + stack_reference registry(L, raw_index(LUA_REGISTRYINDEX)); + registry.push(); + // eliminate all named entries for this usertype + // in the registry (luaL_newmetatable does + // [name] = new table + // in registry upon creation) + for (std::size_t i = 0; i < registry_traits.size(); ++i) { + u_detail::submetatable_type smt = static_cast<u_detail::submetatable_type>(i); + const string_view& gcmetakey = registry_traits[i]; + if (smt == u_detail::submetatable_type::named) { + // use .data() to make it treat it like a c string, + // which it is... + stack::set_field<true>(L, gcmetakey.data(), lua_nil); + } + else { + // do not change the values in the registry: they need to be present + // no matter what, for safety's sake + // stack::set_field(L, gcmetakey, lua_nil, registry.stack_index()); + } + } + + // destroy all storage and tables + base_storage.clear(); + + // 6 strings from gc_names table, + // + 1 registry, + // + 1 gc_names table + // + 1 light userdata of storage + // + 1 registry + // 10 total, 4 left since popping off 6 gc_names tables + lua_settop(L, top); + } + }; + +} // namespace sol + +// end of sol/metatable.hpp + +namespace sol { + + template <typename T, typename base_type> + class basic_usertype : private basic_metatable<base_type> { + private: + using base_t = basic_metatable<base_type>; + using table_base_t = basic_table<base_type>; + + template <typename> + friend class basic_metatable; + + template <bool, typename> + friend class basic_table_core; + + template <std::size_t... I, typename... Args> + void tuple_set(std::index_sequence<I...>, std::tuple<Args...>&& args) { + (void)args; + (void)detail::swallow { 0, (this->set(std::get<I * 2>(std::move(args)), std::get<I * 2 + 1>(std::move(args))), 0)... }; + } + + template <typename R, typename... Args, typename Fx, typename Key, typename = std::invoke_result_t<Fx, Args...>> + void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) { + set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx)); + } + + template <typename Fx, typename Key, meta::enable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward<Key>(key), std::forward<Fx>(fx)); + } + + template <typename Fx, typename Key, typename... Args, + meta::disable<meta::is_specialization_of<meta::unqualified_t<Fx>, overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...)); + } + + template <typename... Sig, typename... Args, typename Key> + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...)); + } + + public: + using base_t::base_t; + + using base_t::get; + using base_t::lua_state; + using base_t::pop; + using base_t::push; + using base_t::traverse_get; + using base_t::traverse_set; + using base_t::unregister; + + template <typename Key, typename Value> + basic_usertype& set(Key&& key, Value&& value) { + optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state()); + if (maybe_uts) { + u_detail::usertype_storage<T>& uts = *maybe_uts; + uts.set(this->lua_state(), std::forward<Key>(key), std::forward<Value>(value)); + } + else { + using ValueU = meta::unqualified_t<Value>; + // cannot get metatable: try regular table set? + if constexpr (detail::is_non_factory_constructor_v<ValueU> || detail::is_policy_v<ValueU>) { + // tag constructors so we don't get destroyed by lack of info + table_base_t::set(std::forward<Key>(key), detail::tagged<T, Value>(std::forward<Value>(value))); + } + else { + table_base_t::set(std::forward<Key>(key), std::forward<Value>(value)); + } + } + return *this; + } + + template <typename Sig, typename Key, typename... Args> + basic_usertype& set_function(Key&& key, Args&&... args) { + set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename Key, typename... Args> + basic_usertype& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename Key> + usertype_proxy<basic_usertype&, std::decay_t<Key>> operator[](Key&& key) { + return usertype_proxy<basic_usertype&, std::decay_t<Key>>(*this, std::forward<Key>(key)); + } + + template <typename Key> + usertype_proxy<const basic_usertype&, std::decay_t<Key>> operator[](Key&& key) const { + return usertype_proxy<const basic_usertype&, std::decay_t<Key>>(*this, std::forward<Key>(key)); + } + }; + +} // namespace sol + +// end of sol/usertype.hpp + +// beginning of sol/table.hpp + +// beginning of sol/lua_table.hpp + +namespace sol { + + template <typename ref_t> + struct basic_lua_table : basic_table_core<false, ref_t> { + private: + using base_t = basic_table_core<false, ref_t>; + + friend class state; + friend class state_view; + + public: + using base_t::lua_state; + + basic_lua_table() noexcept = default; + basic_lua_table(const basic_lua_table&) = default; + basic_lua_table(basic_lua_table&&) = default; + basic_lua_table& operator=(const basic_lua_table&) = default; + basic_lua_table& operator=(basic_lua_table&&) = default; + basic_lua_table(const stack_reference& r) : basic_lua_table(r.lua_state(), r.stack_index()) { + } + basic_lua_table(stack_reference&& r) : basic_lua_table(r.lua_state(), r.stack_index()) { + } + template <typename T, meta::enable_any<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_lua_table(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_lua_table>(lua_state(), -1, handler); +#endif // Safety + } + basic_lua_table(lua_State* L, const new_table& nt) : base_t(L, nt) { + if (!is_stack_based<meta::unqualified_t<ref_t>>::value) { + lua_pop(L, 1); + } + } + basic_lua_table(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_lua_table>(L, index, handler); +#endif // Safety + } + basic_lua_table(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_lua_table>(lua_state(), -1, handler); +#endif // Safety + } + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_lua_table>>, meta::neg<std::is_same<ref_t, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_lua_table(T&& r) noexcept : basic_lua_table(detail::no_safety, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_table<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_lua_table>(lua_state(), -1, handler); + } +#endif // Safety + } + basic_lua_table(lua_nil_t r) noexcept : basic_lua_table(detail::no_safety, r) { + } + }; + +} // namespace sol + +// end of sol/lua_table.hpp + +namespace sol { + typedef table_core<false> table; + + template <bool is_global, typename base_type> + template <typename Class, typename Key> + usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key) { + constant_automagic_enrollments<> enrollments {}; + return this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments)); + } + + template <bool is_global, typename base_type> + template <typename Class, typename Key, automagic_flags enrollment_flags> + usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, constant_automagic_enrollments<enrollment_flags> enrollments) { + int mt_index = u_detail::register_usertype<Class, enrollment_flags>(this->lua_state(), std::move(enrollments)); + usertype<Class> mt(this->lua_state(), -mt_index); + lua_pop(this->lua_state(), 1); + set(std::forward<Key>(key), mt); + return mt; + } + + template <bool is_global, typename base_type> + template <typename Class, typename Key> + usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, automagic_enrollments enrollments) { + int mt_index = u_detail::register_usertype<Class, automagic_flags::all>(this->lua_state(), std::move(enrollments)); + usertype<Class> mt(this->lua_state(), -mt_index); + lua_pop(this->lua_state(), 1); + set(std::forward<Key>(key), mt); + return mt; + } + + template <bool is_global, typename base_type> + template <typename Class, typename Key, typename Arg, typename... Args, typename> + usertype<Class> basic_table_core<is_global, base_type>::new_usertype(Key&& key, Arg&& arg, Args&&... args) { + constexpr automagic_flags enrollment_flags = meta::any_same_v<no_construction, meta::unqualified_t<Arg>, meta::unqualified_t<Args>...> + ? clear_flags(automagic_flags::all, automagic_flags::default_constructor) + : automagic_flags::all; + constant_automagic_enrollments<enrollment_flags> enrollments; + enrollments.default_constructor = !detail::any_is_constructor_v<Arg, Args...>; + enrollments.destructor = !detail::any_is_destructor_v<Arg, Args...>; + usertype<Class> ut = this->new_usertype<Class>(std::forward<Key>(key), std::move(enrollments)); + static_assert(sizeof...(Args) % 2 == static_cast<std::size_t>(!detail::any_is_constructor_v<Arg>), + "you must pass an even number of arguments to new_usertype after first passing a constructor"); + if constexpr (detail::any_is_constructor_v<Arg>) { + ut.set(meta_function::construct, std::forward<Arg>(arg)); + ut.tuple_set(std::make_index_sequence<(sizeof...(Args)) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); + } + else { + ut.tuple_set(std::make_index_sequence<(sizeof...(Args) + 1) / 2>(), std::forward_as_tuple(std::forward<Arg>(arg), std::forward<Args>(args)...)); + } + return ut; + } + + template <typename base_type> + template <typename Key, typename Value> + basic_metatable<base_type>& basic_metatable<base_type>::set(Key&& key, Value&& value) { + this->push(); + lua_State* L = this->lua_state(); + int target = lua_gettop(L); + optional<u_detail::usertype_storage_base&> maybe_uts = nullopt; + maybe_uts = u_detail::maybe_get_usertype_storage_base(L, target); + if (maybe_uts) { + u_detail::usertype_storage_base& uts = *maybe_uts; + uts.set(L, std::forward<Key>(key), std::forward<Value>(value)); + return *this; + } + else { + base_t::set(std::forward<Key>(key), std::forward<Value>(value)); + } + this->pop(); + return *this; + } + + namespace stack { + template <> + struct unqualified_getter<metatable_key_t> { + static metatable get(lua_State* L, int index = -1) { + if (lua_getmetatable(L, index) == 0) { + return metatable(L, ref_index(LUA_REFNIL)); + } + return metatable(L, -1); + } + }; + } // namespace stack +} // namespace sol + +// end of sol/table.hpp + +// beginning of sol/state.hpp + +// beginning of sol/state_view.hpp + +// beginning of sol/environment.hpp + +namespace sol { + + template <typename base_type> + struct basic_environment : basic_table<base_type> { + private: + typedef basic_table<base_type> base_t; + + public: + using base_t::lua_state; + + basic_environment() noexcept = default; + basic_environment(const basic_environment&) = default; + basic_environment(basic_environment&&) = default; + basic_environment& operator=(const basic_environment&) = default; + basic_environment& operator=(basic_environment&&) = default; + basic_environment(const stack_reference& r) : basic_environment(r.lua_state(), r.stack_index()) { + } + basic_environment(stack_reference&& r) : basic_environment(r.lua_state(), r.stack_index()) { + } + + basic_environment(lua_State* L, new_table nt) : base_t(L, std::move(nt)) { + } + template <bool b> + basic_environment(lua_State* L, new_table t, const basic_reference<b>& fallback) : basic_environment(L, std::move(t)) { + stack_table mt(L, new_table(0, 1)); + mt.set(meta_function::index, fallback); + this->set(metatable_key, mt); + mt.pop(); + } + + basic_environment(env_key_t, const stack_reference& extraction_target) + : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<env_key_t>(this->lua_state(), -1, handler); +#endif // Safety + lua_pop(this->lua_state(), 1); + } + template <bool b> + basic_environment(env_key_t, const basic_reference<b>& extraction_target) + : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<env_key_t>(this->lua_state(), -1, handler); +#endif // Safety + lua_pop(this->lua_state(), 1); + } + basic_environment(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_environment>(L, index, handler); +#endif // Safety + } + basic_environment(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_environment>(L, -1, handler); +#endif // Safety + } + template <typename T, + meta::enable<meta::neg<meta::any_same<meta::unqualified_t<T>, basic_environment>>, meta::neg<std::is_same<base_type, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_environment<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_environment>(lua_state(), -1, handler); + } +#endif // Safety + } + basic_environment(lua_nil_t r) noexcept : base_t(detail::no_safety, r) { + } + + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_environment(lua_State* L, T&& r) noexcept : base_t(detail::no_safety, L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_environment<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_environment>(lua_state(), -1, handler); + } +#endif // Safety + } + + template <typename T> + bool set_on(const T& target) const { + lua_State* L = target.lua_state(); + auto pp = stack::push_pop(target); + int target_index = pp.index_of(target); +#if SOL_LUA_VERSION_I_ < 502 + // Use lua_setfenv + this->push(); + int success_result = lua_setfenv(L, target_index); + return success_result != 0; +#else + // If this is a C function, the environment is always placed in + // the first value, as is expected of sol2 (all upvalues have an empty name, "") + if (lua_iscfunction(L, target_index) != 0) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, 1); + if (maybe_upvalue_name == nullptr) { + return false; + } + string_view upvalue_name(maybe_upvalue_name); + if (upvalue_name == "") { + this->push(); + const char* success = lua_setupvalue(L, target_index, 1); + if (success == nullptr) { + // left things alone on the stack, pop them off + lua_pop(L, 2); + return false; + } + lua_pop(L, 1); + return true; + } + lua_pop(L, 1); + return false; + } + else { + // Must search for the right upvalue target on index + for (int upvalue_index = 1;; ++upvalue_index) { + const char* maybe_upvalue_name = lua_getupvalue(L, target_index, upvalue_index); + if (maybe_upvalue_name == nullptr) { + break; + } + string_view upvalue_name(maybe_upvalue_name); + if (upvalue_name == "_ENV") { + lua_pop(L, 1); + this->push(); + const char* success = lua_setupvalue(L, target_index, upvalue_index); + if (success == nullptr) { + // left things alone on the stack, pop them off + lua_pop(L, 1); + break; + } + // whether or not we succeeded, we found _ENV + // so we need to break + return true; + } + lua_pop(L, 1); + } + // if we get here, + // we did not find an _ENV here... + return false; + } +#endif + } + }; + + template <typename T, typename E> + bool set_environment(const basic_environment<E>& env, const T& target) { + return env.set_on(target); + } + + template <typename E = reference, typename T> + basic_environment<E> get_environment(const T& target) { + lua_State* L = target.lua_state(); + auto pp = stack::pop_n(L, stack::push_environment_of(target)); + return basic_environment<E>(L, -1); + } + + struct this_environment { + optional<environment> env; + + this_environment() : env(nullopt) { + } + this_environment(environment e) : env(std::move(e)) { + } + this_environment(const this_environment&) = default; + this_environment(this_environment&&) = default; + this_environment& operator=(const this_environment&) = default; + this_environment& operator=(this_environment&&) = default; + + explicit operator bool() const { + return static_cast<bool>(env); + } + + operator optional<environment>&() { + return env; + } + + operator const optional<environment>&() const { + return env; + } + + operator environment&() { + return env.value(); + } + + operator const environment&() const { + return env.value(); + } + }; + + namespace stack { + template <> + struct unqualified_getter<env_key_t> { + static environment get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return get_environment(stack_reference(L, raw_index(index))); + } + }; + + template <> + struct unqualified_getter<this_environment> { + static this_environment get(lua_State* L, int, record& tracking) { + tracking.use(0); + lua_Debug info; + // Level 0 means current function (this C function, which may or may not be useful for us?) + // Level 1 means next call frame up the stack. (Can be nothing if function called directly from C++ with lua_p/call) + int pre_stack_size = lua_gettop(L); + if (lua_getstack(L, 1, &info) != 1) { + if (lua_getstack(L, 0, &info) != 1) { + lua_settop(L, pre_stack_size); + return this_environment(); + } + } + if (lua_getinfo(L, "f", &info) == 0) { + lua_settop(L, pre_stack_size); + return this_environment(); + } + + stack_reference f(L, -1); + environment env(env_key, f); + if (!env.valid()) { + lua_settop(L, pre_stack_size); + return this_environment(); + } + return this_environment(std::move(env)); + } + }; + } // namespace stack +} // namespace sol + +// end of sol/environment.hpp + +// beginning of sol/load_result.hpp + +#include <cstdint> + +namespace sol { + struct load_result : public proxy_base<load_result> { + private: + lua_State* L; + int index; + int returncount; + int popcount; + load_status err; + + public: + load_result() noexcept : load_result(nullptr) {} + load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept + : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) { + } + + // We do not want anyone to copy these around willy-nilly + // Will likely break people, but also will probably get rid of quiet bugs that have + // been lurking. (E.g., Vanilla Lua will just quietly discard over-pops and under-pops: + // LuaJIT and other Lua engines will implode and segfault at random later times.) + load_result(const load_result&) = delete; + load_result& operator=(const load_result&) = delete; + + load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + } + load_result& operator=(load_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + return *this; + } + + load_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == load_status::ok; + } + + template <typename T> + T get() const { + using UT = meta::unqualified_t<T>; + if constexpr (meta::is_optional_v<UT>) { + using ValueType = typename UT::value_type; + if constexpr (std::is_same_v<ValueType, error>) { + if (valid()) { + return UT(nullopt); + } + return error(detail::direct_error, stack::get<std::string>(L, index)); + } + else { + if (!valid()) { + return UT(nullopt); + } + return stack::get<UT>(L, index); + } + } + else { + if constexpr (std::is_same_v<T, error>) { +#if SOL_IS_ON(SOL_SAFE_PROXIES) + if (valid()) { + type_panic_c_str(L, index, type_of(L, index), type::none, "expecting an error type (a string, from Lua)"); + } +#endif // Check proxy type's safety + return error(detail::direct_error, stack::get<std::string>(L, index)); + } + else { +#if SOL_IS_ON(SOL_SAFE_PROXIES) + if (!valid()) { + type_panic_c_str(L, index, type_of(L, index), type::none); + } +#endif // Check proxy type's safety + return stack::get<T>(L, index); + } + } + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args) { + return get<protected_function>().template call<Ret...>(std::forward<Args>(args)...); + } + + template <typename... Args> + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward<Args>(args)...); + } + + lua_State* lua_state() const noexcept { + return L; + }; + int stack_index() const noexcept { + return index; + }; + + ~load_result() { + if (L != nullptr) { + stack::remove(L, index, popcount); + } + } + }; +} // namespace sol + +// end of sol/load_result.hpp + +// beginning of sol/state_handling.hpp + +// beginning of sol/lua_value.hpp + +namespace sol { + struct lua_value { + public: + struct arr : detail::ebco<std::initializer_list<lua_value>> { + private: + using base_t = detail::ebco<std::initializer_list<lua_value>>; + + public: + using base_t::base_t; + }; + + private: + template <typename T> + using is_reference_or_lua_value_init_list + = meta::any<meta::is_specialization_of<T, std::initializer_list>, std::is_same<T, reference>, std::is_same<T, arr>>; + + template <typename T> + using is_lua_value_single_constructible = meta::any<std::is_same<T, lua_value>, is_reference_or_lua_value_init_list<T>>; + + static lua_State*& thread_local_lua_state() { +#if SOL_IS_ON(SOL_USE_THREAD_LOCAL) + static thread_local lua_State* L = nullptr; +#else + static lua_State* L = nullptr; +#endif + return L; + } + + reference ref_value; + + public: + static void set_lua_state(lua_State* L) { + thread_local_lua_state() = L; + } + + template <typename T, meta::disable<is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler> + lua_value(lua_State* L_, T&& value) : lua_value(((set_lua_state(L_)), std::forward<T>(value))) { + } + + template <typename T, meta::disable<is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler> + lua_value(T&& value) : ref_value(make_reference(thread_local_lua_state(), std::forward<T>(value))) { + } + + lua_value(lua_State* L_, std::initializer_list<std::pair<lua_value, lua_value>> il) + : lua_value([&L_, &il]() { + set_lua_state(L_); + return std::move(il); + }()) { + } + + lua_value(std::initializer_list<std::pair<lua_value, lua_value>> il) : ref_value(make_reference(thread_local_lua_state(), std::move(il))) { + } + + lua_value(lua_State* L_, arr il) + : lua_value([&L_, &il]() { + set_lua_state(L_); + return std::move(il); + }()) { + } + + lua_value(arr il) : ref_value(make_reference(thread_local_lua_state(), std::move(il.value()))) { + } + + lua_value(lua_State* L_, reference r) + : lua_value([&L_, &r]() { + set_lua_state(L_); + return std::move(r); + }()) { + } + + lua_value(reference r) : ref_value(std::move(r)) { + } + + lua_value(const lua_value&) noexcept = default; + lua_value(lua_value&&) = default; + lua_value& operator=(const lua_value&) = default; + lua_value& operator=(lua_value&&) = default; + + const reference& value() const& { + return ref_value; + } + + reference& value() & { + return ref_value; + } + + reference&& value() && { + return std::move(ref_value); + } + + template <typename T> + decltype(auto) as() const { + ref_value.push(); + return stack::pop<T>(ref_value.lua_state()); + } + + template <typename T> + bool is() const { + int r = ref_value.registry_index(); + if (r == LUA_REFNIL) + return meta::any_same<meta::unqualified_t<T>, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; + if (r == LUA_NOREF) + return false; + auto pp = stack::push_pop(ref_value); + return stack::check<T>(ref_value.lua_state(), -1, &no_panic); + } + }; + + using array_value = typename lua_value::arr; + + namespace stack { + template <> + struct unqualified_pusher<lua_value> { + static int push(lua_State* L, const lua_value& lv) { + return stack::push(L, lv.value()); + } + + static int push(lua_State* L, lua_value&& lv) { + return stack::push(L, std::move(lv).value()); + } + }; + + template <> + struct unqualified_getter<lua_value> { + static lua_value get(lua_State* L, int index, record& tracking) { + return lua_value(L, stack::get<reference>(L, index, tracking)); + } + }; + } // namespace stack +} // namespace sol + +// end of sol/lua_value.hpp + +#if SOL_IS_ON(SOL_PRINT_ERRORS) +#include <iostream> +#endif + +namespace sol { + inline void register_main_thread(lua_State* L) { +#if SOL_LUA_VERSION_I_ < 502 + if (L == nullptr) { + lua_pushnil(L); + lua_setglobal(L, detail::default_main_thread_name()); + return; + } + lua_pushthread(L); + lua_setglobal(L, detail::default_main_thread_name()); +#else + (void)L; +#endif + } + + inline int default_at_panic(lua_State* L) { +#if SOL_IS_OFF(SOL_EXCEPTIONS) + (void)L; + return -1; +#else + size_t messagesize; + const char* message = lua_tolstring(L, -1, &messagesize); + if (message) { + std::string err(message, messagesize); + lua_settop(L, 0); +#if SOL_IS_ON(SOL_PRINT_ERRORS) + std::cerr << "[sol2] An error occurred and panic has been invoked: "; + std::cerr << err; + std::cerr << std::endl; +#endif + throw error(err); + } + lua_settop(L, 0); + throw error(std::string("An unexpected error occurred and panic has been invoked")); +#endif // Printing Errors + } + + inline int default_traceback_error_handler(lua_State* L) { + std::string msg = "An unknown error has triggered the default error handler"; + optional<string_view> maybetopmsg = stack::unqualified_check_get<string_view>(L, 1, &no_panic); + if (maybetopmsg) { + const string_view& topmsg = maybetopmsg.value(); + msg.assign(topmsg.data(), topmsg.size()); + } + luaL_traceback(L, L, msg.c_str(), 1); + optional<string_view> maybetraceback = stack::unqualified_check_get<string_view>(L, -1, &no_panic); + if (maybetraceback) { + const string_view& traceback = maybetraceback.value(); + msg.assign(traceback.data(), traceback.size()); + } +#if SOL_IS_ON(SOL_PRINT_ERRORS) + // std::cerr << "[sol2] An error occurred and was caught in traceback: "; + // std::cerr << msg; + // std::cerr << std::endl; +#endif // Printing + return stack::push(L, msg); + } + + inline void set_default_state(lua_State* L, lua_CFunction panic_function = &default_at_panic, + lua_CFunction traceback_function = c_call<decltype(&default_traceback_error_handler), &default_traceback_error_handler>, + exception_handler_function exf = detail::default_exception_handler) { + lua_atpanic(L, panic_function); + protected_function::set_default_handler(object(L, in_place, traceback_function)); + set_default_exception_handler(L, exf); + register_main_thread(L); + stack::luajit_exception_handler(L); + lua_value::set_lua_state(L); + } + + inline std::size_t total_memory_used(lua_State* L) { + std::size_t kb = static_cast<std::size_t>(lua_gc(L, LUA_GCCOUNT, 0)); + kb *= 1024; + kb += static_cast<std::size_t>(lua_gc(L, LUA_GCCOUNTB, 0)); + return kb; + } + + inline protected_function_result script_pass_on_error(lua_State*, protected_function_result result) { + return result; + } + + inline protected_function_result script_throw_on_error(lua_State* L, protected_function_result result) { + type t = type_of(L, result.stack_index()); + std::string err = "sol: "; + err += to_string(result.status()); + err += " error"; +#if SOL_IS_ON(SOL_EXCEPTIONS) + std::exception_ptr eptr = std::current_exception(); + if (eptr) { + err += " with a "; + try { + std::rethrow_exception(eptr); + } + catch (const std::exception& ex) { + err += "std::exception -- "; + err.append(ex.what()); + } + catch (const std::string& message) { + err += "thrown message -- "; + err.append(message); + } + catch (const char* message) { + err += "thrown message -- "; + err.append(message); + } + catch (...) { + err.append("thrown but unknown type, cannot serialize into error message"); + } + } +#endif // serialize exception information if possible + if (t == type::string) { + err += ": "; + string_view serr = stack::unqualified_get<string_view>(L, result.stack_index()); + err.append(serr.data(), serr.size()); + } +#if SOL_IS_ON(SOL_PRINT_ERRORS) + std::cerr << "[sol2] An error occurred and has been passed to an error handler: "; + std::cerr << err; + std::cerr << std::endl; +#endif + // replacing information of stack error into pfr + int target = result.stack_index(); + if (result.pop_count() > 0) { + stack::remove(L, target, result.pop_count()); + } + stack::push(L, err); + int top = lua_gettop(L); + int towards = top - target; + if (towards != 0) { + lua_rotate(L, top, towards); + } +#if SOL_IS_OFF(SOL_EXCEPTIONS) + return result; +#else + // just throw our error + throw error(detail::direct_error, err); +#endif // If exceptions are allowed + } + + inline protected_function_result script_default_on_error(lua_State* L, protected_function_result pfr) { +#if SOL_IS_ON(SOL_DEFAULT_PASS_ON_ERROR) + return script_pass_on_error(L, std::move(pfr)); +#else + return script_throw_on_error(L, std::move(pfr)); +#endif + } + + namespace stack { + inline error get_traceback_or_errors(lua_State* L) { + int p = default_traceback_error_handler(L); + sol::error err = stack::get<sol::error>(L, -p); + lua_pop(L, p); + return err; + } + } // namespace stack +} // namespace sol + +// end of sol/state_handling.hpp + +#include <memory> +#include <cstddef> + +namespace sol { + + class state_view { + private: + lua_State* L; + table reg; + global_table global; + + optional<object> is_loaded_package(const std::string& key) { + auto loaded = reg.traverse_get<optional<object>>("_LOADED", key); + bool is53mod = loaded && !(loaded->is<bool>() && !loaded->as<bool>()); + if (is53mod) + return loaded; +#if SOL_LUA_VERSION_I_ <= 501 + auto loaded51 = global.traverse_get<optional<object>>("package", "loaded", key); + bool is51mod = loaded51 && !(loaded51->is<bool>() && !loaded51->as<bool>()); + if (is51mod) + return loaded51; +#endif + return nullopt; + } + + template <typename T> + void ensure_package(const std::string& key, T&& sr) { +#if SOL_LUA_VERSION_I_ <= 501 + auto pkg = global["package"]; + if (!pkg.valid()) { + pkg = create_table_with("loaded", create_table_with(key, sr)); + } + else { + auto ld = pkg["loaded"]; + if (!ld.valid()) { + ld = create_table_with(key, sr); + } + else { + ld[key] = sr; + } + } +#endif + auto loaded = reg["_LOADED"]; + if (!loaded.valid()) { + loaded = create_table_with(key, sr); + } + else { + loaded[key] = sr; + } + } + + template <typename Fx> + object require_core(const std::string& key, Fx&& action, bool create_global = true) { + optional<object> loaded = is_loaded_package(key); + if (loaded && loaded->valid()) + return std::move(*loaded); + int before = lua_gettop(L); + action(); + int after = lua_gettop(L); + if (before == after) { + // I mean, you were supposed to return + // something, ANYTHING, from your requires script. I guess I'll just + // but some trash in here, it's on you after that? + ensure_package(key, static_cast<void*>(L)); + return object(L, lua_nil); + } + stack_reference sr(L, -1); + if (create_global) + set(key, sr); + ensure_package(key, sr); + return stack::pop<object>(L); + } + + public: + using iterator = typename global_table::iterator; + using const_iterator = typename global_table::const_iterator; + + state_view(lua_State* Ls) : L(Ls), reg(Ls, LUA_REGISTRYINDEX), global(Ls, global_tag) { + } + + state_view(this_state Ls) : state_view(Ls.L) { + } + + lua_State* lua_state() const { + return L; + } + + template <typename... Args> + void open_libraries(Args&&... args) { + static_assert(meta::all_same<lib, meta::unqualified_t<Args>...>::value, "all types must be libraries"); + if constexpr (sizeof...(args) == 0) { + luaL_openlibs(L); + return; + } + else { + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... }; + + for (auto&& library : libraries) { + switch (library) { +#if SOL_LUA_VERSION_I_ <= 501 && SOL_IS_ON(SOL_USE_LUAJIT) + case lib::coroutine: +#endif // luajit opens coroutine base stuff + case lib::base: + luaL_requiref(L, "base", luaopen_base, 1); + lua_pop(L, 1); + break; + case lib::package: + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + break; +#if SOL_IS_OFF(SOL_USE_LUAJIT) + case lib::coroutine: +#if SOL_LUA_VERSION_I_ > 501 + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); +#endif // Lua 5.2+ only + break; +#endif // Not LuaJIT - comes builtin + case lib::string: + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + break; + case lib::table: + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + break; + case lib::math: + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + break; + case lib::bit32: +#if SOL_IS_ON(SOL_USE_LUAJIT) + luaL_requiref(L, "bit32", luaopen_bit, 1); + lua_pop(L, 1); +#elif SOL_IS_ON(SOL_LUA_BIT32_LIB) + luaL_requiref(L, "bit32", luaopen_bit32, 1); + lua_pop(L, 1); +#else +#endif + break; + case lib::io: + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + break; + case lib::os: + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + break; + case lib::debug: + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + break; + case lib::utf8: +#if SOL_LUA_VERSION_I_ > 502 && SOL_IS_OFF(SOL_USE_LUAJIT) + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); +#endif // Lua 5.3+ only + break; + case lib::ffi: +#if SOL_IS_ON(SOL_USE_LUAJIT) && SOL_IS_OFF(SOL_LUAJIT_FFI_DISABLED) + luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); +#endif // LuaJIT only + break; + case lib::jit: +#if SOL_IS_ON(SOL_USE_LUAJIT) + luaL_requiref(L, "jit", luaopen_jit, 0); + lua_pop(L, 1); +#endif // LuaJIT Only + break; + case lib::count: + default: + break; + } + } + } + } + + object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { + luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); + return stack::pop<object>(L); + } + + object require_script(const std::string& key, const string_view& code, bool create_global = true, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + auto action = [this, &code, &chunkname, &mode]() { stack::script(L, code, chunkname, mode); }; + return require_core(key, action, create_global); + } + + object require_file(const std::string& key, const std::string& filename, bool create_global = true, load_mode mode = load_mode::any) { + auto action = [this, &filename, &mode]() { stack::script_file(L, filename, mode); }; + return require_core(key, action, create_global); + } + + void clear_package_loaders() { + optional<table> maybe_package = this->global["package"]; + if (!maybe_package) { + // package lib wasn't opened + // open package lib + return; + } + table& package = *maybe_package; + // yay for version differences... + // one day Lua 5.1 will die a peaceful death + // and its old bones will find blissful rest + auto loaders_proxy = package +#if SOL_LUA_VERSION_I_ < 502 + ["loaders"] +#else + ["searchers"] +#endif + ; + if (!loaders_proxy.valid()) { + // nothing to clear + return; + } + // we need to create the table for loaders + // table does not exist, so create and move forward + loaders_proxy = new_table(1, 0); + } + + template <typename Fx> + void add_package_loader(Fx&& fx, bool clear_all_package_loaders = false) { + optional<table> maybe_package = this->global["package"]; + if (!maybe_package) { + // package lib wasn't opened + // open package lib + return; + } + table& package = *maybe_package; + // yay for version differences... + // one day Lua 5.1 will die a peaceful death + // and its old bones will find blissful rest + auto loaders_proxy = package +#if SOL_LUA_VERSION_I_ < 502 + ["loaders"] +#else + ["searchers"] +#endif + ; + bool make_new_table = clear_all_package_loaders || !loaders_proxy.valid(); + if (make_new_table) { + // we need to create the table for loaders + // table does not exist, so create and move forward + loaders_proxy = new_table(1, 0); + } + optional<table> maybe_loaders = loaders_proxy; + if (!maybe_loaders) { + // loaders/searches + // thing exists in package, but it + // ain't a table or a table-alike...! + return; + } + table loaders = loaders_proxy; + loaders.add(std::forward<Fx>(fx)); + } + + template <typename E> + protected_function_result do_reader(lua_Reader reader, void* data, const basic_environment<E>& env, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); + load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())); + if (x != load_status::ok) { + return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); + } + stack_aligned_protected_function pf(L, -1); + set_environment(env, pf); + return pf(); + } + + protected_function_result do_reader( + lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); + load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())); + if (x != load_status::ok) { + return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); + } + stack_aligned_protected_function pf(L, -1); + return pf(); + } + + template <typename E> + protected_function_result do_string(const string_view& code, const basic_environment<E>& env, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); + load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())); + if (x != load_status::ok) { + return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); + } + stack_aligned_protected_function pf(L, -1); + set_environment(env, pf); + return pf(); + } + + protected_function_result do_string( + const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); + load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())); + if (x != load_status::ok) { + return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); + } + stack_aligned_protected_function pf(L, -1); + return pf(); + } + + template <typename E> + protected_function_result do_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { + load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); + if (x != load_status::ok) { + return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); + } + stack_aligned_protected_function pf(L, -1); + set_environment(env, pf); + return pf(); + } + + protected_function_result do_file(const std::string& filename, load_mode mode = load_mode::any) { + load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); + if (x != load_status::ok) { + return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); + } + stack_aligned_protected_function pf(L, -1); + return pf(); + } + + template <typename Fx, + meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, + meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> + protected_function_result safe_script( + lua_Reader reader, void* data, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + protected_function_result pfr = do_reader(reader, data, chunkname, mode); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + protected_function_result safe_script( + lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(reader, data, script_default_on_error, chunkname, mode); + } + + template <typename Fx, + meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, + meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> + protected_function_result safe_script( + const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + protected_function_result pfr = do_string(code, chunkname, mode); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template <typename Fx, typename E> + protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, Fx&& on_error, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + protected_function_result pfr = do_string(code, env, chunkname, mode); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template <typename E> + protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(code, env, script_default_on_error, chunkname, mode); + } + + protected_function_result safe_script( + const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(code, script_default_on_error, chunkname, mode); + } + + template <typename Fx, + meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, + meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> + protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { + protected_function_result pfr = do_file(filename, mode); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template <typename Fx, typename E> + protected_function_result safe_script_file( + const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) { + protected_function_result pfr = do_file(filename, env, mode); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template <typename E> + protected_function_result safe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { + return safe_script_file(filename, env, script_default_on_error, mode); + } + + protected_function_result safe_script_file(const std::string& filename, load_mode mode = load_mode::any) { + return safe_script_file(filename, script_default_on_error, mode); + } + + template <typename E> + unsafe_function_result unsafe_script(lua_Reader reader, void* data, const basic_environment<E>& env, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); + int index = lua_gettop(L); + if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())) { + lua_error(L); + } + set_environment(env, stack_reference(L, raw_index(index + 1))); + if (lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + int postindex = lua_gettop(L); + int returns = postindex - index; + return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + unsafe_function_result unsafe_script( + lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + int index = lua_gettop(L); + stack::script(L, reader, data, chunkname, mode); + int postindex = lua_gettop(L); + int returns = postindex - index; + return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + template <typename E> + unsafe_function_result unsafe_script(const string_view& code, const basic_environment<E>& env, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); + int index = lua_gettop(L); + if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) { + lua_error(L); + } + set_environment(env, stack_reference(L, raw_index(index + 1))); + if (lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + int postindex = lua_gettop(L); + int returns = postindex - index; + return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + unsafe_function_result unsafe_script( + const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + int index = lua_gettop(L); + stack::script(L, code, chunkname, mode); + int postindex = lua_gettop(L); + int returns = postindex - index; + return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + template <typename E> + unsafe_function_result unsafe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { + int index = lua_gettop(L); + if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) { + lua_error(L); + } + set_environment(env, stack_reference(L, raw_index(index + 1))); + if (lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + int postindex = lua_gettop(L); + int returns = postindex - index; + return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + unsafe_function_result unsafe_script_file(const std::string& filename, load_mode mode = load_mode::any) { + int index = lua_gettop(L); + stack::script_file(L, filename, mode); + int postindex = lua_gettop(L); + int returns = postindex - index; + return unsafe_function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + template <typename Fx, + meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, + meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> + protected_function_result script( + const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(code, std::forward<Fx>(on_error), chunkname, mode); + } + + template <typename Fx, + meta::disable_any<meta::is_string_constructible<meta::unqualified_t<Fx>>, + meta::is_specialization_of<meta::unqualified_t<Fx>, basic_environment>> = meta::enabler> + protected_function_result script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { + return safe_script_file(filename, std::forward<Fx>(on_error), mode); + } + + template <typename Fx, typename E> + protected_function_result script(const string_view& code, const basic_environment<E>& env, Fx&& on_error, + const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode); + } + + template <typename Fx, typename E> + protected_function_result script_file(const std::string& filename, const basic_environment<E>& env, Fx&& on_error, load_mode mode = load_mode::any) { + return safe_script_file(filename, env, std::forward<Fx>(on_error), mode); + } + + protected_function_result script( + const string_view& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(code, env, script_default_on_error, chunkname, mode); + } + + protected_function_result script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) { + return safe_script_file(filename, env, script_default_on_error, mode); + } + +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + protected_function_result script( + lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(reader, data, chunkname, mode); + } + + protected_function_result script( + const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return safe_script(code, chunkname, mode); + } + + protected_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) { + return safe_script_file(filename, mode); + } +#else + unsafe_function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return unsafe_script(code, chunkname, mode); + } + + unsafe_function_result script_file(const std::string& filename, load_mode mode = load_mode::any) { + return unsafe_script_file(filename, mode); + } +#endif + load_result load(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); + load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())); + return load_result(L, absolute_index(L, -1), 1, 1, x); + } + + load_result load_buffer(const char* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return load(string_view(buff, size), chunkname, mode); + } + + load_result load_buffer( + const std::byte* buff, size_t size, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + return load(string_view(reinterpret_cast<const char*>(buff), size), chunkname, mode); + } + + load_result load_file(const std::string& filename, load_mode mode = load_mode::any) { + load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); + return load_result(L, absolute_index(L, -1), 1, 1, x); + } + + load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; + const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); + load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str())); + return load_result(L, absolute_index(L, -1), 1, 1, x); + } + + iterator begin() const { + return global.begin(); + } + + iterator end() const { + return global.end(); + } + + const_iterator cbegin() const { + return global.cbegin(); + } + + const_iterator cend() const { + return global.cend(); + } + + global_table globals() const { + // if we return a reference + // we'll be screwed a bit + return global; + } + + global_table& globals() { + return global; + } + + table registry() const { + return reg; + } + + std::size_t memory_used() const { + return total_memory_used(lua_state()); + } + + int stack_top() const { + return stack::top(L); + } + + int stack_clear() { + int s = stack_top(); + lua_pop(L, s); + return s; + } + + bool supports_gc_mode(gc_mode mode) const noexcept { +#if SOL_LUA_VERSION_I_ >= 504 + // supports all modes + (void)mode; + return true; +#endif + return mode == gc_mode::default_value; + } + + bool is_gc_on() const { +#if SOL_LUA_VERSION_I_ >= 502 + return lua_gc(lua_state(), LUA_GCISRUNNING, 0) == 1; +#else + // You cannot turn it off in Lua 5.1 + return true; +#endif + } + + void collect_garbage() { + lua_gc(lua_state(), LUA_GCCOLLECT, 0); + } + + void collect_gc() { + collect_garbage(); + } + + bool step_gc(int step_size_kilobytes) { + // THOUGHT: std::chrono-alikes to map "kilobyte size" here...? + // Make it harder to give MB or KB to a B parameter...? + // Probably overkill for now. +#if SOL_LUA_VERSION_I_ >= 504 + // The manual implies that this function is almost always successful... + // is it?? It could depend on the GC mode... + return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) != 0; +#else + return lua_gc(lua_state(), LUA_GCSTEP, step_size_kilobytes) == 1; +#endif + } + + void restart_gc() { + lua_gc(lua_state(), LUA_GCRESTART, 0); + } + + void stop_gc() { + lua_gc(lua_state(), LUA_GCSTOP, 0); + } + + // Returns the old GC mode. Check support using the supports_gc_mode function. + gc_mode change_gc_mode_incremental(int pause, int step_multiplier, int step_byte_size) { + // "What the fuck does any of this mean??" + // http://www.lua.org/manual/5.4/manual.html#2.5.1 + + // THOUGHT: std::chrono-alikes to map "byte size" here...? + // Make it harder to give MB or KB to a B parameter...? + // Probably overkill for now. +#if SOL_LUA_VERSION_I_ >= 504 + int old_mode = lua_gc(lua_state(), LUA_GCINC, pause, step_multiplier, step_byte_size); + if (old_mode == LUA_GCGEN) { + return gc_mode::generational; + } + else if (old_mode == LUA_GCINC) { + return gc_mode::incremental; + } +#else + lua_gc(lua_state(), LUA_GCSETPAUSE, pause); + lua_gc(lua_state(), LUA_GCSETSTEPMUL, step_multiplier); + (void)step_byte_size; // means nothing in older versions +#endif + return gc_mode::default_value; + } + + // Returns the old GC mode. Check support using the supports_gc_mode function. + gc_mode change_gc_mode_generational(int minor_multiplier, int major_multiplier) { +#if SOL_LUA_VERSION_I_ >= 504 + // "What does this shit mean?" + // http://www.lua.org/manual/5.4/manual.html#2.5.2 + int old_mode = lua_gc(lua_state(), LUA_GCGEN, minor_multiplier, major_multiplier); + if (old_mode == LUA_GCGEN) { + return gc_mode::generational; + } + else if (old_mode == LUA_GCINC) { + return gc_mode::incremental; + } +#else + (void)minor_multiplier; + (void)major_multiplier; +#endif + return gc_mode::default_value; + } + + operator lua_State*() const { + return lua_state(); + } + + void set_panic(lua_CFunction panic) { + lua_atpanic(lua_state(), panic); + } + + void set_exception_handler(exception_handler_function handler) { + set_default_exception_handler(lua_state(), handler); + } + + template <typename... Args, typename... Keys> + decltype(auto) get(Keys&&... keys) const { + return global.get<Args...>(std::forward<Keys>(keys)...); + } + + template <typename T, typename Key> + decltype(auto) get_or(Key&& key, T&& otherwise) const { + return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise)); + } + + template <typename T, typename Key, typename D> + decltype(auto) get_or(Key&& key, D&& otherwise) const { + return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise)); + } + + template <typename... Args> + state_view& set(Args&&... args) { + global.set(std::forward<Args>(args)...); + return *this; + } + + template <typename T, typename... Keys> + decltype(auto) traverse_get(Keys&&... keys) const { + return global.traverse_get<T>(std::forward<Keys>(keys)...); + } + + template <typename... Args> + state_view& traverse_set(Args&&... args) { + global.traverse_set(std::forward<Args>(args)...); + return *this; + } + + template <typename Class, typename... Args> + usertype<Class> new_usertype(Args&&... args) { + return global.new_usertype<Class>(std::forward<Args>(args)...); + } + + template <bool read_only = true, typename... Args> + state_view& new_enum(const string_view& name, Args&&... args) { + global.new_enum<read_only>(name, std::forward<Args>(args)...); + return *this; + } + + template <typename T, bool read_only = true> + state_view& new_enum(const string_view& name, std::initializer_list<std::pair<string_view, T>> items) { + global.new_enum<T, read_only>(name, std::move(items)); + return *this; + } + + template <typename Fx> + void for_each(Fx&& fx) { + global.for_each(std::forward<Fx>(fx)); + } + + template <typename T> + table_proxy<global_table&, detail::proxy_key_t<T>> operator[](T&& key) { + return global[std::forward<T>(key)]; + } + + template <typename T> + table_proxy<const global_table&, detail::proxy_key_t<T>> operator[](T&& key) const { + return global[std::forward<T>(key)]; + } + + template <typename Sig, typename... Args, typename Key> + state_view& set_function(Key&& key, Args&&... args) { + global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename... Args, typename Key> + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward<Key>(key), std::forward<Args>(args)...); + return *this; + } + + template <typename Name> + table create_table(Name&& name, int narr = 0, int nrec = 0) { + return global.create(std::forward<Name>(name), narr, nrec); + } + + template <typename Name, typename Key, typename Value, typename... Args> + table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); + } + + template <typename Name, typename... Args> + table create_named_table(Name&& name, Args&&... args) { + table x = global.create_with(std::forward<Args>(args)...); + global.set(std::forward<Name>(name), x); + return x; + } + + table create_table(int narr = 0, int nrec = 0) { + return create_table(lua_state(), narr, nrec); + } + + template <typename Key, typename Value, typename... Args> + table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); + } + + template <typename... Args> + table create_table_with(Args&&... args) { + return create_table_with(lua_state(), std::forward<Args>(args)...); + } + + static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { + return global_table::create(L, narr, nrec); + } + + template <typename Key, typename Value, typename... Args> + static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); + } + + template <typename... Args> + static inline table create_table_with(lua_State* L, Args&&... args) { + return global_table::create_with(L, std::forward<Args>(args)...); + } + }; +} // namespace sol + +// end of sol/state_view.hpp + +// beginning of sol/thread.hpp + +namespace sol { + struct lua_thread_state { + lua_State* L; + + lua_thread_state(lua_State* Ls) : L(Ls) { + } + + lua_State* lua_state() const noexcept { + return L; + } + operator lua_State*() const noexcept { + return lua_state(); + } + lua_State* operator->() const noexcept { + return lua_state(); + } + }; + + namespace stack { + template <> + struct unqualified_pusher<lua_thread_state> { + int push(lua_State*, lua_thread_state lts) { + lua_pushthread(lts.L); + return 1; + } + }; + + template <> + struct unqualified_getter<lua_thread_state> { + lua_thread_state get(lua_State* L, int index, record& tracking) { + tracking.use(1); + lua_thread_state lts(lua_tothread(L, index)); + return lts; + } + }; + + template <> + struct unqualified_check_getter<lua_thread_state> { + template <typename Handler> + optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) { + lua_thread_state lts(lua_tothread(L, index)); + if (lts.lua_state() == nullptr) { + handler(L, index, type::thread, type_of(L, index), "value is not a valid thread type"); + return nullopt; + } + tracking.use(1); + return lts; + } + }; + } // namespace stack + + template <typename ref_t> + class basic_thread : public basic_object<ref_t> { + private: + using base_t = basic_object<ref_t>; + + public: + using base_t::lua_state; + + basic_thread() noexcept = default; + basic_thread(const basic_thread&) = default; + basic_thread(basic_thread&&) = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_thread>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_thread(T&& r) : base_t(std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_thread>(lua_state(), -1, handler); +#endif // Safety + } + basic_thread(const stack_reference& r) : basic_thread(r.lua_state(), r.stack_index()) {}; + basic_thread(stack_reference&& r) : basic_thread(r.lua_state(), r.stack_index()) {}; + basic_thread& operator=(const basic_thread&) = default; + basic_thread& operator=(basic_thread&&) = default; + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_thread(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_thread>(lua_state(), -1, handler); +#endif // Safety + } + basic_thread(lua_State* L, int index = -1) : base_t(L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_thread>(L, index, handler); +#endif // Safety + } + basic_thread(lua_State* L, ref_index index) : base_t(L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_thread>(lua_state(), -1, handler); +#endif // Safety + } + basic_thread(lua_State* L, lua_State* actualthread) : basic_thread(L, lua_thread_state { actualthread }) { + } + basic_thread(lua_State* L, this_state actualthread) : basic_thread(L, lua_thread_state { actualthread.L }) { + } + basic_thread(lua_State* L, lua_thread_state actualthread) : base_t(L, -stack::push(L, actualthread)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_thread>(lua_state(), -1, handler); +#endif // Safety + if (!is_stack_based<base_t>::value) { + lua_pop(lua_state(), 1); + } + } + + state_view state() const { + return state_view(this->thread_state()); + } + + bool is_main_thread() const { + return stack::is_main_thread(this->thread_state()); + } + + lua_State* thread_state() const { + auto pp = stack::push_pop(*this); + lua_State* lthread = lua_tothread(lua_state(), -1); + return lthread; + } + + thread_status status() const { + lua_State* lthread = thread_state(); + auto lstat = static_cast<thread_status>(lua_status(lthread)); + if (lstat == thread_status::ok) { + lua_Debug ar; + if (lua_getstack(lthread, 0, &ar) > 0) + return thread_status::ok; + else if (lua_gettop(lthread) == 0) + return thread_status::dead; + else + return thread_status::yielded; + } + return lstat; + } + + basic_thread create() { + return create(lua_state()); + } + + static basic_thread create(lua_State* L) { + lua_newthread(L); + basic_thread result(L); + if (!is_stack_based<base_t>::value) { + lua_pop(L, 1); + } + return result; + } + }; + + typedef basic_thread<reference> thread; + typedef basic_thread<stack_reference> stack_thread; +} // namespace sol + +// end of sol/thread.hpp + +namespace sol { + + class state : private std::unique_ptr<lua_State, detail::state_deleter>, public state_view { + private: + typedef std::unique_ptr<lua_State, detail::state_deleter> unique_base; + + public: + state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate()), state_view(unique_base::get()) { + set_default_state(unique_base::get(), panic); + } + + state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) + : unique_base(lua_newstate(alfunc, alpointer)), state_view(unique_base::get()) { + set_default_state(unique_base::get(), panic); + } + + state(const state&) = delete; + state(state&&) = default; + state& operator=(const state&) = delete; + state& operator=(state&& that) { + state_view::operator=(std::move(that)); + unique_base::operator=(std::move(that)); + return *this; + } + + using state_view::get; + + ~state() { + } + }; +} // namespace sol + +// end of sol/state.hpp + +// beginning of sol/coroutine.hpp + +namespace sol { + template <typename Reference> + class basic_coroutine : public basic_object<Reference> { + private: + using base_t = basic_object<Reference>; + using handler_t = reference; + + private: + call_status stats = call_status::yielded; + + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { +#if SOL_LUA_VERSION_I_ >= 504 + int nresults; + stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount), &nresults)); +#else + stats = static_cast<call_status>(lua_resume(lua_state(), nullptr, static_cast<int>(argcount))); +#endif + } + + template <std::size_t... I, typename... Ret> + auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n) { + luacall(n, sizeof...(Ret)); + return stack::pop<std::tuple<Ret...>>(lua_state()); + } + + template <std::size_t I, typename Ret> + Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n) { + luacall(n, 1); + return stack::pop<Ret>(lua_state()); + } + + template <std::size_t I> + void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) { + luacall(n, 0); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { + int firstreturn = 1; + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(this->lua_state()); + int returncount = poststacksize - (firstreturn - 1); + if (error()) { + if (m_error_handler.valid()) { + string_view err = stack::get<string_view>(this->lua_state(), poststacksize); + m_error_handler.push(); + stack::push(this->lua_state(), err); + lua_call(lua_state(), 1, 1); + } + return protected_function_result(this->lua_state(), lua_absindex(this->lua_state(), -1), 1, returncount, status()); + } + return protected_function_result(this->lua_state(), firstreturn, returncount, returncount, status()); + } + + public: + using base_t::lua_state; + + basic_coroutine() = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_coroutine>>, + meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>, meta::neg<std::is_same<base_t, stack_reference>>, + meta::neg<std::is_same<lua_nil_t, meta::unqualified_t<T>>>, is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_coroutine(T&& r) noexcept + : base_t(std::forward<T>(r)), m_error_handler(detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_function<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_coroutine>(lua_state(), -1, handler); + } +#endif // Safety + } + + basic_coroutine(const basic_coroutine& other) = default; + basic_coroutine& operator=(const basic_coroutine&) = default; + + basic_coroutine(basic_coroutine&& other) noexcept : base_t(std::move(other)), m_error_handler(this->lua_state(), std::move(other.m_error_handler)) { + } + + basic_coroutine& operator=(basic_coroutine&& other) noexcept { + base_t::operator=(std::move(other)); + // must change the state, since it could change on the coroutine type + m_error_handler = handler_t(this->lua_state(), std::move(other.m_error_handler)); + return *this; + } + + basic_coroutine(const basic_function<base_t>& b) noexcept + : basic_coroutine(b, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(b.lua_state())) { + } + basic_coroutine(basic_function<base_t>&& b) noexcept + : basic_coroutine(std::move(b), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(b.lua_state())) { + } + basic_coroutine(const basic_function<base_t>& b, handler_t eh) noexcept : base_t(b), m_error_handler(std::move(eh)) { + } + basic_coroutine(basic_function<base_t>&& b, handler_t eh) noexcept : base_t(std::move(b)), m_error_handler(std::move(eh)) { + } + basic_coroutine(const stack_reference& r) noexcept + : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { + } + basic_coroutine(stack_reference&& r) noexcept + : basic_coroutine(r.lua_state(), r.stack_index(), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(r.lua_state())) { + } + basic_coroutine(const stack_reference& r, handler_t eh) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { + } + basic_coroutine(stack_reference&& r, handler_t eh) noexcept : basic_coroutine(r.lua_state(), r.stack_index(), std::move(eh)) { + } + + template <typename Super> + basic_coroutine(const proxy_base<Super>& p) + : basic_coroutine(p, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) { + } + template <typename Super> + basic_coroutine(proxy_base<Super>&& p) + : basic_coroutine(std::move(p), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(p.lua_state())) { + } + template <typename Proxy, typename HandlerReference, + meta::enable<std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>, + meta::neg<is_lua_index<meta::unqualified_t<HandlerReference>>>> = meta::enabler> + basic_coroutine(Proxy&& p, HandlerReference&& eh) : basic_coroutine(detail::force_cast<base_t>(p), std::forward<HandlerReference>(eh)) { + } + + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_coroutine(lua_State* L, T&& r) noexcept + : basic_coroutine(L, std::forward<T>(r), detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_coroutine(lua_State* L, T&& r, handler_t eh) : base_t(L, std::forward<T>(r)), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_coroutine>(lua_state(), -1, handler); +#endif // Safety + } + + basic_coroutine(lua_nil_t n) : base_t(n), m_error_handler(n) { + } + + basic_coroutine(lua_State* L, int index = -1) + : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { + } + basic_coroutine(lua_State* L, int index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { +#ifdef SOL_SAFE_REFERENCES + constructor_handler handler {}; + stack::check<basic_coroutine>(L, index, handler); +#endif // Safety + } + basic_coroutine(lua_State* L, absolute_index index) + : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { + } + basic_coroutine(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_coroutine>(L, index, handler); +#endif // Safety + } + basic_coroutine(lua_State* L, raw_index index) + : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { + } + basic_coroutine(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_coroutine>(L, index, handler); +#endif // Safety + } + basic_coroutine(lua_State* L, ref_index index) + : basic_coroutine(L, index, detail::get_default_handler<reference, is_main_threaded<base_t>::value>(L)) { + } + basic_coroutine(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), m_error_handler(std::move(eh)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_coroutine>(lua_state(), -1, handler); +#endif // Safety + } + + call_status status() const noexcept { + return stats; + } + + bool error() const noexcept { + call_status cs = status(); + return cs != call_status::ok && cs != call_status::yielded; + } + + bool runnable() const noexcept { + return base_t::valid() && (status() == call_status::yielded); + } + + explicit operator bool() const noexcept { + return runnable(); + } + + template <typename... Args> + protected_function_result operator()(Args&&... args) { + return call<>(std::forward<Args>(args)...); + } + + template <typename... Ret, typename... Args> + decltype(auto) operator()(types<Ret...>, Args&&... args) { + return call<Ret...>(std::forward<Args>(args)...); + } + + template <typename... Ret, typename... Args> + decltype(auto) call(Args&&... args) { + // some users screw up coroutine.create + // and try to use it with sol::coroutine without ever calling the first resume in Lua + // this makes the stack incompatible with other kinds of stacks: protect against this + // make sure coroutines don't screw us over + base_t::push(); + int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); + return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount); + } + + private: + handler_t m_error_handler; + }; +} // namespace sol + +// end of sol/coroutine.hpp + +// beginning of sol/userdata.hpp + +namespace sol { + template <typename base_type> + class basic_userdata : public basic_table<base_type> { + private: + using base_t = basic_table<base_type>; + + public: + using base_t::lua_state; + + basic_userdata() noexcept = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_userdata>>, meta::neg<std::is_same<base_t, stack_reference>>, + is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_userdata(T&& r) noexcept : base_t(std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_userdata<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + type_assert(lua_state(), -1, type::userdata); + } +#endif // Safety + } + basic_userdata(const basic_userdata&) = default; + basic_userdata(basic_userdata&&) = default; + basic_userdata& operator=(const basic_userdata&) = default; + basic_userdata& operator=(basic_userdata&&) = default; + basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) { + } + basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_userdata(lua_State* L, T&& r) : base_t(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_userdata>(L, -1, handler); +#endif // Safety + } + basic_userdata(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_userdata>(L, index, handler); +#endif // Safety + } + basic_userdata(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_userdata>(L, -1, handler); +#endif // Safety + } + }; + + template <typename base_type> + class basic_lightuserdata : public basic_object_base<base_type> { + typedef basic_object_base<base_type> base_t; + + public: + using base_t::lua_state; + + basic_lightuserdata() noexcept = default; + template <typename T, + meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_lightuserdata>>, meta::neg<std::is_same<base_t, stack_reference>>, + is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_lightuserdata(T&& r) noexcept : base_t(std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + if (!is_lightuserdata<meta::unqualified_t<T>>::value) { + auto pp = stack::push_pop(*this); + type_assert(lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } + basic_lightuserdata(const basic_lightuserdata&) = default; + basic_lightuserdata(basic_lightuserdata&&) = default; + basic_lightuserdata& operator=(const basic_lightuserdata&) = default; + basic_lightuserdata& operator=(basic_lightuserdata&&) = default; + basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) { + } + basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) { + } + template <typename T, meta::enable<is_lua_reference<meta::unqualified_t<T>>> = meta::enabler> + basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, std::forward<T>(r)) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_lightuserdata>(lua_state(), -1, handler); +#endif // Safety + } + basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + constructor_handler handler {}; + stack::check<basic_lightuserdata>(L, index, handler); +#endif // Safety + } + basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { +#if SOL_IS_ON(SOL_SAFE_REFERENCES) + auto pp = stack::push_pop(*this); + constructor_handler handler {}; + stack::check<basic_lightuserdata>(lua_state(), index, handler); +#endif // Safety + } + }; + +} // namespace sol + +// end of sol/userdata.hpp + +// beginning of sol/as_args.hpp + +namespace sol { + template <typename T> + struct as_args_t { + T src; + }; + + template <typename Source> + auto as_args(Source&& source) { + return as_args_t<Source> { std::forward<Source>(source) }; + } + + namespace stack { + template <typename T> + struct unqualified_pusher<as_args_t<T>> { + int push(lua_State* L, const as_args_t<T>& e) { + int p = 0; + for (const auto& i : e.src) { + p += stack::push(L, i); + } + return p; + } + }; + } // namespace stack +} // namespace sol + +// end of sol/as_args.hpp + +// beginning of sol/variadic_args.hpp + +#include <limits> +#include <iterator> + +namespace sol { + struct variadic_args { + private: + lua_State* L; + int index; + int stacktop; + + public: + typedef stack_proxy reference_type; + typedef stack_proxy value_type; + typedef stack_proxy* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef stack_iterator<stack_proxy, false> iterator; + typedef stack_iterator<stack_proxy, true> const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + variadic_args() = default; + variadic_args(lua_State* luastate, int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) { + } + variadic_args(lua_State* luastate, int stackindex, int lastindex) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lastindex) { + } + variadic_args(const variadic_args&) = default; + variadic_args& operator=(const variadic_args&) = default; + variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + } + variadic_args& operator=(variadic_args&& o) { + L = o.L; + index = o.index; + stacktop = o.stacktop; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + return *this; + } + + iterator begin() { + return iterator(L, index, stacktop + 1); + } + iterator end() { + return iterator(L, stacktop + 1, stacktop + 1); + } + const_iterator begin() const { + return const_iterator(L, index, stacktop + 1); + } + const_iterator end() const { + return const_iterator(L, stacktop + 1, stacktop + 1); + } + const_iterator cbegin() const { + return begin(); + } + const_iterator cend() const { + return end(); + } + + reverse_iterator rbegin() { + return std::reverse_iterator<iterator>(begin()); + } + reverse_iterator rend() { + return std::reverse_iterator<iterator>(end()); + } + const_reverse_iterator rbegin() const { + return std::reverse_iterator<const_iterator>(begin()); + } + const_reverse_iterator rend() const { + return std::reverse_iterator<const_iterator>(end()); + } + const_reverse_iterator crbegin() const { + return std::reverse_iterator<const_iterator>(cbegin()); + } + const_reverse_iterator crend() const { + return std::reverse_iterator<const_iterator>(cend()); + } + + int push() const { + return push(L); + } + + int push(lua_State* target) const { + int pushcount = 0; + for (int i = index; i <= stacktop; ++i) { + lua_pushvalue(L, i); + pushcount += 1; + } + if (target != L) { + lua_xmove(L, target, pushcount); + } + return pushcount; + } + + template <typename T> + decltype(auto) get(difference_type index_offset = 0) const { + return stack::get<T>(L, index + static_cast<int>(index_offset)); + } + + type get_type(difference_type index_offset = 0) const noexcept { + return type_of(L, index + static_cast<int>(index_offset)); + } + + stack_proxy operator[](difference_type index_offset) const { + return stack_proxy(L, index + static_cast<int>(index_offset)); + } + + lua_State* lua_state() const { + return L; + }; + int stack_index() const { + return index; + }; + int leftover_count() const { + return stacktop - (index - 1); + } + std::size_t size() const { + return static_cast<std::size_t>(leftover_count()); + } + int top() const { + return stacktop; + } + }; + + namespace stack { + template <> + struct unqualified_getter<variadic_args> { + static variadic_args get(lua_State* L, int index, record& tracking) { + tracking.last = 0; + return variadic_args(L, index); + } + }; + + template <> + struct unqualified_pusher<variadic_args> { + static int push(lua_State* L, const variadic_args& ref) { + return ref.push(L); + } + }; + } // namespace stack +} // namespace sol + +// end of sol/variadic_args.hpp + +// beginning of sol/variadic_results.hpp + +// beginning of sol/as_returns.hpp + +namespace sol { + template <typename T> + struct as_returns_t : private detail::ebco<T> { + private: + using base_t = detail::ebco<T>; + + public: + using base_t::base_t; + using base_t::value; + }; + + template <typename Source> + auto as_returns(Source&& source) { + return as_returns_t<std::decay_t<Source>> { std::forward<Source>(source) }; + } + + namespace stack { + template <typename T> + struct unqualified_pusher<as_returns_t<T>> { + int push(lua_State* L, const as_returns_t<T>& e) { + auto& src = detail::unwrap(e.value()); + int p = 0; + for (const auto& i : src) { + p += stack::push(L, i); + } + return p; + } + }; + } // namespace stack +} // namespace sol + +// end of sol/as_returns.hpp + +#include <vector> + +namespace sol { + + template <typename Al = typename std::allocator<object>> + struct basic_variadic_results : public std::vector<object, Al> { + private: + using base_t = std::vector<object, Al>; + + public: + basic_variadic_results() : base_t() { + } + + basic_variadic_results(unsafe_function_result fr) : base_t() { + this->reserve(fr.return_count()); + this->insert(this->cend(), fr.begin(), fr.end()); + } + + basic_variadic_results(protected_function_result fr) : base_t() { + this->reserve(fr.return_count()); + this->insert(this->cend(), fr.begin(), fr.end()); + } + + template <typename Arg0, typename... Args, + meta::disable_any<std::is_same<meta::unqualified_t<Arg0>, basic_variadic_results>, std::is_same<meta::unqualified_t<Arg0>, function_result>, + std::is_same<meta::unqualified_t<Arg0>, protected_function_result>> = meta::enabler> + basic_variadic_results(Arg0&& arg0, Args&&... args) : base_t(std::forward<Arg0>(arg0), std::forward<Args>(args)...) { + } + + basic_variadic_results(const basic_variadic_results&) = default; + basic_variadic_results(basic_variadic_results&&) = default; + }; + + struct variadic_results : public basic_variadic_results<> { + private: + using base_t = basic_variadic_results<>; + + public: + using base_t::base_t; + }; + + template <typename Al> + struct is_container<basic_variadic_results<Al>> : std::false_type { }; + + template <> + struct is_container<variadic_results> : std::false_type { }; + + namespace stack { + template <typename Al> + struct unqualified_pusher<basic_variadic_results<Al>> { + int push(lua_State* L, const basic_variadic_results<Al>& e) { + int p = 0; + for (const auto& i : e) { + p += stack::push(L, i); + } + return p; + } + }; + + template <> + struct unqualified_pusher<variadic_results> { + int push(lua_State* L, const variadic_results& r) { + using base_t = basic_variadic_results<>; + return stack::push(L, static_cast<const base_t&>(r)); + } + }; + } // namespace stack + +} // namespace sol + +// end of sol/variadic_results.hpp + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic pop +#elif SOL_IS_ON(SOL_COMPILER_CLANG) +#elif SOL_IS_ON(SOL_COMPILER_VCXX) +#pragma warning(pop) +#endif // g++ + +#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE) +#undef check +#pragma pop_macro("check") +#endif // Unreal Engine 4 Bullshit + +#endif // SOL_HPP +// end of sol/sol.hpp + +#endif // SOL_SINGLE_INCLUDE_HPP diff --git a/3rdparty/sol2/sol/stack.hpp b/3rdparty/sol2/sol/stack.hpp deleted file mode 100644 index b3bf6dec200..00000000000 --- a/3rdparty/sol2/sol/stack.hpp +++ /dev/null @@ -1,229 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_HPP -#define SOL_STACK_HPP - -#include "stack_core.hpp" -#include "stack_reference.hpp" -#include "stack_check.hpp" -#include "stack_get.hpp" -#include "stack_check_get.hpp" -#include "stack_push.hpp" -#include "stack_pop.hpp" -#include "stack_field.hpp" -#include "stack_probe.hpp" -#include <cstring> -#include <array> - -namespace sol { - namespace stack { - namespace stack_detail { - template<typename T> - inline int push_as_upvalues(lua_State* L, T& item) { - typedef std::decay_t<T> TValue; - const static std::size_t itemsize = sizeof(TValue); - const static std::size_t voidsize = sizeof(void*); - const static std::size_t voidsizem1 = voidsize - 1; - const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; - typedef std::array<void*, data_t_count> data_t; - - data_t data{ {} }; - std::memcpy(&data[0], std::addressof(item), itemsize); - int pushcount = 0; - for (auto&& v : data) { - pushcount += push(L, lightuserdata_value(v)); - } - return pushcount; - } - - template<typename T> - inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) { - const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); - typedef std::array<void*, data_t_count> data_t; - data_t voiddata{ {} }; - for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { - voiddata[i] = get<lightuserdata_value>(L, upvalue_index(index++)); - } - return std::pair<T, int>(*reinterpret_cast<T*>(static_cast<void*>(voiddata.data())), index); - } - - struct evaluator { - template <typename Fx, typename... Args> - static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) { - return std::forward<Fx>(fx)(std::forward<Args>(args)...); - } - - template <typename Fx, typename Arg, typename... Args, std::size_t I, std::size_t... Is, typename... FxArgs> - static decltype(auto) eval(types<Arg, Args...>, std::index_sequence<I, Is...>, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { - return eval(types<Args...>(), std::index_sequence<Is...>(), L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)..., stack_detail::unchecked_get<Arg>(L, start + tracking.used, tracking)); - } - }; - - template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER - static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so fucking sad - multi_check<checkargs, Args...>(L, start, type_panic); - record tracking{}; - return evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool checkargs = default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs> - inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { -#ifndef _MSC_VER - static_assert(meta::all<meta::is_not_move_only<Args>...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); -#endif // This compiler make me so fucking sad - multi_check<checkargs, Args...>(L, start, type_panic); - record tracking{}; - evaluator{}.eval(ta, tai, L, start, tracking, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - } // stack_detail - - template <typename T> - int set_ref(lua_State* L, T&& arg, int tableindex = -2) { - push(L, std::forward<T>(arg)); - return luaL_ref(L, tableindex); - } - - inline void remove(lua_State* L, int index, int count) { - if (count < 1) - return; - int top = lua_gettop(L); - if (index == -1 || top == index) { - // Slice them right off the top - lua_pop(L, static_cast<int>(count)); - return; - } - - // Remove each item one at a time using stack operations - // Probably slower, maybe, haven't benchmarked, - // but necessary - if (index < 0) { - index = lua_gettop(L) + (index + 1); - } - int last = index + count; - for (int i = index; i < last; ++i) { - lua_remove(L, index); - } - } - - template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence<sizeof...(Args)> args_indices; - return stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - return call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline void call(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - typedef std::make_index_sequence<sizeof...(Args)> args_indices; - stack_detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - call<check_args>(tr, ta, L, 1, std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>> - inline decltype(auto) call_from_top(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - return call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template <bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline void call_from_top(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - call<check_args>(tr, ta, L, static_cast<int>(lua_gettop(L) - sizeof...(Args)), std::forward<Fx>(fx), std::forward<FxArgs>(args)...); - } - - template<bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> - inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); - lua_settop(L, 0); - return 0; - } - - template<bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>> - inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); - lua_settop(L, 0); - return push_reference(L, std::forward<decltype(r)>(r)); - } - - template<bool check_args = stack_detail::default_check_arguments, typename Fx, typename... FxArgs> - inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { - typedef lua_bind_traits<meta::unqualified_t<Fx>> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::returns_list returns_list; - return call_into_lua(returns_list(), args_list(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); - } - - inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index) { - if (lua_gettop(L) == 0) { - return call_syntax::dot; - } - luaL_getmetatable(L, key.c_str()); - auto pn = pop_n(L, 1); - if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { - return call_syntax::dot; - } - return call_syntax::colon; - } - - inline void script(lua_State* L, const std::string& code) { - if (luaL_dostring(L, code.c_str())) { - lua_error(L); - } - } - - inline void script_file(lua_State* L, const std::string& filename) { - if (luaL_dofile(L, filename.c_str())) { - lua_error(L); - } - } - - inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { -#ifdef SOL_LUAJIT - lua_pushlightuserdata(L, (void*)handler); - auto pn = pop_n(L, 1); - luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); -#else - (void)L; - (void)handler; -#endif - } - - inline void luajit_exception_off(lua_State* L) { -#ifdef SOL_LUAJIT - luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); -#else - (void)L; -#endif - } - } // stack -} // sol - -#endif // SOL_STACK_HPP diff --git a/3rdparty/sol2/sol/stack_check.hpp b/3rdparty/sol2/sol/stack_check.hpp deleted file mode 100644 index 82739c831a7..00000000000 --- a/3rdparty/sol2/sol/stack_check.hpp +++ /dev/null @@ -1,385 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_CHECK_HPP -#define SOL_STACK_CHECK_HPP - -#include "stack_core.hpp" -#include "usertype_traits.hpp" -#include "inheritance.hpp" -#include <memory> -#include <functional> -#include <utility> - -namespace sol { - namespace stack { - namespace stack_detail { - template <typename T, bool poptable = true> - inline bool check_metatable(lua_State* L, int index = -2) { - const auto& metakey = usertype_traits<T>::metatable(); - luaL_getmetatable(L, &metakey[0]); - const type expectedmetatabletype = static_cast<type>(lua_type(L, -1)); - if (expectedmetatabletype != type::lua_nil) { - if (lua_rawequal(L, -1, index) == 1) { - lua_pop(L, 1 + static_cast<int>(poptable)); - return true; - } - } - lua_pop(L, 1); - return false; - } - - template <type expected, int(*check_func)(lua_State*, int)> - struct basic_check { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = check_func(L, index) == 1; - if (!success) { - // expected type, actual type - handler(L, index, expected, type_of(L, index)); - } - return success; - } - }; - } // stack_detail - - template <typename T, type expected, typename> - struct checker { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - const type indextype = type_of(L, index); - bool success = expected == indextype; - if (!success) { - // expected type, actual type - handler(L, index, expected, indextype); - } - return success; - } - }; - - template<typename T> - struct checker<T, type::number, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = lua_isinteger(L, index) == 1; - if (!success) { - // expected type, actual type - handler(L, index, type::number, type_of(L, index)); - } - return success; - } - }; - - template<typename T> - struct checker<T, type::number, std::enable_if_t<std::is_floating_point<T>::value>> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = lua_isnumber(L, index) == 1; - if (!success) { - // expected type, actual type - handler(L, index, type::number, type_of(L, index)); - } - return success; - } - }; - - template <type expected, typename C> - struct checker<lua_nil_t, expected, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - bool success = lua_isnil(L, index); - if (success) { - tracking.use(1); - return success; - } - tracking.use(0); - success = lua_isnone(L, index); - if (!success) { - // expected type, actual type - handler(L, index, expected, type_of(L, index)); - } - return success; - } - }; - - template <type expected, typename C> - struct checker<nullopt_t, expected, C> : checker<lua_nil_t> {}; - - template <typename C> - struct checker<this_state, type::poly, C> { - template <typename Handler> - static bool check(lua_State*, int, Handler&&, record& tracking) { - tracking.use(0); - return true; - } - }; - - template <typename C> - struct checker<variadic_args, type::poly, C> { - template <typename Handler> - static bool check(lua_State*, int, Handler&&, record& tracking) { - tracking.use(0); - return true; - } - }; - - template <typename C> - struct checker<type, type::poly, C> { - template <typename Handler> - static bool check(lua_State*, int, Handler&&, record& tracking) { - tracking.use(0); - return true; - } - }; - - template <typename T, typename C> - struct checker<T, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - bool success = !lua_isnone(L, index); - if (!success) { - // expected type, actual type - handler(L, index, type::none, type_of(L, index)); - } - return success; - } - }; - - template <typename T, typename C> - struct checker<T, type::lightuserdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - bool success = t == type::userdata || t == type::lightuserdata; - if (!success) { - // expected type, actual type - handler(L, index, type::lightuserdata, t); - } - return success; - } - }; - - template <typename C> - struct checker<userdata_value, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - bool success = t == type::userdata; - if (!success) { - // expected type, actual type - handler(L, index, type::userdata, t); - } - return success; - } - }; - - template <typename T, typename C> - struct checker<user<T>, type::userdata, C> : checker<user<T>, type::lightuserdata, C> {}; - - template <typename T, typename C> - struct checker<non_null<T>, type::userdata, C> : checker<T, lua_type_of<T>::value, C> {}; - - template <typename C> - struct checker<lua_CFunction, type::function, C> : stack_detail::basic_check<type::function, lua_iscfunction> {}; - template <typename C> - struct checker<std::remove_pointer_t<lua_CFunction>, type::function, C> : checker<lua_CFunction, type::function, C> {}; - template <typename C> - struct checker<c_closure, type::function, C> : checker<lua_CFunction, type::function, C> {}; - - template <typename T, typename C> - struct checker<T, type::function, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - if (t == type::lua_nil || t == type::none || t == type::function) { - // allow for lua_nil to be returned - return true; - } - if (t != type::userdata && t != type::table) { - handler(L, index, type::function, t); - return false; - } - // Do advanced check for call-style userdata? - static const auto& callkey = name_of(meta_function::call); - if (lua_getmetatable(L, index) == 0) { - // No metatable, no __call key possible - handler(L, index, type::function, t); - return false; - } - if (lua_isnoneornil(L, -1)) { - lua_pop(L, 1); - handler(L, index, type::function, t); - return false; - } - lua_getfield(L, -1, &callkey[0]); - if (lua_isnoneornil(L, -1)) { - lua_pop(L, 2); - handler(L, index, type::function, t); - return false; - } - // has call, is definitely a function - lua_pop(L, 2); - return true; - } - }; - - template <typename T, typename C> - struct checker<T, type::table, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - tracking.use(1); - type t = type_of(L, index); - if (t == type::table) { - return true; - } - if (t != type::userdata) { - handler(L, index, type::function, t); - return false; - } - return true; - } - }; - - template <typename T, typename C> - struct checker<detail::as_value_tag<T>, type::userdata, C> { - template <typename U, typename Handler> - static bool check(types<U>, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { - tracking.use(1); - if (indextype != type::userdata) { - handler(L, index, type::userdata, indextype); - return false; - } - if (meta::any<std::is_same<T, lightuserdata_value>, std::is_same<T, userdata_value>, std::is_same<T, userdata>, std::is_same<T, lightuserdata>>::value) - return true; - if (lua_getmetatable(L, index) == 0) { - return true; - } - int metatableindex = lua_gettop(L); - if (stack_detail::check_metatable<U>(L, metatableindex)) - return true; - if (stack_detail::check_metatable<U*>(L, metatableindex)) - return true; - if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex)) - return true; - bool success = false; - if (detail::has_derived<T>::value) { - auto pn = stack::pop_n(L, 1); - lua_pushstring(L, &detail::base_class_check_key()[0]); - lua_rawget(L, metatableindex); - if (type_of(L, -1) != type::lua_nil) { - void* basecastdata = lua_touserdata(L, -1); - detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata; - success = ic(detail::id_for<T>::value); - } - } - if (!success) { - lua_pop(L, 1); - handler(L, index, type::userdata, indextype); - return false; - } - lua_pop(L, 1); - return true; - } - }; - - template <typename T, typename C> - struct checker<T, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - const type indextype = type_of(L, index); - return checker<detail::as_value_tag<T>, type::userdata, C>{}.check(types<T>(), L, indextype, index, std::forward<Handler>(handler), tracking); - } - }; - - template <typename T, typename C> - struct checker<T*, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - const type indextype = type_of(L, index); - // Allow lua_nil to be transformed to nullptr - if (indextype == type::lua_nil) { - tracking.use(1); - return true; - } - return checker<meta::unqualified_t<T>, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename T> - struct checker<T, type::userdata, std::enable_if_t<is_unique_usertype<T>::value>> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return checker<typename unique_usertype_traits<T>::type, type::userdata>{}.check(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename T, typename C> - struct checker<std::reference_wrapper<T>, type::userdata, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return checker<T, type::userdata, C>{}.check(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename... Args, typename C> - struct checker<std::tuple<Args...>, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack::multi_check<Args...>(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename A, typename B, typename C> - struct checker<std::pair<A, B>, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack::multi_check<A, B>(L, index, std::forward<Handler>(handler), tracking); - } - }; - - template<typename T, typename C> - struct checker<optional<T>, type::poly, C> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&&, record& tracking) { - type t = type_of(L, index); - if (t == type::none) { - tracking.use(0); - return true; - } - if (t == type::lua_nil) { - tracking.use(1); - return true; - } - return stack::check<T>(L, index, no_panic, tracking); - } - }; - } // stack -} // sol - -#endif // SOL_STACK_CHECK_HPP diff --git a/3rdparty/sol2/sol/stack_check_get.hpp b/3rdparty/sol2/sol/stack_check_get.hpp deleted file mode 100644 index 728d7d9a448..00000000000 --- a/3rdparty/sol2/sol/stack_check_get.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_CHECK_GET_HPP -#define SOL_STACK_CHECK_GET_HPP - -#include "stack_core.hpp" -#include "stack_get.hpp" -#include "stack_check.hpp" -#include "optional.hpp" - -namespace sol { - namespace stack { - template <typename T, typename> - struct check_getter { - typedef decltype(stack_detail::unchecked_get<T>(nullptr, 0, std::declval<record&>())) R; - - template <typename Handler> - static optional<R> get(lua_State* L, int index, Handler&& handler, record& tracking) { - if (!check<T>(L, index, std::forward<Handler>(handler))) { - tracking.use(static_cast<int>(!lua_isnone(L, index))); - return nullopt; - } - return stack_detail::unchecked_get<T>(L, index, tracking); - } - }; - - template <typename T> - struct check_getter<optional<T>> { - template <typename Handler> - static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) { - return check_get<T>(L, index, no_panic, tracking); - } - }; - - template <typename T> - struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> { - template <typename Handler> - static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { - int isnum = 0; - lua_Integer value = lua_tointegerx(L, index, &isnum); - if (isnum == 0) { - type t = type_of(L, index); - tracking.use(static_cast<int>(t != type::none)); - handler(L, index, type::number, t); - return nullopt; - } - tracking.use(1); - return static_cast<T>(value); - } - }; - - template <typename T> - struct check_getter<T, std::enable_if_t<std::is_enum<T>::value && !meta::any_same<T, meta_function, type>::value>> { - template <typename Handler> - static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { - int isnum = 0; - lua_Integer value = lua_tointegerx(L, index, &isnum); - if (isnum == 0) { - type t = type_of(L, index); - tracking.use(static_cast<int>(t != type::none)); - handler(L, index, type::number, t); - return nullopt; - } - tracking.use(1); - return static_cast<T>(value); - } - }; - - template <typename T> - struct check_getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { - template <typename Handler> - static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { - int isnum = 0; - lua_Number value = lua_tonumberx(L, index, &isnum); - if (isnum == 0) { - type t = type_of(L, index); - tracking.use(static_cast<int>(t != type::none)); - handler(L, index, type::number, t); - return nullopt; - } - tracking.use(1); - return static_cast<T>(value); - } - }; - - template <typename T> - struct getter<optional<T>> { - static decltype(auto) get(lua_State* L, int index, record& tracking) { - return check_get<T>(L, index, no_panic, tracking); - } - }; - } // stack -} // sol - -#endif // SOL_STACK_CHECK_GET_HPP diff --git a/3rdparty/sol2/sol/stack_core.hpp b/3rdparty/sol2/sol/stack_core.hpp deleted file mode 100644 index 2675e02e50b..00000000000 --- a/3rdparty/sol2/sol/stack_core.hpp +++ /dev/null @@ -1,410 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_CORE_HPP -#define SOL_STACK_CORE_HPP - -#include "types.hpp" -#include "reference.hpp" -#include "stack_reference.hpp" -#include "userdata.hpp" -#include "tuple.hpp" -#include "traits.hpp" -#include "tie.hpp" -#include "stack_guard.hpp" -#include <vector> -#include <string> - -namespace sol { - namespace detail { - struct as_reference_tag {}; - template <typename T> - struct as_pointer_tag {}; - template <typename T> - struct as_value_tag {}; - - using special_destruct_func = void(*)(void*); - - template <typename T, typename Real> - inline void special_destruct(void* memory) { - T** pointerpointer = static_cast<T**>(memory); - special_destruct_func* dx = static_cast<special_destruct_func*>(static_cast<void*>(pointerpointer + 1)); - Real* target = static_cast<Real*>(static_cast<void*>(dx + 1)); - target->~Real(); - } - - template <typename T> - inline int unique_destruct(lua_State* L) { - void* memory = lua_touserdata(L, 1); - T** pointerpointer = static_cast<T**>(memory); - special_destruct_func& dx = *static_cast<special_destruct_func*>(static_cast<void*>(pointerpointer + 1)); - (dx)(memory); - return 0; - } - - template <typename T> - inline int user_alloc_destroy(lua_State* L) { - void* rawdata = lua_touserdata(L, 1); - T* data = static_cast<T*>(rawdata); - std::allocator<T> alloc; - alloc.destroy(data); - return 0; - } - - template <typename T> - inline int usertype_alloc_destroy(lua_State* L) { - void* rawdata = lua_touserdata(L, 1); - T** pdata = static_cast<T**>(rawdata); - T* data = *pdata; - std::allocator<T> alloc{}; - alloc.destroy(data); - return 0; - } - - template <typename T> - void reserve(T&, std::size_t) {} - - template <typename T, typename Al> - void reserve(std::vector<T, Al>& arr, std::size_t hint) { - arr.reserve(hint); - } - - template <typename T, typename Tr, typename Al> - void reserve(std::basic_string<T, Tr, Al>& arr, std::size_t hint) { - arr.reserve(hint); - } - } // detail - - namespace stack { - - template<typename T, bool global = false, bool raw = false, typename = void> - struct field_getter; - template <typename T, bool global = false, bool raw = false, typename = void> - struct probe_field_getter; - template<typename T, bool global = false, bool raw = false, typename = void> - struct field_setter; - template<typename T, typename = void> - struct getter; - template<typename T, typename = void> - struct popper; - template<typename T, typename = void> - struct pusher; - template<typename T, type = lua_type_of<T>::value, typename = void> - struct checker; - template<typename T, typename = void> - struct check_getter; - - struct probe { - bool success; - int levels; - - probe(bool s, int l) : success(s), levels(l) {} - - operator bool() const { return success; }; - }; - - struct record { - int last; - int used; - - record() : last(), used() {} - void use(int count) { - last = count; - used += count; - } - }; - - namespace stack_detail { - template <typename T> - struct strip { - typedef T type; - }; - template <typename T> - struct strip<std::reference_wrapper<T>> { - typedef T& type; - }; - template <typename T> - struct strip<user<T>> { - typedef T& type; - }; - template <typename T> - struct strip<non_null<T>> { - typedef T type; - }; - template <typename T> - using strip_t = typename strip<T>::type; - const bool default_check_arguments = -#ifdef SOL_CHECK_ARGUMENTS - true; -#else - false; -#endif - template<typename T> - inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { - return getter<meta::unqualified_t<T>>{}.get(L, index, tracking); - } - } // stack_detail - - inline bool maybe_indexable(lua_State* L, int index = -1) { - type t = type_of(L, index); - return t == type::userdata || t == type::table; - } - - template<typename T, typename... Args> - inline int push(lua_State* L, T&& t, Args&&... args) { - return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...); - } - - // overload allows to use a pusher of a specific type, but pass in any kind of args - template<typename T, typename Arg, typename... Args, typename = std::enable_if_t<!std::is_same<T, Arg>::value>> - inline int push(lua_State* L, Arg&& arg, Args&&... args) { - return pusher<meta::unqualified_t<T>>{}.push(L, std::forward<Arg>(arg), std::forward<Args>(args)...); - } - - template<typename T, typename... Args> - inline int push_reference(lua_State* L, T&& t, Args&&... args) { - typedef meta::all< - std::is_lvalue_reference<T>, - meta::neg<std::is_const<T>>, - meta::neg<is_lua_primitive<meta::unqualified_t<T>>>, - meta::neg<is_unique_usertype<meta::unqualified_t<T>>> - > use_reference_tag; - return pusher<std::conditional_t<use_reference_tag::value, detail::as_reference_tag, meta::unqualified_t<T>>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...); - } - - inline int multi_push(lua_State*) { - // do nothing - return 0; - } - - template<typename T, typename... Args> - inline int multi_push(lua_State* L, T&& t, Args&&... args) { - int pushcount = push(L, std::forward<T>(t)); - void(sol::detail::swallow{ (pushcount += sol::stack::push(L, std::forward<Args>(args)), 0)... }); - return pushcount; - } - - inline int multi_push_reference(lua_State*) { - // do nothing - return 0; - } - - template<typename T, typename... Args> - inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { - int pushcount = push_reference(L, std::forward<T>(t)); - void(sol::detail::swallow{ (pushcount += sol::stack::push_reference(L, std::forward<Args>(args)), 0)... }); - return pushcount; - } - - template <typename T, typename Handler> - bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - typedef meta::unqualified_t<T> Tu; - checker<Tu> c; - // VC++ has a bad warning here: shut it up - (void)c; - return c.check(L, index, std::forward<Handler>(handler), tracking); - } - - template <typename T, typename Handler> - bool check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check<T>(L, index, std::forward<Handler>(handler), tracking); - } - - template <typename T> - bool check(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { - auto handler = no_panic; - return check<T>(L, index, handler); - } - - template<typename T, typename Handler> - inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { - return check_getter<meta::unqualified_t<T>>{}.get(L, index, std::forward<Handler>(handler), tracking); - } - - template<typename T, typename Handler> - inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check_get<T>(L, index, handler, tracking); - } - - template<typename T> - inline decltype(auto) check_get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { - auto handler = no_panic; - return check_get<T>(L, index, handler); - } - - namespace stack_detail { - -#ifdef SOL_CHECK_ARGUMENTS - template <typename T> - inline auto tagged_get(types<T>, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get<T>(L, index, tracking)) { - auto op = check_get<T>(L, index, type_panic, tracking); - return *std::move(op); - } -#else - template <typename T> - inline decltype(auto) tagged_get(types<T>, lua_State* L, int index, record& tracking) { - return stack_detail::unchecked_get<T>(L, index, tracking); - } -#endif - - template <typename T> - inline decltype(auto) tagged_get(types<optional<T>>, lua_State* L, int index, record& tracking) { - return stack_detail::unchecked_get<optional<T>>(L, index, tracking); - } - - template <bool b> - struct check_types { - template <typename T, typename... Args, typename Handler> - static bool check(types<T, Args...>, lua_State* L, int firstargument, Handler&& handler, record& tracking) { - if (!stack::check<T>(L, firstargument + tracking.used, handler, tracking)) - return false; - return check(types<Args...>(), L, firstargument, std::forward<Handler>(handler), tracking); - } - - template <typename Handler> - static bool check(types<>, lua_State*, int, Handler&&, record&) { - return true; - } - }; - - template <> - struct check_types<false> { - template <typename... Args, typename Handler> - static bool check(types<Args...>, lua_State*, int, Handler&&, record&) { - return true; - } - }; - - } // stack_detail - - template <bool b, typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack_detail::check_types<b>{}.check(types<meta::unqualified_t<Args>...>(), L, index, std::forward<Handler>(handler), tracking); - } - - template <bool b, typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return multi_check<b, Args...>(L, index, std::forward<Handler>(handler), tracking); - } - - template <bool b, typename... Args> - bool multi_check(lua_State* L, int index) { - auto handler = no_panic; - return multi_check<b, Args...>(L, index, handler); - } - - template <typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { - return multi_check<true, Args...>(L, index, std::forward<Handler>(handler), tracking); - } - - template <typename... Args, typename Handler> - bool multi_check(lua_State* L, int index, Handler&& handler) { - return multi_check<true, Args...>(L, index, std::forward<Handler>(handler)); - } - - template <typename... Args> - bool multi_check(lua_State* L, int index) { - return multi_check<true, Args...>(L, index); - } - - template<typename T> - inline decltype(auto) get(lua_State* L, int index, record& tracking) { - return stack_detail::tagged_get(types<T>(), L, index, tracking); - } - - template<typename T> - inline decltype(auto) get(lua_State* L, int index = -lua_size<meta::unqualified_t<T>>::value) { - record tracking{}; - return get<T>(L, index, tracking); - } - - template<typename T> - inline decltype(auto) pop(lua_State* L) { - return popper<meta::unqualified_t<T>>{}.pop(L); - } - - template <bool global = false, bool raw = false, typename Key> - void get_field(lua_State* L, Key&& key) { - field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key)); - } - - template <bool global = false, bool raw = false, typename Key> - void get_field(lua_State* L, Key&& key, int tableindex) { - field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, typename Key> - void raw_get_field(lua_State* L, Key&& key) { - get_field<global, true>(L, std::forward<Key>(key)); - } - - template <bool global = false, typename Key> - void raw_get_field(lua_State* L, Key&& key, int tableindex) { - get_field<global, true>(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, bool raw = false, typename Key> - probe probe_get_field(lua_State* L, Key&& key) { - return probe_field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key)); - } - - template <bool global = false, bool raw = false, typename Key> - probe probe_get_field(lua_State* L, Key&& key, int tableindex) { - return probe_field_getter<meta::unqualified_t<Key>, global, raw>{}.get(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, typename Key> - probe probe_raw_get_field(lua_State* L, Key&& key) { - return probe_get_field<global, true>(L, std::forward<Key>(key)); - } - - template <bool global = false, typename Key> - probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { - return probe_get_field<global, true>(L, std::forward<Key>(key), tableindex); - } - - template <bool global = false, bool raw = false, typename Key, typename Value> - void set_field(lua_State* L, Key&& key, Value&& value) { - field_setter<meta::unqualified_t<Key>, global, raw>{}.set(L, std::forward<Key>(key), std::forward<Value>(value)); - } - - template <bool global = false, bool raw = false, typename Key, typename Value> - void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { - field_setter<meta::unqualified_t<Key>, global, raw>{}.set(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); - } - - template <bool global = false, typename Key, typename Value> - void raw_set_field(lua_State* L, Key&& key, Value&& value) { - set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value)); - } - - template <bool global = false, typename Key, typename Value> - void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { - set_field<global, true>(L, std::forward<Key>(key), std::forward<Value>(value), tableindex); - } - } // stack -} // sol - -#endif // SOL_STACK_CORE_HPP diff --git a/3rdparty/sol2/sol/stack_field.hpp b/3rdparty/sol2/sol/stack_field.hpp deleted file mode 100644 index 48ebe99220d..00000000000 --- a/3rdparty/sol2/sol/stack_field.hpp +++ /dev/null @@ -1,261 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_FIELD_HPP -#define SOL_STACK_FIELD_HPP - -#include "stack_core.hpp" -#include "stack_push.hpp" -#include "stack_get.hpp" -#include "stack_check_get.hpp" - -namespace sol { - namespace stack { - template <typename T, bool, bool, typename> - struct field_getter { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -2) { - push(L, std::forward<Key>(key)); - lua_gettable(L, tableindex); - } - }; - - template <typename T, bool global, typename C> - struct field_getter<T, global, true, C> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -2) { - push(L, std::forward<Key>(key)); - lua_rawget(L, tableindex); - } - }; - - template <bool b, bool raw, typename C> - struct field_getter<metatable_key_t, b, raw, C> { - void get(lua_State* L, metatable_key_t, int tableindex = -1) { - if (lua_getmetatable(L, tableindex) == 0) - push(L, lua_nil); - } - }; - - template <typename T, bool raw> - struct field_getter<T, true, raw, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int = -1) { - lua_getglobal(L, &key[0]); - } - }; - - template <typename T> - struct field_getter<T, false, false, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -1) { - lua_getfield(L, tableindex, &key[0]); - } - }; - -#if SOL_LUA_VERSION >= 503 - template <typename T> - struct field_getter<T, false, false, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -1) { - lua_geti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; -#endif // Lua 5.3.x - -#if SOL_LUA_VERSION >= 502 - template <typename C> - struct field_getter<void*, false, true, C> { - void get(lua_State* L, void* key, int tableindex = -1) { - lua_rawgetp(L, tableindex, key); - } - }; -#endif // Lua 5.3.x - - template <typename T> - struct field_getter<T, false, true, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key> - void get(lua_State* L, Key&& key, int tableindex = -1) { - lua_rawgeti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; - - template <typename... Args, bool b, bool raw, typename C> - struct field_getter<std::tuple<Args...>, b, raw, C> { - template <std::size_t... I, typename Keys> - void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { - get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); - void(detail::swallow{ (get_field<false, raw>(L, detail::forward_get<I>(keys)), 0)... }); - reference saved(L, -1); - lua_pop(L, static_cast<int>(sizeof...(I))); - saved.push(); - } - - template <typename Keys> - void get(lua_State* L, Keys&& keys) { - apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), lua_absindex(L, -1)); - } - - template <typename Keys> - void get(lua_State* L, Keys&& keys, int tableindex) { - apply(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), tableindex); - } - }; - - template <typename A, typename B, bool b, bool raw, typename C> - struct field_getter<std::pair<A, B>, b, raw, C> { - template <typename Keys> - void get(lua_State* L, Keys&& keys, int tableindex) { - get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); - get_field<false, raw>(L, detail::forward_get<1>(keys)); - reference saved(L, -1); - lua_pop(L, static_cast<int>(2)); - saved.push(); - } - - template <typename Keys> - void get(lua_State* L, Keys&& keys) { - get_field<b, raw>(L, detail::forward_get<0>(keys)); - get_field<false, raw>(L, detail::forward_get<1>(keys)); - reference saved(L, -1); - lua_pop(L, static_cast<int>(2)); - saved.push(); - } - }; - - template <typename T, bool, bool, typename> - struct field_setter { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { - push(L, std::forward<Key>(key)); - push(L, std::forward<Value>(value)); - lua_settable(L, tableindex); - } - }; - - template <typename T, bool b, typename C> - struct field_setter<T, b, true, C> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { - push(L, std::forward<Key>(key)); - push(L, std::forward<Value>(value)); - lua_rawset(L, tableindex); - } - }; - - template <bool b, bool raw, typename C> - struct field_setter<metatable_key_t, b, raw, C> { - template <typename Value> - void set(lua_State* L, metatable_key_t, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_setmetatable(L, tableindex); - } - }; - - template <typename T, bool raw> - struct field_setter<T, true, raw, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int = -2) { - push(L, std::forward<Value>(value)); - lua_setglobal(L, &key[0]); - } - }; - - template <typename T> - struct field_setter<T, false, false, std::enable_if_t<meta::is_c_str<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_setfield(L, tableindex, &key[0]); - } - }; - -#if SOL_LUA_VERSION >= 503 - template <typename T> - struct field_setter<T, false, false, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_seti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; -#endif // Lua 5.3.x - - template <typename T> - struct field_setter<T, false, true, std::enable_if_t<std::is_integral<T>::value>> { - template <typename Key, typename Value> - void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_rawseti(L, tableindex, static_cast<lua_Integer>(key)); - } - }; - -#if SOL_LUA_VERSION >= 502 - template <typename C> - struct field_setter<void*, false, true, C> { - template <typename Key, typename Value> - void set(lua_State* L, void* key, Value&& value, int tableindex = -2) { - push(L, std::forward<Value>(value)); - lua_rawsetp(L, tableindex, key); - } - }; -#endif // Lua 5.2.x - - template <typename... Args, bool b, bool raw, typename C> - struct field_setter<std::tuple<Args...>, b, raw, C> { - template <bool g, std::size_t I, typename Key, typename Value> - void apply(std::index_sequence<I>, lua_State* L, Key&& keys, Value&& value, int tableindex) { - I < 1 ? - set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value), tableindex) : - set_field<g, raw>(L, detail::forward_get<I>(keys), std::forward<Value>(value)); - } - - template <bool g, std::size_t I0, std::size_t I1, std::size_t... I, typename Keys, typename Value> - void apply(std::index_sequence<I0, I1, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { - I0 < 1 ? get_field<g, raw>(L, detail::forward_get<I0>(keys), tableindex) : get_field<g, raw>(L, detail::forward_get<I0>(keys), -1); - apply<false>(std::index_sequence<I1, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), -1); - } - - template <bool g, std::size_t I0, std::size_t... I, typename Keys, typename Value> - void top_apply(std::index_sequence<I0, I...>, lua_State* L, Keys&& keys, Value&& value, int tableindex) { - apply<g>(std::index_sequence<I0, I...>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); - lua_pop(L, static_cast<int>(sizeof...(I))); - } - - template <typename Keys, typename Value> - void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { - top_apply<b>(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<Keys>(keys), std::forward<Value>(value), tableindex); - } - }; - - template <typename A, typename B, bool b, bool raw, typename C> - struct field_setter<std::pair<A, B>, b, raw, C> { - template <typename Keys, typename Value> - void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { - get_field<b, raw>(L, detail::forward_get<0>(keys), tableindex); - set_field<false, raw>(L, detail::forward_get<1>(keys), std::forward<Value>(value)); - lua_pop(L, 1); - } - }; - } // stack -} // sol - -#endif // SOL_STACK_FIELD_HPP diff --git a/3rdparty/sol2/sol/stack_get.hpp b/3rdparty/sol2/sol/stack_get.hpp deleted file mode 100644 index a39eec4a997..00000000000 --- a/3rdparty/sol2/sol/stack_get.hpp +++ /dev/null @@ -1,551 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_GET_HPP -#define SOL_STACK_GET_HPP - -#include "stack_core.hpp" -#include "usertype_traits.hpp" -#include "inheritance.hpp" -#include "overload.hpp" -#include "error.hpp" -#include <memory> -#include <functional> -#include <utility> -#ifdef SOL_CODECVT_SUPPORT -#include <codecvt> -#include <locale> -#endif - -namespace sol { - namespace stack { - - template<typename T, typename> - struct getter { - static T& get(lua_State* L, int index, record& tracking) { - return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<std::is_floating_point<T>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tonumber(L, index)); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tointeger(L, index)); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tointeger(L, index)); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<std::is_enum<T>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T>(lua_tointegerx(L, index, nullptr)); - } - }; - - template<typename T> - struct getter<as_table_t<T>, std::enable_if_t<!meta::has_key_value_pair<meta::unqualified_t<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - typedef typename T::value_type V; - tracking.use(1); - - index = lua_absindex(L, index); - T arr; - get_field<false, true>(L, static_cast<lua_Integer>(-1), index); - int isnum; - std::size_t sizehint = static_cast<std::size_t>(lua_tointegerx(L, -1, &isnum)); - if (isnum != 0) { - detail::reserve(arr, sizehint); - } - lua_pop(L, 1); -#if SOL_LUA_VERSION >= 503 - // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 - for (lua_Integer i = 0; ; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { - for (int vi = 0; vi < lua_size<V>::value; ++vi) { - type t = static_cast<type>(lua_geti(L, index, i + vi)); - if (t == type::lua_nil) { - if (i == 0) { - continue; - } - else { - lua_pop(L, (vi + 1)); - return arr; - } - } - } - arr.push_back(stack::get<V>(L, -lua_size<V>::value)); - } -#else - // Zzzz slower but necessary thanks to the lower version API and missing functions qq - for (lua_Integer i = 0; ; i += lua_size<V>::value, lua_pop(L, lua_size<V>::value)) { - for (int vi = 0; vi < lua_size<V>::value; ++vi) { - lua_pushinteger(L, i); - lua_gettable(L, index); - type t = type_of(L, -1); - if (t == type::lua_nil) { - if (i == 0) { - continue; - } - else { - lua_pop(L, (vi + 1)); - return arr; - } - } - } - arr.push_back(stack::get<V>(L, -1)); - } -#endif - return arr; - } - }; - - template<typename T> - struct getter<as_table_t<T>, std::enable_if_t<meta::has_key_value_pair<meta::unqualified_t<T>>::value>> { - static T get(lua_State* L, int index, record& tracking) { - typedef typename T::value_type P; - typedef typename P::first_type K; - typedef typename P::second_type V; - tracking.use(1); - - T associative; - index = lua_absindex(L, index); - lua_pushnil(L); - while (lua_next(L, index) != 0) { - decltype(auto) key = stack::check_get<K>(L, -2); - if (!key) { - lua_pop(L, 1); - continue; - } - associative.emplace(std::forward<decltype(*key)>(*key), stack::get<V>(L, -1)); - lua_pop(L, 1); - } - return associative; - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> { - static T get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return T(L, index); - } - }; - - template<> - struct getter<userdata_value> { - static userdata_value get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return userdata_value(lua_touserdata(L, index)); - } - }; - - template<> - struct getter<lightuserdata_value> { - static lightuserdata_value get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lightuserdata_value(lua_touserdata(L, index)); - } - }; - - template<typename T> - struct getter<light<T>> { - static light<T> get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return light<T>(static_cast<T*>(lua_touserdata(L, index))); - } - }; - - template<typename T> - struct getter<user<T>> { - static T& get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return *static_cast<T*>(lua_touserdata(L, index)); - } - }; - - template<typename T> - struct getter<user<T*>> { - static T* get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return static_cast<T*>(lua_touserdata(L, index)); - } - }; - - template<> - struct getter<type> { - static type get(lua_State *L, int index, record& tracking) { - tracking.use(1); - return static_cast<type>(lua_type(L, index)); - } - }; - - template<> - struct getter<bool> { - static bool get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_toboolean(L, index) != 0; - } - }; - - template<> - struct getter<std::string> { - static std::string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - std::size_t len; - auto str = lua_tolstring(L, index, &len); - return std::string( str, len ); - } - }; - - template <> - struct getter<string_detail::string_shim> { - string_detail::string_shim get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - const char* p = lua_tolstring(L, index, &len); - return string_detail::string_shim(p, len); - } - }; - - template<> - struct getter<const char*> { - static const char* get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_tostring(L, index); - } - }; - - template<> - struct getter<char> { - static char get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - return len > 0 ? str[0] : '\0'; - } - }; - -#ifdef SOL_CODECVT_SUPPORT - template<> - struct getter<std::wstring> { - static std::wstring get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::wstring(); - if (sizeof(wchar_t) == 2) { - static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; - std::wstring r = convert.from_bytes(str, str + len); -#ifdef __MINGW32__ - // Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug - // https://sourceforge.net/p/mingw-w64/bugs/538/ - // http://chat.stackoverflow.com/transcript/message/32271369#32271369 - for (auto& c : r) { - uint8_t* b = reinterpret_cast<uint8_t*>(&c); - std::swap(b[0], b[1]); - } -#endif - return r; - } - static std::wstring_convert<std::codecvt_utf8<wchar_t>> convert; - std::wstring r = convert.from_bytes(str, str + len); - return r; - } - }; - - template<> - struct getter<std::u16string> { - static std::u16string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::u16string(); -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert; - auto intd = convert.from_bytes(str, str + len); - std::u16string r(intd.size(), '\0'); - std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); -#else - static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; - std::u16string r = convert.from_bytes(str, str + len); -#endif // VC++ is a shit - return r; - } - }; - - template<> - struct getter<std::u32string> { - static std::u32string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::u32string(); -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert; - auto intd = convert.from_bytes(str, str + len); - std::u32string r(intd.size(), '\0'); - std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); -#else - static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; - std::u32string r = convert.from_bytes(str, str + len); -#endif // VC++ is a shit - return r; - } - }; - - template<> - struct getter<wchar_t> { - static wchar_t get(lua_State* L, int index, record& tracking) { - auto str = getter<std::wstring>{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : wchar_t(0); - } - }; - - template<> - struct getter<char16_t> { - static char16_t get(lua_State* L, int index, record& tracking) { - auto str = getter<std::u16string>{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : char16_t(0); - } - }; - - template<> - struct getter<char32_t> { - static char32_t get(lua_State* L, int index, record& tracking) { - auto str = getter<std::u32string>{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : char32_t(0); - } - }; -#endif // codecvt header support - - template<> - struct getter<meta_function> { - static meta_function get(lua_State *L, int index, record& tracking) { - tracking.use(1); - const char* name = getter<const char*>{}.get(L, index, tracking); - for (std::size_t i = 0; i < meta_function_names.size(); ++i) - if (meta_function_names[i] == name) - return static_cast<meta_function>(i); - return meta_function::construct; - } - }; - - template<> - struct getter<lua_nil_t> { - static lua_nil_t get(lua_State*, int, record& tracking) { - tracking.use(1); - return lua_nil; - } - }; - - template<> - struct getter<std::nullptr_t> { - static std::nullptr_t get(lua_State*, int, record& tracking) { - tracking.use(1); - return nullptr; - } - }; - - template<> - struct getter<nullopt_t> { - static nullopt_t get(lua_State*, int, record& tracking) { - tracking.use(1); - return nullopt; - } - }; - - template<> - struct getter<this_state> { - static this_state get(lua_State* L, int, record& tracking) { - tracking.use(0); - return this_state{ L }; - } - }; - - template<> - struct getter<lua_CFunction> { - static lua_CFunction get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_tocfunction(L, index); - } - }; - - template<> - struct getter<c_closure> { - static c_closure get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return c_closure(lua_tocfunction(L, index), -1); - } - }; - - template<> - struct getter<error> { - static error get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t sz = 0; - const char* err = lua_tolstring(L, index, &sz); - if (err == nullptr) { - return error(detail::direct_error, ""); - } - return error(detail::direct_error, std::string(err, sz)); - } - }; - - template<> - struct getter<void*> { - static void* get(lua_State* L, int index, record& tracking) { - tracking.use(1); - return lua_touserdata(L, index); - } - }; - - template<typename T> - struct getter<detail::as_value_tag<T>> { - static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { - tracking.use(1); - void** pudata = static_cast<void**>(lua_touserdata(L, index)); - void* udata = *pudata; - return get_no_lua_nil_from(L, udata, index, tracking); - } - - static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) { - if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { - void* basecastdata = lua_touserdata(L, -1); - detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata; - // use the casting function to properly adjust the pointer for the desired T - udata = ic(udata, detail::id_for<T>::value); - lua_pop(L, 1); - } - T* obj = static_cast<T*>(udata); - return obj; - } - - static T& get(lua_State* L, int index, record& tracking) { - return *get_no_lua_nil(L, index, tracking); - } - }; - - template<typename T> - struct getter<detail::as_pointer_tag<T>> { - static T* get(lua_State* L, int index, record& tracking) { - type t = type_of(L, index); - if (t == type::lua_nil) { - tracking.use(1); - return nullptr; - } - return getter<detail::as_value_tag<T>>::get_no_lua_nil(L, index, tracking); - } - }; - - template<typename T> - struct getter<non_null<T*>> { - static T* get(lua_State* L, int index, record& tracking) { - return getter<detail::as_value_tag<T>>::get_no_lua_nil(L, index, tracking); - } - }; - - template<typename T> - struct getter<T&> { - static T& get(lua_State* L, int index, record& tracking) { - return getter<detail::as_value_tag<T>>::get(L, index, tracking); - } - }; - - template<typename T> - struct getter<std::reference_wrapper<T>> { - static T& get(lua_State* L, int index, record& tracking) { - return getter<T&>{}.get(L, index, tracking); - } - }; - - template<typename T> - struct getter<T*> { - static T* get(lua_State* L, int index, record& tracking) { - return getter<detail::as_pointer_tag<T>>::get(L, index, tracking); - } - }; - - template<typename T> - struct getter<T, std::enable_if_t<is_unique_usertype<T>::value>> { - typedef typename unique_usertype_traits<T>::type P; - typedef typename unique_usertype_traits<T>::actual_type Real; - - static Real& get(lua_State* L, int index, record& tracking) { - tracking.use(1); - P** pref = static_cast<P**>(lua_touserdata(L, index)); - detail::special_destruct_func* fx = static_cast<detail::special_destruct_func*>(static_cast<void*>(pref + 1)); - Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1)); - return *mem; - } - }; - - template<typename... Args> - struct getter<std::tuple<Args...>> { - typedef std::tuple<decltype(stack::get<Args>(nullptr, 0))...> R; - - template <typename... TArgs> - static R apply(std::index_sequence<>, lua_State*, int, record&, TArgs&&... args) { - // Fuck you too, VC++ - return R{std::forward<TArgs>(args)...}; - } - - template <std::size_t I, std::size_t... Ix, typename... TArgs> - static R apply(std::index_sequence<I, Ix...>, lua_State* L, int index, record& tracking, TArgs&&... args) { - // Fuck you too, VC++ - typedef std::tuple_element_t<I, std::tuple<Args...>> T; - return apply(std::index_sequence<Ix...>(), L, index, tracking, std::forward<TArgs>(args)..., stack::get<T>(L, index + tracking.used, tracking)); - } - - static R get(lua_State* L, int index, record& tracking) { - return apply(std::make_index_sequence<sizeof...(Args)>(), L, index, tracking); - } - }; - - template<typename A, typename B> - struct getter<std::pair<A, B>> { - static decltype(auto) get(lua_State* L, int index, record& tracking) { - return std::pair<decltype(stack::get<A>(L, index)), decltype(stack::get<B>(L, index))>{stack::get<A>(L, index, tracking), stack::get<B>(L, index + tracking.used, tracking)}; - } - }; - - } // stack -} // sol - -#endif // SOL_STACK_GET_HPP diff --git a/3rdparty/sol2/sol/stack_guard.hpp b/3rdparty/sol2/sol/stack_guard.hpp deleted file mode 100644 index 54e359fecb8..00000000000 --- a/3rdparty/sol2/sol/stack_guard.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_GUARD_HPP -#define SOL_STACK_GUARD_HPP - -#include "compatibility/version.hpp" -#include "error.hpp" -#include <functional> - -namespace sol { - namespace detail { - inline void stack_fail(int, int) { -#ifndef SOL_NO_EXCEPTIONS - throw error(detail::direct_error, "imbalanced stack after operation finish"); -#else - // Lol, what do you want, an error printout? :3c - // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so - // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. -#endif // No Exceptions - } - } // detail - - struct stack_guard { - lua_State* L; - int top; - std::function<void(int, int)> on_mismatch; - - stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {} - stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {} - bool check_stack(int modification = 0) const { - int bottom = lua_gettop(L) + modification; - if (top == bottom) { - return true; - } - on_mismatch(top, bottom); - return false; - } - ~stack_guard() { - check_stack(); - } - }; -} // sol - -#endif // SOL_STACK_GUARD_HPP diff --git a/3rdparty/sol2/sol/stack_pop.hpp b/3rdparty/sol2/sol/stack_pop.hpp deleted file mode 100644 index f69701311e5..00000000000 --- a/3rdparty/sol2/sol/stack_pop.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_POP_HPP -#define SOL_STACK_POP_HPP - -#include "stack_core.hpp" -#include "stack_get.hpp" -#include <utility> -#include <tuple> - -namespace sol { - namespace stack { - template <typename T, typename> - struct popper { - inline static decltype(auto) pop(lua_State* L) { - record tracking{}; - decltype(auto) r = get<T>(L, -lua_size<T>::value, tracking); - lua_pop(L, tracking.used); - return r; - } - }; - - template <typename T> - struct popper<T, std::enable_if_t<std::is_base_of<stack_reference, meta::unqualified_t<T>>::value>> { - static_assert(meta::neg<std::is_base_of<stack_reference, meta::unqualified_t<T>>>::value, "You cannot pop something that derives from stack_reference: it will not remain on the stack and thusly will go out of scope!"); - }; - } // stack -} // sol - -#endif // SOL_STACK_POP_HPP diff --git a/3rdparty/sol2/sol/stack_probe.hpp b/3rdparty/sol2/sol/stack_probe.hpp deleted file mode 100644 index 62185f4f34b..00000000000 --- a/3rdparty/sol2/sol/stack_probe.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_PROBE_HPP -#define SOL_STACK_PROBE_HPP - -#include "stack_core.hpp" -#include "stack_field.hpp" -#include "stack_check.hpp" - -namespace sol { - namespace stack { - template <typename T, bool b, bool raw, typename> - struct probe_field_getter { - template <typename Key> - probe get(lua_State* L, Key&& key, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); - } - get_field<b, raw>(L, std::forward<Key>(key), tableindex); - return probe(!check<lua_nil_t>(L), 1); - } - }; - - template <typename A, typename B, bool b, bool raw, typename C> - struct probe_field_getter<std::pair<A, B>, b, raw, C> { - template <typename Keys> - probe get(lua_State* L, Keys&& keys, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); - } - get_field<b, raw>(L, std::get<0>(keys), tableindex); - if (!maybe_indexable(L)) { - return probe(false, 1); - } - get_field<false, raw>(L, std::get<1>(keys), tableindex); - return probe(!check<lua_nil_t>(L), 2); - } - }; - - template <typename... Args, bool b, bool raw, typename C> - struct probe_field_getter<std::tuple<Args...>, b, raw, C> { - template <std::size_t I, typename Keys> - probe apply(std::index_sequence<I>, int sofar, lua_State* L, Keys&& keys, int tableindex) { - get_field < I < 1 && b, raw>(L, std::get<I>(keys), tableindex); - return probe(!check<lua_nil_t>(L), sofar); - } - - template <std::size_t I, std::size_t I1, std::size_t... In, typename Keys> - probe apply(std::index_sequence<I, I1, In...>, int sofar, lua_State* L, Keys&& keys, int tableindex) { - get_field < I < 1 && b, raw>(L, std::get<I>(keys), tableindex); - if (!maybe_indexable(L)) { - return probe(false, sofar); - } - return apply(std::index_sequence<I1, In...>(), sofar + 1, L, std::forward<Keys>(keys), -1); - } - - template <typename Keys> - probe get(lua_State* L, Keys&& keys, int tableindex = -2) { - if (!b && !maybe_indexable(L, tableindex)) { - return probe(false, 0); - } - return apply(std::index_sequence_for<Args...>(), 1, L, std::forward<Keys>(keys), tableindex); - } - }; - } // stack -} // sol - -#endif // SOL_STACK_PROBE_HPP
\ No newline at end of file diff --git a/3rdparty/sol2/sol/stack_proxy.hpp b/3rdparty/sol2/sol/stack_proxy.hpp deleted file mode 100644 index 487e4b29772..00000000000 --- a/3rdparty/sol2/sol/stack_proxy.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_PROXY_HPP -#define SOL_STACK_PROXY_HPP - -#include "stack.hpp" -#include "function.hpp" -#include "protected_function.hpp" -#include "proxy_base.hpp" - -namespace sol { - struct stack_proxy : public proxy_base<stack_proxy> { - private: - lua_State* L; - int index; - - public: - stack_proxy() : L(nullptr), index(0) {} - stack_proxy(lua_State* L, int index) : L(L), index(index) {} - - template<typename T> - decltype(auto) get() const { - return stack::get<T>(L, stack_index()); - } - - int push() const { - return push(L); - } - - int push(lua_State* Ls) const { - lua_pushvalue(Ls, index); - return 1; - } - - lua_State* lua_state() const { return L; } - int stack_index() const { return index; } - - template<typename... Ret, typename... Args> - decltype(auto) call(Args&&... args) { - return get<function>().template call<Ret...>(std::forward<Args>(args)...); - } - - template<typename... Args> - decltype(auto) operator()(Args&&... args) { - return call<>(std::forward<Args>(args)...); - } - }; - - namespace stack { - template <> - struct getter<stack_proxy> { - static stack_proxy get(lua_State* L, int index = -1) { - return stack_proxy(L, index); - } - }; - - template <> - struct pusher<stack_proxy> { - static int push(lua_State*, const stack_proxy& ref) { - return ref.push(); - } - }; - } // stack - - namespace detail { - template <> - struct is_speshul<function_result> : std::true_type {}; - template <> - struct is_speshul<protected_function_result> : std::true_type {}; - - template <std::size_t I, typename... Args, typename T> - stack_proxy get(types<Args...>, index_value<0>, index_value<I>, const T& fr) { - return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); - } - - template <std::size_t I, std::size_t N, typename Arg, typename... Args, typename T, meta::enable<meta::boolean<(N > 0)>> = meta::enabler> - stack_proxy get(types<Arg, Args...>, index_value<N>, index_value<I>, const T& fr) { - return get(types<Args...>(), index_value<N - 1>(), index_value<I + lua_size<Arg>::value>(), fr); - } - } - - template <> - struct tie_size<function_result> : std::integral_constant<std::size_t, SIZE_MAX> {}; - - template <std::size_t I> - stack_proxy get(const function_result& fr) { - return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); - } - - template <std::size_t I, typename... Args> - stack_proxy get(types<Args...> t, const function_result& fr) { - return detail::get(t, index_value<I>(), index_value<0>(), fr); - } - - template <> - struct tie_size<protected_function_result> : std::integral_constant<std::size_t, SIZE_MAX> {}; - - template <std::size_t I> - stack_proxy get(const protected_function_result& fr) { - return stack_proxy(fr.lua_state(), static_cast<int>(fr.stack_index() + I)); - } - - template <std::size_t I, typename... Args> - stack_proxy get(types<Args...> t, const protected_function_result& fr) { - return detail::get(t, index_value<I>(), index_value<0>(), fr); - } -} // sol - -#endif // SOL_STACK_PROXY_HPP diff --git a/3rdparty/sol2/sol/stack_push.hpp b/3rdparty/sol2/sol/stack_push.hpp deleted file mode 100644 index 9a839107fde..00000000000 --- a/3rdparty/sol2/sol/stack_push.hpp +++ /dev/null @@ -1,694 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_PUSH_HPP -#define SOL_STACK_PUSH_HPP - -#include "stack_core.hpp" -#include "raii.hpp" -#include "optional.hpp" -#include <memory> -#ifdef SOL_CODECVT_SUPPORT -#include <codecvt> -#include <locale> -#endif - -namespace sol { - namespace stack { - template <typename T> - struct pusher<detail::as_value_tag<T>> { - template <typename F, typename... Args> - static int push_fx(lua_State* L, F&& f, Args&&... args) { - // Basically, we store all user-data like this: - // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new - // data in the first sizeof(T*) bytes, and then however many bytes it takes to - // do the actual object. Things that are std::ref or plain T* are stored as - // just the sizeof(T*), and nothing else. - T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - T*& referencereference = *pointerpointer; - T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1); - referencereference = allocationtarget; - std::allocator<T> alloc{}; - alloc.construct(allocationtarget, std::forward<Args>(args)...); - f(); - return 1; - } - - template <typename K, typename... Args> - static int push_keyed(lua_State* L, K&& k, Args&&... args) { - return push_fx(L, [&L, &k]() { - luaL_newmetatable(L, &k[0]); - lua_setmetatable(L, -2); - }, std::forward<Args>(args)...); - } - - template <typename... Args> - static int push(lua_State* L, Args&&... args) { - return push_keyed(L, usertype_traits<T>::metatable(), std::forward<Args>(args)...); - } - }; - - template <typename T> - struct pusher<detail::as_pointer_tag<T>> { - template <typename F> - static int push_fx(lua_State* L, F&& f, T* obj) { - if (obj == nullptr) - return stack::push(L, lua_nil); - T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*))); - *pref = obj; - f(); - return 1; - } - - template <typename K> - static int push_keyed(lua_State* L, K&& k, T* obj) { - return push_fx(L, [&L, &k]() { - luaL_newmetatable(L, &k[0]); - lua_setmetatable(L, -2); - }, obj); - } - - static int push(lua_State* L, T* obj) { - return push_keyed(L, usertype_traits<meta::unqualified_t<T>*>::metatable(), obj); - } - }; - - template <> - struct pusher<detail::as_reference_tag> { - template <typename T> - static int push(lua_State* L, T&& obj) { - return stack::push(L, detail::ptr(obj)); - } - }; - - template<typename T, typename> - struct pusher { - template <typename... Args> - static int push(lua_State* L, Args&&... args) { - return pusher<detail::as_value_tag<T>>{}.push(L, std::forward<Args>(args)...); - } - }; - - template<typename T> - struct pusher<T*, meta::disable_if_t<meta::all<is_container<meta::unqualified_t<T>>, meta::neg<meta::any<std::is_base_of<reference, meta::unqualified_t<T>>, std::is_base_of<stack_reference, meta::unqualified_t<T>>>>>::value>> { - template <typename... Args> - static int push(lua_State* L, Args&&... args) { - return pusher<detail::as_pointer_tag<T>>{}.push(L, std::forward<Args>(args)...); - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<is_unique_usertype<T>::value>> { - typedef typename unique_usertype_traits<T>::type P; - typedef typename unique_usertype_traits<T>::actual_type Real; - - template <typename Arg, meta::enable<std::is_base_of<Real, meta::unqualified_t<Arg>>> = meta::enabler> - static int push(lua_State* L, Arg&& arg) { - if (unique_usertype_traits<T>::is_null(arg)) - return stack::push(L, lua_nil); - return push_deep(L, std::forward<Arg>(arg)); - } - - template <typename Arg0, typename Arg1, typename... Args> - static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) { - return push_deep(L, std::forward<Arg0>(arg0), std::forward<Arg1>(arg1), std::forward<Args>(args)...); - } - - template <typename... Args> - static int push_deep(lua_State* L, Args&&... args) { - P** pref = static_cast<P**>(lua_newuserdata(L, sizeof(P*) + sizeof(detail::special_destruct_func) + sizeof(Real))); - detail::special_destruct_func* fx = static_cast<detail::special_destruct_func*>(static_cast<void*>(pref + 1)); - Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1)); - *fx = detail::special_destruct<P, Real>; - detail::default_construct::construct(mem, std::forward<Args>(args)...); - *pref = unique_usertype_traits<T>::get(*mem); - if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<P>>::metatable()[0]) == 1) { - set_field(L, "__gc", detail::unique_destruct<P>); - } - lua_setmetatable(L, -2); - return 1; - } - }; - - template<typename T> - struct pusher<std::reference_wrapper<T>> { - static int push(lua_State* L, const std::reference_wrapper<T>& t) { - return stack::push(L, std::addressof(detail::deref(t.get()))); - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<std::is_floating_point<T>::value>> { - static int push(lua_State* L, const T& value) { - lua_pushnumber(L, value); - return 1; - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { - static int push(lua_State* L, const T& value) { - lua_pushinteger(L, static_cast<lua_Integer>(value)); - return 1; - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<std::is_enum<T>::value>> { - static int push(lua_State* L, const T& value) { - if (std::is_same<char, T>::value) { - return stack::push(L, static_cast<int>(value)); - } - return stack::push(L, static_cast<std::underlying_type_t<T>>(value)); - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { - static int push(lua_State* L, const T& value) { - lua_pushinteger(L, static_cast<lua_Integer>(value)); - return 1; - } - }; - - template<typename T> - struct pusher<as_table_t<T>, std::enable_if_t<!meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>::value>> { - static int push(lua_State* L, const as_table_t<T>& tablecont) { - auto& cont = detail::deref(detail::unwrap(tablecont.source)); - lua_createtable(L, static_cast<int>(cont.size()), 0); - int tableindex = lua_gettop(L); - std::size_t index = 1; - for (const auto& i : cont) { -#if SOL_LUA_VERSION >= 503 - int p = stack::push(L, i); - for (int pi = 0; pi < p; ++pi) { - lua_seti(L, tableindex, static_cast<lua_Integer>(index++)); - } -#else - lua_pushinteger(L, static_cast<lua_Integer>(index)); - int p = stack::push(L, i); - if (p == 1) { - ++index; - lua_settable(L, tableindex); - } - else { - int firstindex = tableindex + 1 + 1; - for (int pi = 0; pi < p; ++pi) { - stack::push(L, index); - lua_pushvalue(L, firstindex); - lua_settable(L, tableindex); - ++index; - ++firstindex; - } - lua_pop(L, 1 + p); - } -#endif - } - // TODO: figure out a better way to do this...? - //set_field(L, -1, cont.size()); - return 1; - } - }; - - template<typename T> - struct pusher<as_table_t<T>, std::enable_if_t<meta::has_key_value_pair<meta::unqualified_t<std::remove_pointer_t<T>>>::value>> { - static int push(lua_State* L, const as_table_t<T>& tablecont) { - auto& cont = detail::deref(detail::unwrap(tablecont.source)); - lua_createtable(L, static_cast<int>(cont.size()), 0); - int tableindex = lua_gettop(L); - for (const auto& pair : cont) { - set_field(L, pair.first, pair.second, tableindex); - } - return 1; - } - }; - - template<typename T> - struct pusher<T, std::enable_if_t<std::is_base_of<reference, T>::value || std::is_base_of<stack_reference, T>::value>> { - static int push(lua_State* L, const T& ref) { - return ref.push(L); - } - - static int push(lua_State* L, T&& ref) { - return ref.push(L); - } - }; - - template<> - struct pusher<bool> { - static int push(lua_State* L, bool b) { - lua_pushboolean(L, b); - return 1; - } - }; - - template<> - struct pusher<lua_nil_t> { - static int push(lua_State* L, lua_nil_t) { - lua_pushnil(L); - return 1; - } - }; - - template<> - struct pusher<metatable_key_t> { - static int push(lua_State* L, metatable_key_t) { - lua_pushlstring(L, "__mt", 4); - return 1; - } - }; - - template<> - struct pusher<std::remove_pointer_t<lua_CFunction>> { - static int push(lua_State* L, lua_CFunction func, int n = 0) { - lua_pushcclosure(L, func, n); - return 1; - } - }; - - template<> - struct pusher<lua_CFunction> { - static int push(lua_State* L, lua_CFunction func, int n = 0) { - lua_pushcclosure(L, func, n); - return 1; - } - }; - - template<> - struct pusher<c_closure> { - static int push(lua_State* L, c_closure cc) { - lua_pushcclosure(L, cc.c_function, cc.upvalues); - return 1; - } - }; - - template<typename Arg, typename... Args> - struct pusher<closure<Arg, Args...>> { - template <std::size_t... I, typename T> - static int push(std::index_sequence<I...>, lua_State* L, T&& c) { - int pushcount = multi_push(L, detail::forward_get<I>(c.upvalues)...); - return stack::push(L, c_closure(c.c_function, pushcount)); - } - - template <typename T> - static int push(lua_State* L, T&& c) { - return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward<T>(c)); - } - }; - - template<> - struct pusher<void*> { - static int push(lua_State* L, void* userdata) { - lua_pushlightuserdata(L, userdata); - return 1; - } - }; - - template<> - struct pusher<lightuserdata_value> { - static int push(lua_State* L, lightuserdata_value userdata) { - lua_pushlightuserdata(L, userdata); - return 1; - } - }; - - template<typename T> - struct pusher<light<T>> { - static int push(lua_State* L, light<T> l) { - lua_pushlightuserdata(L, static_cast<void*>(l.value)); - return 1; - } - }; - - template<typename T> - struct pusher<user<T>> { - template <bool with_meta = true, typename Key, typename... Args> - static int push_with(lua_State* L, Key&& name, Args&&... args) { - // A dumb pusher - void* rawdata = lua_newuserdata(L, sizeof(T)); - T* data = static_cast<T*>(rawdata); - std::allocator<T> alloc; - alloc.construct(data, std::forward<Args>(args)...); - if (with_meta) { - lua_CFunction cdel = detail::user_alloc_destroy<T>; - // Make sure we have a plain GC set for this data - if (luaL_newmetatable(L, name) != 0) { - lua_pushcclosure(L, cdel, 0); - lua_setfield(L, -2, "__gc"); - } - lua_setmetatable(L, -2); - } - return 1; - } - - template <typename Arg, typename... Args, meta::disable<meta::any_same<meta::unqualified_t<Arg>, no_metatable_t, metatable_key_t>> = meta::enabler> - static int push(lua_State* L, Arg&& arg, Args&&... args) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with(L, name, std::forward<Arg>(arg), std::forward<Args>(args)...); - } - - template <typename... Args> - static int push(lua_State* L, no_metatable_t, Args&&... args) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with<false>(L, name, std::forward<Args>(args)...); - } - - template <typename Key, typename... Args> - static int push(lua_State* L, metatable_key_t, Key&& key, Args&&... args) { - const auto name = &key[0]; - return push_with<true>(L, name, std::forward<Args>(args)...); - } - - static int push(lua_State* L, const user<T>& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with(L, name, u.value); - } - - static int push(lua_State* L, user<T>&& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with(L, name, std::move(u.value)); - } - - static int push(lua_State* L, no_metatable_t, const user<T>& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with<false>(L, name, u.value); - } - - static int push(lua_State* L, no_metatable_t, user<T>&& u) { - const auto name = &usertype_traits<meta::unqualified_t<T>>::user_gc_metatable()[0]; - return push_with<false>(L, name, std::move(u.value)); - } - }; - - template<> - struct pusher<userdata_value> { - static int push(lua_State* L, userdata_value data) { - void** ud = static_cast<void**>(lua_newuserdata(L, sizeof(void*))); - *ud = data.value; - return 1; - } - }; - - template<> - struct pusher<const char*> { - static int push_sized(lua_State* L, const char* str, std::size_t len) { - lua_pushlstring(L, str, len); - return 1; - } - - static int push(lua_State* L, const char* str) { - if (str == nullptr) - return stack::push(L, lua_nil); - return push_sized(L, str, std::char_traits<char>::length(str)); - } - - static int push(lua_State* L, const char* strb, const char* stre) { - return push_sized(L, strb, stre - strb); - } - - static int push(lua_State* L, const char* str, std::size_t len) { - return push_sized(L, str, len); - } - }; - - template<size_t N> - struct pusher<char[N]> { - static int push(lua_State* L, const char(&str)[N]) { - lua_pushlstring(L, str, N - 1); - return 1; - } - - static int push(lua_State* L, const char(&str)[N], std::size_t sz) { - lua_pushlstring(L, str, sz); - return 1; - } - }; - - template <> - struct pusher<char> { - static int push(lua_State* L, char c) { - const char str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template<> - struct pusher<std::string> { - static int push(lua_State* L, const std::string& str) { - lua_pushlstring(L, str.c_str(), str.size()); - return 1; - } - - static int push(lua_State* L, const std::string& str, std::size_t sz) { - lua_pushlstring(L, str.c_str(), sz); - return 1; - } - }; - - template<> - struct pusher<meta_function> { - static int push(lua_State* L, meta_function m) { - const std::string& str = name_of(m); - lua_pushlstring(L, str.c_str(), str.size()); - return 1; - } - }; - -#ifdef SOL_CODECVT_SUPPORT - template<> - struct pusher<const wchar_t*> { - static int push(lua_State* L, const wchar_t* wstr) { - return push(L, wstr, std::char_traits<wchar_t>::length(wstr)); - } - - static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { - return push(L, wstr, wstr + sz); - } - - static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { - if (sizeof(wchar_t) == 2) { - static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert; - std::string u8str = convert.to_bytes(strb, stre); - return stack::push(L, u8str); - } - static std::wstring_convert<std::codecvt_utf8<wchar_t>> convert; - std::string u8str = convert.to_bytes(strb, stre); - return stack::push(L, u8str); - } - }; - - template<> - struct pusher<const char16_t*> { - static int push(lua_State* L, const char16_t* u16str) { - return push(L, u16str, std::char_traits<char16_t>::length(u16str)); - } - - static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { - return push(L, u16str, u16str + sz); - } - - static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert; - std::string u8str = convert.to_bytes(reinterpret_cast<const int16_t*>(strb), reinterpret_cast<const int16_t*>(stre)); -#else - static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; - std::string u8str = convert.to_bytes(strb, stre); -#endif // VC++ is a shit - return stack::push(L, u8str); - } - }; - - template<> - struct pusher<const char32_t*> { - static int push(lua_State* L, const char32_t* u32str) { - return push(L, u32str, u32str + std::char_traits<char32_t>::length(u32str)); - } - - static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { - return push(L, u32str, u32str + sz); - } - - static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { -#ifdef _MSC_VER - static std::wstring_convert<std::codecvt_utf8<int32_t>, int32_t> convert; - std::string u8str = convert.to_bytes(reinterpret_cast<const int32_t*>(strb), reinterpret_cast<const int32_t*>(stre)); -#else - static std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; - std::string u8str = convert.to_bytes(strb, stre); -#endif // VC++ is a shit - return stack::push(L, u8str); - } - }; - - template<size_t N> - struct pusher<wchar_t[N]> { - static int push(lua_State* L, const wchar_t(&str)[N]) { - return push(L, str, N - 1); - } - - static int push(lua_State* L, const wchar_t(&str)[N], std::size_t sz) { - return stack::push<const wchar_t*>(L, str, str + sz); - } - }; - - template<size_t N> - struct pusher<char16_t[N]> { - static int push(lua_State* L, const char16_t(&str)[N]) { - return push(L, str, N - 1); - } - - static int push(lua_State* L, const char16_t(&str)[N], std::size_t sz) { - return stack::push<const char16_t*>(L, str, str + sz); - } - }; - - template<size_t N> - struct pusher<char32_t[N]> { - static int push(lua_State* L, const char32_t(&str)[N]) { - return push(L, str, N - 1); - } - - static int push(lua_State* L, const char32_t(&str)[N], std::size_t sz) { - return stack::push<const char32_t*>(L, str, str + sz); - } - }; - - template <> - struct pusher<wchar_t> { - static int push(lua_State* L, wchar_t c) { - const wchar_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template <> - struct pusher<char16_t> { - static int push(lua_State* L, char16_t c) { - const char16_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template <> - struct pusher<char32_t> { - static int push(lua_State* L, char32_t c) { - const char32_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); - } - }; - - template<> - struct pusher<std::wstring> { - static int push(lua_State* L, const std::wstring& wstr) { - return push(L, wstr.data(), wstr.size()); - } - - static int push(lua_State* L, const std::wstring& wstr, std::size_t sz) { - return stack::push(L, wstr.data(), wstr.data() + sz); - } - }; - - template<> - struct pusher<std::u16string> { - static int push(lua_State* L, const std::u16string& u16str) { - return push(L, u16str, u16str.size()); - } - - static int push(lua_State* L, const std::u16string& u16str, std::size_t sz) { - return stack::push(L, u16str.data(), u16str.data() + sz); - } - }; - - template<> - struct pusher<std::u32string> { - static int push(lua_State* L, const std::u32string& u32str) { - return push(L, u32str, u32str.size()); - } - - static int push(lua_State* L, const std::u32string& u32str, std::size_t sz) { - return stack::push(L, u32str.data(), u32str.data() + sz); - } - }; -#endif // codecvt Header Support - - template<typename... Args> - struct pusher<std::tuple<Args...>> { - template <std::size_t... I, typename T> - static int push(std::index_sequence<I...>, lua_State* L, T&& t) { - int pushcount = 0; - (void)detail::swallow{ 0, (pushcount += stack::push(L, - detail::forward_get<I>(t) - ), 0)... }; - return pushcount; - } - - template <typename T> - static int push(lua_State* L, T&& t) { - return push(std::index_sequence_for<Args...>(), L, std::forward<T>(t)); - } - }; - - template<typename A, typename B> - struct pusher<std::pair<A, B>> { - template <typename T> - static int push(lua_State* L, T&& t) { - int pushcount = stack::push(L, detail::forward_get<0>(t)); - pushcount += stack::push(L, detail::forward_get<1>(t)); - return pushcount; - } - }; - - template<typename O> - struct pusher<optional<O>> { - template <typename T> - static int push(lua_State* L, T&& t) { - if (t == nullopt) { - return stack::push(L, nullopt); - } - return stack::push(L, t.value()); - } - }; - - template<> - struct pusher<nullopt_t> { - static int push(lua_State* L, nullopt_t) { - return stack::push(L, lua_nil); - } - }; - - template<> - struct pusher<std::nullptr_t> { - static int push(lua_State* L, std::nullptr_t) { - return stack::push(L, lua_nil); - } - }; - - template<> - struct pusher<this_state> { - static int push(lua_State*, const this_state&) { - return 0; - } - }; - } // stack -} // sol - -#endif // SOL_STACK_PUSH_HPP diff --git a/3rdparty/sol2/sol/stack_reference.hpp b/3rdparty/sol2/sol/stack_reference.hpp deleted file mode 100644 index 561690664c3..00000000000 --- a/3rdparty/sol2/sol/stack_reference.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STACK_REFERENCE_HPP -#define SOL_STACK_REFERENCE_HPP - -namespace sol { - class stack_reference { - private: - lua_State* L = nullptr; - int index = 0; - - protected: - int registry_index() const noexcept { - return LUA_NOREF; - } - - public: - stack_reference() noexcept = default; - stack_reference(lua_nil_t) noexcept : stack_reference() {}; - stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {} - stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {} - stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {} - stack_reference(lua_State* L, ref_index i) noexcept = delete; - stack_reference(stack_reference&& o) noexcept = default; - stack_reference& operator=(stack_reference&&) noexcept = default; - stack_reference(const stack_reference&) noexcept = default; - stack_reference& operator=(const stack_reference&) noexcept = default; - - int push() const noexcept { - return push(lua_state()); - } - - int push(lua_State* Ls) const noexcept { - lua_pushvalue(lua_state(), index); - if (Ls != lua_state()) { - lua_xmove(lua_state(), Ls, 1); - } - return 1; - } - - void pop() const noexcept { - pop(lua_state()); - } - - void pop(lua_State* Ls, int n = 1) const noexcept { - lua_pop(Ls, n); - } - - int stack_index() const noexcept { - return index; - } - - type get_type() const noexcept { - int result = lua_type(L, index); - return static_cast<type>(result); - } - - lua_State* lua_state() const noexcept { - return L; - } - - bool valid() const noexcept { - type t = get_type(); - return t != type::lua_nil && t != type::none; - } - }; - - inline bool operator== (const stack_reference& l, const stack_reference& r) { - return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0; - } - - inline bool operator!= (const stack_reference& l, const stack_reference& r) { - return !operator==(l, r); - } -} // sol - -#endif // SOL_STACK_REFERENCE_HPP diff --git a/3rdparty/sol2/sol/state.hpp b/3rdparty/sol2/sol/state.hpp deleted file mode 100644 index 97bbc260dc6..00000000000 --- a/3rdparty/sol2/sol/state.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STATE_HPP -#define SOL_STATE_HPP - -#include "state_view.hpp" - -namespace sol { - inline int default_at_panic(lua_State* L) { -#ifdef SOL_NO_EXCEPTIONS - (void)L; - return -1; -#else - const char* message = lua_tostring(L, -1); - if (message) { - std::string err = message; - lua_pop(L, 1); - throw error(err); - } - throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic")); -#endif - } - - inline int default_error_handler(lua_State*L) { - using namespace sol; - std::string msg = "An unknown error has triggered the default error handler"; - optional<string_detail::string_shim> maybetopmsg = stack::check_get<string_detail::string_shim>(L, 1); - if (maybetopmsg) { - const string_detail::string_shim& topmsg = maybetopmsg.value(); - msg.assign(topmsg.c_str(), topmsg.size()); - } - luaL_traceback(L, L, msg.c_str(), 1); - optional<string_detail::string_shim> maybetraceback = stack::check_get<string_detail::string_shim>(L, -1); - if (maybetraceback) { - const string_detail::string_shim& traceback = maybetraceback.value(); - msg.assign(traceback.c_str(), traceback.size()); - } - return stack::push(L, msg); - } - - - class state : private std::unique_ptr<lua_State, void(*)(lua_State*)>, public state_view { - private: - typedef std::unique_ptr<lua_State, void(*)(lua_State*)> unique_base; - public: - state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), - state_view(unique_base::get()) { - set_panic(panic); - stack::luajit_exception_handler(unique_base::get()); - } - - state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close), - state_view(unique_base::get()) { - set_panic(panic); - sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler)); - stack::luajit_exception_handler(unique_base::get()); - } - - state(const state&) = delete; - state(state&&) = default; - state& operator=(const state&) = delete; - state& operator=(state&&) = default; - - using state_view::get; - - ~state() { - auto& handler = protected_function::get_default_handler(); - if (handler.lua_state() == this->lua_state()) { - protected_function::set_default_handler(reference()); - } - } - }; -} // sol - -#endif // SOL_STATE_HPP diff --git a/3rdparty/sol2/sol/state_view.hpp b/3rdparty/sol2/sol/state_view.hpp deleted file mode 100644 index 14032d65ac5..00000000000 --- a/3rdparty/sol2/sol/state_view.hpp +++ /dev/null @@ -1,491 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STATE_VIEW_HPP -#define SOL_STATE_VIEW_HPP - -#include "error.hpp" -#include "table.hpp" -#include "load_result.hpp" -#include <memory> - -namespace sol { - enum class lib : char { - base, - package, - coroutine, - string, - os, - math, - table, - debug, - bit32, - io, - ffi, - jit, - utf8, - count - }; - - inline std::size_t total_memory_used(lua_State* L) { - std::size_t kb = lua_gc(L, LUA_GCCOUNT, 0); - kb *= 1024; - kb += lua_gc(L, LUA_GCCOUNTB, 0); - return kb; - } - - class state_view { - private: - lua_State* L; - table reg; - global_table global; - - optional<object> is_loaded_package(const std::string& key) { - auto loaded = reg.traverse_get<optional<object>>("_LOADED", key); - bool is53mod = loaded && !(loaded->is<bool>() && !loaded->as<bool>()); - if (is53mod) - return loaded; -#if SOL_LUA_VERSION <= 501 - auto loaded51 = global.traverse_get<optional<object>>("package", "loaded", key); - bool is51mod = loaded51 && !(loaded51->is<bool>() && !loaded51->as<bool>()); - if (is51mod) - return loaded51; -#endif - return nullopt; - } - - template <typename T> - void ensure_package(const std::string& key, T&& sr) { -#if SOL_LUA_VERSION <= 501 - auto pkg = global["package"]; - if (!pkg.valid()) { - pkg = create_table_with("loaded", create_table_with(key, sr)); - } - else { - auto ld = pkg["loaded"]; - if (!ld.valid()) { - ld = create_table_with(key, sr); - } - else { - ld[key] = sr; - } - } -#endif - auto loaded = reg["_LOADED"]; - if (!loaded.valid()) { - loaded = create_table_with(key, sr); - } - else { - loaded[key] = sr; - } - } - - template <typename Fx> - object require_core(const std::string& key, Fx&& action, bool create_global = true) { - optional<object> loaded = is_loaded_package(key); - if (loaded && loaded->valid()) - return std::move(*loaded); - action(); - auto sr = stack::get<stack_reference>(L); - if (create_global) - set(key, sr); - ensure_package(key, sr); - return stack::pop<object>(L); - } - - public: - typedef global_table::iterator iterator; - typedef global_table::const_iterator const_iterator; - - state_view(lua_State* Ls) : - L(Ls), - reg(Ls, LUA_REGISTRYINDEX), - global(Ls, detail::global_) { - - } - - state_view(this_state Ls) : state_view(Ls.L){ - - } - - lua_State* lua_state() const { - return L; - } - - template<typename... Args> - void open_libraries(Args&&... args) { - static_assert(meta::all_same<lib, Args...>::value, "all types must be libraries"); - if (sizeof...(args) == 0) { - luaL_openlibs(L); - return; - } - - lib libraries[1 + sizeof...(args)] = { lib::count, std::forward<Args>(args)... }; - - for (auto&& library : libraries) { - switch (library) { -#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) - case lib::coroutine: -#endif // luajit opens coroutine base stuff - case lib::base: - luaL_requiref(L, "base", luaopen_base, 1); - lua_pop(L, 1); - break; - case lib::package: - luaL_requiref(L, "package", luaopen_package, 1); - lua_pop(L, 1); - break; -#if !defined(SOL_LUAJIT) - case lib::coroutine: -#if SOL_LUA_VERSION > 501 - luaL_requiref(L, "coroutine", luaopen_coroutine, 1); - lua_pop(L, 1); -#endif // Lua 5.2+ only - break; -#endif // Not LuaJIT - comes builtin - case lib::string: - luaL_requiref(L, "string", luaopen_string, 1); - lua_pop(L, 1); - break; - case lib::table: - luaL_requiref(L, "table", luaopen_table, 1); - lua_pop(L, 1); - break; - case lib::math: - luaL_requiref(L, "math", luaopen_math, 1); - lua_pop(L, 1); - break; - case lib::bit32: -#ifdef SOL_LUAJIT - luaL_requiref(L, "bit32", luaopen_bit, 1); - lua_pop(L, 1); -#elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) - luaL_requiref(L, "bit32", luaopen_bit32, 1); - lua_pop(L, 1); -#else -#endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) - break; - case lib::io: - luaL_requiref(L, "io", luaopen_io, 1); - lua_pop(L, 1); - break; - case lib::os: - luaL_requiref(L, "os", luaopen_os, 1); - lua_pop(L, 1); - break; - case lib::debug: - luaL_requiref(L, "debug", luaopen_debug, 1); - lua_pop(L, 1); - break; - case lib::utf8: -#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) - luaL_requiref(L, "utf8", luaopen_utf8, 1); - lua_pop(L, 1); -#endif // Lua 5.3+ only - break; - case lib::ffi: -#ifdef SOL_LUAJIT - luaL_requiref(L, "ffi", luaopen_ffi, 1); - lua_pop(L, 1); -#endif // LuaJIT only - break; - case lib::jit: -#ifdef SOL_LUAJIT - luaL_requiref(L, "jit", luaopen_jit, 1); - lua_pop(L, 1); -#endif // LuaJIT Only - break; - case lib::count: - default: - break; - } - } - } - - object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { - luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); - return stack::pop<object>(L); - } - - object require_script(const std::string& key, const std::string& code, bool create_global = true) { - return require_core(key, [this, &code]() {stack::script(L, code); }, create_global); - } - - object require_file(const std::string& key, const std::string& filename, bool create_global = true) { - return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); - } - - protected_function_result do_string(const std::string& code) { - sol::protected_function pf = load(code); - return pf(); - } - - protected_function_result do_file(const std::string& filename) { - sol::protected_function pf = load_file(filename); - return pf(); - } - - function_result script(const std::string& code) { - int index = lua_gettop(L); - stack::script(L, code); - int postindex = lua_gettop(L); - int returns = postindex - index; - return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); - } - - function_result script_file(const std::string& filename) { - int index = lua_gettop(L); - stack::script_file(L, filename); - int postindex = lua_gettop(L); - int returns = postindex - index; - return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); - } - - load_result load(const std::string& code) { - load_status x = static_cast<load_status>(luaL_loadstring(L, code.c_str())); - return load_result(L, lua_absindex(L, -1), 1, 1, x); - } - - load_result load_file(const std::string& filename) { - load_status x = static_cast<load_status>(luaL_loadfile(L, filename.c_str())); - return load_result(L, lua_absindex(L, -1), 1, 1, x); - } - - load_result load_buffer(const char *buff, size_t size, const char *name, const char* mode = nullptr) { - load_status x = static_cast<load_status>(luaL_loadbufferx(L, buff, size, name, mode)); - return load_result(L, lua_absindex(L, -1), 1, 1, x); - } - - iterator begin() const { - return global.begin(); - } - - iterator end() const { - return global.end(); - } - - const_iterator cbegin() const { - return global.cbegin(); - } - - const_iterator cend() const { - return global.cend(); - } - - global_table globals() const { - return global; - } - - table registry() const { - return reg; - } - - std::size_t memory_used() const { - return total_memory_used(lua_state()); - } - - void collect_garbage() { - lua_gc(lua_state(), LUA_GCCOLLECT, 0); - } - - operator lua_State* () const { - return lua_state(); - } - - void set_panic(lua_CFunction panic) { - lua_atpanic(L, panic); - } - - template<typename... Args, typename... Keys> - decltype(auto) get(Keys&&... keys) const { - return global.get<Args...>(std::forward<Keys>(keys)...); - } - - template<typename T, typename Key> - decltype(auto) get_or(Key&& key, T&& otherwise) const { - return global.get_or(std::forward<Key>(key), std::forward<T>(otherwise)); - } - - template<typename T, typename Key, typename D> - decltype(auto) get_or(Key&& key, D&& otherwise) const { - return global.get_or<T>(std::forward<Key>(key), std::forward<D>(otherwise)); - } - - template<typename... Args> - state_view& set(Args&&... args) { - global.set(std::forward<Args>(args)...); - return *this; - } - - template<typename T, typename... Keys> - decltype(auto) traverse_get(Keys&&... keys) const { - return global.traverse_get<T>(std::forward<Keys>(keys)...); - } - - template<typename... Args> - state_view& traverse_set(Args&&... args) { - global.traverse_set(std::forward<Args>(args)...); - return *this; - } - - template<typename T> - state_view& set_usertype(usertype<T>& user) { - return set_usertype(usertype_traits<T>::name(), user); - } - - template<typename Key, typename T> - state_view& set_usertype(Key&& key, usertype<T>& user) { - global.set_usertype(std::forward<Key>(key), user); - return *this; - } - - template<typename Class, typename... Args> - state_view& new_usertype(const std::string& name, Args&&... args) { - global.new_usertype<Class>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - state_view& new_usertype(const std::string& name, Args&&... args) { - global.new_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... CArgs, typename... Args> - state_view& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - global.new_usertype<Class>(name, ctor, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... Args> - state_view& new_simple_usertype(const std::string& name, Args&&... args) { - global.new_simple_usertype<Class>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - state_view& new_simple_usertype(const std::string& name, Args&&... args) { - global.new_simple_usertype<Class, CTor0, CTor...>(name, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... CArgs, typename... Args> - state_view& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - global.new_simple_usertype<Class>(name, ctor, std::forward<Args>(args)...); - return *this; - } - - template<typename Class, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - return global.create_simple_usertype<Class>(std::forward<Args>(args)...); - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - return global.create_simple_usertype<Class, CTor0, CTor...>(std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - simple_usertype<Class> create_simple_usertype(constructors<CArgs...> ctor, Args&&... args) { - return global.create_simple_usertype<Class>(ctor, std::forward<Args>(args)...); - } - - template<bool read_only = true, typename... Args> - state_view& new_enum(const std::string& name, Args&&... args) { - global.new_enum<read_only>(name, std::forward<Args>(args)...); - return *this; - } - - template <typename Fx> - void for_each(Fx&& fx) { - global.for_each(std::forward<Fx>(fx)); - } - - template<typename T> - proxy<global_table&, T> operator[](T&& key) { - return global[std::forward<T>(key)]; - } - - template<typename T> - proxy<const global_table&, T> operator[](T&& key) const { - return global[std::forward<T>(key)]; - } - - template<typename Sig, typename... Args, typename Key> - state_view& set_function(Key&& key, Args&&... args) { - global.set_function<Sig>(std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template<typename... Args, typename Key> - state_view& set_function(Key&& key, Args&&... args) { - global.set_function(std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template <typename Name> - table create_table(Name&& name, int narr = 0, int nrec = 0) { - return global.create(std::forward<Name>(name), narr, nrec); - } - - template <typename Name, typename Key, typename Value, typename... Args> - table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return global.create(std::forward<Name>(name), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename Name, typename... Args> - table create_named_table(Name&& name, Args&&... args) { - table x = global.create_with(std::forward<Args>(args)...); - global.set(std::forward<Name>(name), x); - return x; - } - - table create_table(int narr = 0, int nrec = 0) { - return create_table(lua_state(), narr, nrec); - } - - template <typename Key, typename Value, typename... Args> - table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return create_table(lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename... Args> - table create_table_with(Args&&... args) { - return create_table_with(lua_state(), std::forward<Args>(args)...); - } - - static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { - return global_table::create(L, narr, nrec); - } - - template <typename Key, typename Value, typename... Args> - static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return global_table::create(L, narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename... Args> - static inline table create_table_with(lua_State* L, Args&&... args) { - return global_table::create_with(L, std::forward<Args>(args)...); - } - }; -} // sol - -#endif // SOL_STATE_VIEW_HPP diff --git a/3rdparty/sol2/sol/string_shim.hpp b/3rdparty/sol2/sol/string_shim.hpp deleted file mode 100644 index 73aa81646fb..00000000000 --- a/3rdparty/sol2/sol/string_shim.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_STRING_SHIM_HPP -#define SOL_STRING_SHIM_HPP - -#include <cstddef> -#include <string> - -namespace sol { - namespace string_detail { - struct string_shim { - std::size_t s; - const char* p; - - string_shim(const std::string& r) : string_shim(r.data(), r.size()) {} - string_shim(const char* ptr) : string_shim(ptr, std::char_traits<char>::length(ptr)) {} - string_shim(const char* ptr, std::size_t sz) : s(sz), p(ptr) {} - - static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) { - int result = std::char_traits<char>::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); - if (result != 0) - return result; - if (lhs_sz < rhs_sz) - return -1; - if (lhs_sz > rhs_sz) - return 1; - return 0; - } - - const char* c_str() const { - return p; - } - - const char* data() const { - return p; - } - - std::size_t size() const { - return s; - } - - bool operator==(const string_shim& r) const { - return compare(p, s, r.data(), r.size()) == 0; - } - - bool operator==(const char* r) const { - return compare(r, std::char_traits<char>::length(r), p, s) == 0; - } - - bool operator==(const std::string& r) const { - return compare(r.data(), r.size(), p, s) == 0; - } - - bool operator!=(const string_shim& r) const { - return !(*this == r); - } - - bool operator!=(const char* r) const { - return !(*this == r); - } - - bool operator!=(const std::string& r) const { - return !(*this == r); - } - }; - } -} - -#endif // SOL_STRING_SHIM_HPP diff --git a/3rdparty/sol2/sol/table.hpp b/3rdparty/sol2/sol/table.hpp deleted file mode 100644 index fd556a6117d..00000000000 --- a/3rdparty/sol2/sol/table.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TABLE_HPP -#define SOL_TABLE_HPP - -#include "table_core.hpp" - -namespace sol { - typedef table_core<false> table; -} // sol - -#endif // SOL_TABLE_HPP diff --git a/3rdparty/sol2/sol/table_core.hpp b/3rdparty/sol2/sol/table_core.hpp deleted file mode 100644 index 8004ebd2180..00000000000 --- a/3rdparty/sol2/sol/table_core.hpp +++ /dev/null @@ -1,475 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TABLE_CORE_HPP -#define SOL_TABLE_CORE_HPP - -#include "proxy.hpp" -#include "stack.hpp" -#include "function_types.hpp" -#include "usertype.hpp" -#include "table_iterator.hpp" - -namespace sol { - namespace detail { - template <std::size_t n> - struct clean { lua_State* L; clean(lua_State* luastate) : L(luastate) {} ~clean() { lua_pop(L, static_cast<int>(n)); } }; - struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* luastate, int& n) : L(luastate), n(n) {} ~ref_clean() { lua_pop(L, static_cast<int>(n)); } }; - inline int fail_on_newindex(lua_State* L) { - return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); - } - } - - template <bool top_level, typename base_t> - class basic_table_core : public base_t { - friend class state; - friend class state_view; - - template <typename... Args> - using is_global = meta::all<meta::boolean<top_level>, meta::is_c_str<Args>...>; - - template<typename Fx> - void for_each(std::true_type, Fx&& fx) const { - auto pp = stack::push_pop(*this); - stack::push(base_t::lua_state(), lua_nil); - while (lua_next(base_t::lua_state(), -2)) { - sol::object key(base_t::lua_state(), -2); - sol::object value(base_t::lua_state(), -1); - std::pair<sol::object&, sol::object&> keyvalue(key, value); - auto pn = stack::pop_n(base_t::lua_state(), 1); - fx(keyvalue); - } - } - - template<typename Fx> - void for_each(std::false_type, Fx&& fx) const { - auto pp = stack::push_pop(*this); - stack::push(base_t::lua_state(), lua_nil); - while (lua_next(base_t::lua_state(), -2)) { - sol::object key(base_t::lua_state(), -2); - sol::object value(base_t::lua_state(), -1); - auto pn = stack::pop_n(base_t::lua_state(), 1); - fx(key, value); - } - } - - template<typename Ret0, typename Ret1, typename... Ret, std::size_t... I, typename Keys> - auto tuple_get(types<Ret0, Ret1, Ret...>, std::index_sequence<0, 1, I...>, Keys&& keys) const - -> decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) { - typedef decltype(stack::pop<std::tuple<Ret0, Ret1, Ret...>>(nullptr)) Tup; - return Tup( - traverse_get_optional<top_level, Ret0>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret0>>(), detail::forward_get<0>(keys)), - traverse_get_optional<top_level, Ret1>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret1>>(), detail::forward_get<1>(keys)), - traverse_get_optional<top_level, Ret>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret>>(), detail::forward_get<I>(keys))... - ); - } - - template<typename Ret, std::size_t I, typename Keys> - decltype(auto) tuple_get(types<Ret>, std::index_sequence<I>, Keys&& keys) const { - return traverse_get_optional<top_level, Ret>(meta::is_specialization_of<sol::optional, meta::unqualified_t<Ret>>(), detail::forward_get<I>(keys)); - } - - template<typename Pairs, std::size_t... I> - void tuple_set(std::index_sequence<I...>, Pairs&& pairs) { - auto pp = stack::push_pop<top_level && (is_global<decltype(detail::forward_get<I * 2>(pairs))...>::value)>(*this); - void(detail::swallow{ (stack::set_field<top_level>(base_t::lua_state(), - detail::forward_get<I * 2>(pairs), - detail::forward_get<I * 2 + 1>(pairs), - lua_gettop(base_t::lua_state()) - ), 0)... }); - } - - template <bool global, typename T, typename Key> - decltype(auto) traverse_get_deep(Key&& key) const { - stack::get_field<global>(base_t::lua_state(), std::forward<Key>(key)); - return stack::get<T>(base_t::lua_state()); - } - - template <bool global, typename T, typename Key, typename... Keys> - decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { - stack::get_field<global>(base_t::lua_state(), std::forward<Key>(key)); - return traverse_get_deep<false, T>(std::forward<Keys>(keys)...); - } - - template <bool global, typename T, std::size_t I, typename Key> - decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { - typedef decltype(stack::get<T>(base_t::lua_state())) R; - auto p = stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), lua_gettop(base_t::lua_state())); - popcount += p.levels; - if (!p.success) - return R(nullopt); - return stack::get<T>(base_t::lua_state()); - } - - template <bool global, typename T, std::size_t I, typename Key, typename... Keys> - decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { - auto p = I > 0 ? stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), -1) : stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), lua_gettop(base_t::lua_state())); - popcount += p.levels; - if (!p.success) - return T(nullopt); - return traverse_get_deep_optional<false, T, I + 1>(popcount, std::forward<Keys>(keys)...); - } - - template <bool global, typename T, typename... Keys> - decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { - detail::clean<sizeof...(Keys)> c(base_t::lua_state()); - return traverse_get_deep<top_level, T>(std::forward<Keys>(keys)...); - } - - template <bool global, typename T, typename... Keys> - decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { - int popcount = 0; - detail::ref_clean c(base_t::lua_state(), popcount); - return traverse_get_deep_optional<top_level, T, 0>(popcount, std::forward<Keys>(keys)...); - } - - template <bool global, typename Key, typename Value> - void traverse_set_deep(Key&& key, Value&& value) const { - stack::set_field<global>(base_t::lua_state(), std::forward<Key>(key), std::forward<Value>(value)); - } - - template <bool global, typename Key, typename... Keys> - void traverse_set_deep(Key&& key, Keys&&... keys) const { - stack::get_field<global>(base_t::lua_state(), std::forward<Key>(key)); - traverse_set_deep<false>(std::forward<Keys>(keys)...); - } - - basic_table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { } - - public: - typedef basic_table_iterator<base_t> iterator; - typedef iterator const_iterator; - - basic_table_core() noexcept : base_t() { } - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_table_core>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_table_core(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_table<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - stack::check<basic_table_core>(base_t::lua_state(), -1, type_panic); - } -#endif // Safety - } - basic_table_core(const basic_table_core&) = default; - basic_table_core(basic_table_core&&) = default; - basic_table_core& operator=(const basic_table_core&) = default; - basic_table_core& operator=(basic_table_core&&) = default; - basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {} - basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_table_core(lua_State* L, T&& r) : basic_table_core(L, sol::ref_index(r.registry_index())) {} - basic_table_core(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check<basic_table_core>(L, index, type_panic); -#endif // Safety - } - basic_table_core(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check<basic_table_core>(L, -1, type_panic); -#endif // Safety - } - - iterator begin() const { - return iterator(*this); - } - - iterator end() const { - return iterator(); - } - - const_iterator cbegin() const { - return begin(); - } - - const_iterator cend() const { - return end(); - } - - template<typename... Ret, typename... Keys> - decltype(auto) get(Keys&&... keys) const { - static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); - auto pp = stack::push_pop<is_global<Keys...>::value>(*this); - return tuple_get(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), std::forward_as_tuple(std::forward<Keys>(keys)...)); - } - - template<typename T, typename Key> - decltype(auto) get_or(Key&& key, T&& otherwise) const { - typedef decltype(get<T>("")) U; - sol::optional<U> option = get<sol::optional<U>>(std::forward<Key>(key)); - if (option) { - return static_cast<U>(option.value()); - } - return static_cast<U>(std::forward<T>(otherwise)); - } - - template<typename T, typename Key, typename D> - decltype(auto) get_or(Key&& key, D&& otherwise) const { - sol::optional<T> option = get<sol::optional<T>>(std::forward<Key>(key)); - if (option) { - return static_cast<T>(option.value()); - } - return static_cast<T>(std::forward<D>(otherwise)); - } - - template <typename T, typename... Keys> - decltype(auto) traverse_get(Keys&&... keys) const { - auto pp = stack::push_pop<is_global<Keys...>::value>(*this); - return traverse_get_optional<top_level, T>(meta::is_specialization_of<sol::optional, meta::unqualified_t<T>>(), std::forward<Keys>(keys)...); - } - - template <typename... Keys> - basic_table_core& traverse_set(Keys&&... keys) { - auto pp = stack::push_pop<is_global<Keys...>::value>(*this); - auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys)-2)); - traverse_set_deep<top_level>(std::forward<Keys>(keys)...); - return *this; - } - - template<typename... Args> - basic_table_core& set(Args&&... args) { - tuple_set(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...)); - return *this; - } - - template<typename T> - basic_table_core& set_usertype(usertype<T>& user) { - return set_usertype(usertype_traits<T>::name(), user); - } - - template<typename Key, typename T> - basic_table_core& set_usertype(Key&& key, usertype<T>& user) { - return set(std::forward<Key>(key), user); - } - - template<typename Class, typename... Args> - basic_table_core& new_usertype(const std::string& name, Args&&... args) { - usertype<Class> utype(std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - basic_table_core& new_usertype(const std::string& name, Args&&... args) { - constructors<types<CTor0, CTor...>> ctor{}; - return new_usertype<Class>(name, ctor, std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - basic_table_core& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - usertype<Class> utype(ctor, std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename... Args> - basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { - constructors<types<CTor0, CTor...>> ctor{}; - return new_simple_usertype<Class>(name, ctor, std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - basic_table_core& new_simple_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), ctor, std::forward<Args>(args)...); - set_usertype(name, utype); - return *this; - } - - template<typename Class, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), std::forward<Args>(args)...); - return utype; - } - - template<typename Class, typename CTor0, typename... CTor, typename... Args> - simple_usertype<Class> create_simple_usertype(Args&&... args) { - constructors<types<CTor0, CTor...>> ctor{}; - return create_simple_usertype<Class>(ctor, std::forward<Args>(args)...); - } - - template<typename Class, typename... CArgs, typename... Args> - simple_usertype<Class> create_simple_usertype(constructors<CArgs...> ctor, Args&&... args) { - simple_usertype<Class> utype(base_t::lua_state(), ctor, std::forward<Args>(args)...); - return utype; - } - - template<bool read_only = true, typename... Args> - basic_table_core& new_enum(const std::string& name, Args&&... args) { - if (read_only) { - table idx = create_with(std::forward<Args>(args)...); - table x = create_with( - meta_function::new_index, detail::fail_on_newindex, - meta_function::index, idx - ); - table target = create_named(name); - target[metatable_key] = x; - } - else { - create_named(name, std::forward<Args>(args)...); - } - return *this; - } - - template<typename Fx> - void for_each(Fx&& fx) const { - typedef meta::is_invokable<Fx(std::pair<sol::object, sol::object>)> is_paired; - for_each(is_paired(), std::forward<Fx>(fx)); - } - - size_t size() const { - auto pp = stack::push_pop(*this); - lua_len(base_t::lua_state(), -1); - return stack::pop<size_t>(base_t::lua_state()); - } - - bool empty() const { - return cbegin() == cend(); - } - - template<typename T> - proxy<basic_table_core&, T> operator[](T&& key) & { - return proxy<basic_table_core&, T>(*this, std::forward<T>(key)); - } - - template<typename T> - proxy<const basic_table_core&, T> operator[](T&& key) const & { - return proxy<const basic_table_core&, T>(*this, std::forward<T>(key)); - } - - template<typename T> - proxy<basic_table_core, T> operator[](T&& key) && { - return proxy<basic_table_core, T>(*this, std::forward<T>(key)); - } - - template<typename Sig, typename Key, typename... Args> - basic_table_core& set_function(Key&& key, Args&&... args) { - set_fx(types<Sig>(), std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template<typename Key, typename... Args> - basic_table_core& set_function(Key&& key, Args&&... args) { - set_fx(types<>(), std::forward<Key>(key), std::forward<Args>(args)...); - return *this; - } - - template <typename... Args> - basic_table_core& add(Args&&... args) { - auto pp = stack::push_pop(*this); - (void)detail::swallow{0, - (stack::set_ref(base_t::lua_state(), std::forward<Args>(args)), 0)... - }; - return *this; - } - - private: - template<typename R, typename... Args, typename Fx, typename Key, typename = std::result_of_t<Fx(Args...)>> - void set_fx(types<R(Args...)>, Key&& key, Fx&& fx) { - set_resolved_function<R(Args...)>(std::forward<Key>(key), std::forward<Fx>(fx)); - } - - template<typename Fx, typename Key, meta::enable<meta::is_specialization_of<overload_set, meta::unqualified_t<Fx>>> = meta::enabler> - void set_fx(types<>, Key&& key, Fx&& fx) { - set(std::forward<Key>(key), std::forward<Fx>(fx)); - } - - template<typename Fx, typename Key, typename... Args, meta::disable<meta::is_specialization_of<overload_set, meta::unqualified_t<Fx>>> = meta::enabler> - void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { - set(std::forward<Key>(key), as_function_reference(std::forward<Fx>(fx), std::forward<Args>(args)...)); - } - - template<typename... Sig, typename... Args, typename Key> - void set_resolved_function(Key&& key, Args&&... args) { - set(std::forward<Key>(key), as_function_reference<function_sig<Sig...>>(std::forward<Args>(args)...)); - } - - public: - static inline table create(lua_State* L, int narr = 0, int nrec = 0) { - lua_createtable(L, narr, nrec); - table result(L); - lua_pop(L, 1); - return result; - } - - template <typename Key, typename Value, typename... Args> - static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - lua_createtable(L, narr, nrec); - table result(L); - result.set(std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - lua_pop(L, 1); - return result; - } - - template <typename... Args> - static inline table create_with(lua_State* L, Args&&... args) { - static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); - static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); - return create(L, narr, static_cast<int>((sizeof...(Args) / 2) - narr), std::forward<Args>(args)...); - } - - table create(int narr = 0, int nrec = 0) { - return create(base_t::lua_state(), narr, nrec); - } - - template <typename Key, typename Value, typename... Args> - table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - } - - template <typename Name> - table create(Name&& name, int narr = 0, int nrec = 0) { - table x = create(base_t::lua_state(), narr, nrec); - this->set(std::forward<Name>(name), x); - return x; - } - - template <typename Name, typename Key, typename Value, typename... Args> - table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - table x = create(base_t::lua_state(), narr, nrec, std::forward<Key>(key), std::forward<Value>(value), std::forward<Args>(args)...); - this->set(std::forward<Name>(name), x); - return x; - } - - template <typename... Args> - table create_with(Args&&... args) { - return create_with(base_t::lua_state(), std::forward<Args>(args)...); - } - - template <typename Name, typename... Args> - table create_named(Name&& name, Args&&... args) { - static const int narr = static_cast<int>(meta::count_2_for_pack<std::is_integral, Args...>::value); - return create(std::forward<Name>(name), narr, sizeof...(Args) / 2 - narr, std::forward<Args>(args)...); - } - - ~basic_table_core() { - - } - }; -} // sol - -#endif // SOL_TABLE_CORE_HPP diff --git a/3rdparty/sol2/sol/table_iterator.hpp b/3rdparty/sol2/sol/table_iterator.hpp deleted file mode 100644 index c1102a8eff6..00000000000 --- a/3rdparty/sol2/sol/table_iterator.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TABLE_ITERATOR_HPP -#define SOL_TABLE_ITERATOR_HPP - -#include "object.hpp" -#include <iterator> - -namespace sol { - - template <typename reference_type> - class basic_table_iterator : public std::iterator<std::input_iterator_tag, std::pair<object, object>> { - private: - typedef std::iterator<std::input_iterator_tag, std::pair<object, object>> base_t; - public: - typedef object key_type; - typedef object mapped_type; - typedef base_t::value_type value_type; - typedef base_t::iterator_category iterator_category; - typedef base_t::difference_type difference_type; - typedef base_t::pointer pointer; - typedef base_t::reference reference; - typedef const value_type& const_reference; - - private: - std::pair<object, object> kvp; - reference_type ref; - int tableidx = 0; - int keyidx = 0; - std::ptrdiff_t idx = 0; - - public: - - basic_table_iterator() : keyidx(-1), idx(-1) { - - } - - basic_table_iterator(reference_type x) : ref(std::move(x)) { - ref.push(); - tableidx = lua_gettop(ref.lua_state()); - stack::push(ref.lua_state(), lua_nil); - this->operator++(); - if (idx == -1) { - return; - } - --idx; - } - - basic_table_iterator& operator++() { - if (idx == -1) - return *this; - - if (lua_next(ref.lua_state(), tableidx) == 0) { - idx = -1; - keyidx = -1; - return *this; - } - ++idx; - kvp.first = object(ref.lua_state(), -2); - kvp.second = object(ref.lua_state(), -1); - lua_pop(ref.lua_state(), 1); - // leave key on the stack - keyidx = lua_gettop(ref.lua_state()); - return *this; - } - - basic_table_iterator operator++(int) { - auto saved = *this; - this->operator++(); - return saved; - } - - reference operator*() { - return kvp; - } - - const_reference operator*() const { - return kvp; - } - - bool operator== (const basic_table_iterator& right) const { - return idx == right.idx; - } - - bool operator!= (const basic_table_iterator& right) const { - return idx != right.idx; - } - - ~basic_table_iterator() { - if (keyidx != -1) { - stack::remove(ref.lua_state(), keyidx, 1); - } - if (ref.valid()) { - stack::remove(ref.lua_state(), tableidx, 1); - } - } - }; - -} // sol - -#endif // SOL_TABLE_ITERATOR_HPP diff --git a/3rdparty/sol2/sol/thread.hpp b/3rdparty/sol2/sol/thread.hpp deleted file mode 100644 index 5e57ad1de02..00000000000 --- a/3rdparty/sol2/sol/thread.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_THREAD_HPP -#define SOL_THREAD_HPP - -#include "reference.hpp" -#include "stack.hpp" - -namespace sol { - struct lua_thread_state { - lua_State* L; - operator lua_State* () const { - return L; - } - lua_State* operator-> () const { - return L; - } - }; - - namespace stack { - - template <> - struct pusher<lua_thread_state> { - int push(lua_State*, lua_thread_state lts) { - lua_pushthread(lts.L); - return 1; - } - }; - - template <> - struct getter<lua_thread_state> { - lua_thread_state get(lua_State* L, int index, record& tracking) { - tracking.use(1); - lua_thread_state lts{ lua_tothread(L, index) }; - return lts; - } - }; - - template <> - struct check_getter<lua_thread_state> { - template <typename Handler> - optional<lua_thread_state> get(lua_State* L, int index, Handler&& handler, record& tracking) { - lua_thread_state lts{ lua_tothread(L, index) }; - if (lts.L == nullptr) { - handler(L, index, type::thread, type_of(L, index)); - return nullopt; - } - tracking.use(1); - return lts; - } - }; - - } - -#if SOL_LUA_VERSION < 502 - inline lua_State* main_thread(lua_State*, lua_State* backup_if_unsupported = nullptr) { - return backup_if_unsupported; - } -#else - inline lua_State* main_thread(lua_State* L, lua_State* = nullptr) { - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); - lua_thread_state s = stack::pop<lua_thread_state>(L); - return s.L; - } -#endif // Lua 5.2+ has the main thread getter - - class thread : public reference { - public: - thread() noexcept = default; - thread(const thread&) = default; - thread(thread&&) = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, thread>>, std::is_base_of<reference, meta::unqualified_t<T>>> = meta::enabler> - thread(T&& r) : reference(std::forward<T>(r)) {} - thread(const stack_reference& r) : thread(r.lua_state(), r.stack_index()) {}; - thread(stack_reference&& r) : thread(r.lua_state(), r.stack_index()) {}; - thread& operator=(const thread&) = default; - thread& operator=(thread&&) = default; - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - thread(lua_State* L, T&& r) : thread(L, sol::ref_index(r.registry_index())) {} - thread(lua_State* L, int index = -1) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::thread); -#endif // Safety - } - thread(lua_State* L, ref_index index) : reference(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::thread); -#endif // Safety - } - thread(lua_State* L, lua_State* actualthread) : thread(L, lua_thread_state{ actualthread }) {} - thread(lua_State* L, sol::this_state actualthread) : thread(L, lua_thread_state{ actualthread.L }) {} - thread(lua_State* L, lua_thread_state actualthread) : reference(L, -stack::push(L, actualthread)) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, -1, type::thread); -#endif // Safety - lua_pop(L, 1); - } - - state_view state() const { - return state_view(this->thread_state()); - } - - bool is_main_thread() const { - int ismainthread = lua_pushthread(this->thread_state()); - lua_pop(this->thread_state(), 1); - return ismainthread == 1; - } - - lua_State* thread_state() const { - auto pp = stack::push_pop(*this); - lua_State* lthread = lua_tothread(lua_state(), -1); - return lthread; - } - - thread_status status() const { - lua_State* lthread = thread_state(); - thread_status lstat = static_cast<thread_status>(lua_status(lthread)); - if (lstat != thread_status::ok && lua_gettop(lthread) == 0) { - // No thing on the thread's stack means its dead - return thread_status::dead; - } - return lstat; - } - - thread create() { - return create(lua_state()); - } - - static thread create(lua_State* L) { - lua_newthread(L); - thread result(L); - lua_pop(L, 1); - return result; - } - }; -} // sol - -#endif // SOL_THREAD_HPP diff --git a/3rdparty/sol2/sol/tie.hpp b/3rdparty/sol2/sol/tie.hpp deleted file mode 100644 index 9157ed008d1..00000000000 --- a/3rdparty/sol2/sol/tie.hpp +++ /dev/null @@ -1,101 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TIE_HPP -#define SOL_TIE_HPP - -#include "traits.hpp" - -namespace sol { - - namespace detail { - template <typename T> - struct is_speshul : std::false_type {}; - } - - template <typename T> - struct tie_size : std::tuple_size<T> {}; - - template <typename T> - struct is_tieable : std::integral_constant<bool, (::sol::tie_size<T>::value > 0)> {}; - - template <typename... Tn> - struct tie_t : public std::tuple<std::add_lvalue_reference_t<Tn>...> { - private: - typedef std::tuple<std::add_lvalue_reference_t<Tn>...> base_t; - - template <typename T> - void set(std::false_type, T&& target) { - std::get<0>(*this) = std::forward<T>(target); - } - - template <typename T> - void set(std::true_type, T&& target) { - typedef tie_size<meta::unqualified_t<T>> value_size; - typedef tie_size<std::tuple<Tn...>> tie_size; - typedef std::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; - typedef std::make_index_sequence<indices_size::value> indices; - set_extra(detail::is_speshul<meta::unqualified_t<T>>(), indices(), std::forward<T>(target)); - } - - template <std::size_t... I, typename T> - void set_extra(std::true_type, std::index_sequence<I...>, T&& target) { - using std::get; - (void)detail::swallow{ 0, - (get<I>(static_cast<base_t&>(*this)) = get<I>(types<Tn...>(), target), 0)... - , 0 }; - } - - template <std::size_t... I, typename T> - void set_extra(std::false_type, std::index_sequence<I...>, T&& target) { - using std::get; - (void)detail::swallow{ 0, - (get<I>(static_cast<base_t&>(*this)) = get<I>(target), 0)... - , 0 }; - } - - public: - using base_t::base_t; - - template <typename T> - tie_t& operator= (T&& value) { - typedef is_tieable<meta::unqualified_t<T>> tieable; - set(tieable(), std::forward<T>(value)); - return *this; - } - - }; - - template <typename... Tn> - struct tie_size< tie_t<Tn...> > : std::tuple_size< std::tuple<Tn...> > { }; - - namespace adl_barrier_detail { - template <typename... Tn> - inline tie_t<std::remove_reference_t<Tn>...> tie(Tn&&... argn) { - return tie_t<std::remove_reference_t<Tn>...>(std::forward<Tn>(argn)...); - } - } - - using namespace adl_barrier_detail; - -} // sol - -#endif // SOL_TIE_HPP diff --git a/3rdparty/sol2/sol/traits.hpp b/3rdparty/sol2/sol/traits.hpp deleted file mode 100644 index 1ed95a1656e..00000000000 --- a/3rdparty/sol2/sol/traits.hpp +++ /dev/null @@ -1,428 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TRAITS_HPP -#define SOL_TRAITS_HPP - -#include "tuple.hpp" -#include "bind_traits.hpp" -#include <type_traits> -#include <memory> -#include <functional> - -namespace sol { - template<std::size_t I> - using index_value = std::integral_constant<std::size_t, I>; - - namespace meta { - template<typename T> - struct identity { typedef T type; }; - - template<typename T> - using identity_t = typename identity<T>::type; - - template<typename... Args> - struct is_tuple : std::false_type { }; - - template<typename... Args> - struct is_tuple<std::tuple<Args...>> : std::true_type { }; - - template <typename T> - struct is_builtin_type : std::integral_constant<bool, std::is_arithmetic<T>::value || std::is_pointer<T>::value || std::is_array<T>::value> {}; - - template<typename T> - struct unwrapped { - typedef T type; - }; - - template<typename T> - struct unwrapped<std::reference_wrapper<T>> { - typedef T type; - }; - - template<typename T> - using unwrapped_t = typename unwrapped<T>::type; - - template <typename T> - struct unwrap_unqualified : unwrapped<unqualified_t<T>> {}; - - template <typename T> - using unwrap_unqualified_t = typename unwrap_unqualified<T>::type; - - template<typename T> - struct remove_member_pointer; - - template<typename R, typename T> - struct remove_member_pointer<R T::*> { - typedef R type; - }; - - template<typename R, typename T> - struct remove_member_pointer<R T::* const> { - typedef R type; - }; - - template<typename T> - using remove_member_pointer_t = remove_member_pointer<T>; - - template<template<typename...> class Templ, typename T> - struct is_specialization_of : std::false_type { }; - template<typename... T, template<typename...> class Templ> - struct is_specialization_of<Templ, Templ<T...>> : std::true_type { }; - - template<class T, class...> - struct all_same : std::true_type { }; - - template<class T, class U, class... Args> - struct all_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value && all_same<T, Args...>::value> { }; - - template<class T, class...> - struct any_same : std::false_type { }; - - template<class T, class U, class... Args> - struct any_same<T, U, Args...> : std::integral_constant <bool, std::is_same<T, U>::value || any_same<T, Args...>::value> { }; - - template<typename T> - using invoke_t = typename T::type; - - template<bool B> - using boolean = std::integral_constant<bool, B>; - - template<typename T> - using neg = boolean<!T::value>; - - template<typename Condition, typename Then, typename Else> - using condition = std::conditional_t<Condition::value, Then, Else>; - - template<typename... Args> - struct all : boolean<true> {}; - - template<typename T, typename... Args> - struct all<T, Args...> : condition<T, all<Args...>, boolean<false>> {}; - - template<typename... Args> - struct any : boolean<false> {}; - - template<typename T, typename... Args> - struct any<T, Args...> : condition<T, boolean<true>, any<Args...>> {}; - - enum class enable_t { - _ - }; - - constexpr const auto enabler = enable_t::_; - - template<bool value, typename T = void> - using disable_if_t = std::enable_if_t<!value, T>; - - template<typename... Args> - using enable = std::enable_if_t<all<Args...>::value, enable_t>; - - template<typename... Args> - using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>; - - template<typename... Args> - using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>; - - template<typename V, typename... Vs> - struct find_in_pack_v : boolean<false> { }; - - template<typename V, typename Vs1, typename... Vs> - struct find_in_pack_v<V, Vs1, Vs...> : any<boolean<(V::value == Vs1::value)>, find_in_pack_v<V, Vs...>> { }; - - namespace meta_detail { - template<std::size_t I, typename T, typename... Args> - struct index_in_pack : std::integral_constant<std::size_t, SIZE_MAX> { }; - - template<std::size_t I, typename T, typename T1, typename... Args> - struct index_in_pack<I, T, T1, Args...> : std::conditional_t<std::is_same<T, T1>::value, std::integral_constant<std::ptrdiff_t, I>, index_in_pack<I + 1, T, Args...>> { }; - } - - template<typename T, typename... Args> - struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; - - template<typename T, typename List> - struct index_in : meta_detail::index_in_pack<0, T, List> { }; - - template<typename T, typename... Args> - struct index_in<T, types<Args...>> : meta_detail::index_in_pack<0, T, Args...> { }; - - template<std::size_t I, typename... Args> - struct at_in_pack {}; - - template<std::size_t I, typename... Args> - using at_in_pack_t = typename at_in_pack<I, Args...>::type; - - template<std::size_t I, typename Arg, typename... Args> - struct at_in_pack<I, Arg, Args...> : std::conditional<I == 0, Arg, at_in_pack_t<I - 1, Args...>> {}; - - template<typename Arg, typename... Args> - struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; - - namespace meta_detail { - template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename... Ts> - struct count_for_pack : std::integral_constant<std::size_t, 0> {}; - template<std::size_t Limit, std::size_t I, template<typename...> class Pred, typename T, typename... Ts> - struct count_for_pack<Limit, I, Pred, T, Ts...> : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, - std::integral_constant<std::size_t, I + static_cast<std::size_t>(Limit != 0 && Pred<T>::value)>, - count_for_pack<Limit - 1, I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...> - > { }; - template<std::size_t I, template<typename...> class Pred, typename... Ts> - struct count_2_for_pack : std::integral_constant<std::size_t, 0> {}; - template<std::size_t I, template<typename...> class Pred, typename T, typename U, typename... Ts> - struct count_2_for_pack<I, Pred, T, U, Ts...> : std::conditional_t<sizeof...(Ts) == 0, - std::integral_constant<std::size_t, I + static_cast<std::size_t>(Pred<T>::value)>, - count_2_for_pack<I + static_cast<std::size_t>(Pred<T>::value), Pred, Ts...> - > { }; - } // meta_detail - - template<template<typename...> class Pred, typename... Ts> - struct count_for_pack : meta_detail::count_for_pack<sizeof...(Ts), 0, Pred, Ts...> { }; - - template<template<typename...> class Pred, typename List> - struct count_for; - - template<template<typename...> class Pred, typename... Args> - struct count_for<Pred, types<Args...>> : count_for_pack<Pred, Args...> {}; - - template<std::size_t Limit, template<typename...> class Pred, typename... Ts> - struct count_for_to_pack : meta_detail::count_for_pack<Limit, 0, Pred, Ts...> { }; - - template<template<typename...> class Pred, typename... Ts> - struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; - - template<typename... Args> - struct return_type { - typedef std::tuple<Args...> type; - }; - - template<typename T> - struct return_type<T> { - typedef T type; - }; - - template<> - struct return_type<> { - typedef void type; - }; - - template <typename... Args> - using return_type_t = typename return_type<Args...>::type; - - namespace meta_detail { - template <typename> struct always_true : std::true_type {}; - struct is_invokable_tester { - template <typename Fun, typename... Args> - always_true<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int); - template <typename...> - std::false_type static test(...); - }; - } // meta_detail - - template <typename T> - struct is_invokable; - template <typename Fun, typename... Args> - struct is_invokable<Fun(Args...)> : decltype(meta_detail::is_invokable_tester::test<Fun, Args...>(0)) {}; - - namespace meta_detail { - - template<typename T, bool isclass = std::is_class<unqualified_t<T>>::value> - struct is_callable : std::is_function<std::remove_pointer_t<T>> {}; - - template<typename T> - struct is_callable<T, true> { - using yes = char; - using no = struct { char s[2]; }; - - struct F { void operator()(); }; - struct Derived : T, F {}; - template<typename U, U> struct Check; - - template<typename V> - static no test(Check<void (F::*)(), &V::operator()>*); - - template<typename> - static yes test(...); - - static const bool value = sizeof(test<Derived>(0)) == sizeof(yes); - }; - - struct has_begin_end_impl { - template<typename T, typename U = unqualified_t<T>, - typename B = decltype(std::declval<U&>().begin()), - typename E = decltype(std::declval<U&>().end())> - static std::true_type test(int); - - template<typename...> - static std::false_type test(...); - }; - - struct has_key_value_pair_impl { - template<typename T, typename U = unqualified_t<T>, - typename V = typename U::value_type, - typename F = decltype(std::declval<V&>().first), - typename S = decltype(std::declval<V&>().second)> - static std::true_type test(int); - - template<typename...> - static std::false_type test(...); - }; - - template <typename T, typename U = T, typename = decltype(std::declval<T&>() < std::declval<U&>())> - std::true_type supports_op_less_test(const T&); - std::false_type supports_op_less_test(...); - template <typename T, typename U = T, typename = decltype(std::declval<T&>() == std::declval<U&>())> - std::true_type supports_op_equal_test(const T&); - std::false_type supports_op_equal_test(...); - template <typename T, typename U = T, typename = decltype(std::declval<T&>() <= std::declval<U&>())> - std::true_type supports_op_less_equal_test(const T&); - std::false_type supports_op_less_equal_test(...); - - } // meta_detail - - template <typename T> - using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval<T&>())); - template <typename T> - using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval<T&>())); - template <typename T> - using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval<T&>())); - - template<typename T> - struct is_callable : boolean<meta_detail::is_callable<T>::value> {}; - - template<typename T> - struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test<T>(0)) {}; - - template<typename T> - struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {}; - - template <typename T> - using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>; - - template <typename T> - using is_c_str = any< - std::is_same<std::decay_t<unqualified_t<T>>, const char*>, - std::is_same<std::decay_t<unqualified_t<T>>, char*>, - std::is_same<unqualified_t<T>, std::string> - >; - - template <typename T> - struct is_move_only : all< - neg<std::is_reference<T>>, - neg<std::is_copy_constructible<unqualified_t<T>>>, - std::is_move_constructible<unqualified_t<T>> - > {}; - - template <typename T> - using is_not_move_only = neg<is_move_only<T>>; - - namespace meta_detail { - template <typename T, meta::disable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler> - decltype(auto) force_tuple(T&& x) { - return std::forward_as_tuple(std::forward<T>(x)); - } - - template <typename T, meta::enable<meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>> = meta::enabler> - decltype(auto) force_tuple(T&& x) { - return std::forward<T>(x); - } - } // meta_detail - - template <typename... X> - decltype(auto) tuplefy(X&&... x) { - return std::tuple_cat(meta_detail::force_tuple(std::forward<X>(x))...); - } - } // meta - namespace detail { - template <std::size_t I, typename Tuple> - decltype(auto) forward_get(Tuple&& tuple) { - return std::forward<meta::tuple_element_t<I, Tuple>>(std::get<I>(tuple)); - } - - template <std::size_t... I, typename Tuple> - auto forward_tuple_impl(std::index_sequence<I...>, Tuple&& tuple) -> decltype(std::tuple<decltype(forward_get<I>(tuple))...>(forward_get<I>(tuple)...)) { - return std::tuple<decltype(forward_get<I>(tuple))...>(std::move(std::get<I>(tuple))...); - } - - template <typename Tuple> - auto forward_tuple(Tuple&& tuple) { - auto x = forward_tuple_impl(std::make_index_sequence<std::tuple_size<meta::unqualified_t<Tuple>>::value>(), std::forward<Tuple>(tuple)); - return x; - } - - template<typename T> - auto unwrap(T&& item) -> decltype(std::forward<T>(item)) { - return std::forward<T>(item); - } - - template<typename T> - T& unwrap(std::reference_wrapper<T> arg) { - return arg.get(); - } - - template<typename T> - auto deref(T&& item) -> decltype(std::forward<T>(item)) { - return std::forward<T>(item); - } - - template<typename T> - inline T& deref(T* item) { - return *item; - } - - template<typename T, typename Dx> - inline std::add_lvalue_reference_t<T> deref(std::unique_ptr<T, Dx>& item) { - return *item; - } - - template<typename T> - inline std::add_lvalue_reference_t<T> deref(std::shared_ptr<T>& item) { - return *item; - } - - template<typename T, typename Dx> - inline std::add_lvalue_reference_t<T> deref(const std::unique_ptr<T, Dx>& item) { - return *item; - } - - template<typename T> - inline std::add_lvalue_reference_t<T> deref(const std::shared_ptr<T>& item) { - return *item; - } - - template<typename T> - inline T* ptr(T& val) { - return std::addressof(val); - } - - template<typename T> - inline T* ptr(std::reference_wrapper<T> val) { - return std::addressof(val.get()); - } - - template<typename T> - inline T* ptr(T* val) { - return val; - } - } // detail -} // sol - -#endif // SOL_TRAITS_HPP diff --git a/3rdparty/sol2/sol/tuple.hpp b/3rdparty/sol2/sol/tuple.hpp deleted file mode 100644 index 07a6d493de1..00000000000 --- a/3rdparty/sol2/sol/tuple.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TUPLE_HPP -#define SOL_TUPLE_HPP - -#include <tuple> -#include <cstddef> - -namespace sol { - namespace detail { - using swallow = std::initializer_list<int>; - } // detail - - template<typename... Args> - struct types { typedef std::make_index_sequence<sizeof...(Args)> indices; static constexpr std::size_t size() { return sizeof...(Args); } }; - namespace meta { - namespace detail { - template<typename... Args> - struct tuple_types_ { typedef types<Args...> type; }; - - template<typename... Args> - struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; }; - } // detail - - template<typename T> - using unqualified = std::remove_cv<std::remove_reference_t<T>>; - - template<typename T> - using unqualified_t = typename unqualified<T>::type; - - template<typename... Args> - using tuple_types = typename detail::tuple_types_<Args...>::type; - - template<typename Arg> - struct pop_front_type; - - template<typename Arg> - using pop_front_type_t = typename pop_front_type<Arg>::type; - - template<typename... Args> - struct pop_front_type<types<Args...>> { typedef void front_type; typedef types<Args...> type; }; - - template<typename Arg, typename... Args> - struct pop_front_type<types<Arg, Args...>> { typedef Arg front_type; typedef types<Args...> type; }; - - template <std::size_t N, typename Tuple> - using tuple_element = std::tuple_element<N, unqualified_t<Tuple>>; - - template <std::size_t N, typename Tuple> - using tuple_element_t = std::tuple_element_t<N, unqualified_t<Tuple>>; - - template <std::size_t N, typename Tuple> - using unqualified_tuple_element = unqualified<tuple_element_t<N, Tuple>>; - - template <std::size_t N, typename Tuple> - using unqualified_tuple_element_t = unqualified_t<tuple_element_t<N, Tuple>>; - - } // meta -} // sol - -#endif // SOL_TUPLE_HPP diff --git a/3rdparty/sol2/sol/types.hpp b/3rdparty/sol2/sol/types.hpp deleted file mode 100644 index ca349a56d19..00000000000 --- a/3rdparty/sol2/sol/types.hpp +++ /dev/null @@ -1,806 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_TYPES_HPP -#define SOL_TYPES_HPP - -#include "optional.hpp" -#include "compatibility.hpp" -#include "traits.hpp" -#include "string_shim.hpp" -#include <array> -#include <string> - -namespace sol { - namespace detail { -#ifdef SOL_NO_EXCEPTIONS - template <lua_CFunction f> - int static_trampoline(lua_State* L) { - return f(L); - } - - template <typename Fx, typename... Args> - int trampoline(lua_State* L, Fx&& f, Args&&... args) { - return f(L, std::forward<Args>(args)...); - } - - inline int c_trampoline(lua_State* L, lua_CFunction f) { - return trampoline(L, f); - } -#else - template <lua_CFunction f> - int static_trampoline(lua_State* L) { - try { - return f(L); - } - catch (const char *s) { - lua_pushstring(L, s); - } - catch (const std::exception& e) { - lua_pushstring(L, e.what()); - } -#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) - catch (...) { - lua_pushstring(L, "caught (...) exception"); - } -#endif - return lua_error(L); - } - - template <typename Fx, typename... Args> - int trampoline(lua_State* L, Fx&& f, Args&&... args) { - try { - return f(L, std::forward<Args>(args)...); - } - catch (const char *s) { - lua_pushstring(L, s); - } - catch (const std::exception& e) { - lua_pushstring(L, e.what()); - } -#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) - catch (...) { - lua_pushstring(L, "caught (...) exception"); - } -#endif - return lua_error(L); - } - - inline int c_trampoline(lua_State* L, lua_CFunction f) { - return trampoline(L, f); - } -#endif // Exceptions vs. No Exceptions - - template <typename T> - struct unique_usertype {}; - - template <typename T> - struct implicit_wrapper { - T& item; - implicit_wrapper(T* item) : item(*item) {} - implicit_wrapper(T& item) : item(item) {} - operator T& () { - return item; - } - operator T* () { - return std::addressof(item); - } - }; - } // detail - - struct lua_nil_t {}; - const lua_nil_t lua_nil{}; - inline bool operator==(lua_nil_t, lua_nil_t) { return true; } - inline bool operator!=(lua_nil_t, lua_nil_t) { return false; } -#ifndef __OBJC__ - typedef lua_nil_t nil_t; - const nil_t nil{}; -#endif - - struct metatable_key_t {}; - const metatable_key_t metatable_key = {}; - - struct no_metatable_t {}; - const no_metatable_t no_metatable = {}; - - typedef std::remove_pointer_t<lua_CFunction> lua_r_CFunction; - - template <typename T> - struct unique_usertype_traits { - typedef T type; - typedef T actual_type; - static const bool value = false; - - template <typename U> - static bool is_null(U&&) { - return false; - } - - template <typename U> - static auto get(U&& value) { - return std::addressof(detail::deref(value)); - } - }; - - template <typename T> - struct unique_usertype_traits<std::shared_ptr<T>> { - typedef T type; - typedef std::shared_ptr<T> actual_type; - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - - template <typename T, typename D> - struct unique_usertype_traits<std::unique_ptr<T, D>> { - typedef T type; - typedef std::unique_ptr<T, D> actual_type; - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - - template <typename T> - struct non_null {}; - - template <typename... Args> - struct function_sig {}; - - struct upvalue_index { - int index; - upvalue_index(int idx) : index(lua_upvalueindex(idx)) {} - operator int() const { return index; } - }; - - struct raw_index { - int index; - raw_index(int i) : index(i) {} - operator int() const { return index; } - }; - - struct absolute_index { - int index; - absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {} - operator int() const { return index; } - }; - - struct ref_index { - int index; - ref_index(int idx) : index(idx) {} - operator int() const { return index; } - }; - - struct lightuserdata_value { - void* value; - lightuserdata_value(void* data) : value(data) {} - operator void*() const { return value; } - }; - - struct userdata_value { - void* value; - userdata_value(void* data) : value(data) {} - operator void*() const { return value; } - }; - - template <typename L> - struct light { - L* value; - - light(L& x) : value(std::addressof(x)) {} - light(L* x) : value(x) {} - light(void* x) : value(static_cast<L*>(x)) {} - operator L* () const { return value; } - operator L& () const { return *value; } - }; - - template <typename T> - auto make_light(T& l) { - typedef meta::unwrapped_t<std::remove_pointer_t<std::remove_pointer_t<T>>> L; - return light<L>(l); - } - - template <typename U> - struct user { - U value; - - user(U x) : value(std::move(x)) {} - operator U* () { return std::addressof(value); } - operator U& () { return value; } - operator const U& () const { return value; } - }; - - template <typename T> - auto make_user(T&& u) { - typedef meta::unwrapped_t<meta::unqualified_t<T>> U; - return user<U>(std::forward<T>(u)); - } - - template <typename T> - struct metatable_registry_key { - T key; - - metatable_registry_key(T key) : key(std::forward<T>(key)) {} - }; - - template <typename T> - auto meta_registry_key(T&& key) { - typedef meta::unqualified_t<T> K; - return metatable_registry_key<K>(std::forward<T>(key)); - } - - template <typename... Upvalues> - struct closure { - lua_CFunction c_function; - std::tuple<Upvalues...> upvalues; - closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward<Upvalues>(targetupvalues)...) {} - }; - - template <> - struct closure<> { - lua_CFunction c_function; - int upvalues; - closure(lua_CFunction f, int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) {} - }; - - typedef closure<> c_closure; - - template <typename... Args> - closure<Args...> make_closure(lua_CFunction f, Args&&... args) { - return closure<Args...>(f, std::forward<Args>(args)...); - } - - template <typename Sig, typename... Ps> - struct function_arguments { - std::tuple<Ps...> arguments; - template <typename Arg, typename... Args, meta::disable<std::is_same<meta::unqualified_t<Arg>, function_arguments>> = meta::enabler> - function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward<Arg>(arg), std::forward<Args>(args)...) {} - }; - - template <typename Sig = function_sig<>, typename... Args> - auto as_function(Args&&... args) { - return function_arguments<Sig, std::decay_t<Args>...>(std::forward<Args>(args)...); - } - - template <typename Sig = function_sig<>, typename... Args> - auto as_function_reference(Args&&... args) { - return function_arguments<Sig, Args...>(std::forward<Args>(args)...); - } - - template <typename T> - struct as_table_t { - T source; - template <typename... Args> - as_table_t(Args&&... args) : source(std::forward<Args>(args)...) {} - - operator std::add_lvalue_reference_t<T> () { - return source; - } - }; - - template <typename T> - as_table_t<T> as_table(T&& container) { - return as_table_t<T>(std::forward<T>(container)); - } - - struct this_state { - lua_State* L; - operator lua_State* () const { - return L; - } - lua_State* operator-> () const { - return L; - } - }; - - enum class call_syntax { - dot = 0, - colon = 1 - }; - - enum class call_status : int { - ok = LUA_OK, - yielded = LUA_YIELD, - runtime = LUA_ERRRUN, - memory = LUA_ERRMEM, - handler = LUA_ERRERR, - gc = LUA_ERRGCMM - }; - - enum class thread_status : int { - ok = LUA_OK, - yielded = LUA_YIELD, - runtime = LUA_ERRRUN, - memory = LUA_ERRMEM, - gc = LUA_ERRGCMM, - handler = LUA_ERRERR, - dead = -1, - }; - - enum class load_status : int { - ok = LUA_OK, - syntax = LUA_ERRSYNTAX, - memory = LUA_ERRMEM, - gc = LUA_ERRGCMM, - file = LUA_ERRFILE, - }; - - enum class type : int { - none = LUA_TNONE, - lua_nil = LUA_TNIL, -#ifndef __OBJC__ - nil = lua_nil, -#endif // Objective C++ Keyword - string = LUA_TSTRING, - number = LUA_TNUMBER, - thread = LUA_TTHREAD, - boolean = LUA_TBOOLEAN, - function = LUA_TFUNCTION, - userdata = LUA_TUSERDATA, - lightuserdata = LUA_TLIGHTUSERDATA, - table = LUA_TTABLE, - poly = none | lua_nil | string | number | thread | - table | boolean | function | userdata | lightuserdata - }; - - enum class meta_function { - construct, - index, - new_index, - mode, - call, - call_function = call, - metatable, - to_string, - length, - unary_minus, - addition, - subtraction, - multiplication, - division, - modulus, - power_of, - involution = power_of, - concatenation, - equal_to, - less_than, - less_than_or_equal_to, - garbage_collect, - floor_division, - bitwise_left_shift, - bitwise_right_shift, - bitwise_not, - bitwise_and, - bitwise_or, - bitwise_xor, - pairs, - next - }; - - typedef meta_function meta_method; - - const std::array<std::string, 2> meta_variable_names = { { - "__index", - "__newindex", - } }; - - const std::array<std::string, 29> meta_function_names = { { - "new", - "__index", - "__newindex", - "__mode", - "__call", - "__mt", - "__tostring", - "__len", - "__unm", - "__add", - "__sub", - "__mul", - "__div", - "__mod", - "__pow", - "__concat", - "__eq", - "__lt", - "__le", - "__gc", - - "__idiv", - "__shl", - "__shr", - "__bnot", - "__band", - "__bor", - "__bxor", - - "__pairs", - "__next" - } }; - - inline const std::string& name_of(meta_function mf) { - return meta_function_names[static_cast<int>(mf)]; - } - - inline type type_of(lua_State* L, int index) { - return static_cast<type>(lua_type(L, index)); - } - - inline int type_panic(lua_State* L, int index, type expected, type actual) { - return luaL_error(L, "stack index %d, expected %s, received %s", index, - expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)), - expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(actual)) - ); - } - - // Specify this function as the handler for lua::check if you know there's nothing wrong - inline int no_panic(lua_State*, int, type, type) noexcept { - return 0; - } - - inline void type_error(lua_State* L, int expected, int actual) { - luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); - } - - inline void type_error(lua_State* L, type expected, type actual) { - type_error(L, static_cast<int>(expected), static_cast<int>(actual)); - } - - inline void type_assert(lua_State* L, int index, type expected, type actual) { - if (expected != type::poly && expected != actual) { - type_panic(L, index, expected, actual); - } - } - - inline void type_assert(lua_State* L, int index, type expected) { - type actual = type_of(L, index); - type_assert(L, index, expected, actual); - } - - inline std::string type_name(lua_State* L, type t) { - return lua_typename(L, static_cast<int>(t)); - } - - class reference; - class stack_reference; - template <typename Table, typename Key> - struct proxy; - template<typename T> - class usertype; - template <bool, typename T> - class basic_table_core; - template <bool b> - using table_core = basic_table_core<b, reference>; - template <bool b> - using stack_table_core = basic_table_core<b, stack_reference>; - typedef table_core<false> table; - typedef table_core<true> global_table; - typedef stack_table_core<false> stack_table; - typedef stack_table_core<true> stack_global_table; - template <typename T> - class basic_function; - template <typename T> - class basic_protected_function; - using function = basic_function<reference>; - using protected_function = basic_protected_function<reference>; - using stack_function = basic_function<stack_reference>; - using stack_protected_function = basic_protected_function<stack_reference>; - template <typename base_t> - class basic_object; - template <typename base_t> - class basic_userdata; - template <typename base_t> - class basic_lightuserdata; - struct variadic_args; - using object = basic_object<reference>; - using stack_object = basic_object<stack_reference>; - using userdata = basic_userdata<reference>; - using stack_userdata = basic_userdata<stack_reference>; - using lightuserdata = basic_lightuserdata<reference>; - using stack_lightuserdata = basic_lightuserdata<stack_reference>; - class coroutine; - class thread; - struct variadic_args; - struct this_state; - - namespace detail { - template <typename T, typename = void> - struct lua_type_of : std::integral_constant<type, type::userdata> {}; - - template <> - struct lua_type_of<std::string> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<std::wstring> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<std::u16string> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<std::u32string> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<char[N]> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<wchar_t[N]> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<char16_t[N]> : std::integral_constant<type, type::string> {}; - - template <std::size_t N> - struct lua_type_of<char32_t[N]> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<char> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<wchar_t> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<char16_t> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<char32_t> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<const char*> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<const char16_t*> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<const char32_t*> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<string_detail::string_shim> : std::integral_constant<type, type::string> {}; - - template <> - struct lua_type_of<bool> : std::integral_constant<type, type::boolean> {}; - - template <> - struct lua_type_of<lua_nil_t> : std::integral_constant<type, type::lua_nil> { }; - - template <> - struct lua_type_of<nullopt_t> : std::integral_constant<type, type::lua_nil> { }; - - template <> - struct lua_type_of<std::nullptr_t> : std::integral_constant<type, type::lua_nil> { }; - - template <> - struct lua_type_of<sol::error> : std::integral_constant<type, type::string> { }; - - template <bool b, typename Base> - struct lua_type_of<basic_table_core<b, Base>> : std::integral_constant<type, type::table> { }; - - template <> - struct lua_type_of<reference> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<stack_reference> : std::integral_constant<type, type::poly> {}; - - template <typename Base> - struct lua_type_of<basic_object<Base>> : std::integral_constant<type, type::poly> {}; - - template <typename... Args> - struct lua_type_of<std::tuple<Args...>> : std::integral_constant<type, type::poly> {}; - - template <typename A, typename B> - struct lua_type_of<std::pair<A, B>> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<void*> : std::integral_constant<type, type::lightuserdata> {}; - - template <> - struct lua_type_of<lightuserdata_value> : std::integral_constant<type, type::lightuserdata> {}; - - template <> - struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {}; - - template <typename T> - struct lua_type_of<light<T>> : std::integral_constant<type, type::lightuserdata> {}; - - template <typename T> - struct lua_type_of<user<T>> : std::integral_constant<type, type::userdata> {}; - - template <typename Base> - struct lua_type_of<basic_lightuserdata<Base>> : std::integral_constant<type, type::lightuserdata> {}; - - template <typename Base> - struct lua_type_of<basic_userdata<Base>> : std::integral_constant<type, type::userdata> {}; - - template <> - struct lua_type_of<lua_CFunction> : std::integral_constant<type, type::function> {}; - - template <> - struct lua_type_of<std::remove_pointer_t<lua_CFunction>> : std::integral_constant<type, type::function> {}; - - template <typename Base> - struct lua_type_of<basic_function<Base>> : std::integral_constant<type, type::function> {}; - - template <typename Base> - struct lua_type_of<basic_protected_function<Base>> : std::integral_constant<type, type::function> {}; - - template <> - struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {}; - - template <> - struct lua_type_of<thread> : std::integral_constant<type, type::thread> {}; - - template <typename Signature> - struct lua_type_of<std::function<Signature>> : std::integral_constant<type, type::function> {}; - - template <typename T> - struct lua_type_of<optional<T>> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<variadic_args> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<this_state> : std::integral_constant<type, type::poly> {}; - - template <> - struct lua_type_of<type> : std::integral_constant<type, type::poly> {}; - - template <typename T> - struct lua_type_of<T*> : std::integral_constant<type, type::userdata> {}; - - template <typename T> - struct lua_type_of<T, std::enable_if_t<std::is_arithmetic<T>::value>> : std::integral_constant<type, type::number> {}; - - template <typename T> - struct lua_type_of<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<type, type::number> {}; - - template <typename T, typename C = void> - struct is_container : std::false_type {}; - - template <typename T> - struct is_container<T, std::enable_if_t<meta::has_begin_end<meta::unqualified_t<T>>::value>> : std::true_type {}; - - template <> - struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {}; - - template <typename C, C v, template <typename...> class V, typename... Args> - struct accumulate : std::integral_constant<C, v> {}; - - template <typename C, C v, template <typename...> class V, typename T, typename... Args> - struct accumulate<C, v, V, T, Args...> : accumulate<C, v + V<T>::value, V, Args...> {}; - } // detail - - template <typename T> - struct is_unique_usertype : std::integral_constant<bool, unique_usertype_traits<T>::value> {}; - - template <typename T> - struct lua_type_of : detail::lua_type_of<T> {}; - - template <typename T> - struct lua_size : std::integral_constant<int, 1> { }; - - template <typename A, typename B> - struct lua_size<std::pair<A, B>> : std::integral_constant<int, lua_size<A>::value + lua_size<B>::value> { }; - - template <typename... Args> - struct lua_size<std::tuple<Args...>> : std::integral_constant<int, detail::accumulate<int, 0, lua_size, Args...>::value> { }; - - template <typename T> - struct is_lua_primitive : std::integral_constant<bool, - type::userdata != lua_type_of<meta::unqualified_t<T>>::value - || (lua_size<T>::value > 1) - || std::is_base_of<reference, meta::unqualified_t<T>>::value - || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value - || meta::is_specialization_of<std::tuple, meta::unqualified_t<T>>::value - || meta::is_specialization_of<std::pair, meta::unqualified_t<T>>::value - > { }; - - template <typename T> - struct is_lua_reference : std::integral_constant<bool, - std::is_base_of<reference, meta::unqualified_t<T>>::value - || std::is_base_of<stack_reference, meta::unqualified_t<T>>::value - || meta::is_specialization_of<proxy, meta::unqualified_t<T>>::value - > { }; - - template <typename T> - struct is_lua_primitive<T*> : std::true_type {}; - template <typename T> - struct is_lua_primitive<std::reference_wrapper<T>> : std::true_type { }; - template <typename T> - struct is_lua_primitive<user<T>> : std::true_type { }; - template <typename T> - struct is_lua_primitive<light<T>> : is_lua_primitive<T*> { }; - template <typename T> - struct is_lua_primitive<optional<T>> : std::true_type {}; - template <> - struct is_lua_primitive<userdata_value> : std::true_type {}; - template <> - struct is_lua_primitive<lightuserdata_value> : std::true_type {}; - template <typename T> - struct is_lua_primitive<non_null<T>> : is_lua_primitive<T*> {}; - - template <typename T> - struct is_proxy_primitive : is_lua_primitive<T> { }; - - template <typename T> - struct is_transparent_argument : std::false_type {}; - - template <> - struct is_transparent_argument<this_state> : std::true_type {}; - - template <> - struct is_transparent_argument<variadic_args> : std::true_type {}; - - template <typename T> - struct is_variadic_arguments : std::is_same<T, variadic_args> {}; - - template <typename Signature> - struct lua_bind_traits : meta::bind_traits<Signature> { - private: - typedef meta::bind_traits<Signature> base_t; - public: - typedef std::integral_constant<bool, meta::count_for<is_transparent_argument, typename base_t::args_list>::value != 0> runtime_variadics_t; - static const std::size_t true_arity = base_t::arity; - static const std::size_t arity = base_t::arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; - static const std::size_t true_free_arity = base_t::free_arity; - static const std::size_t free_arity = base_t::free_arity - meta::count_for<is_transparent_argument, typename base_t::args_list>::value; - }; - - template <typename T> - struct is_table : std::false_type {}; - template <bool x, typename T> - struct is_table<basic_table_core<x, T>> : std::true_type {}; - - template <typename T> - struct is_function : std::false_type {}; - template <typename T> - struct is_function<basic_function<T>> : std::true_type {}; - template <typename T> - struct is_function<basic_protected_function<T>> : std::true_type {}; - - template <typename T> - struct is_lightuserdata : std::false_type {}; - template <typename T> - struct is_lightuserdata<basic_lightuserdata<T>> : std::true_type {}; - - template <typename T> - struct is_userdata : std::false_type {}; - template <typename T> - struct is_userdata<basic_userdata<T>> : std::true_type {}; - - template <typename T> - struct is_container : detail::is_container<T>{}; - - template<typename T> - inline type type_of() { - return lua_type_of<meta::unqualified_t<T>>::value; - } -} // sol - -#endif // SOL_TYPES_HPP diff --git a/3rdparty/sol2/sol/userdata.hpp b/3rdparty/sol2/sol/userdata.hpp deleted file mode 100644 index 382f89b17da..00000000000 --- a/3rdparty/sol2/sol/userdata.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_USERDATA_HPP -#define SOL_USERDATA_HPP - -#include "reference.hpp" - -namespace sol { - template <typename base_t> - class basic_userdata : public base_t { - public: - basic_userdata() noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_userdata>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_userdata(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_userdata<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - type_assert(base_t::lua_state(), -1, type::userdata); - } -#endif // Safety - } - basic_userdata(const basic_userdata&) = default; - basic_userdata(basic_userdata&&) = default; - basic_userdata& operator=(const basic_userdata&) = default; - basic_userdata& operator=(basic_userdata&&) = default; - basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {} - basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} - basic_userdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::userdata); -#endif // Safety - } - basic_userdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::userdata); -#endif // Safety - } - }; - - template <typename base_t> - class basic_lightuserdata : public base_t { - public: - basic_lightuserdata() noexcept = default; - template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_lightuserdata>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> - basic_lightuserdata(T&& r) noexcept : base_t(std::forward<T>(r)) { -#ifdef SOL_CHECK_ARGUMENTS - if (!is_userdata<meta::unqualified_t<T>>::value) { - auto pp = stack::push_pop(*this); - type_assert(base_t::lua_state(), -1, type::lightuserdata); - } -#endif // Safety - } - basic_lightuserdata(const basic_lightuserdata&) = default; - basic_lightuserdata(basic_lightuserdata&&) = default; - basic_lightuserdata& operator=(const basic_lightuserdata&) = default; - basic_lightuserdata& operator=(basic_lightuserdata&&) = default; - basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} - basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} - template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<std::is_same<T, ref_index>>> = meta::enabler> - basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} - basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::lightuserdata); -#endif // Safety - } - basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::lightuserdata); -#endif // Safety - } - }; - -} // sol - -#endif // SOL_USERDATA_HPP diff --git a/3rdparty/sol2/sol/usertype.hpp b/3rdparty/sol2/sol/usertype.hpp deleted file mode 100644 index 7fae5119c6d..00000000000 --- a/3rdparty/sol2/sol/usertype.hpp +++ /dev/null @@ -1,97 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_USERTYPE_HPP -#define SOL_USERTYPE_HPP - -#include "stack.hpp" -#include "usertype_metatable.hpp" -#include "simple_usertype_metatable.hpp" -#include "container_usertype_metatable.hpp" -#include <memory> - -namespace sol { - - template<typename T> - class usertype { - private: - std::unique_ptr<usertype_detail::registrar, detail::deleter> metatableregister; - - template<typename... Args> - usertype(usertype_detail::verified_tag, Args&&... args) : metatableregister(detail::make_unique_deleter<usertype_metatable<T, std::make_index_sequence<sizeof...(Args) / 2>, Args...>, detail::deleter>(std::forward<Args>(args)...)) {} - - template<typename... Args> - usertype(usertype_detail::add_destructor_tag, Args&&... args) : usertype(usertype_detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) {} - - template<typename... Args> - usertype(usertype_detail::check_destructor_tag, Args&&... args) : usertype(meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward<Args>(args)...) {} - - public: - - template<typename... Args> - usertype(Args&&... args) : usertype(meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward<Args>(args)...) {} - - template<typename... Args, typename... CArgs> - usertype(constructors<CArgs...> constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - template<typename... Args, typename... Fxs> - usertype(constructor_wrapper<Fxs...> constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {} - - template<typename... Args> - usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter<simple_usertype_metatable<T>, detail::deleter>(L, std::forward<Args>(args)...)) {} - - usertype_detail::registrar* registrar_data() { - return metatableregister.get(); - } - - int push(lua_State* L) { - return metatableregister->push_um(L); - } - }; - - template<typename T> - class simple_usertype : public usertype<T> { - private: - typedef usertype<T> base_t; - lua_State* state; - - public: - template<typename... Args> - simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward<Args>(args)...), state(L) {} - - template <typename N, typename F> - void set(N&& n, F&& f) { - auto meta = static_cast<simple_usertype_metatable<T>*>(base_t::registrar_data()); - meta->add(state, n, f); - } - }; - - namespace stack { - template<typename T> - struct pusher<usertype<T>> { - static int push(lua_State* L, usertype<T>& user) { - return user.push(L); - } - }; - } // stack -} // sol - -#endif // SOL_USERTYPE_HPP diff --git a/3rdparty/sol2/sol/usertype_metatable.hpp b/3rdparty/sol2/sol/usertype_metatable.hpp deleted file mode 100644 index 37693227a75..00000000000 --- a/3rdparty/sol2/sol/usertype_metatable.hpp +++ /dev/null @@ -1,609 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_USERTYPE_METATABLE_HPP -#define SOL_USERTYPE_METATABLE_HPP - -#include "wrapper.hpp" -#include "call.hpp" -#include "stack.hpp" -#include "types.hpp" -#include "stack_reference.hpp" -#include "usertype_traits.hpp" -#include "inheritance.hpp" -#include "raii.hpp" -#include "deprecate.hpp" -#include <unordered_map> -#include <cstdio> - -namespace sol { - namespace usertype_detail { - struct no_comp { - template <typename A, typename B> - bool operator()(A&&, B&&) const { - return false; - } - }; - - typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); - typedef int(*member_search)(lua_State*, void*); - - struct find_call_pair { - member_search first; - member_search second; - - find_call_pair(member_search first, member_search second) : first(first), second(second) {} - }; - - inline bool is_indexer(string_detail::string_shim s) { - return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); - } - - inline bool is_indexer(meta_function mf) { - return mf == meta_function::index || mf == meta_function::new_index; - } - - inline bool is_indexer(call_construction) { - return false; - } - - inline bool is_indexer(base_classes_tag) { - return false; - } - - inline auto make_shim(string_detail::string_shim s) { - return s; - } - - inline auto make_shim(call_construction) { - return string_detail::string_shim(name_of(meta_function::call_function)); - } - - inline auto make_shim(meta_function mf) { - return string_detail::string_shim(name_of(mf)); - } - - inline auto make_shim(base_classes_tag) { - return string_detail::string_shim(detail::base_class_cast_key()); - } - - template <typename Arg> - inline std::string make_string(Arg&& arg) { - string_detail::string_shim s = make_shim(arg); - return std::string(s.c_str(), s.size()); - } - - template <typename N> - inline luaL_Reg make_reg(N&& n, lua_CFunction f) { - luaL_Reg l{ make_shim(std::forward<N>(n)).c_str(), f }; - return l; - } - - struct registrar { - virtual int push_um(lua_State* L) = 0; - virtual ~registrar() {} - }; - - template <bool is_index> - inline int indexing_fail(lua_State* L) { - auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2); - string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); - if (is_index) - return luaL_error(L, "sol: attempt to index (get) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); - else - return luaL_error(L, "sol: attempt to index (set) lua_nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); - } - - template <bool is_index, typename Base> - static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { - if (found) - return; - const char* metakey = &usertype_traits<Base>::metatable()[0]; - const char* gcmetakey = &usertype_traits<Base>::gc_table()[0]; - const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); - - luaL_getmetatable(L, metakey); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 1); - return; - } - - stack::get_field(L, basewalkkey); - if (type_of(L, -1) == type::lua_nil) { - lua_pop(L, 2); - return; - } - lua_CFunction basewalkfunc = stack::pop<lua_CFunction>(L); - lua_pop(L, 1); - - stack::get_field<true>(L, gcmetakey); - int value = basewalkfunc(L); - if (value > -1) { - found = true; - ret = value; - } - } - - template <bool is_index, typename... Bases> - static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { - (void)L; - (void)found; - (void)ret; - (void)accessor; - (void)detail::swallow{ 0, (walk_single_base<is_index, Bases>(L, found, ret, accessor), 0)... }; - } - - template <typename T, typename Op> - inline int operator_wrap(lua_State* L) { - auto maybel = stack::check_get<T>(L, 1); - if (maybel) { - auto mayber = stack::check_get<T>(L, 2); - if (mayber) { - auto& l = *maybel; - auto& r = *mayber; - if (std::is_same<no_comp, Op>::value) { - return stack::push(L, detail::ptr(l) == detail::ptr(r)); - } - else { - Op op; - return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); - } - } - } - return stack::push(L, false); - } - - template <typename T, typename Op, typename Supports, typename Regs, meta::enable<Supports> = meta::enabler> - inline void make_reg_op(Regs& l, int& index, const char* name) { - l[index] = { name, &operator_wrap<T, Op> }; - ++index; - } - - template <typename T, typename Op, typename Supports, typename Regs, meta::disable<Supports> = meta::enabler> - inline void make_reg_op(Regs&, int&, const char*) { - // Do nothing if there's no support - } - - struct add_destructor_tag {}; - struct check_destructor_tag {}; - struct verified_tag {} const verified{}; - - template <typename T> - struct is_non_factory_constructor : std::false_type {}; - - template <typename... Args> - struct is_non_factory_constructor<constructors<Args...>> : std::true_type {}; - - template <typename... Args> - struct is_non_factory_constructor<constructor_wrapper<Args...>> : std::true_type {}; - - template <> - struct is_non_factory_constructor<no_construction> : std::true_type {}; - - template <typename T> - struct is_constructor : is_non_factory_constructor<T> {}; - - template <typename... Args> - struct is_constructor<factory_wrapper<Args...>> : std::true_type {}; - - template <typename... Args> - using has_constructor = meta::any<is_constructor<meta::unqualified_t<Args>>...>; - - template <typename T> - struct is_destructor : std::false_type {}; - - template <typename Fx> - struct is_destructor<destructor_wrapper<Fx>> : std::true_type {}; - - template <typename... Args> - using has_destructor = meta::any<is_destructor<meta::unqualified_t<Args>>...>; - - } // usertype_detail - - template <typename T> - struct clean_type { - typedef std::conditional_t<std::is_array<meta::unqualified_t<T>>::value, T&, std::decay_t<T>> type; - }; - - template <typename T> - using clean_type_t = typename clean_type<T>::type; - - template <typename T, typename IndexSequence, typename... Tn> - struct usertype_metatable : usertype_detail::registrar {}; - - template <typename T, std::size_t... I, typename... Tn> - struct usertype_metatable<T, std::index_sequence<I...>, Tn...> : usertype_detail::registrar { - typedef std::make_index_sequence<sizeof...(I) * 2> indices; - typedef std::index_sequence<I...> half_indices; - typedef std::array<luaL_Reg, sizeof...(Tn) / 2 + 1 + 3> regs_t; - typedef std::tuple<Tn...> RawTuple; - typedef std::tuple<clean_type_t<Tn> ...> Tuple; - template <std::size_t Idx> - struct check_binding : is_variable_binding<meta::unqualified_tuple_element_t<Idx, Tuple>> {}; - typedef std::unordered_map<std::string, usertype_detail::find_call_pair> mapping_t; - Tuple functions; - mapping_t mapping; - lua_CFunction indexfunc; - lua_CFunction newindexfunc; - lua_CFunction destructfunc; - lua_CFunction callconstructfunc; - lua_CFunction indexbase; - lua_CFunction newindexbase; - usertype_detail::base_walk indexbaseclasspropogation; - usertype_detail::base_walk newindexbaseclasspropogation; - void* baseclasscheck; - void* baseclasscast; - bool mustindex; - bool secondarymeta; - bool hasequals; - bool hasless; - bool haslessequals; - - template <std::size_t Idx, meta::enable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> - inline lua_CFunction make_func() { - return std::get<Idx + 1>(functions); - } - - template <std::size_t Idx, meta::disable<std::is_same<lua_CFunction, meta::unqualified_tuple_element<Idx + 1, RawTuple>>> = meta::enabler> - inline lua_CFunction make_func() { - return call<Idx + 1>; - } - - static bool contains_variable() { - typedef meta::any<check_binding<(I * 2 + 1)>...> has_variables; - return has_variables::value; - } - - bool contains_index() const { - bool idx = false; - (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get<I * 2>(functions))), 0) ... }; - return idx; - } - - int finish_regs(regs_t& l, int& index) { - if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); - usertype_detail::make_reg_op<T, std::less<>, meta::supports_op_less<T>>(l, index, name); - } - if (!haslessequals) { - const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); - usertype_detail::make_reg_op<T, std::less_equal<>, meta::supports_op_less_equal<T>>(l, index, name); - } - if (!hasequals) { - const char* name = name_of(meta_function::equal_to).c_str(); - usertype_detail::make_reg_op<T, std::conditional_t<meta::supports_op_equal<T>::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); - } - if (destructfunc != nullptr) { - l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; - ++index; - } - return index; - } - - template <std::size_t Idx, typename F> - void make_regs(regs_t&, int&, call_construction, F&&) { - callconstructfunc = call<Idx + 1>; - secondarymeta = true; - } - - template <std::size_t, typename... Bases> - void make_regs(regs_t&, int&, base_classes_tag, bases<Bases...>) { - if (sizeof...(Bases) < 1) { - return; - } - mustindex = true; - (void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... }; - - static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); - static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); - baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check; - baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast; - indexbaseclasspropogation = usertype_detail::walk_all_bases<true, Bases...>; - newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>; - } - - template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>> - void make_regs(regs_t& l, int& index, N&& n, F&&) { - if (is_variable_binding<meta::unqualified_t<F>>::value) { - return; - } - luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>()); - // Returnable scope - // That would be a neat keyword for C++ - // returnable { ... }; - if (reg.name == name_of(meta_function::equal_to)) { - hasequals = true; - } - if (reg.name == name_of(meta_function::less_than)) { - hasless = true; - } - if (reg.name == name_of(meta_function::less_than_or_equal_to)) { - haslessequals = true; - } - if (reg.name == name_of(meta_function::garbage_collect)) { - destructfunc = reg.func; - return; - } - else if (reg.name == name_of(meta_function::index)) { - indexfunc = reg.func; - mustindex = true; - return; - } - else if (reg.name == name_of(meta_function::new_index)) { - newindexfunc = reg.func; - mustindex = true; - return; - } - l[index] = reg; - ++index; - } - - template <typename... Args, typename = std::enable_if_t<sizeof...(Args) == sizeof...(Tn)>> - usertype_metatable(Args&&... args) : functions(std::forward<Args>(args)...), - mapping(), - indexfunc(usertype_detail::indexing_fail<true>), newindexfunc(usertype_detail::indexing_fail<false>), - destructfunc(nullptr), callconstructfunc(nullptr), - indexbase(&core_indexing_call<true>), newindexbase(&core_indexing_call<false>), - indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(usertype_detail::walk_all_bases<false>), - baseclasscheck(nullptr), baseclasscast(nullptr), - mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()), - hasequals(false), hasless(false), haslessequals(false) { - std::initializer_list<typename mapping_t::value_type> ilist{ { - std::pair<std::string, usertype_detail::find_call_pair>( - usertype_detail::make_string(std::get<I * 2>(functions)), - usertype_detail::find_call_pair(&usertype_metatable::real_find_call<I * 2, I * 2 + 1, false>, - &usertype_metatable::real_find_call<I * 2, I * 2 + 1, true>) - ) - }... }; - mapping.insert(ilist); - } - - template <std::size_t I0, std::size_t I1, bool is_index> - static int real_find_call(lua_State* L, void* um) { - auto& f = *static_cast<usertype_metatable*>(um); - if (is_variable_binding<decltype(std::get<I1>(f.functions))>::value) { - return real_call_with<I1, is_index, true>(L, f); - } - return stack::push(L, c_closure(call<I1, is_index>, stack::push(L, light<usertype_metatable>(f)))); - } - - template <bool is_index, bool toplevel = false> - static int core_indexing_call(lua_State* L) { - usertype_metatable& f = toplevel ? stack::get<light<usertype_metatable>>(L, upvalue_index(1)) : stack::pop<light<usertype_metatable>>(L); - static const int keyidx = -2 + static_cast<int>(is_index); - if (toplevel && stack::get<type>(L, keyidx) != type::string) { - return is_index ? f.indexfunc(L) : f.newindexfunc(L); - } - std::string name = stack::get<std::string>(L, keyidx); - auto memberit = f.mapping.find(name); - if (memberit != f.mapping.cend()) { - auto& member = is_index ? memberit->second.second : memberit->second.first; - return (member)(L, static_cast<void*>(&f)); - } - string_detail::string_shim accessor = name; - int ret = 0; - bool found = false; - // Otherwise, we need to do propagating calls through the bases - if (is_index) - f.indexbaseclasspropogation(L, found, ret, accessor); - else - f.newindexbaseclasspropogation(L, found, ret, accessor); - if (found) { - return ret; - } - return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; - } - - static int real_index_call(lua_State* L) { - return core_indexing_call<true, true>(L); - } - - static int real_new_index_call(lua_State* L) { - return core_indexing_call<false, true>(L); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int real_call(lua_State* L) { - usertype_metatable& f = stack::get<light<usertype_metatable>>(L, upvalue_index(1)); - return real_call_with<Idx, is_index, is_variable>(L, f); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int real_call_with(lua_State* L, usertype_metatable& um) { - typedef meta::unqualified_tuple_element_t<Idx - 1, Tuple> K; - typedef meta::unqualified_tuple_element_t<Idx, Tuple> F; - static const int boost = - !usertype_detail::is_non_factory_constructor<F>::value - && std::is_same<K, call_construction>::value ? - 1 : 0; - auto& f = std::get<Idx>(um.functions); - return call_detail::call_wrapped<T, is_index, is_variable, boost>(L, f); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int call(lua_State* L) { - return detail::static_trampoline<(&real_call<Idx, is_index, is_variable>)>(L); - } - - template <std::size_t Idx, bool is_index = true, bool is_variable = false> - static int call_with(lua_State* L) { - return detail::static_trampoline<(&real_call_with<Idx, is_index, is_variable>)>(L); - } - - static int index_call(lua_State* L) { - return detail::static_trampoline<(&real_index_call)>(L); - } - - static int new_index_call(lua_State* L) { - return detail::static_trampoline<(&real_new_index_call)>(L); - } - - virtual int push_um(lua_State* L) override { - return stack::push(L, std::move(*this)); - } - - ~usertype_metatable() override { - - } - }; - - namespace stack { - - template <typename T, std::size_t... I, typename... Args> - struct pusher<usertype_metatable<T, std::index_sequence<I...>, Args...>> { - typedef usertype_metatable<T, std::index_sequence<I...>, Args...> umt_t; - typedef typename umt_t::regs_t regs_t; - - static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { - // ensure some sort of uniqueness - static int uniqueness = 0; - std::string uniquegcmetakey = usertype_traits<T>::user_gc_metatable(); - // std::to_string doesn't exist in android still, with NDK, so this bullshit - // is necessary - // thanks, Android :v - int appended = snprintf(nullptr, 0, "%d", uniqueness); - std::size_t insertionpoint = uniquegcmetakey.length() - 1; - uniquegcmetakey.append(appended, '\0'); - char* uniquetarget = &uniquegcmetakey[insertionpoint]; - snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); - ++uniqueness; - - const char* gcmetakey = &usertype_traits<T>::gc_table()[0]; - // Make sure userdata's memory is properly in lua first, - // otherwise all the light userdata we make later will become invalid - stack::push<user<umt_t>>(L, metatable_key, uniquegcmetakey, std::move(umx)); - // Create the top level thing that will act as our deleter later on - stack_reference umt(L, -1); - stack::set_field<true>(L, gcmetakey, umt); - umt.pop(); - - stack::get_field<true>(L, gcmetakey); - return stack::pop<light<umt_t>>(L); - } - - static int push(lua_State* L, umt_t&& umx) { - - umt_t& um = make_cleanup(L, std::move(umx)); - regs_t value_table{ {} }; - int lastreg = 0; - (void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... }; - um.finish_regs(value_table, lastreg); - value_table[lastreg] = { nullptr, nullptr }; - regs_t ref_table = value_table; - regs_t unique_table = value_table; - bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; - if (hasdestructor) { - ref_table[lastreg - 1] = { nullptr, nullptr }; - unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct<T> }; - } - - // Now use um - const bool& mustindex = um.mustindex; - for (std::size_t i = 0; i < 3; ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - luaL_Reg* metaregs = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits<T*>::metatable()[0]; - metaregs = ref_table.data(); - break; - case 1: - metakey = &usertype_traits<detail::unique_usertype<T>>::metatable()[0]; - metaregs = unique_table.data(); - break; - case 2: - default: - metakey = &usertype_traits<T>::metatable()[0]; - metaregs = value_table.data(); - break; - } - luaL_newmetatable(L, metakey); - stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, metaregs, 1); - - if (um.baseclasscheck != nullptr) { - stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); - } - if (um.baseclasscast != nullptr) { - stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); - } - - stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um)), t.stack_index()); - stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um)), t.stack_index()); - - if (mustindex) { - // Basic index pushing: specialize - // index and newindex to give variables and stuff - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), t.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), t.stack_index()); - } - else { - // If there's only functions, we can use the fast index version - stack::set_field(L, meta_function::index, t, t.stack_index()); - } - // metatable on the metatable - // for call constructor purposes and such - lua_createtable(L, 0, 3); - stack_reference metabehind(L, -1); - if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - // We want to just leave the table - // in the registry only, otherwise we return it - t.pop(); - } - - // Now for the shim-table that actually gets assigned to the name - luaL_newmetatable(L, &usertype_traits<T>::user_metatable()[0]); - stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, value_table.data(), 1); - { - lua_createtable(L, 0, 3); - stack_reference metabehind(L, -1); - if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); - } - stack::set_field(L, metatable_key, metabehind, t.stack_index()); - metabehind.pop(); - } - - return 1; - } - }; - - } // stack - -} // sol - -#endif // SOL_USERTYPE_METATABLE_HPP diff --git a/3rdparty/sol2/sol/usertype_traits.hpp b/3rdparty/sol2/sol/usertype_traits.hpp deleted file mode 100644 index a10ff082529..00000000000 --- a/3rdparty/sol2/sol/usertype_traits.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_USERTYPE_TRAITS_HPP -#define SOL_USERTYPE_TRAITS_HPP - -#include "demangle.hpp" - -namespace sol { - - template<typename T> - struct usertype_traits { - static const std::string& name() { - static const std::string& n = detail::short_demangle<T>(); - return n; - } - static const std::string& qualified_name() { - static const std::string& q_n = detail::demangle<T>(); - return q_n; - } - static const std::string& metatable() { - static const std::string m = std::string("sol.").append(detail::demangle<T>()); - return m; - } - static const std::string& user_metatable() { - static const std::string u_m = std::string("sol.").append(detail::demangle<T>()).append(".user"); - return u_m; - } - static const std::string& user_gc_metatable() { - static const std::string u_g_m = std::string("sol.").append(detail::demangle<T>()).append(".user\xE2\x99\xBB"); - return u_g_m; - } - static const std::string& gc_table() { - static const std::string g_t = std::string("sol.").append(detail::demangle<T>()).append(".\xE2\x99\xBB"); - return g_t; - } - }; - -} - -#endif // SOL_USERTYPE_TRAITS_HPP diff --git a/3rdparty/sol2/sol/variadic_args.hpp b/3rdparty/sol2/sol/variadic_args.hpp deleted file mode 100644 index 38d258220e0..00000000000 --- a/3rdparty/sol2/sol/variadic_args.hpp +++ /dev/null @@ -1,243 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_VARIADIC_ARGS_HPP -#define SOL_VARIADIC_ARGS_HPP - -#include "stack.hpp" -#include "stack_proxy.hpp" -#include <limits> -#include <iterator> - -namespace sol { - template <bool is_const> - struct va_iterator : std::iterator<std::random_access_iterator_tag, std::conditional_t<is_const, const stack_proxy, stack_proxy>, std::ptrdiff_t, std::conditional_t<is_const, const stack_proxy*, stack_proxy*>, std::conditional_t<is_const, const stack_proxy, stack_proxy>> { - typedef std::iterator<std::random_access_iterator_tag, std::conditional_t<is_const, const stack_proxy, stack_proxy>, std::ptrdiff_t, std::conditional_t<is_const, const stack_proxy*, stack_proxy*>, std::conditional_t<is_const, const stack_proxy, stack_proxy>> base_t; - typedef typename base_t::reference reference; - typedef typename base_t::pointer pointer; - typedef typename base_t::value_type value_type; - typedef typename base_t::difference_type difference_type; - typedef typename base_t::iterator_category iterator_category; - lua_State* L; - int index; - int stacktop; - stack_proxy sp; - - va_iterator() : L(nullptr), index((std::numeric_limits<int>::max)()), stacktop((std::numeric_limits<int>::max)()) {} - va_iterator(lua_State* luastate, int idx, int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {} - - reference operator*() { - return stack_proxy(L, index); - } - - pointer operator->() { - sp = stack_proxy(L, index); - return &sp; - } - - va_iterator& operator++ () { - ++index; - return *this; - } - - va_iterator operator++ (int) { - auto r = *this; - this->operator ++(); - return r; - } - - va_iterator& operator-- () { - --index; - return *this; - } - - va_iterator operator-- (int) { - auto r = *this; - this->operator --(); - return r; - } - - va_iterator& operator+= (difference_type idx) { - index += static_cast<int>(idx); - return *this; - } - - va_iterator& operator-= (difference_type idx) { - index -= static_cast<int>(idx); - return *this; - } - - difference_type operator- (const va_iterator& r) const { - return index - r.index; - } - - va_iterator operator+ (difference_type idx) const { - va_iterator r = *this; - r += idx; - return r; - } - - reference operator[](difference_type idx) { - return stack_proxy(L, index + static_cast<int>(idx)); - } - - bool operator==(const va_iterator& r) const { - if (stacktop == (std::numeric_limits<int>::max)()) { - return r.index == r.stacktop; - } - else if (r.stacktop == (std::numeric_limits<int>::max)()) { - return index == stacktop; - } - return index == r.index; - } - - bool operator != (const va_iterator& r) const { - return !(this->operator==(r)); - } - - bool operator < (const va_iterator& r) const { - return index < r.index; - } - - bool operator > (const va_iterator& r) const { - return index > r.index; - } - - bool operator <= (const va_iterator& r) const { - return index <= r.index; - } - - bool operator >= (const va_iterator& r) const { - return index >= r.index; - } - }; - - template <bool is_const> - inline va_iterator<is_const> operator+(typename va_iterator<is_const>::difference_type n, const va_iterator<is_const>& r) { - return r + n; - } - - struct variadic_args { - private: - lua_State* L; - int index; - int stacktop; - - public: - typedef stack_proxy reference_type; - typedef stack_proxy value_type; - typedef stack_proxy* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::size_t size_type; - typedef va_iterator<false> iterator; - typedef va_iterator<true> const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - variadic_args() = default; - variadic_args(lua_State* luastate, int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {} - variadic_args(const variadic_args&) = default; - variadic_args& operator=(const variadic_args&) = default; - variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.stacktop = 0; - } - variadic_args& operator=(variadic_args&& o) { - L = o.L; - index = o.index; - stacktop = o.stacktop; - // Must be manual, otherwise destructor will screw us - // return count being 0 is enough to keep things clean - // but will be thorough - o.L = nullptr; - o.index = 0; - o.stacktop = 0; - return *this; - } - - iterator begin() { return iterator(L, index, stacktop + 1); } - iterator end() { return iterator(L, stacktop + 1, stacktop + 1); } - const_iterator begin() const { return const_iterator(L, index, stacktop + 1); } - const_iterator end() const { return const_iterator(L, stacktop + 1, stacktop + 1); } - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } - - reverse_iterator rbegin() { return std::reverse_iterator<iterator>(begin()); } - reverse_iterator rend() { return std::reverse_iterator<iterator>(end()); } - const_reverse_iterator rbegin() const { return std::reverse_iterator<const_iterator>(begin()); } - const_reverse_iterator rend() const { return std::reverse_iterator<const_iterator>(end()); } - const_reverse_iterator crbegin() const { return std::reverse_iterator<const_iterator>(cbegin()); } - const_reverse_iterator crend() const { return std::reverse_iterator<const_iterator>(cend()); } - - int push() const { - return push(L); - } - - int push(lua_State* target) const { - int pushcount = 0; - for (int i = index; i <= stacktop; ++i) { - lua_pushvalue(L, i); - pushcount += 1; - } - if (target != L) { - lua_xmove(L, target, pushcount); - } - return pushcount; - } - - template<typename T> - decltype(auto) get(difference_type start = 0) const { - return stack::get<T>(L, index + static_cast<int>(start)); - } - - stack_proxy operator[](difference_type start) const { - return stack_proxy(L, index + static_cast<int>(start)); - } - - lua_State* lua_state() const { return L; }; - int stack_index() const { return index; }; - int leftover_count() const { return stacktop - (index - 1); } - int top() const { return stacktop; } - }; - - namespace stack { - template <> - struct getter<variadic_args> { - static variadic_args get(lua_State* L, int index, record& tracking) { - tracking.last = 0; - return variadic_args(L, index); - } - }; - - template <> - struct pusher<variadic_args> { - static int push(lua_State* L, const variadic_args& ref) { - return ref.push(L); - } - }; - } // stack -} // sol - -#endif // SOL_VARIADIC_ARGS_HPP diff --git a/3rdparty/sol2/sol/wrapper.hpp b/3rdparty/sol2/sol/wrapper.hpp deleted file mode 100644 index 7e38d39f3fe..00000000000 --- a/3rdparty/sol2/sol/wrapper.hpp +++ /dev/null @@ -1,233 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#ifndef SOL_WRAPPER_HPP -#define SOL_WRAPPER_HPP - -#include "types.hpp" - -namespace sol { - - template <typename F, typename = void> - struct wrapper { - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::args_list free_args_list; - typedef typename traits_type::returns_list returns_list; - - template <typename... Args> - static decltype(auto) call(F& f, Args&&... args) { - return f(std::forward<Args>(args)...); - } - - struct caller { - template <typename... Args> - decltype(auto) operator()(F& fx, Args&&... args) const { - return call(fx, std::forward<Args>(args)...); - } - }; - }; - - template <typename F> - struct wrapper<F, std::enable_if_t<std::is_function<meta::unqualified_t<std::remove_pointer_t<F>>>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::args_list args_list; - typedef typename traits_type::args_list free_args_list; - typedef typename traits_type::returns_list returns_list; - - template <F fx, typename... Args> - static decltype(auto) invoke(Args&&... args) { - return fx(std::forward<Args>(args)...); - } - - template <typename... Args> - static decltype(auto) call(F& fx, Args&&... args) { - return fx(std::forward<Args>(args)...); - } - - struct caller { - template <typename... Args> - decltype(auto) operator()(F& fx, Args&&... args) const { - return call(fx, std::forward<Args>(args)...); - } - }; - - template <F fx> - struct invoker { - template <typename... Args> - decltype(auto) operator()(Args&&... args) const { - return invoke<fx>(std::forward<Args>(args)...); - } - }; - }; - - template <typename F> - struct wrapper<F, std::enable_if_t<std::is_member_object_pointer<meta::unqualified_t<F>>::value>> { - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::object_type object_type; - typedef typename traits_type::return_type return_type; - typedef typename traits_type::args_list args_list; - typedef types<object_type&, return_type> free_args_list; - typedef typename traits_type::returns_list returns_list; - - template <F fx, typename... Args> - static decltype(auto) invoke(object_type& mem, Args&&... args) { - return (mem.*fx)(std::forward<Args>(args)...); - } - - template <typename Fx> - static decltype(auto) call(Fx&& fx, object_type& mem) { - return (mem.*fx); - } - - template <typename Fx, typename Arg, typename... Args> - static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { - (mem.*fx) = std::forward<Arg>(arg); - } - - struct caller { - template <typename Fx, typename... Args> - decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { - return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); - } - }; - - template <F fx> - struct invoker { - template <typename... Args> - decltype(auto) operator()(Args&&... args) const { - return invoke<fx>(std::forward<Args>(args)...); - } - }; - }; - - template <typename F, typename R, typename O, typename... FArgs> - struct member_function_wrapper { - typedef O object_type; - typedef lua_bind_traits<F> traits_type; - typedef typename traits_type::args_list args_list; - typedef types<object_type&, FArgs...> free_args_list; - typedef meta::tuple_types<R> returns_list; - - template <F fx, typename... Args> - static R invoke(O& mem, Args&&... args) { - return (mem.*fx)(std::forward<Args>(args)...); - } - - template <typename Fx, typename... Args> - static R call(Fx&& fx, O& mem, Args&&... args) { - return (mem.*fx)(std::forward<Args>(args)...); - } - - struct caller { - template <typename Fx, typename... Args> - decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { - return call(std::forward<Fx>(fx), mem, std::forward<Args>(args)...); - } - }; - - template <F fx> - struct invoker { - template <typename... Args> - decltype(auto) operator()(O& mem, Args&&... args) const { - return invoke<fx>(mem, std::forward<Args>(args)...); - } - }; - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...)> : public member_function_wrapper<R(O:: *)(Args...), R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const> : public member_function_wrapper<R(O:: *)(Args...) const, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const volatile> : public member_function_wrapper<R(O:: *)(Args...) const volatile, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) &> : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const &> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const volatile &> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) &> : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const &> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const volatile &> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) && > : public member_function_wrapper<R(O:: *)(Args...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const &&> : public member_function_wrapper<R(O:: *)(Args...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args...) const volatile &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) && > : public member_function_wrapper<R(O:: *)(Args..., ...) &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const &, R, O, Args...> { - - }; - - template <typename R, typename O, typename... Args> - struct wrapper<R(O:: *)(Args..., ...) const volatile &&> : public member_function_wrapper<R(O:: *)(Args..., ...) const volatile &, R, O, Args...> { - - }; - -} // sol - -#endif // SOL_WRAPPER_HPP diff --git a/3rdparty/sol2/test_containers.cpp b/3rdparty/sol2/test_containers.cpp deleted file mode 100644 index 224c7ccef5c..00000000000 --- a/3rdparty/sol2/test_containers.cpp +++ /dev/null @@ -1,492 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <sol.hpp> -#include <catch.hpp> - -#include <iterator> -#include <vector> -#include <list> -#include <map> -#include <unordered_map> -#include <set> -#include <unordered_set> - -std::vector<int> test_table_return_one() { - return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; -} - -std::vector<std::pair<std::string, int>> test_table_return_two() { - return{ { "one", 1 },{ "two", 2 },{ "three", 3 } }; -} - -std::map<std::string, std::string> test_table_return_three() { - return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } }; -} - -TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") { - sol::state lua; - std::vector<int> v{ 1, 2, 3 }; - lua.set_function("f", [&]() -> std::vector<int>& { - return v; - }); - lua.script("x = f()"); - sol::object x = lua["x"]; - sol::type xt = x.get_type(); - REQUIRE(xt == sol::type::userdata); - sol::table t = x; - bool matching; - matching = t[1] == 1; - REQUIRE(matching); - matching = t[2] == 2; - REQUIRE(matching); - matching = t[3] == 3; - REQUIRE(matching); -} - -TEST_CASE("containers/vector_roundtrip", "make sure vectors can be round-tripped") { - sol::state lua; - std::vector<int> v{ 1, 2, 3 }; - lua.set_function("f", [&]() -> std::vector<int>& { - return v; - }); - lua.script("x = f()"); - std::vector<int> x = lua["x"]; - bool areequal = x == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/list_roundtrip", "make sure lists can be round-tripped") { - sol::state lua; - std::list<int> v{ 1, 2, 3 }; - lua.set_function("f", [&]() -> std::list<int>& { - return v; - }); - lua.script("x = f()"); - std::list <int> x = lua["x"]; - bool areequal = x == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/map_roundtrip", "make sure maps can be round-tripped") { - sol::state lua; - std::map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; - lua.set_function("f", [&]() -> std::map<std::string, int>& { - return v; - }); - lua.script("x = f()"); - std::map<std::string, int> x = lua["x"]; - bool areequal = x == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/unordered_map_roundtrip", "make sure unordered_maps can be round-tripped") { - sol::state lua; - std::unordered_map<std::string, int> v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; - lua.set_function("f", [&]() -> std::unordered_map<std::string, int>& { - return v; - }); - lua.script("x = f()"); - std::unordered_map<std::string, int> x = lua["x"]; - bool areequal = x == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/unordered_set_roundtrip", "make sure unordered_sets can be round-tripped") { - sol::state lua; - std::unordered_set<int> v{ 1, 2, 3 }; - lua.set_function("f", [&]() -> std::unordered_set<int>& { - return v; - }); - lua.script("x = f()"); - std::unordered_set<int> x = lua["x"]; - bool areequal = x == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/set_roundtrip", "make sure sets can be round-tripped") { - sol::state lua; - std::set<int> v{ 1, 2, 3 }; - lua.set_function("f", [&]() -> std::set<int>& { - return v; - }); - lua.script("x = f()"); - std::set<int> x = lua["x"]; - bool areequal = x == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/custom-usertype", "make sure container usertype metatables can be overridden") { - typedef std::unordered_map<int, int> bark; - - sol::state lua; - lua.open_libraries(); - lua.new_usertype<bark>("bark", - "something", [](const bark& b) { - INFO("It works: " << b.at(24)); - }, - "size", &bark::size, - "at", sol::resolve<const int&>(&bark::at), - "clear", &bark::clear - ); - bark obj{ { 24, 50 } }; - lua.set("a", &obj); - REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)")); - REQUIRE_NOTHROW(lua.script("a:something()")); - lua.set("a", obj); - REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)")); - REQUIRE_NOTHROW(lua.script("a:something()")); -} - -TEST_CASE("containers/const-serialization-kvp", "make sure const keys / values are respected") { - typedef std::map<int, const int> bark; - - sol::state lua; - lua.open_libraries(); - bark obj{ { 24, 50 } }; - lua.set("a", &obj); - REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)")); - REQUIRE_THROWS(lua.script("a[24] = 51")); - REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)")); -} - -TEST_CASE("containers/basic-serialization", "make sure containers are turned into proper userdata and have basic hooks established") { - typedef std::vector<int> woof; - sol::state lua; - lua.open_libraries(); - lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }); - REQUIRE_NOTHROW( - lua.script("for k = 1, #b do assert(k == b[k]) end"); - ); - woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; - lua.set("b", w); - REQUIRE_NOTHROW( - lua.script("for k = 1, #b do assert(k == b[k]) end"); - ); - lua.set("b", &w); - REQUIRE_NOTHROW( - lua.script("for k = 1, #b do assert(k == b[k]) end"); - ); - lua.set("b", std::ref(w)); - REQUIRE_NOTHROW( - lua.script("for k = 1, #b do assert(k == b[k]) end"); - ); -} - -#if 0 // glibc is a fuccboi -TEST_CASE("containers/const-serialization", "make sure containers are turned into proper userdata and the basic hooks respect const-ness") { - typedef std::vector<const int> woof; - sol::state lua; - lua.open_libraries(); - lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }); - REQUIRE_NOTHROW( - lua.script("for k, v in pairs(b) do assert(k == v) end"); - ); - REQUIRE_THROWS(lua.script("b[1] = 20")); -} -#endif // Fuck you, glibc - -TEST_CASE("containers/table-serialization", "ensure types can be serialized as tables still") { - typedef std::vector<int> woof; - sol::state lua; - lua.open_libraries(); - lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 })); - REQUIRE_NOTHROW( - lua.script("for k, v in ipairs(b) do assert(k == v) end"); - ); - woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; - lua.set("b", sol::as_table(w)); - REQUIRE_NOTHROW( - lua.script("for k, v in ipairs(b) do assert(k == v) end"); - ); - lua.set("b", sol::as_table(&w)); - REQUIRE_NOTHROW( - lua.script("for k, v in ipairs(b) do assert(k == v) end"); - ); - lua.set("b", sol::as_table(std::ref(w))); - REQUIRE_NOTHROW( - lua.script("for k, v in ipairs(b) do assert(k == v) end"); - ); -} - -TEST_CASE("containers/const-correctness", "usertype metatable names should reasonably ignore const attributes") { - struct Vec { - int x, y, z; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<Vec>("Vec", "x", &Vec::x, "y", &Vec::y, "z", &Vec::z); - - Vec vec; - vec.x = 1; - vec.y = 2; - vec.z = -3; - - std::vector<Vec> foo; - foo.push_back(vec); - - std::vector<Vec const *> bar; - bar.push_back(&vec); - - lua.script(R"( -func = function(vecs) - for i = 1, #vecs do - vec = vecs[i] - print(i, ":", vec.x, vec.y, vec.z) - end -end -)"); - - REQUIRE_NOTHROW({ - lua["func"](foo); - lua["func"](bar); - }); -} - -TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable from standard containers") { - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.set_function("test_one", test_table_return_one); - lua.set_function("test_two", test_table_return_two); - lua.set_function("test_three", test_table_return_three); - - REQUIRE_NOTHROW(lua.script("a = test_one()")); - REQUIRE_NOTHROW(lua.script("b = test_two()")); - REQUIRE_NOTHROW(lua.script("c = test_three()")); - - REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(b.one == 1, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')")); - REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')")); - REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')")); - - sol::table a = lua.get<sol::table>("a"); - sol::table b = lua.get<sol::table>("b"); - sol::table c = lua.get<sol::table>("c"); - - REQUIRE(a.size() == 10ULL); - REQUIRE(a.get<int>(3) == 3); - REQUIRE(b.get<int>("one") == 1); - REQUIRE(b.get<int>("three") == 3); - REQUIRE(c.get<std::string>("name") == "Rapptz"); - REQUIRE(c.get<std::string>("project") == "sol"); -} - -TEST_CASE("containers/extra-functions", "make sure the manipulation functions are present and usable and working across various container types") { - sol::state lua; - lua.open_libraries(); - - lua.script(R"( -function g (x) - x:add(20) -end - -function h (x) - x:add(20, 40) -end - -function i (x) - x:clear() -end -)"); - - // Have the function we - // just defined in Lua - sol::function g = lua["g"]; - sol::function h = lua["h"]; - sol::function i = lua["i"]; - - // Set a global variable called - // "arr" to be a vector of 5 lements - lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 }; - lua["map"] = std::map<int, int>{ { 1 , 2 },{ 2, 4 },{ 3, 6 },{ 4, 8 },{ 5, 10 } }; - lua["set"] = std::set<int>{ 2, 4, 6, 8, 10 }; - std::vector<int>& arr = lua["arr"]; - std::map<int, int>& map = lua["map"]; - std::set<int>& set = lua["set"]; - REQUIRE(arr.size() == 5); - REQUIRE(map.size() == 5); - REQUIRE(set.size() == 5); - - g(lua["set"]); - g(lua["arr"]); - h(lua["map"]); - REQUIRE(arr.size() == 6); - REQUIRE(map.size() == 6); - REQUIRE(set.size() == 6); - - i(lua["arr"]); - i(lua["map"]); - i(lua["set"]); - REQUIRE(arr.empty()); - REQUIRE(map.empty()); - REQUIRE(set.empty()); -} - -TEST_CASE("containers/usertype-transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") { - class A { - public: - int a; - A(int b = 2) : a(b) {}; - - void func() { } - }; - - struct B { - - B() { - for (std::size_t i = 0; i < 20; ++i) { - a_list.emplace_back(static_cast<int>(i)); - } - } - - std::vector<A> a_list; - }; - - sol::state lua; - lua.new_usertype<B>("B", - "a_list", &B::a_list - ); - - lua.script(R"( -b = B.new() -a_ref = b.a_list[2] -)"); - - B& b = lua["b"]; - A& a_ref = lua["a_ref"]; - REQUIRE(&b.a_list[1] == &a_ref); - REQUIRE(b.a_list[1].a == a_ref.a); -} - -struct options { - static int livingcount; - static options* last; - options() { - ++livingcount; - last = this; - INFO("constructor: " << this); - } - - std::string output_help() { - last = this; - INFO("func: " << this); - return ""; - } - - void begin() {} - void end() {} - - ~options() { - last = this; - --livingcount; - } -}; - -options* options::last = nullptr; -int options::livingcount = 0; - -struct machine { - options opt; -}; - -namespace sol { - template <> - struct is_container<options> : std::false_type {}; -} - -TEST_CASE("containers/is-container", "make sure the is_container trait behaves properly") { - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<options>("options_type", - "output_help", &options::output_help - ); - - lua.new_usertype<machine>("machine_type", - "new", sol::no_constructor, - "opt", [](machine& m) { return &m.opt; }, - "copy_opt", [](machine& m) { return m.opt; } - ); - - { - machine m; - lua["machine"] = &m; - - lua.script(R"( - machine:opt():output_help() - )"); - - REQUIRE(options::last == &m.opt); - REQUIRE(options::livingcount == 1); - } - REQUIRE(options::livingcount == 0); -} - -TEST_CASE("containers/readonly", "make sure readonly members are stored appropriately") { - sol::state lua; - lua.open_libraries(); - - struct bar { - int x = 24; - }; - - struct foo { - std::list<bar> seq; - }; - - lua.new_usertype<foo>( - "foo", - "seq", &foo::seq, // this one works - "readonly_seq", sol::readonly(&foo::seq) // this one does not work - ); - lua["value"] = std::list<bar>{ {},{},{} }; - - lua.script(R"( -a = foo.new() -x = a.seq -a.seq = value -y = a.readonly_seq -)"); - std::list<bar>& seqrefx = lua["x"]; - std::list<bar>& seqrefy = lua["y"]; - REQUIRE(&seqrefx == &seqrefy); - REQUIRE(seqrefx.size() == 3); - auto result = lua.do_string(R"( -a.readonly_seq = value; -)"); - REQUIRE_FALSE(result.valid()); -} - -TEST_CASE("containers/to_args", "Test that the to_args abstractions works") { - sol::state lua; - lua.open_libraries(); - - lua.script("function f (a, b, c, d) print(a, b, c, d) return a, b, c, d end"); - - sol::function f = lua["f"]; - int a, b, c, d; - - std::vector<int> v2{ 3, 4 }; - sol::tie(a, b, c, d) = f(1, 2, sol::as_args(v2)); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); - REQUIRE(d == 4); - - std::set<int> v4{ 7, 6, 8, 5 }; - sol::tie(a, b, c, d) = f(sol::as_args(v4)); - REQUIRE(a == 5); - REQUIRE(b == 6); - REQUIRE(c == 7); - REQUIRE(d == 8); - - int v3[] = { 10, 11, 12 }; - sol::tie(a, b, c, d) = f(9, sol::as_args(v3)); - REQUIRE(a == 9); - REQUIRE(b == 10); - REQUIRE(c == 11); - REQUIRE(d == 12); - -} diff --git a/3rdparty/sol2/test_coroutines.cpp b/3rdparty/sol2/test_coroutines.cpp deleted file mode 100644 index 1581dc3d5a8..00000000000 --- a/3rdparty/sol2/test_coroutines.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - -TEST_CASE("threading/coroutines", "ensure calling a coroutine works") { - const auto& script = R"(counter = 20 - -function loop() - while counter ~= 30 - do - coroutine.yield(counter); - counter = counter + 1; - end - return counter -end -)"; - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.script(script); - sol::coroutine cr = lua["loop"]; - - int counter; - for (counter = 20; counter < 31 && cr; ++counter) { - int value = cr(); - if (counter != value) { - throw std::logic_error("fuck"); - } - } - counter -= 1; - REQUIRE(counter == 30); -} - -TEST_CASE("threading/new-thread-coroutines", "ensure calling a coroutine works when the work is put on a different thread") { - const auto& script = R"(counter = 20 - -function loop() - while counter ~= 30 - do - coroutine.yield(counter); - counter = counter + 1; - end - return counter -end -)"; - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::coroutine); - lua.script(script); - sol::thread runner = sol::thread::create(lua.lua_state()); - sol::state_view runnerstate = runner.state(); - sol::coroutine cr = runnerstate["loop"]; - - int counter; - for (counter = 20; counter < 31 && cr; ++counter) { - int value = cr(); - if (counter != value) { - throw std::logic_error("fuck"); - } - } - counter -= 1; - REQUIRE(counter == 30); -}
\ No newline at end of file diff --git a/3rdparty/sol2/test_customizations.cpp b/3rdparty/sol2/test_customizations.cpp deleted file mode 100644 index dc15a92027c..00000000000 --- a/3rdparty/sol2/test_customizations.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - -#include <unordered_map> -#include <vector> - -struct two_things { - int a; - bool b; -}; - -namespace sol { - - // First, the expected size - // Specialization of a struct - template <> - struct lua_size<two_things> : std::integral_constant<int, 2> {}; - - // Now, specialize various stack structures - namespace stack { - - template <> - struct checker<two_things> { - template <typename Handler> - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - // Check first and second second index for being the proper types - bool success = stack::check<int>(L, index, handler) - && stack::check<bool>(L, index + 1, handler); - tracking.use(2); - return success; - } - }; - - template <> - struct getter<two_things> { - static two_things get(lua_State* L, int index, record& tracking) { - // Get the first element - int a = stack::get<int>(L, index); - // Get the second element, - // in the +1 position from the first - bool b = stack::get<bool>(L, index + 1); - // we use 2 slots, each of the previous takes 1 - tracking.use(2); - return two_things{ a, b }; - } - }; - - template <> - struct pusher<two_things> { - static int push(lua_State* L, const two_things& things) { - int amount = stack::push(L, things.a); - amount += stack::push(L, things.b); - // Return 2 things - return amount; - } - }; - - } -} - -TEST_CASE("customization/split-struct", "using the newly documented customization points to handle different kinds of classes") { - sol::state lua; - - // Create a pass-through style of function - lua.script("function f ( a, b, c ) return a + c, b end"); - lua.set_function("g", [](int a, bool b, int c, double d) { - return std::make_tuple(a + c, b, d + 2.5); - }); - - // get the function out of Lua - sol::function f = lua["f"]; - sol::function g = lua["g"]; - - two_things thingsf = f(two_things{ 24, true }, 1); - two_things thingsg; - double d; - sol::tie( thingsg, d ) = g(two_things{ 25, false }, 2, 34.0); - REQUIRE(thingsf.a == 25); - REQUIRE(thingsf.b); - - REQUIRE(thingsg.a == 27); - REQUIRE_FALSE(thingsg.b); - REQUIRE(d == 36.5); -} diff --git a/3rdparty/sol2/test_functions.cpp b/3rdparty/sol2/test_functions.cpp deleted file mode 100644 index f47a08dc6e1..00000000000 --- a/3rdparty/sol2/test_functions.cpp +++ /dev/null @@ -1,1066 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> -#include <iostream> -#include "test_stack_guard.hpp" - -std::function<int()> makefn() { - auto fx = []() -> int { - return 0x1456789; - }; - return fx; -} - -template <typename T> -T va_func(sol::variadic_args va, T first) { - T s = 0; - for (auto arg : va) { - T v = arg; - s += v; - } - std::cout << first << std::endl; - std::cout << s << std::endl; - - return s; -} - -void takefn(std::function<int()> purr) { - if (purr() != 0x1456789) - throw 0; -} - -struct A { - int a = 0xA; int bark() { return 1; } -}; - -std::tuple<int, int> bark(int num_value, A* a) { - return std::tuple<int, int>(num_value * 2, a->bark()); -} - -void test_free_func(std::function<void()> f) { - f(); -} - -void test_free_func2(std::function<int(int)> f, int arg1) { - int val = f(arg1); - if (val != arg1) - throw sol::error("failed function call!"); -} - -int overloaded(int x) { - INFO(x); - return 3; -} - -int overloaded(int x, int y) { - INFO(x << " " << y); - return 7; -} - -int overloaded(int x, int y, int z) { - INFO(x << " " << y << " " << z); - return 11; -} - -int non_overloaded(int x, int y, int z) { - INFO(x << " " << y << " " << z); - return 13; -} - -namespace sep { - int plop_xyz(int x, int y, std::string z) { - INFO(x << " " << y << " " << z); - return 11; - } -} - -int func_1(int) { - return 1; -} - -std::string func_1s(std::string a) { - return "string: " + a; -} - -int func_2(int, int) { - return 2; -} - -void func_3(int, int, int) { - -} - -int f1(int) { return 32; } -int f2(int, int) { return 1; } -struct fer { - double f3(int, int) { - return 2.5; - } -}; - -TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") { - sol::state lua; - lua.script("function f() return '3', 4 end"); - - std::tuple<std::string, int> result = lua["f"](); - auto s = std::get<0>(result); - auto v = std::get<1>(result); - REQUIRE(s == "3"); - REQUIRE(v == 4); -} - -TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("non_overloaded", non_overloaded); - REQUIRE_NOTHROW(lua.script("x = non_overloaded(1, 2, 3)\nprint(x)")); - - /* - // Cannot reasonably support: clang++ refuses to try enough - // deductions to make this work - lua.set_function<int>("overloaded", overloaded); - REQUIRE_NOTHROW(lua.script("print(overloaded(1))")); - - lua.set_function<int, int>("overloaded", overloaded); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))")); - - lua.set_function<int, int, int>("overloaded", overloaded); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))")); - */ - lua.set_function("overloaded", sol::resolve<int(int)>(overloaded)); - REQUIRE_NOTHROW(lua.script("print(overloaded(1))")); - - lua.set_function("overloaded", sol::resolve<int(int, int)>(overloaded)); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))")); - - lua.set_function("overloaded", sol::resolve<int(int, int, int)>(overloaded)); - REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))")); -} - -TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") { - const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12); - const static std::tuple<int, float> paired = std::make_tuple(10, 10.f); - sol::state lua; - lua.set_function("f", [] { - return std::make_tuple(10, 11, 12); - }); - int a = 0; - lua.set_function("h", []() { - return std::make_tuple(10, 10.0f); - }); - lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); - auto tcpp = lua.get<sol::function>("f").call<int, int, int>(); - auto tlua = lua.get<sol::function>("g").call<int, int, int>(); - auto tcpp2 = lua.get<sol::function>("h").call<int, float>(); - auto tluaget = lua.get<int, int, int>("x", "y", "z"); - REQUIRE(tcpp == triple); - REQUIRE(tlua == triple); - REQUIRE(tluaget == triple); - REQUIRE(tcpp2 == paired); -} - -TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") { - const static std::tuple<int, int, int> triple = std::make_tuple(10, 11, 12); - sol::state lua; - lua.set_function("f_string", []() { return "this is a string!"; }); - sol::function f_string = lua["f_string"]; - - // Make sure there are no overload collisions / compiler errors for automatic string conversions - std::string f_string_result = f_string(); - REQUIRE(f_string_result == "this is a string!"); - f_string_result = f_string(); - REQUIRE(f_string_result == "this is a string!"); - - lua.set_function("f", [] { - return std::make_tuple(10, 11, 12); - }); - lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); - std::tuple<int, int, int> tcpp = lua.get<sol::function>("f")(); - std::tuple<int, int, int> tlua = lua.get<sol::function>("g")(); - std::tuple<int, int, int> tluaget = lua.get<int, int, int>("x", "y", "z"); - INFO("cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp)); - INFO("lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua)); - INFO("lua xyz: " << lua.get<int>("x") << ',' << lua.get<int>("y") << ',' << lua.get<int>("z")); - REQUIRE(tcpp == triple); - REQUIRE(tlua == triple); - REQUIRE(tluaget == triple); -} - -TEST_CASE("functions/optional-values", "check if optionals can be passed in to be nil or otherwise") { - struct thing { - int v; - }; - sol::state lua; - lua.script(R"( function f (a) - return a -end )"); - - sol::function lua_bark = lua["f"]; - - sol::optional<int> testv = lua_bark(sol::optional<int>(29)); - sol::optional<int> testn = lua_bark(sol::nullopt); - REQUIRE((bool)testv); - REQUIRE_FALSE((bool)testn); - REQUIRE(testv.value() == 29); - sol::optional<thing> v = lua_bark(sol::optional<thing>(thing{ 29 })); - REQUIRE_NOTHROW(sol::nil_t n = lua_bark(sol::nullopt)); - REQUIRE(v->v == 29); -} - -TEST_CASE("functions/pair-and-tuple-and-proxy-tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") { - sol::state lua; - lua.new_usertype<A>("A", - "bark", &A::bark); - lua.script(R"( function f (num_value, a) - return num_value * 2, a:bark() -end -function h (num_value, a, b) - return num_value * 2, a:bark(), b * 3 -end -nested = { variables = { no = { problem = 10 } } } )"); - lua.set_function("g", bark); - - sol::function cpp_bark = lua["g"]; - sol::function lua_bark = lua["f"]; - sol::function lua_bark2 = lua["h"]; - - sol::reference lua_variable_x = lua["nested"]["variables"]["no"]["problem"]; - A cpp_variable_y; - - static const std::tuple<int, int> abdesired(20, 1); - static const std::pair<int, int> cddesired = { 20, 1 }; - static const std::tuple<int, int, int> abcdesired(20, 1, 3); - - std::tuple<int, int> ab = cpp_bark(lua_variable_x, cpp_variable_y); - std::pair<int, int> cd = lua_bark(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y); - - REQUIRE(ab == abdesired); - REQUIRE(cd == cddesired); - - ab = cpp_bark(std::make_pair(lua_variable_x, cpp_variable_y)); - cd = lua_bark(std::make_pair(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y)); - - REQUIRE(ab == abdesired); - REQUIRE(cd == cddesired); - - std::tuple<int, int, int> abc = lua_bark2(std::make_tuple(10, cpp_variable_y), sol::optional<int>(1)); - REQUIRE(abc == abcdesired); -} - -TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("testFunc", test_free_func); - lua.set_function("testFunc2", test_free_func2); - lua.script( - "testFunc(function() print(\"hello std::function\") end)" - ); - REQUIRE_NOTHROW(lua.script( - "function m(a)\n" - " print(\"hello std::function with arg \", a)\n" - " return a\n" - "end\n" - "\n" - "testFunc2(m, 1)" - )); -} - -TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("makefn", makefn); - lua.set_function("takefn", takefn); - lua.script("afx = makefn()\n" - "print(afx())\n" - "takefn(afx)\n"); -} - -TEST_CASE("functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::debug); - static const char unhandlederrormessage[] = "true error message"; - static const char handlederrormessage[] = "doodle"; - static const std::string handlederrormessage_s = handlederrormessage; - - // Some function; just using a lambda to be cheap - auto doomfx = []() { - INFO("doomfx called"); - throw std::runtime_error(unhandlederrormessage); - }; - auto luadoomfx = [&lua]() { - INFO("luadoomfx called"); - // Does not bypass error function, will call it - luaL_error(lua.lua_state(), unhandlederrormessage); - }; - lua.set_function("doom", doomfx); - lua.set_function("luadoom", luadoomfx); - - auto cpphandlerfx = [](std::string x) { - INFO("c++ handler called with: " << x); - return handlederrormessage; - }; - lua.set_function("cpphandler", cpphandlerfx); - lua.script( - std::string("function luahandler ( message )") - + " print('lua handler called with: ' .. message)" - + " return '" + handlederrormessage + "'" - + "end" - ); - auto nontrampolinefx = [](lua_State*) -> int { throw "x"; }; - lua_CFunction c_nontrampolinefx = nontrampolinefx; - lua.set("nontrampoline", c_nontrampolinefx); - lua.set_function("bark", []() -> int {return 100; }); - - sol::function luahandler = lua["luahandler"]; - sol::function cpphandler = lua["cpphandler"]; - sol::protected_function doom(lua["doom"], luahandler); - sol::protected_function luadoom(lua["luadoom"]); - sol::protected_function nontrampoline = lua["nontrampoline"]; - sol::protected_function justfine = lua["bark"]; - sol::protected_function justfinewithhandler = lua["bark"]; - luadoom.error_handler = cpphandler; - nontrampoline.error_handler = cpphandler; - justfinewithhandler.error_handler = luahandler; - bool present = true; - { - sol::protected_function_result result = doom(); - REQUIRE_FALSE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE(present); - present = (bool)opvalue; - REQUIRE_FALSE(present); - sol::error err = result; - REQUIRE(err.what() == handlederrormessage_s); - } - { - sol::protected_function_result result = luadoom(); - REQUIRE_FALSE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE(present); - present = (bool)opvalue; - REQUIRE_FALSE(present); - sol::error err = result; - REQUIRE(err.what() == handlederrormessage_s); - } - { - sol::protected_function_result result = nontrampoline(); - REQUIRE_FALSE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE(present); - present = (bool)opvalue; - REQUIRE_FALSE(present); - sol::error err = result; - REQUIRE(err.what() == handlederrormessage_s); - } - { - sol::protected_function_result result = justfine(); - REQUIRE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE_FALSE(present); - present = (bool)opvalue; - REQUIRE(present); - int value = result; - REQUIRE(value == 100); - } - { - sol::protected_function_result result = justfinewithhandler(); - REQUIRE(result.valid()); - sol::optional<sol::error> operr = result; - sol::optional<int> opvalue = result; - present = (bool)operr; - REQUIRE_FALSE(present); - present = (bool)opvalue; - REQUIRE(present); - int value = result; - REQUIRE(value == 100); - } -} - -TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") { - static int created = 0; - static int destroyed = 0; - static void* last_call = nullptr; - static void* static_call = reinterpret_cast<void*>(0x01); - typedef void(*fptr)(); - struct x { - x() { ++created; } - x(const x&) { ++created; } - x(x&&) { ++created; } - x& operator=(const x&) { return *this; } - x& operator=(x&&) { return *this; } - void func() { last_call = static_cast<void*>(this); }; - ~x() { ++destroyed; } - }; - struct y { - y() { ++created; } - y(const x&) { ++created; } - y(x&&) { ++created; } - y& operator=(const x&) { return *this; } - y& operator=(x&&) { return *this; } - static void func() { last_call = static_call; }; - void operator()() { func(); } - operator fptr () { return func; } - ~y() { ++destroyed; } - }; - - // stateful functors/member functions should always copy unless specified - { - created = 0; - destroyed = 0; - last_call = nullptr; - { - sol::state lua; - x x1; - lua.set_function("x1copy", &x::func, x1); - lua.script("x1copy()"); - REQUIRE(created == 2); - REQUIRE(destroyed == 0); - REQUIRE_FALSE(last_call == &x1); - - lua.set_function("x1ref", &x::func, std::ref(x1)); - lua.script("x1ref()"); - REQUIRE(created == 2); - REQUIRE(destroyed == 0); - REQUIRE(last_call == &x1); - } - REQUIRE(created == 2); - REQUIRE(destroyed == 2); - } - - // things convertible to a static function should _never_ be forced to make copies - // therefore, pass through untouched - { - created = 0; - destroyed = 0; - last_call = nullptr; - { - sol::state lua; - y y1; - lua.set_function("y1copy", y1); - lua.script("y1copy()"); - REQUIRE(created == 1); - REQUIRE(destroyed == 0); - REQUIRE(last_call == static_call); - - last_call = nullptr; - lua.set_function("y1ref", std::ref(y1)); - lua.script("y1ref()"); - REQUIRE(created == 1); - REQUIRE(destroyed == 0); - REQUIRE(last_call == static_call); - } - REQUIRE(created == 1); - REQUIRE(destroyed == 1); - } -} - - -TEST_CASE("functions/all-kinds", "Register all kinds of functions, make sure they all compile and work") { - sol::state lua; - - struct test_1 { - int a = 0xA; - virtual int bark() { - return a; - } - - int bark_mem() { - return a; - } - - static std::tuple<int, int> x_bark(int num_value, test_1* a) { - return std::tuple<int, int>(num_value * 2, a->a); - } - }; - - struct test_2 { - int a = 0xC; - int bark() { - return 20; - } - }; - - struct inner { - const int z = 5653; - }; - - struct nested { - inner i; - }; - - auto a = []() { return 500; }; - auto b = [&]() { return 501; }; - auto c = [&]() { return 502; }; - auto d = []() { return 503; }; - - lua.new_usertype<test_1>("test_1", - "bark", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem> - ); - lua.new_usertype<test_2>("test_2", - "bark", sol::c_call<decltype(&test_2::bark), &test_2::bark> - ); - test_2 t2; - - lua.set_function("a", a); - lua.set_function("b", b); - lua.set_function("c", std::ref(c)); - lua.set_function("d", std::ref(d)); - lua.set_function("f", &test_1::bark); - lua.set_function("g", test_1::x_bark); - lua.set_function("h", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>); - lua.set_function("i", &test_2::bark, test_2()); - lua.set_function("j", &test_2::a, test_2()); - lua.set_function("k", &test_2::a); - lua.set_function("l", sol::c_call<decltype(&test_1::a), &test_1::a>); - lua.set_function("m", &test_2::a, &t2); - lua.set_function("n", sol::c_call<decltype(&non_overloaded), &non_overloaded>); - - lua.script(R"( -o1 = test_1.new() -o2 = test_2.new() -)"); - - lua.script(R"( -ob = o1:bark() - -A = a() -B = b() -C = c() -D = d() -F = f(o1) -G0, G1 = g(2, o1) -H = h(o1) -I = i(o1) -I = i(o1) -)"); - - - lua.script(R"( -J0 = j() -j(24) -J1 = j() - )"); - - lua.script(R"( -K0 = k(o2) -k(o2, 1024) -K1 = k(o2) - )"); - - lua.script(R"( -L0 = l(o1) -l(o1, 678) -L1 = l(o1) - )"); - - - lua.script(R"( -M0 = m() -m(256) -M1 = m() - )"); - - lua.script(R"( -N = n(1, 2, 3) - )"); - int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N; - std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) - = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>( - "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" - ); - - REQUIRE(ob == 0xA); - - REQUIRE(A == 500); - REQUIRE(B == 501); - REQUIRE(C == 502); - REQUIRE(D == 503); - - REQUIRE(F == 0xA); - REQUIRE(G0 == 4); - REQUIRE(G1 == 0xA); - REQUIRE(H == 0xA); - REQUIRE(I == 20); - - REQUIRE(J0 == 0xC); - REQUIRE(J1 == 24); - - REQUIRE(K0 == 0xC); - REQUIRE(K1 == 1024); - - REQUIRE(L0 == 0xA); - REQUIRE(L1 == 678); - - REQUIRE(M0 == 0xC); - REQUIRE(M1 == 256); - - REQUIRE(N == 13); - - sol::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) - = lua.get<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>( - "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" - ); - - REQUIRE(ob == 0xA); - - REQUIRE(A == 500); - REQUIRE(B == 501); - REQUIRE(C == 502); - REQUIRE(D == 503); - - REQUIRE(F == 0xA); - REQUIRE(G0 == 4); - REQUIRE(G1 == 0xA); - REQUIRE(H == 0xA); - REQUIRE(I == 20); - - REQUIRE(J0 == 0xC); - REQUIRE(J1 == 24); - - REQUIRE(K0 == 0xC); - REQUIRE(K1 == 1024); - - REQUIRE(L0 == 0xA); - REQUIRE(L1 == 678); - - REQUIRE(M0 == 0xC); - REQUIRE(M1 == 256); - - REQUIRE(N == 13); - - // Work that compiler, WORK IT! - lua.set("o", &test_1::bark); - lua.set("p", test_1::x_bark); - lua.set("q", sol::c_call<decltype(&test_1::bark_mem), &test_1::bark_mem>); - lua.set("r", &test_2::a); - lua.set("s", sol::readonly(&test_2::a)); - lua.set_function("t", sol::readonly(&test_2::a), test_2()); - lua.set_function("u", &nested::i, nested()); - lua.set("v", &nested::i); - lua.set("nested", nested()); - lua.set("inner", inner()); - REQUIRE_THROWS(lua.script("s(o2, 2)")); - REQUIRE_THROWS(lua.script("t(2)")); - REQUIRE_THROWS(lua.script("u(inner)")); - REQUIRE_THROWS(lua.script("v(nested, inner)")); -} - -TEST_CASE("simple/call-with-parameters", "Lua function is called with a few parameters from C++") { - sol::state lua; - - REQUIRE_NOTHROW(lua.script("function my_add(i, j, k) return i + j + k end")); - auto f = lua.get<sol::function>("my_add"); - REQUIRE_NOTHROW(lua.script("function my_nothing(i, j, k) end")); - auto fvoid = lua.get<sol::function>("my_nothing"); - int a; - REQUIRE_NOTHROW(fvoid(1, 2, 3)); - REQUIRE_NOTHROW(a = f.call<int>(1, 2, 3)); - REQUIRE(a == 6); - REQUIRE_THROWS(a = f(1, 2, "arf")); -} - -TEST_CASE("simple/call-c++-function", "C++ function is called from lua") { - sol::state lua; - - lua.set_function("plop_xyz", sep::plop_xyz); - lua.script("x = plop_xyz(2, 6, 'hello')"); - - REQUIRE(lua.get<int>("x") == 11); -} - -TEST_CASE("simple/call-lambda", "A C++ lambda is exposed to lua and called") { - sol::state lua; - - int a = 0; - - lua.set_function("foo", [&a] { a = 1; }); - - lua.script("foo()"); - - REQUIRE(a == 1); -} - -TEST_CASE("advanced/get-and-call", "Checks for lambdas returning values after a get operation") { - const static std::string lol = "lol", str = "str"; - const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); - sol::state lua; - - REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; })); - REQUIRE(lua.get<sol::function>("a").call<int>() == 42); - - REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); - REQUIRE(lua.get<sol::function>("b").call<unsigned int>() == 42u); - - REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); - REQUIRE(lua.get<sol::function>("c").call<double>() == 3.14); - - REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); - REQUIRE(lua.get<sol::function>("d").call<float>() == 6.28f); - - REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); - REQUIRE(lua.get<sol::function>("e").call<std::string>() == lol); - - REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); - REQUIRE(lua.get<sol::function>("f").call<bool>()); - - REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); - REQUIRE(lua.get<sol::function>("g").call<std::string>() == str); - - REQUIRE_NOTHROW(lua.set_function("h", [] {})); - REQUIRE_NOTHROW(lua.get<sol::function>("h").call()); - - REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); - REQUIRE(lua.get<sol::function>("i").call<sol::nil_t>() == sol::nil); - REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); - REQUIRE((lua.get<sol::function>("j").call<int, float, double, std::string>() == heh_tuple)); -} - -TEST_CASE("advanced/operator[]-call", "Checks for lambdas returning values using operator[]") { - const static std::string lol = "lol", str = "str"; - const static std::tuple<int, float, double, std::string> heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); - sol::state lua; - - REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; })); - REQUIRE(lua["a"].call<int>() == 42); - - REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); - REQUIRE(lua["b"].call<unsigned int>() == 42u); - - REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); - REQUIRE(lua["c"].call<double>() == 3.14); - - REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); - REQUIRE(lua["d"].call<float>() == 6.28f); - - REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); - REQUIRE(lua["e"].call<std::string>() == lol); - - REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); - REQUIRE(lua["f"].call<bool>()); - - REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); - REQUIRE(lua["g"].call<std::string>() == str); - - REQUIRE_NOTHROW(lua.set_function("h", [] {})); - REQUIRE_NOTHROW(lua["h"].call()); - - REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); - REQUIRE(lua["i"].call<sol::nil_t>() == sol::nil); - REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); - REQUIRE((lua["j"].call<int, float, double, std::string>() == heh_tuple)); -} - -TEST_CASE("advanced/call-lambdas", "A C++ lambda is exposed to lua and called") { - sol::state lua; - - int x = 0; - lua.set_function("set_x", [&](int new_x) { - x = new_x; - return 0; - }); - - lua.script("set_x(9)"); - REQUIRE(x == 9); -} - -TEST_CASE("advanced/call-referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") { - sol::state lua; - - int x = 0; - auto objx = [&](int new_x) { - x = new_x; - return 0; - }; - lua.set_function("set_x", std::ref(objx)); - - int y = 0; - auto objy = [&](int new_y) { - y = new_y; - return std::tuple<int, int>(0, 0); - }; - lua.set_function("set_y", &decltype(objy)::operator(), std::ref(objy)); - - lua.script("set_x(9)"); - lua.script("set_y(9)"); - REQUIRE(x == 9); - REQUIRE(y == 9); -} - -TEST_CASE("functions/tie", "make sure advanced syntax with 'tie' works") { - sol::state lua; - - lua.script(R"(function f () - return 1, 2, 3 -end)"); - sol::function f = lua["f"]; - - int a, b, c; - sol::tie(a, b, c) = f(); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); -} - -TEST_CASE("functions/variadic_args", "Check to see we can receive multiple arguments through a variadic") { - struct structure { - int x; - bool b; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.set_function("v", [](sol::this_state, sol::variadic_args va) -> structure { - int r = 0; - for (auto v : va) { - int value = v; - r += value; - } - return{ r, r > 200 }; - }); - - lua.script("x = v(25, 25)"); - lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); - lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); - - structure& lx = lua["x"]; - structure& lx2 = lua["x2"]; - structure& lx3 = lua["x3"]; - REQUIRE(lx.x == 50); - REQUIRE(lx2.x == 600); - REQUIRE(lx3.x == 21); - REQUIRE_FALSE(lx.b); - REQUIRE(lx2.b); - REQUIRE_FALSE(lx3.b); -} - -TEST_CASE("functions/required_and_variadic_args", "Check if a certain number of arguments can still be required even when using variadic_args") { - sol::state lua; - lua.set_function("v", - [](sol::this_state, sol::variadic_args, int, int) { - } - ); - REQUIRE_NOTHROW(lua.script("v(20, 25, 30)")); - REQUIRE_NOTHROW(lua.script("v(20, 25)")); -#ifndef SOL_LUAJIT - REQUIRE_THROWS(lua.script("v(20)")); -#endif // LuaJIT has problems with exceptions, as fucking usual -} - -TEST_CASE("functions/overloading", "Check if overloading works properly for regular set function syntax") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("func_1", func_1); - lua.set_function("func", sol::overload(func_2, func_3, func_1, func_1s)); - - const std::string string_bark = "string: bark"; - - REQUIRE_NOTHROW(lua.script( - "a = func(1)\n" - "b = func('bark')\n" - "c = func(1,2)\n" - "func(1,2,3)\n" - )); - - REQUIRE((lua["a"] == 1)); - REQUIRE((lua["b"] == string_bark)); - REQUIRE((lua["c"] == 2)); - - REQUIRE_THROWS(lua.script("func(1,2,'meow')")); -} - -TEST_CASE("overloading/c_call", "Make sure that overloading works with c_call functionality") { - sol::state lua; - lua.set("f", sol::c_call<sol::wrap<decltype(&f1), &f1>, sol::wrap<decltype(&f2), &f2>, sol::wrap<decltype(&fer::f3), &fer::f3>>); - lua.set("g", sol::c_call<sol::wrap<decltype(&f1), &f1>>); - lua.set("h", sol::c_call<decltype(&f2), &f2>); - lua.set("obj", fer()); - - lua.script("r1 = f(1)"); - lua.script("r2 = f(1, 2)"); - lua.script("r3 = f(obj, 1, 2)"); - lua.script("r4 = g(1)"); - lua.script("r5 = h(1, 2)"); - - int r1 = lua["r1"]; - int r2 = lua["r2"]; - double r3 = lua["r3"]; - int r4 = lua["r4"]; - int r5 = lua["r5"]; - - REQUIRE(r1 == 32); - REQUIRE(r2 == 1); - REQUIRE(r3 == 2.5); - REQUIRE(r4 == 32); - REQUIRE(r5 == 1); -} - -TEST_CASE("functions/stack-protect", "make sure functions don't impede on the stack") { - //setup sol/lua - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::string); - - lua.script("function ErrorHandler(msg) print('Lua created error msg : ' .. msg) return msg end"); - lua.script("function stringtest(a) if a == nil then error('fuck') end print('Lua recieved content : ' .. a) return a end"); - - // test normal function - { - sol::stack_guard normalsg(lua); - std::string str = lua["stringtest"]("normal test"); - INFO("Back in C++, direct call result is : " << str); - } - - //test protected_function - sol::protected_function Stringtest(lua["stringtest"]); - Stringtest.error_handler = lua["ErrorHandler"]; - sol::stack_guard sg(lua); - { - sol::protected_function_result stringresult = Stringtest("protected test"); - REQUIRE(stringresult.valid()); - std::string s = stringresult; - INFO("Back in C++, protected result is : " << s); - } - REQUIRE(sg.check_stack()); - - //test optional - { - sol::stack_guard opsg(lua); - sol::optional<std::string> opt_result = Stringtest("optional test"); - REQUIRE(opsg.check_stack()); - if (opt_result) - { - std::string s = opt_result.value(); - INFO("Back in C++, opt_result is : " << s); - } - else - { - INFO("opt_result failed"); - } - } - REQUIRE(sg.check_stack()); - - { - sol::protected_function_result errresult = Stringtest(sol::nil); - REQUIRE_FALSE(errresult.valid()); - sol::error err = errresult; - std::string msg = err.what(); - INFO("error :" << msg); - } - REQUIRE(sg.check_stack()); -} - -TEST_CASE("functions/same-type-closures", "make sure destructions are per-object, not per-type, by destroying one type multiple times") { - static std::set<void*> last_my_closures; - static bool checking_closures = false; - static bool check_failed = false; - - struct my_closure { - int& n; - - my_closure(int& n) : n(n) {} - ~my_closure() noexcept(false) { - if (!checking_closures) - return; - void* addr = static_cast<void*>(this); - auto f = last_my_closures.find(addr); - if (f != last_my_closures.cend()) { - check_failed = true; - } - last_my_closures.insert(f, addr); - } - - int operator() () { - ++n; return n; - } - }; - - int n = 250; - my_closure a(n); - my_closure b(n); - { - sol::state lua; - - lua.set_function("f", a); - lua.set_function("g", b); - checking_closures = true; - } - REQUIRE_FALSE(check_failed); - REQUIRE(last_my_closures.size() == 2); -} - -TEST_CASE("functions/stack-multi-return", "Make sure the stack is protected after multi-returns") { - sol::state lua; - lua.script("function f () return 1, 2, 3, 4, 5 end"); - - { - sol::stack_guard sg(lua); - sol::stack::push(lua, double(256.78)); - { - int a, b, c, d, e; - sol::stack_guard sg2(lua); - sol::function f = lua["f"]; - sol::tie(a, b, c, d, e) = f(); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); - REQUIRE(d == 4); - REQUIRE(e == 5); - } - double f = sol::stack::pop<double>(lua); - REQUIRE(f == 256.78); - } -} - -TEST_CASE("functions/protected-stack-multi-return", "Make sure the stack is protected after multi-returns") { - sol::state lua; - lua.script("function f () return 1, 2, 3, 4, 5 end"); - - { - sol::stack_guard sg(lua); - sol::stack::push(lua, double(256.78)); - { - int a, b, c, d, e; - sol::stack_guard sg2(lua); - sol::protected_function pf = lua["f"]; - sol::tie(a, b, c, d, e) = pf(); - REQUIRE(a == 1); - REQUIRE(b == 2); - REQUIRE(c == 3); - REQUIRE(d == 4); - REQUIRE(e == 5); - } - double f = sol::stack::pop<double>(lua); - REQUIRE(f == 256.78); - } -} - -TEST_CASE("functions/overloaded-variadic", "make sure variadics work to some degree with overloading") { - sol::state lua; - lua.open_libraries(); - - sol::table ssl = lua.create_named_table("ssl"); - ssl.set_function("test", sol::overload(&va_func<int>, &va_func<double>)); - - lua.script("a = ssl.test(1, 2, 3)"); - lua.script("b = ssl.test(1, 2)"); - lua.script("c = ssl.test(2.2)"); - - int a = lua["a"]; - int b = lua["b"]; - double c = lua["c"]; - REQUIRE(a == 6); - REQUIRE(b == 3); - REQUIRE(c == 2.2); -} diff --git a/3rdparty/sol2/test_inheritance.cpp b/3rdparty/sol2/test_inheritance.cpp deleted file mode 100644 index ccd46b7d8c7..00000000000 --- a/3rdparty/sol2/test_inheritance.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <sol.hpp> -#include <catch.hpp> - -#include <iostream> - -TEST_CASE("inheritance/basic", "test that metatables are properly inherited") { - struct A { - int a = 5; - }; - - struct B { - int b() { - return 10; - } - }; - - struct C : B, A { - double c = 2.4; - }; - - struct D : C { - bool d() const { - return true; - } - }; - - sol::state lua; - lua.new_usertype<A>("A", - "a", &A::a - ); - lua.new_usertype<B>("B", - "b", &B::b - ); - lua.new_usertype<C>("C", - "c", &C::c, - sol::base_classes, sol::bases<B, A>() - ); - lua.new_usertype<D>("D", - "d", &D::d, - sol::base_classes, sol::bases<C, B, A>() - ); - - lua.script("obj = D.new()"); - lua.script("d = obj:d()"); - bool d = lua["d"]; - lua.script("c = obj.c"); - double c = lua["c"]; - lua.script("b = obj:b()"); - int b = lua["b"]; - lua.script("a = obj.a"); - int a = lua["a"]; - - REQUIRE(d); - REQUIRE(c == 2.4); - REQUIRE(b == 10); - REQUIRE(a == 5); -} - -TEST_CASE("inheritance/multi-base", "test that multiple bases all work and overloading for constructors works with them") { - class TestClass00 { - public: - int Thing() const { return 123; } - }; - - class TestClass01 : public TestClass00 { - public: - TestClass01() : a(1) {} - TestClass01(const TestClass00& other) : a(other.Thing()) {} - - int a; - }; - - class TestClass02 : public TestClass01 { - public: - TestClass02() : b(2) {} - TestClass02(const TestClass01& other) : b(other.a) {} - TestClass02(const TestClass00& other) : b(other.Thing()) {} - - int b; - }; - - class TestClass03 : public TestClass02 { - public: - TestClass03() : c(2) {} - TestClass03(const TestClass02& other) : c(other.b) {} - TestClass03(const TestClass01& other) : c(other.a) {} - TestClass03(const TestClass00& other) : c(other.Thing()) {} - - int c; - }; - - sol::state lua; - - sol::usertype<TestClass00> s_TestUsertype00( - sol::call_constructor, sol::constructors<sol::types<>>(), - "Thing", &TestClass00::Thing - ); - - lua.set_usertype("TestClass00", s_TestUsertype00); - - sol::usertype<TestClass01> s_TestUsertype01( - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(), - sol::base_classes, sol::bases<TestClass00>(), - "a", &TestClass01::a - ); - - lua.set_usertype("TestClass01", s_TestUsertype01); - - sol::usertype<TestClass02> s_TestUsertype02( - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), - sol::base_classes, sol::bases<TestClass01, TestClass00>(), - "b", &TestClass02::b - ); - - lua.set_usertype("TestClass02", s_TestUsertype02); - - sol::usertype<TestClass03> s_TestUsertype03( - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), - sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(), - "c", &TestClass03::c - ); - - lua.set_usertype("TestClass03", s_TestUsertype03); - - lua.script(R"( -tc0 = TestClass00() -)"); - - lua.script(R"( -tc2 = TestClass02(tc0) -)"); - - lua.script(R"( -tc1 = TestClass01() -)"); - - lua.script(R"( -tc3 = TestClass03(tc1) -)"); - - TestClass00& tc0 = lua["tc0"]; - TestClass01& tc1 = lua["tc1"]; - TestClass02& tc2 = lua["tc2"]; - TestClass03& tc3 = lua["tc3"]; - REQUIRE(tc0.Thing() == 123); - REQUIRE(tc1.a == 1); - REQUIRE(tc2.a == 1); - REQUIRE(tc2.b == 123); - REQUIRE(tc3.a == 1); - REQUIRE(tc3.b == 2); - REQUIRE(tc3.c == 1); -} - -TEST_CASE("inheritance/simple-multi-base", "test that multiple bases all work and overloading for constructors works with them") { - class TestClass00 { - public: - int Thing() const { return 123; } - }; - - class TestClass01 : public TestClass00 { - public: - TestClass01() : a(1) {} - TestClass01(const TestClass00& other) : a(other.Thing()) {} - - int a; - }; - - class TestClass02 : public TestClass01 { - public: - TestClass02() : b(2) {} - TestClass02(const TestClass01& other) : b(other.a) {} - TestClass02(const TestClass00& other) : b(other.Thing()) {} - - int b; - }; - - class TestClass03 : public TestClass02 { - public: - TestClass03() : c(2) {} - TestClass03(const TestClass02& other) : c(other.b) {} - TestClass03(const TestClass01& other) : c(other.a) {} - TestClass03(const TestClass00& other) : c(other.Thing()) {} - - int c; - }; - - sol::state lua; - - sol::simple_usertype<TestClass00> s_TestUsertype00( lua, - sol::call_constructor, sol::constructors<sol::types<>>(), - "Thing", &TestClass00::Thing - ); - - lua.set_usertype("TestClass00", s_TestUsertype00); - - sol::simple_usertype<TestClass01> s_TestUsertype01( lua, - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(), - sol::base_classes, sol::bases<TestClass00>(), - "a", &TestClass01::a - ); - - lua.set_usertype("TestClass01", s_TestUsertype01); - - sol::simple_usertype<TestClass02> s_TestUsertype02( lua, - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), - sol::base_classes, sol::bases<TestClass01, TestClass00>(), - "b", &TestClass02::b - ); - - lua.set_usertype("TestClass02", s_TestUsertype02); - - sol::simple_usertype<TestClass03> s_TestUsertype03( lua, - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(), - sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(), - "c", &TestClass03::c - ); - - lua.set_usertype("TestClass03", s_TestUsertype03); - - lua.script(R"( -tc0 = TestClass00() -)"); - - lua.script(R"( -tc2 = TestClass02(tc0) -)"); - - lua.script(R"( -tc1 = TestClass01() -)"); - - lua.script(R"( -tc3 = TestClass03(tc1) -)"); - - TestClass00& tc0 = lua["tc0"]; - TestClass01& tc1 = lua["tc1"]; - TestClass02& tc2 = lua["tc2"]; - TestClass03& tc3 = lua["tc3"]; - REQUIRE(tc1.a == 1); - REQUIRE(tc2.a == 1); - REQUIRE(tc2.b == 123); - REQUIRE(tc3.a == 1); - REQUIRE(tc3.b == 2); - REQUIRE(tc3.c == 1); -} diff --git a/3rdparty/sol2/test_operators.cpp b/3rdparty/sol2/test_operators.cpp deleted file mode 100644 index b8e48e783ee..00000000000 --- a/3rdparty/sol2/test_operators.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <sol.hpp> -#include <catch.hpp> - -TEST_CASE("operators/default", "test that generic equality operators and all sorts of equality tests can be used") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - struct T {}; - struct U { - int a; - U(int x = 20) : a(x) {} - bool operator==(const U& r) { - return a == r.a; - } - }; - struct V { - int a; - V(int x = 20) : a(x) {} - bool operator==(const V& r) const { - return a == r.a; - } - }; - lua.new_usertype<T>("T"); - lua.new_usertype<U>("U"); - lua.new_usertype<V>("V"); - - T t1; - T& t2 = t1; - T t3; - U u1; - U u2{ 30 }; - U u3; - U v1; - U v2{ 30 }; - U v3; - lua["t1"] = &t1; - lua["t2"] = &t2; - lua["t3"] = &t3; - lua["u1"] = &u1; - lua["u2"] = &u2; - lua["u3"] = &u3; - lua["v1"] = &v1; - lua["v2"] = &v2; - lua["v3"] = &v3; - - // Can only compare identity here - REQUIRE_NOTHROW({ - lua.script("assert(t1 == t1)"); - lua.script("assert(t2 == t2)"); - lua.script("assert(t3 == t3)"); - }); - REQUIRE_NOTHROW({ - lua.script("assert(t1 == t2)"); - lua.script("assert(not (t1 == t3))"); - lua.script("assert(not (t2 == t3))"); - }); - // Object should compare equal to themselves - // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW({ - lua.script("assert(u1 == u1)"); - lua.script("assert(u2 == u2)"); - lua.script("assert(u3 == u3)"); - }); - REQUIRE_NOTHROW({ - lua.script("assert(not (u1 == u2))"); - lua.script("assert(u1 == u3)"); - lua.script("assert(not (u2 == u3))"); - }); - // Object should compare equal to themselves - // (and not invoke operator==; pointer test should be sufficient) - REQUIRE_NOTHROW({ - lua.script("assert(v1 == v1)"); - lua.script("assert(v2 == v2)"); - lua.script("assert(v3 == v3)"); - }); - REQUIRE_NOTHROW({ - lua.script("assert(not (v1 == v2))"); - lua.script("assert(v1 == v3)"); - lua.script("assert(not (v2 == v3))"); - }); -}
\ No newline at end of file diff --git a/3rdparty/sol2/test_overflow.cpp b/3rdparty/sol2/test_overflow.cpp deleted file mode 100644 index 68c11811a97..00000000000 --- a/3rdparty/sol2/test_overflow.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - - -TEST_CASE("issues/stack-overflow", "make sure various operations repeated don't trigger stack overflow") { - sol::state lua; - lua.script("t = {};t[0]=20"); - lua.script("lua_function=function(i)return i;end"); - - sol::function f = lua["lua_function"]; - std::string teststring = "testtext"; - REQUIRE_NOTHROW( - for (int i = 0; i < 1000000; ++i) { - std::string result = f(teststring); - if (result != teststring) throw std::logic_error("RIP"); - } - ); - sol::table t = lua["t"]; - int expected = 20; - REQUIRE_NOTHROW( - for (int i = 0; i < 1000000; ++i) { - int result = t[0]; - t.size(); - if (result != expected) - throw std::logic_error("RIP"); - } - ); -} - - -TEST_CASE("issues/stack-overflow-2", "make sure basic iterators clean up properly when they're not iterated through (e.g., with empty())") { - sol::state lua; - sol::table t = lua.create_table_with(1, "wut"); - int MAX = 50000; - auto fx = [&]() { - int a = 50; - for (int i = 0; i < MAX; ++i) { - if (t.empty()) { - a += 4; - } - a += 2; - } - }; - REQUIRE_NOTHROW(fx()); -} diff --git a/3rdparty/sol2/test_simple_usertypes.cpp b/3rdparty/sol2/test_simple_usertypes.cpp deleted file mode 100644 index ca3e7cdca89..00000000000 --- a/3rdparty/sol2/test_simple_usertypes.cpp +++ /dev/null @@ -1,463 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <sol.hpp> -#include <catch.hpp> - -#include <iostream> -#include <list> -#include <memory> -#include <mutex> - -TEST_CASE("usertype/simple-usertypes", "Ensure that simple usertypes properly work here") { - struct marker { - bool value = false; - }; - struct bark { - int var = 50; - marker mark; - - void fun() { - var = 51; - } - - int get() const { - return var; - } - - int set(int x) { - var = x; - return var; - } - - std::string special() const { - return mark.value ? "woof" : "pantpant"; - } - - const marker& the_marker() const { - return mark; - } - }; - - sol::state lua; - lua.new_simple_usertype<bark>("bark", - "fun", &bark::fun, - "get", &bark::get, - "var", sol::as_function( &bark::var ), - "the_marker", sol::as_function(&bark::the_marker), - "x", sol::overload(&bark::get), - "y", sol::overload(&bark::set), - "z", sol::overload(&bark::get, &bark::set) - ); - - lua.script("b = bark.new()"); - bark& b = lua["b"]; - - lua.script("b:fun()"); - int var = b.var; - REQUIRE(var == 51); - - lua.script("b:var(20)"); - lua.script("v = b:var()"); - int v = lua["v"]; - REQUIRE(v == 20); - REQUIRE(b.var == 20); - - lua.script("m = b:the_marker()"); - marker& m = lua["m"]; - REQUIRE_FALSE(b.mark.value); - REQUIRE_FALSE(m.value); - m.value = true; - REQUIRE(&b.mark == &m); - REQUIRE(b.mark.value); - - sol::table barktable = lua["bark"]; - barktable["special"] = &bark::special; - - lua.script("s = b:special()"); - std::string s = lua["s"]; - REQUIRE(s == "woof"); - - lua.script("b:y(24)"); - lua.script("x = b:x()"); - int x = lua["x"]; - REQUIRE(x == 24); - - lua.script("z = b:z(b:z() + 5)"); - int z = lua["z"]; - REQUIRE(z == 29); -} - -TEST_CASE("usertype/simple-usertypes-constructors", "Ensure that calls with specific arguments work") { - struct marker { - bool value = false; - }; - struct bark { - int var = 50; - marker mark; - - bark() {} - bark(int v) : var(v) {} - - void fun() { - var = 51; - } - - int get() const { - return var; - } - - int set(int x) { - var = x; - return var; - } - - std::string special() const { - return mark.value ? "woof" : "pantpant"; - } - - const marker& the_marker() const { - return mark; - } - }; - - sol::state lua; - lua.new_simple_usertype<bark>("bark", - sol::constructors<sol::types<>, sol::types<int>>(), - "fun", sol::protect( &bark::fun ), - "get", &bark::get, - "var", sol::as_function( &bark::var ), - "the_marker", &bark::the_marker, - "x", sol::overload(&bark::get), - "y", sol::overload(&bark::set), - "z", sol::overload(&bark::get, &bark::set) - ); - - lua.script("bx = bark.new(760)"); - bark& bx = lua["bx"]; - REQUIRE(bx.var == 760); - - lua.script("b = bark.new()"); - bark& b = lua["b"]; - - lua.script("b:fun()"); - int var = b.var; - REQUIRE(var == 51); - - lua.script("b:var(20)"); - lua.script("v = b:var()"); - int v = lua["v"]; - REQUIRE(v == 20); - - lua.script("m = b:the_marker()"); - marker& m = lua["m"]; - REQUIRE_FALSE(b.mark.value); - REQUIRE_FALSE(m.value); - m.value = true; - REQUIRE(&b.mark == &m); - REQUIRE(b.mark.value); - - sol::table barktable = lua["bark"]; - barktable["special"] = &bark::special; - - lua.script("s = b:special()"); - std::string s = lua["s"]; - REQUIRE(s == "woof"); - - lua.script("b:y(24)"); - lua.script("x = b:x()"); - int x = lua["x"]; - REQUIRE(x == 24); - - lua.script("z = b:z(b:z() + 5)"); - int z = lua["z"]; - REQUIRE(z == 29); -} - -TEST_CASE("usertype/simple-shared-ptr-regression", "simple usertype metatables should not screw over unique usertype metatables") { - static int created = 0; - static int destroyed = 0; - struct test { - test() { - ++created; - } - - ~test() { - ++destroyed; - } - }; - { - std::list<std::shared_ptr<test>> tests; - sol::state lua; - lua.open_libraries(); - - lua.new_simple_usertype<test>("test", - "create", [&]() -> std::shared_ptr<test> { - tests.push_back(std::make_shared<test>()); - return tests.back(); - } - ); - REQUIRE(created == 0); - REQUIRE(destroyed == 0); - lua.script("x = test.create()"); - REQUIRE(created == 1); - REQUIRE(destroyed == 0); - REQUIRE_FALSE(tests.empty()); - std::shared_ptr<test>& x = lua["x"]; - std::size_t xuse = x.use_count(); - std::size_t tuse = tests.back().use_count(); - REQUIRE(xuse == tuse); - } - REQUIRE(created == 1); - REQUIRE(destroyed == 1); -} - -TEST_CASE("usertype/simple-vars", "simple usertype vars can bind various values (no ref)") { - int muh_variable = 10; - int through_variable = 25; - - sol::state lua; - lua.open_libraries(); - - struct test {}; - lua.new_simple_usertype<test>("test", - "straight", sol::var(2), - "global", sol::var(muh_variable), - "global2", sol::var(through_variable), - "global3", sol::var(std::ref(through_variable)) - ); - - through_variable = 20; - - lua.script(R"( -print(test.straight) -s = test.straight -print(test.global) -g = test.global -print(test.global2) -g2 = test.global2 -print(test.global3) -g3 = test.global3 -)"); - - int s = lua["s"]; - int g = lua["g"]; - int g2 = lua["g2"]; - int g3 = lua["g3"]; - REQUIRE(s == 2); - REQUIRE(g == 10); - REQUIRE(g2 == 25); - REQUIRE(g3 == 20); -} - -TEST_CASE("usertypes/simple-variable-control", "test to see if usertypes respond to inheritance and variable controls") { - class A { - public: - virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; - }; - - class B : public A { - public: - virtual void a() override { } - }; - - class sA { - public: - virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; - }; - - class sB : public sA { - public: - virtual void a() override { } - }; - - struct sV { - int a = 10; - int b = 20; - - int get_b() const { - return b + 2; - } - - void set_b(int value) { - b = value; - } - }; - - struct sW : sV {}; - - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<A>("A", "a", &A::a); - lua.new_usertype<B>("B", sol::base_classes, sol::bases<A>()); - lua.new_simple_usertype<sA>("sA", "a", &sA::a); - lua.new_simple_usertype<sB>("sB", sol::base_classes, sol::bases<sA>()); - lua.new_simple_usertype<sV>("sV", "a", &sV::a, "b", &sV::b, "pb", sol::property(&sV::get_b, &sV::set_b)); - lua.new_simple_usertype<sW>("sW", sol::base_classes, sol::bases<sV>()); - - B b; - lua.set("b", &b); - lua.script("b:a()"); - - sB sb; - lua.set("sb", &sb); - lua.script("sb:a()"); - - sV sv; - lua.set("sv", &sv); - lua.script("print(sv.b)assert(sv.b == 20)"); - - sW sw; - lua.set("sw", &sw); - lua.script("print(sw.a)assert(sw.a == 10)"); - lua.script("print(sw.b)assert(sw.b == 20)"); - lua.script("print(sw.pb)assert(sw.pb == 22)"); - lua.script("sw.a = 11"); - lua.script("sw.b = 21"); - lua.script("print(sw.a)assert(sw.a == 11)"); - lua.script("print(sw.b)assert(sw.b == 21)"); - lua.script("print(sw.pb)assert(sw.pb == 23)"); - lua.script("sw.pb = 25"); - lua.script("print(sw.b)assert(sw.b == 25)"); - lua.script("print(sw.pb)assert(sw.pb == 27)"); -} - -TEST_CASE("usertype/simple-factory-constructor-overload-usage", "simple usertypes should probably invoke types") { - class A { - public: - virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; - }; - - class B : public A { - public: - int bvar = 24; - virtual void a() override { } - void f() {} - }; - - sol::state lua; - lua.open_libraries(); - sol::constructors<sol::types<>, sol::types<const B&>> c; - lua.new_simple_usertype<B>("B", - sol::call_constructor, c, - "new", sol::factories([]() { return B(); }), - "new2", sol::initializers([](B& mem) { new(&mem)B(); }, [](B& mem, int v) { new(&mem)B(); mem.bvar = v; }), - "f", sol::as_function(&B::bvar), - "g", sol::overload([](B&) { return 2; }, [](B&, int v) { return v; }) - ); - - lua.script("b = B()"); - lua.script("b2 = B.new()"); - lua.script("b3 = B.new2()"); - lua.script("b4 = B.new2(11)"); - - lua.script("x = b:f()"); - lua.script("x2 = b2:f()"); - lua.script("x3 = b3:f()"); - lua.script("x4 = b4:f()"); - int x = lua["x"]; - int x2 = lua["x2"]; - int x3 = lua["x3"]; - int x4 = lua["x4"]; - REQUIRE(x == 24); - REQUIRE(x2 == 24); - REQUIRE(x3 == 24); - REQUIRE(x4 == 11); - - lua.script("y = b:g()"); - lua.script("y2 = b2:g(3)"); - lua.script("y3 = b3:g()"); - lua.script("y4 = b4:g(3)"); - int y = lua["y"]; - int y2 = lua["y2"]; - int y3 = lua["y3"]; - int y4 = lua["y4"]; - REQUIRE(y == 2); - REQUIRE(y2 == 3); - REQUIRE(y3 == 2); - REQUIRE(y4 == 3); -} - -TEST_CASE("usertype/simple-runtime-append", "allow extra functions to be appended at runtime directly to the metatable itself") { - class A { - }; - - class B : public A { - }; - - sol::state lua; - lua.new_simple_usertype<A>("A"); - lua.new_simple_usertype<B>("B", sol::base_classes, sol::bases<A>()); - lua.set("b", std::make_unique<B>()); - lua["A"]["method"] = []() { return 200; }; - lua["B"]["method2"] = [](B&) { return 100; }; - lua.script("x = b.method()"); - lua.script("y = b:method()"); - - int x = lua["x"]; - int y = lua["y"]; - REQUIRE(x == 200); - REQUIRE(y == 200); - - lua.script("z = b.method2(b)"); - lua.script("w = b:method2()"); - int z = lua["z"]; - int w = lua["w"]; - REQUIRE(z == 100); - REQUIRE(w == 100); -} - -TEST_CASE("usertype/simple-destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") { - sol::state lua; - - class CrashClass { - public: - CrashClass() { - } - - ~CrashClass() { - a = 10; // This will cause a crash. - } - - private: - int a; - }; - - lua.new_simple_usertype<CrashClass>("CrashClass", - sol::call_constructor, sol::constructors<sol::types<>>() - ); - - lua.script(R"( - function testCrash() - local x = CrashClass() - end - )"); - - for (int i = 0; i < 1000; ++i) { - lua["testCrash"](); - } -} - -TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta table also affects the internal function table for pointers as well") { - struct A { - int func() { - return 5000; - } - }; - - sol::state lua; - lua.open_libraries(); - - lua.new_simple_usertype<A>("A"); - sol::table table = lua["A"]; - table["func"] = &A::func; - A a; - lua.set("a", &a); - lua.set("pa", &a); - lua.set("ua", std::make_unique<A>()); - REQUIRE_NOTHROW( - lua.script("assert(a:func() == 5000)"); - lua.script("assert(pa:func() == 5000)"); - lua.script("assert(ua:func() == 5000)"); - ); -} diff --git a/3rdparty/sol2/test_stack_guard.hpp b/3rdparty/sol2/test_stack_guard.hpp deleted file mode 100644 index d77ffb8b682..00000000000 --- a/3rdparty/sol2/test_stack_guard.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -struct test_stack_guard { - lua_State* L; - int& begintop; - int& endtop; - test_stack_guard(lua_State* L, int& begintop, int& endtop) : L(L), begintop(begintop), endtop(endtop) { - begintop = lua_gettop(L); - } - ~test_stack_guard() { endtop = lua_gettop(L); } -}; diff --git a/3rdparty/sol2/test_storage.cpp b/3rdparty/sol2/test_storage.cpp deleted file mode 100644 index f2b73aff262..00000000000 --- a/3rdparty/sol2/test_storage.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - -TEST_CASE("storage/registry=construction", "ensure entries from the registry can be retrieved") { - const auto& script = R"( -function f() - return 2 -end -)"; - - sol::state lua; - sol::function f = lua["f"]; - sol::reference r = lua["f"]; - sol::function regf(lua, f); - sol::reference regr(lua, sol::ref_index(f.registry_index())); - bool isequal = f == r; - REQUIRE(isequal); - isequal = f == regf; - REQUIRE(isequal); - isequal = f == regr; - REQUIRE(isequal); -} - -TEST_CASE("storage/main-thread", "ensure round-tripping and pulling out thread data even on 5.1 with a backup works") { - sol::state lua; - { - sol::stack_guard g(lua); - lua_State* orig = lua; - lua_State* ts = sol::main_thread(lua, lua); - REQUIRE(ts == orig); - } -} diff --git a/3rdparty/sol2/test_strings.cpp b/3rdparty/sol2/test_strings.cpp deleted file mode 100644 index 98396e204bd..00000000000 --- a/3rdparty/sol2/test_strings.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - -#include <iostream> - -struct test {}; -template <typename T> -struct test_t {}; - -namespace muh_namespace { - struct ns_test {}; - - namespace { - struct ns_anon_test {}; - } -} - -// There isn't a single library roundtripping which codecvt works on. We'll do the nitty-gritty of it later... -TEST_CASE("stack/strings", "test that strings can be roundtripped") { - sol::state lua; - - static const char utf8str[] = "\xF0\x9F\x8D\x8C\x20\xE6\x99\xA5\x20\x46\x6F\x6F\x20\xC2\xA9\x20\x62\x61\x72\x20\xF0\x9D\x8C\x86\x20\x62\x61\x7A\x20\xE2\x98\x83\x20\x71\x75\x78"; - static const char16_t utf16str[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 }; - static const char32_t utf32str[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 }; -#ifdef _WIN32 - INFO("win32 widestr"); - static const wchar_t widestr[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 }; -#else - INFO("non-windows widestr"); - static const wchar_t widestr[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 }; -#endif - static const std::string utf8str_s = utf8str; - static const std::u16string utf16str_s = utf16str; - static const std::u32string utf32str_s = utf32str; - static const std::wstring widestr_s = widestr; - -#ifdef SOL_CODECVT_SUPPORT - INFO("sizeof(wchar_t): " << sizeof(wchar_t)); - INFO("sizeof(char16_t): " << sizeof(char16_t)); - INFO("sizeof(char32_t): " << sizeof(char32_t)); - INFO("utf8str: " << utf8str); - INFO("utf8str_s: " << utf8str_s); - - lua["utf8"] = utf8str; - lua["utf16"] = utf16str; - lua["utf32"] = utf32str; - lua["wide"] = widestr; - - std::string utf8_to_utf8 = lua["utf8"]; - std::string utf16_to_utf8 = lua["utf16"]; - std::string utf32_to_utf8 = lua["utf32"]; - std::string wide_to_utf8 = lua["wide"]; - - REQUIRE(utf8_to_utf8 == utf8str_s); - REQUIRE(utf16_to_utf8 == utf8str_s); - REQUIRE(utf32_to_utf8 == utf8str_s); - REQUIRE(wide_to_utf8 == utf8str_s); - - std::wstring utf8_to_wide = lua["utf8"]; - std::wstring utf16_to_wide = lua["utf16"]; - std::wstring utf32_to_wide = lua["utf32"]; - std::wstring wide_to_wide = lua["wide"]; - - REQUIRE(utf8_to_wide == widestr_s); - REQUIRE(utf16_to_wide == widestr_s); - REQUIRE(utf32_to_wide == widestr_s); - REQUIRE(wide_to_wide == widestr_s); - - std::u16string utf8_to_utf16 = lua["utf8"]; - std::u16string utf16_to_utf16 = lua["utf16"]; - std::u16string utf32_to_utf16 = lua["utf32"]; - std::u16string wide_to_utf16 = lua["wide"]; - - REQUIRE(utf8_to_utf16 == utf16str_s); - REQUIRE(utf16_to_utf16 == utf16str_s); - REQUIRE(utf32_to_utf16 == utf16str_s); - REQUIRE(wide_to_utf16 == utf16str_s); - - std::u32string utf8_to_utf32 = lua["utf8"]; - std::u32string utf16_to_utf32 = lua["utf16"]; - std::u32string utf32_to_utf32 = lua["utf32"]; - std::u32string wide_to_utf32 = lua["wide"]; - - REQUIRE(utf8_to_utf32 == utf32str_s); - REQUIRE(utf16_to_utf32 == utf32str_s); - REQUIRE(utf32_to_utf32 == utf32str_s); - REQUIRE(wide_to_utf32 == utf32str_s); - - char32_t utf8_to_char32 = lua["utf8"]; - char32_t utf16_to_char32 = lua["utf16"]; - char32_t utf32_to_char32 = lua["utf32"]; - char32_t wide_to_char32 = lua["wide"]; - - REQUIRE(utf8_to_char32 == utf32str[0]); - REQUIRE(utf16_to_char32 == utf32str[0]); - REQUIRE(utf32_to_char32 == utf32str[0]); - REQUIRE(wide_to_char32 == utf32str[0]); -#endif // codecvt support -} - -TEST_CASE("detail/demangling", "test some basic demangling cases") { - std::string teststr = sol::detail::short_demangle<test>(); - std::string nsteststr = sol::detail::short_demangle<muh_namespace::ns_test>(); - std::string nsateststr = sol::detail::short_demangle<muh_namespace::ns_anon_test>(); - - REQUIRE(teststr == "test"); - REQUIRE(nsteststr == "ns_test"); - REQUIRE(nsateststr == "ns_anon_test"); -} - -TEST_CASE("object/string-pushers", "test some basic string pushers with in_place constructor") { - sol::state lua; - - sol::object ocs(lua, sol::in_place, "bark\0bark", 9); - sol::object os(lua, sol::in_place<std::string>, std::string("bark\0bark", 9), 8); - bool test1 = os.as<std::string>() == std::string("bark\0bar", 8); - bool test2 = ocs.as<std::string>() == std::string("bark\0bark", 9); - REQUIRE(test1); - REQUIRE(test2); -} diff --git a/3rdparty/sol2/test_tables.cpp b/3rdparty/sol2/test_tables.cpp deleted file mode 100644 index cb8f291ee09..00000000000 --- a/3rdparty/sol2/test_tables.cpp +++ /dev/null @@ -1,548 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - -#include <iostream> -#include <algorithm> -#include <numeric> -#include <vector> - -#include "test_stack_guard.hpp" - -std::string free_function() { - INFO("free_function()"); - return "test"; -} - -struct object { - std::string operator() () { - INFO("member_test()"); - return "test"; - } -}; - -int plop_xyz(int x, int y, std::string z) { - INFO(x << " " << y << " " << z); - return 11; -} - -TEST_CASE("tables/as-enums", "Making sure enums can be put in and gotten out as values") { - enum direction { - up, - down, - left, - right - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua["direction"] = lua.create_table_with( - "up", direction::up, - "down", direction::down, - "left", direction::left, - "right", direction::right - ); - - sol::object obj = lua["direction"]["up"]; - bool isdir = obj.is<direction>(); - REQUIRE(isdir); - auto dir = obj.as<direction>(); - REQUIRE(dir == direction::up); -} - -TEST_CASE("tables/as-enum-classes", "Making sure enums can be put in and gotten out as values") { - enum class direction { - up, - down, - left, - right - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua["direction"] = lua.create_table_with( - "up", direction::up, - "down", direction::down, - "left", direction::left, - "right", direction::right - ); - - sol::object obj = lua["direction"]["up"]; - bool isdir = obj.is<direction>(); - REQUIRE(isdir); - auto dir = obj.as<direction>(); - REQUIRE(dir == direction::up); -} - -TEST_CASE("tables/cleanup", "make sure tables leave the stack balanced") { - sol::state lua; - lua.open_libraries(); - - auto f = [] { return 5; }; - for (int i = 0; i < 30; i++) { - std::string name = std::string("init") + std::to_string(i); - int top = lua_gettop(lua); - lua[name] = f; - int aftertop = lua_gettop(lua); - REQUIRE(aftertop == top); - int val = lua[name](); - REQUIRE(val == 5); - } -} - -TEST_CASE("tables/nested-cleanup", "make sure tables leave the stack balanced") { - sol::state lua; - lua.open_libraries(); - - lua.script("A={}"); - auto f = [] { return 5; }; - for (int i = 0; i < 30; i++) { - std::string name = std::string("init") + std::to_string(i); - int top = lua_gettop(lua); - auto A = lua["A"]; - int beforetop = lua_gettop(lua); - REQUIRE(beforetop == top); - A[name] = f; - int aftertop = lua_gettop(lua); - REQUIRE(aftertop == top); - int val = A[name](); - REQUIRE(val == 5); - } -} - -TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as values") { - enum class direction { - up, - down, - left, - right - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_enum( "direction", - "up", direction::up, - "down", direction::down, - "left", direction::left, - "right", direction::right - ); - - direction d = lua["direction"]["left"]; - REQUIRE(d == direction::left); - REQUIRE_THROWS(lua.script("direction.left = 50")); - d = lua["direction"]["left"]; - REQUIRE(d == direction::left); -} - -TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a lua table") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("arr = {\n" - "[0] = \"Hi\",\n" - "[1] = 123.45,\n" - "[2] = \"String value\",\n" - // Does nothing - //"[3] = nil,\n" - //"[nil] = 3,\n" - "[\"WOOF\"] = 123,\n" - "}"); - sol::table tbl = lua["arr"]; - std::size_t tablesize = 4; - std::size_t iterations = 0; - auto fx = [&iterations](sol::object key, sol::object value) { - ++iterations; - sol::type keytype = key.get_type(); - switch (keytype) { - case sol::type::number: - switch (key.as<int>()) { - case 0: - REQUIRE((value.as<std::string>() == "Hi")); - break; - case 1: - REQUIRE((value.as<double>() == 123.45)); - break; - case 2: - REQUIRE((value.as<std::string>() == "String value")); - break; - case 3: - REQUIRE((value.is<sol::nil_t>())); - break; - } - break; - case sol::type::string: - if (key.as<std::string>() == "WOOF") { - REQUIRE((value.as<double>() == 123)); - } - break; - case sol::type::nil: - REQUIRE((value.as<double>() == 3)); - break; - default: - break; - } - }; - auto fxpair = [&fx](std::pair<sol::object, sol::object> kvp) { fx(kvp.first, kvp.second); }; - tbl.for_each(fx); - REQUIRE(iterations == tablesize); - - iterations = 0; - tbl.for_each(fxpair); - REQUIRE(iterations == tablesize); -} - -TEST_CASE("tables/for-each-empty", "empty tables should not crash") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("arr = {}"); - sol::table tbl = lua["arr"]; - REQUIRE(tbl.empty()); - std::size_t tablesize = 0; - std::size_t iterations = 0; - auto fx = [&iterations](sol::object key, sol::object value) { - ++iterations; - sol::type keytype = key.get_type(); - switch (keytype) { - case sol::type::number: - switch (key.as<int>()) { - case 0: - REQUIRE((value.as<std::string>() == "Hi")); - break; - case 1: - REQUIRE((value.as<double>() == 123.45)); - break; - case 2: - REQUIRE((value.as<std::string>() == "String value")); - break; - case 3: - REQUIRE((value.is<sol::nil_t>())); - break; - } - break; - case sol::type::string: - if (key.as<std::string>() == "WOOF") { - REQUIRE((value.as<double>() == 123)); - } - break; - case sol::type::nil: - REQUIRE((value.as<double>() == 3)); - break; - default: - break; - } - }; - auto fxpair = [&fx](std::pair<sol::object, sol::object> kvp) { fx(kvp.first, kvp.second); }; - tbl.for_each(fx); - REQUIRE(iterations == tablesize); - - iterations = 0; - tbl.for_each(fxpair); - REQUIRE(iterations == tablesize); - - iterations = 0; - for (const auto& kvp : tbl) { - fxpair(kvp); - ++iterations; - } - REQUIRE(iterations == tablesize); -} - -TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a lua table") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("arr = {\n" - "[0] = \"Hi\",\n" - "[1] = 123.45,\n" - "[2] = \"String value\",\n" - // Does nothing - //"[3] = nil,\n" - //"[nil] = 3,\n" - "[\"WOOF\"] = 123,\n" - "}"); - sol::table tbl = lua["arr"]; - std::size_t tablesize = 4; - std::size_t iterations = 0; - - int begintop = 0; - int endtop = 0; - { - test_stack_guard s(lua.lua_state(), begintop, endtop); - for (auto& kvp : tbl) { - [&iterations](sol::object key, sol::object value) { - ++iterations; - sol::type keytype = key.get_type(); - switch (keytype) { - case sol::type::number: - switch (key.as<int>()) { - case 0: - REQUIRE((value.as<std::string>() == "Hi")); - break; - case 1: - REQUIRE((value.as<double>() == 123.45)); - break; - case 2: - REQUIRE((value.as<std::string>() == "String value")); - break; - case 3: - REQUIRE((value.is<sol::nil_t>())); - break; - } - break; - case sol::type::string: - if (key.as<std::string>() == "WOOF") { - REQUIRE((value.as<double>() == 123)); - } - break; - case sol::type::nil: - REQUIRE((value.as<double>() == 3)); - break; - default: - break; - } - }(kvp.first, kvp.second); - } - } REQUIRE(begintop == endtop); - REQUIRE(iterations == tablesize); -} - -TEST_CASE("tables/variables", "Check if tables and variables work as intended") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::os); - lua.get<sol::table>("os").set("name", "windows"); - REQUIRE_NOTHROW(lua.script("assert(os.name == \"windows\")")); -} - -TEST_CASE("tables/create", "Check if creating a table is kosher") { - sol::state lua; - lua["testtable"] = sol::table::create(lua.lua_state(), 0, 0, "Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is<sol::table>()); - sol::table testtable = testobj.as<sol::table>(); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/create-local", "Check if creating a table is kosher") { - sol::state lua; - lua["testtable"] = lua.create_table(0, 0, "Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is<sol::table>()); - sol::table testtable = testobj.as<sol::table>(); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/create-local-named", "Check if creating a table is kosher") { - sol::state lua; - sol::table testtable = lua.create_table("testtable", 0, 0, "Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is<sol::table>()); - REQUIRE((testobj == testtable)); - REQUIRE_FALSE((testobj != testtable)); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/create-with-local", "Check if creating a table is kosher") { - sol::state lua; - lua["testtable"] = lua.create_table_with("Woof", "Bark", 1, 2, 3, 4); - sol::object testobj = lua["testtable"]; - REQUIRE(testobj.is<sol::table>()); - sol::table testtable = testobj.as<sol::table>(); - REQUIRE((testtable["Woof"] == std::string("Bark"))); - REQUIRE((testtable[1] == 2)); - REQUIRE((testtable[3] == 4)); -} - -TEST_CASE("tables/functions-variables", "Check if tables and function calls work as intended") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::os); - auto run_script = [](sol::state& lua) -> void { - lua.script("assert(os.fun() == \"test\")"); - }; - - lua.get<sol::table>("os").set_function("fun", - []() { - INFO("stateless lambda()"); - return "test"; - } - ); - REQUIRE_NOTHROW(run_script(lua)); - - lua.get<sol::table>("os").set_function("fun", &free_function); - REQUIRE_NOTHROW(run_script(lua)); - - // l-value, canNOT optimise - // prefer value semantics unless wrapped with std::reference_wrapper - { - auto lval = object(); - lua.get<sol::table>("os").set_function("fun", &object::operator(), lval); - } - REQUIRE_NOTHROW(run_script(lua)); - - auto reflval = object(); - lua.get<sol::table>("os").set_function("fun", &object::operator(), std::ref(reflval)); - REQUIRE_NOTHROW(run_script(lua)); - - - // stateful lambda: non-convertible, cannot be optimised - int breakit = 50; - lua.get<sol::table>("os").set_function("fun", - [&breakit]() { - INFO("stateful lambda()"); - return "test"; - } - ); - REQUIRE_NOTHROW(run_script(lua)); - - // r-value, cannot optimise - lua.get<sol::table>("os").set_function("fun", &object::operator(), object()); - REQUIRE_NOTHROW(run_script(lua)); - - // r-value, cannot optimise - auto rval = object(); - lua.get<sol::table>("os").set_function("fun", &object::operator(), std::move(rval)); - REQUIRE_NOTHROW(run_script(lua)); -} - -TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.script("foo = 20\nbar = \"hello world\""); - // basic retrieval - std::string bar = lua["bar"]; - int foo = lua["foo"]; - REQUIRE(bar == "hello world"); - REQUIRE(foo == 20); - // test operator= for stringification - // errors due to ambiguous operators - bar = lua["bar"]; - - // basic setting - lua["bar"] = 20.4; - lua["foo"] = "goodbye"; - - // doesn't modify the actual values obviously. - REQUIRE(bar == "hello world"); - REQUIRE(foo == 20); - - // function setting - lua["test"] = plop_xyz; - REQUIRE_NOTHROW(lua.script("assert(test(10, 11, \"hello\") == 11)")); - - // function retrieval - sol::function test = lua["test"]; - REQUIRE(test.call<int>(10, 11, "hello") == 11); - - // setting a lambda - lua["lamb"] = [](int x) { - return x * 2; - }; - - REQUIRE_NOTHROW(lua.script("assert(lamb(220) == 440)")); - - // function retrieval of a lambda - sol::function lamb = lua["lamb"]; - REQUIRE(lamb.call<int>(220) == 440); - - // test const table retrieval - auto assert1 = [](const sol::table& t) { - std::string a = t["foo"]; - double b = t["bar"]; - REQUIRE(a == "goodbye"); - REQUIRE(b == 20.4); - }; - - REQUIRE_NOTHROW(assert1(lua.globals())); -} - -TEST_CASE("tables/operator[]-valid", "Test if proxies on tables can lazily evaluate validity") { - sol::state lua; - bool isFullScreen = false; - auto fullscreennopers = lua["fullscreen"]["nopers"]; - auto fullscreen = lua["fullscreen"]; - REQUIRE_FALSE(fullscreennopers.valid()); - REQUIRE_FALSE(fullscreen.valid()); - - lua["fullscreen"] = true; - - REQUIRE_FALSE(fullscreennopers.valid()); - REQUIRE(fullscreen.valid()); - isFullScreen = lua["fullscreen"]; - REQUIRE(isFullScreen); - - lua["fullscreen"] = false; - REQUIRE_FALSE(fullscreennopers.valid()); - REQUIRE(fullscreen.valid()); - isFullScreen = lua["fullscreen"]; - REQUIRE_FALSE(isFullScreen); -} - -TEST_CASE("tables/operator[]-optional", "Test if proxies on tables can lazily evaluate validity") { - sol::state lua; - - sol::optional<int> test1 = lua["no_exist_yet"]; - bool present = (bool)test1; - REQUIRE_FALSE(present); - - lua["no_exist_yet"] = 262; - sol::optional<int> test2 = lua["no_exist_yet"]; - present = (bool)test2; - REQUIRE(present); - REQUIRE(test2.value() == 262); - - sol::optional<int> nope = lua["nope"]["kek"]["hah"]; - auto nope2 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah")); - present = (bool)nope; - REQUIRE_FALSE(present); - present = (bool)nope2; - REQUIRE_FALSE(present); - lua.create_named_table("nope", "kek", lua.create_table_with("hah", 1)); - sol::optional<int> non_nope = lua["nope"]["kek"]["hah"].get<sol::optional<int>>(); - sol::optional<int> non_nope2 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah")); - present = (bool)non_nope; - REQUIRE(present); - present = (bool)non_nope2; - REQUIRE(present); - REQUIRE(non_nope.value() == 1); - REQUIRE(non_nope2.value() == 1); - - INFO("Keys: nope, kek, hah"); - lua.set(std::make_tuple("nope", "kek", "hah"), 35); - sol::optional<int> non_nope3 = lua["nope"]["kek"]["hah"].get<sol::optional<int>>(); - sol::optional<int> non_nope4 = lua.get<sol::optional<int>>(std::make_tuple("nope", "kek", "hah")); - present = (bool)non_nope3; - REQUIRE(present); - present = (bool)non_nope4; - REQUIRE(present); - REQUIRE(non_nope3.value() == 35); - REQUIRE(non_nope4.value() == 35); -} - -TEST_CASE("tables/add", "Basic test to make sure the 'add' feature works") { - static const int sz = 120; - - sol::state lua; - sol::table t = lua.create_table(sz, 0); - - std::vector<int> bigvec( sz ); - std::iota(bigvec.begin(), bigvec.end(), 1); - - for (std::size_t i = 0; i < bigvec.size(); ++i) { - t.add(bigvec[i]); - } - for (std::size_t i = 0; i < bigvec.size(); ++i) { - int val = t[i + 1]; - REQUIRE(val == bigvec[i]); - } -} diff --git a/3rdparty/sol2/test_usertypes.cpp b/3rdparty/sol2/test_usertypes.cpp deleted file mode 100644 index 60adc73017c..00000000000 --- a/3rdparty/sol2/test_usertypes.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -#define SOL_CHECK_ARGUMENTS - -#include <sol.hpp> -#include <catch.hpp> - -#include <iostream> -#include <list> -#include <memory> -#include <mutex> - -struct vars { - vars() { - - } - - int boop = 0; - - ~vars() { - - } -}; - -struct fuser { - int x; - fuser() : x(0) {} - - fuser(int x) : x(x) {} - - int add(int y) { - return x + y; - } - - int add2(int y) { - return x + y + 2; - } -}; - -namespace crapola { - struct fuser { - int x; - fuser() : x(0) {} - fuser(int x) : x(x) {} - fuser(int x, int x2) : x(x * x2) {} - - int add(int y) { - return x + y; - } - int add2(int y) { - return x + y + 2; - } - }; -} // crapola - -class Base { -public: - Base(int a_num) : m_num(a_num) { } - - int get_num() { - return m_num; - } - -protected: - int m_num; -}; - -class Derived : public Base { -public: - Derived(int a_num) : Base(a_num) { } - - int get_num_10() { - return 10 * m_num; - } -}; - -class abstract_A { -public: - virtual void a() = 0; -}; - -class abstract_B : public abstract_A { -public: - virtual void a() override { - INFO("overridden a() in B : public A - BARK"); - } -}; - -struct Vec { - float x, y, z; - Vec(float x, float y, float z) : x{ x }, y{ y }, z{ z } {} - float length() { - return sqrtf(x*x + y*y + z*z); - } - Vec normalized() { - float invS = 1 / length(); - return{ x * invS, y * invS, z * invS }; - } -}; - -struct giver { - int a = 0; - - giver() { - - } - - void gief() { - a = 1; - } - - static void stuff() { - - } - - static void gief_stuff(giver& t, int a) { - t.a = a; - } - - ~giver() { - - } - -}; - -struct factory_test { -private: - factory_test() { a = true_a; } - ~factory_test() { a = 0; } -public: - static int num_saved; - static int num_killed; - - struct deleter { - void operator()(factory_test* f) { - f->~factory_test(); - } - }; - - static const int true_a; - int a; - - static std::unique_ptr<factory_test, deleter> make() { - return std::unique_ptr<factory_test, deleter>(new factory_test(), deleter()); - } - - static void save(factory_test& f) { - new(&f)factory_test(); - ++num_saved; - } - - static void kill(factory_test& f) { - f.~factory_test(); - ++num_killed; - } -}; - -int factory_test::num_saved = 0; -int factory_test::num_killed = 0; -const int factory_test::true_a = 156; - -bool something() { - return true; -} - -struct thing { - int v = 100; - - thing() {} - thing(int x) : v(x) {} -}; - -struct self_test { - int bark; - - self_test() : bark(100) { - - } - - void g(const std::string& str) { - std::cout << str << '\n'; - bark += 1; - } - - void f(const self_test& t) { - std::cout << "got test" << '\n'; - if (t.bark != bark) - throw sol::error("bark values are not the same for self_test f function"); - if (&t != this) - throw sol::error("call does not reference self for self_test f function"); - } -}; - -struct ext_getset { - - int bark = 24; - const int meow = 56; - - ext_getset() = default; - ext_getset(int v) : bark(v) {} - ext_getset(ext_getset&&) = default; - ext_getset(const ext_getset&) = delete; - ext_getset& operator=(ext_getset&&) = default; - ext_getset& operator=(const ext_getset&) = delete; - ~ext_getset() { - - } - - std::string x() { - return "bark bark bark"; - } - - int x2(std::string x) { - return static_cast<int>(x.length()); - } - - void set(sol::variadic_args, sol::this_state, int x) { - bark = x; - } - - int get(sol::this_state, sol::variadic_args) { - return bark; - } - - static void s_set(int) { - - } - - static int s_get(int x) { - return x + 20; - } - -}; - -template <typename T> -void des(T& e) { - e.~T(); -} - -struct matrix_xf { - float a, b; - - static matrix_xf from_lua_table(sol::table t) { - matrix_xf m; - m.a = t[1][1]; - m.b = t[1][2]; - return m; - } -}; - -struct matrix_xi { - int a, b; - - static matrix_xi from_lua_table(sol::table t) { - matrix_xi m; - m.a = t[1][1]; - m.b = t[1][2]; - return m; - } -}; - -TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") { - sol::state lua; - - sol::usertype<fuser> lc{ "add", &fuser::add, "add2", &fuser::add2 }; - lua.set_usertype(lc); - - lua.script("a = fuser:new()\n" - "b = a:add(1)\n" - "c = a:add2(1)\n"); - - sol::object a = lua.get<sol::object>("a"); - sol::object b = lua.get<sol::object>("b"); - sol::object c = lua.get<sol::object>("c"); - REQUIRE((a.is<sol::userdata_value>())); - auto atype = a.get_type(); - auto btype = b.get_type(); - auto ctype = c.get_type(); - REQUIRE((atype == sol::type::userdata)); - REQUIRE((btype == sol::type::number)); - REQUIRE((ctype == sol::type::number)); - int bresult = b.as<int>(); - int cresult = c.as<int>(); - REQUIRE(bresult == 1); - REQUIRE(cresult == 3); -} - -TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") { - - sol::state lua; - - sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>> con; - sol::usertype<crapola::fuser> lc(con, "add", &crapola::fuser::add, "add2", &crapola::fuser::add2); - lua.set_usertype(lc); - - lua.script( - "a = fuser.new(2)\n" - "u = a:add(1)\n" - "v = a:add2(1)\n" - "b = fuser:new()\n" - "w = b:add(1)\n" - "x = b:add2(1)\n" - "c = fuser.new(2, 3)\n" - "y = c:add(1)\n" - "z = c:add2(1)\n"); - sol::object a = lua.get<sol::object>("a"); - auto atype = a.get_type(); - REQUIRE((atype == sol::type::userdata)); - sol::object u = lua.get<sol::object>("u"); - sol::object v = lua.get<sol::object>("v"); - REQUIRE((u.as<int>() == 3)); - REQUIRE((v.as<int>() == 5)); - - sol::object b = lua.get<sol::object>("b"); - auto btype = b.get_type(); - REQUIRE((btype == sol::type::userdata)); - sol::object w = lua.get<sol::object>("w"); - sol::object x = lua.get<sol::object>("x"); - REQUIRE((w.as<int>() == 1)); - REQUIRE((x.as<int>() == 3)); - - sol::object c = lua.get<sol::object>("c"); - auto ctype = c.get_type(); - REQUIRE((ctype == sol::type::userdata)); - sol::object y = lua.get<sol::object>("y"); - sol::object z = lua.get<sol::object>("z"); - REQUIRE((y.as<int>() == 7)); - REQUIRE((z.as<int>() == 9)); -} - -TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") { - sol::state lua; - - lua.new_usertype<fuser>("fuser", "add", &fuser::add, "add2", &fuser::add2); - - lua.script("a = fuser.new()\n" - "b = a:add(1)\n" - "c = a:add2(1)\n"); - - sol::object a = lua.get<sol::object>("a"); - sol::object b = lua.get<sol::object>("b"); - sol::object c = lua.get<sol::object>("c"); - REQUIRE((a.is<sol::userdata_value>())); - auto atype = a.get_type(); - auto btype = b.get_type(); - auto ctype = c.get_type(); - REQUIRE((atype == sol::type::userdata)); - REQUIRE((btype == sol::type::number)); - REQUIRE((ctype == sol::type::number)); - int bresult = b.as<int>(); - int cresult = c.as<int>(); - REQUIRE(bresult == 1); - REQUIRE(cresult == 3); -} - -TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") { - sol::state lua; - lua.open_libraries(sol::lib::base); - sol::constructors<sol::types<int>> basector; - sol::usertype<Base> baseusertype(basector, "get_num", &Base::get_num); - - lua.set_usertype(baseusertype); - - lua.script("base = Base.new(5)"); - REQUIRE_NOTHROW(lua.script("print(base:get_num())")); - - sol::constructors<sol::types<int>> derivedctor; - sol::usertype<Derived> derivedusertype(derivedctor, - "get_num_10", &Derived::get_num_10, - "get_num", &Derived::get_num - ); - - lua.set_usertype(derivedusertype); - - lua.script("derived = Derived.new(7)"); - lua.script("dgn = derived:get_num()\n" - "print(dgn)"); - lua.script("dgn10 = derived:get_num_10()\n" - "print(dgn10)"); - - REQUIRE((lua.get<int>("dgn10") == 70)); - REQUIRE((lua.get<int>("dgn") == 7)); -} - -TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<self_test>("test", "g", &self_test::g, "f", &self_test::f); - - lua.script( - "local a = test.new()\n" - "a:g(\"woof\")\n" - "a:f(a)\n" - ); -} - -TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") { - struct test { - int x = 0; - test& set() { - x = 10; - return *this; - } - - int get() { - return x; - } - - test* pget() { - return this; - } - - test create_get() { - return *this; - } - - int fun(int xa) { - return xa * 10; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<test>("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get); - REQUIRE_NOTHROW(lua.script("x = test.new()")); - REQUIRE_NOTHROW(lua.script("assert(x:set():get() == 10)")); - REQUIRE_NOTHROW(lua.script("y = x:pointer_get()")); - REQUIRE_NOTHROW(lua.script("y:set():get()")); - REQUIRE_NOTHROW(lua.script("y:fun(10)")); - REQUIRE_NOTHROW(lua.script("x:fun(10)")); - REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == x:fun(10), '...')")); - REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == 100, '...')")); - REQUIRE_NOTHROW(lua.script("assert(y:set():get() == y:set():get(), '...')")); - REQUIRE_NOTHROW(lua.script("assert(y:set():get() == 10, '...')")); -} - -TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - sol::constructors<sol::types<float, float, float>> ctor; - sol::usertype<Vec> udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length); - lua.set_usertype(udata); - - REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" - "print(v:length())")); - REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" - "print(v:normalized():length())")); -} - -TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - { - sol::constructors<sol::types<float, float, float>> ctor; - sol::usertype<Vec> udata(ctor, - "normalized", &Vec::normalized, - "length", &Vec::length); - - lua.set_usertype(udata); - // usertype dies, but still usable in lua! - } - - REQUIRE_NOTHROW(lua.script("collectgarbage()\n" - "v = Vec.new(1, 2, 3)\n" - "print(v:length())")); - - REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" - "print(v:normalized():length())")); -} - -TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") { - sol::state lua; - lua.open_libraries(sol::lib::base); - sol::constructors<sol::types<float, float, float>> ctor; - sol::usertype<Vec> udata(ctor, - "x", &Vec::x, - "y", &Vec::y, - "z", &Vec::z, - "normalized", &Vec::normalized, - "length", &Vec::length); - lua.set_usertype(udata); - - REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" - "v2 = Vec.new(0, 1, 0)\n" - "print(v:length())\n" - )); - REQUIRE_NOTHROW(lua.script("v.x = 2\n" - "v2.y = 2\n" - "print(v.x, v.y, v.z)\n" - "print(v2.x, v2.y, v2.z)\n" - )); - REQUIRE_NOTHROW(lua.script("assert(v.x == 2)\n" - "assert(v2.x == 0)\n" - "assert(v2.y == 2)\n" - )); - REQUIRE_NOTHROW(lua.script("v.x = 3\n" - "local x = v.x\n" - "assert(x == 3)\n" - )); - - struct breaks { - sol::function f; - }; - - lua.open_libraries(sol::lib::base); - lua.set("b", breaks()); - lua.new_usertype<breaks>("breaks", - "f", &breaks::f - ); - - breaks& b = lua["b"]; - REQUIRE_NOTHROW(lua.script("b.f = function () print('BARK!') end")); - REQUIRE_NOTHROW(lua.script("b.f()")); - REQUIRE_NOTHROW(b.f()); -} - -TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<giver>("giver", - "gief_stuff", giver::gief_stuff, - "gief", &giver::gief, - "__tostring", [](const giver& t) { - return std::to_string(t.a) + ": giving value"; - } - ).get<sol::table>("giver") - .set_function("stuff", giver::stuff); - - REQUIRE_NOTHROW(lua.script("giver.stuff()")); - REQUIRE_NOTHROW(lua.script("t = giver.new()\n" - "print(tostring(t))\n" - "t:gief()\n" - "t:gief_stuff(20)\n")); - giver& g = lua.get<giver>("t"); - REQUIRE(g.a == 20); -} - -TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique and shared pointers ('unique usertypes')") { - const int64_t unique_value = 0x7125679355635963; - auto uniqueint = std::make_unique<int64_t>(unique_value); - auto sharedint = std::make_shared<int64_t>(unique_value); - long preusecount = sharedint.use_count(); - { sol::state lua; - lua.open_libraries(sol::lib::base); - lua.set("uniqueint", std::move(uniqueint)); - lua.set("sharedint", sharedint); - std::unique_ptr<int64_t>& uniqueintref = lua["uniqueint"]; - std::shared_ptr<int64_t>& sharedintref = lua["sharedint"]; - int64_t* rawuniqueintref = lua["uniqueint"]; - int64_t* rawsharedintref = lua["sharedint"]; - int siusecount = sharedintref.use_count(); - REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref)); - REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr)); - REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get())); - REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref)); - REQUIRE(siusecount == sharedint.use_count()); - std::shared_ptr<int64_t> moreref = sharedint; - REQUIRE(unique_value == *moreref.get()); - REQUIRE(moreref.use_count() == sharedint.use_count()); - REQUIRE(moreref.use_count() == sharedintref.use_count()); - } - REQUIRE(preusecount == sharedint.use_count()); -} - -TEST_CASE("regressions/one", "issue number 48") { - sol::state lua; - lua.new_usertype<vars>("vars", - "boop", &vars::boop); - REQUIRE_NOTHROW(lua.script("beep = vars.new()\n" - "beep.boop = 1")); - // test for segfault - auto my_var = lua.get<vars>("beep"); - REQUIRE(my_var.boop == 1); - auto* ptr = &my_var; - REQUIRE(ptr->boop == 1); -} - -TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified<T> on the type...") { - sol::state lua; - - lua.new_usertype<vars>("vars", - "boop", &vars::boop); - vars var{}; - vars rvar{}; - lua.set("beep", var); - lua.set("rbeep", std::ref(rvar)); - auto& my_var = lua.get<vars>("beep"); - auto& ref_var = lua.get<std::reference_wrapper<vars>>("rbeep"); - vars& proxy_my_var = lua["beep"]; - std::reference_wrapper<vars> proxy_ref_var = lua["rbeep"]; - var.boop = 2; - rvar.boop = 5; - - // Was return as a value: var must be diferent from "beep" - REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var)); - REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var)); - REQUIRE((my_var.boop == 0)); - REQUIRE(var.boop != my_var.boop); - - REQUIRE(std::addressof(ref_var) == std::addressof(rvar)); - REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar)); - REQUIRE(rvar.boop == 5); - REQUIRE(rvar.boop == ref_var.boop); -} - -TEST_CASE("usertype/destructor-tests", "Show that proper copies / destruction happens") { - static int created = 0; - static int destroyed = 0; - static void* last_call = nullptr; - struct x { - x() { ++created; } - x(const x&) { ++created; } - x(x&&) { ++created; } - x& operator=(const x&) { return *this; } - x& operator=(x&&) { return *this; } - ~x() { ++destroyed; } - }; - { - sol::state lua; - lua.new_usertype<x>("x"); - x x1; - x x2; - lua.set("x1copy", x1, "x2copy", x2, "x1ref", std::ref(x1)); - x& x1copyref = lua["x1copy"]; - x& x2copyref = lua["x2copy"]; - x& x1ref = lua["x1ref"]; - REQUIRE(created == 4); - REQUIRE(destroyed == 0); - REQUIRE(std::addressof(x1) == std::addressof(x1ref)); - REQUIRE(std::addressof(x1copyref) != std::addressof(x1)); - REQUIRE(std::addressof(x2copyref) != std::addressof(x2)); - } - REQUIRE(created == 4); - REQUIRE(destroyed == 4); -} - -TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") { - int numsaved = factory_test::num_saved; - int numkilled = factory_test::num_killed; - { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<factory_test>("factory_test", - "new", sol::initializers(factory_test::save), - "__gc", sol::destructor(factory_test::kill), - "a", &factory_test::a - ); - - std::unique_ptr<factory_test, factory_test::deleter> f = factory_test::make(); - lua.set("true_a", factory_test::true_a, "f", f.get()); - REQUIRE_NOTHROW(lua.script("assert(f.a == true_a)")); - - REQUIRE_NOTHROW(lua.script( - "local fresh_f = factory_test:new()\n" - "assert(fresh_f.a == true_a)\n")); - } - int expectednumsaved = numsaved + 1; - int expectednumkilled = numkilled + 1; - REQUIRE(expectednumsaved == factory_test::num_saved); - REQUIRE(expectednumkilled == factory_test::num_killed); -} - -TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") { - struct A { int x = 201; }; - struct B { - int foo(const A* a) { return a->x; }; - }; - - sol::state lua; - lua.new_usertype<B>("B", - "foo", &B::foo - ); - lua.set("a", A()); - lua.set("b", B()); - lua.script("x = b:foo(a)"); - int x = lua["x"]; - REQUIRE(x == 201); -} - -TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") { - struct woof { - int var; - - int func(int x) { - return var + x; - } - - double func2(int x, int y) { - return var + x + y + 0.5; - } - - std::string func2s(int x, std::string y) { - return y + " " + std::to_string(x); - } - }; - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<woof>("woof", - "var", &woof::var, - "func", sol::overload(&woof::func, &woof::func2, &woof::func2s) - ); - - const std::string bark_58 = "bark 58"; - - REQUIRE_NOTHROW(lua.script( - "r = woof:new()\n" - "a = r:func(1)\n" - "b = r:func(1, 2)\n" - "c = r:func(58, 'bark')\n" - )); - REQUIRE((lua["a"] == 1)); - REQUIRE((lua["b"] == 3.5)); - REQUIRE((lua["c"] == bark_58)); - - REQUIRE_THROWS(lua.script("r:func(1,2,'meow')")); -} - -TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") { - struct overloading_test { - int print(int i) { INFO("Integer print: " << i); return 500 + i; } - int print() { INFO("No param print."); return 500; } - }; - - sol::state lua; - lua.new_usertype<overloading_test>("overloading_test", sol::constructors<>(), - "print", sol::overload(static_cast<int (overloading_test::*)(int)>(&overloading_test::print), static_cast<int (overloading_test::*)()>(&overloading_test::print)), - "print2", sol::overload(static_cast<int (overloading_test::*)()>(&overloading_test::print), static_cast<int (overloading_test::*)(int)>(&overloading_test::print)) - ); - lua.set("test", overloading_test()); - - sol::function f0_0 = lua.load("return test:print()"); - sol::function f0_1 = lua.load("return test:print2()"); - sol::function f1_0 = lua.load("return test:print(24)"); - sol::function f1_1 = lua.load("return test:print2(24)"); - int res = f0_0(); - int res2 = f0_1(); - int res3 = f1_0(); - int res4 = f1_1(); - - REQUIRE(res == 500); - REQUIRE(res2 == 500); - - REQUIRE(res3 == 524); - REQUIRE(res4 == 524); -} - -TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") { - struct bark { - int var = 50; - }; - struct woof { - bark b; - }; - - struct nested { - const int f = 25; - }; - - struct outer { - nested n; - }; - - sol::state lua; - lua.new_usertype<woof>("woof", - "b", &woof::b); - lua.new_usertype<bark>("bark", - "var", &bark::var); - lua.new_usertype<outer>("outer", - "n", &outer::n); - lua.set("w", woof()); - lua.set("n", nested()); - lua.set("o", outer()); - lua.set("f", sol::c_call<decltype(&nested::f), &nested::f>); - lua.script(R"( - x = w.b - x.var = 20 - val = w.b.var == x.var - v = f(n); - )"); - - woof& w = lua["w"]; - bark& x = lua["x"]; - nested& n = lua["n"]; - int v = lua["v"]; - bool val = lua["val"]; - // enforce reference semantics - REQUIRE(std::addressof(w.b) == std::addressof(x)); - REQUIRE(n.f == 25); - REQUIRE(v == 25); - REQUIRE(val); - - REQUIRE_THROWS(lua.script("f(n, 50)")); - REQUIRE_THROWS(lua.script("o.n = 25")); -} - -TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions can be called on userdata and from their originating (meta)tables") { - struct bark { - int var = 50; - - void func() {} - - static void oh_boy() {} - - static int oh_boy(std::string name) { - return static_cast<int>(name.length()); - } - - int operator()(int x) { - return x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<bark>("bark", - "var", &bark::var, - "var2", sol::readonly(&bark::var), - "something", something, - "something2", [](int x, int y) { return x + y; }, - "func", &bark::func, - "oh_boy", sol::overload(sol::resolve<void()>(&bark::oh_boy), sol::resolve<int(std::string)>(&bark::oh_boy)), - sol::meta_function::call_function, &bark::operator() - ); - - REQUIRE_NOTHROW(lua.script("assert(bark.oh_boy('woo') == 3)")); - REQUIRE_NOTHROW(lua.script("bark.oh_boy()")); - - bark b; - lua.set("b", &b); - - sol::table b_table = lua["b"]; - sol::function member_func = b_table["func"]; - sol::function s = b_table["something"]; - sol::function s2 = b_table["something2"]; - - sol::table b_metatable = b_table[sol::metatable_key]; - bool isvalidmt = b_metatable.valid(); - REQUIRE(isvalidmt); - sol::function b_call = b_metatable["__call"]; - sol::function b_as_function = lua["b"]; - - int x = b_as_function(1); - int y = b_call(b, 1); - bool z = s(); - int w = s2(2, 3); - REQUIRE(x == 1); - REQUIRE(y == 1); - REQUIRE(z); - REQUIRE(w == 5); - - lua.script(R"( -lx = b(1) -ly = getmetatable(b).__call(b, 1) -lz = b.something() -lz2 = bark.something() -lw = b.something2(2, 3) -lw2 = bark.something2(2, 3) - )"); - - int lx = lua["lx"]; - int ly = lua["ly"]; - bool lz = lua["lz"]; - int lw = lua["lw"]; - bool lz2 = lua["lz2"]; - int lw2 = lua["lw2"]; - REQUIRE(lx == 1); - REQUIRE(ly == 1); - REQUIRE(lz); - REQUIRE(lz2); - REQUIRE(lw == 5); - REQUIRE(lw2 == 5); - REQUIRE(lx == ly); - REQUIRE(lz == lz2); - REQUIRE(lw == lw2); - - REQUIRE_THROWS(lua.script("b.var2 = 2")); -} - -TEST_CASE("usertype/properties", "Check if member properties/variables work") { - struct bark { - int var = 50; - int var2 = 25; - - int get_var2() const { - return var2; - } - - int get_var3() { - return var2; - } - - void set_var2(int x) { - var2 = x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<bark>("bark", - "var", &bark::var, - "var2", sol::readonly(&bark::var2), - "a", sol::property(&bark::get_var2, &bark::set_var2), - "b", sol::property(&bark::get_var2), - "c", sol::property(&bark::get_var3), - "d", sol::property(&bark::set_var2) - ); - - bark b; - lua.set("b", &b); - - lua.script("b.a = 59"); - lua.script("var2_0 = b.a"); - lua.script("var2_1 = b.b"); - lua.script("b.d = 1568"); - lua.script("var2_2 = b.c"); - - int var2_0 = lua["var2_0"]; - int var2_1 = lua["var2_1"]; - int var2_2 = lua["var2_2"]; - REQUIRE(var2_0 == 59); - REQUIRE(var2_1 == 59); - REQUIRE(var2_2 == 1568); - - REQUIRE_THROWS(lua.script("b.var2 = 24")); - REQUIRE_THROWS(lua.script("r = b.d")); - REQUIRE_THROWS(lua.script("r = b.d")); - REQUIRE_THROWS(lua.script("b.b = 25")); - REQUIRE_THROWS(lua.script("b.c = 11")); -} - -TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") { - class Test { - public: - void sayHello() { std::cout << "Hey\n"; } - }; - - sol::state lua; - lua.new_usertype<Test>("Test", "sayHello", &Test::sayHello); - static const std::string code = R"( - local t = Test.new() - t:sayHello() --Works fine - t.sayHello() --Uh oh. - )"; - REQUIRE_THROWS(lua.script(code)); -} - -TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<thing>("thing", - "v", &thing::v - , sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>() - ); - - lua.script(R"( -t = thing(256) -)"); - - thing& y = lua["t"]; - INFO(y.v); - REQUIRE(y.v == 256); -} - -TEST_CASE("usertype/call_constructor-factories", "make sure tables can be passed to factory-based call constructors") { - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<matrix_xf>("mat", - sol::call_constructor, sol::factories(&matrix_xf::from_lua_table) - ); - - lua.script("m = mat{ {1.1, 2.2} }"); - - lua.new_usertype<matrix_xi>("mati", - sol::call_constructor, sol::factories(&matrix_xi::from_lua_table) - ); - - lua.script("mi = mati{ {1, 2} }"); - - matrix_xf& m = lua["m"]; - REQUIRE(m.a == 1.1f); - REQUIRE(m.b == 2.2f); - matrix_xi& mi = lua["mi"]; - REQUIRE(mi.a == 1); - REQUIRE(mi.b == 2); -} - -TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") { - class class01 { - public: - int x = 57; - class01() {} - }; - - class class02 { - public: - int x = 50; - class02() {} - class02(const class01& other) : x(other.x) {} - }; - - sol::state lua; - - lua.new_usertype<class01>("class01", - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class01&>>() - ); - - lua.new_usertype<class02>("class02", - sol::call_constructor, sol::constructors<sol::types<>, sol::types<const class02&>, sol::types<const class01&>>() - ); - - REQUIRE_NOTHROW(lua.script(R"( -x = class01() -y = class02(x) -)")); - class02& y = lua["y"]; - REQUIRE(y.x == 57); -} - -TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<thing>("thing", - "v", &thing::v - , sol::call_constructor, sol::constructors<>() - ); - - REQUIRE_THROWS(lua.script("t = thing(256)")); -} - - -TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - SECTION("order1") - { - lua.new_usertype<thing>("thing", - "v", &thing::v - , sol::call_constructor, sol::no_constructor - ); - REQUIRE_THROWS(lua.script("t = thing.new()")); - } - - SECTION("order2") - { - lua.new_usertype<thing>("thing" - , sol::call_constructor, sol::no_constructor - , "v", &thing::v - ); - REQUIRE_THROWS(lua.script("t = thing.new()")); - } - - REQUIRE_THROWS(lua.script("t = thing.new()")); -} - -TEST_CASE("usertype/coverage", "try all the things") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<ext_getset>("ext_getset", - sol::call_constructor, sol::constructors<sol::types<>, sol::types<int>>(), - sol::meta_function::garbage_collect, sol::destructor(des<ext_getset>), - "x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) { - return m.meow + 50 + y + x.length(); - }), - "bark", &ext_getset::bark, - "meow", &ext_getset::meow, - "readonlybark", sol::readonly(&ext_getset::bark), - "set", &ext_getset::set, - "get", &ext_getset::get, - "sset", &ext_getset::s_set, - "sget", &ext_getset::s_get, - "propbark", sol::property(&ext_getset::set, &ext_getset::get), - "readonlypropbark", sol::property(&ext_getset::get), - "writeonlypropbark", sol::property(&ext_getset::set) - ); - - INFO("usertype created"); - - lua.script(R"( -e = ext_getset() -w = e:x(e:x(), e:x(e:x())) -print(w) -)"); - - int w = lua["w"]; - REQUIRE(w == (56 + 50 + 14 + 14)); - - INFO("REQUIRE(w) successful"); - - lua.script(R"( -e:set(500) -e.sset(24) -x = e:get() -y = e.sget(20) -)"); - - int x = lua["x"]; - int y = lua["y"]; - REQUIRE(x == 500); - REQUIRE(y == 40); - - INFO("REQUIRE(x, y) successful"); - - lua.script(R"( -e.bark = 5001 -a = e:get() -print(e.bark) -print(a) - -e.propbark = 9700 -b = e:get() -print(e.propbark) -print(b) -)"); - int a = lua["a"]; - int b = lua["b"]; - - REQUIRE(a == 5001); - REQUIRE(b == 9700); - - INFO("REQUIRE(a, b) successful"); - - lua.script(R"( -c = e.readonlybark -d = e.meow -print(e.readonlybark) -print(c) -print(e.meow) -print(d) -)"); - - int c = lua["c"]; - int d = lua["d"]; - REQUIRE(c == 9700); - REQUIRE(d == 56); - - INFO("REQUIRE(c, d) successful"); - - lua.script(R"( -e.writeonlypropbark = 500 -z = e.readonlypropbark -print(e.readonlybark) -print(e.bark) -)"); - - int z = lua["z"]; - REQUIRE(z == 500); - - INFO("REQUIRE(z) successful"); - - REQUIRE_THROWS(lua.script("e.readonlybark = 24")); - INFO("REQUIRE_THROWS 1 successful"); - REQUIRE_THROWS(lua.script("e.readonlypropbark = 500")); - INFO("REQUIRE_THROWS 2 successful"); - REQUIRE_THROWS(lua.script("y = e.writeonlypropbark")); - INFO("REQUIRE_THROWS 3 successful"); - -} - -TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") { - struct NoCopy { - int get() const { return _you_can_copy_me; } - void set(int val) { _you_can_copy_me = val; } - - int _you_can_copy_me; - std::mutex _haha_you_cant_copy_me; - }; - - sol::state lua; - lua.new_usertype<NoCopy>("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set)); - - REQUIRE_NOTHROW( - lua.script(R"__( -nocopy = NoCopy.new() -nocopy.val = 5 - )__") - ); -} - -TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") { - struct protect_me { - int gen(int x) { - return x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<protect_me>("protect_me", - "gen", sol::protect( &protect_me::gen ) - ); - - REQUIRE_NOTHROW( - lua.script(R"__( -pm = protect_me.new() -value = pcall(pm.gen,pm) -)__"); - ); - bool value = lua["value"]; - REQUIRE_FALSE(value); -} - -TEST_CASE("usertype/shared-ptr-regression", "usertype metatables should not screw over unique usertype metatables") { - static int created = 0; - static int destroyed = 0; - struct test { - test() { - ++created; - } - - ~test() { - ++destroyed; - } - }; - { - std::list<std::shared_ptr<test>> tests; - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<test>("test", - "create", [&]() -> std::shared_ptr<test> { - tests.push_back(std::make_shared<test>()); - return tests.back(); - } - ); - REQUIRE(created == 0); - REQUIRE(destroyed == 0); - lua.script("x = test.create()"); - REQUIRE(created == 1); - REQUIRE(destroyed == 0); - REQUIRE_FALSE(tests.empty()); - std::shared_ptr<test>& x = lua["x"]; - std::size_t xuse = x.use_count(); - std::size_t tuse = tests.back().use_count(); - REQUIRE(xuse == tuse); - } - REQUIRE(created == 1); - REQUIRE(destroyed == 1); -} - -TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must not rely on internal ") { - struct c_a { int x; }; - struct c_b { int y; }; - REQUIRE_NOTHROW( { - sol::state lua; - lua.new_usertype<c_a>("c_a", "x", &c_a::x); - lua.new_usertype<c_b>("c_b", "y", &c_b::y); - lua = sol::state(); - lua.new_usertype<c_a>("c_a", "x", &c_a::x); - lua.new_usertype<c_b>("c_b", "y", &c_b::y); - lua = sol::state(); - }); -} - -TEST_CASE("usertype/vars", "usertype vars can bind various class items") { - static int muh_variable = 25; - static int through_variable = 10; - - sol::state lua; - lua.open_libraries(); - struct test {}; - lua.new_usertype<test>("test", - "straight", sol::var(2), - "global", sol::var(muh_variable), - "ref_global", sol::var(std::ref(muh_variable)), - "global2", sol::var(through_variable), - "ref_global2", sol::var(std::ref(through_variable)) - ); - - int prets = lua["test"]["straight"]; - int pretg = lua["test"]["global"]; - int pretrg = lua["test"]["ref_global"]; - int pretg2 = lua["test"]["global2"]; - int pretrg2 = lua["test"]["ref_global2"]; - - REQUIRE(prets == 2); - REQUIRE(pretg == 25); - REQUIRE(pretrg == 25); - REQUIRE(pretg2 == 10); - REQUIRE(pretrg2 == 10); - - lua.script(R"( -print(test.straight) -test.straight = 50 -print(test.straight) -)"); - int s = lua["test"]["straight"]; - REQUIRE(s == 50); - - lua.script(R"( -t = test.new() -print(t.global) -t.global = 50 -print(t.global) -)"); - int mv = lua["test"]["global"]; - REQUIRE(mv == 50); - REQUIRE(muh_variable == 25); - - - lua.script(R"( -print(t.ref_global) -t.ref_global = 50 -print(t.ref_global) -)"); - int rmv = lua["test"]["ref_global"]; - REQUIRE(rmv == 50); - REQUIRE(muh_variable == 50); - - REQUIRE(through_variable == 10); - lua.script(R"( -print(test.global2) -test.global2 = 35 -print(test.global2) -)"); - int tv = lua["test"]["global2"]; - REQUIRE(through_variable == 10); - REQUIRE(tv == 35); - - lua.script(R"( -print(test.ref_global2) -test.ref_global2 = 35 -print(test.ref_global2) -)"); - int rtv = lua["test"]["ref_global2"]; - REQUIRE(rtv == 35); - REQUIRE(through_variable == 35); -} - -TEST_CASE("usertypes/var-and-property", "make sure const vars are readonly and properties can handle lambdas") { - const static int arf = 20; - - struct test { - int value = 10; - }; - - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<test>("test", - "prop", sol::property( - [](test& t) { - return t.value; - }, - [](test& t, int x) { - t.value = x; - } - ), - "global", sol::var(std::ref(arf)) - ); - - lua.script(R"( -t = test.new() -print(t.prop) -t.prop = 50 -print(t.prop) - )"); - - test& t = lua["t"]; - REQUIRE(t.value == 50); - - - REQUIRE_THROWS( - lua.script(R"( -t = test.new() -print(t.global) -t.global = 20 -print(t.global) - )")); -} - -TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") { - class Entity { - public: - std::string GetName() { - return "Charmander"; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io); - - lua.new_usertype<Entity>("Entity", - "new", sol::no_constructor, - "get_name", &Entity::GetName - ); - - lua.script(R"( - function my_func(entity) - print("INSIDE LUA") - print(entity:get_name()) - end -)"); - - sol::function my_func = lua["my_func"]; - REQUIRE_NOTHROW({ - auto ent = std::make_shared<Entity>(); - my_func(ent); - Entity ent2; - my_func(ent2); - my_func(std::make_shared<Entity>()); - }); -} - -TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") { - sol::state lua; - lua.new_usertype<abstract_A>("A", "a", &abstract_A::a); - lua.new_usertype<abstract_B>("B", sol::base_classes, sol::bases<abstract_A>()); - lua.script(R"(local b = B.new() -b:a() -)"); -} - -TEST_CASE("usertype/as_function", "Ensure that variables can be turned into functions by as_function") { - class B { - public: - int bvar = 24; - }; - - sol::state lua; - lua.open_libraries(); - lua.new_usertype<B>("B", "b", &B::bvar, "f", sol::as_function(&B::bvar)); - - B b; - lua.set("b", &b); - lua.script("x = b:f()"); - lua.script("y = b.b"); - int x = lua["x"]; - int y = lua["y"]; - REQUIRE(x == 24); - REQUIRE(y == 24); -} - -TEST_CASE("usertype/destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") { - sol::state lua; - - class CrashClass { - public: - CrashClass() { - } - - ~CrashClass() { - a = 10; // This will cause a crash. - } - - private: - int a; - }; - - lua.new_usertype<CrashClass>("CrashClass", - sol::call_constructor, sol::constructors<sol::types<>>() - ); - - lua.script(R"( - function testCrash() - local x = CrashClass() - end - )"); - - for (int i = 0; i < 1000; ++i) { - lua["testCrash"](); - } -} - -TEST_CASE("usertype/call-initializers", "Ensure call constructors with initializers work well") { - struct A { - double f = 25.5; - - static void init(A& x, double f) { - x.f = f; - } - }; - - sol::state lua; - lua.open_libraries(); - - lua.new_usertype<A>("A", - sol::call_constructor, sol::initializers(&A::init) - ); - - lua.script(R"( -a = A(24.3) -)"); - A& a = lua["a"]; - REQUIRE(a.f == 24.3); -} diff --git a/3rdparty/sol2/tests.cpp b/3rdparty/sol2/tests.cpp deleted file mode 100644 index 9e6dcf5c5d5..00000000000 --- a/3rdparty/sol2/tests.cpp +++ /dev/null @@ -1,794 +0,0 @@ -#define CATCH_CONFIG_MAIN -#define SOL_CHECK_ARGUMENTS - -#include <catch.hpp> -#include <sol.hpp> - -#include <fstream> -#include <iostream> -#include <map> -#include <unordered_map> -#include <vector> - -#include "test_stack_guard.hpp" - -bool func_opt_ret_bool(sol::optional<int> i) { - if (i) - { - INFO(i.value()); - } - else - { - INFO("optional isn't set"); - } - return true; -} - -TEST_CASE("table/traversal", "ensure that we can chain requests and tunnel down into a value if we desire") { - - sol::state lua; - int begintop = 0, endtop = 0; - - sol::function scriptload = lua.load("t1 = {t2 = {t3 = 24}};"); - scriptload(); - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - int traversex24 = lua.traverse_get<int>("t1", "t2", "t3"); - REQUIRE(traversex24 == 24); - } REQUIRE(begintop == endtop); - - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - int x24 = lua["t1"]["t2"]["t3"]; - REQUIRE(x24 == 24); - } REQUIRE(begintop == endtop); - - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - lua["t1"]["t2"]["t3"] = 64; - int traversex64 = lua.traverse_get<int>("t1", "t2", "t3"); - REQUIRE(traversex64 == 64); - } REQUIRE(begintop == endtop); - - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - int x64 = lua["t1"]["t2"]["t3"]; - REQUIRE(x64 == 64); - } REQUIRE(begintop == endtop); - - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - lua.traverse_set("t1", "t2", "t3", 13); - int traversex13 = lua.traverse_get<int>("t1", "t2", "t3"); - REQUIRE(traversex13 == 13); - } REQUIRE(begintop == endtop); - - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - int x13 = lua["t1"]["t2"]["t3"]; - REQUIRE(x13 == 13); - } REQUIRE(begintop == endtop); -} - -TEST_CASE("simple/set", "Check if the set works properly.") { - sol::state lua; - int begintop = 0, endtop = 0; - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - lua.set("a", 9); - } REQUIRE(begintop == endtop); - REQUIRE_NOTHROW(lua.script("if a ~= 9 then error('wrong value') end")); - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - lua.set("d", "hello"); - } REQUIRE(begintop == endtop); - REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); - - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - lua.set("e", std::string("hello"), "f", true); - } REQUIRE(begintop == endtop); - REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); - REQUIRE_NOTHROW(lua.script("if f ~= true then error('wrong value') end")); -} - -TEST_CASE("simple/get", "Tests if the get function works properly.") { - sol::state lua; - int begintop = 0, endtop = 0; - - lua.script("a = 9"); - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - auto a = lua.get<int>("a"); - REQUIRE(a == 9.0); - } REQUIRE(begintop == endtop); - - lua.script("b = nil"); - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - REQUIRE_NOTHROW(lua.get<sol::nil_t>("b")); - } REQUIRE(begintop == endtop); - - lua.script("d = 'hello'"); - lua.script("e = true"); - { - test_stack_guard g(lua.lua_state(), begintop, endtop); - std::string d; - bool e; - std::tie(d, e) = lua.get<std::string, bool>("d", "e"); - REQUIRE(d == "hello"); - REQUIRE(e == true); - } REQUIRE(begintop == endtop); -} - -TEST_CASE("simple/set-get-global-integer", "Tests if the get function works properly with global integers") { - sol::state lua; - lua[1] = 25.4; - lua.script("b = 1"); - double a = lua.get<double>(1); - double b = lua.get<double>("b"); - REQUIRE(a == 25.4); - REQUIRE(b == 1); -} - -TEST_CASE("simple/get_or", "check if table.get_or works correctly") { - sol::state lua; - - auto bob_table = lua.create_table("bob"); - bob_table.set("is_set", 42); - - int is_set = bob_table.get_or("is_set", 3); - int is_not_set = bob_table.get_or("is_not_set", 22); - - REQUIRE(is_set == 42); - REQUIRE(is_not_set == 22); - - lua["joe"] = 55.6; - double bark = lua.get_or<double>("joe", 60); - REQUIRE(bark == 55.6); -} - -TEST_CASE("simple/proxy_get_or", "check if proxy.get_or works correctly") { - sol::state lua; - - auto bob_table = lua.create_table("bob"); - bob_table.set("is_set", 42); - - int is_set = bob_table["is_set"].get_or(3); - int is_not_set = bob_table["is_not_set"].get_or(22); - - REQUIRE(is_set == 42); - REQUIRE(is_not_set == 22); - - lua["joe"] = 55.6; - double bark = lua["joe"].get_or<double>(60); - REQUIRE(bark == 55.6); -} - -TEST_CASE("simple/addition", "check if addition works and can be gotten through lua.get and lua.set") { - sol::state lua; - - lua.set("b", 0.2); - lua.script("c = 9 + b"); - auto c = lua.get<double>("c"); - - REQUIRE(c == 9.2); -} - -TEST_CASE("simple/if", "check if if statements work through lua") { - sol::state lua; - - std::string program = "if true then f = 0.1 else f = 'test' end"; - lua.script(program); - auto f = lua.get<double>("f"); - - REQUIRE(f == 0.1); - REQUIRE((f == lua["f"])); -} - -TEST_CASE("negative/basic_errors", "Check if error handling works correctly") { - sol::state lua; - - REQUIRE_THROWS(lua.script("nil[5]")); -} - -TEST_CASE("libraries", "Check if we can open libraries") { - sol::state lua; - REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base, sol::lib::os)); -} - -TEST_CASE("libraries2", "Check if we can open ALL the libraries") { - sol::state lua; - REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base, - sol::lib::bit32, - sol::lib::coroutine, - sol::lib::debug, - sol::lib::ffi, - sol::lib::jit, - sol::lib::math, - sol::lib::os, - sol::lib::package, - sol::lib::string, - sol::lib::table)); -} - -TEST_CASE("interop/null-to-nil-and-back", "nil should be the given type when a pointer from C++ is returned as nullptr, and nil should result in nullptr in connected C++ code") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("lol", []() -> int* { - return nullptr; - }); - lua.set_function("rofl", [](int* x) { - INFO(x); - }); - REQUIRE_NOTHROW(lua.script("x = lol()\n" - "rofl(x)\n" - "assert(x == nil)")); -} - -TEST_CASE("utilities/this_state", "Ensure this_state argument can be gotten anywhere in the function.") { - struct bark { - int with_state(sol::this_state l, int a, int b) { - lua_State* L = l; - int c = lua_gettop(L); - return a + b + (c - c); - } - - static int with_state_2(int a, sol::this_state l, int b) { - INFO("inside with_state_2"); - lua_State* L = l; - INFO("L is" << (void*)L); - int c = lua_gettop(L); - return a * b + (c - c); - } - }; - - sol::state lua; - INFO("created lua state"); - lua.open_libraries(sol::lib::base); - lua.new_usertype<bark>("bark", - "with_state", &bark::with_state - ); - - INFO("setting b and with_state_2"); - bark b; - lua.set("b", &b); - lua.set("with_state_2", bark::with_state_2); - INFO("finished setting"); - INFO("getting fx"); - sol::function fx = lua["with_state_2"]; - INFO("calling fx"); - int a = fx(25, 25); - INFO("finished setting fx"); - INFO("calling a script"); - lua.script("a = with_state_2(25, 25)"); - INFO("calling c script"); - lua.script("c = b:with_state(25, 25)"); - INFO("getting a"); - int la = lua["a"]; - INFO("getting b"); - int lc = lua["c"]; - - REQUIRE(lc == 50); - REQUIRE(a == 625); - REQUIRE(la == 625); -} - -TEST_CASE("object/conversions", "make sure all basic reference types can be made into objects") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - struct d {}; - - lua.script("function f () print('bark') end"); - lua["d"] = d{}; - lua["l"] = static_cast<void*>(nullptr); - - sol::table t = lua.create_table(); - sol::thread th = sol::thread::create(lua); - sol::function f = lua["f"]; - sol::protected_function pf = lua["f"]; - sol::userdata ud = lua["d"]; - sol::lightuserdata lud = lua["l"]; - - sol::object ot(t); - sol::object ot2 = ot; - sol::object oth(th); - sol::object of(f); - sol::object opf(pf); - sol::object od(ud); - sol::object ol(lud); - - auto oni = sol::make_object(lua, 50); - auto ond = sol::make_object(lua, 50.0); - - std::string somestring = "look at this text isn't it nice"; - auto osl = sol::make_object(lua, "Bark bark bark"); - auto os = sol::make_object(lua, somestring); - - auto omn = sol::make_object(lua, sol::nil); - - REQUIRE(ot.get_type() == sol::type::table); - REQUIRE(ot2.get_type() == sol::type::table); - REQUIRE(oth.get_type() == sol::type::thread); - REQUIRE(of.get_type() == sol::type::function); - REQUIRE(opf.get_type() == sol::type::function); - REQUIRE(od.get_type() == sol::type::userdata); - REQUIRE(ol.get_type() == sol::type::lightuserdata); - REQUIRE(oni.get_type() == sol::type::number); - REQUIRE(ond.get_type() == sol::type::number); - REQUIRE(osl.get_type() == sol::type::string); - REQUIRE(os.get_type() == sol::type::string); - REQUIRE(omn.get_type() == sol::type::nil); -} - -TEST_CASE("state/require_file", "opening files as 'requires'") { - static const char FILE_NAME[] = "./tmp_thingy.lua"; - - std::fstream file(FILE_NAME, std::ios::out); - - sol::state lua; - lua.open_libraries(sol::lib::base); - - SECTION("with usertypes") - { - struct foo { - foo(int bar) : bar(bar) {} - - const int bar; - }; - - lua.new_usertype<foo>("foo", - sol::constructors<sol::types<int>>{}, - "bar", &foo::bar - ); - - file << "return { modfunc = function () return foo.new(221) end }" << std::endl; - file.close(); - - const sol::table thingy1 = lua.require_file("thingy", FILE_NAME); - - CHECK(thingy1.valid()); - - const foo foo_v = thingy1["modfunc"](); - - int val1 = foo_v.bar; - - CHECK(val1 == 221); - } - - SECTION("simple") - { - file << "return { modfunc = function () return 221 end }" << std::endl; - file.close(); - - const sol::table thingy1 = lua.require_file("thingy", FILE_NAME); - const sol::table thingy2 = lua.require_file("thingy", FILE_NAME); - - CHECK(thingy1.valid()); - CHECK(thingy2.valid()); - - int val1 = thingy1["modfunc"](); - int val2 = thingy2["modfunc"](); - - CHECK(val1 == 221); - CHECK(val2 == 221); - // must have loaded the same table - CHECK(thingy1 == thingy2); - } - - std::remove(FILE_NAME); -} - -TEST_CASE("state/require_script", "opening strings as 'requires' clauses") { - std::string code = "return { modfunc = function () return 221 end }"; - - sol::state lua; - sol::table thingy1 = lua.require_script("thingy", code); - sol::table thingy2 = lua.require_script("thingy", code); - - int val1 = thingy1["modfunc"](); - int val2 = thingy2["modfunc"](); - REQUIRE(val1 == 221); - REQUIRE(val2 == 221); - // must have loaded the same table - REQUIRE(thingy1 == thingy2); -} - -TEST_CASE("state/require", "opening using a file") { - struct open { - static int open_func(lua_State* L) { - sol::state_view lua = L; - return sol::stack::push(L, lua.create_table_with("modfunc", sol::as_function([]() { return 221; }))); - } - }; - - sol::state lua; - sol::table thingy1 = lua.require("thingy", open::open_func); - sol::table thingy2 = lua.require("thingy", open::open_func); - - int val1 = thingy1["modfunc"](); - int val2 = thingy2["modfunc"](); - REQUIRE(val1 == 221); - REQUIRE(val2 == 221); - // THIS IS ONLY REQUIRED IN LUA 5.3, FOR SOME REASON - // must have loaded the same table - // REQUIRE(thingy1 == thingy2); -} - -TEST_CASE("state/multi-require", "make sure that requires transfers across hand-rolled script implementation and standard requiref") { - struct open { - static int open_func(lua_State* L) { - sol::state_view lua = L; - return sol::stack::push(L, lua.create_table_with("modfunc", sol::as_function([]() { return 221; }))); - } - }; - - std::string code = "return { modfunc = function () return 221 end }"; - sol::state lua; - sol::table thingy1 = lua.require("thingy", open::open_func); - sol::table thingy2 = lua.require("thingy", open::open_func); - sol::table thingy3 = lua.require_script("thingy", code); - - int val1 = thingy1["modfunc"](); - int val2 = thingy2["modfunc"](); - int val3 = thingy3["modfunc"](); - REQUIRE(val1 == 221); - REQUIRE(val2 == 221); - REQUIRE(val3 == 221); - // must have loaded the same table - // Lua is not obliged to give a shit. Thanks, Lua - //REQUIRE(thingy1 == thingy2); - // But we care, thankfully - //REQUIRE(thingy1 == thingy3); - REQUIRE(thingy2 == thingy3); -} - -TEST_CASE("feature/indexing-overrides", "make sure index functions can be overridden on types") { - struct PropertySet { - sol::object get_property_lua(const char* name, sol::this_state s) - { - auto& var = props[name]; - return sol::make_object(s, var); - } - - void set_property_lua(const char* name, sol::stack_object object) - { - props[name] = object.as<std::string>(); - } - - std::unordered_map<std::string, std::string> props; - }; - - struct DynamicObject { - PropertySet& get_dynamic_props() { - return dynamic_props; - } - - PropertySet dynamic_props; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype<PropertySet>("PropertySet" - , sol::meta_function::new_index, &PropertySet::set_property_lua - , sol::meta_function::index, &PropertySet::get_property_lua - ); - lua.new_usertype<DynamicObject>("DynamicObject" - , "props", sol::property(&DynamicObject::get_dynamic_props) - ); - - lua.script(R"__( -obj = DynamicObject:new() -obj.props.name = 'test name' -print('name = ' .. obj.props.name) -)__"); - - std::string name = lua["obj"]["props"]["name"]; - REQUIRE(name == "test name"); -} - -TEST_CASE("features/indexing-numbers", "make sure indexing functions can be override on usertypes") { - class vector { - public: - double data[3]; - - vector() : data{ 0,0,0 } {} - - double& operator[](int i) - { - return data[i]; - } - - - static double my_index(vector& v, int i) - { - return v[i]; - } - - static void my_new_index(vector& v, int i, double x) - { - v[i] = x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<vector>("vector", sol::constructors<sol::types<>>(), - sol::meta_function::index, &vector::my_index, - sol::meta_function::new_index, &vector::my_new_index); - lua.script("v = vector.new()\n" - "print(v[1])\n" - "v[2] = 3\n" - "print(v[2])\n" - ); - - vector& v = lua["v"]; - REQUIRE(v[0] == 0.0); - REQUIRE(v[1] == 0.0); - REQUIRE(v[2] == 3.0); -} - -TEST_CASE("features/multiple-inheritance", "Ensure that multiple inheritance works as advertised") { - struct base1 { - int a1 = 250; - }; - - struct base2 { - int a2 = 500; - }; - - struct simple : base1 { - - }; - - struct complex : base1, base2 { - - }; - - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype<base1>("base1", - "a1", &base1::a1 - ); - lua.new_usertype<base2>("base2", - "a2", &base2::a2 - ); - lua.new_usertype<simple>("simple", - "a1", &simple::a1, - sol::base_classes, sol::bases<base1>() - ); - lua.new_usertype<complex>("complex", - "a1", &complex::a1, - "a2", &complex::a2, - sol::base_classes, sol::bases<base1, base2>() - ); - lua.script("c = complex.new()\n" - "s = simple.new()\n" - "b1 = base1.new()\n" - "b2 = base1.new()\n" - ); - - base1* sb1 = lua["s"]; - REQUIRE(sb1 != nullptr); - REQUIRE(sb1->a1 == 250); - - base1* cb1 = lua["c"]; - base2* cb2 = lua["c"]; - - REQUIRE(cb1 != nullptr); - REQUIRE(cb2 != nullptr); - REQUIRE(cb1->a1 == 250); - REQUIRE(cb2->a2 == 500); -} - - -TEST_CASE("regressions/std::ref", "Ensure that std::reference_wrapper<> isn't considered as a function by using unwrap_unqualified_t trait") { - struct base1 { - int a1 = 250; - }; - - sol::state lua; - base1 v; - lua["vp"] = &v; - lua["vr"] = std::ref(v); - - base1* vp = lua["vp"]; - base1& vr = lua["vr"]; - REQUIRE(vp != nullptr); - REQUIRE(vp == &v); - - REQUIRE(vp->a1 == 250); - REQUIRE(vr.a1 == 250); - - v.a1 = 568; - - REQUIRE(vp->a1 == 568); - REQUIRE(vr.a1 == 568); -} - -TEST_CASE("optional/left-out-args", "Make sure arguments can be left out of optional without tanking miserably") { - - sol::state lua; - lua.open_libraries(sol::lib::base); - - // sol::optional needs an argument no matter what? - lua.set_function("func_opt_ret_bool", func_opt_ret_bool); - REQUIRE_NOTHROW( - lua.script(R"( - func_opt_ret_bool(42) - func_opt_ret_bool() - print('ok') - )"); - ); -} - -TEST_CASE("pusher/constness", "Make sure more types can handle being const and junk") { - struct Foo { - Foo(const sol::function& f) : _f(f) {} - const sol::function& _f; - - const sol::function& f() const { return _f; } - }; - - sol::state lua; - - lua.new_usertype<Foo>("Foo", - sol::call_constructor, sol::no_constructor, - "f", &Foo::f - ); - - lua["func"] = []() { return 20; }; - sol::function f = lua["func"]; - lua["foo"] = Foo(f); - Foo& foo = lua["foo"]; - int x = foo.f()(); - REQUIRE(x == 20); -} - -TEST_CASE("proxy/proper-pushing", "allow proxies to reference other proxies and be serialized as the proxy itself and not a function or something") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::io); - - class T {}; - lua.new_usertype<T>("T"); - - T t; - lua["t1"] = &t; - lua["t2"] = lua["t1"]; - lua.script("b = t1 == t2"); - bool b = lua["b"]; - REQUIRE(b); -} - -TEST_CASE("proxy/equality", "check to make sure equality tests work") { - sol::state lua; - REQUIRE((lua["a"] == sol::nil)); - REQUIRE_FALSE((lua["a"] == nullptr)); - REQUIRE_FALSE((lua["a"] == 0)); - REQUIRE_FALSE((lua["a"] == 2)); - - lua["a"] = 2; - - REQUIRE_FALSE((lua["a"] == sol::nil)); //0 - REQUIRE_FALSE((lua["a"] == nullptr)); //0 - REQUIRE_FALSE((lua["a"] == 0)); //0 - REQUIRE((lua["a"] == 2)); //1 -} - -TEST_CASE("compilation/const-regression", "make sure constness in tables is respected all the way down") { - struct State { - public: - State() { - this->state_.registry()["state"] = this; - } - - sol::state state_; - }; - - State state; - State* s = state.state_.registry()["state"]; - REQUIRE(s == &state); -} - -TEST_CASE("numbers/integers", "make sure integers are detectable on most platforms") { - sol::state lua; - - lua["a"] = 50; // int - lua["b"] = 50.5; // double - - sol::object a = lua["a"]; - sol::object b = lua["b"]; - - bool a_is_int = a.is<int>(); - bool a_is_double = a.is<double>(); - - bool b_is_int = b.is<int>(); - bool b_is_double = b.is<double>(); - - REQUIRE(a_is_int); - REQUIRE(a_is_double); - - // TODO: will this fail on certain lower Lua versions? - REQUIRE_FALSE(b_is_int); - REQUIRE(b_is_double); -} - -TEST_CASE("state/script-returns", "make sure script returns are done properly") { - std::string script = - R"( -local example = -{ - str = "this is a string", - num = 1234, - - func = function(self) - print(self.str) - return "fstr" - end -} - -return example; -)"; - - auto bar = [&script](sol::this_state l) { - sol::state_view lua = l; - sol::table data = lua.script(script); - - std::string str = data["str"]; - int num = data["num"]; - std::string fstr = data["func"](data); - REQUIRE(str == "this is a string"); - REQUIRE(fstr == "fstr"); - REQUIRE(num == 1234); - }; - - auto foo = [&script](int, sol::this_state l) { - sol::state_view lua = l; - sol::table data = lua.script(script); - - std::string str = data["str"]; - int num = data["num"]; - std::string fstr = data["func"](data); - REQUIRE(str == "this is a string"); - REQUIRE(fstr == "fstr"); - REQUIRE(num == 1234); - }; - - auto bar2 = [&script](sol::this_state l) { - sol::state_view lua = l; - sol::table data = lua.do_string(script); - - std::string str = data["str"]; - int num = data["num"]; - std::string fstr = data["func"](data); - REQUIRE(str == "this is a string"); - REQUIRE(fstr == "fstr"); - REQUIRE(num == 1234); - }; - - auto foo2 = [&script](int, sol::this_state l) { - sol::state_view lua = l; - sol::table data = lua.do_string(script); - - std::string str = data["str"]; - int num = data["num"]; - std::string fstr = data["func"](data); - REQUIRE(str == "this is a string"); - REQUIRE(fstr == "fstr"); - REQUIRE(num == 1234); - }; - - sol::state lua; - lua.open_libraries(); - - lua.set_function("foo", foo); - lua.set_function("foo2", foo2); - lua.set_function("bar", bar); - lua.set_function("bar2", bar2); - - lua.script("bar() bar2() foo(1) foo2(1)"); -} |