Completley overhaul tests

Add unregister funcationality
Make sure clearing is stack-size-safe.
This commit is contained in:
ThePhD 2019-03-22 16:28:17 -04:00
parent 04b36f1fc1
commit e8467334f6
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
41 changed files with 1271 additions and 526 deletions

3
.gitignore vendored
View File

@ -100,6 +100,9 @@ docs/build/
*.sublime-project
# MacOS Garbage
.DS_Store
# Windows Crap
desktop.ini
*.db

View File

@ -35,8 +35,16 @@ before_install:
script:
- export SOL2_DIR=${TRAVIS_BUILD_DIR}
- sudo docker image pull thephd/sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION}
- sudo docker run --rm --interactive --tty --name "sol2.test" -v "${SOL2_DIR}:/root/sol2" --env "CI=${CI}" --env "PLATFORM=${PLATFORM}" --env "LUA_VERSION=${LUA_VERSION}" --env "GCC_VERSION=${GCC_VERSION}" --env "LLVM_VERSION=${LLVM_VERSION}" thephd/sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION}
- sudo docker rmi $(sudo docker image ls -q)
- sudo docker run --rm --interactive --tty --name "sol2.test" -v "${SOL2_DIR}:/root/sol2" --env "SOL2_CI=${SOL2_CI}" --env "SOL2_PLATFORM=${SOL2_PLATFORM}" --env "SOL2_LUA_VERSION=${SOL2_LUA_VERSION}" --env "SOL2_TEST_SINGLE=${SOL2_TEST_SINGLE}" --env "SOL2_TEST_INTEROP=${SOL2_TEST_INTEROP}" --env "GCC_VERSION=${GCC_VERSION}" --env "LLVM_VERSION=${LLVM_VERSION}" thephd/sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION}
after_success:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
- chmod +x send.sh
- ./send.sh success ${DISORD_WEBHOOK_URL}
after_failure:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
- chmod +x send.sh
- ./send.sh failure ${DISORD_WEBHOOK_URL}
matrix:
fast_finish: true
@ -44,91 +52,108 @@ matrix:
- os: osx
include:
# GCC 4.9.x, 5.x, 6.x, 7.x
# LLVM 5.0.x -> 8.0.x
- env:
- LUA_VERSION=5.3.5
GCC_VERSION=7
PLATFORM=i686
CI=true
- env:
- LUA_VERSION=luajit-2.0.5
GCC_VERSION=7
PLATFORM=i686
CI=true
- env:
- LUA_VERSION=luajit-2.1.0-beta3
GCC_VERSION=7
PLATFORM=i686
CI=true
- env:
- LUA_VERSION=5.3.5
GCC_VERSION=7
PLATFORM=x64
CI=true
# LLVM 3.9.x -> 5.0.x
- env:
- LUA_VERSION=5.3.5
LLVM_VERSION=3.9.1
PLATFORM=x64
CI=true
- env:
- LUA_VERSION=5.3.5
LLVM_VERSION=4.0.1
PLATFORM=x64
CI=true
- env:
- LUA_VERSION=5.3.5
- SOL2_LUA_VERSION=5.3.5
LLVM_VERSION=5.0.2
PLATFORM=x64
CI=true
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- LUA_VERSION=5.3.5
- SOL2_LUA_VERSION=5.3.5
LLVM_VERSION=6.0.1
PLATFORM=x64
CI=true
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- LUA_VERSION=5.3.5
LLVM_VERSION=7.0.0
PLATFORM=x64
CI=true
- LLVM_VERSION=7.0.1
SOL2_LUA_VERSION=5.3.5
SOL2_PLATFORM=x64
SOL2_CI=true
# Lua Versions 5.2.4, 5.1.5, and LuaJIT (as well as x86)
- env:
- LUA_VERSION=5.2.4
- LLVM_VERSION=8.0.0
SOL2_LUA_VERSION=5.3.5
SOL2_PLATFORM=x64
SOL2_CI=true
# GCC 7.x, 8.x
- env:
- SOL2_LUA_VERSION=5.3.5
GCC_VERSION=8
SOL2_PLATFORM=i686
SOL2_CI=true
- env:
- SOL2_LUA_VERSION=5.3.5
GCC_VERSION=7
PLATFORM=x64
CI=true
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- SOL2_LUA_VERSION=5.3.5
GCC_VERSION=8
SOL2_PLATFORM=x64
SOL2_CI=true
# Lua Versions 5.2.4, 5.1.5, and LuaJIT
- env:
- SOL2_LUA_VERSION=5.1.5
GCC_VERSION=8
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- LUA_VERSION=5.1.5
GCC_VERSION=7
PLATFORM=x64
CI=true
- SOL2_LUA_VERSION=5.2.4
GCC_VERSION=8
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- LUA_VERSION=luajit-2.0.4
GCC_VERSION=7
PLATFORM=x64
CI=true
- SOL2_LUA_VERSION=luajit-2.0.4
GCC_VERSION=8
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- LUA_VERSION=luajit-2.0.5
GCC_VERSION=7
PLATFORM=x64
CI=true
- SOL2_LUA_VERSION=luajit-2.0.5
GCC_VERSION=8
SOL2_PLATFORM=x64
SOL2_CI=true
- env:
- SOL2_LUA_VERSION=luajit-2.0.5
GCC_VERSION=8
SOL2_PLATFORM=i686
SOL2_CI=true
- env:
- SOL2_LUA_VERSION=luajit-2.1.0-beta3
GCC_VERSION=8
SOL2_PLATFORM=i686
SOL2_CI=true
# Test Single, Interop, Etc.
- env:
- LLVM_VERSION=7.0.0
SOL2_LUA_VERSION=5.3.5
SOL2_PLATFORM=x64
SOL2_CI=true
SOL2_TEST_SINGLE=true
SOL2_TEST_INTEROP=true
- env:
- SOL2_LUA_VERSION=5.3.5
GCC_VERSION=8
SOL2_PLATFORM=x64
SOL2_CI=true
SOL2_TEST_SINGLE=true
SOL2_TEST_INTEROP=true
- os: osx
osx_image: xcode9.0
env:
- LUA_VERSION=lua-5.3.5
- SOL2_LUA_VERSION=lua-5.3.5
LLVM_VERSION=5.0.2
before_install:
- chmod +x ./scripts/run.osx.sh
@ -140,7 +165,7 @@ matrix:
- os: osx
osx_image: xcode9.1
env:
- LUA_VERSION=lua-5.3.5
- SOL2_LUA_VERSION=lua-5.3.5
LLVM_VERSION=5.0.2
before_install:
- chmod +x ./scripts/run.osx.sh
@ -152,7 +177,7 @@ matrix:
- os: osx
osx_image: xcode9.2
env:
- LUA_VERSION=lua-5.3.5
- SOL2_LUA_VERSION=lua-5.3.5
LLVM_VERSION=5.0.2
before_install:
- chmod +x ./scripts/run.osx.sh
@ -164,7 +189,7 @@ matrix:
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/b864d553270a069d26c8
- https://skyhook.glitch.me/api/webhooks/427786348108185611/y2nTmghqltv1SKX2DclEMEKyZtRcwKFlwfZpB_mL1A0nZTVS5MSfumqDKq30-gvWgeL5/travis
on_success: change
on_failure: always
on_start: always

View File

@ -20,8 +20,8 @@
# 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.
# Start from the ubuntu:xenial image
FROM ubuntu:xenial
# Start from the ubuntu:bionic image
FROM ubuntu:bionic
# owner
LABEL author="ThePhD <phdofthehouse@gmail.com>"
LABEL maintainer="ThePhD <phdofthehouse@gmail.com>"
@ -48,13 +48,17 @@ VOLUME /root/sol2
# # This is ordered like this so making multiple of these
# # containers is more or less identical up to this point
# Command line arguments, with default values
ARG CI=true
ARG SOL2_PLATFORM=x64
ARG SOL2_LUA_VERSION=x64
ARG SOL2_LUA_VERSION=5.3.5
ARG SOL2_TEST_SINGLE=false
ARG SOL2_TEST_INTEROP=false
ARG SOL2_CI=true
ARG GCC_VERSION
ARG LLVM_VERSION
ARG PLATFORM=x64
# Potential environment variables
ENV CI=${CI} PLATFORM=${PLATFORM} GCC_VERSION=${GCC_VERSION} LLVM_VERSION=${LLVM_VERSION} SOL2_DIR=/root/sol2
ENV SOL2_LUA_VERSION=${SOL2_LUA_VERSION} SOL2_TEST_SINGLE=${SOL2_TEST_SINGLE} SOL2_TEST_INTEROP=${SOL2_TEST_INTEROP} SOL2_CI=${SOL2_CI} SOL2_PLATFORM=${SOL2_PLATFORM} GCC_VERSION=${GCC_VERSION} LLVM_VERSION=${LLVM_VERSION} SOL2_DIR=/root/sol2
RUN ["/usr/bin/env", "zsh", "-e", "/root/sol2-scripts/preparation.linux.sh"]

View File

@ -45,16 +45,14 @@ platform:
environment:
matrix:
# apparently, I can't quite make LLVM work right now...
#- LUA_VERSION: 5.3.4
# LLVM_VERSION: 4.0.0
- LUA_VERSION: 5.3.5
MINGW_VERSION: 7.2.0
MINGW_VERSION: 7.3.0
- LUA_VERSION: 5.3.5
MINGW_VERSION: 6.3.0
MINGW_VERSION: 8.1.0
- LUA_VERSION: luajit-2.0.5
MINGW_VERSION: 6.3.0
MINGW_VERSION: 8.1.0
- LUA_VERSION: luajit-2.1.0-beta3
MINGW_VERSION: 6.3.0
MINGW_VERSION: 8.1.0
- LUA_VERSION: 5.3.5
- LUA_VERSION: 5.2.4
- LUA_VERSION: 5.1.5
@ -65,32 +63,22 @@ matrix:
allow_failures:
# 32-bit builds are temperamental with exceptions
- platform: x86
# Visual Studio 2015 builds are allowed to fail, since I have no intention of dealing with bad old builds
- image: Visual Studio 2015
# LLVM is experimental as all get-out
- LLVM_VERSION: 4.0.0
exclude:
# Necessary: MinGW doesn't exist on VS 2017 images
# Also does not have MinGW x64 for 5.3.0
- image: Visual Studio 2017
MINGW_VERSION: 6.3.0
# LLVM exists in all images, and we only want the VS 2017 x64 versions
- image: Visual Studio 2015
LLVM_VERSION: 4.0.0
- platform: x86
LLVM_VERSION: 4.0.0
# Get rid of x86 builds
MINGW_VERSION: 7.3.0
- image: Visual Studio 2017
MINGW_VERSION: 8.1.0
# There are no recent i686 compilers on the VS2015/2017 images
- MINGW_VERSION: 7.3.0
platform: x86
- MINGW_VERSION: 8.1.0
platform: x86
# Get rid of x86 builds for non-latest (no reason to redo that work)
- platform: x86
LUA_VERSION: 5.2.4
- platform: x86
LUA_VERSION: 5.1.5
- platform: x86
MINGW_VERSION: 7.2.0
# Get rid of redundant Visual Studio 2015 builds
- image: Visual Studio 2015
LUA_VERSION: 5.1.5
- image: Visual Studio 2015
LUA_VERSION: 5.2.4
init:
# # Ninja
@ -109,10 +97,8 @@ init:
- set python_path=C:\Python36
- set mingw_path=
- set llvm_path=
- if "%MINGW_VERSION%"=="5.3.0" (set mingw_path=C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin)
- if "%MINGW_VERSION%"=="6.3.0" (if "%PLATFORM%"=="x64" (set mingw_path=C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin) else ( set mingw_path=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin))
- if "%MINGW_VERSION%"=="7.2.0" (if "%PLATFORM%"=="x64" (set mingw_path=C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin) else ( set mingw_path=C:\mingw-w64\i686-7.2.0-posix-seh-rt_v5-rev1\mingw32\bin))
- if "%LLVM_VERSION%"=="4.0.0" (set llvm_path=C:\Program Files\LLVM\bin)
- if "%MINGW_VERSION%"=="7.3.0" (if "%PLATFORM%"=="x64" (set mingw_path=C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev1\mingw64\bin) else ( set mingw_path=C:\mingw-w64\i686-7.3.0-posix-seh-rt_v5-rev1\mingw32\bin))
- if "%MINGW_VERSION%"=="8.1.0" (if "%PLATFORM%"=="x64" (set mingw_path=C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v5-rev1\mingw64\bin) else ( set mingw_path=C:\mingw-w64\i686-8.1.0-posix-seh-rt_v5-rev1\mingw32\bin))
- if "%PLATFORM%"=="x64" (set python_path=C:\Python36-x64)
- set PATH=%python_path%;%PATH%
- set PATH=%mingw_path%;%PATH%
@ -124,50 +110,44 @@ init:
- set arch=
- set parallelism=
- set logger=
- set build_type=
- set build_compiler=
- set lua_build_type=OFF
- set vcvars_script="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
- if "%PLATFORM%"=="x64" (set arch= Win64)
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (set CMAKE_GENERATOR=Visual Studio 15 2017%arch%&&set parallelism=/maxcpucount&&set logger=/verbosity:quiet /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"&&set vcvars_script="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat")
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (set CMAKE_GENERATOR=Visual Studio 14 2015%arch%&&set parallelism=/maxcpucount&&set logger=/verbosity:quiet /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll")
- if "%MINGW_VERSION%"=="5.3.0" (set CMAKE_GENERATOR=Ninja&&set parallelism= &&set logger= &&set build_type=-DCMAKE_BUILD_TYPE=Release&&set build_compiler=-DCMAKE_CXX_COMPILER=g++.exe -DCMAKE_C_COMPILER=gcc.exe)
- if "%MINGW_VERSION%"=="6.3.0" (set CMAKE_GENERATOR=Ninja&&set parallelism= &&set logger= &&set build_type=-DCMAKE_BUILD_TYPE=Release&&set build_compiler=-DCMAKE_CXX_COMPILER=g++.exe -DCMAKE_C_COMPILER=gcc.exe)
- if "%MINGW_VERSION%"=="7.2.0" (set CMAKE_GENERATOR=Ninja&&set parallelism= &&set logger= &&set build_type=-DCMAKE_BUILD_TYPE=Release&&set build_compiler=-DCMAKE_CXX_COMPILER=g++.exe -DCMAKE_C_COMPILER=gcc.exe)
- if "%LLVM_VERSION%"=="4.0.0" (set CMAKE_GENERATOR=Ninja&&set parallelism= &&set logger= &&set build_type=-DCMAKE_BUILD_TYPE=Release&&set build_compiler=-DCMAKE_CXX_COMPILER=clang-cl.exe -DCMAKE_C_COMPILER=clang-cl.exe)
- if "%MINGW_VERSION%"=="7.3.0" (set CMAKE_GENERATOR=Ninja&&set parallelism= &&set logger= &&set build_compiler=-DCMAKE_CXX_COMPILER=g++.exe -DCMAKE_C_COMPILER=gcc.exe)
- if "%MINGW_VERSION%"=="8.1.0" (set CMAKE_GENERATOR=Ninja&&set parallelism= &&set logger= &&set build_compiler=-DCMAKE_CXX_COMPILER=g++.exe -DCMAKE_C_COMPILER=gcc.exe)
# # Last printouts
# print out generator information
- echo Appveyor Image is %APPVEYOR_BUILD_WORKER_IMAGE% (vcvars script is %vcvars_script%)
- echo cmake generator is %CMAKE_GENERATOR% using build_type=%build_type% and build_compiler=%build_compiler% with special flags logger=%logger% parallelism=%parallelism%
- echo cmake generator is %CMAKE_GENERATOR% using build_compiler=%build_compiler% with special flags logger=%logger% parallelism=%parallelism%
# print out useful tool information
- ninja --version
- cmake --version
- if DEFINED LLVM_VERSION (clang-cl.exe -v)
- if DEFINED MINGW_VERSION (g++.exe --version)
# We need to use CMAKE_BUILD_TYPE=Release since there are no "configuration"
# toolsets for Ninja or Makefiles as far as cmake is concerned, so
# the --config / -C switches on builds do nothing...!
before_build:
- if DEFINED LLVM_VERSION (call %vcvars_script% && cd C:\projects\sol2)
- md build-sol2
- md buid-sol2\Debug
- md buid-sol2\Release
- cd build-sol2
- cmake .. -G "%CMAKE_GENERATOR%" %build_type% %build_compiler% -DSOL2_LUA_VERSION="%LUA_VERSION%" -DSOL2_CI=ON -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=%lua_build_type% -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON
- if not defined %MINGW_VERSION% (cmake .. -G "%CMAKE_GENERATOR%" %build_compiler% -DSOL2_LUA_VERSION="%LUA_VERSION%" -DSOL2_CI=ON -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=%lua_build_type% -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON)
- if defined %MINGW_VERSION% (cmake ..\.. -G "%CMAKE_GENERATOR%" %build_compiler% -DSOL2_LUA_VERSION="%LUA_VERSION%" -DSOL2_CI=ON -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=%lua_build_type% -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON)
- if defined %MINGW_VERSION% (cmake ..\.. -G "%CMAKE_GENERATOR%" %build_compiler% -DSOL2_LUA_VERSION="%LUA_VERSION%" -DSOL2_CI=ON -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=%lua_build_type% -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON)
# We do not build the debug versions because the compiler
# generates too much debug info for MinGW to handle
# TODO: fix the damn compilation space and time already
build_script:
- if NOT "%build_type%"=="-DCMAKE_BUILD_TYPE=Release" (cmake --build . --config Debug -- %parallelism% %logger%)
- cmake --build . --config Debug -- %parallelism% %logger%
- cmake --build . --config Release -- %parallelism% %logger%
test_script:
- if NOT "%build_type%"=="-DCMAKE_BUILD_TYPE=Release" (ctest -C Debug --output-on-failure)
- ctest -C Debug --output-on-failure
- ctest -C Release --output-on-failure
notifications:
- provider: Webhook
url: https://webhooks.gitter.im/e/1af10e654a918bef7f1e
url: http://skyhook.glitch.me/api/webhooks/427786348108185611/y2nTmghqltv1SKX2DclEMEKyZtRcwKFlwfZpB_mL1A0nZTVS5MSfumqDKq30-gvWgeL5/appveyor
method: POST
on_build_success: true
on_build_failure: true

View File

@ -86,9 +86,17 @@ function (MAKE_EXAMPLE example_source_file example_suffix target_sol)
target_compile_options(${example_name}
PRIVATE -std=c++1z
-ftemplate-backtrace-limit=0
-Wno-unknown-warning -Wno-unknown-warning-option
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
-Wno-noexcept-type
-Wno-unknown-warning -Wno-unknown-warning-option)
-Wno-noexcept-type)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# For another day, when C++ is not so crap
# and we have time to audit the entire lib
# for all uses of `detail::swallow`...
#target_compile_options(${example_name}
# PRIVATE -Wcomma)
endif()
endif()
target_link_libraries(${example_name}

View File

@ -62,9 +62,19 @@ function(make_require_from_dll_example target_lib example_lib_name_suffix)
else()
target_compile_options(${example_lib_name}
PRIVATE -std=c++1z
-Wno-unknown-warning -Wno-unknown-warning-option
-Wall -Wextra -Wpedantic -pedantic -pedantic-errors
-Wno-noexcept-type
-Wno-unknown-warning -Wno-unknown-warning-option)
-Wno-noexcept-type)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# For another day, when C++ is not so crap
# and we have time to audit the entire lib
# for all uses of `detail::swallow`...
#target_compile_options(${test_target_name}
# PRIVATE -Wcomma)
endif()
if (IS_X86)
target_compile_options(${example_lib_name} BEFORE PRIVATE -m32)
endif()
@ -93,9 +103,17 @@ function(make_require_from_dll_example target_lib example_lib_name_suffix)
else()
target_compile_options(${example_name}
PRIVATE -std=c++1z
-Wno-unknown-warning -Wno-unknown-warning-option
-Wall -Wextra -Wpedantic -pedantic -pedantic-errors
-Wno-noexcept-type
-Wno-unknown-warning -Wno-unknown-warning-option)
-Wno-noexcept-type)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# For another day, when C++ is not so crap
# and we have time to audit the entire lib
# for all uses of `detail::swallow`...
#target_compile_options(${test_target_name}
# PRIVATE -Wcomma)
endif()
endif()
if(CMAKE_DL_LIBS)

View File

@ -3,7 +3,8 @@
struct A {
int a = 10;
virtual int call() { return 0; }
virtual int call() { return 0; }
virtual ~A(){}
};
struct B : A {
int b = 11;

View File

@ -38,18 +38,18 @@ namespace sol {
using base_t = std::vector<std::byte, Allocator>;
public:
using base_t::allocator_type;
using base_t::const_iterator;
using base_t::const_pointer;
using base_t::const_reference;
using base_t::const_reverse_iterator;
using base_t::difference_type;
using base_t::iterator;
using base_t::pointer;
using base_t::reference;
using base_t::reverse_iterator;
using base_t::size_type;
using base_t::value_type;
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=;

View File

@ -314,7 +314,7 @@ namespace sol {
construct_match<T, TypeLists...>(constructor_match<T, checked, clean_stack>(obj), L, argcount, 1 + static_cast<int>(syntax));
userdataref.push();
stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]);
stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
umf();
return 1;
@ -633,7 +633,7 @@ namespace sol {
construct_match<T, Args...>(constructor_match<T, false, clean_stack>(obj), L, argcount, boost + 1 + static_cast<int>(syntax));
userdataref.push();
stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]);
stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
umf();
return 1;
@ -655,7 +655,7 @@ namespace sol {
stack::call_into_lua<checked, clean_stack>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj));
userdataref.push();
stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]);
stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
umf();
return 1;

View File

@ -41,7 +41,7 @@ namespace sol { namespace detail {
ebco(const T& v) : value_(v){};
ebco(T&& v) : value_(std::move(v)){};
ebco& operator=(const T& v) {
value = v;
value_ = v;
return *this;
}
ebco& operator=(T&& v) {
@ -53,13 +53,17 @@ namespace sol { namespace detail {
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
T& value() {
T& value() & {
return value_;
}
T const& value() const {
T const& value() const & {
return value_;
}
T&& value() && {
return std::move(value_);
}
};
template <typename T, std::size_t tag>
@ -86,13 +90,17 @@ namespace sol { namespace detail {
return *this;
};
T& value() {
T& value() & {
return static_cast<T&>(*this);
}
T const& value() const {
T const& value() const & {
return static_cast<T const&>(*this);
}
T&& value() && {
return std::move(static_cast<T&>(*this));
}
};
template <typename T, std::size_t tag>
@ -128,10 +136,18 @@ namespace sol { namespace detail {
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco& operator=(T&& v) {
ref = v;
ref = std::move(v);
return *this;
}
T& value() & {
return ref;
}
const T& value() const & {
return ref;
}
T&& value() && {
return std::move(ref);
}

View File

@ -67,7 +67,7 @@ namespace sol {
const char* name = lua_tolstring(L, -1, &sz);
std::string tn(name, static_cast<std::string::size_type>(sz));
lua_pop(L, 2);
return std::move(tn);
return tn;
}
default:
break;

View File

@ -46,7 +46,11 @@ namespace sol {
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

View File

@ -29,16 +29,23 @@
#include "make_reference.hpp"
namespace sol {
namespace detail {
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>>;
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>>;
}
struct lua_value {
private:
static lua_State*& thread_local_lua_state() {
static thread_local lua_State* L = nullptr;
return L;
@ -51,21 +58,39 @@ namespace sol {
thread_local_lua_state() = L;
}
template <typename T, meta::disable<detail::is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
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<detail::is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
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<lua_value> il) : lua_value(((set_lua_state(L_)), std::move(il))) {
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<lua_value> il) : ref_value(make_reference(thread_local_lua_state(), 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_, reference r) : lua_value(((thread_local_lua_state() = L_), std::move(r))) {
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)) {
@ -106,6 +131,8 @@ namespace sol {
}
};
using array_value = typename lua_value::arr;
namespace stack {
template <>
struct unqualified_pusher<lua_value> {

View File

@ -106,27 +106,28 @@ namespace sol {
using ustorage_base = u_detail::usertype_storage_base;
lua_State* L = this->lua_state();
int x = lua_gettop(L);
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) {
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) {
return;
}
ustorage_base& base_storage = *static_cast<ustorage_base*>(stack::get<void*>(L, -1));
base_storage.clear();
stack_reference gc_names_table(L, -1);
std::array<const char*, 6> registry_traits;
for (int i = 0; i < registry_traits.size(); ++i) {
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(L, smt, gc_names_table.stack_index());
registry_traits[i] = stack::get<const char*>(L, -1);
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();
@ -134,26 +135,31 @@ namespace sol {
// in the registry (luaL_newmetatable does
// [name] = new table
// in registry upon creation)
for (int i = 0; i < registry_traits.size(); ++i) {
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) {
const char* gcmetakey = registry_traits[i];
stack::set_field<true>(L, gcmetakey, lua_nil);
// use .data() to make it treat it like a c string,
// which it is...
stack::set_field<true>(L, gcmetakey.data(), lua_nil);
}
else {
stack::set_field(L, registry_traits[i], lua_nil, registry.stack_index());
// 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
// 8 total
int y = lua_gettop(L);
lua_pop(L, 9);
int z = lua_gettop(L);
int a = x + y + z;
// + 1 registry
// 10 total, 4 left since popping off 6 gc_names tables
lua_settop(L, top);
}
};

View File

@ -516,13 +516,13 @@ namespace sol {
}
template <typename T, typename Al>
void reserve(std::vector<T, Al>& arr, std::size_t hint) {
arr.reserve(hint);
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>& arr, std::size_t hint) {
arr.reserve(hint);
void reserve(std::basic_string<T, Tr, Al>& str, std::size_t hint) {
str.reserve(hint);
}
inline bool property_always_true(meta_function) {
@ -798,6 +798,24 @@ namespace sol {
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) {
@ -831,6 +849,30 @@ namespace sol {
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());
}
template <typename T, typename... Args>
inline int push(lua_State* L, T&& t, Args&&... args) {
using Tu = meta::unqualified_t<T>;
@ -971,7 +1013,7 @@ namespace sol {
}
template <typename T, typename Handler>
bool check_usertype(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) {
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);

View File

@ -143,7 +143,7 @@ namespace stack {
template <typename T, bool global, bool raw, typename>
struct field_setter {
static constexpr int default_table_index = meta::conditional_t < meta::is_c_str_v<T> || (std::is_integral_v<T> && !std::is_same_v<T, bool>)
static constexpr int default_table_index = meta::conditional_t<(meta::is_c_str_v<T> || meta::is_string_of_v<T, char>) || (std::is_integral_v<T> && !std::is_same_v<T, bool>)
|| (std::is_integral_v<T> && !std::is_same_v<T, bool>) || (raw && std::is_void_v<std::remove_pointer_t<T>>),
std::integral_constant<int, -2>, std::integral_constant<int, -3>> ::value;
@ -178,7 +178,7 @@ namespace stack {
}
}
else {
if constexpr (meta::is_c_str_v<T>) {
if constexpr (meta::is_c_str_v<T> || meta::is_string_of_v<T, char>) {
if constexpr (global) {
push(L, std::forward<Value>(value));
lua_setglobal(L, &key[0]);

View File

@ -232,32 +232,32 @@ namespace sol { namespace stack {
using Tu = meta::unqualified_t<T>;
template <typename V>
static void push_back_at_end(std::true_type, types<V>, lua_State* L, T& arr, std::size_t) {
arr.push_back(stack::get<V>(L, -lua_size<V>::value));
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& arr, std::size_t idx) {
insert_at_end(meta::has_insert<Tu>(), t, L, arr, idx);
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& arr, std::size_t) {
static void insert_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) {
using std::cend;
arr.insert(cend(arr), stack::get<V>(L, -lua_size<V>::value));
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& arr, std::size_t idx) {
arr[idx] = stack::get<V>(L, -lua_size<V>::value);
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& arr, std::size_t idx) {
return idx >= arr.max_size();
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) {
@ -279,7 +279,7 @@ namespace sol { namespace stack {
// without hitting where the gotos have infested
// so now I would get the error W4XXX unreachable
// me that the return arr at the end of this function
// 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
@ -308,14 +308,14 @@ namespace sol { namespace stack {
// all in all: W4 is great!~
int index = lua_absindex(L, relindex);
T arr;
T cont;
std::size_t idx = 0;
#if SOL_LUA_VERSION >= 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>(), arr, idx)) {
if (max_size_check(meta::has_max_size<Tu>(), cont, idx)) {
// see above comment
goto done;
}
@ -359,14 +359,14 @@ namespace sol { namespace stack {
continue;
}
push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx);
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 >= arr.max_size()) {
if (idx >= cont.max_size()) {
// see above comment
goto done;
}
@ -390,12 +390,12 @@ namespace sol { namespace stack {
}
if (isnil)
continue;
push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx);
push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
++idx;
}
#endif
done:
return arr;
return cont;
}
static T get(std::true_type, lua_State* L, int index, record& tracking) {
@ -457,13 +457,13 @@ namespace sol { namespace stack {
#endif // make sure stack doesn't overflow
int index = lua_absindex(L, relindex);
C arr;
auto at = arr.cbefore_begin();
C cont;
auto at = cont.cbefore_begin();
std::size_t idx = 0;
#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)) {
if (idx >= arr.max_size()) {
if (idx >= cont.max_size()) {
goto done;
}
bool isnil = false;
@ -480,13 +480,13 @@ namespace sol { namespace stack {
}
if (isnil)
continue;
at = arr.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
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 >= arr.max_size()) {
if (idx >= cont.max_size()) {
goto done;
}
bool isnil = false;
@ -505,12 +505,12 @@ namespace sol { namespace stack {
}
if (isnil)
continue;
at = arr.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
++idx;
}
#endif
done:
return arr;
return cont;
}
template <typename K, typename V>

View File

@ -128,7 +128,7 @@ namespace sol {
template <typename K, typename... Args>
static int push_keyed(lua_State* L, K&& k, Args&&... args) {
stack_detail::undefined_metatable<T> fx(L, &k[0]);
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)...);
}
@ -167,7 +167,7 @@ namespace sol {
template <typename K>
static int push_keyed(lua_State* L, K&& k, T* obj) {
stack_detail::undefined_metatable<U*> fx(L, &k[0]);
stack_detail::undefined_metatable fx(L, &k[0], &stack::stack_detail::set_undefined_methods_on<U*>);
return push_fx(L, fx, obj);
}

View File

@ -300,6 +300,12 @@ namespace sol {
return end();
}
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");

View File

@ -630,8 +630,7 @@ namespace sol {
struct is_pair<std::pair<T1, T2>> : std::true_type {};
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>>;
using is_c_str = any<std::is_same<T, const char*>, std::is_same<T, char const* const>, std::is_same<T, char*>, is_string_of<T, char>, is_string_literal_array_of<T, char>>;
template <typename T>
constexpr inline bool is_c_str_v = is_c_str<T>::value;

View File

@ -19,13 +19,13 @@ namespace sol {
};
inline const string_view& to_string(error_code ec) {
static const string_view arr[4] = {
static const string_view storage[4] = {
"ok",
"invalid code points",
"invalid code unit",
"overlong sequence"
};
return arr[static_cast<std::size_t>(ec)];
return storage[static_cast<std::size_t>(ec)];
}
template <typename It>

View File

@ -37,20 +37,22 @@ namespace sol {
private:
using base_t = basic_metatable<base_type>;
public:
using base_t::base_t;
template <typename>
friend class basic_metatable;
using base_t::pop;
using base_t::push;
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) {
using args_tuple = std::tuple<Args...>&&;
optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());
if constexpr(sizeof...(I) > 0) {
if constexpr (sizeof...(I) > 0) {
if (maybe_uts) {
u_detail::usertype_storage<T>& uts = *maybe_uts;
detail::swallow{ 0, (uts.set(this->lua_state(), std::get<I * 2>(std::forward<args_tuple>(args)), std::get<I * 2 + 1>(std::forward<args_tuple>(args))), 0)... };
(void)detail::swallow{ 0,
(uts.set(this->lua_state(), std::get<I * 2>(std::forward<args_tuple>(args)), std::get<I * 2 + 1>(std::forward<args_tuple>(args))),
0)... };
}
}
else {
@ -58,6 +60,15 @@ namespace sol {
}
}
public:
using base_t::base_t;
using base_t::pop;
using base_t::push;
using base_t::lua_state;
using base_t::get;
using base_t::unregister;
template <typename Key, typename Value>
void set(Key&& key, Value&& value) {
optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());

View File

@ -140,26 +140,26 @@ namespace sol {
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::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::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<T>::value) {
auto f = &detail::static_trampoline<&default_to_string<T>>;
ifx(meta_function::to_string, f);
}
if (fx(meta_function::to_string)) {
if constexpr (is_to_stringable<T>::value) {
auto f = &detail::static_trampoline<&default_to_string<T>>;
ifx(meta_function::to_string, f);
}
}
if (fx(meta_function::call_function)) {
if constexpr (meta::has_deducible_signature<T>::value) {
auto f = &c_call<decltype(&T::operator()), &T::operator()>;
ifx(meta_function::call_function, f);
}
}
if (fx(meta_function::call_function)) {
if constexpr (meta::has_deducible_signature<T>::value) {
auto f = &c_call<decltype(&T::operator()), &T::operator()>;
ifx(meta_function::call_function, f);
}
}
}
@ -167,43 +167,36 @@ namespace sol {
} // namespace detail
namespace stack { namespace stack_detail {
template <typename T>
struct undefined_metatable {
typedef meta::all<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> is_destructible;
typedef std::remove_pointer_t<T> P;
lua_State* L;
const char* key;
undefined_metatable(lua_State* l, const char* k)
: L(l), key(k) {
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());
void operator()() const {
if (luaL_newmetatable(L, key) == 1) {
detail::lua_reg_table l{};
int index = 0;
detail::indexed_insert insert_fx(l, index);
detail::insert_default_registrations<P>(insert_fx, detail::property_always_true);
if constexpr (!std::is_pointer_v<T>) {
l[index] = luaL_Reg{ to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<P>() };
}
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, -2, to_string(meta_function::type).c_str());
}
lua_setmetatable(L, -2);
}
};
}
} // namespace stack::stack_detail
t.pop();
}
}} // namespace stack::stack_detail
} // namespace sol
#endif // SOL_USERTYPE_CORE_HPP

View File

@ -389,12 +389,53 @@ namespace sol { namespace u_detail {
}
void clear() {
if (value_index_table.valid()) {
stack::clear(value_index_table);
}
if (reference_index_table.valid()) {
stack::clear(reference_index_table);
}
if (unique_index_table.valid()) {
stack::clear(unique_index_table);
}
if (const_reference_index_table.valid()) {
stack::clear(const_reference_index_table);
}
if (const_value_index_table.valid()) {
stack::clear(const_value_index_table);
}
if (named_index_table.valid()) {
stack::clear(named_index_table);
}
if (type_table.valid()) {
stack::clear(type_table);
}
if (gc_names_table.valid()) {
stack::clear(gc_names_table);
}
if (named_metatable.valid()) {
lua_State* L = named_metatable.lua_state();
auto pp = stack::push_pop(named_metatable);
int named_metatable_index = pp.index_of(named_metatable);
if (lua_getmetatable(L, named_metatable_index) == 1) {
stack::clear(L, absolute_index(L, -1));
}
stack::clear(named_metatable);
}
value_index_table = lua_nil;
reference_index_table = lua_nil;
unique_index_table = lua_nil;
const_reference_index_table = lua_nil;
const_value_index_table = lua_nil;
named_index_table = lua_nil;
type_table = lua_nil;
gc_names_table = lua_nil;
named_metatable = lua_nil;
storage.clear();
string_keys.clear();
auxiliary_keys.clear();
// TODO: also nuke individual lua tables,
// one by one,
// then replace unqualified_getter/setter
}
template <bool is_new_index, typename Base>
@ -433,7 +474,7 @@ namespace sol { namespace u_detail {
}
}
}
else if (k_type != type::nil && k_type != type::none) {
else if (k_type != type::lua_nil && k_type != type::none) {
reference* target = nullptr;
{
stack_reference k = stack::get<stack_reference>(L, 2);
@ -461,7 +502,7 @@ namespace sol { namespace u_detail {
int base_result;
(void)keep_going;
(void)base_result;
detail::swallow{ 1, (base_walk_index<is_new_index, Bases>(L, self, keep_going, base_result), 1)... };
(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;
@ -498,7 +539,6 @@ namespace sol { namespace u_detail {
this->is_using_index |= true;
this->is_using_new_index |= true;
//detail::clear_entries(t);
if (submetatable == submetatable_type::named) {
stack::set_field(L, metatable_key, named_index_table, t.stack_index());
stack_reference stack_metametatable(L, -named_metatable.push());
@ -567,6 +607,11 @@ namespace sol { namespace u_detail {
inline void set(lua_State* L, Key&& key, Value&& value);
};
template <typename T>
inline int destruct_usertype_storage (lua_State* L) {
return detail::user_alloc_destruct<usertype_storage<T>>(L);
}
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>;
@ -706,7 +751,7 @@ namespace sol { namespace u_detail {
int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1));
stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count);
// set the destruction routine on the metatable
stack::set_field(L, meta_function::garbage_collect, detail::user_alloc_destruct<usertype_storage<T>>, usertype_storage_metatable.stack_index());
stack::set_field(L, meta_function::garbage_collect, &destruct_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();
@ -759,10 +804,12 @@ namespace sol { namespace u_detail {
template <typename T>
inline void delete_usertype_storage(lua_State* L) {
using u_traits = usertype_traits<T>;
#if 0
using u_const_traits = usertype_traits<const T>;
using u_unique_traits = usertype_traits<detail::unique_usertype<T>>;
using u_ref_traits = usertype_traits<T*>;
using u_const_ref_traits = usertype_traits<T const*>;
#endif
using uts = usertype_storage<T>;
const char* gcmetakey = &u_traits::gc_table()[0];
@ -771,9 +818,11 @@ namespace sol { namespace u_detail {
lua_pop(L, 1);
return;
}
lua_pop(L, 1);
usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L);
target_umt.clear();
// get the registry
#if 0
stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
registry.push();
// eliminate all named entries for this usertype
@ -786,6 +835,7 @@ namespace sol { namespace u_detail {
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();
#endif // Registry Cleanout
stack::set_field<true>(L, gcmetakey, lua_nil);
}

View File

@ -23,53 +23,60 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
CI=true
declare -a gcc_versions
gcc_versions=(
4.9
5
6
7
# 7
# 8
)
declare -r gcc_versions
declare -a llvm_versions
llvm_versions=(
3.6.2
3.7.1
3.8.1
3.9.1
4.0.1
5.0.1
4.0.0
# 5.0.2
# 6.0.1
# 7.0.1
# 8.0.0
)
declare -r llvm_versions
build_generic=false
if [ -z "${DOCKER_USERNAME}" ]
then
docker_username=
else
docker_username=${DOCKER_USERNAME}/
fi
if [ -z "${SOL2_CI}"]
then
SOL2_CI=true
fi
echo "====== ======= ======= ======= ======"
echo "====== Building All Docker Images ======"
echo "====== ======= ======= ======= ======"
echo "For: ${DOCKER_USERNAME} from Dockerfile in ${SOL2_DIR}\n"
for i in $gcc_versions; do
GCC_VERSION=$i
unset LLVM_VERSION
echo "====== Building Docker Image: ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} ======="
docker build --tag ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} --build-arg GCC_VERSION=${GCC_VERSION} --build-arg LLVM_VERSION=${LLVM_VERSION} --build-arg CI=${CI} "${SOL2_DIR}"
docker build --tag ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} --build-arg GCC_VERSION=${GCC_VERSION} --build-arg LLVM_VERSION=${LLVM_VERSION} --build-arg SOL2_CI=${SOL2_CI} "${SOL2_DIR}"
done
for i in $llvm_versions; do
LLVM_VERSION=$i
unset GCC_VERSION
echo "====== Building Docker Image: ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} ======="
docker build --tag ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} --build-arg GCC_VERSION=${GCC_VERSION} --build-arg LLVM_VERSION=${LLVM_VERSION} --build-arg CI=${CI} "${SOL2_DIR}"
docker build --tag ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} --build-arg GCC_VERSION=${GCC_VERSION} --build-arg LLVM_VERSION=${LLVM_VERSION} --build-arg SOL2_CI=${SOL2_CI} "${SOL2_DIR}"
done
unset LLVM_VERSION
unset GCC_VERSION
echo "====== Building Docker Image: ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} ======="
docker build --tag ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} --build-arg GCC_VERSION=${GCC_VERSION} --build-arg LLVM_VERSION=${LLVM_VERSION} --build-arg CI=${CI} "${SOL2_DIR}"
if [ "${build_generic}" = true ]
then
unset LLVM_VERSION
unset GCC_VERSION
echo "====== Building Docker Image: ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} ======="
docker build --tag ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} --build-arg GCC_VERSION=${GCC_VERSION} --build-arg LLVM_VERSION=${LLVM_VERSION} --build-arg SOL2_CI=${SOL2_CI} "${SOL2_DIR}"
fi

View File

@ -32,7 +32,7 @@ build_dir="$(pwd)"
echo "#\!/usr/bin/env zsh\n\n" > "sol2.compiler.vars"
# # Initial and necessary installations
apt-get update && apt-get -y install ninja-build libreadline6 libreadline6-dev lib32readline6 lib32readline6-dev python3 wget curl libcurl3 cmake git
apt-get update && apt-get -y install lsb-release ninja-build libreadline7 libreadline-dev lib32readline7 lib32readline-dev python3 wget curl libcurl4 cmake git
# # LLVM and GCC updates
# Grab LLVM or GCC
@ -46,13 +46,17 @@ then
minor=$version_nums[2]
revision=$version_nums[3]
download_llvm=true
download_version=16.04
image_version=$(lsb_release -rs)
download_version=${image_version}
apt_version=${major}.${minor}
#sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
#sudo apt-get -y update
if [ ${major} -le 5 ] && [ ${major} -ge 4 ];
if [ ${major} -le 6 ];
then
download_llvm=false
download_llvm=true
download_version=16.04
elif [ ${major} -eq 4 ]
then
download_llvm=true
download_version=16.04
elif [ ${major} -eq 3 ]
then
download_llvm=false
@ -60,27 +64,43 @@ then
then
download_llvm=true
download_version=14.04
elif [ ${minor} -lt 10 ]
then
download_llvm=true
download_version=16.04
fi
fi
if [ ${download_llvm} = true ]
then
export LLVM_ARCHIVE_PATH=${build_dir}/clang+llvm.tar.xz
export CLANG_PREFIX=${build_dir}/clang-${LLVM_VERSION}
export LLVM_ARCHIVE_PATH=${build_dir}/clang-llvm.tar.xz
export CLANG_PREFIX=${build_dir}/clang-llvm-${LLVM_VERSION}
export PATH=$CLANG_PREFIX/bin:$PATH
export LD_LIBRARY_PATH=$CLANG_PREFIX/lib:$LD_LIBRARY_PATH
echo "export LLVM_ARCHIVE_PATH=${build_dir}/clang+llvm.tar.xz\nexport CLANG_PREFIX=${build_dir}/clang-$LLVM_VERSION\nexport PATH=$CLANG_PREFIX/bin:$PATH\nexport LD_LIBRARY_PATH=$CLANG_PREFIX/lib:$LD_LIBRARY_PATH\n" >> "sol2.compiler.vars"
apt-get -y install xz-utils clang
#if [${major} -le 5]
#then
# wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-${download_version}.tar.xz -O ${LLVM_ARCHIVE_PATH}
# http://releases.llvm.org/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-${download_version}.tar.xz
#else
# wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-${download_version}.tar.xz -O ${LLVM_ARCHIVE_PATH}
#fi
wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-${download_version}.tar.xz -O ${LLVM_ARCHIVE_PATH}
mkdir -p "${CLANG_PREFIX}"
tar xf "${LLVM_ARCHIE_PATH}" -C "${CLANG_PREFIX}" --strip-components 1
# make sure a clang(++) of major/minor exists
# use || true to ignore potential failures
ln -s "clang-${major}.${minor}" "${CLANG_PREFIX}/bin/clang-${major}.${minor}" || true
ln -s "clang-${major}.${minor}" "${CLANG_PREFIX}/bin/clang++-${major}.${minor}" || true
rm -f "${LLVM_ARCHIVE_PATH}"
export CC=clang-${major}.${minor}
export CXX=clang++-${major}.${minor}
tar xf "${LLVM_ARCHIVE_PATH}" -C "${CLANG_PREFIX}" --strip-components 1
if [ -f "${CLANG_PREFIX}/bin/clang" ]
then
export CC="${CLANG_PREFIX}/bin/clang"
else
export CC="${CLANG_PREFIX}/bin/clang-${major}"
fi
if [ -f "${CLANG_PREFIX}/bin/clang++-${major}" ]
then
export CXX="${CLANG_PREFIX}/bin/clang++-${major}"
else
export CXX="${CLANG_PREFIX}/bin/clang++"
fi
else
apt-get -y install clang-${apt_version}
export CC=clang-${apt_version}
@ -89,11 +109,15 @@ then
elif [ "${GCC_VERSION}" ]
then
# get and use GCC version that we desire
apt-get -y install software-properties-common python-software-properties
# python-software-properties is no longer needed in 18.04, it
# comes with software-properties-common
apt-get -y install software-properties-common
add-apt-repository -y ppa:ubuntu-toolchain-r/test
apt-get -y update
apt-get -y dist-upgrade
apt-get -y install gcc-${GCC_VERSION} g++-${GCC_VERSION} gcc-${GCC_VERSION}-multilib g++-${GCC_VERSION}-multilib
#update-alternatives --remove-all gcc
#update-alternatives --remove-all g++
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 60 --slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION}
update-alternatives --config gcc
export CC=gcc-${GCC_VERSION}
@ -112,8 +136,8 @@ apt-get -y autoclean
echo "=== Compiler and tool variables ==="
ninja --version
cmake --version
$CC --version
$CXX --version
${CC} --version
${CXX} --version
echo "export CC=$CC\nexport CXX=$CXX\n" >> "sol2.compiler.vars"

View File

@ -26,24 +26,22 @@
CI=true
declare -a gcc_versions
gcc_versions=(
4.9
5
6
7
8
)
declare -r gcc_versions
declare -a llvm_versions
llvm_versions=(
3.6.2
3.7.1
3.8.1
3.9.1
4.0.1
5.0.1
# 5.0.2
# 6.0.1
# 7.0.1
# 8.0.0
)
declare -r llvm_versions
push_generic=false
if [ -z "${DOCKER_USERNAME}" ]
then
docker_username=
@ -69,8 +67,10 @@ for i in $llvm_versions; do
docker push ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION}
done
unset LLVM_VERSION
unset GCC_VERSION
echo "====== Pushing Docker Image: ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} ======="
docker push ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION}
if [ "${push_generic}" = true ]
then
unset LLVM_VERSION
unset GCC_VERSION
echo "====== Pushing Docker Image: ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION} ======="
docker push ${docker_username}sol2:gcc-${GCC_VERSION}_llvm-${LLVM_VERSION}
fi

View File

@ -24,10 +24,10 @@
# # This script runs the actual project
echo -en "travis_fold:start:build_preparation.1\r"
echo -e "travis_fold:start:build_preparation.1\r"
if [ -z "${SOL2_DIR}" ]
then
if [ ${CI} = true ]
if [ "${SOL2_CI}" = true ]
then
export SOL2_DIR=~/sol2
else
@ -35,9 +35,14 @@ echo -en "travis_fold:start:build_preparation.1\r"
fi
fi
if [ -z "${LUA_VERSION}" ]
if [ -z "${SOL2_LUA_VERSION}" ]
then
export LUA_VERSION=5.3.4
export SOL2_LUA_VERSION=5.3.5
fi
if [ -z "${SOL2_PLATFORM}" ]
then
export SOL2_PLATFORM=x64
fi
mkdir -p build-sol2
@ -50,47 +55,82 @@ echo -en "travis_fold:start:build_preparation.1\r"
source ./sol2.compiler.vars
fi
if [[ ${LUA_VERSION} =~ "5.3" ]]
if [ ! -z "${CC}" ]
then
export INTEROP_DEFINES="-DINTEROP_EXAMPLES=ON -DTESTS_INTEROP_EXAMPLES=ON -DINTEROP_EXAMPLES_SINGLE=ON -DDYNAMIC_LOADING_EXAMPLES=ON -DDYNAMIC_LOADING_EXAMPLES_SINGLE=ON -DTESTS_DYNAMIC_LOADING_EXAMPLES=ON"
build_type_cc="-DCMAKE_CXX_COMPILER=${CC}"
else
export INTEROP_DEFINES=
build_type_cc=
fi
if [ ! -z "${CXX}" ]
then
build_type_cxx="-DCMAKE_CXX_COMPILER=${CXX}"
else
build_type_cxx=
fi
SOL2_CMAKE_DEFINES=("-DSOL2_LUA_VERSION=${SOL2_LUA_VERSION}")
SOL2_CMAKE_DEFINES+=("-DSOL2_PLATFORM=${SOL2_PLATFORM}")
SOL2_CMAKE_DEFINES+=('-DSOL2_CI=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_BUILD_LUA=ON')
SOL2_CMAKE_DEFINES+=('-DBUILD_LUA_AS_DLL=OFF')
SOL2_CMAKE_DEFINES+=('-DSOL2_TESTS=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_EXAMPLES=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_TESTS_EXAMPLES=ON')
if [[ ! -z ${SOL2_TEST_SINGLE} ]]
then
SOL2_CMAKE_DEFINES+=('-DSOL2_GENERATE_SINGLE=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_EXAMPLES_SINGLE=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_EXAMPLES_SINGLE_GENERATED=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_TESTS_SINGLE=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_TESTS_SINGLE_GENERATED=ON')
fi
if [[ ! -z ${SOL2_TEST_INTEROP} ]]
then
SOL2_CMAKE_DEFINES+=('-DSOL2_INTEROP_EXAMPLES=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_TESTS_INTEROP_EXAMPLES=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_DYNAMIC_LOADING_EXAMPLES=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_TESTS_DYNAMIC_LOADING_EXAMPLES=ON')
if [[ ! -z ${SOL2_TEST_SINGLE} ]]
then
SOL2_CMAKE_DEFINES+=('-DSOL2_INTEROP_EXAMPLES_SINGLE=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_INTEROP_EXAMPLES_SINGLE_GENERATED=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_DYNAMIC_LOADING_EXAMPLES_SINGLE=ON')
SOL2_CMAKE_DEFINES+=('-DSOL2_DYNAMIC_LOADING_EXAMPLES_SINGLE_GENERATED=ON')
fi
fi
mkdir -p Debug Release
export build_type_cc=-DCMAKE_C_COMPILER\=${CC}
export build_type_cxx=-DCMAKE_CXX_COMPILER\=${CXX}
echo -en "travis_fold:end:build_preparation.1\r"
echo -e "travis_fold:end:build_preparation.1\r"
# show the tool and compiler versions we're using
echo -en "travis_fold:start:build_preparation.2\r"
echo -e "travis_fold:start:build_preparation.2\r"
echo "=== Compiler and tool variables ==="
ninja --version
cmake --version
${CC} --version
${CXX} --version
echo build_type_cc : "${build_type_cc}"
echo build_type_cxx: "${build_type_cxx}"
echo -en "travis_fold:end:build_preparation.2\r"
echo sol2 source dir : "${SOL2_DIR}"
echo build_type_cc : "${build_type_cc}"
echo build_type_cxx : "${build_type_cxx}"
echo cmake defines : "${SOL2_CMAKE_DEFINES[@]}"
echo -e "travis_fold:end:build_preparation.2\r"
echo -en "travis_fold:start:build.debug\r"
echo -e "travis_fold:start:build.debug\r"
cd Debug
cmake ${SOL2_DIR} -G Ninja -DCMAKE_BUILD_TYPE=Debug ${build_type_cc} ${build_type_cxx} -DSOL2_LUA_VERSION="${LUA_VERSION}" -DSOL2_CI=ON -DSOL2_PLATFORM=${PLATFORM} -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=OFF -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON ${INTEROP_DEFINES}
cmake "${SOL2_DIR}" -G Ninja -DCMAKE_BUILD_TYPE=Debug ${build_type_cc} ${build_type_cxx} "${SOL2_CMAKE_DEFINES[@]}"
cmake --build . --config Debug
echo -en "travis_fold:end:build.debug\r"
echo -en "travis_fold:start:test.debug\r"
echo -e "travis_fold:end:build.debug\r"
echo -e "travis_fold:start:test.debug\r"
ctest --build-config Debug --output-on-failure
cd ..
echo -en "travis_fold:end:test.debug\r"
echo -e "travis_fold:end:test.debug\r"
echo "travis_fold:start:build.release\r"
echo -e "travis_fold:start:build.release\r"
cd Release
cmake ${SOL2_DIR} -G Ninja -DCMAKE_BUILD_TYPE=Release ${build_type_cc} ${build_type_cxx} -DSOL2_LUA_VERSION="${LUA_VERSION}" -DSOL2_CI=ON -DSOL2_PLATFORM=${PLATFORM} -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=OFF -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON ${INTEROP_DEFINES}
cmake "${SOL2_DIR}" -G Ninja -DCMAKE_BUILD_TYPE=Release ${build_type_cc} ${build_type_cxx} "${SOL2_CMAKE_DEFINES[@]}"
cmake --build . --config Release
echo -en "travis_fold:end:build.release\r"
echo -en "travis_fold:start:test.release\r"
echo -e "travis_fold:end:build.release\r"
echo -e "travis_fold:start:test.release\r"
ctest --build-config Release --output-on-failure
cd ..
echo -en "travis_fold:end:test.release\r"
echo -e "travis_fold:end:test.release\r"

View File

@ -32,13 +32,13 @@ ninja --version
cmake --version
cd Debug
cmake ${SOL2_DIR} -G Xcode -DCMAKE_BUILD_TYPE=Debug -DSOL2_LUA_VERSION="${LUA_VERSION}" -DSOL2_CI=ON -DSOL2_PLATFORM=${PLATFORM} -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=OFF -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON
cmake ${SOL2_DIR} -G Xcode -DCMAKE_BUILD_TYPE=Debug -DSOL2_LUA_VERSION="${SOL2_LUA_VERSION}" -DSOL2_CI=ON -DSOL2_PLATFORM=${SOL2_PLATFORM} -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=OFF -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE_GENERATED=ON -DSOL2_TESTS_SINGLE_GENERATED=ON
cmake --build . --config Debug
ctest --build-config Debug --output-on-failure
cd ..
cd Release
cmake ${SOL2_DIR} -G Xcode -DCMAKE_BUILD_TYPE=Release -DSOL2_LUA_VERSION="${LUA_VERSION}" -DSOL2_CI=ON -DSOL2_PLATFORM=${PLATFORM} -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=OFF -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE=ON -DSOL2_TESTS_SINGLE_GENERATED=ON
cmake ${SOL2_DIR} -G Xcode -DCMAKE_BUILD_TYPE=Release -DSOL2_LUA_VERSION="${SOL2_LUA_VERSION}" -DSOL2_CI=ON -DSOL2_PLATFORM=${SOL2_PLATFORM} -DSOL2_BUILD_LUA=ON -DBUILD_LUA_AS_DLL=OFF -DSOL2_TESTS=ON -DSOL2_EXAMPLES=ON -DSOL2_GENERATE_SINGLE=ON -DSOL2_TESTS_EXAMPLES=ON -DSOL2_EXAMPLES_SINGLE=ON -DSOL2_TESTS_SINGLE_GENERATED=ON
cmake --build . --config Release
ctest --build-config Release --output-on-failure
cd ..

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2019-03-18 11:44:35.615829 UTC
// This header was generated with sol v3.0.0-beta (revision b63d7af)
// Generated 2019-03-21 16:10:16.440886 UTC
// This header was generated with sol v3.0.0-beta (revision 04b36f1)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script.
// Generated 2019-03-18 11:44:35.317733 UTC
// This header was generated with sol v3.0.0-beta (revision b63d7af)
// Generated 2019-03-21 16:10:16.112045 UTC
// This header was generated with sol v3.0.0-beta (revision 04b36f1)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -2042,7 +2042,11 @@ namespace sol {
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
@ -3383,18 +3387,18 @@ namespace sol {
using base_t = std::vector<std::byte, Allocator>;
public:
using base_t::allocator_type;
using base_t::const_iterator;
using base_t::const_pointer;
using base_t::const_reference;
using base_t::const_reverse_iterator;
using base_t::difference_type;
using base_t::iterator;
using base_t::pointer;
using base_t::reference;
using base_t::reverse_iterator;
using base_t::size_type;
using base_t::value_type;
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=;
@ -6047,7 +6051,7 @@ namespace sol { namespace detail {
ebco(const T& v) : value_(v){};
ebco(T&& v) : value_(std::move(v)){};
ebco& operator=(const T& v) {
value = v;
value_ = v;
return *this;
}
ebco& operator=(T&& v) {
@ -6059,13 +6063,17 @@ namespace sol { namespace detail {
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){}
T& value() {
T& value() & {
return value_;
}
T const& value() const {
T const& value() const & {
return value_;
}
T&& value() && {
return std::move(value_);
}
};
template <typename T, std::size_t tag>
@ -6092,13 +6100,17 @@ namespace sol { namespace detail {
return *this;
};
T& value() {
T& value() & {
return static_cast<T&>(*this);
}
T const& value() const {
T const& value() const & {
return static_cast<T const&>(*this);
}
T&& value() && {
return std::move(static_cast<T&>(*this));
}
};
template <typename T, std::size_t tag>
@ -6134,10 +6146,18 @@ namespace sol { namespace detail {
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco& operator=(T&& v) {
ref = v;
ref = std::move(v);
return *this;
}
T& value() & {
return ref;
}
const T& value() const & {
return ref;
}
T&& value() && {
return std::move(ref);
}
@ -8084,7 +8104,7 @@ namespace sol {
const char* name = lua_tolstring(L, -1, &sz);
std::string tn(name, static_cast<std::string::size_type>(sz));
lua_pop(L, 2);
return std::move(tn);
return tn;
}
default:
break;
@ -9497,13 +9517,13 @@ namespace sol {
}
template <typename T, typename Al>
void reserve(std::vector<T, Al>& arr, std::size_t hint) {
arr.reserve(hint);
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>& arr, std::size_t hint) {
arr.reserve(hint);
void reserve(std::basic_string<T, Tr, Al>& str, std::size_t hint) {
str.reserve(hint);
}
inline bool property_always_true(meta_function) {
@ -9778,6 +9798,24 @@ namespace sol {
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) {
@ -9811,6 +9849,30 @@ namespace sol {
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());
}
template <typename T, typename... Args>
inline int push(lua_State* L, T&& t, Args&&... args) {
using Tu = meta::unqualified_t<T>;
@ -11052,13 +11114,13 @@ namespace sol {
};
inline const string_view& to_string(error_code ec) {
static const string_view arr[4] = {
static const string_view storage[4] = {
"ok",
"invalid code points",
"invalid code unit",
"overlong sequence"
};
return arr[static_cast<std::size_t>(ec)];
return storage[static_cast<std::size_t>(ec)];
}
template <typename It>
@ -11537,32 +11599,32 @@ namespace sol { namespace stack {
using Tu = meta::unqualified_t<T>;
template <typename V>
static void push_back_at_end(std::true_type, types<V>, lua_State* L, T& arr, std::size_t) {
arr.push_back(stack::get<V>(L, -lua_size<V>::value));
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& arr, std::size_t idx) {
insert_at_end(meta::has_insert<Tu>(), t, L, arr, idx);
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& arr, std::size_t) {
static void insert_at_end(std::true_type, types<V>, lua_State* L, T& cont, std::size_t) {
using std::cend;
arr.insert(cend(arr), stack::get<V>(L, -lua_size<V>::value));
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& arr, std::size_t idx) {
arr[idx] = stack::get<V>(L, -lua_size<V>::value);
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& arr, std::size_t idx) {
return idx >= arr.max_size();
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) {
@ -11584,7 +11646,7 @@ namespace sol { namespace stack {
// without hitting where the gotos have infested
// so now I would get the error W4XXX unreachable
// me that the return arr at the end of this function
// 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
@ -11613,14 +11675,14 @@ namespace sol { namespace stack {
// all in all: W4 is great!~
int index = lua_absindex(L, relindex);
T arr;
T cont;
std::size_t idx = 0;
#if SOL_LUA_VERSION >= 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>(), arr, idx)) {
if (max_size_check(meta::has_max_size<Tu>(), cont, idx)) {
// see above comment
goto done;
}
@ -11664,14 +11726,14 @@ namespace sol { namespace stack {
continue;
}
push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx);
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 >= arr.max_size()) {
if (idx >= cont.max_size()) {
// see above comment
goto done;
}
@ -11695,12 +11757,12 @@ namespace sol { namespace stack {
}
if (isnil)
continue;
push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx);
push_back_at_end(meta::has_push_back<Tu>(), t, L, cont, idx);
++idx;
}
#endif
done:
return arr;
return cont;
}
static T get(std::true_type, lua_State* L, int index, record& tracking) {
@ -11762,13 +11824,13 @@ namespace sol { namespace stack {
#endif // make sure stack doesn't overflow
int index = lua_absindex(L, relindex);
C arr;
auto at = arr.cbefore_begin();
C cont;
auto at = cont.cbefore_begin();
std::size_t idx = 0;
#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)) {
if (idx >= arr.max_size()) {
if (idx >= cont.max_size()) {
goto done;
}
bool isnil = false;
@ -11785,13 +11847,13 @@ namespace sol { namespace stack {
}
if (isnil)
continue;
at = arr.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
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 >= arr.max_size()) {
if (idx >= cont.max_size()) {
goto done;
}
bool isnil = false;
@ -11810,12 +11872,12 @@ namespace sol { namespace stack {
}
if (isnil)
continue;
at = arr.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
at = cont.insert_after(at, stack::get<V>(L, -lua_size<V>::value));
++idx;
}
#endif
done:
return arr;
return cont;
}
template <typename K, typename V>
@ -12648,7 +12710,7 @@ namespace sol {
template <typename K, typename... Args>
static int push_keyed(lua_State* L, K&& k, Args&&... args) {
stack_detail::undefined_metatable<T> fx(L, &k[0]);
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)...);
}
@ -12687,7 +12749,7 @@ namespace sol {
template <typename K>
static int push_keyed(lua_State* L, K&& k, T* obj) {
stack_detail::undefined_metatable<U*> fx(L, &k[0]);
stack_detail::undefined_metatable fx(L, &k[0], &stack::stack_detail::set_undefined_methods_on<U*>);
return push_fx(L, fx, obj);
}
@ -15911,7 +15973,7 @@ namespace sol {
construct_match<T, TypeLists...>(constructor_match<T, checked, clean_stack>(obj), L, argcount, 1 + static_cast<int>(syntax));
userdataref.push();
stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]);
stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
umf();
return 1;
@ -16230,7 +16292,7 @@ namespace sol {
construct_match<T, Args...>(constructor_match<T, false, clean_stack>(obj), L, argcount, boost + 1 + static_cast<int>(syntax));
userdataref.push();
stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]);
stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
umf();
return 1;
@ -16252,7 +16314,7 @@ namespace sol {
stack::call_into_lua<checked, clean_stack>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj));
userdataref.push();
stack::stack_detail::undefined_metatable<T> umf(L, &meta[0]);
stack::stack_detail::undefined_metatable umf(L, &meta[0], &stack::stack_detail::set_undefined_methods_on<T>);
umf();
return 1;
@ -20390,26 +20452,26 @@ namespace sol {
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::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::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<T>::value) {
auto f = &detail::static_trampoline<&default_to_string<T>>;
ifx(meta_function::to_string, f);
}
if (fx(meta_function::to_string)) {
if constexpr (is_to_stringable<T>::value) {
auto f = &detail::static_trampoline<&default_to_string<T>>;
ifx(meta_function::to_string, f);
}
}
if (fx(meta_function::call_function)) {
if constexpr (meta::has_deducible_signature<T>::value) {
auto f = &c_call<decltype(&T::operator()), &T::operator()>;
ifx(meta_function::call_function, f);
}
}
if (fx(meta_function::call_function)) {
if constexpr (meta::has_deducible_signature<T>::value) {
auto f = &c_call<decltype(&T::operator()), &T::operator()>;
ifx(meta_function::call_function, f);
}
}
}
@ -20417,43 +20479,36 @@ namespace sol {
} // namespace detail
namespace stack { namespace stack_detail {
template <typename T>
struct undefined_metatable {
typedef meta::all<meta::neg<std::is_pointer<T>>, std::is_destructible<T>> is_destructible;
typedef std::remove_pointer_t<T> P;
lua_State* L;
const char* key;
undefined_metatable(lua_State* l, const char* k)
: L(l), key(k) {
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());
void operator()() const {
if (luaL_newmetatable(L, key) == 1) {
detail::lua_reg_table l{};
int index = 0;
detail::indexed_insert insert_fx(l, index);
detail::insert_default_registrations<P>(insert_fx, detail::property_always_true);
if constexpr (!std::is_pointer_v<T>) {
l[index] = luaL_Reg{ to_string(meta_function::garbage_collect).c_str(), detail::make_destructor<P>() };
}
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, -2, to_string(meta_function::type).c_str());
}
lua_setmetatable(L, -2);
}
};
}
} // namespace stack::stack_detail
t.pop();
}
}} // namespace stack::stack_detail
} // namespace sol
// end of sol/usertype_core.hpp
@ -20819,12 +20874,47 @@ namespace sol { namespace u_detail {
}
void clear() {
if (value_index_table.valid()) {
stack::clear(value_index_table);
}
if (reference_index_table.valid()) {
stack::clear(reference_index_table);
}
if (unique_index_table.valid()) {
stack::clear(unique_index_table);
}
if (const_reference_index_table.valid()) {
stack::clear(const_reference_index_table);
}
if (const_value_index_table.valid()) {
stack::clear(const_value_index_table);
}
if (named_index_table.valid()) {
stack::clear(named_index_table);
}
if (type_table.valid()) {
stack::clear(type_table);
}
if (gc_names_table.valid()) {
stack::clear(gc_names_table);
}
if (named_metatable.valid()) {
stack::clear(named_metatable);
}
value_index_table = lua_nil;
reference_index_table = lua_nil;
unique_index_table = lua_nil;
const_reference_index_table = lua_nil;
const_value_index_table = lua_nil;
named_index_table = lua_nil;
type_table = lua_nil;
gc_names_table = lua_nil;
named_metatable = lua_nil;
storage.clear();
string_keys.clear();
auxiliary_keys.clear();
// TODO: also nuke individual lua tables,
// one by one,
// then replace unqualified_getter/setter
}
template <bool is_new_index, typename Base>
@ -20863,7 +20953,7 @@ namespace sol { namespace u_detail {
}
}
}
else if (k_type != type::nil && k_type != type::none) {
else if (k_type != type::lua_nil && k_type != type::none) {
reference* target = nullptr;
{
stack_reference k = stack::get<stack_reference>(L, 2);
@ -20928,7 +21018,6 @@ namespace sol { namespace u_detail {
this->is_using_index |= true;
this->is_using_new_index |= true;
//detail::clear_entries(t);
if (submetatable == submetatable_type::named) {
stack::set_field(L, metatable_key, named_index_table, t.stack_index());
stack_reference stack_metametatable(L, -named_metatable.push());
@ -20997,6 +21086,11 @@ namespace sol { namespace u_detail {
inline void set(lua_State* L, Key&& key, Value&& value);
};
template <typename T>
inline int destruct_usertype_storage (lua_State* L) {
return detail::user_alloc_destruct<usertype_storage<T>>(L);
}
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>;
@ -21136,7 +21230,7 @@ namespace sol { namespace u_detail {
int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1));
stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count);
// set the destruction routine on the metatable
stack::set_field(L, meta_function::garbage_collect, detail::user_alloc_destruct<usertype_storage<T>>, usertype_storage_metatable.stack_index());
stack::set_field(L, meta_function::garbage_collect, &destruct_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();
@ -21189,10 +21283,12 @@ namespace sol { namespace u_detail {
template <typename T>
inline void delete_usertype_storage(lua_State* L) {
using u_traits = usertype_traits<T>;
#if 0
using u_const_traits = usertype_traits<const T>;
using u_unique_traits = usertype_traits<detail::unique_usertype<T>>;
using u_ref_traits = usertype_traits<T*>;
using u_const_ref_traits = usertype_traits<T const*>;
#endif
using uts = usertype_storage<T>;
const char* gcmetakey = &u_traits::gc_table()[0];
@ -21201,9 +21297,11 @@ namespace sol { namespace u_detail {
lua_pop(L, 1);
return;
}
lua_pop(L, 1);
usertype_storage<T>& target_umt = stack::pop<user<usertype_storage<T>>>(L);
target_umt.clear();
// get the registry
#if 0
stack_reference registry(L, raw_index(LUA_REGISTRYINDEX));
registry.push();
// eliminate all named entries for this usertype
@ -21216,6 +21314,7 @@ namespace sol { namespace u_detail {
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();
#endif // Registry Cleanout
stack::set_field<true>(L, gcmetakey, lua_nil);
}
@ -22096,6 +22195,12 @@ namespace sol {
return end();
}
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");
@ -22483,7 +22588,8 @@ namespace sol {
using ustorage_base = u_detail::usertype_storage_base;
lua_State* L = this->lua_state();
int x = lua_gettop(L);
int top = lua_gettop(L);
auto pp = stack::push_pop(*this);
stack_reference mt(L, -1);
@ -22491,19 +22597,19 @@ namespace sol {
if (type_of(L, -1) != type::table) {
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) {
return;
}
ustorage_base& base_storage = *static_cast<ustorage_base*>(stack::get<void*>(L, -1));
base_storage.clear();
stack_reference gc_names_table(L, -1);
std::array<const char*, 6> registry_traits;
std::array<string_view, 6> registry_traits;
for (int i = 0; i < registry_traits.size(); ++i) {
u_detail::submetatable_type smt = static_cast<u_detail::submetatable_type>(i);
stack::get_field(L, smt, gc_names_table.stack_index());
registry_traits[i] = stack::get<const char*>(L, -1);
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();
@ -22513,24 +22619,27 @@ namespace sol {
// in registry upon creation)
for (int 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) {
const char* gcmetakey = registry_traits[i];
stack::set_field<true>(L, gcmetakey, lua_nil);
}
else {
stack::set_field(L, registry_traits[i], lua_nil, registry.stack_index());
// 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
// 8 total
int y = lua_gettop(L);
lua_pop(L, 9);
int z = lua_gettop(L);
int a = x + y + z;
// + 1 registry
// 10 total, 4 left since popping off 6 gc_names tables
lua_settop(L, top);
}
};
@ -22545,20 +22654,22 @@ namespace sol {
private:
using base_t = basic_metatable<base_type>;
public:
using base_t::base_t;
template <typename>
friend class basic_metatable;
using base_t::pop;
using base_t::push;
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) {
using args_tuple = std::tuple<Args...>&&;
optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());
if constexpr(sizeof...(I) > 0) {
if constexpr (sizeof...(I) > 0) {
if (maybe_uts) {
u_detail::usertype_storage<T>& uts = *maybe_uts;
detail::swallow{ 0, (uts.set(this->lua_state(), std::get<I * 2>(std::forward<args_tuple>(args)), std::get<I * 2 + 1>(std::forward<args_tuple>(args))), 0)... };
detail::swallow{ 0,
(uts.set(this->lua_state(), std::get<I * 2>(std::forward<args_tuple>(args)), std::get<I * 2 + 1>(std::forward<args_tuple>(args))),
0)... };
}
}
else {
@ -22566,6 +22677,15 @@ namespace sol {
}
}
public:
using base_t::base_t;
using base_t::pop;
using base_t::push;
using base_t::lua_state;
using base_t::get;
using base_t::unregister;
template <typename Key, typename Value>
void set(Key&& key, Value&& value) {
optional<u_detail::usertype_storage<T>&> maybe_uts = u_detail::maybe_get_usertype_storage<T>(this->lua_state());
@ -23064,16 +23184,23 @@ namespace sol {
// beginning of sol/lua_value.hpp
namespace sol {
namespace detail {
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>>;
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>>;
}
struct lua_value {
private:
static lua_State*& thread_local_lua_state() {
static thread_local lua_State* L = nullptr;
return L;
@ -23086,21 +23213,39 @@ namespace sol {
thread_local_lua_state() = L;
}
template <typename T, meta::disable<detail::is_reference_or_lua_value_init_list<meta::unqualified_t<T>>> = meta::enabler>
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<detail::is_lua_value_single_constructible<meta::unqualified_t<T>>> = meta::enabler>
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<lua_value> il) : lua_value(((set_lua_state(L_)), std::move(il))) {
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<lua_value> il) : ref_value(make_reference(thread_local_lua_state(), 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_, reference r) : lua_value(((thread_local_lua_state() = L_), std::move(r))) {
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)) {
@ -23141,6 +23286,8 @@ namespace sol {
}
};
using array_value = typename lua_value::arr;
namespace stack {
template <>
struct unqualified_pusher<lua_value> {

View File

@ -49,10 +49,18 @@ function(CREATE_TEST test_target_name test_name target_sol)
_CRT_SECURE_NO_WARNINGS _CRT_SECURE_NO_DEPRECATE)
else()
target_compile_options(${test_target_name}
PRIVATE -std=c++1z
PRIVATE -std=c++1z
-Wno-unknown-warning -Wno-unknown-warning-option
-Wall -Wextra -Wpedantic -pedantic -pedantic-errors
-Wno-noexcept-type
-Wno-unknown-warning -Wno-unknown-warning-option)
-Wno-noexcept-type)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# For another day, when C++ is not so crap
# and we have time to audit the entire lib
# for all uses of `detail::swallow`...
#target_compile_options(${test_target_name}
# PRIVATE -Wcomma)
endif()
endif()
if (MSVC)

View File

@ -47,10 +47,18 @@ function(CREATE_TEST test_target_name test_name target_sol)
endif()
else()
target_compile_options(${test_target_name}
PRIVATE -std=c++1z
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
-Wno-noexcept-type -pthread
-Wno-unknown-warning -Wno-unknown-warning-option)
PRIVATE -std=c++1z -pthread
-Wno-unknown-warning -Wno-unknown-warning-option
-Wall -Wpedantic -Werror -pedantic -pedantic-errors
-Wno-noexcept-type)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# For another day, when C++ is not so crap
# and we have time to audit the entire lib
# for all uses of `detail::swallow`...
#target_compile_options(${test_target_name}
# PRIVATE -Wcomma)
endif()
if (IS_X86)
if(MINGW)

View File

@ -704,11 +704,11 @@ TEST_CASE("object/base_of_things", "make sure that object is the base of things
lua["ud"] = base1{};
lua["f1"] = [](sol::stack_object o) -> sol::stack_object { return o; };
lua["f2"] = [](sol::stack_table o) -> sol::stack_object { return o; };
lua["f3"] = [](sol::stack_thread o) -> sol::stack_object { return o; };
lua["f4"] = [](sol::stack_unsafe_function o) -> sol::stack_object { return o; };
lua["f5"] = [](sol::stack_protected_function o) -> sol::stack_object { return o; };
lua["f6"] = [](sol::stack_userdata o) -> sol::stack_object { return o; };
lua["f2"] = [](sol::stack_table o) -> sol::stack_object { return std::move(o); };
lua["f3"] = [](sol::stack_thread o) -> sol::stack_object { return std::move(o); };
lua["f4"] = [](sol::stack_unsafe_function o) -> sol::stack_object { return std::move(o); };
lua["f5"] = [](sol::stack_protected_function o) -> sol::stack_object { return std::move(o); };
lua["f6"] = [](sol::stack_userdata o) -> sol::stack_object { return std::move(o); };
auto result1 = lua.safe_script("f1(2)", sol::script_pass_on_error);
REQUIRE(result1.valid());
auto result2 = lua.safe_script("f2({})", sol::script_pass_on_error);

View File

@ -131,6 +131,8 @@ public:
class abstract_A {
public:
virtual void a() = 0;
virtual ~abstract_A() {
}
};
class abstract_B : public abstract_A {

View File

@ -487,6 +487,7 @@ TEST_CASE("containers/pairs", "test how well pairs work with the underlying syst
TEST_CASE("containers/pointer types", "check that containers with unique usertypes and pointers or something") {
struct base_t {
virtual int get() const = 0;
virtual ~base_t(){}
};
struct derived_1_t : base_t {

View File

@ -480,7 +480,7 @@ end
// Resume from lua via thread and coroutine
sol::thread runner_thread = lua["loop_th"];
sol::state_view runner_thread_state = runner_thread.state();
auto test_resume = [&runner_thread, &runner_thread_state]() {
auto test_resume = [&runner_thread_state]() {
sol::coroutine cr = runner_thread_state["loop"];
sol::stack::push(runner_thread_state, 50);
sol::stack::push(runner_thread_state, 25);

View File

@ -534,6 +534,9 @@ TEST_CASE("functions/all kinds", "Register all kinds of functions, make sure the
static std::tuple<int, int> x_bark(int num_value, test_1* a) {
return std::tuple<int, int>(num_value * 2, a->a);
}
virtual ~test_1() {
}
};
struct test_2 {

View File

@ -26,6 +26,7 @@
#include <catch.hpp>
#include <vector>
#include <map>
#include <thread>
#include <mutex>
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
@ -81,8 +82,8 @@ TEST_CASE("lua_value/nested", "make nested values can be put in lua_value proper
sol::state lua;
sol::lua_value lv_mixed_table(lua, { 1, int_entry(2), 3, int_entry(4), 5 });
sol::lua_value lv_mixed_nested_table(lua, { 1, int_entry(2), 3, int_entry(4), { 5, 6, int_entry(7), "8" } });
sol::lua_value lv_mixed_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), 5 });
sol::lua_value lv_mixed_nested_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), sol::array_value{ 5, 6, int_entry(7), "8" } });
REQUIRE(lv_mixed_table.is<sol::table>());
REQUIRE(lv_mixed_nested_table.is<sol::table>());
@ -96,13 +97,13 @@ TEST_CASE("lua_value/nested", "make nested values can be put in lua_value proper
SECTION("type check (object)") {
sol::object obj_mixed_table(lv_mixed_table.value());
sol::object obj_mixed_nested_table(lv_mixed_nested_table.value());
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
@ -118,7 +119,79 @@ TEST_CASE("lua_value/nested", "make nested values can be put in lua_value proper
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
SECTION("pushing/popping (object)") {
lua["obj_mixed_table"] = lv_mixed_table;
lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
sol::object obj_mixed_table = lua["obj_mixed_table"];
sol::object obj_mixed_nested_table = lua["obj_mixed_nested_table"];
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
#else
REQUIRE(true);
#endif // C++17
}
TEST_CASE("lua_value/nested key value", "make nested values (key value) can be put in lua_value properly") {
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
using mixed_table_entry = std::variant<int, int_entry, std::string>;
using nested_entry = std::variant<int, int_entry, std::string, std::vector<mixed_table_entry>>;
const std::vector<std::variant<int, int_entry>> mixed_table_truth = { 1, int_entry(2), 3, int_entry(4), 5 };
const std::vector<nested_entry> mixed_nested_table_truth = { 1, int_entry(2), 3, int_entry(4), std::vector<mixed_table_entry>{ 5, 6, int_entry(7), "8" } };
sol::state lua;
sol::lua_value lv_mixed_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), 5 });
sol::lua_value lv_mixed_nested_table(lua, sol::array_value{ 1, int_entry(2), 3, int_entry(4), sol::array_value{ 5, 6, int_entry(7), "8" } });
REQUIRE(lv_mixed_table.is<sol::table>());
REQUIRE(lv_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value_lv = lv_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value_lv = lv_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value_lv);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value_lv);
SECTION("type check (object)") {
sol::object obj_mixed_table(lv_mixed_table.value());
sol::object obj_mixed_nested_table(lv_mixed_nested_table.value());
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
SECTION("pushing/popping") {
lua["obj_mixed_table"] = lv_mixed_table;
lua["obj_mixed_nested_table"] = lv_mixed_nested_table;
sol::lua_value obj_mixed_table = lua["obj_mixed_table"];
sol::lua_value obj_mixed_nested_table = lua["obj_mixed_nested_table"];
REQUIRE(obj_mixed_table.is<sol::table>());
REQUIRE(obj_mixed_nested_table.is<sol::table>());
std::vector<std::variant<int, int_entry>> mixed_table_value = obj_mixed_table.as<std::vector<std::variant<int, int_entry>>>();
std::vector<nested_entry> mixed_nested_table_value = obj_mixed_nested_table.as<std::vector<nested_entry>>();
REQUIRE(mixed_table_truth == mixed_table_value);
REQUIRE(mixed_nested_table_truth == mixed_nested_table_value);
}
@ -148,6 +221,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
const int_entry userdata_truth = int_entry(3);
const std::vector<int> int_table_truth = { 1, 2, 3, 4, 5 };
const std::map<int, int> int_map_truth = { {1, 2}, {3, 4}, {5, 6} };
sol::lua_value lv_int(lua, 1);
sol::lua_value lv_double(lua, 2.0);
@ -157,6 +231,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
sol::lua_value lv_nil(lua, sol::lua_nil);
sol::lua_value lv_userdata(lua, int_entry(3));
sol::lua_value lv_int_table(lua, { 1, 2, 3, 4, 5 });
sol::lua_value lv_int_map(lua, { {1, 2}, {3, 4}, {5, 6} });
REQUIRE(lv_int.is<int>());
REQUIRE(lv_double.is<double>());
REQUIRE(lv_string.is<std::string>());
@ -166,6 +241,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
REQUIRE(lv_userdata.is<sol::userdata>());
REQUIRE(lv_userdata.is<int_entry>());
REQUIRE(lv_int_table.is<sol::table>());
REQUIRE(lv_int_map.is<sol::table>());
REQUIRE(lv_int.as<int>() == 1);
REQUIRE(lv_double.as<double>() == 2.0);
@ -178,6 +254,8 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
std::vector<int> int_table_value_lv = lv_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value_lv);
std::map<int, int> int_map_value_lv = lv_int_map.as<std::map<int, int>>();
REQUIRE(int_map_truth == int_map_value_lv);
SECTION("type check (object)") {
sol::object obj_int(lv_int.value());
@ -188,6 +266,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
sol::object obj_nil(lv_nil.value());
sol::object obj_userdata(lv_userdata.value());
sol::object obj_int_table(lv_int_table.value());
sol::object obj_int_map(lv_int_map.value());
REQUIRE(obj_int.is<int>());
REQUIRE(obj_double.is<double>());
@ -198,6 +277,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
REQUIRE(obj_userdata.is<sol::userdata>());
REQUIRE(obj_userdata.is<int_entry>());
REQUIRE(obj_int_table.is<sol::table>());
REQUIRE(obj_int_map.is<sol::table>());
REQUIRE(obj_int.as<int>() == 1);
REQUIRE(obj_double.as<double>() == 2.0);
@ -210,6 +290,8 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value);
std::map<int, int> int_map_value = obj_int_map.as<std::map<int, int>>();
REQUIRE(int_map_truth == int_map_value);
}
SECTION("push/popping") {
lua["obj_int"] = lv_int;
@ -220,6 +302,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
lua["obj_nil"] = lv_nil;
lua["obj_userdata"] = lv_userdata;
lua["obj_int_table"] = lv_int_table;
lua["obj_int_map"] = lv_int_map;
// these all actually invoke the constructor
// so do one .get<> explicitly to ensure it's
@ -233,6 +316,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
sol::lua_value obj_nil = lua["obj_nil"];
sol::lua_value obj_userdata = lua["obj_userdata"];
sol::lua_value obj_int_table = lua["obj_int_table"];
sol::lua_value obj_int_map = lua["obj_int_map"];
REQUIRE(obj_int.is<int>());
REQUIRE(obj_double.is<double>());
@ -241,6 +325,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
REQUIRE(obj_bool.is<bool>());
REQUIRE(obj_nil.is<sol::lua_nil_t>());
REQUIRE(obj_int_table.is<sol::table>());
REQUIRE(obj_int_map.is<sol::table>());
REQUIRE(obj_int.as<int>() == 1);
REQUIRE(obj_double.as<double>() == 2.0);
@ -252,6 +337,8 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value);
std::map<int, int> int_map_value = obj_int_map.as<std::map<int, int>>();
REQUIRE(int_map_truth == int_map_value);
}
SECTION("push/popping (object)") {
lua["obj_int"] = lv_int;
@ -262,6 +349,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
lua["obj_nil"] = lv_nil;
lua["obj_userdata"] = lv_userdata;
lua["obj_int_table"] = lv_int_table;
lua["obj_int_map"] = lv_int_map;
sol::object obj_int = lua["obj_int"];
sol::object obj_double = lua["obj_double"];
@ -271,6 +359,7 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
sol::object obj_nil = lua["obj_nil"];
sol::object obj_userdata = lua["obj_userdata"];
sol::object obj_int_table = lua["obj_int_table"];
sol::object obj_int_map = lua["obj_int_map"];
REQUIRE(obj_int.is<int>());
REQUIRE(obj_double.is<double>());
@ -293,6 +382,8 @@ TEST_CASE("lua_value/basic types", "make sure we can stick values and nested val
std::vector<int> int_table_value = obj_int_table.as<std::vector<int>>();
REQUIRE(int_table_truth == int_table_value);
std::map<int, int> int_map_value = obj_int_map.as<std::map<int, int>>();
REQUIRE(int_map_truth == int_map_value);
}
}

View File

@ -0,0 +1,74 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 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.
#include "sol_test.hpp"
#include <catch.hpp>
TEST_CASE("tables/clear", "clear method works and does not clobber stack") {
sol::state lua;
sol::stack_guard luasg(lua);
lua["t"] = sol::lua_value({ { "a", "b" }, { "c", "d" } });
sol::table t = lua["t"];
{
sol::stack_guard clearsg(lua);
t.clear();
}
REQUIRE(!t["a"].valid());
REQUIRE(!t["c"].valid());
}
TEST_CASE("tables/stack clear", "stack-based clear method works and does not clobber stack") {
sol::state lua;
SECTION("reference based") {
sol::stack_guard luasg(lua);
lua["t"] = sol::lua_value({ { "a", "b" }, { "c", "d" } });
sol::table t = lua["t"];
REQUIRE(t["a"] == std::string("b"));
REQUIRE(t["c"] == std::string("d"));
{
sol::stack_guard clearsg(lua);
sol::stack::clear(t);
}
REQUIRE(!t["a"].valid());
REQUIRE(!t["c"].valid());
}
SECTION("with index") {
sol::stack_guard luasg(lua);
lua["t"] = sol::lua_value({ { "a", "b" }, { "c", "d" } });
sol::table t = lua["t"];
REQUIRE(t["a"] == std::string("b"));
REQUIRE(t["c"] == std::string("d"));
{
sol::stack_guard ppclearsg(lua);
auto pp = sol::stack::push_pop(t);
int table_index = pp.index_of(t);
{
sol::stack_guard clearsg(lua);
sol::stack::clear(lua, table_index);
}
}
REQUIRE(!t["a"].valid());
REQUIRE(!t["c"].valid());
}
}

View File

@ -0,0 +1,147 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2019 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.
#include "sol_test.hpp"
#include <catch.hpp>
struct unregister_me {
double b = 5.5;
std::string f_val = "registered";
unregister_me() {
}
std::string f() {
return f_val;
}
};
TEST_CASE("usertypes/unregister", "make sure that a class can still be bound but that it becomes completely unregistered") {
const sol::string_view line1 = "assert(u:f() == 'registered')";
const sol::string_view line2 = "assert(urm.a() == 20)";
const sol::string_view line3 = "assert(u.a() == 20) assert(u:a() == 20)";
const sol::string_view line4 = "assert(u.b == 5.5)";
sol::state lua;
lua.open_libraries();
auto register_urm = [&lua, &line1, &line2, &line3, &line4]() {
lua.new_usertype<unregister_me>("urm", "f", &unregister_me::f, "a", []() { return 20; }, "b", &unregister_me::b);
{
sol::object urm_obj = lua["urm"];
REQUIRE(urm_obj.get_type() == sol::type::table);
REQUIRE(urm_obj.is<sol::table>());
REQUIRE(urm_obj.is<sol::metatable>());
REQUIRE(urm_obj.is<sol::usertype<unregister_me>>());
}
lua["urm_unregister"] = [](sol::this_state ts) {
sol::state_view current_lua = ts;
sol::usertype<unregister_me> urm = current_lua["urm"];
urm.unregister();
};
auto sresult0 = lua.safe_script("u = urm.new()", sol::script_pass_on_error);
REQUIRE(sresult0.valid());
auto sresult1 = lua.safe_script(line1, sol::script_pass_on_error);
REQUIRE(sresult1.valid());
auto sresult2 = lua.safe_script(line2, sol::script_pass_on_error);
REQUIRE(sresult2.valid());
auto sresult3 = lua.safe_script(line3, sol::script_pass_on_error);
REQUIRE(sresult3.valid());
auto sresult4 = lua.safe_script(line4, sol::script_pass_on_error);
REQUIRE(sresult4.valid());
unregister_me& u_orig = lua["u"];
REQUIRE(u_orig.b == 5.5);
REQUIRE(u_orig.f() == "registered");
};
SECTION("unregister C++") {
register_urm();
{
sol::usertype<unregister_me> urm = lua["urm"];
urm.unregister();
}
auto result0 = lua.safe_script("u_fail = urm.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result0.valid());
auto result1 = lua.safe_script(line1, sol::script_pass_on_error);
REQUIRE_FALSE(result1.valid());
auto result2 = lua.safe_script(line2, sol::script_pass_on_error);
REQUIRE_FALSE(result2.valid());
auto result3 = lua.safe_script(line3, sol::script_pass_on_error);
REQUIRE_FALSE(result3.valid());
auto result4 = lua.safe_script(line4, sol::script_pass_on_error);
REQUIRE_FALSE(result4.valid());
unregister_me& u = lua["u"];
REQUIRE(u.b == 5.5);
REQUIRE(u.f() == "registered");
}
SECTION("re-register") {
register_urm();
sol::protected_function urm_unregister_func = lua["urm_unregister"];
auto unregister_result = urm_unregister_func();
REQUIRE(unregister_result.valid());
auto result0 = lua.safe_script("u_fail2 = urm.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result0.valid());
auto result1 = lua.safe_script(line1, sol::script_pass_on_error);
REQUIRE_FALSE(result1.valid());
auto result2 = lua.safe_script(line2, sol::script_pass_on_error);
REQUIRE_FALSE(result2.valid());
auto result3 = lua.safe_script(line3, sol::script_pass_on_error);
REQUIRE_FALSE(result3.valid());
auto result4 = lua.safe_script(line4, sol::script_pass_on_error);
REQUIRE_FALSE(result4.valid());
unregister_me& u = lua["u"];
REQUIRE(u.b == 5.5);
REQUIRE(u.f() == "registered");
register_urm();
}
SECTION("unregister lua") {
register_urm();
auto unregister_result = lua.safe_script("urm_unregister()", sol::script_pass_on_error);
REQUIRE(unregister_result.valid());
auto result0 = lua.safe_script("u_fail2 = urm.new()", sol::script_pass_on_error);
REQUIRE_FALSE(result0.valid());
auto result1 = lua.safe_script(line1, sol::script_pass_on_error);
REQUIRE_FALSE(result1.valid());
auto result2 = lua.safe_script(line2, sol::script_pass_on_error);
REQUIRE_FALSE(result2.valid());
auto result3 = lua.safe_script(line3, sol::script_pass_on_error);
REQUIRE_FALSE(result3.valid());
auto result4 = lua.safe_script(line4, sol::script_pass_on_error);
REQUIRE_FALSE(result4.valid());
unregister_me& u = lua["u"];
REQUIRE(u.b == 5.5);
REQUIRE(u.f() == "registered");
}
}