From 377472a6dd2c9bdff4d5667f5789c49aee2abb4c Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 7 Oct 2016 14:43:09 +0200 Subject: [PATCH] Added sol2 header only library as future replacement for luabridge (nw) --- 3rdparty/sol2/.gitignore | 71 + 3rdparty/sol2/.gitmodules | 6 + 3rdparty/sol2/.travis.yml | 186 + 3rdparty/sol2/CONTRIBUTING.md | 58 + 3rdparty/sol2/Catch/.gitignore | 22 + 3rdparty/sol2/Catch/.travis.yml | 163 + 3rdparty/sol2/Catch/LICENSE_1_0.txt | 23 + 3rdparty/sol2/Catch/README.md | 22 + 3rdparty/sol2/Catch/catch-logo-small.png | Bin 0 -> 51470 bytes 3rdparty/sol2/Catch/docs/Readme.md | 20 + 3rdparty/sol2/Catch/docs/assertions.md | 82 + 3rdparty/sol2/Catch/docs/build-systems.md | 86 + 3rdparty/sol2/Catch/docs/command-line.md | 220 + 3rdparty/sol2/Catch/docs/configuration.md | 73 + 3rdparty/sol2/Catch/docs/contributing.md | 23 + 3rdparty/sol2/Catch/docs/logging.md | 52 + 3rdparty/sol2/Catch/docs/own-main.md | 68 + 3rdparty/sol2/Catch/docs/slow-compiles.md | 22 + .../Catch/docs/test-cases-and-sections.md | 86 + 3rdparty/sol2/Catch/docs/test-fixtures.md | 32 + 3rdparty/sol2/Catch/docs/tostring.md | 70 + 3rdparty/sol2/Catch/docs/tutorial.md | 249 + 3rdparty/sol2/Catch/docs/why-catch.md | 42 + .../sol2/Catch/projects/CMake/CMakeLists.txt | 48 + .../Catch/projects/SelfTest/ApproxTests.cpp | 112 + .../sol2/Catch/projects/SelfTest/BDDTests.cpp | 103 + .../Baselines/console.std.approved.txt | 835 ++ .../Baselines/console.sw.approved.txt | 9050 ++++++++++++ .../Baselines/console.swa4.approved.txt | 491 + .../SelfTest/Baselines/junit.sw.approved.txt | 684 + .../SelfTest/Baselines/xml.sw.approved.txt | 9511 ++++++++++++ .../Catch/projects/SelfTest/ClassTests.cpp | 57 + .../Catch/projects/SelfTest/CmdLineTests.cpp | 264 + .../projects/SelfTest/ConditionTests.cpp | 335 + .../Catch/projects/SelfTest/EnumToString.cpp | 76 + .../projects/SelfTest/ExceptionTests.cpp | 203 + .../projects/SelfTest/GeneratorTests.cpp | 42 + .../Catch/projects/SelfTest/MessageTests.cpp | 133 + .../Catch/projects/SelfTest/MiscTests.cpp | 480 + .../projects/SelfTest/PartTrackerTests.cpp | 328 + .../SelfTest/SurrogateCpps/catch_common.cpp | 3 + .../SurrogateCpps/catch_console_colour.cpp | 3 + .../SelfTest/SurrogateCpps/catch_debugger.cpp | 2 + .../catch_interfaces_capture.cpp | 3 + .../SurrogateCpps/catch_interfaces_config.cpp | 2 + .../catch_interfaces_exception.cpp | 2 + .../catch_interfaces_generators.cpp | 1 + .../catch_interfaces_registry_hub.cpp | 3 + .../catch_interfaces_reporter.cpp | 2 + .../SurrogateCpps/catch_interfaces_runner.cpp | 1 + .../catch_interfaces_testcase.cpp | 2 + .../SelfTest/SurrogateCpps/catch_message.cpp | 3 + .../SelfTest/SurrogateCpps/catch_option.cpp | 3 + .../SelfTest/SurrogateCpps/catch_ptr.cpp | 3 + .../SelfTest/SurrogateCpps/catch_stream.cpp | 3 + .../SurrogateCpps/catch_streambuf.cpp | 3 + .../SurrogateCpps/catch_test_spec.cpp | 3 + .../SurrogateCpps/catch_xmlwriter.cpp | 4 + .../Catch/projects/SelfTest/TagAliasTests.cpp | 41 + .../sol2/Catch/projects/SelfTest/TestMain.cpp | 461 + .../Catch/projects/SelfTest/ToStringPair.cpp | 47 + .../Catch/projects/SelfTest/ToStringTuple.cpp | 59 + .../projects/SelfTest/ToStringVector.cpp | 77 + .../Catch/projects/SelfTest/ToStringWhich.cpp | 68 + .../Catch/projects/SelfTest/TrickyTests.cpp | 401 + .../projects/SelfTest/VariadicMacrosTests.cpp | 31 + .../sol2/Catch/projects/SelfTest/makefile | 30 + .../VS2008/TestCatch/TestCatch/TestCatch.cpp | 8 + .../TestCatch/TestCatch/TestCatch.vcproj | 390 + .../CatchSelfTest.xcodeproj/project.pbxproj | 742 + .../contents.xcworkspacedata | 7 + .../CatchSelfTest/CatchSelfTest.1 | 79 + .../CatchSelfTest/catch_text.cpp | 3 + .../project.pbxproj | 258 + .../contents.xcworkspacedata | 7 + .../CatchSelfTestSingle/dummy.txt | 0 .../OCTest/OCTest.xcodeproj/project.pbxproj | 265 + .../contents.xcworkspacedata | 7 + .../XCode/OCTest/OCTest/CatchOCTestCase.h | 25 + .../XCode/OCTest/OCTest/CatchOCTestCase.mm | 83 + .../projects/XCode/OCTest/OCTest/Main.mm | 2 + .../projects/XCode/OCTest/OCTest/OCTest.1 | 79 + .../projects/XCode/OCTest/OCTest/OCTest.mm | 28 + .../projects/XCode/OCTest/OCTest/TestObj.h | 28 + .../projects/XCode/OCTest/OCTest/TestObj.m | 25 + .../iOSTest/iOSTest.xcodeproj/project.pbxproj | 299 + .../contents.xcworkspacedata | 7 + .../projects/XCode/iOSTest/iOSTest/OCTest.mm | 27 + .../projects/XCode/iOSTest/iOSTest/TestObj.h | 25 + .../projects/XCode/iOSTest/iOSTest/TestObj.m | 18 + .../iOSTest/en.lproj/InfoPlist.strings | 2 + .../XCode/iOSTest/iOSTest/iOSTest-Info.plist | 47 + .../XCode/iOSTest/iOSTest/iOSTest-Prefix.pch | 14 + .../internal/iTchRunnerAppDelegate.h | 114 + .../iTchRunner/internal/iTchRunnerMainView.h | 189 + .../iTchRunner/internal/iTchRunnerReporter.h | 115 + .../runners/iTchRunner/itChRunnerMain.mm | 27 + .../Catch/projects/runners/iTchRunner/readme | 6 + 3rdparty/sol2/Catch/scripts/approvalTests.py | 115 + 3rdparty/sol2/Catch/scripts/approve.py | 31 + 3rdparty/sol2/Catch/scripts/developBuild.py | 9 + .../Catch/scripts/fixTrailingWhitespace.py | 46 + .../Catch/scripts/generateSingleHeader.py | 103 + 3rdparty/sol2/Catch/scripts/majorRelease.py | 9 + 3rdparty/sol2/Catch/scripts/minorRelease.py | 9 + 3rdparty/sol2/Catch/scripts/patchRelease.py | 9 + 3rdparty/sol2/Catch/scripts/releaseCommon.py | 89 + 3rdparty/sol2/Catch/scripts/releaseNotes.py | 62 + 3rdparty/sol2/Catch/scripts/scriptCommon.py | 21 + 3rdparty/sol2/Catch/single_include/catch.hpp | 10359 +++++++++++++ 3rdparty/sol2/LICENSE.txt | 20 + 3rdparty/sol2/Optional/CMakeLists.txt | 11 + 3rdparty/sol2/Optional/LICENSE_1_0.txt | 23 + 3rdparty/sol2/Optional/README.md | 39 + 3rdparty/sol2/Optional/copyright.txt | 10 + 3rdparty/sol2/Optional/optional.hpp | 1064 ++ 3rdparty/sol2/Optional/test_optional.cpp | 1459 ++ 3rdparty/sol2/Optional/test_type_traits.cpp | 66 + 3rdparty/sol2/README.md | 75 + 3rdparty/sol2/bootstrap.py | 206 + 3rdparty/sol2/docs/Makefile | 216 + 3rdparty/sol2/docs/make.bat | 263 + 3rdparty/sol2/docs/source/api/api-top.rst | 46 + 3rdparty/sol2/docs/source/api/as_function.rst | 67 + 3rdparty/sol2/docs/source/api/as_table.rst | 24 + 3rdparty/sol2/docs/source/api/c_call.rst | 71 + .../sol2/docs/source/api/compatibility.rst | 16 + 3rdparty/sol2/docs/source/api/coroutine.rst | 109 + 3rdparty/sol2/docs/source/api/error.rst | 15 + 3rdparty/sol2/docs/source/api/function.rst | 89 + .../sol2/docs/source/api/make_reference.rst | 26 + .../sol2/docs/source/api/metatable_key.rst | 154 + 3rdparty/sol2/docs/source/api/object.rst | 70 + 3rdparty/sol2/docs/source/api/optional.rst | 6 + 3rdparty/sol2/docs/source/api/overload.rst | 89 + 3rdparty/sol2/docs/source/api/property.rst | 64 + 3rdparty/sol2/docs/source/api/protect.rst | 33 + .../docs/source/api/protected_function.rst | 185 + 3rdparty/sol2/docs/source/api/proxy.rst | 201 + 3rdparty/sol2/docs/source/api/readonly.rst | 11 + 3rdparty/sol2/docs/source/api/reference.rst | 75 + 3rdparty/sol2/docs/source/api/resolve.rst | 39 + .../sol2/docs/source/api/simple_usertype.rst | 16 + 3rdparty/sol2/docs/source/api/stack.rst | 199 + .../sol2/docs/source/api/stack_reference.rst | 8 + 3rdparty/sol2/docs/source/api/state.rst | 121 + 3rdparty/sol2/docs/source/api/table.rst | 208 + 3rdparty/sol2/docs/source/api/this_state.rst | 31 + 3rdparty/sol2/docs/source/api/thread.rst | 52 + 3rdparty/sol2/docs/source/api/tie.rst | 26 + 3rdparty/sol2/docs/source/api/types.rst | 207 + .../source/api/unique_usertype_traits.rst | 44 + 3rdparty/sol2/docs/source/api/user.rst | 19 + 3rdparty/sol2/docs/source/api/userdata.rst | 13 + 3rdparty/sol2/docs/source/api/usertype.rst | 329 + .../sol2/docs/source/api/usertype_memory.rst | 47 + 3rdparty/sol2/docs/source/api/var.rst | 49 + .../sol2/docs/source/api/variadic_args.rst | 49 + 3rdparty/sol2/docs/source/benchmarks.rst | 94 + 3rdparty/sol2/docs/source/cmake.rst | 54 + 3rdparty/sol2/docs/source/codecvt.rst | 8 + 3rdparty/sol2/docs/source/conf.py | 291 + .../sol2/docs/source/eevee_code_after.jpg | Bin 0 -> 9593 bytes .../sol2/docs/source/eevee_code_before.jpg | Bin 0 -> 59507 bytes 3rdparty/sol2/docs/source/exceptions.rst | 51 + 3rdparty/sol2/docs/source/features.rst | 258 + 3rdparty/sol2/docs/source/index.rst | 123 + 3rdparty/sol2/docs/source/licenses.rst | 47 + 3rdparty/sol2/docs/source/mentions.rst | 50 + 3rdparty/sol2/docs/source/origin.rst | 28 + 3rdparty/sol2/docs/source/performance.rst | 15 + 3rdparty/sol2/docs/source/rtti.rst | 14 + 3rdparty/sol2/docs/source/safety.rst | 22 + 3rdparty/sol2/docs/source/sol.png | Bin 0 -> 14482 bytes 3rdparty/sol2/docs/source/sol.psd | Bin 0 -> 121930 bytes .../docs/source/tutorial/all-the-things.rst | 606 + .../docs/source/tutorial/customization.rst | 114 + .../sol2/docs/source/tutorial/cxx-in-lua.rst | 138 + .../sol2/docs/source/tutorial/existing.rst | 27 + .../sol2/docs/source/tutorial/functions.rst | 341 + .../docs/source/tutorial/getting-started.rst | 84 + .../sol2/docs/source/tutorial/ownership.rst | 94 + .../docs/source/tutorial/tutorial-top.rst | 21 + .../sol2/docs/source/tutorial/variables.rst | 202 + 3rdparty/sol2/examples/any_return.cpp | 46 + 3rdparty/sol2/examples/basic.cpp | 19 + 3rdparty/sol2/examples/config.cpp | 39 + 3rdparty/sol2/examples/config.lua | 3 + 3rdparty/sol2/examples/customization.cpp | 91 + 3rdparty/sol2/examples/functions.cpp | 110 + 3rdparty/sol2/examples/namespacing.cpp | 33 + 3rdparty/sol2/examples/player_script.lua | 29 + .../sol2/examples/protected_functions.cpp | 47 + 3rdparty/sol2/examples/require.cpp | 47 + 3rdparty/sol2/examples/self_call.cpp | 35 + 3rdparty/sol2/examples/static_variables.cpp | 61 + 3rdparty/sol2/examples/tables.cpp | 59 + 3rdparty/sol2/examples/usertype.cpp | 109 + 3rdparty/sol2/examples/usertype_advanced.cpp | 121 + .../sol2/examples/usertype_initializers.cpp | 67 + 3rdparty/sol2/examples/usertype_simple.cpp | 95 + .../examples/usertype_special_functions.cpp | 70 + 3rdparty/sol2/examples/usertype_var.cpp | 45 + 3rdparty/sol2/examples/variables.cpp | 37 + 3rdparty/sol2/examples/variadic_args.cpp | 40 + 3rdparty/sol2/install.deps.sh | 96 + 3rdparty/sol2/ninja_syntax.py | 156 + 3rdparty/sol2/single.py | 165 + 3rdparty/sol2/single/sol/sol.hpp | 12323 ++++++++++++++++ 3rdparty/sol2/sol.hpp | 50 + 3rdparty/sol2/sol/bind_traits.hpp | 243 + 3rdparty/sol2/sol/call.hpp | 573 + 3rdparty/sol2/sol/compatibility.hpp | 47 + 3rdparty/sol2/sol/compatibility/5.0.0.h | 44 + 3rdparty/sol2/sol/compatibility/5.1.0.h | 175 + 3rdparty/sol2/sol/compatibility/5.x.x.h | 57 + 3rdparty/sol2/sol/compatibility/5.x.x.inl | 707 + 3rdparty/sol2/sol/compatibility/version.hpp | 121 + .../sol2/sol/container_usertype_metatable.hpp | 412 + 3rdparty/sol2/sol/coroutine.hpp | 119 + 3rdparty/sol2/sol/debug.hpp | 54 + 3rdparty/sol2/sol/demangle.hpp | 158 + 3rdparty/sol2/sol/deprecate.hpp | 44 + 3rdparty/sol2/sol/error.hpp | 55 + 3rdparty/sol2/sol/function.hpp | 151 + 3rdparty/sol2/sol/function_result.hpp | 88 + 3rdparty/sol2/sol/function_types.hpp | 342 + 3rdparty/sol2/sol/function_types_core.hpp | 39 + .../sol2/sol/function_types_overloaded.hpp | 59 + 3rdparty/sol2/sol/function_types_stateful.hpp | 103 + .../sol2/sol/function_types_stateless.hpp | 163 + .../sol2/sol/function_types_templated.hpp | 132 + 3rdparty/sol2/sol/in_place.hpp | 50 + 3rdparty/sol2/sol/inheritance.hpp | 117 + 3rdparty/sol2/sol/load_result.hpp | 139 + 3rdparty/sol2/sol/object.hpp | 152 + 3rdparty/sol2/sol/optional.hpp | 43 + 3rdparty/sol2/sol/overload.hpp | 45 + 3rdparty/sol2/sol/property.hpp | 105 + 3rdparty/sol2/sol/protect.hpp | 51 + 3rdparty/sol2/sol/protected_function.hpp | 190 + .../sol2/sol/protected_function_result.hpp | 130 + 3rdparty/sol2/sol/proxy.hpp | 175 + 3rdparty/sol2/sol/proxy_base.hpp | 51 + 3rdparty/sol2/sol/raii.hpp | 132 + 3rdparty/sol2/sol/reference.hpp | 174 + 3rdparty/sol2/sol/resolve.hpp | 96 + .../sol2/sol/simple_usertype_metatable.hpp | 494 + 3rdparty/sol2/sol/stack.hpp | 226 + 3rdparty/sol2/sol/stack_check.hpp | 350 + 3rdparty/sol2/sol/stack_check_get.hpp | 114 + 3rdparty/sol2/sol/stack_core.hpp | 410 + 3rdparty/sol2/sol/stack_field.hpp | 261 + 3rdparty/sol2/sol/stack_get.hpp | 537 + 3rdparty/sol2/sol/stack_guard.hpp | 63 + 3rdparty/sol2/sol/stack_pop.hpp | 49 + 3rdparty/sol2/sol/stack_probe.hpp | 87 + 3rdparty/sol2/sol/stack_proxy.hpp | 124 + 3rdparty/sol2/sol/stack_push.hpp | 693 + 3rdparty/sol2/sol/stack_reference.hpp | 84 + 3rdparty/sol2/sol/state.hpp | 59 + 3rdparty/sol2/sol/state_view.hpp | 460 + 3rdparty/sol2/sol/string_shim.hpp | 64 + 3rdparty/sol2/sol/table.hpp | 31 + 3rdparty/sol2/sol/table_core.hpp | 462 + 3rdparty/sol2/sol/table_iterator.hpp | 120 + 3rdparty/sol2/sol/thread.hpp | 77 + 3rdparty/sol2/sol/tie.hpp | 101 + 3rdparty/sol2/sol/traits.hpp | 425 + 3rdparty/sol2/sol/tuple.hpp | 80 + 3rdparty/sol2/sol/types.hpp | 756 + 3rdparty/sol2/sol/userdata.hpp | 82 + 3rdparty/sol2/sol/usertype.hpp | 97 + 3rdparty/sol2/sol/usertype_metatable.hpp | 583 + 3rdparty/sol2/sol/usertype_traits.hpp | 55 + 3rdparty/sol2/sol/variadic_args.hpp | 236 + 3rdparty/sol2/sol/wrapper.hpp | 233 + 3rdparty/sol2/test_containers.cpp | 310 + 3rdparty/sol2/test_coroutines.cpp | 64 + 3rdparty/sol2/test_customizations.cpp | 86 + 3rdparty/sol2/test_functions.cpp | 949 ++ 3rdparty/sol2/test_inheritance.cpp | 247 + 3rdparty/sol2/test_operators.cpp | 83 + 3rdparty/sol2/test_overflow.cpp | 47 + 3rdparty/sol2/test_simple_usertypes.cpp | 459 + 3rdparty/sol2/test_stack_guard.hpp | 11 + 3rdparty/sol2/test_strings.cpp | 122 + 3rdparty/sol2/test_tables.cpp | 548 + 3rdparty/sol2/test_usertypes.cpp | 1425 ++ 3rdparty/sol2/tests.cpp | 680 + 290 files changed, 80392 insertions(+) create mode 100644 3rdparty/sol2/.gitignore create mode 100644 3rdparty/sol2/.gitmodules create mode 100644 3rdparty/sol2/.travis.yml create mode 100644 3rdparty/sol2/CONTRIBUTING.md create mode 100644 3rdparty/sol2/Catch/.gitignore create mode 100644 3rdparty/sol2/Catch/.travis.yml create mode 100644 3rdparty/sol2/Catch/LICENSE_1_0.txt create mode 100644 3rdparty/sol2/Catch/README.md create mode 100644 3rdparty/sol2/Catch/catch-logo-small.png create mode 100644 3rdparty/sol2/Catch/docs/Readme.md create mode 100644 3rdparty/sol2/Catch/docs/assertions.md create mode 100644 3rdparty/sol2/Catch/docs/build-systems.md create mode 100644 3rdparty/sol2/Catch/docs/command-line.md create mode 100644 3rdparty/sol2/Catch/docs/configuration.md create mode 100644 3rdparty/sol2/Catch/docs/contributing.md create mode 100644 3rdparty/sol2/Catch/docs/logging.md create mode 100644 3rdparty/sol2/Catch/docs/own-main.md create mode 100644 3rdparty/sol2/Catch/docs/slow-compiles.md create mode 100644 3rdparty/sol2/Catch/docs/test-cases-and-sections.md create mode 100644 3rdparty/sol2/Catch/docs/test-fixtures.md create mode 100644 3rdparty/sol2/Catch/docs/tostring.md create mode 100644 3rdparty/sol2/Catch/docs/tutorial.md create mode 100644 3rdparty/sol2/Catch/docs/why-catch.md create mode 100644 3rdparty/sol2/Catch/projects/CMake/CMakeLists.txt create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ApproxTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/BDDTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.std.approved.txt create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.sw.approved.txt create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ClassTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/CmdLineTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ConditionTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/EnumToString.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ExceptionTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/GeneratorTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/MessageTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/MiscTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/PartTrackerTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/TagAliasTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/TestMain.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ToStringPair.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ToStringTuple.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ToStringVector.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/ToStringWhich.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/TrickyTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/VariadicMacrosTests.cpp create mode 100644 3rdparty/sol2/Catch/projects/SelfTest/makefile create mode 100644 3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp create mode 100644 3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle/dummy.txt create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/Main.mm create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.1 create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.mm create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.h create mode 100644 3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.m create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist create mode 100644 3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch create mode 100644 3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h create mode 100644 3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h create mode 100644 3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h create mode 100644 3rdparty/sol2/Catch/projects/runners/iTchRunner/itChRunnerMain.mm create mode 100644 3rdparty/sol2/Catch/projects/runners/iTchRunner/readme create mode 100644 3rdparty/sol2/Catch/scripts/approvalTests.py create mode 100644 3rdparty/sol2/Catch/scripts/approve.py create mode 100644 3rdparty/sol2/Catch/scripts/developBuild.py create mode 100644 3rdparty/sol2/Catch/scripts/fixTrailingWhitespace.py create mode 100644 3rdparty/sol2/Catch/scripts/generateSingleHeader.py create mode 100644 3rdparty/sol2/Catch/scripts/majorRelease.py create mode 100644 3rdparty/sol2/Catch/scripts/minorRelease.py create mode 100644 3rdparty/sol2/Catch/scripts/patchRelease.py create mode 100644 3rdparty/sol2/Catch/scripts/releaseCommon.py create mode 100644 3rdparty/sol2/Catch/scripts/releaseNotes.py create mode 100644 3rdparty/sol2/Catch/scripts/scriptCommon.py create mode 100644 3rdparty/sol2/Catch/single_include/catch.hpp create mode 100644 3rdparty/sol2/LICENSE.txt create mode 100644 3rdparty/sol2/Optional/CMakeLists.txt create mode 100644 3rdparty/sol2/Optional/LICENSE_1_0.txt create mode 100644 3rdparty/sol2/Optional/README.md create mode 100644 3rdparty/sol2/Optional/copyright.txt create mode 100644 3rdparty/sol2/Optional/optional.hpp create mode 100644 3rdparty/sol2/Optional/test_optional.cpp create mode 100644 3rdparty/sol2/Optional/test_type_traits.cpp create mode 100644 3rdparty/sol2/README.md create mode 100644 3rdparty/sol2/bootstrap.py create mode 100644 3rdparty/sol2/docs/Makefile create mode 100644 3rdparty/sol2/docs/make.bat create mode 100644 3rdparty/sol2/docs/source/api/api-top.rst create mode 100644 3rdparty/sol2/docs/source/api/as_function.rst create mode 100644 3rdparty/sol2/docs/source/api/as_table.rst create mode 100644 3rdparty/sol2/docs/source/api/c_call.rst create mode 100644 3rdparty/sol2/docs/source/api/compatibility.rst create mode 100644 3rdparty/sol2/docs/source/api/coroutine.rst create mode 100644 3rdparty/sol2/docs/source/api/error.rst create mode 100644 3rdparty/sol2/docs/source/api/function.rst create mode 100644 3rdparty/sol2/docs/source/api/make_reference.rst create mode 100644 3rdparty/sol2/docs/source/api/metatable_key.rst create mode 100644 3rdparty/sol2/docs/source/api/object.rst create mode 100644 3rdparty/sol2/docs/source/api/optional.rst create mode 100644 3rdparty/sol2/docs/source/api/overload.rst create mode 100644 3rdparty/sol2/docs/source/api/property.rst create mode 100644 3rdparty/sol2/docs/source/api/protect.rst create mode 100644 3rdparty/sol2/docs/source/api/protected_function.rst create mode 100644 3rdparty/sol2/docs/source/api/proxy.rst create mode 100644 3rdparty/sol2/docs/source/api/readonly.rst create mode 100644 3rdparty/sol2/docs/source/api/reference.rst create mode 100644 3rdparty/sol2/docs/source/api/resolve.rst create mode 100644 3rdparty/sol2/docs/source/api/simple_usertype.rst create mode 100644 3rdparty/sol2/docs/source/api/stack.rst create mode 100644 3rdparty/sol2/docs/source/api/stack_reference.rst create mode 100644 3rdparty/sol2/docs/source/api/state.rst create mode 100644 3rdparty/sol2/docs/source/api/table.rst create mode 100644 3rdparty/sol2/docs/source/api/this_state.rst create mode 100644 3rdparty/sol2/docs/source/api/thread.rst create mode 100644 3rdparty/sol2/docs/source/api/tie.rst create mode 100644 3rdparty/sol2/docs/source/api/types.rst create mode 100644 3rdparty/sol2/docs/source/api/unique_usertype_traits.rst create mode 100644 3rdparty/sol2/docs/source/api/user.rst create mode 100644 3rdparty/sol2/docs/source/api/userdata.rst create mode 100644 3rdparty/sol2/docs/source/api/usertype.rst create mode 100644 3rdparty/sol2/docs/source/api/usertype_memory.rst create mode 100644 3rdparty/sol2/docs/source/api/var.rst create mode 100644 3rdparty/sol2/docs/source/api/variadic_args.rst create mode 100644 3rdparty/sol2/docs/source/benchmarks.rst create mode 100644 3rdparty/sol2/docs/source/cmake.rst create mode 100644 3rdparty/sol2/docs/source/codecvt.rst create mode 100644 3rdparty/sol2/docs/source/conf.py create mode 100644 3rdparty/sol2/docs/source/eevee_code_after.jpg create mode 100644 3rdparty/sol2/docs/source/eevee_code_before.jpg create mode 100644 3rdparty/sol2/docs/source/exceptions.rst create mode 100644 3rdparty/sol2/docs/source/features.rst create mode 100644 3rdparty/sol2/docs/source/index.rst create mode 100644 3rdparty/sol2/docs/source/licenses.rst create mode 100644 3rdparty/sol2/docs/source/mentions.rst create mode 100644 3rdparty/sol2/docs/source/origin.rst create mode 100644 3rdparty/sol2/docs/source/performance.rst create mode 100644 3rdparty/sol2/docs/source/rtti.rst create mode 100644 3rdparty/sol2/docs/source/safety.rst create mode 100644 3rdparty/sol2/docs/source/sol.png create mode 100644 3rdparty/sol2/docs/source/sol.psd create mode 100644 3rdparty/sol2/docs/source/tutorial/all-the-things.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/customization.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/existing.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/functions.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/getting-started.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/ownership.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/tutorial-top.rst create mode 100644 3rdparty/sol2/docs/source/tutorial/variables.rst create mode 100644 3rdparty/sol2/examples/any_return.cpp create mode 100644 3rdparty/sol2/examples/basic.cpp create mode 100644 3rdparty/sol2/examples/config.cpp create mode 100644 3rdparty/sol2/examples/config.lua create mode 100644 3rdparty/sol2/examples/customization.cpp create mode 100644 3rdparty/sol2/examples/functions.cpp create mode 100644 3rdparty/sol2/examples/namespacing.cpp create mode 100644 3rdparty/sol2/examples/player_script.lua create mode 100644 3rdparty/sol2/examples/protected_functions.cpp create mode 100644 3rdparty/sol2/examples/require.cpp create mode 100644 3rdparty/sol2/examples/self_call.cpp create mode 100644 3rdparty/sol2/examples/static_variables.cpp create mode 100644 3rdparty/sol2/examples/tables.cpp create mode 100644 3rdparty/sol2/examples/usertype.cpp create mode 100644 3rdparty/sol2/examples/usertype_advanced.cpp create mode 100644 3rdparty/sol2/examples/usertype_initializers.cpp create mode 100644 3rdparty/sol2/examples/usertype_simple.cpp create mode 100644 3rdparty/sol2/examples/usertype_special_functions.cpp create mode 100644 3rdparty/sol2/examples/usertype_var.cpp create mode 100644 3rdparty/sol2/examples/variables.cpp create mode 100644 3rdparty/sol2/examples/variadic_args.cpp create mode 100644 3rdparty/sol2/install.deps.sh create mode 100644 3rdparty/sol2/ninja_syntax.py create mode 100644 3rdparty/sol2/single.py create mode 100644 3rdparty/sol2/single/sol/sol.hpp create mode 100644 3rdparty/sol2/sol.hpp create mode 100644 3rdparty/sol2/sol/bind_traits.hpp create mode 100644 3rdparty/sol2/sol/call.hpp create mode 100644 3rdparty/sol2/sol/compatibility.hpp create mode 100644 3rdparty/sol2/sol/compatibility/5.0.0.h create mode 100644 3rdparty/sol2/sol/compatibility/5.1.0.h create mode 100644 3rdparty/sol2/sol/compatibility/5.x.x.h create mode 100644 3rdparty/sol2/sol/compatibility/5.x.x.inl create mode 100644 3rdparty/sol2/sol/compatibility/version.hpp create mode 100644 3rdparty/sol2/sol/container_usertype_metatable.hpp create mode 100644 3rdparty/sol2/sol/coroutine.hpp create mode 100644 3rdparty/sol2/sol/debug.hpp create mode 100644 3rdparty/sol2/sol/demangle.hpp create mode 100644 3rdparty/sol2/sol/deprecate.hpp create mode 100644 3rdparty/sol2/sol/error.hpp create mode 100644 3rdparty/sol2/sol/function.hpp create mode 100644 3rdparty/sol2/sol/function_result.hpp create mode 100644 3rdparty/sol2/sol/function_types.hpp create mode 100644 3rdparty/sol2/sol/function_types_core.hpp create mode 100644 3rdparty/sol2/sol/function_types_overloaded.hpp create mode 100644 3rdparty/sol2/sol/function_types_stateful.hpp create mode 100644 3rdparty/sol2/sol/function_types_stateless.hpp create mode 100644 3rdparty/sol2/sol/function_types_templated.hpp create mode 100644 3rdparty/sol2/sol/in_place.hpp create mode 100644 3rdparty/sol2/sol/inheritance.hpp create mode 100644 3rdparty/sol2/sol/load_result.hpp create mode 100644 3rdparty/sol2/sol/object.hpp create mode 100644 3rdparty/sol2/sol/optional.hpp create mode 100644 3rdparty/sol2/sol/overload.hpp create mode 100644 3rdparty/sol2/sol/property.hpp create mode 100644 3rdparty/sol2/sol/protect.hpp create mode 100644 3rdparty/sol2/sol/protected_function.hpp create mode 100644 3rdparty/sol2/sol/protected_function_result.hpp create mode 100644 3rdparty/sol2/sol/proxy.hpp create mode 100644 3rdparty/sol2/sol/proxy_base.hpp create mode 100644 3rdparty/sol2/sol/raii.hpp create mode 100644 3rdparty/sol2/sol/reference.hpp create mode 100644 3rdparty/sol2/sol/resolve.hpp create mode 100644 3rdparty/sol2/sol/simple_usertype_metatable.hpp create mode 100644 3rdparty/sol2/sol/stack.hpp create mode 100644 3rdparty/sol2/sol/stack_check.hpp create mode 100644 3rdparty/sol2/sol/stack_check_get.hpp create mode 100644 3rdparty/sol2/sol/stack_core.hpp create mode 100644 3rdparty/sol2/sol/stack_field.hpp create mode 100644 3rdparty/sol2/sol/stack_get.hpp create mode 100644 3rdparty/sol2/sol/stack_guard.hpp create mode 100644 3rdparty/sol2/sol/stack_pop.hpp create mode 100644 3rdparty/sol2/sol/stack_probe.hpp create mode 100644 3rdparty/sol2/sol/stack_proxy.hpp create mode 100644 3rdparty/sol2/sol/stack_push.hpp create mode 100644 3rdparty/sol2/sol/stack_reference.hpp create mode 100644 3rdparty/sol2/sol/state.hpp create mode 100644 3rdparty/sol2/sol/state_view.hpp create mode 100644 3rdparty/sol2/sol/string_shim.hpp create mode 100644 3rdparty/sol2/sol/table.hpp create mode 100644 3rdparty/sol2/sol/table_core.hpp create mode 100644 3rdparty/sol2/sol/table_iterator.hpp create mode 100644 3rdparty/sol2/sol/thread.hpp create mode 100644 3rdparty/sol2/sol/tie.hpp create mode 100644 3rdparty/sol2/sol/traits.hpp create mode 100644 3rdparty/sol2/sol/tuple.hpp create mode 100644 3rdparty/sol2/sol/types.hpp create mode 100644 3rdparty/sol2/sol/userdata.hpp create mode 100644 3rdparty/sol2/sol/usertype.hpp create mode 100644 3rdparty/sol2/sol/usertype_metatable.hpp create mode 100644 3rdparty/sol2/sol/usertype_traits.hpp create mode 100644 3rdparty/sol2/sol/variadic_args.hpp create mode 100644 3rdparty/sol2/sol/wrapper.hpp create mode 100644 3rdparty/sol2/test_containers.cpp create mode 100644 3rdparty/sol2/test_coroutines.cpp create mode 100644 3rdparty/sol2/test_customizations.cpp create mode 100644 3rdparty/sol2/test_functions.cpp create mode 100644 3rdparty/sol2/test_inheritance.cpp create mode 100644 3rdparty/sol2/test_operators.cpp create mode 100644 3rdparty/sol2/test_overflow.cpp create mode 100644 3rdparty/sol2/test_simple_usertypes.cpp create mode 100644 3rdparty/sol2/test_stack_guard.hpp create mode 100644 3rdparty/sol2/test_strings.cpp create mode 100644 3rdparty/sol2/test_tables.cpp create mode 100644 3rdparty/sol2/test_usertypes.cpp create mode 100644 3rdparty/sol2/tests.cpp diff --git a/3rdparty/sol2/.gitignore b/3rdparty/sol2/.gitignore new file mode 100644 index 00000000000..242803c126c --- /dev/null +++ b/3rdparty/sol2/.gitignore @@ -0,0 +1,71 @@ +# Python (Bytecode) +*.pyc + +# ninja files +*.ninja + +# Visual Studio +*.props +*.user +.vs/ +Debug/ +Release/ +x64/ +*.vcxproj +*.vcxproj.filters +*.tlog +*.lastbuildstate +*.idb +*.sln +*.gitattributes + +# VSCode +.vscode/ + +# Compiler outputs +obj/* +bin/* + +# Dropbox interference +.dropbox* + +# QtCreator +*.creator.user.* +*.config +*.creator +*.files +*.includes + +# Scratchpad Files +main2.cpp +main.cpp + +# Local Lua Testbeds +lua-5.3.2/ +lua-5.3.1/ +lua-5.3.0/ +lua-5.2.4/ +lua-5.2.2/ +lua-5.2.3/ +lua-5.1.5/ +luajit-2.0.4/ +luajit-2.0.3/ +include/ +liblua.a +lib/liblua5.2.a + +# Windows Crap +desktop.ini +*.sublime-workspace +docs/build/ +*.sublime-project +m.lua +single/sol.hpp +*.db +lua53.dll +main.exe +main.o +lua-5.3.3/ +*.pdf +main.lua +LuaJIT-2.1.0/ diff --git a/3rdparty/sol2/.gitmodules b/3rdparty/sol2/.gitmodules new file mode 100644 index 00000000000..f6ae162a2f3 --- /dev/null +++ b/3rdparty/sol2/.gitmodules @@ -0,0 +1,6 @@ +[submodule "Catch"] + path = Catch + url = https://github.com/philsquared/Catch.git +[submodule "Optional"] + path = Optional + url = https://github.com/ThePhD/Optional.git diff --git a/3rdparty/sol2/.travis.yml b/3rdparty/sol2/.travis.yml new file mode 100644 index 00000000000..aa6677ef55f --- /dev/null +++ b/3rdparty/sol2/.travis.yml @@ -0,0 +1,186 @@ +language: cpp +sudo: required +dist: trusty + +git: + depth: 5 + +before_install: +- source ./install.deps.sh + +install: +- install_os_deps + +script: +- echo "Configuration info:" +- export_compiler_vars +- ninja --version +- ./bootstrap.py --ci && ninja + +notifications: + email: + on_success: change + on_failure: change + +matrix: + include: + - os: linux + env: COMPILER=g++-4.9 LUA_VERSION=lua52 + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - ninja-build + - liblua5.2-dev + + # gcc-5 + - os: linux + env: COMPILER=g++-4.9 LUA_VERSION=luajit51 + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - ninja-build + - libluajit-5.1-dev + + # gcc-5 + - os: linux + env: COMPILER=g++-5 LUA_VERSION=lua52 + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-5 + - g++-5 + - ninja-build + - liblua5.2-dev + + # gcc-5 + - os: linux + env: COMPILER=g++-5 LUA_VERSION=luajit51 + compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-5 + - g++-5 + - ninja-build + - libluajit-5.1-dev + + # clang + - os: linux + env: + - LLVM_VERSION=3.5.0 + - LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz + - COMPILER=clang++ + - CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1" + - CXXFLAGS=-lc++ + - PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH + - LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH + - LUA_VERSION=lua52 + before_install: + - wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH + - mkdir $HOME/clang-$LLVM_VERSION + - tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1 + - export PATH=$HOME/clang+llvm/bin:$PATH + - source ./install.deps.sh + compiler: clang + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - ninja-build + - liblua5.2-dev + + - os: linux + env: + - LLVM_VERSION=3.6.0 + - LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz + - COMPILER=clang++ + - CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1" + - CXXFLAGS=-lc++ + - PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH + - LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH + - LUA_VERSION=lua52 + before_install: + - wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH + - mkdir $HOME/clang-$LLVM_VERSION + - tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1 + - export PATH=$HOME/clang+llvm/bin:$PATH + - source ./install.deps.sh + compiler: clang + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - ninja-build + - liblua5.2-dev + + - os: linux + env: + - LLVM_VERSION=3.6.0 + - LLVM_ARCHIVE_PATH=$HOME/clang+llvm.tar.xz + - COMPILER=clang++ + - CPPFLAGS="-I $HOME/clang-$LLVM_VERSION/include/c++/v1" + - CXXFLAGS=-lc++ + - PATH=$HOME/clang-$LLVM_VERSION/bin:$PATH + - LD_LIBRARY_PATH=$HOME/clang-$LLVM_VERSION/lib:$LD_LIBRARY_PATH + - LUA_VERSION=luajit51 + before_install: + - wget http://llvm.org/releases/$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-linux-gnu-ubuntu-14.04.tar.xz -O $LLVM_ARCHIVE_PATH + - mkdir $HOME/clang-$LLVM_VERSION + - tar xf $LLVM_ARCHIVE_PATH -C $HOME/clang-$LLVM_VERSION --strip-components 1 + - export PATH=$HOME/clang+llvm/bin:$PATH + - source ./install.deps.sh + compiler: clang + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-4.9 + - g++-4.9 + - ninja-build + - libluajit-5.1-dev + + - os: osx + osx_image: xcode7 + compiler: gcc + env: COMPILER=g++-4.9 LUA_VERSION=lua53 + + - os: osx + osx_image: xcode7 + compiler: gcc + env: COMPILER=g++-5 LUA_VERSION=lua53 + + - os: osx + osx_image: xcode7 + compiler: gcc + env: COMPILER=g++-5 LUA_VERSION=luajit + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER=appleclang LUA_VERSION=lua53 + + allow_failures: + - os: osx + compiler: clang diff --git a/3rdparty/sol2/CONTRIBUTING.md b/3rdparty/sol2/CONTRIBUTING.md new file mode 100644 index 00000000000..e7a4147a648 --- /dev/null +++ b/3rdparty/sol2/CONTRIBUTING.md @@ -0,0 +1,58 @@ +## Contributing to Sol + +Looking to contribute to Sol? Well, first thing I want to mention is thank you! +Second of all, this is probably where you should look :) + +## Reporting Issues + +If you found a bug, please make sure to make an issue in the issue tracker. + +The guidelines for reporting a bug are relatively simple and are as follows: + +1. Produce a simple, short, compilable test case that reproduces your problem. +2. Make a descriptive title that summarises the bug as a whole. +3. Explain the bug in as much detail as you can in the body of the issue. + +If you have all of those requirements set, then your issue reporting is golden. + +## Submitting a pull request + +Submitting a pull request is fairly simple, just make sure it focuses on a single aspect and doesn't +manage to have scope creep and it's probably good to go. It would be incredibly lovely if the style is +consistent to those found in the repository. + +They are as follows (more will be added as they come up): + +- No spaces between parentheses. e.g. `f(g())` not `f ( g ( ) )`. +- Tabs for indentation, spaces for alignment. +- Bracing style is + +```cpp +if(my_bool) { + +} +else if(my_other_bool) { + +} +else { + +} +``` + +- Variable names follow those in the C++ standard, basically snake_case. +- Maximum column length is 125 +- Trailing return type will always be in the same line. Even if it goes off the column length. e.g. +`auto f() -> decltype(/* my long expression */) {` +- Since this is a header-only library, all free functions must be marked `inline`. +- Use braces in optional contexts like `if`, `for`, `else`, `while`, etc. e.g. + +```cpp +if(x > 12) { + return x * 2; +} +``` + +- Use `typename` instead of `class` for template parameters. e.g. `template`. + +If you don't meet all of these style guidelines, don't fret. I'll probably fix it. But please +do make an effort to actually meet them. Otherwise I'm more likely to reject the pull request. diff --git a/3rdparty/sol2/Catch/.gitignore b/3rdparty/sol2/Catch/.gitignore new file mode 100644 index 00000000000..3ca4b5c555c --- /dev/null +++ b/3rdparty/sol2/Catch/.gitignore @@ -0,0 +1,22 @@ +*.build +*.pbxuser +*.mode1v3 +*.ncb +*.suo +Debug +Release +*.user +*.xcuserstate +.DS_Store +xcuserdata +CatchSelfTest.xcscheme +Breakpoints.xcbkptlist +projects/VS2010/TestCatch/_UpgradeReport_Files/ +projects/VS2010/TestCatch/TestCatch/TestCatch.vcxproj.filters +projects/VisualStudio/TestCatch/UpgradeLog.XML +UpgradeLog.XML +Resources/DWARF +projects/XCode/iOSTest/Build +*.pyc +DerivedData +*.xccheckout diff --git a/3rdparty/sol2/Catch/.travis.yml b/3rdparty/sol2/Catch/.travis.yml new file mode 100644 index 00000000000..e63a76a36ef --- /dev/null +++ b/3rdparty/sol2/Catch/.travis.yml @@ -0,0 +1,163 @@ +language: cpp +sudo: false + +cache: + ccache: true + directories: + - $HOME/.ccache + +env: + global: + - USE_CCACHE=1 + - CCACHE_COMPRESS=1 + - CCACHE_MAXSIZE=200M + - CCACHE_CPP2=1 + + +matrix: + include: + + # 1/ Linux Clang Builds + - os: linux + compiler: clang + addons: &clang35 + apt: + sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.5'] + env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang35 + env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang36 + apt: + sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.6'] + env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang36 + env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang37 + apt: + sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.7'] + env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang37 + env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang38 + apt: + sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.8'] + env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang38 + env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Debug' + + + # 2/ Linux GCC Builds + - os: linux + compiler: gcc + addons: &gcc48 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.8'] + env: COMPILER='ccache g++-4.8' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc48 + env: COMPILER='ccache g++-4.8' BUILD_TYPE='Debug' + + + - os: linux + compiler: gcc + addons: &gcc49 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.9'] + env: COMPILER='ccache g++-4.9' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc49 + env: COMPILER='ccache g++-4.9' BUILD_TYPE='Debug' + + + - os: linux + compiler: gcc + addons: &gcc5 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-5'] + env: COMPILER='ccache g++-5' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc5 + env: COMPILER='ccache g++-5' BUILD_TYPE='Debug' + + + # 3/ OSX Clang Builds + - os: osx + osx_image: xcode6.4 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Debug' + + - os: osx + osx_image: xcode6.4 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Release' + + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Debug' + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Release' + + +install: + - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" + - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} + - | + if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then + CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz" + mkdir cmake && travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake + export PATH=${DEPS_DIR}/cmake/bin:${PATH} + elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then + brew install cmake ccache + fi + +before_script: + - export CXX=${COMPILER} + - cd ${TRAVIS_BUILD_DIR} + - cmake -Hprojects/CMake -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} + - cd Build + +script: + - make -j 2 + - ctest -V -j 2 diff --git a/3rdparty/sol2/Catch/LICENSE_1_0.txt b/3rdparty/sol2/Catch/LICENSE_1_0.txt new file mode 100644 index 00000000000..36b7cd93cdf --- /dev/null +++ b/3rdparty/sol2/Catch/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/sol2/Catch/README.md b/3rdparty/sol2/Catch/README.md new file mode 100644 index 00000000000..33d124135c9 --- /dev/null +++ b/3rdparty/sol2/Catch/README.md @@ -0,0 +1,22 @@ +![catch logo](catch-logo-small.png) + +*v1.3.4* + +Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) + +The latest, single header, version can be downloaded directly using this link + +## What's the Catch? + +Catch stands for C++ Automated Test Cases in Headers and is a multi-paradigm automated test framework for C++ and Objective-C (and, maybe, C). It is implemented entirely in a set of header files, but is packaged up as a single header for extra convenience. + +## How to use it +This documentation comprises these three parts: + +* [Why do we need yet another C++ Test Framework?](docs/why-catch.md) +* [Tutorial](docs/tutorial.md) - getting started +* [Reference section](docs/Readme.md) - all the details + +## More +* Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues) +* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) diff --git a/3rdparty/sol2/Catch/catch-logo-small.png b/3rdparty/sol2/Catch/catch-logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e74e8a27efefa4974928735be4bc94ae7fba89 GIT binary patch literal 51470 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 ` ...`
+ ` -h, -?, --help`
+ ` -l, --list-tests`
+ ` -t, --list-tags`
+ ` -s, --success`
+ ` -b, --break`
+ ` -e, --nothrow`
+ ` -i, --invisibles`
+ ` -o, --out`
+ ` -r, --reporter`
+ ` -n, --name`
+ ` -a, --abort`
+ ` -x, --abortx`
+ ` -w, --warn`
+ ` -d, --durations`
+ ` -f, --input-file`
+ +
+ + ` --list-test-names-only`
+ ` --list-reporters`
+ ` --order`
+ ` --rng-seed`
+ +
+ + + + +## Specifying which tests to run + +
<test-spec> ...
+ +Test cases, wildcarded test cases, tags and tag expressions are all passed directly as arguments. Tags are distinguished by being enclosed in square brackets. + +If no test specs are supplied then all test cases, except "hidden" tests, are run. +A test is hidden by giving it any tag starting with (or just) a period (```.```) - or, in the deprecated case, tagged ```[hide]``` or given name starting with `'./'`. To specify hidden tests from the command line ```[.]``` or ```[hide]``` can be used *regardless of how they were declared*. + +Specs must be enclosed in quotes if they contain spaces. If they do not contain spaces the quotes are optional. + +Wildcards consist of the `*` character at the beginning and/or end of test case names and can substitute for any number of any characters (including none). + +Test specs are case insensitive. + +If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precendence, however. +Inclusions and exclusions are evaluated in left-to-right order. + +Test case examples: + +
thisTestOnly            Matches the test case called, 'thisTestOnly'
+"this test only"        Matches the test case called, 'this test only'
+these*                  Matches all cases starting with 'these'
+exclude:notThis         Matches all tests except, 'notThis'
+~notThis                Matches all tests except, 'notThis'
+~*private*              Matches all tests except those that contain 'private'
+a* ~ab* abc             Matches all tests that start with 'a', except those that
+                        start with 'ab', except 'abc', which is included
+
+ +Names within square brackets are interpreted as tags. +A series of tags form an AND expression wheras a comma-separated sequence forms an OR expression. e.g.: + +
[one][two],[three]
+This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]` + + + +## Choosing a reporter to use + +
-r, --reporter <reporter>
+ +A reporter is an object that formats and structures the output of running tests, and potentially summarises the results. By default a console reporter is used that writes, IDE friendly, textual output. Catch comes bundled with some alternative reporters, but more can be added in client code.
+The bundled reporters are: + +
-r console
+-r compact
+-r xml
+-r junit
+
+ +The JUnit reporter is an xml format that follows the structure of the JUnit XML Report ANT task, as consumed by a number of third-party tools, including Continuous Integration servers such as Hudson. If not otherwise needed, the standard XML reporter is preferred as this is a streaming reporter, whereas the Junit reporter needs to hold all its results until the end so it can write the overall results into attributes of the root node. + + +## Breaking into the debugger +
-b, --break
+ +In some IDEs (currently XCode and Visual Studio) it is possible for Catch to break into the debugger on a test failure. This can be very helpful during debug sessions - especially when there is more than one path through a particular test. +In addition to the command line option, ensure you have built your code with the DEBUG preprocessor symbol + + +## Showing results for successful tests +
-s, --success
+ +Usually you only want to see reporting for failed tests. Sometimes it's useful to see *all* the output (especially when you don't trust that that test you just added worked first time!). +To see successful, as well as failing, test results just pass this option. Note that each reporter may treat this option differently. The Junit reporter, for example, logs all results regardless. + + +## Aborting after a certain number of failures +
-a, --abort
+-x, --abortx [<failure threshold>]
+
+ +If a ```REQUIRE``` assertion fails the test case aborts, but subsequent test cases are still run. +If a ```CHECK``` assertion fails even the current test case is not aborted. + +Sometimes this results in a flood of failure messages and you'd rather just see the first few. Specifying ```-a``` or ```--abort``` on its own will abort the whole test run on the first failed assertion of any kind. Use ```-x``` or ```--abortx``` followed by a number to abort after that number of assertion failures. + + +## Listing available tests, tags or reporters +
-l, --list-tests
+-t, --list-tags
+--list-reporters
+
+ +```-l``` or ```--list-tests`` will list all registered tests, along with any tags. +If one or more test-specs have been supplied too then only the matching tests will be listed. + +```-t``` or ```--list-tags``` lists all available tags, along with the number of test cases they match. Again, supplying test specs limits the tags that match. + +```--list-reporters``` lists the available reporters. + + +## Sending output to a file +
-o, --out <filename>
+
+ +Use this option to send all output to a file. By default output is sent to stdout (note that uses of stdout and stderr *from within test cases* are redirected and included in the report - so even stderr will effectively end up on stdout). + + +## Naming a test run +
-n, --name <name for test run>
+ +If a name is supplied it will be used by the reporter to provide an overall name for the test run. This can be useful if you are sending to a file, for example, and need to distinguish different test runs - either from different Catch executables or runs of the same executable with different options. If not supplied the name is defaulted to the name of the executable. + + +## Eliding assertions expected to throw +
-e, --nothrow
+ +Skips all assertions that test that an exception is thrown, e.g. ```REQUIRE_THROWS```. + +These can be a nuisance in certain debugging environments that may break when exceptions are thrown (while this is usually optional for handled exceptions, it can be useful to have enabled if you are trying to track down something unexpected). + +Sometimes exceptions are expected outside of one of the assertions that tests for them (perhaps thrown and caught within the code-under-test). The whole test case can be skipped when using ```-e``` by marking it with the ```[!throws]``` tag. + +When running with this option any throw checking assertions are skipped so as not to contribute additional noise. Be careful if this affects the behaviour of subsequent tests. + + +## Make whitespace visible +
-i, --invisibles
+ +If a string comparison fails due to differences in whitespace - especially leading or trailing whitespace - it can be hard to see what's going on. +This option transforms tabs and newline characters into ```\t``` and ```\n``` respectively when printing. + + +## Warnings +
-w, --warn <warning name>
+ +Enables reporting of warnings (only one, at time of this writing). If a warning is issued it fails the test. + +The ony available warning, presently, is ```NoAssertions```. This warning fails a test case, or (leaf) section if no assertions (```REQUIRE```/ ```CHECK``` etc) are encountered. + + +## Reporting timings +
-d, --durations <yes/no>
+ +When set to ```yes``` Catch will report the duration of each test case, in milliseconds. Note that it does this regardless of whether a test case passes or fails. Note, also, the certain reporters (e.g. Junit) always report test case durations regardless of this option being set or not. + + +## Load test names to run from a file +
-f, --input-file <filename>
+ +Provide the name of a file that contains a list of test case names - one per line. Blank lines are skipped and anything after the comment character, ```#```, is ignored. + +A useful way to generate an initial instance of this file is to use the list-test-names-only option. This can then be manually curated to specify a specific subset of tests - or in a specific order. + + +## Just test names +
--list-test-names-only
+ +This option lists all available tests in a non-indented form, one on each line. This makes it ideal for saving to a file and feeding back into the ```-f``` or ```--input-file``` option. + + + +## Specify the order test cases are run +
--order <decl|lex|rand>
+ +Test cases are ordered one of three ways: + + +### decl +Declaration order. The order the tests were originally declared in. Note that ordering between files is not guaranteed and is implementation dependent. + +### lex +Lexicographically sorted. Tests are sorted, alpha-numerically, by name. + +### rand +Randomly sorted. Test names are sorted using ```std::random_shuffle()```. By default the random number generator is seeded with 0 - and so the order is repeatable. To control the random seed see rng-seed. + + +## Specify a seed for the Random Number Generator +
--rng-seed <'time'|number>
+ +Sets a seed for the random number generator using ```std::srand()```. +If a number is provided this is used directly as the seed so the random pattern is repeatable. +Alternatively if the keyword ```time``` is provided then the result of calling ```std::time(0)``` is used and so the pattern becomes unpredictable. + +In either case the actual value for the seed is printed as part of Catch's output so if an issue is discovered that is sensitive to test ordering the ordering can be reproduced - even if it was originally seeded from ```std::time(0)```. + + +## Usage +
-h, -?, --help
+ +Prints the command line arguments to stdout + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/configuration.md b/3rdparty/sol2/Catch/docs/configuration.md new file mode 100644 index 00000000000..33052190cf3 --- /dev/null +++ b/3rdparty/sol2/Catch/docs/configuration.md @@ -0,0 +1,73 @@ +Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). + +Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a small set of macros for configuring how it is built. + +# main()/ implementation + + CATCH_CONFIG_MAIN // Designates this as implementation file and defines main() + CATCH_CONFIG_RUNNER // Designates this as implementation file + +Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*. + +# Prefixing Catch macros + + CATCH_CONFIG_PREFIX_ALL + +To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```). + + +# Terminal colour + + CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring + CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used + CATCH_CONFIG_COLOUR_ANSI // forces ANSI colour codes to be used + +Yes, I am English, so I will continue to spell "colour" with a 'u'. + +When sending output to the terminal, if it detects that it can, Catch will use colourised text. On Windows the Win32 API, ```SetConsoleTextAttribute```, is used. On POSIX systems ANSI colour escape codes are inserted into the stream. + +For finer control you can define one of the above identifiers (these are mutually exclusive - but that is not checked so may behave unexpectedly if you mix them): + +Note that when ANSI colour codes are used "unistd.h" must be includable - along with a definition of ```isatty()``` + +Typically you should place the ```#define``` before #including "catch.hpp" in your main source file - but if you prefer you can define it for your whole project by whatever your IDE or build system provides for you to do so. + +# Console width + + CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number + +Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this. +By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value. + +# stdout + + CATCH_CONFIG_NOSTDOUT + +Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them from ```Catch::cout()``` and ```Catch::cerr()``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are: + + std::ostream& cout(); + std::ostream& cerr(); + +This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems. + +# C++ conformance toggles + + CATCH_CONFIG_CPP11_NULLPTR // nullptr is supported? + CATCH_CONFIG_CPP11_NOEXCEPT // noexcept is supported? + CATCH_CONFIG_CPP11_GENERATED_METHODS // delete and default keywords for methods + CATCH_CONFIG_CPP11_IS_ENUM // std::is_enum is supported? + CATCH_CONFIG_CPP11_TUPLE // std::tuple is supported + CATCH_CONFIG_VARIADIC_MACROS // Usually pre-C++11 compiler extensions are sufficient + CATCH_CONFIG_CPP11_LONG_LONG // generates overloads for the long long type + CATCH_CONFIG_CPP11_OVERRIDE // CATCH_OVERRIDE expands to override (for virtual function implementations) + CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr + +Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative. +So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support. +You may also suppress any of these features by using the `_NO_` form, e.g. `CATCH_CONFIG_CPP11_NO_NULLPTR`. + +All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11` + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/contributing.md b/3rdparty/sol2/Catch/docs/contributing.md new file mode 100644 index 00000000000..49a663c042b --- /dev/null +++ b/3rdparty/sol2/Catch/docs/contributing.md @@ -0,0 +1,23 @@ +# Contributing to Catch + +So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated. Of course so are bug reports and other comments and questions. + +If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to help you find your way around. As this is liable to drift out of date please raise an issue or, better still, a pull request for this file, if you notice that. + +## Branches + +Ongoing development is on the "develop" branch (if there is one, currently), or on feature branches that are branched off of develop. Please target any pull requests at develop, or, for larger chunks of work, a branch off of develop. + +## Directory structure + +Users of Catch primarily use the single header version. Maintainers should work with the full source (which is still, primarily, in headers). This can be found in the ```include``` folder, but you may prefer to use one of the IDE project files (for MSVC or XCode). These can be found under ```projects/```*IDE Name*```/```*project name*. A number of contributors have proposed make files, and submitted their own versions. At some point these should be made available too. + +In addition to the include files and IDE projects there are a number of tests in cpp files. These can all be found in ```projects/SelfTest```. You'll also see a ```SurrogateCpps``` directory in there. This contains a set of cpp files that each ```#include``` a single header. While these files are not essential to compilation they help to keep the implementation headers self-contained. At time of writing this set is not complete but has reasonable coverage. If you add additional headers please try to remember to add a surrogate cpp for it. + +The other directories are ```scripts``` which contains a set of python scripts to help in testing Catch as well as generating the single include, and docs, which contains the documentation as a set of markdown files. + + *this document is in-progress...* + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/logging.md b/3rdparty/sol2/Catch/docs/logging.md new file mode 100644 index 00000000000..a659b3e8e81 --- /dev/null +++ b/3rdparty/sol2/Catch/docs/logging.md @@ -0,0 +1,52 @@ +# Logging macros + +Additional messages can be logged during a test case. + +## Streaming macros + +All these macros allow heterogenous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it. + +E.g.: +```c++ +INFO( "The number is " << i ); +``` + +(Note that there is no initial ```<<``` - instead the insertion sequence is placed in parentheses.) +These macros come in three forms: + +**INFO(** _message expression_ **)** + +The message is logged to a buffer, but only reported with the next assertion that is logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops. + +**WARN(** _message expression_ **)** + +The message is always reported but does not fail the test. + +**FAIL(** _message expression_ **)** + +The message is reported and the test case fails. + +## Quickly capture a variable value + +**CAPTURE(** _expression_ **)** + +Sometimes you just want to log the name and value of a variable. While you can easily do this with the INFO macro, above, as a convenience the CAPTURE macro handles the stringising of the variable name for you (actually it works with any expression, not just variables). + +E.g. +```c++ +CAPTURE( theAnswer ); +``` + +This would log something like: + +
"theAnswer := 42"
+ +## Deprecated macros + +**SCOPED_INFO and SCOPED_CAPTURE** + +These macros are now deprecated and are just aliases for INFO and CAPTURE (which were not previously scoped). + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/own-main.md b/3rdparty/sol2/Catch/docs/own-main.md new file mode 100644 index 00000000000..f8c836e6f27 --- /dev/null +++ b/3rdparty/sol2/Catch/docs/own-main.md @@ -0,0 +1,68 @@ +# Supplying main() yourself + +The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line. + +This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file. + +Sometimes, though, you need to write your own version of main(). You can do this by writing ```#define CATCH_CONFIG_RUNNER``` instead. Now you are free to write ```main()``` as normal and call into Catch yourself manually. + +You now have a lot of flexibility - but here are three recipes to get your started: + +## Let Catch take full control of args and config + +If you just need to have code that executes before and/ or after Catch this is the simplest option. + +```c++ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +int main( int argc, char* const argv[] ) +{ + // global setup... + + int result = Catch::Session().run( argc, argv ); + + // global clean-up... + + return result; +} +``` + +## Amending the config + +If you still want Catch to process the command line, but you want to programatically tweak the config, you can do so in one of two ways: + +```c++ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +int main( int argc, char* const argv[] ) +{ + Catch::Session session; // There must be exactly once instance + + // writing to session.configData() here sets defaults + // this is the preferred way to set them + + int returnCode = session.applyCommandLine( argc, argv ); + if( returnCode != 0 ) // Indicates a command line error + return returnCode; + + // writing to session.configData() or session.Config() here + // overrides command line args + // only do this if you know you need to + + return session.run(); +} +``` + +Take a look at the definitions of Config and ConfigData to see what you can do with them. + +To take full control of the config simply omit the call to ```applyCommandLine()```. + +## Adding your own command line options + +Catch embeds a powerful command line parser which you can also use to parse your own options out. This capability is still in active development but will be documented here when it is ready. + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/slow-compiles.md b/3rdparty/sol2/Catch/docs/slow-compiles.md new file mode 100644 index 00000000000..5291aeccc1d --- /dev/null +++ b/3rdparty/sol2/Catch/docs/slow-compiles.md @@ -0,0 +1,22 @@ +# Why do my tests take so long to compile? + +Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? + +Catch is implemented entirely in headers. There is a little overhead due to this - but not as much as you might think - and you can minimise it simply by organising your test code as follows: + +## Short answer +Exactly one source file must ```#define``` either ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER``` before ```#include```-ing Catch. In this file *do not write any test cases*! In most cases that means this file will just contain two lines (the ```#define``` and the ```#include```). + +## Long answer + +Usually C++ code is split between a header file, containing declarations and prototypes, and an implementation file (.cpp) containing the definition, or implementation, code. Each implementation file, along with all the headers that it includes (and which those headers include, etc), is expanded into a single entity called a translation unit - which is then passed to the compiler and compiled down to an object file. + +But functions and methods can also be written inline in header files. The downside to this is that these definitions will then be compiled in *every* translation unit that includes the header. + +Because Catch is implemented *entirely* in headers you might think that the whole of Catch must be compiled into every translation unit that uses it! Actually it's not quite as bad as that. Catch mitigates this situation by effectively maintaining the traditional separation between the implementation code and declarations. Internally the implementation code is protected by ```#ifdef```s and is conditionally compiled into only one translation unit. This translation unit is that one that ```#define```s ```CATCH_CONFIG_MAIN``` or ```CATCH_CONFIG_RUNNER```. Let's call this the main source file. + +As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/test-cases-and-sections.md b/3rdparty/sol2/Catch/docs/test-cases-and-sections.md new file mode 100644 index 00000000000..86644f006cd --- /dev/null +++ b/3rdparty/sol2/Catch/docs/test-cases-and-sections.md @@ -0,0 +1,86 @@ +# Test cases and sections + +While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style. + +Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#testCasesAndSections). + +Test cases and sections are very easy to use in practice: + +* **TEST_CASE(** _test name_ \[, _tags_ \] **)** +* **SECTION(** _section name_ **)** + +_test name_ and _section name_ are free form, quoted, strings. The optional _tags_ argument is a quoted string containing one or more tags enclosed in square brackets. Tags are discussed below. Test names must be unique within the Catch executable. + +For examples see the [Tutorial](tutorial.md) + +## Tags + +Tags allow an arbitrary number of additional strings to be associated with a test case. Test cases can be selected (for running, or just for listing) by tag - or even by an expression that combines several tags. At their most basic level they provide a simple way to group several related tests together. + +As an example - given the following test cases: + + TEST_CASE( "A", "[widget]" ) { /* ... */ } + TEST_CASE( "B", "[widget]" ) { /* ... */ } + TEST_CASE( "C", "[gadget]" ) { /* ... */ } + TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ } + +The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects C & D. ```"[widget][gadget]"``` selects just D and ```"[widget],[gadget]"``` selects all four test cases. + +For more detail on command line selection see [the command line docs](command-line.md#specifying-which-tests-to-run) + +Tag names are not case sensitive. + +### Special Tags + +All tag names beginning with non-alphanumeric characters are reserved by Catch. Catch defines a number of "special" tags, which have meaning to the test runner itself. These special tags all begin with a symbol character. Following is a list of currently defined special tags and their meanings. + +* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them. + +* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be exluded when running with `-e` or `--nothrow`. + +* `[!shouldfail]` - reverse the failing logic of the test: if the test is successful if it fails, and vice-versa. + +* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests. + +* `[#]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`. + +* `[@]` - tag aliases all begin with `@` (see below). + +## Tag aliases + +Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form: + + CATCH_REGISTER_TAG_ALIAS( , ) + +Aliases must begining with the `@` character. An example of a tag alias is: + + CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) + +Now when `[@nhf]` is used on the command line this matches all tests that are tagged `[failing]`, but which are not also hidden. + +## BDD-style test cases + +In addition to Catch's take on the classic style of test cases, Catch supports an alternative syntax that allow tests to be written as "executable specifications" (one of the early goals of [Behaviour Driven Development](http://dannorth.net/introducing-bdd/)). This set of macros map on to ```TEST_CASE```s and ```SECTION```s, with a little internal support to make them smoother to work with. + +* **SCENARIO(** _scenario name_ \[, _tags_ \] **)** + +This macro maps onto ```TEST_CASE``` and works in the same way, except that the test case name will be prefixed by "Scenario: " + +* **GIVEN(** _something_ **)** +* **WHEN(** _something_ **)** +* **THEN(** _something_ **)** + +These macros map onto ```SECTION```s except that the section names are the _something_s prefixed by "given: ", "when: " or "then: " respectively. + +* **AND_WHEN(** _something_ **)** +* **AND_THEN(** _something_ **)** + +Similar to ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```WHEN```s and ```THEN```s together. + +When any of these macros are used the console reporter recognises them and formats the test case header such that the Givens, Whens and Thens are aligned to aid readability. + +Other than the additional prefixes and the formatting in the console reporter these macros behave exactly as ```TEST_CASE```s and ```SECTION```s. As such there is nothing enforcing the correct sequencing of these macros - that's up to the programmer! + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/test-fixtures.md b/3rdparty/sol2/Catch/docs/test-fixtures.md new file mode 100644 index 00000000000..6bef762b8e3 --- /dev/null +++ b/3rdparty/sol2/Catch/docs/test-fixtures.md @@ -0,0 +1,32 @@ +Although Catch allows you to group tests together as sections within a test case, it can still convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure: + +```c++ +class UniqueTestsFixture { + private: + static int uniqueID; + protected: + DBConnection conn; + public: + UniqueTestsFixture() : conn(DBConnection::createConnection("myDB")) { + } + protected: + int getID() { + return ++uniqueID; + } + }; + + int UniqueTestsFixture::uniqueID = 0; + + TEST_CASE_METHOD(UniqueTestsFixture, "Create Employee/No Name", "[create]") { + REQUIRE_THROWS(conn.executeSQL("INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "")); + } + TEST_CASE_METHOD(UniqueTestsFixture, "Create Employee/Normal", "[create]") { + REQUIRE(conn.executeSQL("INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "Joe Bloggs")); + } +``` + +The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter. + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/docs/tostring.md b/3rdparty/sol2/Catch/docs/tostring.md new file mode 100644 index 00000000000..dbb6cb8d5d0 --- /dev/null +++ b/3rdparty/sol2/Catch/docs/tostring.md @@ -0,0 +1,70 @@ +# String conversions + +Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). +Most built-in or std types are supported out of the box but there are three ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. + +## operator << overload for std::ostream + +This is the standard way of providing string conversions in C++ - and the chances are you may already provide this for your own purposes. If you're not familiar with this idiom it involves writing a free function of the form: + +``` +std::ostream& operator << ( std::ostream& os, T const& value ) { + os << convertMyTypeToString( value ); + return os; +} +``` + +(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function). + +You should put this function in the same namespace as your type. + +Alternatively you may prefer to write it as a member function: + +``` +std::ostream& T::operator << ( std::ostream& os ) const { + os << convertMyTypeToString( *this ); + return os; +} +``` + +## Catch::toString overload + +If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide an overload for ```Catch::toString()``` for your type. + +``` +namespace Catch { + std::string toString( T const& value ) { + return convertMyTypeToString( value ); + } +} +``` + +Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace. + +## Catch::StringMaker specialisation + +There are some cases where overloading toString does not work as expected. Specialising StringMaker gives you more precise, and reliable, control - but at the cost of slightly more code and complexity: + +``` +namespace Catch { + template<> struct StringMaker { + static std::string convert( T const& value ) { + return convertMyTypeToString( value ); + } + }; +} +``` + +## Exceptions + +By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example: + +``` +CATCH_TRANSLATE_EXCEPTION( MyType& ex ) { + return ex.message(); +} +``` + +--- + +[Home](Readme.md) diff --git a/3rdparty/sol2/Catch/docs/tutorial.md b/3rdparty/sol2/Catch/docs/tutorial.md new file mode 100644 index 00000000000..0fdaff9bbe3 --- /dev/null +++ b/3rdparty/sol2/Catch/docs/tutorial.md @@ -0,0 +1,249 @@ +# Getting Catch + +The simplest way to get Catch is to download the single header version from [http://builds.catch-lib.net](http://builds.catch-lib.net). Don't be put off by the word "builds" there. The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. + +The full source for Catch, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there. + + +## Where to put it? + +Catch is header only. All you need to do is drop the file(s) somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html). + +The rest of this tutorial will assume that the Catch single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary. + +# Writing tests + +Let's start with a really simple example. Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now). + +```c++ +unsigned int Factorial( unsigned int number ) { + return number <= 1 ? number : Factorial(number-1)*number; +} +``` + +To keep things simple we'll put everything in a single file (see later for more on how to structure your test files) + +```c++ +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include "catch.hpp" + +unsigned int Factorial( unsigned int number ) { + return number <= 1 ? number : Factorial(number-1)*number; +} + +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} +``` + +This will compile to a complete executable which responds to [command line arguments](command-line.md). If you just run it with no arguments it will execute all test cases (in this case there is just one), report any failures, report a summary of how many tests passed and failed and return the number of failed tests (useful for if you just want a yes/ no answer to: "did it work"). + +If you run this as written it will pass. Everything is good. Right? +Well, there is still a bug here. In fact the first version of this tutorial I posted here genuinely had the bug in! So it's not completely contrived (thanks to Daryle Walker (```@CTMacUser```) for pointing this out). + +What is the bug? Well what is the factorial of zero? +[The factorial of zero is one](http://mathforum.org/library/drmath/view/57128.html) - which is just one of those things you have to know (and remember!). + +Let's add that to the test case: + +```c++ +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(0) == 1 ); + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} +``` + +Now we get a failure - something like: + +``` +Example.cpp:9: FAILED: + REQUIRE( Factorial(0) == 1 ) +with expansion: + 0 == 1 +``` + +Note that we get the actual return value of Factorial(0) printed for us (0) - even though we used a natural expression with the == operator. That let's us immediately see what the problem is. + +Let's change the factorial function to: + +```c++ +unsigned int Factorial( unsigned int number ) { + return number > 1 ? Factorial(number-1)*number : 1; +} +``` + +Now all the tests pass. + +Of course there are still more issues to do deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here. + +## What did we do here? + +Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on. + +1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md)). +2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see Test cases and Sections, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests. +3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names. +4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced. + + +## Test cases and sections + +Most test frameworks have a class-based fixture mechanism. That is, test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages, like C++, that support deterministic destruction). + +While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was problems like these that led James Newkirk, who led the team that built NUnit, to start again from scratch and build xUnit). + +Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example: + +```c++ +TEST_CASE( "vectors can be sized and resized", "[vector]" ) { + + std::vector v( 5 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + + SECTION( "resizing bigger changes size and capacity" ) { + v.resize( 10 ); + + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "resizing smaller changes size but not capacity" ) { + v.resize( 0 ); + + REQUIRE( v.size() == 0 ); + REQUIRE( v.capacity() >= 5 ); + } + SECTION( "reserving bigger changes capacity but not size" ) { + v.reserve( 10 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "reserving smaller does not change size or capacity" ) { + v.reserve( 0 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + } +} +``` + +For each ```SECTION``` the ```TEST_CASE``` is executed from the start - so as we enter each section we know that size is 5 and capacity is at least 5. We enforced those requirements with the ```REQUIRE```s at the top level so we can be confident in them. +This works because the ```SECTION``` macro contains an if statement that calls back into Catch to see if the section should be executed. One leaf section is executed on each run through a ```TEST_CASE```. The other sections are skipped. Next time through the next section is executed, and so on until no new sections are encountered. + +So far so good - this is already an improvement on the setup/teardown approach because now we see our setup code inline and use the stack. + +The power of sections really shows, however, when we need to execute a sequence of, checked, operations. Continuing the vector example, we might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing. We can do that, naturally, like so: + +```c++ + SECTION( "reserving bigger changes capacity but not size" ) { + v.reserve( 10 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + + SECTION( "reserving smaller again does not change capacity" ) { + v.reserve( 7 ); + + REQUIRE( v.capacity() >= 10 ); + } + } +``` + +Sections can be nested to an arbitrary depth (limited only by your stack size). Each leaf section (i.e. a section that contains no nested sections) will be executed exactly once, on a separate path of execution from any other leaf section (so no leaf section can interfere with another). A failure in a parent section will prevent nested sections from running - but then that's the idea. + +## BDD-Style + +If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively. For more details see [Test cases and sections](test-cases-and-sections.md). + +The vector example can be adjusted to use these macros like so: + +```c++ +SCENARIO( "vectors can be sized and resized", "[vector]" ) { + + GIVEN( "A vector with some items" ) { + std::vector v( 5 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + + WHEN( "the size is increased" ) { + v.resize( 10 ); + + THEN( "the size and capacity change" ) { + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + } + } + WHEN( "the size is reduced" ) { + v.resize( 0 ); + + THEN( "the size changes but not capacity" ) { + REQUIRE( v.size() == 0 ); + REQUIRE( v.capacity() >= 5 ); + } + } + WHEN( "more capacity is reserved" ) { + v.reserve( 10 ); + + THEN( "the capacity changes but not the size" ) { + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + } + WHEN( "less capacity is reserved" ) { + v.reserve( 0 ); + + THEN( "neither size nor capacity are changed" ) { + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + } + } + } +} +``` + +Conveniently, these tests will be reported as follows when run: + +``` +Scenario: vectors can be sized and resized + Given: A vector with some items + When: more capacity is reserved + Then: the capacity changes but not the size +``` + + +## Scaling up + +To keep the tutorial simple we put all our code in a single file. This is fine to get started - and makes jumping into Catch even quicker and easier. As you write more real-world tests, though, this is not really the best approach. + +The requirement is that the following block of code ([or equivalent](own-main.md)): + +```c++ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" +``` + +appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```! + +In fact it is usually a good idea to put the block with the ```#define``` [in it's own source file](slow-compiles.md). + +Do not write your tests in header files! + + +## Next steps + +This has been a brief introduction to get you up and running with Catch, and to point out some of the key differences between Catch and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests. + +Of course there is more to learn - most of which you should be able to page-fault in as you go. Please see the ever-growing [Reference section](Readme.md) for what's available. + +--- + +[Home](Readme.md) diff --git a/3rdparty/sol2/Catch/docs/why-catch.md b/3rdparty/sol2/Catch/docs/why-catch.md new file mode 100644 index 00000000000..93488d2291d --- /dev/null +++ b/3rdparty/sol2/Catch/docs/why-catch.md @@ -0,0 +1,42 @@ +# Why do we need yet another C++ test framework? + +Good question. For C++ there are quite a number of established frameworks, including (but not limited to), [CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page), [Google Test](http://code.google.com/p/googletest/), [Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html), [Aeryn](https://launchpad.net/aeryn), [Cute](http://r2.ifs.hsr.ch/cute), [Fructose](http://fructose.sourceforge.net/) and [many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B). Even for Objective-C there are a few, including OCUnit - which now comes bundled with XCode. + +So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course. + +## Key Features + +* Really easy to get started. Just download catch.hpp, #include it and you're away. +* No external dependencies. As long as you can compile C++98 and have a C++ standard library available. +* Write test cases as, self-registering, functions or methods. +* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures!) +* Use BDD-style Given-When-Then sections as well as traditional unit test cases. +* Only one core assertion macro for comparisons. Standard C/C++ operators are used for the comparison - yet the full expression is decomposed and lhs and rhs values are logged. + +## Other core features + +* Tests are named using free-form strings - no more couching names in legal identifiers. +* Tests can be tagged for easily running ad-hoc groups of tests. +* Failures can (optionally) break into the debugger on Windows and Mac. +* Output is through modular reporter objects. Basic textual and XML reporters are included. Custom reporters can easily be added. +* JUnit xml output is supported for integration with third-party tools, such as CI servers. +* A default main() function is provided (in a header), but you can supply your own for complete control (e.g. integration into your own test runner GUI). +* A command line parser is provided and can still be used if you choose to provided your own main() function. +* Catch can test itself. +* Alternative assertion macro(s) report failures but don't abort the test case +* Floating point tolerance comparisons are built in using an expressive Approx() syntax. +* Internal and friendly macros are isolated so name clashes can be managed +* Support for Matchers (early stages) + +## Objective-C-specific features + +* Automatically detects if you are using it from an Objective-C project +* Works with and without ARC with no additional configuration +* Implement test fixtures using Obj-C classes too (like OCUnit) +* Additional built in matchers that work with Obj-C types (e.g. string matchers) + +See the [tutorial](tutorial.md) to get more of a taste of using CATCH in practice + +--- + +[Home](Readme.md) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/projects/CMake/CMakeLists.txt b/3rdparty/sol2/Catch/projects/CMake/CMakeLists.txt new file mode 100644 index 00000000000..960d9fb1fcb --- /dev/null +++ b/3rdparty/sol2/Catch/projects/CMake/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 2.8) + +project(Catch) + +# define some folders +get_filename_component(CATCH_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PATH) +get_filename_component(CATCH_DIR "${CATCH_DIR}" PATH) +set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) +if(USE_CPP11) + ## We can't turn this on by default, since it breaks on travis + message(STATUS "Enabling C++11") + set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") +endif() + +# define the sources of the self test +set(SOURCES + ${SELF_TEST_DIR}/ApproxTests.cpp + ${SELF_TEST_DIR}/BDDTests.cpp + ${SELF_TEST_DIR}/ClassTests.cpp + ${SELF_TEST_DIR}/ConditionTests.cpp + ${SELF_TEST_DIR}/ExceptionTests.cpp + ${SELF_TEST_DIR}/GeneratorTests.cpp + ${SELF_TEST_DIR}/MessageTests.cpp + ${SELF_TEST_DIR}/MiscTests.cpp + ${SELF_TEST_DIR}/PartTrackerTests.cpp + ${SELF_TEST_DIR}/TestMain.cpp + ${SELF_TEST_DIR}/TrickyTests.cpp + ${SELF_TEST_DIR}/VariadicMacrosTests.cpp + ${SELF_TEST_DIR}/EnumToString.cpp + ${SELF_TEST_DIR}/ToStringPair.cpp + ${SELF_TEST_DIR}/ToStringVector.cpp + ${SELF_TEST_DIR}/ToStringWhich.cpp + ${SELF_TEST_DIR}/ToStringTuple.cpp +) + +# configure the executable +include_directories(${CATCH_DIR}/include) +add_executable(SelfTest ${SOURCES}) + +# configure unit tests via CTest +enable_testing() +add_test(NAME RunTests COMMAND SelfTest) + +add_test(NAME ListTests COMMAND SelfTest --list-tests) +set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases") + +add_test(NAME ListTags COMMAND SelfTest --list-tags) +set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags") diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ApproxTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ApproxTests.cpp new file mode 100644 index 00000000000..53656596c0a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ApproxTests.cpp @@ -0,0 +1,112 @@ +/* + * Created by Phil on 28/04/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Some simple comparisons between doubles", + "[Approx]" +) +{ + double d = 1.23; + + REQUIRE( d == Approx( 1.23 ) ); + REQUIRE( d != Approx( 1.22 ) ); + REQUIRE( d != Approx( 1.24 ) ); + + REQUIRE( Approx( d ) == 1.23 ); + REQUIRE( Approx( d ) != 1.22 ); + REQUIRE( Approx( d ) != 1.24 ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with different epsilons", + "[Approx]" + ) +{ + double d = 1.23; + + REQUIRE( d != Approx( 1.231 ) ); + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with floats", + "[Approx]" +) +{ + REQUIRE( 1.23f == Approx( 1.23f ) ); + REQUIRE( 0.0f == Approx( 0.0f ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with ints", + "[Approx]" +) +{ + REQUIRE( 1 == Approx( 1 ) ); + REQUIRE( 0 == Approx( 0 ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Approximate comparisons with mixed numeric types", + "[Approx]" +) +{ + const double dZero = 0; + const double dSmall = 0.00001; + const double dMedium = 1.234; + + REQUIRE( 1.0f == Approx( 1 ) ); + REQUIRE( 0 == Approx( dZero) ); + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ); + REQUIRE( 1.234f == Approx( dMedium ) ); + REQUIRE( dMedium == Approx( 1.234f ) ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Use a custom approx", + "[Approx][custom]" +) +{ + double d = 1.23; + + Approx approx = Approx::custom().epsilon( 0.005 ); + + REQUIRE( d == approx( 1.23 ) ); + REQUIRE( d == approx( 1.22 ) ); + REQUIRE( d == approx( 1.24 ) ); + REQUIRE( d != approx( 1.25 ) ); + + REQUIRE( approx( d ) == 1.23 ); + REQUIRE( approx( d ) == 1.22 ); + REQUIRE( approx( d ) == 1.24 ); + REQUIRE( approx( d ) != 1.25 ); +} + +inline double divide( double a, double b ) { + return a/b; +} + +TEST_CASE( "Approximate PI", "[Approx][PI]" ) +{ + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ); + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ); +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/BDDTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/BDDTests.cpp new file mode 100644 index 00000000000..2c8bc2495b0 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/BDDTests.cpp @@ -0,0 +1,103 @@ +/* + * Created by Phil on 29/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +inline bool itDoesThis(){ return true; } +inline bool itDoesThat(){ return true; } + +SCENARIO( "Do that thing with the thing", "[Tags]" ) { + GIVEN( "This stuff exists" ) { + // make stuff exist + WHEN( "I do this" ) { + // do this + THEN( "it should do this") + { + REQUIRE( itDoesThis() ); + AND_THEN( "do that") + REQUIRE( itDoesThat() ); + } + } + } +} + +SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capacity]" ) { + GIVEN( "an empty vector" ) { + std::vector v; + REQUIRE( v.size() == 0 ); + + WHEN( "it is made larger" ) { + v.resize( 10 ); + THEN( "the size and capacity go up" ) { + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + + AND_WHEN( "it is made smaller again" ) { + v.resize( 5 ); + THEN( "the size goes down but the capacity stays the same" ) { + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + } + } + } + + WHEN( "we reserve more space" ) { + v.reserve( 10 ); + THEN( "The capacity is increased but the size remains the same" ) { + REQUIRE( v.capacity() >= 10 ); + REQUIRE( v.size() == 0 ); + } + } + } +} + +SCENARIO( "This is a really long scenario name to see how the list command deals with wrapping", + "[very long tags][lots][long][tags][verbose]" + "[one very long tag name that should cause line wrapping writing out using the list command]" + "[anotherReallyLongTagNameButThisOneHasNoObviousWrapPointsSoShouldSplitWithinAWordUsingADashCharacter]" ) { + GIVEN( "A section name that is so long that it cannot fit in a single console width" ) + WHEN( "The test headers are printed as part of the normal running of the scenario" ) + THEN( "The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" ) + SUCCEED("boo!"); +} + +namespace { + +// a trivial fixture example to support SCENARIO_METHOD tests +struct Fixture +{ + Fixture() + : d_counter(0) + { + } + + int counter() + { + return d_counter++; + } + + int d_counter; +}; + +} + +SCENARIO_METHOD(Fixture, + "BDD tests requiring Fixtures to provide commonly-accessed data or methods", + "[bdd][fixtures]") { + const int before(counter()); + GIVEN("No operations precede me") { + REQUIRE(before == 0); + WHEN("We get the count") { + const int after(counter()); + THEN("Subsequently values are higher") { + REQUIRE(after > before); + } + } + } +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.std.approved.txt b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.std.approved.txt new file mode 100644 index 00000000000..7bbae96e57b --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.std.approved.txt @@ -0,0 +1,835 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CatchSelfTest is a host application. +Run with -? for options + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 0 ) +with expansion: + 7 == 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.11f ) ) +with expansion: + 9.1f == Approx( 9.1099996567 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.0f ) ) +with expansion: + 9.1f == Approx( 9.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 1 ) ) +with expansion: + 9.1f == Approx( 1.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 0 ) ) +with expansion: + 9.1f == Approx( 0.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi == Approx( 3.1415 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "goodbye" ) +with expansion: + "hello" == "goodbye" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hell" ) +with expansion: + "hello" == "hell" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hello1" ) +with expansion: + "hello" == "hello1" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() == 6 ) +with expansion: + 5 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( x == Approx( 1.301 ) ) +with expansion: + 1.3 == Approx( 1.301 ) + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi != Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415926535 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello != "hello" ) +with expansion: + "hello" != "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() != 5 ) +with expansion: + 5 != 5 + +------------------------------------------------------------------------------- +Ordering comparison checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 7 ) +with expansion: + 7 > 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 7 ) +with expansion: + 7 < 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 8 ) +with expansion: + 7 > 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 6 ) +with expansion: + 7 < 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 0 ) +with expansion: + 7 < 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < -1 ) +with expansion: + 7 < -1 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven >= 8 ) +with expansion: + 7 >= 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven <= 6 ) +with expansion: + 7 <= 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one < 9 ) +with expansion: + 9.1f < 9 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 10 ) +with expansion: + 9.1f > 10 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 9.2 ) +with expansion: + 9.1f > 9.2 + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hello" ) +with expansion: + "hello" > "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hello" ) +with expansion: + "hello" < "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hellp" ) +with expansion: + "hello" > "hellp" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "z" ) +with expansion: + "hello" > "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hellm" ) +with expansion: + "hello" < "hellm" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "a" ) +with expansion: + "hello" < "a" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello >= "z" ) +with expansion: + "hello" >= "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello <= "a" ) +with expansion: + "hello" <= "a" + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( true ) + +ConditionTests.cpp:: FAILED: + CHECK( !trueValue ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( trueValue ) +with expansion: + !true + +ConditionTests.cpp:: FAILED: + CHECK( !(1 == 1) ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( 1 == 1 ) +with expansion: + !(1 == 1) + +------------------------------------------------------------------------------- +Expected exceptions that don't throw or unexpected exceptions fail the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisThrows() ) +due to unexpected exception with message: + expected exception + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisDoesntThrow() ) +because no exception was thrown where one was expected: + +ExceptionTests.cpp:: FAILED: + CHECK_NOTHROW( thisThrows() ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown directly they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +An unchecked exception reports the line of the last assertion +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + {Unknown expression after the reported line} +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from sections they are always failures + section name +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from functions they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a REQUIRE the test should abort +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a CHECK the test should abort and +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +Non-std exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom exception + +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for nothrow +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for throwing as something else +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_AS( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Unexpected exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + 3.14 + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + +------------------------------------------------------------------------------- +INFO and WARN do not abort tests +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + this is a warning + +------------------------------------------------------------------------------- +INFO gets logged on failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message should be logged + so should this + +------------------------------------------------------------------------------- +INFO gets logged on failure, even if captured before successful assertions +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + CHECK( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message may be logged later + this message should be logged + +MessageTests.cpp:: FAILED: + CHECK( a == 0 ) +with expansion: + 2 == 0 +with message: + and this, but later + +------------------------------------------------------------------------------- +FAIL aborts the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + This is a failure + +------------------------------------------------------------------------------- +FAIL does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + +------------------------------------------------------------------------------- +Output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section one + +------------------------------------------------------------------------------- +Output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section two + +Message from section one +Message from section two +------------------------------------------------------------------------------- +SCOPED_INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + +------------------------------------------------------------------------------- +just failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Previous info should not be seen + +------------------------------------------------------------------------------- +sends information to INFO +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( false ) +with messages: + hi + i := 7 + +------------------------------------------------------------------------------- +Pointers can be converted to strings +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + actual address of p: 0x + +MessageTests.cpp:: +warning: + toString(p): 0x + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( a == b ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +looped SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( b > a ) +with expansion: + 0 > 1 + +------------------------------------------------------------------------------- +looped tests +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[0] (1) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[1] (1) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[3] (3) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[4] (5) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[6] (13) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[7] (21) is even + +A string sent directly to stdout +A string sent directly to stderr +------------------------------------------------------------------------------- +checkedIf, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_IF( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedIf( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +checkedElse, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_ELSE( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedElse( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +send a single char to INFO +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( false ) +with message: + 3 + +------------------------------------------------------------------------------- +Contains string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "not there" + +------------------------------------------------------------------------------- +StartsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "string" + +------------------------------------------------------------------------------- +EndsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "this" + +------------------------------------------------------------------------------- +Equals string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "something else" + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + +------------------------------------------------------------------------------- +Nice descriptive name +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +warning: + This one ran + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: +explicitly with message: + to infinity and beyond + +------------------------------------------------------------------------------- +Tabs and newlines show in output +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( s1 == s2 ) +with expansion: + "if ($b == 10) { + $a= 20; + }" + == + "if ($b == 10) { + $a = 20; + } + " + +hello +hello +------------------------------------------------------------------------------- +Where there is more to the expression after the RHS +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +Where the LHS is not a simple value +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +A failing expression with a non streamable type is still captured +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + CHECK( &o1 == &o2 ) +with expansion: + 0x == 0x + +TrickyTests.cpp:: FAILED: + CHECK( o1 == o2 ) +with expansion: + {?} == {?} + +------------------------------------------------------------------------------- +string literals of different sizes can be compared +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + REQUIRE( std::string( "first" ) == "second" ) +with expansion: + "first" == "second" + +=============================================================================== +test cases: 167 | 124 passed | 42 failed | 1 failed as expected +assertions: 914 | 818 passed | 83 failed | 13 failed as expected + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.sw.approved.txt b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.sw.approved.txt new file mode 100644 index 00000000000..d8c0b9b910a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.sw.approved.txt @@ -0,0 +1,9050 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CatchSelfTest is a host application. +Run with -? for options + +------------------------------------------------------------------------------- +toString(enum) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "E2{0}" ) +with expansion: + "E2{0}" == "E2{0}" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "E2{1}" ) +with expansion: + "E2{1}" == "E2{1}" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum class w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "E2/V0" ) +with expansion: + "E2/V0" == "E2/V0" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "E2/V1" ) +with expansion: + "E2/V1" == "E2/V1" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e3) == "Unknown enum value 10" ) +with expansion: + "Unknown enum value 10" + == + "Unknown enum value 10" + +------------------------------------------------------------------------------- +Some simple comparisons between doubles +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == Approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.22 ) ) +with expansion: + 1.23 != Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.24 ) ) +with expansion: + 1.23 != Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) != 1.22 ) +with expansion: + Approx( 1.23 ) != 1.22 + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) != 1.24 ) +with expansion: + Approx( 1.23 ) != 1.24 + +------------------------------------------------------------------------------- +Approximate comparisons with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.231 ) ) +with expansion: + 1.23 != Approx( 1.231 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ) +with expansion: + 1.23 == Approx( 1.231 ) + +------------------------------------------------------------------------------- +Approximate comparisons with floats +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.23f == Approx( 1.23f ) ) +with expansion: + 1.23f == Approx( 1.2300000191 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0.0f == Approx( 0.0f ) ) +with expansion: + 0.0f == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with ints +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1 == Approx( 1 ) ) +with expansion: + 1 == Approx( 1.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( 0 ) ) +with expansion: + 0 == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with mixed numeric types +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.0f == Approx( 1 ) ) +with expansion: + 1.0f == Approx( 1.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( dZero) ) +with expansion: + 0 == Approx( 0.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) +with expansion: + 0 == Approx( 0.00001 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.234f == Approx( dMedium ) ) +with expansion: + 1.234f == Approx( 1.234 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( dMedium == Approx( 1.234f ) ) +with expansion: + 1.234 == Approx( 1.2339999676 ) + +------------------------------------------------------------------------------- +Use a custom approx +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.22 ) ) +with expansion: + 1.23 == Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.24 ) ) +with expansion: + 1.23 == Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != approx( 1.25 ) ) +with expansion: + 1.23 != Approx( 1.25 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.22 ) +with expansion: + Approx( 1.23 ) == 1.22 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.24 ) +with expansion: + Approx( 1.23 ) == 1.24 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) != 1.25 ) +with expansion: + Approx( 1.23 ) != 1.25 + +------------------------------------------------------------------------------- +Approximate PI +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ) +with expansion: + 3.1428571429 == Approx( 3.141 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ) +with expansion: + 3.1428571429 != Approx( 3.141 ) + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: +PASSED: + REQUIRE( m_a == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +Equality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven == 7 ) +with expansion: + 7 == 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ) +with expansion: + 9.1f == Approx( 9.1000003815 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415926535 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello == "hello" ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( "hello" == data.str_hello ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello.size() == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( x == Approx( 1.3 ) ) +with expansion: + 1.3 == Approx( 1.3 ) + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 0 ) +with expansion: + 7 == 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.11f ) ) +with expansion: + 9.1f == Approx( 9.1099996567 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.0f ) ) +with expansion: + 9.1f == Approx( 9.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 1 ) ) +with expansion: + 9.1f == Approx( 1.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 0 ) ) +with expansion: + 9.1f == Approx( 0.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi == Approx( 3.1415 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "goodbye" ) +with expansion: + "hello" == "goodbye" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hell" ) +with expansion: + "hello" == "hell" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hello1" ) +with expansion: + "hello" == "hello1" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() == 6 ) +with expansion: + 5 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( x == Approx( 1.301 ) ) +with expansion: + 1.3 == Approx( 1.301 ) + +------------------------------------------------------------------------------- +Inequality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven != 6 ) +with expansion: + 7 != 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven != 8 ) +with expansion: + 7 != 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ) +with expansion: + 9.1f != Approx( 9.1099996567 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ) +with expansion: + 9.1f != Approx( 9.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 1 ) ) +with expansion: + 9.1f != Approx( 1.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 0 ) ) +with expansion: + 9.1f != Approx( 0.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.double_pi != Approx( 3.1415 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "goodbye" ) +with expansion: + "hello" != "goodbye" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "hell" ) +with expansion: + "hello" != "hell" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "hello1" ) +with expansion: + "hello" != "hello1" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello.size() != 6 ) +with expansion: + 5 != 6 + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi != Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415926535 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello != "hello" ) +with expansion: + "hello" != "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() != 5 ) +with expansion: + 5 != 5 + +------------------------------------------------------------------------------- +Ordering comparison checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven < 8 ) +with expansion: + 7 < 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven > 6 ) +with expansion: + 7 > 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven > 0 ) +with expansion: + 7 > 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven > -1 ) +with expansion: + 7 > -1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven >= 7 ) +with expansion: + 7 >= 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven >= 6 ) +with expansion: + 7 >= 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven <= 7 ) +with expansion: + 7 <= 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven <= 8 ) +with expansion: + 7 <= 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one > 9 ) +with expansion: + 9.1f > 9 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one < 10 ) +with expansion: + 9.1f < 10 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one < 9.2 ) +with expansion: + 9.1f < 9.2 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello <= "hello" ) +with expansion: + "hello" <= "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello >= "hello" ) +with expansion: + "hello" >= "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello < "hellp" ) +with expansion: + "hello" < "hellp" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello < "zebra" ) +with expansion: + "hello" < "zebra" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello > "hellm" ) +with expansion: + "hello" > "hellm" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello > "a" ) +with expansion: + "hello" > "a" + +------------------------------------------------------------------------------- +Ordering comparison checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 7 ) +with expansion: + 7 > 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 7 ) +with expansion: + 7 < 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 8 ) +with expansion: + 7 > 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 6 ) +with expansion: + 7 < 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 0 ) +with expansion: + 7 < 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < -1 ) +with expansion: + 7 < -1 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven >= 8 ) +with expansion: + 7 >= 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven <= 6 ) +with expansion: + 7 <= 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one < 9 ) +with expansion: + 9.1f < 9 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 10 ) +with expansion: + 9.1f > 10 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 9.2 ) +with expansion: + 9.1f > 9.2 + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hello" ) +with expansion: + "hello" > "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hello" ) +with expansion: + "hello" < "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hellp" ) +with expansion: + "hello" > "hellp" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "z" ) +with expansion: + "hello" > "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hellm" ) +with expansion: + "hello" < "hellm" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "a" ) +with expansion: + "hello" < "a" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello >= "z" ) +with expansion: + "hello" >= "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello <= "a" ) +with expansion: + "hello" <= "a" + +------------------------------------------------------------------------------- +Comparisons with int literals don't warn when mixing signed/ unsigned +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( i == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( ui == 2 ) +with expansion: + 2 == 2 + +ConditionTests.cpp:: +PASSED: + REQUIRE( l == 3 ) +with expansion: + 3 == 3 + +ConditionTests.cpp:: +PASSED: + REQUIRE( ul == 4 ) +with expansion: + 4 == 4 + +ConditionTests.cpp:: +PASSED: + REQUIRE( c == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( uc == 6 ) +with expansion: + 6 == 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 1 == i ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 2 == ui ) +with expansion: + 2 == 2 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 3 == l ) +with expansion: + 3 == 3 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 4 == ul ) +with expansion: + 4 == 4 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 5 == c ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 6 == uc ) +with expansion: + 6 == 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( (std::numeric_limits::max)() > ul ) +with expansion: + 18446744073709551615 (0x) + > + 4 + +------------------------------------------------------------------------------- +comparisons between int variables +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_char_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_short_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_int_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_long_var ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +comparisons between const int variables +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_char_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_short_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_int_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_long_var == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Comparisons between unsigned ints and negative signed ints match c++ standard +behaviour +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + CHECK( ( -1 > 2u ) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + CHECK( -1 > 2u ) +with expansion: + -1 > 2 + +ConditionTests.cpp:: +PASSED: + CHECK( ( 2u < -1 ) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + CHECK( 2u < -1 ) +with expansion: + 2 < -1 + +ConditionTests.cpp:: +PASSED: + CHECK( ( minInt > 2u ) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + CHECK( minInt > 2u ) +with expansion: + -2147483648 > 2 + +------------------------------------------------------------------------------- +Comparisons between ints where one side is computed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + CHECK( 54 == 6*9 ) +with expansion: + 54 == 54 + +------------------------------------------------------------------------------- +Pointers can be compared to null +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( p == nullptr ) +with expansion: + NULL == nullptr + +ConditionTests.cpp:: +PASSED: + REQUIRE( p == pNULL ) +with expansion: + NULL == NULL + +ConditionTests.cpp:: +PASSED: + REQUIRE( p != nullptr ) +with expansion: + 0x != nullptr + +ConditionTests.cpp:: +PASSED: + REQUIRE( cp != nullptr ) +with expansion: + 0x != nullptr + +ConditionTests.cpp:: +PASSED: + REQUIRE( cpc != nullptr ) +with expansion: + 0x != nullptr + +ConditionTests.cpp:: +PASSED: + REQUIRE( returnsNull() == nullptr ) +with expansion: + {null string} == nullptr + +ConditionTests.cpp:: +PASSED: + REQUIRE( returnsConstNull() == nullptr ) +with expansion: + {null string} == nullptr + +ConditionTests.cpp:: +PASSED: + REQUIRE( nullptr != p ) +with expansion: + nullptr != 0x + +------------------------------------------------------------------------------- +'Not' checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( false == false ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( true == true ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( !false ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + REQUIRE_FALSE( false ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( !falseValue ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + REQUIRE_FALSE( falseValue ) +with expansion: + !false + +ConditionTests.cpp:: +PASSED: + REQUIRE( !(1 == 2) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + REQUIRE_FALSE( 1 == 2 ) +with expansion: + !(1 == 2) + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( true ) + +ConditionTests.cpp:: FAILED: + CHECK( !trueValue ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( trueValue ) +with expansion: + !true + +ConditionTests.cpp:: FAILED: + CHECK( !(1 == 1) ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( 1 == 1 ) +with expansion: + !(1 == 1) + +------------------------------------------------------------------------------- +When checked exceptions are thrown they can be expected or unexpected +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_AS( thisThrows() ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_NOTHROW( thisDoesntThrow() ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS( thisThrows() ) + +------------------------------------------------------------------------------- +Expected exceptions that don't throw or unexpected exceptions fail the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisThrows() ) +due to unexpected exception with message: + expected exception + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisDoesntThrow() ) +because no exception was thrown where one was expected: + +ExceptionTests.cpp:: FAILED: + CHECK_NOTHROW( thisThrows() ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown directly they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +An unchecked exception reports the line of the last assertion +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + CHECK( 1 == 1 ) + +ExceptionTests.cpp:: FAILED: + {Unknown expression after the reported line} +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from sections they are always failures + section name +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from functions they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a REQUIRE the test should abort +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a CHECK the test should abort and +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +Non-std exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom exception + +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for nothrow +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for throwing as something else +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_AS( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Unexpected exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + 3.14 + +------------------------------------------------------------------------------- +NotImplemented exception +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + exact match +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + different case +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + wildcarded +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 200 == 200 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 202 == 202 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 204 == 204 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 206 == 206 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 208 == 208 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 210 == 210 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 212 == 212 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 2 == 2 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 4 == 4 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 6 == 6 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 8 == 8 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 10 == 10 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 30 == 30 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 40 == 40 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 42 == 42 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generators over two ranges +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) +with expansion: + 72 == 72 + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) +with expansion: + 214 == 214 + +------------------------------------------------------------------------------- +Generator over a range of pairs +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( i->first == i->second-1 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Generator over a range of pairs +------------------------------------------------------------------------------- +GeneratorTests.cpp: +............................................................................... + +GeneratorTests.cpp:: +PASSED: + CATCH_REQUIRE( i->first == i->second-1 ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +INFO and WARN do not abort tests +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + this is a message + this is a warning + +------------------------------------------------------------------------------- +SUCCEED counts as a test pass +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: +with message: + this is a success + +------------------------------------------------------------------------------- +INFO gets logged on failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message should be logged + so should this + +------------------------------------------------------------------------------- +INFO gets logged on failure, even if captured before successful assertions +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + CHECK( a == 2 ) +with expansion: + 2 == 2 +with message: + this message may be logged later + +MessageTests.cpp:: FAILED: + CHECK( a == 1 ) +with expansion: + 2 == 1 +with message: + this message should be logged + +MessageTests.cpp:: FAILED: + CHECK( a == 0 ) +with expansion: + 2 == 0 +with message: + and this, but later + +MessageTests.cpp:: +PASSED: + CHECK( a == 2 ) +with expansion: + 2 == 2 +with message: + but not this + +------------------------------------------------------------------------------- +FAIL aborts the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + This is a failure + +------------------------------------------------------------------------------- +FAIL does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + +------------------------------------------------------------------------------- +SUCCESS does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +Output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section one + +------------------------------------------------------------------------------- +Output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section two + +Message from section one +------------------------------------------------------------------------------- +Standard output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'one' + +Message from section two +------------------------------------------------------------------------------- +Standard output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'two' + +------------------------------------------------------------------------------- +SCOPED_INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 0 < 10 +with messages: + current counter 0 + i := 0 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 1 < 10 +with messages: + current counter 1 + i := 1 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 2 < 10 +with messages: + current counter 2 + i := 2 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 3 < 10 +with messages: + current counter 3 + i := 3 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 4 < 10 +with messages: + current counter 4 + i := 4 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 5 < 10 +with messages: + current counter 5 + i := 5 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 6 < 10 +with messages: + current counter 6 + i := 6 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 7 < 10 +with messages: + current counter 7 + i := 7 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 8 < 10 +with messages: + current counter 8 + i := 8 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 9 < 10 +with messages: + current counter 9 + i := 9 + +MessageTests.cpp:: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + +------------------------------------------------------------------------------- +The NO_FAIL macro reports a failure but does not fail the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +FAILED - but was ok: + CHECK_NOFAIL( 1 == 2 ) + +------------------------------------------------------------------------------- +just failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Previous info should not be seen + +------------------------------------------------------------------------------- +sends information to INFO +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( false ) +with messages: + hi + i := 7 + +------------------------------------------------------------------------------- +Pointers can be converted to strings +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + actual address of p: 0x + +MessageTests.cpp:: +warning: + toString(p): 0x + +------------------------------------------------------------------------------- +random SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +MiscTests.cpp:: +PASSED: + REQUIRE( b != a ) +with expansion: + 2 != 1 + +------------------------------------------------------------------------------- +random SECTION tests + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +nested SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +MiscTests.cpp:: +PASSED: + REQUIRE( b != a ) +with expansion: + 2 != 1 + +------------------------------------------------------------------------------- +nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( a == b ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s3 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s4 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a < b ) +with expansion: + 1 < 2 + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + d (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + e (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + f (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +looped SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( b > a ) +with expansion: + 0 > 1 + +------------------------------------------------------------------------------- +looped tests +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[0] (1) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[1] (1) is even + +MiscTests.cpp:: +PASSED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 0 == 0 +with message: + Testing if fib[2] (2) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[3] (3) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[4] (5) is even + +MiscTests.cpp:: +PASSED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 0 == 0 +with message: + Testing if fib[5] (8) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[6] (13) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[7] (21) is even + +A string sent directly to stdout +A string sent directly to stderr +------------------------------------------------------------------------------- +null strings +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( makeString( false ) != static_cast(nullptr) ) +with expansion: + "valid string" != {null string} + +MiscTests.cpp:: +PASSED: + REQUIRE( makeString( true ) == static_cast(nullptr) ) +with expansion: + {null string} == {null string} + +------------------------------------------------------------------------------- +checkedIf +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECKED_IF( flag ) +with expansion: + true + +MiscTests.cpp:: +PASSED: + REQUIRE( testCheckedIf( true ) ) +with expansion: + true + +------------------------------------------------------------------------------- +checkedIf, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_IF( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedIf( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +checkedElse +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECKED_ELSE( flag ) +with expansion: + true + +MiscTests.cpp:: +PASSED: + REQUIRE( testCheckedElse( true ) ) +with expansion: + true + +------------------------------------------------------------------------------- +checkedElse, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_ELSE( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedElse( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +xmlentitycheck + embedded xml +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +xmlentitycheck + encoded chars +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +send a single char to INFO +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( false ) +with message: + 3 + +------------------------------------------------------------------------------- +atomic if +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( x == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +String matchers +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "string" + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "abc" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "abc" + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "this" + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "substring" + +------------------------------------------------------------------------------- +Contains string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "not there" + +------------------------------------------------------------------------------- +StartsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "string" + +------------------------------------------------------------------------------- +EndsWith string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "this" + +------------------------------------------------------------------------------- +Equals string matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "something else" + +------------------------------------------------------------------------------- +Equals string matcher, with NULL +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE_THAT( "", Equals(nullptr) ) +with expansion: + "" equals: "" + +------------------------------------------------------------------------------- +AllOf matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" ) + +------------------------------------------------------------------------------- +AnyOf matcher +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "not there" ) + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "not there" or + contains: "string" ) + +------------------------------------------------------------------------------- +Equals +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "this string contains + 'abc' as a substring" + +------------------------------------------------------------------------------- +Matchers can be (AllOf) composed with the && operator +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" and contains: "substring" and contains: "contains" ) + +------------------------------------------------------------------------------- +Matchers can be (AnyOf) composed with the || operator +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "different" or contains: "random" ) + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "some completely different text that contains one common word" ( contains: + "string" or contains: "different" or contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "substring" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), !Contains( "different" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "different" + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + +------------------------------------------------------------------------------- +Factorials are computed +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(0) == 1 ) +with expansion: + 1 == 1 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(1) == 1 ) +with expansion: + 1 == 1 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(2) == 2 ) +with expansion: + 2 == 2 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(3) == 6 ) +with expansion: + 6 == 6 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(10) == 3628800 ) +with expansion: + 3628800 (0x) == 3628800 (0x) + +------------------------------------------------------------------------------- +Nice descriptive name +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +warning: + This one ran + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing bigger changes size and capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 10 ) +with expansion: + 10 == 10 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing smaller changes size but not capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing smaller changes size but not capacity + We can use the 'swap trick' to reset the capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + reserving bigger changes capacity but not size +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + reserving smaller does not change size or capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure + Outer + Inner +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + that's not flying - that's failing in style + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: +explicitly with message: + to infinity and beyond + +------------------------------------------------------------------------------- +not allowed +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +Tabs and newlines show in output +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( s1 == s2 ) +with expansion: + "if ($b == 10) { + $a= 20; + }" + == + "if ($b == 10) { + $a = 20; + } + " + +------------------------------------------------------------------------------- +toString on const wchar_t const pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on const wchar_t pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on wchar_t const pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on wchar_t returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +XmlEncode + normal string +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "normal string" ) == "normal string" ) +with expansion: + "normal string" == "normal string" + +------------------------------------------------------------------------------- +XmlEncode + empty string +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "" ) == "" ) +with expansion: + "" == "" + +------------------------------------------------------------------------------- +XmlEncode + string with ampersand +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith & jones" ) == "smith & jones" ) +with expansion: + "smith & jones" == "smith & jones" + +------------------------------------------------------------------------------- +XmlEncode + string with less-than +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith < jones" ) == "smith < jones" ) +with expansion: + "smith < jones" == "smith < jones" + +------------------------------------------------------------------------------- +XmlEncode + string with greater-than +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith > jones" ) == "smith > jones" ) +with expansion: + "smith > jones" == "smith > jones" + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ) +with expansion: + "smith ]]> jones" + == + "smith ]]> jones" + +------------------------------------------------------------------------------- +XmlEncode + string with quotes +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (1) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "[\x01]" ) == "[]" ) +with expansion: + "[]" == "[]" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (x7F) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "[\x7F]" ) == "[]" ) +with expansion: + "[]" == "[]" + +------------------------------------------------------------------------------- +long long +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( l == std::numeric_limits::max() ) +with expansion: + 9223372036854775807 (0x) + == + 9223372036854775807 (0x) + +------------------------------------------------------------------------------- +Process can be configured on command line + default - no arguments +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + CHECK( config.shouldDebugBreak == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + CHECK( config.abortAfter == -1 ) +with expansion: + -1 == -1 + +TestMain.cpp:: +PASSED: + CHECK( config.noThrow == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + CHECK( config.reporterNames.empty() ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + 1 test +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + Specify one test case exclusion using exclude: +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + Specify one test case exclusion using ~ +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r/console +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "console" ) +with expansion: + "console" == "console" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r/xml +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r xml and junit +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames.size() == 2 ) +with expansion: + 2 == 2 + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[1] == "junit" ) +with expansion: + "junit" == "junit" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + --reporter/junit +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "junit" ) +with expansion: + "junit" == "junit" + +------------------------------------------------------------------------------- +Process can be configured on command line + debugger + -b +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.shouldDebugBreak == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + debugger + --break +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.shouldDebugBreak ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -a aborts after first failure +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.abortAfter == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x 2 aborts after two failures +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.abortAfter == 2 ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x must be greater than zero +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ) +with expansion: + "Value after -x or --abortAfter must be greater than zero + - while parsing: (-x, --abortx )" contains: "greater than zero" + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x must be numeric +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ) +with expansion: + "Unable to convert oops to destination type + - while parsing: (-x, --abortx )" contains: "-x" + +------------------------------------------------------------------------------- +Process can be configured on command line + nothrow + -e +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + nothrow + --nothrow +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + output filename + -o filename +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.outputFilename == "filename.ext" ) +with expansion: + "filename.ext" == "filename.ext" + +------------------------------------------------------------------------------- +Process can be configured on command line + output filename + --out +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.outputFilename == "filename.ext" ) +with expansion: + "filename.ext" == "filename.ext" + +------------------------------------------------------------------------------- +Process can be configured on command line + combinations + Single character flags can be combined +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + CHECK( config.abortAfter == 1 ) +with expansion: + 1 == 1 + +TestMain.cpp:: +PASSED: + CHECK( config.shouldDebugBreak ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + force-colour + --force-colour +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.forceColour ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + force-colour + without --force-colour +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( !config.forceColour ) +with expansion: + true + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one two three four" + == + "one two three four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) +with expansion: + "one two three four" + == + "one two three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped once +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ) +with expansion: + "one two + three four" + == + "one two + three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped twice +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped three times +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Short wrap +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ) +with expansion: + "abc- + def" + == + "abc- + def" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ) +with expansion: + "abc- + defg" + == + "abc- + defg" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ) +with expansion: + "abc- + def- + gh" + == + "abc- + def- + gh" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ) +with expansion: + "one + two + thr- + ee + four" + == + "one + two + thr- + ee + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ) +with expansion: + "one + two + th- + ree + fo- + ur" + == + "one + two + th- + ree + fo- + ur" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + As container +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + REQUIRE( text.size() == 4 ) +with expansion: + 4 == 4 + +TestMain.cpp:: +PASSED: + CHECK( text[0] == "one" ) +with expansion: + "one" == "one" + +TestMain.cpp:: +PASSED: + CHECK( text[1] == "two" ) +with expansion: + "two" == "two" + +TestMain.cpp:: +PASSED: + CHECK( text[2] == "three" ) +with expansion: + "three" == "three" + +TestMain.cpp:: +PASSED: + CHECK( text[3] == "four" ) +with expansion: + "four" == "four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Indent first line differently +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( text.toString() == " one two\n three\n four" ) +with expansion: + " one two + three + four" + == + " one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Trailing newline +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" ) +with expansion: + "abcdef + " + == + "abcdef + " + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) +with expansion: + "abcdef" == "abcdef" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" ) +with expansion: + "abcdef + " + == + "abcdef + " + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Wrapped once +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Wrapped twice +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With tabs +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" ) +with expansion: + "one two three + four + five + six" + == + "one two three + four + five + six" + +------------------------------------------------------------------------------- +replaceInPlace + replace single char +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "b", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "azcdefcg" ) +with expansion: + "azcdefcg" == "azcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + replace two chars +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "c", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "abzdefzg" ) +with expansion: + "abzdefzg" == "abzdefzg" + +------------------------------------------------------------------------------- +replaceInPlace + replace first char +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "a", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "zbcdefcg" ) +with expansion: + "zbcdefcg" == "zbcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + replace last char +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "g", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "abcdefcz" ) +with expansion: + "abcdefcz" == "abcdefcz" + +------------------------------------------------------------------------------- +replaceInPlace + replace all chars +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, letters, "replaced" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "replaced" ) +with expansion: + "replaced" == "replaced" + +------------------------------------------------------------------------------- +replaceInPlace + replace no chars +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ) +with expansion: + !false + +TestMain.cpp:: +PASSED: + CHECK( letters == letters ) +with expansion: + "abcdefcg" == "abcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + escape ' +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( s, "'", "|'" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( s == "didn|'t" ) +with expansion: + "didn|'t" == "didn|'t" + +hello +hello +------------------------------------------------------------------------------- +Text can be formatted using the Text class +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( "hi there" ).toString() == "hi there" ) +with expansion: + "hi there" == "hi there" + +TestMain.cpp:: +PASSED: + CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ) +with expansion: + "hi + there" + == + "hi + there" + +------------------------------------------------------------------------------- +Long text is truncted +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ) +with expansion: + "***************************************************************************- + ***- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ +... message truncated due to excessive size + +------------------------------------------------------------------------------- +ManuallyRegistered +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: +with message: + was called + +------------------------------------------------------------------------------- +Parsing a std::pair +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( (std::pair( 1, 2 )) == aNicePair ) +with expansion: + std::pair( 1, 2 ) == std::pair( 1, 2 ) + +------------------------------------------------------------------------------- +Where there is more to the expression after the RHS +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +Where the LHS is not a simple value +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +A failing expression with a non streamable type is still captured +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + CHECK( &o1 == &o2 ) +with expansion: + 0x == 0x + +TrickyTests.cpp:: FAILED: + CHECK( o1 == o2 ) +with expansion: + {?} == {?} + +------------------------------------------------------------------------------- +string literals of different sizes can be compared +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + REQUIRE( std::string( "first" ) == "second" ) +with expansion: + "first" == "second" + +------------------------------------------------------------------------------- +An expression with side-effects should only be evaluated once +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( i++ == 7 ) +with expansion: + 7 == 7 + +TrickyTests.cpp:: +PASSED: + REQUIRE( i++ == 8 ) +with expansion: + 8 == 8 + +------------------------------------------------------------------------------- +Operators at different namespace levels not hijacked by Koenig lookup +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( 0x == o ) +with expansion: + 3221225472 (0x) == {?} + +------------------------------------------------------------------------------- +Demonstrate that a non-const == is not used +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( t == 1u ) +with expansion: + {?} == 1 + +------------------------------------------------------------------------------- +Test enum bit values +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( 0x == bit30and31 ) +with expansion: + 3221225472 (0x) == 3221225472 + +------------------------------------------------------------------------------- +boolean member +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( obj.prop != nullptr ) +with expansion: + 0x != nullptr + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + compare to true +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( is_true::value == true ) +with expansion: + true == true + +TrickyTests.cpp:: +PASSED: + REQUIRE( true == is_true::value ) +with expansion: + true == true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + compare to false +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( is_true::value == false ) +with expansion: + false == false + +TrickyTests.cpp:: +PASSED: + REQUIRE( false == is_true::value ) +with expansion: + false == false + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + negation +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( !is_true::value ) +with expansion: + true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + double negation +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( !!is_true::value ) +with expansion: + true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + direct +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( is_true::value ) +with expansion: + true + +TrickyTests.cpp:: +PASSED: + REQUIRE_FALSE( is_true::value ) +with expansion: + !false + +------------------------------------------------------------------------------- +Objects that evaluated in boolean contexts can be checked +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + CHECK( True ) +with expansion: + true + +TrickyTests.cpp:: +PASSED: + CHECK( !False ) +with expansion: + true + +TrickyTests.cpp:: +PASSED: + CHECK_FALSE( False ) +with expansion: + !false + +------------------------------------------------------------------------------- +Assertions then sections +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section + Another section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section + Another other section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +non streamable - with conv. op +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( s == "7" ) +with expansion: + "7" == "7" + +------------------------------------------------------------------------------- +Comparing function pointers +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( a ) +with expansion: + true + +TrickyTests.cpp:: +PASSED: + REQUIRE( a == &foo ) +with expansion: + 0x == 0x + +------------------------------------------------------------------------------- +Comparing member function pointers +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + CHECK( m == &S::f ) +with expansion: + 0x + == + 0x + +------------------------------------------------------------------------------- +pointer to class +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( p == 0 ) +with expansion: + NULL == 0 + +------------------------------------------------------------------------------- +null_ptr +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( ptr.get() == nullptr ) +with expansion: + NULL == nullptr + +------------------------------------------------------------------------------- +X/level/0/a +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +X/level/0/b +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +X/level/1/a +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +X/level/1/b +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +toString( has_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( Catch::toString( item ) == "toString( has_toString )" ) +with expansion: + "toString( has_toString )" + == + "toString( has_toString )" + +------------------------------------------------------------------------------- +toString( has_maker ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( Catch::toString( item ) == "StringMaker" ) +with expansion: + "StringMaker" + == + "StringMaker" + +------------------------------------------------------------------------------- +toString( has_maker_and_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" ) +with expansion: + "toString( has_maker_and_toString )" + == + "toString( has_maker_and_toString )" + +------------------------------------------------------------------------------- +toString( vectors +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( Catch::toString( v ) == "{ {?} }" ) +with expansion: + "{ {?} }" == "{ {?} }" + +------------------------------------------------------------------------------- +toString( vectors +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( Catch::toString( v ) == "{ StringMaker }" ) +with expansion: + "{ StringMaker }" + == + "{ StringMaker }" + +------------------------------------------------------------------------------- +toString( vectors +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( Catch::toString( v ) == "{ StringMaker }" ) +with expansion: + "{ StringMaker }" + == + "{ StringMaker }" + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section and find next section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + Successfully close S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + fail S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + open a nested section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +std::pair -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" ) +with expansion: + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + +------------------------------------------------------------------------------- +std::pair -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" ) +with expansion: + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + +------------------------------------------------------------------------------- +std::vector > -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" ) +with expansion: + "{ { "green", 55 } }" + == + "{ { "green", 55 } }" + +------------------------------------------------------------------------------- +pair > -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ) +with expansion: + "{ { 42, "Arthur" }, { "Ford", 24 } }" + == + "{ { 42, "Arthur" }, { "Ford", 24 } }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ \"hello\" }" ) +with expansion: + "{ "hello" }" == "{ "hello" }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + +------------------------------------------------------------------------------- +vec> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(v) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" ) +with expansion: + "{ { "hello" }, { "world" } }" + == + "{ { "hello" }, { "world" } }" + +------------------------------------------------------------------------------- +Parse test names and tags + Empty test spec should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from empty string should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches(tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from just a comma should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from quoted name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at the start +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at the end +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at both ends +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at the start +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at the end +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at both ends +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at both ends, redundant at start +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Just wildcard +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag, two matches +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Two tags +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Two tags, spare separated +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcarded name and tag +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion and one tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion and one wldcarded name inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion, using exclude:, and one wldcarded name inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + name exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion with tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion, using exclude:, with tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + two wildcarded names +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + empty tag +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + empty quoted name +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + quoted string followed by tag exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +tuple<> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ }" == Catch::toString(type{}) ) +with expansion: + "{ }" == "{ }" + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ }" == Catch::toString(value) ) +with expansion: + "{ }" == "{ }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 0 }" == Catch::toString(type{0}) ) +with expansion: + "{ 0 }" == "{ 0 }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "1.2f" == Catch::toString(float(1.2)) ) +with expansion: + "1.2f" == "1.2f" + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) ) +with expansion: + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +tuple,tuple<>,float> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ) +with expansion: + "{ { 42 }, { }, 1.2f }" + == + "{ { 42 }, { }, 1.2f }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ) +with expansion: + "{ nullptr, 42, "Catch me" }" + == + "{ nullptr, 42, "Catch me" }" + +------------------------------------------------------------------------------- +Tag alias can be registered against tag patterns + The same tag alias can only be registered once +------------------------------------------------------------------------------- +TagAliasTests.cpp: +............................................................................... + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "[@zzz]" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: " + [@zzz]" + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "file" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: + "file" + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "2" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: + "2" + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "10" ) ) +with expansion: + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: + "10" + +------------------------------------------------------------------------------- +Tag alias can be registered against tag patterns + Tag aliases must be of the form [@name] +------------------------------------------------------------------------------- +TagAliasTests.cpp: +............................................................................... + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +------------------------------------------------------------------------------- +Anonymous test case 1 +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp: +............................................................................... + +VariadicMacrosTests.cpp:: +PASSED: +with message: + anonymous test case + +------------------------------------------------------------------------------- +Test case with one argument +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp: +............................................................................... + +VariadicMacrosTests.cpp:: +PASSED: +with message: + no assertions + +------------------------------------------------------------------------------- +Variadic macros + Section with one argument +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp: +............................................................................... + +VariadicMacrosTests.cpp:: +PASSED: +with message: + no assertions + +------------------------------------------------------------------------------- +Scenario: Do that thing with the thing + Given: This stuff exists + When: I do this + Then: it should do this +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( itDoesThis() ) +with expansion: + true + +------------------------------------------------------------------------------- +Scenario: Do that thing with the thing + Given: This stuff exists + When: I do this + Then: it should do this + And: do that +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( itDoesThat() ) +with expansion: + true + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: it is made larger + Then: the size and capacity go up +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 10 ) +with expansion: + 10 == 10 + +BDDTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: it is made larger + Then: the size and capacity go up + And when: it is made smaller again + Then: the size goes down but the capacity stays the same +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +BDDTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: we reserve more space + Then: The capacity is increased but the size remains the same +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: This is a really long scenario name to see how the list command deals + with wrapping + Given: A section name that is so long that it cannot fit in a single + console width + When: The test headers are printed as part of the normal running of the + scenario + Then: The, deliberately very long and overly verbose (you see what I did + there?) section names must wrap, along with an indent +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: +with message: + boo! + +------------------------------------------------------------------------------- +Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or + methods + Given: No operations precede me +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( before == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or + methods + Given: No operations precede me + When: We get the count + Then: Subsequently values are higher +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( after > before ) +with expansion: + 1 > 0 + +=============================================================================== +test cases: 167 | 123 passed | 43 failed | 1 failed as expected +assertions: 916 | 818 passed | 85 failed | 13 failed as expected + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt new file mode 100644 index 00000000000..0793f1d1eed --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -0,0 +1,491 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CatchSelfTest is a host application. +Run with -? for options + +------------------------------------------------------------------------------- +toString(enum) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "E2{0}" ) +with expansion: + "E2{0}" == "E2{0}" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "E2{1}" ) +with expansion: + "E2{1}" == "E2{1}" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +toString(enum class w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e0) == "E2/V0" ) +with expansion: + "E2/V0" == "E2/V0" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e1) == "E2/V1" ) +with expansion: + "E2/V1" == "E2/V1" + +EnumToString.cpp:: +PASSED: + CHECK( Catch::toString(e3) == "Unknown enum value 10" ) +with expansion: + "Unknown enum value 10" + == + "Unknown enum value 10" + +------------------------------------------------------------------------------- +Some simple comparisons between doubles +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == Approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.22 ) ) +with expansion: + 1.23 != Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.24 ) ) +with expansion: + 1.23 != Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) != 1.22 ) +with expansion: + Approx( 1.23 ) != 1.22 + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) != 1.24 ) +with expansion: + Approx( 1.23 ) != 1.24 + +------------------------------------------------------------------------------- +Approximate comparisons with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.231 ) ) +with expansion: + 1.23 != Approx( 1.231 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ) +with expansion: + 1.23 == Approx( 1.231 ) + +------------------------------------------------------------------------------- +Approximate comparisons with floats +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.23f == Approx( 1.23f ) ) +with expansion: + 1.23f == Approx( 1.2300000191 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0.0f == Approx( 0.0f ) ) +with expansion: + 0.0f == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with ints +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1 == Approx( 1 ) ) +with expansion: + 1 == Approx( 1.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( 0 ) ) +with expansion: + 0 == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with mixed numeric types +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.0f == Approx( 1 ) ) +with expansion: + 1.0f == Approx( 1.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( dZero) ) +with expansion: + 0 == Approx( 0.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) +with expansion: + 0 == Approx( 0.00001 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.234f == Approx( dMedium ) ) +with expansion: + 1.234f == Approx( 1.234 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( dMedium == Approx( 1.234f ) ) +with expansion: + 1.234 == Approx( 1.2339999676 ) + +------------------------------------------------------------------------------- +Use a custom approx +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.22 ) ) +with expansion: + 1.23 == Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.24 ) ) +with expansion: + 1.23 == Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != approx( 1.25 ) ) +with expansion: + 1.23 != Approx( 1.25 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.22 ) +with expansion: + Approx( 1.23 ) == 1.22 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.24 ) +with expansion: + Approx( 1.23 ) == 1.24 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) != 1.25 ) +with expansion: + Approx( 1.23 ) != 1.25 + +------------------------------------------------------------------------------- +Approximate PI +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ) +with expansion: + 3.1428571429 == Approx( 3.141 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ) +with expansion: + 3.1428571429 != Approx( 3.141 ) + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: +PASSED: + REQUIRE( m_a == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +Equality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven == 7 ) +with expansion: + 7 == 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ) +with expansion: + 9.1f == Approx( 9.1000003815 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415926535 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello == "hello" ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( "hello" == data.str_hello ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello.size() == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( x == Approx( 1.3 ) ) +with expansion: + 1.3 == Approx( 1.3 ) + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +------------------------------------------------------------------------------- +Inequality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven != 6 ) +with expansion: + 7 != 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven != 8 ) +with expansion: + 7 != 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ) +with expansion: + 9.1f != Approx( 9.1099996567 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ) +with expansion: + 9.1f != Approx( 9.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 1 ) ) +with expansion: + 9.1f != Approx( 1.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 0 ) ) +with expansion: + 9.1f != Approx( 0.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.double_pi != Approx( 3.1415 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "goodbye" ) +with expansion: + "hello" != "goodbye" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "hell" ) +with expansion: + "hello" != "hell" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "hello1" ) +with expansion: + "hello" != "hello1" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello.size() != 6 ) +with expansion: + 5 != 6 + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +=============================================================================== +test cases: 19 | 15 passed | 3 failed | 1 failed as expected +assertions: 62 | 56 passed | 4 failed | 2 failed as expected + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt new file mode 100644 index 00000000000..18792059a7e --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -0,0 +1,684 @@ + + + + + + + + + + + + + + + + +ClassTests.cpp: + + + + + +ClassTests.cpp: + + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + + + + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + +expected exception +ExceptionTests.cpp: + + +ExceptionTests.cpp: + + +expected exception +ExceptionTests.cpp: + + + + +unexpected exception +ExceptionTests.cpp: + + + + +unexpected exception +ExceptionTests.cpp: + + + + +unexpected exception +ExceptionTests.cpp: + + + + +expected exception +ExceptionTests.cpp: + + + + +expected exception +ExceptionTests.cpp: + + + + +expected exception +ExceptionTests.cpp: + + + + +custom exception +ExceptionTests.cpp: + + + + +custom std exception +ExceptionTests.cpp: + + + + +custom exception - not std +ExceptionTests.cpp: + + + + +custom exception - not std +ExceptionTests.cpp: + + + + +3.14 +ExceptionTests.cpp: + + + + + + + + +ExceptionTests.cpp: + + + + + + + + +this message should be logged +so should this +MessageTests.cpp: + + + + +this message should be logged +MessageTests.cpp: + + +and this, but later +MessageTests.cpp: + + + + +This is a failure +MessageTests.cpp: + + + + +MessageTests.cpp: + + + + + +Message from section one +MessageTests.cpp: + + + + +Message from section two +MessageTests.cpp: + + + + +Message from section one +Message from section two + + + + +current counter 10 +i := 10 +MessageTests.cpp: + + + + + +Previous info should not be seen +MessageTests.cpp: + + + + +hi +i := 7 +MessageTests.cpp: + + + + + + + + + +MiscTests.cpp: + + + + + + + + + +MiscTests.cpp: + + + + +Testing if fib[0] (1) is even +MiscTests.cpp: + + +Testing if fib[1] (1) is even +MiscTests.cpp: + + +Testing if fib[3] (3) is even +MiscTests.cpp: + + +Testing if fib[4] (5) is even +MiscTests.cpp: + + +Testing if fib[6] (13) is even +MiscTests.cpp: + + +Testing if fib[7] (21) is even +MiscTests.cpp: + + + + +A string sent directly to stdout + + +A string sent directly to stderr + + + + + + +MiscTests.cpp: + + +MiscTests.cpp: + + + + + +MiscTests.cpp: + + +MiscTests.cpp: + + + + + + +3 +MiscTests.cpp: + + + + + + +MiscTests.cpp: + + + + +MiscTests.cpp: + + + + +MiscTests.cpp: + + + + +MiscTests.cpp: + + + + + + + + + + + +MiscTests.cpp: + + + + + +MiscTests.cpp: + + + + + + + + + + + + +to infinity and beyond +MiscTests.cpp: + + + + + + +MiscTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +hello +hello + + + + + + + + + + +TrickyTests.cpp: + + +TrickyTests.cpp: + + + + +TrickyTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Message from section one +Message from section two +A string sent directly to stdout +hello +hello + + +A string sent directly to stderr + + + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt new file mode 100644 index 00000000000..e88e47ebc35 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -0,0 +1,9511 @@ + + + + + + Catch::toString(e0) == "0" + + + "0" == "0" + + + + + Catch::toString(e1) == "1" + + + "1" == "1" + + + + + + + + Catch::toString(e0) == "E2{0}" + + + "E2{0}" == "E2{0}" + + + + + Catch::toString(e1) == "E2{1}" + + + "E2{1}" == "E2{1}" + + + + + + + + Catch::toString(e0) == "0" + + + "0" == "0" + + + + + Catch::toString(e1) == "1" + + + "1" == "1" + + + + + + + + Catch::toString(e0) == "E2/V0" + + + "E2/V0" == "E2/V0" + + + + + Catch::toString(e1) == "E2/V1" + + + "E2/V1" == "E2/V1" + + + + + Catch::toString(e3) == "Unknown enum value 10" + + + "Unknown enum value 10" +== +"Unknown enum value 10" + + + + + + + + d == Approx( 1.23 ) + + + 1.23 == Approx( 1.23 ) + + + + + d != Approx( 1.22 ) + + + 1.23 != Approx( 1.22 ) + + + + + d != Approx( 1.24 ) + + + 1.23 != Approx( 1.24 ) + + + + + Approx( d ) == 1.23 + + + Approx( 1.23 ) == 1.23 + + + + + Approx( d ) != 1.22 + + + Approx( 1.23 ) != 1.22 + + + + + Approx( d ) != 1.24 + + + Approx( 1.23 ) != 1.24 + + + + + + + + d != Approx( 1.231 ) + + + 1.23 != Approx( 1.231 ) + + + + + d == Approx( 1.231 ).epsilon( 0.1 ) + + + 1.23 == Approx( 1.231 ) + + + + + + + + 1.23f == Approx( 1.23f ) + + + 1.23f == Approx( 1.2300000191 ) + + + + + 0.0f == Approx( 0.0f ) + + + 0.0f == Approx( 0.0 ) + + + + + + + + 1 == Approx( 1 ) + + + 1 == Approx( 1.0 ) + + + + + 0 == Approx( 0 ) + + + 0 == Approx( 0.0 ) + + + + + + + + 1.0f == Approx( 1 ) + + + 1.0f == Approx( 1.0 ) + + + + + 0 == Approx( dZero) + + + 0 == Approx( 0.0 ) + + + + + 0 == Approx( dSmall ).epsilon( 0.001 ) + + + 0 == Approx( 0.00001 ) + + + + + 1.234f == Approx( dMedium ) + + + 1.234f == Approx( 1.234 ) + + + + + dMedium == Approx( 1.234f ) + + + 1.234 == Approx( 1.2339999676 ) + + + + + + + + d == approx( 1.23 ) + + + 1.23 == Approx( 1.23 ) + + + + + d == approx( 1.22 ) + + + 1.23 == Approx( 1.22 ) + + + + + d == approx( 1.24 ) + + + 1.23 == Approx( 1.24 ) + + + + + d != approx( 1.25 ) + + + 1.23 != Approx( 1.25 ) + + + + + approx( d ) == 1.23 + + + Approx( 1.23 ) == 1.23 + + + + + approx( d ) == 1.22 + + + Approx( 1.23 ) == 1.22 + + + + + approx( d ) == 1.24 + + + Approx( 1.23 ) == 1.24 + + + + + approx( d ) != 1.25 + + + Approx( 1.23 ) != 1.25 + + + + + + + + divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) + + + 3.1428571429 == Approx( 3.141 ) + + + + + divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) + + + 3.1428571429 != Approx( 3.141 ) + + + + + + + + s == "hello" + + + "hello" == "hello" + + + + + + + + s == "world" + + + "hello" == "world" + + + + + + + + m_a == 1 + + + 1 == 1 + + + + + + + + m_a == 2 + + + 1 == 2 + + + + + + + + data.int_seven == 7 + + + 7 == 7 + + + + + data.float_nine_point_one == Approx( 9.1f ) + + + 9.1f == Approx( 9.1000003815 ) + + + + + data.double_pi == Approx( 3.1415926535 ) + + + 3.1415926535 == Approx( 3.1415926535 ) + + + + + data.str_hello == "hello" + + + "hello" == "hello" + + + + + "hello" == data.str_hello + + + "hello" == "hello" + + + + + data.str_hello.size() == 5 + + + 5 == 5 + + + + + x == Approx( 1.3 ) + + + 1.3 == Approx( 1.3 ) + + + + + + + + data.int_seven == 6 + + + 7 == 6 + + + + + data.int_seven == 8 + + + 7 == 8 + + + + + data.int_seven == 0 + + + 7 == 0 + + + + + data.float_nine_point_one == Approx( 9.11f ) + + + 9.1f == Approx( 9.1099996567 ) + + + + + data.float_nine_point_one == Approx( 9.0f ) + + + 9.1f == Approx( 9.0 ) + + + + + data.float_nine_point_one == Approx( 1 ) + + + 9.1f == Approx( 1.0 ) + + + + + data.float_nine_point_one == Approx( 0 ) + + + 9.1f == Approx( 0.0 ) + + + + + data.double_pi == Approx( 3.1415 ) + + + 3.1415926535 == Approx( 3.1415 ) + + + + + data.str_hello == "goodbye" + + + "hello" == "goodbye" + + + + + data.str_hello == "hell" + + + "hello" == "hell" + + + + + data.str_hello == "hello1" + + + "hello" == "hello1" + + + + + data.str_hello.size() == 6 + + + 5 == 6 + + + + + x == Approx( 1.301 ) + + + 1.3 == Approx( 1.301 ) + + + + + + + + data.int_seven != 6 + + + 7 != 6 + + + + + data.int_seven != 8 + + + 7 != 8 + + + + + data.float_nine_point_one != Approx( 9.11f ) + + + 9.1f != Approx( 9.1099996567 ) + + + + + data.float_nine_point_one != Approx( 9.0f ) + + + 9.1f != Approx( 9.0 ) + + + + + data.float_nine_point_one != Approx( 1 ) + + + 9.1f != Approx( 1.0 ) + + + + + data.float_nine_point_one != Approx( 0 ) + + + 9.1f != Approx( 0.0 ) + + + + + data.double_pi != Approx( 3.1415 ) + + + 3.1415926535 != Approx( 3.1415 ) + + + + + data.str_hello != "goodbye" + + + "hello" != "goodbye" + + + + + data.str_hello != "hell" + + + "hello" != "hell" + + + + + data.str_hello != "hello1" + + + "hello" != "hello1" + + + + + data.str_hello.size() != 6 + + + 5 != 6 + + + + + + + + data.int_seven != 7 + + + 7 != 7 + + + + + data.float_nine_point_one != Approx( 9.1f ) + + + 9.1f != Approx( 9.1000003815 ) + + + + + data.double_pi != Approx( 3.1415926535 ) + + + 3.1415926535 != Approx( 3.1415926535 ) + + + + + data.str_hello != "hello" + + + "hello" != "hello" + + + + + data.str_hello.size() != 5 + + + 5 != 5 + + + + + + + + data.int_seven < 8 + + + 7 < 8 + + + + + data.int_seven > 6 + + + 7 > 6 + + + + + data.int_seven > 0 + + + 7 > 0 + + + + + data.int_seven > -1 + + + 7 > -1 + + + + + data.int_seven >= 7 + + + 7 >= 7 + + + + + data.int_seven >= 6 + + + 7 >= 6 + + + + + data.int_seven <= 7 + + + 7 <= 7 + + + + + data.int_seven <= 8 + + + 7 <= 8 + + + + + data.float_nine_point_one > 9 + + + 9.1f > 9 + + + + + data.float_nine_point_one < 10 + + + 9.1f < 10 + + + + + data.float_nine_point_one < 9.2 + + + 9.1f < 9.2 + + + + + data.str_hello <= "hello" + + + "hello" <= "hello" + + + + + data.str_hello >= "hello" + + + "hello" >= "hello" + + + + + data.str_hello < "hellp" + + + "hello" < "hellp" + + + + + data.str_hello < "zebra" + + + "hello" < "zebra" + + + + + data.str_hello > "hellm" + + + "hello" > "hellm" + + + + + data.str_hello > "a" + + + "hello" > "a" + + + + + + + + data.int_seven > 7 + + + 7 > 7 + + + + + data.int_seven < 7 + + + 7 < 7 + + + + + data.int_seven > 8 + + + 7 > 8 + + + + + data.int_seven < 6 + + + 7 < 6 + + + + + data.int_seven < 0 + + + 7 < 0 + + + + + data.int_seven < -1 + + + 7 < -1 + + + + + data.int_seven >= 8 + + + 7 >= 8 + + + + + data.int_seven <= 6 + + + 7 <= 6 + + + + + data.float_nine_point_one < 9 + + + 9.1f < 9 + + + + + data.float_nine_point_one > 10 + + + 9.1f > 10 + + + + + data.float_nine_point_one > 9.2 + + + 9.1f > 9.2 + + + + + data.str_hello > "hello" + + + "hello" > "hello" + + + + + data.str_hello < "hello" + + + "hello" < "hello" + + + + + data.str_hello > "hellp" + + + "hello" > "hellp" + + + + + data.str_hello > "z" + + + "hello" > "z" + + + + + data.str_hello < "hellm" + + + "hello" < "hellm" + + + + + data.str_hello < "a" + + + "hello" < "a" + + + + + data.str_hello >= "z" + + + "hello" >= "z" + + + + + data.str_hello <= "a" + + + "hello" <= "a" + + + + + + + + i == 1 + + + 1 == 1 + + + + + ui == 2 + + + 2 == 2 + + + + + l == 3 + + + 3 == 3 + + + + + ul == 4 + + + 4 == 4 + + + + + c == 5 + + + 5 == 5 + + + + + uc == 6 + + + 6 == 6 + + + + + 1 == i + + + 1 == 1 + + + + + 2 == ui + + + 2 == 2 + + + + + 3 == l + + + 3 == 3 + + + + + 4 == ul + + + 4 == 4 + + + + + 5 == c + + + 5 == 5 + + + + + 6 == uc + + + 6 == 6 + + + + + (std::numeric_limits<unsigned long>::max)() > ul + + + 18446744073709551615 (0x) +> +4 + + + + + + + + long_var == unsigned_char_var + + + 1 == 1 + + + + + long_var == unsigned_short_var + + + 1 == 1 + + + + + long_var == unsigned_int_var + + + 1 == 1 + + + + + long_var == unsigned_long_var + + + 1 == 1 + + + + + + + + unsigned_char_var == 1 + + + 1 == 1 + + + + + unsigned_short_var == 1 + + + 1 == 1 + + + + + unsigned_int_var == 1 + + + 1 == 1 + + + + + unsigned_long_var == 1 + + + 1 == 1 + + + + + + + + ( -1 > 2u ) + + + true + + + + + -1 > 2u + + + -1 > 2 + + + + + ( 2u < -1 ) + + + true + + + + + 2u < -1 + + + 2 < -1 + + + + + ( minInt > 2u ) + + + true + + + + + minInt > 2u + + + -2147483648 > 2 + + + + + + + + 54 == 6*9 + + + 54 == 54 + + + + + + + + p == nullptr + + + NULL == nullptr + + + + + p == pNULL + + + NULL == NULL + + + + + p != nullptr + + + 0x != nullptr + + + + + cp != nullptr + + + 0x != nullptr + + + + + cpc != nullptr + + + 0x != nullptr + + + + + returnsNull() == nullptr + + + {null string} == nullptr + + + + + returnsConstNull() == nullptr + + + {null string} == nullptr + + + + + nullptr != p + + + nullptr != 0x + + + + + + + + false == false + + + false == false + + + + + true == true + + + true == true + + + + + !false + + + true + + + + + !false + + + !false + + + + + !falseValue + + + true + + + + + !falseValue + + + !false + + + + + !(1 == 2) + + + true + + + + + !1 == 2 + + + !(1 == 2) + + + + + + + + false != false + + + false != false + + + + + true != true + + + true != true + + + + + !true + + + false + + + + + !true + + + !true + + + + + !trueValue + + + false + + + + + !trueValue + + + !true + + + + + !(1 == 1) + + + false + + + + + !1 == 1 + + + !(1 == 1) + + + + + + + + thisThrows() + + + thisThrows() + + + + + thisDoesntThrow() + + + thisDoesntThrow() + + + + + thisThrows() + + + thisThrows() + + + + + + + + thisThrows() + + + thisThrows() + + + expected exception + + + + + thisDoesntThrow() + + + thisDoesntThrow() + + + + + thisThrows() + + + thisThrows() + + + expected exception + + + + + + + unexpected exception + + + + + + + 1 == 1 + + + 1 == 1 + + + + + {Unknown expression after the reported line} + + + {Unknown expression after the reported line} + + + unexpected exception + + + + + +
+ + unexpected exception + + +
+ +
+ + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + + + custom exception + + + + + + custom std exception + + + + + + + throwCustom() + + + throwCustom() + + + custom exception - not std + + + + + + + + throwCustom() + + + throwCustom() + + + custom exception - not std + + + + + + + 3.14 + + + + + + + thisFunctionNotImplemented( 7 ) + + + thisFunctionNotImplemented( 7 ) + + + + + +
+ + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + +
+
+ + + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + + + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + + + +
+
+ + + thisThrows(), StartsWith( "expected" ) + + + thisThrows(), StartsWith( "expected" ) + + + + + thisThrows(), EndsWith( "exception" ) + + + thisThrows(), EndsWith( "exception" ) + + + + + thisThrows(), Contains( "except" ) + + + thisThrows(), Contains( "except" ) + + + + + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + + + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + + + +
+ +
+ + + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + + + thisThrows(), "should fail" + + + expected exception + + + + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 200 == 200 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 202 == 202 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 204 == 204 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 206 == 206 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 208 == 208 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 210 == 210 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 212 == 212 + + + + + multiply( i, 2 ) == i*2 + + + 2 == 2 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 4 == 4 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 6 == 6 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 8 == 8 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 10 == 10 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 30 == 30 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 40 == 40 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 42 == 42 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + multiply( i, 2 ) == i*2 + + + 72 == 72 + + + + + multiply( j, 2 ) == j*2 + + + 214 == 214 + + + + + + + + i->first == i->second-1 + + + 0 == 0 + + + + + i->first == i->second-1 + + + 2 == 2 + + + + + + + this is a message + + + this is a warning + + + + + + + + + this message should be logged + + + so should this + + + + a == 1 + + + 2 == 1 + + + + + + + + a == 2 + + + 2 == 2 + + + + this message should be logged + + + + a == 1 + + + 2 == 1 + + + + and this, but later + + + + a == 0 + + + 2 == 0 + + + + + a == 2 + + + 2 == 2 + + + + + + + This is a failure + + + + + + + + + + + +
+ + Message from section one + + +
+
+ + Message from section two + + +
+ +
+ +
+ +
+
+ +
+ +
+ + + + i < 10 + + + 0 < 10 + + + + + i < 10 + + + 1 < 10 + + + + + i < 10 + + + 2 < 10 + + + + + i < 10 + + + 3 < 10 + + + + + i < 10 + + + 4 < 10 + + + + + i < 10 + + + 5 < 10 + + + + + i < 10 + + + 6 < 10 + + + + + i < 10 + + + 7 < 10 + + + + + i < 10 + + + 8 < 10 + + + + + i < 10 + + + 9 < 10 + + + + current counter 10 + + + i := 10 + + + + i < 10 + + + 10 < 10 + + + + + + + + 1 == 2 + + + 1 == 2 + + + + + + + + + + Previous info should not be seen + + + + + + hi + + + i := 7 + + + + false + + + false + + + + + + + actual address of p: 0x + + + toString(p): 0x + + + + +
+ + + a != b + + + 1 != 2 + + + + + b != a + + + 2 != 1 + + + +
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+ +
+ + + a != b + + + 1 != 2 + + + + + b != a + + + 2 != 1 + + +
+ + + a != b + + + 1 != 2 + + + +
+ +
+ +
+ +
+
+ + + a == b + + + 1 == 2 + + + +
+ +
+
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+
+
+ + + a < b + + + 1 < 2 + + + +
+ +
+ +
+ +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ +
+ + + b > a + + + 0 > 1 + + + +
+ +
+ + + Testing if fib[0] (1) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[1] (1) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + + ( fib[i] % 2 ) == 0 + + + 0 == 0 + + + + Testing if fib[3] (3) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[4] (5) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + + ( fib[i] % 2 ) == 0 + + + 0 == 0 + + + + Testing if fib[6] (13) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[7] (21) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + + + + + + + + makeString( false ) != static_cast<char*>(nullptr) + + + "valid string" != {null string} + + + + + makeString( true ) == static_cast<char*>(nullptr) + + + {null string} == {null string} + + + + + + + + flag + + + true + + + + + testCheckedIf( true ) + + + true + + + + + + + + flag + + + false + + + + + testCheckedIf( false ) + + + false + + + + + + + + flag + + + true + + + + + testCheckedElse( true ) + + + true + + + + + + + + flag + + + false + + + + + testCheckedElse( false ) + + + false + + + + + +
+ +
+
+ +
+ +
+ + + 3 + + + + false + + + false + + + + + + + + x == 0 + + + 0 == 0 + + + + + + + + testStringForMatching(), Contains( "string" ) + + + "this string contains 'abc' as a substring" contains: "string" + + + + + testStringForMatching(), Contains( "abc" ) + + + "this string contains 'abc' as a substring" contains: "abc" + + + + + testStringForMatching(), StartsWith( "this" ) + + + "this string contains 'abc' as a substring" starts with: "this" + + + + + testStringForMatching(), EndsWith( "substring" ) + + + "this string contains 'abc' as a substring" ends with: "substring" + + + + + + + + testStringForMatching(), Contains( "not there" ) + + + "this string contains 'abc' as a substring" contains: "not there" + + + + + + + + testStringForMatching(), StartsWith( "string" ) + + + "this string contains 'abc' as a substring" starts with: "string" + + + + + + + + testStringForMatching(), EndsWith( "this" ) + + + "this string contains 'abc' as a substring" ends with: "this" + + + + + + + + testStringForMatching(), Equals( "something else" ) + + + "this string contains 'abc' as a substring" equals: "something else" + + + + + + + + "", Equals(nullptr) + + + "" equals: "" + + + + + + + + testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) + + + + + + + + testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) + + + + + testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) + + + "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) + + + + + + + + testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) + + + "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" + + + + + + + + testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) + + + + + + + + testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + + + + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) + + + + + + + + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) + + + + + + + + testStringForMatching(), !Contains( "different" ) + + + "this string contains 'abc' as a substring" not contains: "different" + + + + + + + + testStringForMatching(), !Contains( "substring" ) + + + "this string contains 'abc' as a substring" not contains: "substring" + + + + + + + + Factorial(0) == 1 + + + 1 == 1 + + + + + Factorial(1) == 1 + + + 1 == 1 + + + + + Factorial(2) == 2 + + + 2 == 2 + + + + + Factorial(3) == 6 + + + 6 == 6 + + + + + Factorial(10) == 3628800 + + + 3628800 (0x) == 3628800 (0x) + + + + + + + + + + This one ran + + + + + + + + + + + + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 10 + + + 10 == 10 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 0 + + + 0 == 0 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.capacity() == 0 + + + 0 == 0 + + + +
+ +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + + +
+ +
+ +
+
+ +
+ +
+ + to infinity and beyond + + +
+ + + + + + + s1 == s2 + + + "if ($b == 10) { + $a = 20; +}" +== +"if ($b == 10) { + $a = 20; +} +" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + +
+ + + encode( "normal string" ) == "normal string" + + + "normal string" == "normal string" + + + +
+
+ + + encode( "" ) == "" + + + "" == "" + + + +
+
+ + + encode( "smith & jones" ) == "smith &amp; jones" + + + "smith &amp; jones" == "smith &amp; jones" + + + +
+
+ + + encode( "smith < jones" ) == "smith &lt; jones" + + + "smith &lt; jones" == "smith &lt; jones" + + + +
+
+ + + encode( "smith > jones" ) == "smith > jones" + + + "smith > jones" == "smith > jones" + + + + + encode( "smith ]]> jones" ) == "smith ]]&gt; jones" + + + "smith ]]&gt; jones" +== +"smith ]]&gt; jones" + + + +
+
+ + + encode( stringWithQuotes ) == stringWithQuotes + + + "don't "quote" me on that" +== +"don't "quote" me on that" + + + + + encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" + + + "don't &quot;quote&quot; me on that" +== +"don't &quot;quote&quot; me on that" + + + +
+
+ + + encode( "[\x01]" ) == "[&#x1]" + + + "[&#x1]" == "[&#x1]" + + + +
+
+ + + encode( "[\x7F]" ) == "[&#x7F]" + + + "[&#x7F]" == "[&#x7F]" + + + +
+ +
+ + + + l == std::numeric_limits<long long>::max() + + + 9223372036854775807 (0x) +== +9223372036854775807 (0x) + + + + + +
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.shouldDebugBreak == false + + + false == false + + + + + config.abortAfter == -1 + + + -1 == -1 + + + + + config.noThrow == false + + + false == false + + + + + config.reporterNames.empty() + + + true + + + +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false + + + false == false + + + + + cfg.testSpec().matches( fakeTestCase( "test1" ) ) + + + true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + + + false == false + + + + + cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + + + true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + + + false == false + + + + + cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + + + true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.reporterNames[0] == "console" + + + "console" == "console" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.reporterNames.size() == 2 + + + 2 == 2 + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + + + config.reporterNames[1] == "junit" + + + "junit" == "junit" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.reporterNames[0] == "junit" + + + "junit" == "junit" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.shouldDebugBreak == true + + + true == true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.shouldDebugBreak + + + true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.abortAfter == 1 + + + 1 == 1 + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.abortAfter == 2 + + + 2 == 2 + + + +
+ +
+
+
+ + + parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) + + + "Value after -x or --abortAfter must be greater than zero +- while parsing: (-x, --abortx <no. failures>)" contains: "greater than zero" + + + +
+ +
+
+
+ + + parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) + + + "Unable to convert oops to destination type +- while parsing: (-x, --abortx <no. failures>)" contains: "-x" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.noThrow == true + + + true == true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.noThrow == true + + + true == true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.outputFilename == "filename.ext" + + + "filename.ext" == "filename.ext" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.outputFilename == "filename.ext" + + + "filename.ext" == "filename.ext" + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.abortAfter == 1 + + + 1 == 1 + + + + + config.shouldDebugBreak + + + true + + + + + config.noThrow == true + + + true == true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.forceColour + + + true + + + +
+ +
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + !config.forceColour + + + true + + + +
+ +
+ +
+ +
+
+ + + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + + + "one two three four" +== +"one two three four" + + + + + Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString + + + "one two three four" +== +"one two three four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" + + + "one two +three four" +== +"one two +three four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + + + "one +two +three +four" +== +"one +two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" + + + "one +two +three +four" +== +"one +two +three +four" + + + +
+ +
+
+
+ + + Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" + + + "abc- +def" +== +"abc- +def" + + + + + Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" + + + "abc- +defg" +== +"abc- +defg" + + + + + Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" + + + "abc- +def- +gh" +== +"abc- +def- +gh" + + + + + Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" + + + "one +two +thr- +ee +four" +== +"one +two +thr- +ee +four" + + + + + Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" + + + "one +two +th- +ree +fo- +ur" +== +"one +two +th- +ree +fo- +ur" + + + +
+ +
+
+
+ + + text.size() == 4 + + + 4 == 4 + + + + + text[0] == "one" + + + "one" == "one" + + + + + text[1] == "two" + + + "two" == "two" + + + + + text[2] == "three" + + + "three" == "three" + + + + + text[3] == "four" + + + "four" == "four" + + + +
+ +
+
+
+ + + text.toString() == " one two\n three\n four" + + + " one two + three + four" +== +" one two + three + four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + + + "one two +three four" +== +"one two +three four" + + + + + Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString + + + "one two +three four" +== +"one two +three four" + + + + + Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString + + + "one two +three four" +== +"one two +three four" + + + +
+ +
+
+
+ + + Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" + + + "abcdef +" +== +"abcdef +" + + + + + Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" + + + "abcdef" == "abcdef" + + + + + Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" + + + "abcdef +" +== +"abcdef +" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + + + "one +two +three +four" +== +"one +two +three +four" + + + +
+ +
+
+ + + Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" + + + "one two three + four + five + six" +== +"one two three + four + five + six" + + + +
+ +
+ +
+ + + replaceInPlace( letters, "b", "z" ) + + + true + + + + + letters == "azcdefcg" + + + "azcdefcg" == "azcdefcg" + + + +
+
+ + + replaceInPlace( letters, "c", "z" ) + + + true + + + + + letters == "abzdefzg" + + + "abzdefzg" == "abzdefzg" + + + +
+
+ + + replaceInPlace( letters, "a", "z" ) + + + true + + + + + letters == "zbcdefcg" + + + "zbcdefcg" == "zbcdefcg" + + + +
+
+ + + replaceInPlace( letters, "g", "z" ) + + + true + + + + + letters == "abcdefcz" + + + "abcdefcz" == "abcdefcz" + + + +
+
+ + + replaceInPlace( letters, letters, "replaced" ) + + + true + + + + + letters == "replaced" + + + "replaced" == "replaced" + + + +
+
+ + + !replaceInPlace( letters, "x", "z" ) + + + !false + + + + + letters == letters + + + "abcdefcg" == "abcdefcg" + + + +
+
+ + + replaceInPlace( s, "'", "|'" ) + + + true + + + + + s == "didn|'t" + + + "didn|'t" == "didn|'t" + + + +
+ +
+ + + + + + + Text( "hi there" ).toString() == "hi there" + + + "hi there" == "hi there" + + + + + Text( "hi there", narrow ).toString() == "hi\nthere" + + + "hi +there" +== +"hi +there" + + + + + + + + t.toString(), EndsWith( "... message truncated due to excessive size" ) + + + "******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +... message truncated due to excessive size" ends with: "... message truncated due to excessive size" + + + + + + + + + + + (std::pair<int, int>( 1, 2 )) == aNicePair + + + std::pair( 1, 2 ) == std::pair( 1, 2 ) + + + + + + + Uncomment the code in this test to check that it gives a sensible compiler error + + + + + + Uncomment the code in this test to check that it gives a sensible compiler error + + + + + + + &o1 == &o2 + + + 0x == 0x + + + + + o1 == o2 + + + {?} == {?} + + + + + + + + std::string( "first" ) == "second" + + + "first" == "second" + + + + + + + + i++ == 7 + + + 7 == 7 + + + + + i++ == 8 + + + 8 == 8 + + + + + + + + 0x == o + + + 3221225472 (0x) == {?} + + + + + + + + t == 1u + + + {?} == 1 + + + + + + + + 0x == bit30and31 + + + 3221225472 (0x) == 3221225472 + + + + + + + + obj.prop != nullptr + + + 0x != nullptr + + + + + +
+ + + is_true<true>::value == true + + + true == true + + + + + true == is_true<true>::value + + + true == true + + + +
+
+ + + is_true<false>::value == false + + + false == false + + + + + false == is_true<false>::value + + + false == false + + + +
+
+ + + !is_true<false>::value + + + true + + + +
+
+ + + !!is_true<true>::value + + + true + + + +
+
+ + + is_true<true>::value + + + true + + + + + !is_true<false>::value + + + !false + + + +
+ +
+ + + + True + + + true + + + + + !False + + + true + + + + + !False + + + !false + + + + + + + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + + +
+ +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + + +
+ +
+ +
+ + + + s == "7" + + + "7" == "7" + + + + + + + + a + + + true + + + + + a == &foo + + + 0x == 0x + + + + + + + + m == &S::f + + + 0x +== +0x + + + + + + + + p == 0 + + + NULL == 0 + + + + + + + + ptr.get() == nullptr + + + NULL == nullptr + + + + + + + + + + + + + + + + + + + + Catch::toString( item ) == "toString( has_toString )" + + + "toString( has_toString )" +== +"toString( has_toString )" + + + + + + + + Catch::toString( item ) == "StringMaker<has_maker>" + + + "StringMaker<has_maker>" +== +"StringMaker<has_maker>" + + + + + + + + Catch::toString( item ) == "toString( has_maker_and_toString )" + + + "toString( has_maker_and_toString )" +== +"toString( has_maker_and_toString )" + + + + + + + + Catch::toString( v ) == "{ {?} }" + + + "{ {?} }" == "{ {?} }" + + + + + + + + Catch::toString( v ) == "{ StringMaker<has_maker> }" + + + "{ StringMaker<has_maker> }" +== +"{ StringMaker<has_maker> }" + + + + + + + + Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" + + + "{ StringMaker<has_maker_and_toString> }" +== +"{ StringMaker<has_maker_and_toString> }" + + + + + + + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isSuccessfullyCompleted() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2.isOpen() + + + true + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isSuccessfullyCompleted() + + + true + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isComplete() + + + true + + + + + s2b.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() == false + + + false == false + + + + + s2c.isOpen() == false + + + false == false + + + + + testCase3.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + s1.isComplete() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + testCase.isComplete() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s1.isComplete() == false + + + false == false + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s1.isComplete() == false + + + false == false + + + + + s1b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s2b.isOpen() + + + true + + + + + s2b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + s1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s2.isSuccessfullyCompleted() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 0 + + + 0 == 0 + + + + + s2b.isOpen() == false + + + false == false + + + + + g1b.isComplete() == false + + + false == false + + + + + s1b.isComplete() == false + + + false == false + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() + + + true + + + + + g1c.isOpen() + + + true + + + + + g1c.index() == 1 + + + 1 == 1 + + + + + s2c.isOpen() + + + true + + + + + s2c.isComplete() + + + true + + + + + g1c.isComplete() + + + true + + + + + s1c.isComplete() + + + true + + + + + testCase3.isComplete() + + + true + + + +
+ +
+ +
+ +
+ + + + Catch::toString( value ) == "{ 34, \"xyzzy\" }" + + + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + + + + + + + + Catch::toString(value) == "{ 34, \"xyzzy\" }" + + + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + + + + + + + + Catch::toString( pr ) == "{ { \"green\", 55 } }" + + + "{ { "green", 55 } }" +== +"{ { "green", 55 } }" + + + + + + + + Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" + + + "{ { 42, "Arthur" }, { "Ford", 24 } }" +== +"{ { 42, "Arthur" }, { "Ford", 24 } }" + + + + + + + + Catch::toString(vv) == "{ }" + + + "{ }" == "{ }" + + + + + Catch::toString(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + Catch::toString(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + + + + + Catch::toString(vv) == "{ }" + + + "{ }" == "{ }" + + + + + Catch::toString(vv) == "{ \"hello\" }" + + + "{ "hello" }" == "{ "hello" }" + + + + + Catch::toString(vv) == "{ \"hello\", \"world\" }" + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + Catch::toString(vv) == "{ }" + + + "{ }" == "{ }" + + + + + Catch::toString(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + Catch::toString(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + + + + + Catch::toString(v) == "{ }" + + + "{ }" == "{ }" + + + + + Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" + + + "{ { "hello" }, { "world" } }" +== +"{ { "hello" }, { "world" } }" + + + + + +
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches(tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + + + parseTestSpec( "*a" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + + + parseTestSpec( "a*" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + + + parseTestSpec( "*a*" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+ +
+ + + + "{ }" == Catch::toString(type{}) + + + "{ }" == "{ }" + + + + + "{ }" == Catch::toString(value) + + + "{ }" == "{ }" + + + + + + + + "{ 0 }" == Catch::toString(type{0}) + + + "{ 0 }" == "{ 0 }" + + + + + + + + "1.2f" == Catch::toString(float(1.2)) + + + "1.2f" == "1.2f" + + + + + "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) + + + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + + + + + + + + "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + "{ { 42 }, { }, 1.2f }" == Catch::toString(value) + + + "{ { 42 }, { }, 1.2f }" +== +"{ { 42 }, { }, 1.2f }" + + + + + + + + "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) + + + "{ nullptr, 42, "Catch me" }" +== +"{ nullptr, 42, "Catch me" }" + + + + + +
+ + + what, Contains( "[@zzz]" ) + + + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "[@zzz]" + + + + + what, Contains( "file" ) + + + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "file" + + + + + what, Contains( "2" ) + + + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "2" + + + + + what, Contains( "10" ) + + + "error: tag alias, "[@zzz]" already registered. + First seen at file:2 + Redefined at file:10" contains: "10" + + + +
+
+ + + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + + + +
+ +
+ + + + + + + +
+ +
+ +
+ +
+
+
+ + + itDoesThis() + + + true + + +
+ + + itDoesThat() + + + true + + + +
+ +
+ +
+ +
+ +
+ +
+ + + v.size() == 0 + + + 0 == 0 + + +
+
+ + + v.size() == 10 + + + 10 == 10 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + +
+
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ +
+ +
+ +
+ +
+
+ + + v.size() == 0 + + + 0 == 0 + + +
+
+ + + v.capacity() >= 10 + + + 10 >= 10 + + + + + v.size() == 0 + + + 0 == 0 + + + +
+ +
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+ +
+ + + before == 0 + + + 0 == 0 + + +
+
+ + + after > before + + + 1 > 0 + + + +
+ +
+ +
+ +
+ +
+ +
diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ClassTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ClassTests.cpp new file mode 100644 index 00000000000..a4707849bb9 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ClassTests.cpp @@ -0,0 +1,57 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +namespace +{ + class TestClass + { + std::string s; + + public: + TestClass() + : s( "hello" ) + {} + + void succeedingCase() + { + REQUIRE( s == "hello" ); + } + void failingCase() + { + REQUIRE( s == "world" ); + } + }; +} + + +METHOD_AS_TEST_CASE( TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" ) +METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" ) + + +struct Fixture +{ + Fixture() : m_a( 1 ) {} + + int m_a; +}; + +TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[class]" ) +{ + REQUIRE( m_a == 1 ); +} + +// We should be able to write our tests within a different namespace +namespace Inner +{ + TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that fails", "[.][class][failing]" ) + { + REQUIRE( m_a == 2 ); + } +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/CmdLineTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/CmdLineTests.cpp new file mode 100644 index 00000000000..719c89b8fb0 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/CmdLineTests.cpp @@ -0,0 +1,264 @@ +/* + * Created by Phil on 13/5/2013. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" +#include "catch_test_spec_parser.hpp" + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } + +TEST_CASE( "Parse test names and tags", "" ) { + + using Catch::parseTestSpec; + using Catch::TestSpec; + + Catch::TestCase tcA = fakeTestCase( "a", "" ); + Catch::TestCase tcB = fakeTestCase( "b", "[one][x]" ); + Catch::TestCase tcC = fakeTestCase( "longer name with spaces", "[two][three][.][x]" ); + Catch::TestCase tcD = fakeTestCase( "zlonger name with spacesz", "" ); + + SECTION( "Empty test spec should have no filters", "" ) { + TestSpec spec; + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from empty string should have no filters", "" ) { + TestSpec spec = parseTestSpec( "" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches(tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from just a comma should have no filters", "" ) { + TestSpec spec = parseTestSpec( "," ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from name should have one filter", "" ) { + TestSpec spec = parseTestSpec( "b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + } + + SECTION( "Test spec from quoted name should have one filter", "" ) { + TestSpec spec = parseTestSpec( "\"b\"" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + } + + SECTION( "Test spec from name should have one filter", "" ) { + TestSpec spec = parseTestSpec( "b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + + SECTION( "Wildcard at the start", "" ) { + TestSpec spec = parseTestSpec( "*spaces" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ); + } + SECTION( "Wildcard at the end", "" ) { + TestSpec spec = parseTestSpec( "long*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ); + } + SECTION( "Wildcard at both ends", "" ) { + TestSpec spec = parseTestSpec( "*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ); + } + SECTION( "Redundant wildcard at the start", "" ) { + TestSpec spec = parseTestSpec( "*a" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + } + SECTION( "Redundant wildcard at the end", "" ) { + TestSpec spec = parseTestSpec( "a*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + } + SECTION( "Redundant wildcard at both ends", "" ) { + TestSpec spec = parseTestSpec( "*a*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + } + SECTION( "Wildcard at both ends, redundant at start", "" ) { + TestSpec spec = parseTestSpec( "*longer*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "Just wildcard", "" ) { + TestSpec spec = parseTestSpec( "*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + + SECTION( "Single tag", "" ) { + TestSpec spec = parseTestSpec( "[one]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + SECTION( "Single tag, two matches", "" ) { + TestSpec spec = parseTestSpec( "[x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Two tags", "" ) { + TestSpec spec = parseTestSpec( "[two][x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Two tags, spare separated", "" ) { + TestSpec spec = parseTestSpec( "[two] [x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Wildcarded name and tag", "" ) { + TestSpec spec = parseTestSpec( "*name*[x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "Single tag exclusion", "" ) { + TestSpec spec = parseTestSpec( "~[one]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "One tag exclusion and one tag inclusion", "" ) { + TestSpec spec = parseTestSpec( "~[two][x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + SECTION( "One tag exclusion and one wldcarded name inclusion", "" ) { + TestSpec spec = parseTestSpec( "~[two]*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion", "" ) { + TestSpec spec = parseTestSpec( "exclude:[two]*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "name exclusion", "" ) { + TestSpec spec = parseTestSpec( "~b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "wildcarded name exclusion", "" ) { + TestSpec spec = parseTestSpec( "~*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "wildcarded name exclusion with tag inclusion", "" ) { + TestSpec spec = parseTestSpec( "~*name*,[three]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion", "" ) { + TestSpec spec = parseTestSpec( "exclude:*name*,[three]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "two wildcarded names", "" ) { + TestSpec spec = parseTestSpec( "\"longer*\"\"*spaces\"" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "empty tag", "" ) { + TestSpec spec = parseTestSpec( "[]" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "empty quoted name", "" ) { + TestSpec spec = parseTestSpec( "\"\"" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "quoted string followed by tag exclusion", "" ) { + TestSpec spec = parseTestSpec( "\"*name*\"~[.]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ConditionTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ConditionTests.cpp new file mode 100644 index 00000000000..d1b7ed24ce3 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ConditionTests.cpp @@ -0,0 +1,335 @@ +/* + * Created by Phil on 08/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +#include "catch.hpp" + +#include +#include + +struct TestData { + TestData() + : int_seven( 7 ), + str_hello( "hello" ), + float_nine_point_one( 9.1f ), + double_pi( 3.1415926535 ) + {} + + int int_seven; + std::string str_hello; + float float_nine_point_one; + double double_pi; +}; + + +struct TestDef { + TestDef& operator + ( const std::string& ) { + return *this; + } + TestDef& operator[]( const std::string& ) { + return *this; + } + +}; + +// The "failing" tests all use the CHECK macro, which continues if the specific test fails. +// This allows us to see all results, even if an earlier check fails + +// Equality tests +TEST_CASE( "Equality checks that should succeed", "" ) +{ + + TestDef td; + td + "hello" + "hello"; + + TestData data; + + REQUIRE( data.int_seven == 7 ); + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ); + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ); + REQUIRE( data.str_hello == "hello" ); + REQUIRE( "hello" == data.str_hello ); + REQUIRE( data.str_hello.size() == 5 ); + + double x = 1.1 + 0.1 + 0.1; + REQUIRE( x == Approx( 1.3 ) ); +} + +TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" ) +{ + TestData data; + + CHECK( data.int_seven == 6 ); + CHECK( data.int_seven == 8 ); + CHECK( data.int_seven == 0 ); + CHECK( data.float_nine_point_one == Approx( 9.11f ) ); + CHECK( data.float_nine_point_one == Approx( 9.0f ) ); + CHECK( data.float_nine_point_one == Approx( 1 ) ); + CHECK( data.float_nine_point_one == Approx( 0 ) ); + CHECK( data.double_pi == Approx( 3.1415 ) ); + CHECK( data.str_hello == "goodbye" ); + CHECK( data.str_hello == "hell" ); + CHECK( data.str_hello == "hello1" ); + CHECK( data.str_hello.size() == 6 ); + + double x = 1.1 + 0.1 + 0.1; + CHECK( x == Approx( 1.301 ) ); +} + +TEST_CASE( "Inequality checks that should succeed", "" ) +{ + TestData data; + + REQUIRE( data.int_seven != 6 ); + REQUIRE( data.int_seven != 8 ); + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ); + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ); + REQUIRE( data.float_nine_point_one != Approx( 1 ) ); + REQUIRE( data.float_nine_point_one != Approx( 0 ) ); + REQUIRE( data.double_pi != Approx( 3.1415 ) ); + REQUIRE( data.str_hello != "goodbye" ); + REQUIRE( data.str_hello != "hell" ); + REQUIRE( data.str_hello != "hello1" ); + REQUIRE( data.str_hello.size() != 6 ); +} + +TEST_CASE( "Inequality checks that should fail", "[.][failing]" ) +{ + TestData data; + + CHECK( data.int_seven != 7 ); + CHECK( data.float_nine_point_one != Approx( 9.1f ) ); + CHECK( data.double_pi != Approx( 3.1415926535 ) ); + CHECK( data.str_hello != "hello" ); + CHECK( data.str_hello.size() != 5 ); +} + +// Ordering comparison tests +TEST_CASE( "Ordering comparison checks that should succeed", "" ) +{ + TestData data; + + REQUIRE( data.int_seven < 8 ); + REQUIRE( data.int_seven > 6 ); + REQUIRE( data.int_seven > 0 ); + REQUIRE( data.int_seven > -1 ); + + REQUIRE( data.int_seven >= 7 ); + REQUIRE( data.int_seven >= 6 ); + REQUIRE( data.int_seven <= 7 ); + REQUIRE( data.int_seven <= 8 ); + + REQUIRE( data.float_nine_point_one > 9 ); + REQUIRE( data.float_nine_point_one < 10 ); + REQUIRE( data.float_nine_point_one < 9.2 ); + + REQUIRE( data.str_hello <= "hello" ); + REQUIRE( data.str_hello >= "hello" ); + + REQUIRE( data.str_hello < "hellp" ); + REQUIRE( data.str_hello < "zebra" ); + REQUIRE( data.str_hello > "hellm" ); + REQUIRE( data.str_hello > "a" ); +} + +TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) +{ + TestData data; + + CHECK( data.int_seven > 7 ); + CHECK( data.int_seven < 7 ); + CHECK( data.int_seven > 8 ); + CHECK( data.int_seven < 6 ); + CHECK( data.int_seven < 0 ); + CHECK( data.int_seven < -1 ); + + CHECK( data.int_seven >= 8 ); + CHECK( data.int_seven <= 6 ); + + CHECK( data.float_nine_point_one < 9 ); + CHECK( data.float_nine_point_one > 10 ); + CHECK( data.float_nine_point_one > 9.2 ); + + CHECK( data.str_hello > "hello" ); + CHECK( data.str_hello < "hello" ); + CHECK( data.str_hello > "hellp" ); + CHECK( data.str_hello > "z" ); + CHECK( data.str_hello < "hellm" ); + CHECK( data.str_hello < "a" ); + + CHECK( data.str_hello >= "z" ); + CHECK( data.str_hello <= "a" ); +} + +// Comparisons with int literals +TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned", "" ) +{ + int i = 1; + unsigned int ui = 2; + long l = 3; + unsigned long ul = 4; + char c = 5; + unsigned char uc = 6; + + REQUIRE( i == 1 ); + REQUIRE( ui == 2 ); + REQUIRE( l == 3 ); + REQUIRE( ul == 4 ); + REQUIRE( c == 5 ); + REQUIRE( uc == 6 ); + + REQUIRE( 1 == i ); + REQUIRE( 2 == ui ); + REQUIRE( 3 == l ); + REQUIRE( 4 == ul ); + REQUIRE( 5 == c ); + REQUIRE( 6 == uc ); + + REQUIRE( (std::numeric_limits::max)() > ul ); +} + +// Disable warnings about sign conversions for the next two tests +// (as we are deliberately invoking them) +// - Currently only disabled for GCC/ LLVM. Should add VC++ too +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif +#ifdef _MSC_VER +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +TEST_CASE( "comparisons between int variables", "" ) +{ + long long_var = 1L; + unsigned char unsigned_char_var = 1; + unsigned short unsigned_short_var = 1; + unsigned int unsigned_int_var = 1; + unsigned long unsigned_long_var = 1L; + + REQUIRE( long_var == unsigned_char_var ); + REQUIRE( long_var == unsigned_short_var ); + REQUIRE( long_var == unsigned_int_var ); + REQUIRE( long_var == unsigned_long_var ); +} + +TEST_CASE( "comparisons between const int variables", "" ) +{ + const unsigned char unsigned_char_var = 1; + const unsigned short unsigned_short_var = 1; + const unsigned int unsigned_int_var = 1; + const unsigned long unsigned_long_var = 1L; + + REQUIRE( unsigned_char_var == 1 ); + REQUIRE( unsigned_short_var == 1 ); + REQUIRE( unsigned_int_var == 1 ); + REQUIRE( unsigned_long_var == 1 ); +} + +TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour", "" ) +{ + CHECK( ( -1 > 2u ) ); + CHECK( -1 > 2u ); + + CHECK( ( 2u < -1 ) ); + CHECK( 2u < -1 ); + + const int minInt = (std::numeric_limits::min)(); + CHECK( ( minInt > 2u ) ); + CHECK( minInt > 2u ); +} + +template +struct Ex +{ + Ex( T ){} + + bool operator == ( const T& ) const { return true; } + T operator * ( const T& ) const { return T(); } +}; + +TEST_CASE( "Comparisons between ints where one side is computed", "" ) +{ + CHECK( 54 == 6*9 ); +} + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +inline const char* returnsConstNull(){ return CATCH_NULL; } +inline char* returnsNull(){ return CATCH_NULL; } + +TEST_CASE( "Pointers can be compared to null", "" ) +{ + TestData* p = CATCH_NULL; + TestData* pNULL = CATCH_NULL; + + REQUIRE( p == CATCH_NULL ); + REQUIRE( p == pNULL ); + + TestData data; + p = &data; + + REQUIRE( p != CATCH_NULL ); + + const TestData* cp = p; + REQUIRE( cp != CATCH_NULL ); + + const TestData* const cpc = p; + REQUIRE( cpc != CATCH_NULL ); + + REQUIRE( returnsNull() == CATCH_NULL ); + REQUIRE( returnsConstNull() == CATCH_NULL ); + + REQUIRE( CATCH_NULL != p ); +} + +// Not (!) tests +// The problem with the ! operator is that it has right-to-left associativity. +// This means we can't isolate it when we decompose. The simple REQUIRE( !false ) form, therefore, +// cannot have the operand value extracted. The test will work correctly, and the situation +// is detected and a warning issued. +// An alternative form of the macros (CHECK_FALSE and REQUIRE_FALSE) can be used instead to capture +// the operand value. +TEST_CASE( "'Not' checks that should succeed", "" ) +{ + bool falseValue = false; + + REQUIRE( false == false ); + REQUIRE( true == true ); + REQUIRE( !false ); + REQUIRE_FALSE( false ); + + REQUIRE( !falseValue ); + REQUIRE_FALSE( falseValue ); + + REQUIRE( !(1 == 2) ); + REQUIRE_FALSE( 1 == 2 ); +} + +TEST_CASE( "'Not' checks that should fail", "[.][failing]" ) +{ + bool trueValue = true; + + CHECK( false != false ); + CHECK( true != true ); + CHECK( !true ); + CHECK_FALSE( true ); + + CHECK( !trueValue ); + CHECK_FALSE( trueValue ); + + CHECK( !(1 == 1) ); + CHECK_FALSE( 1 == 1 ); +} + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/EnumToString.cpp b/3rdparty/sol2/Catch/projects/SelfTest/EnumToString.cpp new file mode 100644 index 00000000000..6917d8ae8a0 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/EnumToString.cpp @@ -0,0 +1,76 @@ +#include "catch.hpp" + +/* + TODO: maybe ought to check that user-provided specialisations of + Catch::toString also do the right thing +*/ + +// Enum without user-provided stream operator +enum Enum1 { Enum1Value0, Enum1Value1 }; + +TEST_CASE( "toString(enum)", "[toString][enum]" ) { + Enum1 e0 = Enum1Value0; + CHECK( Catch::toString(e0) == "0" ); + Enum1 e1 = Enum1Value1; + CHECK( Catch::toString(e1) == "1" ); +} + +// Enum with user-provided stream operator +enum Enum2 { Enum2Value0, Enum2Value1 }; + +inline std::ostream& operator<<( std::ostream& os, Enum2 v ) { + return os << "E2{" << static_cast(v) << "}"; +} + +TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { + Enum2 e0 = Enum2Value0; + CHECK( Catch::toString(e0) == "E2{0}" ); + Enum2 e1 = Enum2Value1; + CHECK( Catch::toString(e1) == "E2{1}" ); +} + +#if defined(CATCH_CPP11_OR_GREATER) +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +// Enum class without user-provided stream operator +enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; + +TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) { + EnumClass1 e0 = EnumClass1::EnumClass1Value0; + CHECK( Catch::toString(e0) == "0" ); + EnumClass1 e1 = EnumClass1::EnumClass1Value1; + CHECK( Catch::toString(e1) == "1" ); +} + +// Enum class with user-provided stream operator +enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 }; + +inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { + switch( static_cast( e2 ) ) { + case static_cast( EnumClass2::EnumClass2Value0 ): + return os << "E2/V0"; + case static_cast( EnumClass2::EnumClass2Value1 ): + return os << "E2/V1"; + default: + return os << "Unknown enum value " << static_cast( e2 ); + } +} + +TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) { + EnumClass2 e0 = EnumClass2::EnumClass2Value0; + CHECK( Catch::toString(e0) == "E2/V0" ); + EnumClass2 e1 = EnumClass2::EnumClass2Value1; + CHECK( Catch::toString(e1) == "E2/V1" ); + + EnumClass2 e3 = static_cast(10); + CHECK( Catch::toString(e3) == "Unknown enum value 10" ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif // CATCH_CPP11_OR_GREATER + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ExceptionTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ExceptionTests.cpp new file mode 100644 index 00000000000..5ef91a1239a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ExceptionTests.cpp @@ -0,0 +1,203 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#include +#include + +namespace +{ + inline int thisThrows() + { + if( Catch::alwaysTrue() ) + throw std::domain_error( "expected exception" ); + return 1; + } + + int thisDoesntThrow() + { + return 0; + } +} + +TEST_CASE( "When checked exceptions are thrown they can be expected or unexpected", "" ) +{ + REQUIRE_THROWS_AS( thisThrows(), std::domain_error ); + REQUIRE_NOTHROW( thisDoesntThrow() ); + REQUIRE_THROWS( thisThrows() ); +} + +TEST_CASE( "Expected exceptions that don't throw or unexpected exceptions fail the test", "[.][failing]" ) +{ + CHECK_THROWS_AS( thisThrows(), std::string ); + CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ); + CHECK_NOTHROW( thisThrows() ); +} + +TEST_CASE( "When unchecked exceptions are thrown directly they are always failures", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw std::domain_error( "unexpected exception" ); +} + +TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.][failing]" ) +{ + CHECK( 1 == 1 ); + if( Catch::alwaysTrue() ) + throw std::domain_error( "unexpected exception" ); +} + +TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing]" ) +{ + SECTION( "section name", "" ) + { + if( Catch::alwaysTrue() ) + throw std::domain_error( "unexpected exception" ); + } +} + +TEST_CASE( "When unchecked exceptions are thrown from functions they are always failures", "[.][failing]" ) +{ + CHECK( thisThrows() == 0 ); +} + +TEST_CASE( "When unchecked exceptions are thrown during a REQUIRE the test should abort fail", "[.][failing]" ) +{ + REQUIRE( thisThrows() == 0 ); + FAIL( "This should never happen" ); +} + +TEST_CASE( "When unchecked exceptions are thrown during a CHECK the test should abort and fail", "[.][failing]" ) +{ + CHECK( thisThrows() == 0 ); + FAIL( "This should never happen" ); +} + +TEST_CASE( "When unchecked exceptions are thrown, but caught, they do not affect the test", "" ) +{ + try + { + throw std::domain_error( "unexpected exception" ); + } + catch(...) + { + } +} + +class CustomException +{ +public: + CustomException( const std::string& msg ) + : m_msg( msg ) + {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + +class CustomStdException : public std::exception +{ +public: + CustomStdException( const std::string& msg ) + : m_msg( msg ) + {} + ~CustomStdException() CATCH_NOEXCEPT {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + + +CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) +{ + return ex.getMessage(); +} + +CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) +{ + return ex.getMessage(); +} + +CATCH_TRANSLATE_EXCEPTION( double& ex ) +{ + return Catch::toString( ex ); +} + +TEST_CASE("Non-std exceptions can be translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw CustomException( "custom exception" ); +} + +TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw CustomException( "custom std exception" ); +} + +inline void throwCustom() { + if( Catch::alwaysTrue() ) + throw CustomException( "custom exception - not std" ); +} + +TEST_CASE( "Custom exceptions can be translated when testing for nothrow", "[.][failing]" ) +{ + REQUIRE_NOTHROW( throwCustom() ); +} + +TEST_CASE( "Custom exceptions can be translated when testing for throwing as something else", "[.][failing]" ) +{ + REQUIRE_THROWS_AS( throwCustom(), std::exception ); +} + + +TEST_CASE( "Unexpected exceptions can be translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw double( 3.14 ); +} + +inline int thisFunctionNotImplemented( int ) { + CATCH_NOT_IMPLEMENTED; +} + +TEST_CASE( "NotImplemented exception", "" ) +{ + REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); +} + +TEST_CASE( "Exception messages can be tested for", "" ) { + using namespace Catch::Matchers; + SECTION( "exact match" ) + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); + SECTION( "different case" ) + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ); + SECTION( "wildcarded" ) { + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ); + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ); + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ); + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ); + } +} + +TEST_CASE( "Mismatching exception messages failing the test", "[.][failing]" ) { + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/GeneratorTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/GeneratorTests.cpp new file mode 100644 index 00000000000..af08b1d316a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/GeneratorTests.cpp @@ -0,0 +1,42 @@ +/* + * Created by Phil on 28/01/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +// This define means we have to prefix all the CATCH macros with CATCH_ +// We're using it here to test it out +#define CATCH_CONFIG_PREFIX_ALL +#include "catch.hpp" + +inline int multiply( int a, int b ) +{ + return a*b; +} + +CATCH_TEST_CASE( "Generators over two ranges", "[generators]" ) +{ + using namespace Catch::Generators; + + int i = CATCH_GENERATE( between( 1, 5 ).then( values( 15, 20, 21 ).then( 36 ) ) ); + int j = CATCH_GENERATE( between( 100, 107 ) ); + + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ); + CATCH_REQUIRE( multiply( j, 2 ) == j*2 ); +} + +struct IntPair { int first, second; }; + +CATCH_TEST_CASE( "Generator over a range of pairs", "[generators]" ) +{ + using namespace Catch::Generators; + + IntPair p[] = { { 0, 1 }, { 2, 3 } }; + + IntPair* i = CATCH_GENERATE( between( p, &p[1] ) ); + + CATCH_REQUIRE( i->first == i->second-1 ); + +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/MessageTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/MessageTests.cpp new file mode 100644 index 00000000000..87a85a82d84 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/MessageTests.cpp @@ -0,0 +1,133 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) +{ + INFO( "this is a " << "message" ); // This should output the message if a failure occurs + WARN( "this is a " << "warning" ); // This should always output the message but then continue +} +TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) +{ + SUCCEED( "this is a " << "success" ); +} + +TEST_CASE( "INFO gets logged on failure", "[failing][messages][.]" ) +{ + INFO( "this message should be logged" ); + INFO( "so should this" ); + int a = 2; + REQUIRE( a == 1 ); +} + +TEST_CASE( "INFO gets logged on failure, even if captured before successful assertions", "[failing][messages][.]" ) +{ + INFO( "this message may be logged later" ); + int a = 2; + CHECK( a == 2 ); + + INFO( "this message should be logged" ); + + CHECK( a == 1 ); + + INFO( "and this, but later" ); + + CHECK( a == 0 ); + + INFO( "but not this" ); + + CHECK( a == 2 ); +} + +TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) +{ + FAIL( "This is a " << "failure" ); // This should output the message and abort +} + +#ifdef CATCH_CONFIG_VARIADIC_MACROS +TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) +{ + FAIL(); +} +TEST_CASE( "SUCCESS does not require an argument", "[messages][.]" ) +{ + SUCCEED(); +} +#endif + +TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) +{ + SECTION( "one", "" ) + { + FAIL( "Message from section one" ); + } + + SECTION( "two", "" ) + { + FAIL( "Message from section two" ); + } +} + +TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) +{ + SECTION( "one", "" ) + { + std::cout << "Message from section one" << std::endl; + } + + SECTION( "two", "" ) + { + std::cout << "Message from section two" << std::endl; + } +} + +TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" ) +{ + for( int i=0; i<100; i++ ) + { + SCOPED_INFO( "current counter " << i ); + SCOPED_CAPTURE( i ); + REQUIRE( i < 10 ); + } +} + +TEST_CASE( "The NO_FAIL macro reports a failure but does not fail the test", "[messages]" ) +{ + CHECK_NOFAIL( 1 == 2 ); +} + +TEST_CASE( "just info", "[info][isolated info][messages]" ) +{ + INFO( "this should never be seen" ); +} +TEST_CASE( "just failure", "[fail][isolated info][.][messages]" ) +{ + FAIL( "Previous info should not be seen" ); +} + + +TEST_CASE( "sends information to INFO", "[.][failing]" ) +{ + INFO( "hi" ); + int i = 7; + CAPTURE( i ); + REQUIRE( false ); +} + +TEST_CASE( "Pointers can be converted to strings", "[messages][.]" ) +{ + int p; + WARN( "actual address of p: " << &p ); + WARN( "toString(p): " << Catch::toString( &p ) ); +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/MiscTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/MiscTests.cpp new file mode 100644 index 00000000000..cf7f48cf313 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/MiscTests.cpp @@ -0,0 +1,480 @@ +/* + * Created by Phil on 29/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#include "../include/internal/catch_xmlwriter.hpp" + +#include + +TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) +{ + int a = 1; + int b = 2; + + SECTION( "s1", "doesn't equal" ) + { + REQUIRE( a != b ); + REQUIRE( b != a ); + } + + SECTION( "s2", "not equal" ) + { + REQUIRE( a != b); + } +} + +TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) +{ + int a = 1; + int b = 2; + + SECTION( "s1", "doesn't equal" ) + { + REQUIRE( a != b ); + REQUIRE( b != a ); + + SECTION( "s2", "not equal" ) + { + REQUIRE( a != b); + } + } +} + +TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) +{ + int a = 1; + int b = 2; + + SECTION( "s1", "doesn't equal" ) + { + SECTION( "s2", "equal" ) + { + REQUIRE( a == b ); + } + + SECTION( "s3", "not equal" ) + { + REQUIRE( a != b ); + } + SECTION( "s4", "less than" ) + { + REQUIRE( a < b ); + } + } +} + +TEST_CASE( "even more nested SECTION tests", "[sections]" ) +{ + SECTION( "c", "" ) + { + SECTION( "d (leaf)", "" ) + { + SUCCEED(""); // avoid failing due to no tests + } + + SECTION( "e (leaf)", "" ) + { + SUCCEED(""); // avoid failing due to no tests + } + } + + SECTION( "f (leaf)", "" ) + { + SUCCEED(""); // avoid failing due to no tests + } +} + +TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) +{ + int a = 1; + + for( int b = 0; b < 10; ++b ) + { + std::ostringstream oss; + oss << "b is currently: " << b; + SECTION( "s1", oss.str() ) + { + CHECK( b > a ); + } + } +} + +TEST_CASE( "looped tests", "[.][failing]" ) +{ + static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 }; + + for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) + { + INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" ); + CHECK( ( fib[i] % 2 ) == 0 ); + } +} + +TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) +{ + std::cout << "A string sent directly to stdout" << std::endl; + + std::cerr << "A string sent directly to stderr" << std::endl; +} + +inline const char* makeString( bool makeNull ) +{ + return makeNull ? CATCH_NULL : "valid string"; +} + +TEST_CASE( "null strings", "" ) +{ + REQUIRE( makeString( false ) != static_cast(CATCH_NULL)); + REQUIRE( makeString( true ) == static_cast(CATCH_NULL)); +} + + +inline bool testCheckedIf( bool flag ) +{ + CHECKED_IF( flag ) + return true; + else + return false; +} + +TEST_CASE( "checkedIf", "" ) +{ + REQUIRE( testCheckedIf( true ) ); +} + +TEST_CASE( "checkedIf, failing", "[failing][.]" ) +{ + REQUIRE( testCheckedIf( false ) ); +} + +inline bool testCheckedElse( bool flag ) +{ + CHECKED_ELSE( flag ) + return false; + + return true; +} + +TEST_CASE( "checkedElse", "" ) +{ + REQUIRE( testCheckedElse( true ) ); +} + +TEST_CASE( "checkedElse, failing", "[failing][.]" ) +{ + REQUIRE( testCheckedElse( false ) ); +} + +TEST_CASE( "xmlentitycheck", "" ) +{ + SECTION( "embedded xml", "it should be possible to embed xml characters, such as <, \" or &, or even whole documents within an attribute" ) + { + SUCCEED(""); // We need this here to stop it failing due to no tests + } + SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) + { + SUCCEED(""); // We need this here to stop it failing due to no tests + } +} + +TEST_CASE( "send a single char to INFO", "[failing][.]" ) +{ + INFO(3); + REQUIRE(false); +} + +TEST_CASE( "atomic if", "[failing][0]") +{ + size_t x = 0; + + if( x ) + REQUIRE(x > 0); + else + REQUIRE(x == 0); +} + +inline const char* testStringForMatching() +{ + return "this string contains 'abc' as a substring"; +} +inline const char* testStringForMatching2() +{ + return "some completely different text that contains one common word"; +} + +using namespace Catch::Matchers; + +TEST_CASE("String matchers", "[matchers]" ) +{ + REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ); + CHECK_THAT( testStringForMatching(), Contains( "abc" ) ); + + CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ); + CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ); +} + +TEST_CASE("Contains string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ); +} + +TEST_CASE("StartsWith string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ); +} + +TEST_CASE("EndsWith string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ); +} + +TEST_CASE("Equals string matcher", "[.][failing][matchers]") +{ + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ); +} +TEST_CASE("Equals string matcher, with NULL", "[matchers]") +{ + REQUIRE_THAT("", Equals(CATCH_NULL)); +} +TEST_CASE("AllOf matcher", "[matchers]") +{ + CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ); +} +TEST_CASE("AnyOf matcher", "[matchers]") +{ + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ); + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ); +} + +TEST_CASE("Equals", "[matchers]") +{ + CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ); +} + +TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") +{ + CHECK_THAT( testStringForMatching(), + Contains( "string" ) && + Contains( "abc" ) && + Contains( "substring" ) && + Contains( "contains" ) ); +} + +TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") +{ + CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); + CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); +} + +TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") +{ + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ); +} + +TEST_CASE("Matchers can be composed with both && and || - failing", "[matchers][operators][operator||][operator&&][.failing]") +{ + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ); +} + +TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") +{ + CHECK_THAT( testStringForMatching(), !Contains( "different" ) ); +} + +TEST_CASE("Matchers can be negated (Not) with the ! operator - failing", "[matchers][operators][not][.failing]") +{ + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ); +} + + +inline unsigned int Factorial( unsigned int number ) +{ +// return number <= 1 ? number : Factorial(number-1)*number; + return number > 1 ? Factorial(number-1)*number : 1; +} + +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(0) == 1 ); + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} + +TEST_CASE( "An empty test with no assertions", "[empty]" ) +{ +} + +TEST_CASE( "Nice descriptive name", "[tag1][tag2][tag3][.]" ) +{ + WARN( "This one ran" ); +} +TEST_CASE( "first tag", "[tag1]" ) +{ +} +TEST_CASE( "second tag", "[tag2]" ) +{ +} +// +//TEST_CASE( "spawn a new process", "[.]" ) +//{ +// // !TBD Work in progress +// char line[200]; +// FILE* output = popen("./CatchSelfTest ./failing/matchers/StartsWith", "r"); +// while ( fgets(line, 199, output) ) +// std::cout << line; +//} + +TEST_CASE( "vectors can be sized and resized", "[vector]" ) { + + std::vector v( 5 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + + SECTION( "resizing bigger changes size and capacity", "" ) { + v.resize( 10 ); + + REQUIRE( v.size() == 10 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "resizing smaller changes size but not capacity", "" ) { + v.resize( 0 ); + + REQUIRE( v.size() == 0 ); + REQUIRE( v.capacity() >= 5 ); + + SECTION( "We can use the 'swap trick' to reset the capacity", "" ) { + std::vector empty; + empty.swap( v ); + + REQUIRE( v.capacity() == 0 ); + } + } + SECTION( "reserving bigger changes capacity but not size", "" ) { + v.reserve( 10 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 10 ); + } + SECTION( "reserving smaller does not change size or capacity", "" ) { + v.reserve( 0 ); + + REQUIRE( v.size() == 5 ); + REQUIRE( v.capacity() >= 5 ); + } +} + +// https://github.com/philsquared/Catch/issues/166 +TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") +{ + SECTION("Outer", "") + SECTION("Inner", "") + SUCCEED("that's not flying - that's failing in style"); + + FAIL("to infinity and beyond"); +} + +TEST_CASE("not allowed", "[!throws]") +{ + // This test case should not be included if you run with -e on the command line + SUCCEED( "" ); +} + +//TEST_CASE( "Is big endian" ) { +// CHECK( Catch::Detail::Endianness::which() == Catch::Detail::Endianness::Little ); +//} + +TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) { + + // Based on issue #242 + std::string s1 = "if ($b == 10) {\n\t\t$a\t= 20;\n}"; + std::string s2 = "if ($b == 10) {\n\t$a = 20;\n}\n"; + CHECK( s1 == s2 ); +} + + +TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) { + const wchar_t * const s = L"wide load"; + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) { + const wchar_t * s = L"wide load"; + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) { + wchar_t * const s = const_cast( L"wide load" ); + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) { + wchar_t * s = const_cast( L"wide load" ); + std::string result = Catch::toString( s ); + CHECK( result == "\"wide load\"" ); +} + +inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) { + std::ostringstream oss; + oss << Catch::XmlEncode( str, forWhat ); + return oss.str(); +} + +TEST_CASE( "XmlEncode" ) { + SECTION( "normal string" ) { + REQUIRE( encode( "normal string" ) == "normal string" ); + } + SECTION( "empty string" ) { + REQUIRE( encode( "" ) == "" ); + } + SECTION( "string with ampersand" ) { + REQUIRE( encode( "smith & jones" ) == "smith & jones" ); + } + SECTION( "string with less-than" ) { + REQUIRE( encode( "smith < jones" ) == "smith < jones" ); + } + SECTION( "string with greater-than" ) { + REQUIRE( encode( "smith > jones" ) == "smith > jones" ); + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ); + } + SECTION( "string with quotes" ) { + std::string stringWithQuotes = "don't \"quote\" me on that"; + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ); + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ); + } + SECTION( "string with control char (1)" ) { + REQUIRE( encode( "[\x01]" ) == "[]" ); + } + SECTION( "string with control char (x7F)" ) { + REQUIRE( encode( "[\x7F]" ) == "[]" ); + } +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +TEST_CASE( "long long" ) { + long long l = std::numeric_limits::max(); + + REQUIRE( l == std::numeric_limits::max() ); +} +#endif + +//TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) { +// int i = 0; +// int x = 10/i; // This should cause the signal to fire +// CHECK( x == 0 ); +//} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/PartTrackerTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/PartTrackerTests.cpp new file mode 100644 index 00000000000..29256351197 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/PartTrackerTests.cpp @@ -0,0 +1,328 @@ +/* + * Created by Phil on 1/10/2015. + * Copyright 2015 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#include "internal/catch_suppress_warnings.h" +#include "internal/catch_test_case_tracker.hpp" + + +namespace Catch +{ + class LocalContext { + + public: + TrackerContext& operator()() const { + return TrackerContext::instance(); + } + }; + +} // namespace Catch + +inline Catch::TrackerContext& C_A_T_C_H_Context() { + return Catch::TrackerContext::instance(); +} + +// ------------------- + +#include "catch.hpp" + +using namespace Catch; + +//inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { +// +// REQUIRE( C_A_T_C_H_Context().i() == 42 ); +//} + +TEST_CASE( "Tracker", "" ) { + + TrackerContext ctx; + ctx.startRun(); + ctx.startCycle(); + + ITracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase.isOpen() ); + + ITracker& s1 = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1.isOpen() ); + + SECTION( "successfully close one section", "" ) { + s1.close(); + REQUIRE( s1.isSuccessfullyCompleted() ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + + SECTION( "fail one section", "" ) { + s1.fail(); + REQUIRE( s1.isComplete() ); + REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); + + SECTION( "re-enter after failed section", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + testCase2.close(); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isComplete() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + SECTION( "re-enter after failed section and find next section", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( ctx.completedCycle() ); + + testCase2.close(); + REQUIRE( testCase.isComplete() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + } + + SECTION( "successfully close one section, then find another", "" ) { + s1.close(); + + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter - skips S1 and enters S2", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() ); + + REQUIRE( ctx.completedCycle() == false ); + + SECTION ("Successfully close S2") { + s2b.close(); + REQUIRE( ctx.completedCycle() ); + + REQUIRE( s2b.isSuccessfullyCompleted() ); + REQUIRE( testCase2.isComplete() == false ); + + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() ); + } + SECTION ("fail S2") { + s2b.fail(); + REQUIRE( ctx.completedCycle() ); + + REQUIRE( s2b.isComplete() ); + REQUIRE( s2b.isSuccessfullyCompleted() == false ); + + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + + // Need a final cycle + ctx.startCycle(); + ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase3.isOpen() ); + + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1c.isOpen() == false ); + + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2c.isOpen() == false ); + + testCase3.close(); + REQUIRE( testCase3.isSuccessfullyCompleted() ); + } + } + } + + SECTION( "open a nested section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( s2.isComplete() ); + REQUIRE( s1.isComplete() == false ); + + s1.close(); + REQUIRE( s1.isComplete() ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() ); + } + + SECTION( "start a generator", "" ) { + IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1.isOpen() ); + REQUIRE( g1.index() == 0 ); + + REQUIRE( g1.isComplete() == false ); + REQUIRE( s1.isComplete() == false ); + + SECTION( "close outer section" ) + { + s1.close(); + REQUIRE( s1.isComplete() == false ); + testCase.close(); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); + + SECTION( "Re-enter for second generation", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 1 ); + + REQUIRE( s1.isComplete() == false ); + + s1b.close(); + REQUIRE( s1b.isComplete() ); + REQUIRE( g1b.isComplete() ); + testCase2.close(); + REQUIRE( testCase2.isComplete() ); + } + } + SECTION( "Start a new inner section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( s2.isComplete() ); + + s1.close(); + REQUIRE( s1.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter for second generation", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + // generator - next value + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 1 ); + + // inner section again + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() ); + + s2b.close(); + REQUIRE( s2b.isComplete() ); + + s1b.close(); + REQUIRE( g1b.isComplete() ); + REQUIRE( s1b.isComplete() ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() ); + } + } + + SECTION( "Fail an inner section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.fail(); + REQUIRE( s2.isComplete() ); + REQUIRE( s2.isSuccessfullyCompleted() == false ); + + s1.close(); + REQUIRE( s1.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter for second generation", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + // generator - still same value + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 0 ); + + // inner section again - this time won't open + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() == false ); + + s1b.close(); + REQUIRE( g1b.isComplete() == false ); + REQUIRE( s1b.isComplete() == false ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() == false ); + + // Another cycle - now should complete + ctx.startCycle(); + ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase3.isOpen() ); + + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1c.isOpen() ); + + // generator - now next value + IndexTracker& g1c = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1c.isOpen() ); + REQUIRE( g1c.index() == 1 ); + + // inner section - now should open again + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2c.isOpen() ); + + s2c.close(); + REQUIRE( s2c.isComplete() ); + + s1c.close(); + REQUIRE( g1c.isComplete() ); + REQUIRE( s1c.isComplete() ); + + testCase3.close(); + REQUIRE( testCase3.isComplete() ); + } + } + // !TBD" + // nested generator + // two sections within a generator + } +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp new file mode 100644 index 00000000000..72f90bd6aa5 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_common.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_common.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp new file mode 100644 index 00000000000..e7378c04ad7 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_console_colour.hpp" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp new file mode 100644 index 00000000000..33f76ae6f9e --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_debugger.cpp @@ -0,0 +1,2 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_debugger.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp new file mode 100644 index 00000000000..2d1c8f35462 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_interfaces_capture.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp new file mode 100644 index 00000000000..de0f18d3793 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_config.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp new file mode 100644 index 00000000000..183d87d9aa4 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_exception.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp new file mode 100644 index 00000000000..271b1bcc3a4 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp @@ -0,0 +1 @@ +#include "catch_interfaces_generators.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp new file mode 100644 index 00000000000..ffece3b4317 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_interfaces_registry_hub.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp new file mode 100644 index 00000000000..544f9d0f081 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_reporter.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp new file mode 100644 index 00000000000..401de26251a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp @@ -0,0 +1 @@ +#include "catch_interfaces_runner.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp new file mode 100644 index 00000000000..733dcb4e547 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp @@ -0,0 +1,2 @@ +#include "catch_suppress_warnings.h" +#include "catch_interfaces_testcase.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp new file mode 100644 index 00000000000..ad2f5e77a1e --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_message.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_message.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp new file mode 100644 index 00000000000..35e3282901c --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_option.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_option.hpp" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp new file mode 100644 index 00000000000..a25ad66dfc2 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_ptr.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_ptr.hpp" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp new file mode 100644 index 00000000000..7aaffa1e709 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_stream.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_stream.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp new file mode 100644 index 00000000000..5c0043c2d8a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_streambuf.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp new file mode 100644 index 00000000000..46bf89f681c --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_test_spec.hpp" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp new file mode 100644 index 00000000000..15328efe74a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp @@ -0,0 +1,4 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_xmlwriter.hpp" +#include "catch_reenable_warnings.h" diff --git a/3rdparty/sol2/Catch/projects/SelfTest/TagAliasTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/TagAliasTests.cpp new file mode 100644 index 00000000000..002a93c04e9 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/TagAliasTests.cpp @@ -0,0 +1,41 @@ +/* + * Created by Phil on 27/06/2014. + * Copyright 2014 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" +#include "internal/catch_tag_alias_registry.h" + +TEST_CASE( "Tag alias can be registered against tag patterns", "" ) { + + using namespace Catch::Matchers; + + Catch::TagAliasRegistry registry; + + registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); + + SECTION( "The same tag alias can only be registered once", "" ) { + + try { + registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 10 ) ); + FAIL( "expected exception" ); + } + catch( std::exception& ex ) { + std::string what = ex.what(); + CHECK_THAT( what, Contains( "[@zzz]" ) ); + CHECK_THAT( what, Contains( "file" ) ); + CHECK_THAT( what, Contains( "2" ) ); + CHECK_THAT( what, Contains( "10" ) ); + } + } + + SECTION( "Tag aliases must be of the form [@name]", "" ) { + CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ); + CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ); + CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ); + CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) ); + } +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/TestMain.cpp b/3rdparty/sol2/Catch/projects/SelfTest/TestMain.cpp new file mode 100644 index 00000000000..1713b51aad1 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/TestMain.cpp @@ -0,0 +1,461 @@ +/* + * Created by Phil on 22/10/2010. + * Copyright 2010 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" +#include "../include/reporters/catch_reporter_teamcity.hpp" + +// Some example tag aliases +CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) +CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" ) + + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + + +template +void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { + Catch::Clara::CommandLine parser = Catch::makeCommandLineParser(); + parser.parseInto( size, argv, config ); +} + +template +std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::ConfigData& config ) { + try { + parseIntoConfig( argv, config ); + FAIL( "expected exception" ); + } + catch( std::exception& ex ) { + return ex.what(); + } + return ""; +} + +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } + +TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { + + using namespace Catch::Matchers; + + Catch::ConfigData config; + + SECTION( "default - no arguments", "" ) { + const char* argv[] = { "test" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + CHECK( config.shouldDebugBreak == false ); + CHECK( config.abortAfter == -1 ); + CHECK( config.noThrow == false ); + CHECK( config.reporterNames.empty() ); + } + + SECTION( "test lists", "" ) { + SECTION( "1 test", "Specify one test case using" ) { + const char* argv[] = { "test", "test1" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + Catch::Config cfg( config ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) ); + } + SECTION( "Specify one test case exclusion using exclude:", "" ) { + const char* argv[] = { "test", "exclude:test1" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + Catch::Config cfg( config ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ); + } + + SECTION( "Specify one test case exclusion using ~", "" ) { + const char* argv[] = { "test", "~test1" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + Catch::Config cfg( config ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ); + REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ); + } + + } + + SECTION( "reporter", "" ) { + SECTION( "-r/console", "" ) { + const char* argv[] = { "test", "-r", "console" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames[0] == "console" ); + } + SECTION( "-r/xml", "" ) { + const char* argv[] = { "test", "-r", "xml" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames[0] == "xml" ); + } + SECTION( "-r xml and junit", "" ) { + const char* argv[] = { "test", "-r", "xml", "-r", "junit" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames.size() == 2 ); + REQUIRE( config.reporterNames[0] == "xml" ); + REQUIRE( config.reporterNames[1] == "junit" ); + } + SECTION( "--reporter/junit", "" ) { + const char* argv[] = { "test", "--reporter", "junit" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames[0] == "junit" ); + } + } + + SECTION( "debugger", "" ) { + SECTION( "-b", "" ) { + const char* argv[] = { "test", "-b" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.shouldDebugBreak == true ); + } + SECTION( "--break", "" ) { + const char* argv[] = { "test", "--break" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.shouldDebugBreak ); + } + } + + SECTION( "abort", "" ) { + SECTION( "-a aborts after first failure", "" ) { + const char* argv[] = { "test", "-a" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.abortAfter == 1 ); + } + SECTION( "-x 2 aborts after two failures", "" ) { + const char* argv[] = { "test", "-x", "2" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.abortAfter == 2 ); + } + SECTION( "-x must be greater than zero", "" ) { + const char* argv[] = { "test", "-x", "0" }; + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ); + } + SECTION( "-x must be numeric", "" ) { + const char* argv[] = { "test", "-x", "oops" }; + REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ); + } + } + + SECTION( "nothrow", "" ) { + SECTION( "-e", "" ) { + const char* argv[] = { "test", "-e" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.noThrow == true ); + } + SECTION( "--nothrow", "" ) { + const char* argv[] = { "test", "--nothrow" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.noThrow == true ); + } + } + + SECTION( "output filename", "" ) { + SECTION( "-o filename", "" ) { + const char* argv[] = { "test", "-o", "filename.ext" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.outputFilename == "filename.ext" ); + } + SECTION( "--out", "" ) { + const char* argv[] = { "test", "--out", "filename.ext" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.outputFilename == "filename.ext" ); + } + } + + SECTION( "combinations", "" ) { + SECTION( "Single character flags can be combined", "" ) { + const char* argv[] = { "test", "-abe" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + CHECK( config.abortAfter == 1 ); + CHECK( config.shouldDebugBreak ); + CHECK( config.noThrow == true ); + } + } + + SECTION( "force-colour", "") { + SECTION( "--force-colour", "" ) { + const char* argv[] = { "test", "--force-colour" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.forceColour ); + } + + SECTION( "without --force-colour", "" ) { + const char* argv[] = { "test" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( !config.forceColour ); + } + } +} + + +TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { + + using namespace Catch; + SECTION( "plain string", "" ) { + // guide: 123456789012345678 + std::string testString = "one two three four"; + + SECTION( "No wrapping", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); + } + SECTION( "Wrapped once", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ); + } + SECTION( "Wrapped twice", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); + } + SECTION( "Wrapped three times", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ); + } + SECTION( "Short wrap", "" ) { + CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ); + CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ); + CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ); + + CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ); + } + SECTION( "As container", "" ) { + Text text( testString, TextAttributes().setWidth( 6 ) ); + REQUIRE( text.size() == 4 ); + CHECK( text[0] == "one" ); + CHECK( text[1] == "two" ); + CHECK( text[2] == "three" ); + CHECK( text[3] == "four" ); + } + SECTION( "Indent first line differently", "" ) { + Text text( testString, TextAttributes() + .setWidth( 10 ) + .setIndent( 4 ) + .setInitialIndent( 1 ) ); + CHECK( text.toString() == " one two\n three\n four" ); + } + + } + + SECTION( "With newlines", "" ) { + + // guide: 1234567890123456789 + std::string testString = "one two\nthree four"; + + SECTION( "No wrapping" , "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); + CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ); + } + SECTION( "Trailing newline" , "" ) { + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" ); + CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" ); + } + SECTION( "Wrapped once", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); + } + SECTION( "Wrapped twice", "" ) { + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); + } + } + + SECTION( "With tabs", "" ) { + + // guide: 1234567890123456789 + std::string testString = "one two \tthree four five six"; + + CHECK( Text( testString, TextAttributes().setWidth( 15 ) ).toString() + == "one two three\n four\n five\n six" ); + } + + +} + +using namespace Catch; + +class ColourString { +public: + + struct ColourIndex { + ColourIndex( Colour::Code _colour, std::size_t _fromIndex, std::size_t _toIndex ) + : colour( _colour ), + fromIndex( _fromIndex ), + toIndex( _toIndex ) + {} + + Colour::Code colour; + std::size_t fromIndex; + std::size_t toIndex; + }; + + ColourString( std::string const& _string ) + : string( _string ) + {} + ColourString( std::string const& _string, std::vector const& _colours ) + : string( _string ), colours( _colours ) + {} + + ColourString& addColour( Colour::Code colour, int _index ) { + colours.push_back( ColourIndex( colour, + resolveRelativeIndex( _index ), + resolveRelativeIndex( _index )+1 ) ); + return *this; + } + ColourString& addColour( Colour::Code colour, int _fromIndex, int _toIndex ) { + colours.push_back( ColourIndex( colour, + resolveRelativeIndex(_fromIndex), + resolveLastRelativeIndex( _toIndex ) ) ); + return *this; + } + + void writeToStream( std::ostream& _stream ) const { + std::size_t last = 0; + for( std::size_t i = 0; i < colours.size(); ++i ) { + ColourIndex const& index = colours[i]; + if( index.fromIndex > last ) + _stream << string.substr( last, index.fromIndex-last ); + { + Colour colourGuard( index.colour ); + _stream << string.substr( index.fromIndex, index.toIndex-index.fromIndex ); + } + last = index.toIndex; + } + if( last < string.size() ) + _stream << string.substr( last ); + } + friend std::ostream& operator << ( std::ostream& _stream, ColourString const& _colourString ) { + _colourString.writeToStream( _stream ); + return _stream; + } + +private: + + std::size_t resolveLastRelativeIndex( int _index ) { + std::size_t index = resolveRelativeIndex( _index ); + return index == 0 ? string.size() : index; + } + std::size_t resolveRelativeIndex( int _index ) { + return static_cast( _index >= 0 + ? _index + : static_cast( string.size() )+_index ); + } + std::string string; + std::vector colours; +}; + +TEST_CASE( "replaceInPlace", "" ) { + std::string letters = "abcdefcg"; + SECTION( "replace single char" ) { + CHECK( replaceInPlace( letters, "b", "z" ) ); + CHECK( letters == "azcdefcg" ); + } + SECTION( "replace two chars" ) { + CHECK( replaceInPlace( letters, "c", "z" ) ); + CHECK( letters == "abzdefzg" ); + } + SECTION( "replace first char" ) { + CHECK( replaceInPlace( letters, "a", "z" ) ); + CHECK( letters == "zbcdefcg" ); + } + SECTION( "replace last char" ) { + CHECK( replaceInPlace( letters, "g", "z" ) ); + CHECK( letters == "abcdefcz" ); + } + SECTION( "replace all chars" ) { + CHECK( replaceInPlace( letters, letters, "replaced" ) ); + CHECK( letters == "replaced" ); + } + SECTION( "replace no chars" ) { + CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ); + CHECK( letters == letters ); + } + SECTION( "escape '" ) { + std::string s = "didn't"; + CHECK( replaceInPlace( s, "'", "|'" ) ); + CHECK( s == "didn|'t" ); + } +} + +// !TBD: This will be folded into Text class +TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) { + + { + ColourString cs( "hello" ); + cs .addColour( Colour::Red, 0 ) + .addColour( Colour::Green, -1 ); + + Catch::cout() << cs << std::endl; + } + + { + ColourString cs( "hello" ); + cs .addColour( Colour::Blue, 1, -2 ); + + Catch::cout() << cs << std::endl; + } + +} + +TEST_CASE( "Text can be formatted using the Text class", "" ) { + + CHECK( Text( "hi there" ).toString() == "hi there" ); + + TextAttributes narrow; + narrow.setWidth( 6 ); + + CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ); +} + +TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) { + + std::string longLine( 90, '*' ); + + std::ostringstream oss; + for(int i = 0; i < 600; ++i ) + oss << longLine << longLine << "\n"; + Text t( oss.str() ); + CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ); + +} + +inline void manuallyRegisteredTestFunction() { + SUCCEED( "was called" ); +} +struct AutoTestReg { + AutoTestReg() { + REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered", "" ); + } +}; +AutoTestReg autoTestReg; diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ToStringPair.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ToStringPair.cpp new file mode 100644 index 00000000000..8f51070069b --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ToStringPair.cpp @@ -0,0 +1,47 @@ +#include "catch.hpp" + +// === Pair === +namespace Catch { + // Note: If we put this in the right place in catch_tostring, then + // we can make it an overload of Catch::toString + template + struct StringMaker > { + static std::string convert( const std::pair& pair ) { + std::ostringstream oss; + oss << "{ " + << toString( pair.first ) + << ", " + << toString( pair.second ) + << " }"; + return oss.str(); + } + }; +} + +TEST_CASE( "std::pair -> toString", "[toString][pair]" ) { + std::pair value( 34, "xyzzy" ); + REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" ); +} + +TEST_CASE( "std::pair -> toString", "[toString][pair]" ) { + std::pair value( 34, "xyzzy" ); + REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" ); +} + +TEST_CASE( "std::vector > -> toString", "[toString][pair]" ) { + std::vector > pr; + pr.push_back( std::make_pair("green", 55 ) ); + REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" ); +} + +// This is pretty contrived - I figure if this works, anything will... +TEST_CASE( "pair > -> toString", "[toString][pair]" ) { + typedef std::pair left_t; + typedef std::pair right_t; + + left_t left( 42, "Arthur" ); + right_t right( "Ford", 24 ); + + std::pair pair( left, right ); + REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ); +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ToStringTuple.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ToStringTuple.cpp new file mode 100644 index 00000000000..80e5453097a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ToStringTuple.cpp @@ -0,0 +1,59 @@ +#include "catch.hpp" + +#ifdef CATCH_CPP11_OR_GREATER + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +TEST_CASE( "tuple<>", "[toString][tuple]" ) +{ + typedef std::tuple<> type; + CHECK( "{ }" == Catch::toString(type{}) ); + type value {}; + CHECK( "{ }" == Catch::toString(value) ); +} + +TEST_CASE( "tuple", "[toString][tuple]" ) +{ + typedef std::tuple type; + CHECK( "{ 0 }" == Catch::toString(type{0}) ); +} + + +TEST_CASE( "tuple", "[toString][tuple]" ) +{ + typedef std::tuple type; + CHECK( "1.2f" == Catch::toString(float(1.2)) ); + CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) ); +} + +TEST_CASE( "tuple", "[toString][tuple]" ) +{ + typedef std::tuple type; + CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) ); +} + +TEST_CASE( "tuple,tuple<>,float>", "[toString][tuple]" ) +{ + typedef std::tuple,std::tuple<>,float> type; + type value { std::tuple{42}, {}, 1.2f }; + CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +TEST_CASE( "tuple", "[toString][tuple]" ) +{ + typedef std::tuple type; + type value { nullptr, 42, "Catch me" }; + CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ); +} +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif /* #ifdef CATCH_CPP11_OR_GREATER */ + diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ToStringVector.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ToStringVector.cpp new file mode 100644 index 00000000000..c3a8d4ed647 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ToStringVector.cpp @@ -0,0 +1,77 @@ +#include "catch.hpp" +#include + + +// vedctor +TEST_CASE( "vector -> toString", "[toString][vector]" ) +{ + std::vector vv; + REQUIRE( Catch::toString(vv) == "{ }" ); + vv.push_back( 42 ); + REQUIRE( Catch::toString(vv) == "{ 42 }" ); + vv.push_back( 250 ); + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ); +} + +TEST_CASE( "vector -> toString", "[toString][vector]" ) +{ + std::vector vv; + REQUIRE( Catch::toString(vv) == "{ }" ); + vv.push_back( "hello" ); + REQUIRE( Catch::toString(vv) == "{ \"hello\" }" ); + vv.push_back( "world" ); + REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ); +} + +#if defined(CATCH_CPP11_OR_GREATER) +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +/* + Note: These tests *can* be made to work with C++ < 11, but the + allocator is a lot more work... +*/ +namespace { + /* Minimal Allocator */ + template + struct minimal_allocator { + typedef T value_type; + typedef std::size_t size_type; + T *allocate( size_type n ) { + return static_cast( ::operator new( n * sizeof(T) ) ); + } + void deallocate( T *p, size_type /*n*/ ) { + ::operator delete( static_cast(p) ); + } + template + bool operator==( const minimal_allocator& ) const { return true; } + template + bool operator!=( const minimal_allocator& ) const { return false; } + }; +} + +TEST_CASE( "vector -> toString", "[toString][vector,allocator]" ) { + std::vector > vv; + REQUIRE( Catch::toString(vv) == "{ }" ); + vv.push_back( 42 ); + REQUIRE( Catch::toString(vv) == "{ 42 }" ); + vv.push_back( 250 ); + REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ); +} + +TEST_CASE( "vec> -> toString", "[toString][vector,allocator]" ) { + typedef std::vector > inner; + typedef std::vector vector; + vector v; + REQUIRE( Catch::toString(v) == "{ }" ); + v.push_back( inner { "hello" } ); + v.push_back( inner { "world" } ); + REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +#endif // CATCH_CPP11_OR_GREATER diff --git a/3rdparty/sol2/Catch/projects/SelfTest/ToStringWhich.cpp b/3rdparty/sol2/Catch/projects/SelfTest/ToStringWhich.cpp new file mode 100644 index 00000000000..1d4aa892581 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/ToStringWhich.cpp @@ -0,0 +1,68 @@ +#include "catch.hpp" +/* + Demonstrate which version of toString/StringMaker is being used + for various types +*/ + + +struct has_toString { }; +struct has_maker {}; +struct has_maker_and_toString {}; + +namespace Catch { + inline std::string toString( const has_toString& ) { + return "toString( has_toString )"; + } + inline std::string toString( const has_maker_and_toString& ) { + return "toString( has_maker_and_toString )"; + } + template<> + struct StringMaker { + static std::string convert( const has_maker& ) { + return "StringMaker"; + } + }; + template<> + struct StringMaker { + static std::string convert( const has_maker_and_toString& ) { + return "StringMaker"; + } + }; +} + +// Call the overload +TEST_CASE( "toString( has_toString )", "[toString]" ) { + has_toString item; + REQUIRE( Catch::toString( item ) == "toString( has_toString )" ); +} + +// Call the overload +TEST_CASE( "toString( has_maker )", "[toString]" ) { + has_maker item; + REQUIRE( Catch::toString( item ) == "StringMaker" ); +} + +// Call the overload +TEST_CASE( "toString( has_maker_and_toString )", "[toString]" ) { + has_maker_and_toString item; + REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" ); +} + +// Vectors... +TEST_CASE( "toString( vectors v(1); + // This invokes template toString which actually gives us '{ ? }' + REQUIRE( Catch::toString( v ) == "{ {?} }" ); +} + +TEST_CASE( "toString( vectors v(1); + REQUIRE( Catch::toString( v ) == "{ StringMaker }" ); +} + + +TEST_CASE( "toString( vectors v(1); + // Note: This invokes the template toString -> StringMaker + REQUIRE( Catch::toString( v ) == "{ StringMaker }" ); +} diff --git a/3rdparty/sol2/Catch/projects/SelfTest/TrickyTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/TrickyTests.cpp new file mode 100644 index 00000000000..eb53e420156 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/TrickyTests.cpp @@ -0,0 +1,401 @@ +/* + * Created by Phil on 09/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include "catch.hpp" + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +namespace Catch +{ + template<> + std::string toString >( const std::pair& value ) + { + std::ostringstream oss; + oss << "std::pair( " << value.first << ", " << value.second << " )"; + return oss.str(); + + } +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Parsing a std::pair", + "[Tricky][std::pair]" +) +{ + std::pair aNicePair( 1, 2 ); + + REQUIRE( (std::pair( 1, 2 )) == aNicePair ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Where there is more to the expression after the RHS", + "[Tricky][failing][.]" +) +{ +// int a = 1, b = 2; +// REQUIRE( a == 2 || b == 2 ); + WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); +} +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "Where the LHS is not a simple value", + "[Tricky][failing][.]" +) +{ + /* + int a = 1; + int b = 2; + + // This only captures part of the expression, but issues a warning about the rest + REQUIRE( a+1 == b-1 ); + */ + WARN( "Uncomment the code in this test to check that it gives a sensible compiler error" ); +} + +struct Opaque +{ + int val; + bool operator ==( const Opaque& o ) const + { + return val == o.val; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "A failing expression with a non streamable type is still captured", + "[Tricky][failing][.]" +) +{ + + Opaque o1, o2; + o1.val = 7; + o2.val = 8; + + CHECK( &o1 == &o2 ); + CHECK( o1 == o2 ); +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "string literals of different sizes can be compared", + "[Tricky][failing][.]" +) +{ + REQUIRE( std::string( "first" ) == "second" ); + +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "An expression with side-effects should only be evaluated once", + "[Tricky]" +) +{ + int i = 7; + + REQUIRE( i++ == 7 ); + REQUIRE( i++ == 8 ); + +} + +namespace A { + struct X + { + X() : a(4), b(2), c(7) {} + X(int v) : a(v), b(2), c(7) {} + int a; + int b; + int c; + }; +} + +namespace B { + struct Y + { + Y() : a(4), b(2), c(7) {} + Y(int v) : a(v), b(2), c(7) {} + int a; + int b; + int c; + }; +} + +inline bool operator==(const A::X& lhs, const B::Y& rhs) +{ + return (lhs.a == rhs.a); +} + +inline bool operator==(const B::Y& lhs, const A::X& rhs) +{ + return (lhs.a == rhs.a); +} + + +/////////////////////////////////////////////////////////////////////////////// +/* This, currently, does not compile with LLVM +TEST_CASE +( + "Operators at different namespace levels not hijacked by Koenig lookup" + "[Tricky]" +) +{ + A::X x; + B::Y y; + REQUIRE( x == y ); +} +*/ + +namespace ObjectWithConversions +{ + struct Object + { + operator unsigned int() {return 0xc0000000;} + }; + + /////////////////////////////////////////////////////////////////////////////// + TEST_CASE + ( + "Operators at different namespace levels not hijacked by Koenig lookup", + "[Tricky]" + ) + { + Object o; + REQUIRE(0xc0000000 == o ); + } +} + +namespace ObjectWithNonConstEqualityOperator +{ + struct Test + { + Test( unsigned int v ) + : m_value(v) + {} + + bool operator==( const Test&rhs ) + { + return (m_value == rhs.m_value); + } + bool operator==( const Test&rhs ) const + { + return (m_value != rhs.m_value); + } + unsigned int m_value; + }; + + TEST_CASE("Demonstrate that a non-const == is not used", "[Tricky]" ) + { + Test t( 1 ); + REQUIRE( t == 1u ); + } +} + +namespace EnumBitFieldTests +{ + enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006, + bit30 = 0x40000000, bit31 = 0x80000000, + bit30and31 = 0xc0000000}; + + TEST_CASE( "Test enum bit values", "[Tricky]" ) + { + REQUIRE( 0xc0000000 == bit30and31 ); + } +} + +struct Obj +{ + Obj():prop(&p){} + + int p; + int* prop; +}; + +TEST_CASE("boolean member", "[Tricky]") +{ + Obj obj; + REQUIRE( obj.prop != CATCH_NULL ); +} + +// Tests for a problem submitted by Ralph McArdell +// +// The static bool value should not need to be defined outside the +// struct it is declared in - but when evaluating it in a deduced +// context it appears to require the extra definition. +// The issue was fixed by adding bool overloads to bypass the +// templates that were there to deduce it. +template +struct is_true +{ + static const bool value = B; +}; + +TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" ) +{ + SECTION("compare to true","") + { + REQUIRE( is_true::value == true ); + REQUIRE( true == is_true::value ); + } + SECTION("compare to false","") + { + REQUIRE( is_true::value == false ); + REQUIRE( false == is_true::value ); + } + + SECTION("negation", "") + { + REQUIRE( !is_true::value ); + } + + SECTION("double negation","") + { + REQUIRE( !!is_true::value ); + } + + SECTION("direct","") + { + REQUIRE( is_true::value ); + REQUIRE_FALSE( is_true::value ); + } +} + +// Uncomment these tests to produce an error at test registration time +/* +TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) +{ + +} +TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) +{ + +} +*/ + +struct Boolable +{ + explicit Boolable( bool value ) : m_value( value ) {} + + operator Catch::SafeBool::type() const { + return Catch::SafeBool::makeSafe( m_value ); + } + + bool m_value; +}; + +TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" ) +{ + Boolable True( true ); + Boolable False( false ); + + CHECK( True ); + CHECK( !False ); + CHECK_FALSE( False ); +} + +TEST_CASE( "Assertions then sections", "[Tricky]" ) +{ + // This was causing a failure due to the way the console reporter was handling + // the current section + + REQUIRE( Catch::alwaysTrue() ); + + SECTION( "A section", "" ) + { + REQUIRE( Catch::alwaysTrue() ); + + SECTION( "Another section", "" ) + { + REQUIRE( Catch::alwaysTrue() ); + } + SECTION( "Another other section", "" ) + { + REQUIRE( Catch::alwaysTrue() ); + } + } +} + +struct Awkward +{ + operator int() const { return 7; } +}; + +TEST_CASE( "non streamable - with conv. op", "[Tricky]" ) +{ + Awkward awkward; + std::string s = Catch::toString( awkward ); + REQUIRE( s == "7" ); +} + +inline void foo() {} + +typedef void (*fooptr_t)(); + +TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" ) +{ + // This was giving a warning in VS2010 + // #179 + fooptr_t a = foo; + + REQUIRE( a ); + REQUIRE( a == &foo ); +} + +struct S +{ + void f() {} +}; + + +TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer]" ) +{ + typedef void (S::*MF)(); + MF m = &S::f; + + CHECK( m == &S::f ); +} + +class ClassName {}; + +TEST_CASE( "pointer to class", "[Tricky]" ) +{ + ClassName *p = 0; + REQUIRE( p == 0 ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + +#include + +TEST_CASE( "null_ptr", "[Tricky][c++11]" ) +{ + std::unique_ptr ptr; + REQUIRE(ptr.get() == nullptr); +} + +#endif + +TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); } +TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); } +TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); } +TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); } diff --git a/3rdparty/sol2/Catch/projects/SelfTest/VariadicMacrosTests.cpp b/3rdparty/sol2/Catch/projects/SelfTest/VariadicMacrosTests.cpp new file mode 100644 index 00000000000..b784076d89f --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/VariadicMacrosTests.cpp @@ -0,0 +1,31 @@ +/* + * Created by Phil on 15/03/2013. + * Copyright 2013 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch.hpp" + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + +TEST_CASE() +{ + SUCCEED( "anonymous test case" ); +} + +TEST_CASE( "Test case with one argument" ) +{ + SUCCEED( "no assertions" ); +} + +TEST_CASE( "Variadic macros", "[variadic][sections]" ) +{ + SECTION( "Section with one argument" ) + { + SUCCEED( "no assertions" ); + } +} + +#endif diff --git a/3rdparty/sol2/Catch/projects/SelfTest/makefile b/3rdparty/sol2/Catch/projects/SelfTest/makefile new file mode 100644 index 00000000000..0a29372c875 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/SelfTest/makefile @@ -0,0 +1,30 @@ +SOURCES = ApproxTests.cpp \ + ClassTests.cpp \ + ConditionTests.cpp \ + ExceptionTests.cpp \ + GeneratorTests.cpp \ + MessageTests.cpp \ + MiscTests.cpp \ + TestMain.cpp \ + TrickyTests.cpp \ + BDDTests.cpp \ + VariadicMacrosTests.cpp \ + EnumToString.cpp \ + ToStringPair.cpp \ + ToStringVector.cpp \ + ToStringWhich.cpp + + +OBJECTS = $(patsubst %.cpp, %.o, $(SOURCES)) +CXX = g++ +CXXFLAGS = -I../../include -std=c++11 + +CatchSelfTest: $(OBJECTS) + $(CXX) -o $@ $^ + +test: CatchSelfTest + ./CatchSelfTest + +clean: + rm -f $(OBJECTS) CatchSelfTest + diff --git a/3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp b/3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp new file mode 100644 index 00000000000..8dd2067d480 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.cpp @@ -0,0 +1,8 @@ +// TestCatch.cpp : Defines the entry point for the console application. +// + +int main(int argc, char* argv[]) +{ + return 0; +} + diff --git a/3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj b/3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj new file mode 100644 index 00000000000..d4cb0c97532 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj @@ -0,0 +1,390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..a26df5361bd --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -0,0 +1,742 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */; }; + 263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */; }; + 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */; }; + 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */; }; + 263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */; }; + 2656C2211925E7330040DB02 /* catch_test_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2656C2201925E7330040DB02 /* catch_test_spec.cpp */; }; + 266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */; }; + 266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266ECD73170F3C620030D735 /* BDDTests.cpp */; }; + 26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */; }; + 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; }; + 2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2691574B1A532A280054F1ED /* ToStringTuple.cpp */; }; + 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; }; + 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E1B7D119213BC900812682 /* CmdLineTests.cpp */; }; + 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */; }; + 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */; }; + 4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */; }; + 4A45DA2B16161F79004F8D6B /* catch_interfaces_registry_hub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2A16161F79004F8D6B /* catch_interfaces_registry_hub.cpp */; }; + 4A45DA2D16161FA2004F8D6B /* catch_interfaces_capture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2C16161FA2004F8D6B /* catch_interfaces_capture.cpp */; }; + 4A45DA3116161FFC004F8D6B /* catch_interfaces_reporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA3016161FFB004F8D6B /* catch_interfaces_reporter.cpp */; }; + 4A45DA3316162047004F8D6B /* catch_interfaces_exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA3216162047004F8D6B /* catch_interfaces_exception.cpp */; }; + 4A45DA3516162071004F8D6B /* catch_interfaces_runner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA3416162071004F8D6B /* catch_interfaces_runner.cpp */; }; + 4A6D0C27149B3D3B00DB3EAA /* CatchSelfTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */; }; + 4A6D0C37149B3D9E00DB3EAA /* ApproxTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */; }; + 4A6D0C38149B3D9E00DB3EAA /* ClassTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C2F149B3D9E00DB3EAA /* ClassTests.cpp */; }; + 4A6D0C39149B3D9E00DB3EAA /* ConditionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C30149B3D9E00DB3EAA /* ConditionTests.cpp */; }; + 4A6D0C3A149B3D9E00DB3EAA /* ExceptionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C31149B3D9E00DB3EAA /* ExceptionTests.cpp */; }; + 4A6D0C3B149B3D9E00DB3EAA /* GeneratorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C32149B3D9E00DB3EAA /* GeneratorTests.cpp */; }; + 4A6D0C3C149B3D9E00DB3EAA /* MessageTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */; }; + 4A6D0C3D149B3D9E00DB3EAA /* MiscTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */; }; + 4A6D0C3E149B3D9E00DB3EAA /* TestMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */; }; + 4A6D0C3F149B3D9E00DB3EAA /* TrickyTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */; }; + 4AB3D99D1616216500C9A0F8 /* catch_interfaces_testcase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AB3D99C1616216500C9A0F8 /* catch_interfaces_testcase.cpp */; }; + 4AB3D9A01616219100C9A0F8 /* catch_interfaces_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */; }; + 4AB3D9A2161621B500C9A0F8 /* catch_interfaces_generators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */; }; + 4ACE21CC166CA1B300FB5509 /* catch_option.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4ACE21CA166CA1B300FB5509 /* catch_option.cpp */; }; + 4AEE032016142F910071E950 /* catch_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE031F16142F910071E950 /* catch_common.cpp */; }; + 4AEE032316142FC70071E950 /* catch_debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE032216142FC70071E950 /* catch_debugger.cpp */; }; + 4AEE032516142FF10071E950 /* catch_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE032416142FF10071E950 /* catch_stream.cpp */; }; + 4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AEE0327161434FD0071E950 /* catch_xmlwriter.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A6D0C1E149B3D3B00DB3EAA /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4A6D0C27149B3D3B00DB3EAA /* CatchSelfTest.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PartTrackerTests.cpp; path = ../../../SelfTest/PartTrackerTests.cpp; sourceTree = ""; }; + 261488FA184C81130041FBEB /* catch_test_spec.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec.hpp; sourceTree = ""; }; + 261488FC184D1DC10041FBEB /* catch_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_stream.h; sourceTree = ""; }; + 261488FD184D21290041FBEB /* catch_section_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section_info.h; sourceTree = ""; }; + 261488FE184DC32F0041FBEB /* catch_section.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section.h; sourceTree = ""; }; + 261488FF184DC4A20041FBEB /* catch_debugger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_debugger.h; sourceTree = ""; }; + 2627F7051935B16F009BCE2D /* catch_result_builder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_result_builder.h; sourceTree = ""; }; + 2627F7061935B55F009BCE2D /* catch_result_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_result_builder.hpp; sourceTree = ""; }; + 262E7399184673A800CAC268 /* catch_reporter_bases.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_bases.hpp; sourceTree = ""; }; + 262E739A1846759000CAC268 /* catch_common.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_common.hpp; sourceTree = ""; }; + 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_fatal_condition.hpp; sourceTree = ""; }; + 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EnumToString.cpp; path = ../../../SelfTest/EnumToString.cpp; sourceTree = ""; }; + 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringPair.cpp; path = ../../../SelfTest/ToStringPair.cpp; sourceTree = ""; }; + 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringVector.cpp; path = ../../../SelfTest/ToStringVector.cpp; sourceTree = ""; }; + 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringWhich.cpp; path = ../../../SelfTest/ToStringWhich.cpp; sourceTree = ""; }; + 263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = ""; }; + 263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = ""; }; + 2656C21F1925E5100040DB02 /* catch_test_spec_parser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec_parser.hpp; sourceTree = ""; }; + 2656C2201925E7330040DB02 /* catch_test_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_spec.cpp; path = ../../../SelfTest/SurrogateCpps/catch_test_spec.cpp; sourceTree = ""; }; + 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_suppress_warnings.h; sourceTree = ""; }; + 2656C227192A78410040DB02 /* catch_reenable_warnings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_reenable_warnings.h; sourceTree = ""; }; + 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = ""; }; + 266ECD73170F3C620030D735 /* BDDTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BDDTests.cpp; path = ../../../SelfTest/BDDTests.cpp; sourceTree = ""; }; + 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_legacy_reporter_adapter.hpp; sourceTree = ""; }; + 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_legacy_reporter_adapter.h; sourceTree = ""; }; + 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TagAliasTests.cpp; path = ../../../SelfTest/TagAliasTests.cpp; sourceTree = ""; }; + 26711C90195D46CD0033EDA2 /* catch_interfaces_tag_alias_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_tag_alias_registry.h; sourceTree = ""; }; + 26711C91195D47820033EDA2 /* catch_tag_alias.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tag_alias.h; sourceTree = ""; }; + 26711C92195D48F60033EDA2 /* catch_tag_alias_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_tag_alias_registry.hpp; sourceTree = ""; }; + 26711C94195D4B120033EDA2 /* catch_tag_alias_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tag_alias_registry.h; sourceTree = ""; }; + 26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_compiler_capabilities.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 26847E5B16BBAB790043B9C1 /* catch_message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_message.h; sourceTree = ""; }; + 26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = ""; }; + 26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = ""; }; + 268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = ""; }; + 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_teamcity.hpp; sourceTree = ""; }; + 2691574B1A532A280054F1ED /* ToStringTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringTuple.cpp; path = ../../../SelfTest/ToStringTuple.cpp; sourceTree = ""; }; + 26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = ""; }; + 26926E8418D77809004E10F2 /* tbc_text_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/external/tbc_text_format.h; sourceTree = ""; }; + 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = ""; }; + 2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = ""; }; + 269831E519078C1600BB0CE0 /* catch_tostring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_tostring.h; sourceTree = ""; }; + 269831E619078CA200BB0CE0 /* catch_tostring.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_tostring.hpp; sourceTree = ""; }; + 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = ""; }; + 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = ""; }; + 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = ""; }; + 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = ""; }; + 26EDFBD91B72011F00B1873C /* catch_reporter_multi.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_multi.hpp; sourceTree = ""; }; + 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = ""; }; + 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = ""; }; + 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_console_colour.cpp; path = ../../../SelfTest/SurrogateCpps/catch_console_colour.cpp; sourceTree = ""; }; + 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_ptr.cpp; path = ../../../SelfTest/SurrogateCpps/catch_ptr.cpp; sourceTree = ""; }; + 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_streambuf.cpp; path = ../../../SelfTest/SurrogateCpps/catch_streambuf.cpp; sourceTree = ""; }; + 4A45DA2A16161F79004F8D6B /* catch_interfaces_registry_hub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_registry_hub.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp; sourceTree = ""; }; + 4A45DA2C16161FA2004F8D6B /* catch_interfaces_capture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_capture.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_capture.cpp; sourceTree = ""; }; + 4A45DA3016161FFB004F8D6B /* catch_interfaces_reporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_reporter.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_reporter.cpp; sourceTree = ""; }; + 4A45DA3216162047004F8D6B /* catch_interfaces_exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_exception.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_exception.cpp; sourceTree = ""; }; + 4A45DA3416162071004F8D6B /* catch_interfaces_runner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_runner.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_runner.cpp; sourceTree = ""; }; + 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_registry_hub.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A4B0F9915CE6EC100AE2392 /* catch_interfaces_registry_hub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_interfaces_registry_hub.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_notimplemented_exception.h; sourceTree = ""; }; + 4A4B0F9B15CEF8C400AE2392 /* catch_notimplemented_exception.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_notimplemented_exception.hpp; sourceTree = ""; }; + 4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_impl.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CatchSelfTest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = CatchSelfTest.1; sourceTree = ""; }; + 4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ApproxTests.cpp; path = ../../../SelfTest/ApproxTests.cpp; sourceTree = ""; }; + 4A6D0C2F149B3D9E00DB3EAA /* ClassTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClassTests.cpp; path = ../../../SelfTest/ClassTests.cpp; sourceTree = ""; }; + 4A6D0C30149B3D9E00DB3EAA /* ConditionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConditionTests.cpp; path = ../../../SelfTest/ConditionTests.cpp; sourceTree = ""; }; + 4A6D0C31149B3D9E00DB3EAA /* ExceptionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionTests.cpp; path = ../../../SelfTest/ExceptionTests.cpp; sourceTree = ""; }; + 4A6D0C32149B3D9E00DB3EAA /* GeneratorTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GeneratorTests.cpp; path = ../../../SelfTest/GeneratorTests.cpp; sourceTree = ""; }; + 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MessageTests.cpp; path = ../../../SelfTest/MessageTests.cpp; sourceTree = ""; }; + 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MiscTests.cpp; path = ../../../SelfTest/MiscTests.cpp; sourceTree = ""; }; + 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestMain.cpp; path = ../../../SelfTest/TestMain.cpp; sourceTree = ""; }; + 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TrickyTests.cpp; path = ../../../SelfTest/TrickyTests.cpp; sourceTree = ""; }; + 4A6D0C42149B3E1500DB3EAA /* catch_session.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = catch_session.hpp; path = ../../../../include/catch_session.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C43149B3E1500DB3EAA /* catch_with_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_with_main.hpp; path = ../../../../include/catch_with_main.hpp; sourceTree = ""; }; + 4A6D0C44149B3E1500DB3EAA /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../../../../include/catch.hpp; sourceTree = ""; }; + 4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_approx.hpp; sourceTree = ""; }; + 4A6D0C47149B3E3D00DB3EAA /* catch_capture.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_capture.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C48149B3E3D00DB3EAA /* catch_commandline.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_commandline.hpp; sourceTree = ""; }; + 4A6D0C49149B3E3D00DB3EAA /* catch_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_common.h; sourceTree = ""; }; + 4A6D0C4A149B3E3D00DB3EAA /* catch_config.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_config.hpp; sourceTree = ""; }; + 4A6D0C4B149B3E3D00DB3EAA /* catch_debugger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_debugger.hpp; sourceTree = ""; }; + 4A6D0C4C149B3E3D00DB3EAA /* catch_default_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_default_main.hpp; sourceTree = ""; }; + 4A6D0C4D149B3E3D00DB3EAA /* catch_evaluate.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_evaluate.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C4E149B3E3D00DB3EAA /* catch_exception_translator_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_exception_translator_registry.hpp; sourceTree = ""; }; + 4A6D0C4F149B3E3D00DB3EAA /* catch_generators.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_generators.hpp; sourceTree = ""; }; + 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_generators_impl.hpp; sourceTree = ""; }; + 4A6D0C51149B3E3D00DB3EAA /* catch_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_context.h; sourceTree = ""; }; + 4A6D0C52149B3E3D00DB3EAA /* catch_context_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_context_impl.hpp; sourceTree = ""; }; + 4A6D0C53149B3E3D00DB3EAA /* catch_interfaces_capture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_capture.h; sourceTree = ""; }; + 4A6D0C54149B3E3D00DB3EAA /* catch_interfaces_exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_interfaces_exception.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 4A6D0C55149B3E3D00DB3EAA /* catch_interfaces_reporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_reporter.h; sourceTree = ""; }; + 4A6D0C56149B3E3D00DB3EAA /* catch_interfaces_runner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_runner.h; sourceTree = ""; }; + 4A6D0C57149B3E3D00DB3EAA /* catch_interfaces_testcase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_testcase.h; sourceTree = ""; }; + 4A6D0C58149B3E3D00DB3EAA /* catch_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_list.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C59149B3E3D00DB3EAA /* catch_objc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_objc.hpp; sourceTree = ""; }; + 4A6D0C5A149B3E3D00DB3EAA /* catch_reporter_registrars.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_reporter_registrars.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C5B149B3E3D00DB3EAA /* catch_reporter_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_registry.hpp; sourceTree = ""; }; + 4A6D0C5C149B3E3D00DB3EAA /* catch_result_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_result_type.h; sourceTree = ""; }; + 4A6D0C5D149B3E3D00DB3EAA /* catch_assertionresult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_assertionresult.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 4A6D0C5E149B3E3D00DB3EAA /* catch_run_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_run_context.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_section.hpp; sourceTree = ""; }; + 4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_stream.hpp; sourceTree = ""; }; + 4A6D0C61149B3E3D00DB3EAA /* catch_test_case_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_test_case_info.h; sourceTree = ""; }; + 4A6D0C62149B3E3D00DB3EAA /* catch_test_case_registry_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_test_case_registry_impl.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C63149B3E3D00DB3EAA /* catch_test_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_test_registry.hpp; sourceTree = ""; }; + 4A6D0C64149B3E3D00DB3EAA /* catch_xmlwriter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_xmlwriter.hpp; sourceTree = ""; }; + 4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_junit.hpp; sourceTree = ""; }; + 4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_xml.hpp; sourceTree = ""; }; + 4A7ADB4314F631E10094FE10 /* catch_totals.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_totals.hpp; sourceTree = ""; }; + 4A7DB2CD1652FE4B00FA6523 /* catch_version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = catch_version.h; path = ../../../../include/internal/catch_version.h; sourceTree = ""; }; + 4A90B59B15D0F61A00EF71BC /* catch_interfaces_generators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_generators.h; sourceTree = ""; }; + 4A90B59D15D24FE900EF71BC /* catch_assertionresult.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_assertionresult.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4AA7B8B4165428BA003155F6 /* catch_version.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = catch_version.hpp; path = ../../../../include/internal/catch_version.hpp; sourceTree = ""; }; + 4AB1C73514F97BDA00F31DF7 /* catch_console_colour_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_console_colour_impl.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4AB1C73714F97C1300F31DF7 /* catch_console_colour.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_console_colour.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4AB3D99C1616216500C9A0F8 /* catch_interfaces_testcase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_testcase.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp; sourceTree = ""; }; + 4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_config.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_config.cpp; sourceTree = ""; }; + 4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_generators.cpp; path = ../../../SelfTest/SurrogateCpps/catch_interfaces_generators.cpp; sourceTree = ""; }; + 4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_console.hpp; sourceTree = ""; }; + 4AB77CB51551AEA200857BF0 /* catch_ptr.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_ptr.hpp; sourceTree = ""; }; + 4AB77CB71553B72B00857BF0 /* catch_section_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_section_info.hpp; sourceTree = ""; }; + 4ABEA80415C90D2B009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_objc_arc.hpp; sourceTree = ""; }; + 4AC91CCE155CF02800DC5117 /* catch_expression_lhs.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_expression_lhs.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4ACE21C8166CA19700FB5509 /* catch_option.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_option.hpp; sourceTree = ""; }; + 4ACE21CA166CA1B300FB5509 /* catch_option.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_option.cpp; path = ../../../SelfTest/SurrogateCpps/catch_option.cpp; sourceTree = ""; }; + 4AEE031F16142F910071E950 /* catch_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_common.cpp; path = ../../../SelfTest/SurrogateCpps/catch_common.cpp; sourceTree = ""; }; + 4AEE032216142FC70071E950 /* catch_debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_debugger.cpp; path = ../../../SelfTest/SurrogateCpps/catch_debugger.cpp; sourceTree = ""; }; + 4AEE032416142FF10071E950 /* catch_stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_stream.cpp; path = ../../../SelfTest/SurrogateCpps/catch_stream.cpp; sourceTree = ""; }; + 4AEE0326161431070071E950 /* catch_streambuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_streambuf.h; sourceTree = ""; }; + 4AEE0327161434FD0071E950 /* catch_xmlwriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_xmlwriter.cpp; path = ../../../SelfTest/SurrogateCpps/catch_xmlwriter.cpp; sourceTree = ""; }; + 4AFC661D157E96A7009D58CF /* catch_interfaces_config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_config.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A6D0C1D149B3D3B00DB3EAA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 266E9AD317290E710061DAB2 /* Introspective Tests */ = { + isa = PBXGroup; + children = ( + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */, + 26E1B7D119213BC900812682 /* CmdLineTests.cpp */, + 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */, + ); + name = "Introspective Tests"; + sourceTree = ""; + }; + 26C5F3EB17514B670056FB3C /* External */ = { + isa = PBXGroup; + children = ( + 26926E8418D77809004E10F2 /* tbc_text_format.h */, + 26926E8318D7777D004E10F2 /* clara.h */, + ); + name = External; + sourceTree = ""; + }; + 4A6D0C15149B3D3B00DB3EAA = { + isa = PBXGroup; + children = ( + 4A6D0C23149B3D3B00DB3EAA /* CatchSelfTest */, + 4A6D0C21149B3D3B00DB3EAA /* Products */, + ); + sourceTree = ""; + }; + 4A6D0C21149B3D3B00DB3EAA /* Products */ = { + isa = PBXGroup; + children = ( + 4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */, + ); + name = Products; + sourceTree = ""; + }; + 4A6D0C23149B3D3B00DB3EAA /* CatchSelfTest */ = { + isa = PBXGroup; + children = ( + 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */, + 266E9AD317290E710061DAB2 /* Introspective Tests */, + 4A6D0C40149B3DAB00DB3EAA /* Tests */, + 4A6D0C41149B3DE900DB3EAA /* Catch */, + 4A6D0C26149B3D3B00DB3EAA /* CatchSelfTest.1 */, + ); + path = CatchSelfTest; + sourceTree = ""; + }; + 4A6D0C40149B3DAB00DB3EAA /* Tests */ = { + isa = PBXGroup; + children = ( + 2691574B1A532A280054F1ED /* ToStringTuple.cpp */, + 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */, + 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */, + 263F7A4A19B6FE1E009474C2 /* ToStringWhich.cpp */, + 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */, + 266ECD73170F3C620030D735 /* BDDTests.cpp */, + 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */, + 4A6D0C2D149B3D9E00DB3EAA /* ApproxTests.cpp */, + 4A6D0C2F149B3D9E00DB3EAA /* ClassTests.cpp */, + 4A6D0C30149B3D9E00DB3EAA /* ConditionTests.cpp */, + 4A6D0C31149B3D9E00DB3EAA /* ExceptionTests.cpp */, + 4A6D0C32149B3D9E00DB3EAA /* GeneratorTests.cpp */, + 4A6D0C33149B3D9E00DB3EAA /* MessageTests.cpp */, + 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */, + 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */, + ); + name = Tests; + sourceTree = ""; + }; + 4A6D0C41149B3DE900DB3EAA /* Catch */ = { + isa = PBXGroup; + children = ( + 26C5F3EB17514B670056FB3C /* External */, + 4A7DB2CD1652FE4B00FA6523 /* catch_version.h */, + 4AA7B8B4165428BA003155F6 /* catch_version.hpp */, + 4A8E4DCF160A34E200194CBD /* SurrogateCpps */, + 4A6D0C44149B3E1500DB3EAA /* catch.hpp */, + 4A6D0C42149B3E1500DB3EAA /* catch_session.hpp */, + 4A6D0C43149B3E1500DB3EAA /* catch_with_main.hpp */, + 4A6D0C45149B3E3D00DB3EAA /* internal */, + 4A6D0C65149B3E3D00DB3EAA /* reporters */, + ); + name = Catch; + sourceTree = ""; + }; + 4A6D0C45149B3E3D00DB3EAA /* internal */ = { + isa = PBXGroup; + children = ( + 4AC91CC3155C38D300DC5117 /* Objective-C */, + 4AC91CC2155C388300DC5117 /* Infrastructure */, + 4AC91CC1155C387400DC5117 /* Interfaces */, + 4AC91CC0155C384400DC5117 /* Process */, + 4AC91CBF155C381600DC5117 /* Test execution */, + 4AC91CBE155C37F800DC5117 /* Registries */, + 4AC91CBD155C37B500DC5117 /* Assertions */, + 4AC91CB4155B9EBF00DC5117 /* impl */, + ); + name = internal; + path = ../../../../include/internal; + sourceTree = ""; + }; + 4A6D0C65149B3E3D00DB3EAA /* reporters */ = { + isa = PBXGroup; + children = ( + 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */, + 262E7399184673A800CAC268 /* catch_reporter_bases.hpp */, + 4A6D0C67149B3E3D00DB3EAA /* catch_reporter_junit.hpp */, + 4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */, + 4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */, + 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */, + 26EDFBD91B72011F00B1873C /* catch_reporter_multi.hpp */, + ); + name = reporters; + path = ../../../../include/reporters; + sourceTree = ""; + }; + 4A8E4DCF160A34E200194CBD /* SurrogateCpps */ = { + isa = PBXGroup; + children = ( + 2656C2201925E7330040DB02 /* catch_test_spec.cpp */, + 4AEE031F16142F910071E950 /* catch_common.cpp */, + 4AEE032216142FC70071E950 /* catch_debugger.cpp */, + 4AEE032416142FF10071E950 /* catch_stream.cpp */, + 4AEE0327161434FD0071E950 /* catch_xmlwriter.cpp */, + 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */, + 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */, + 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */, + 4A45DA2A16161F79004F8D6B /* catch_interfaces_registry_hub.cpp */, + 4A45DA2C16161FA2004F8D6B /* catch_interfaces_capture.cpp */, + 4A45DA3216162047004F8D6B /* catch_interfaces_exception.cpp */, + 4A45DA3016161FFB004F8D6B /* catch_interfaces_reporter.cpp */, + 4A45DA3416162071004F8D6B /* catch_interfaces_runner.cpp */, + 4AB3D99C1616216500C9A0F8 /* catch_interfaces_testcase.cpp */, + 4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */, + 4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */, + 4ACE21CA166CA1B300FB5509 /* catch_option.cpp */, + 2694A1FB16A0000E004816E3 /* catch_text.cpp */, + 26847E5D16BBADB40043B9C1 /* catch_message.cpp */, + ); + name = SurrogateCpps; + sourceTree = ""; + }; + 4AC91CB4155B9EBF00DC5117 /* impl */ = { + isa = PBXGroup; + children = ( + 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */, + 263FD06017AF8DF200988A20 /* catch_timer.hpp */, + 4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */, + 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */, + 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */, + 4A6D0C52149B3E3D00DB3EAA /* catch_context_impl.hpp */, + 4A6D0C5E149B3E3D00DB3EAA /* catch_run_context.hpp */, + 4A6D0C62149B3E3D00DB3EAA /* catch_test_case_registry_impl.hpp */, + 4AB1C73514F97BDA00F31DF7 /* catch_console_colour_impl.hpp */, + 4A4B0F9B15CEF8C400AE2392 /* catch_notimplemented_exception.hpp */, + 4A90B59D15D24FE900EF71BC /* catch_assertionresult.hpp */, + 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */, + 26847E5C16BBACB60043B9C1 /* catch_message.hpp */, + 2627F7061935B55F009BCE2D /* catch_result_builder.hpp */, + 26711C92195D48F60033EDA2 /* catch_tag_alias_registry.hpp */, + ); + name = impl; + sourceTree = ""; + }; + 4AC91CBD155C37B500DC5117 /* Assertions */ = { + isa = PBXGroup; + children = ( + 269831E519078C1600BB0CE0 /* catch_tostring.h */, + 269831E619078CA200BB0CE0 /* catch_tostring.hpp */, + 4A6D0C4D149B3E3D00DB3EAA /* catch_evaluate.hpp */, + 4A6D0C4F149B3E3D00DB3EAA /* catch_generators.hpp */, + 4A6D0C5C149B3E3D00DB3EAA /* catch_result_type.h */, + 4A6D0C5D149B3E3D00DB3EAA /* catch_assertionresult.h */, + 261488FE184DC32F0041FBEB /* catch_section.h */, + 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */, + 4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */, + 4A6D0C47149B3E3D00DB3EAA /* catch_capture.hpp */, + 4AC91CCE155CF02800DC5117 /* catch_expression_lhs.hpp */, + 4A4B0F9A15CEF84800AE2392 /* catch_notimplemented_exception.h */, + 26847E5B16BBAB790043B9C1 /* catch_message.h */, + 261488FD184D21290041FBEB /* catch_section_info.h */, + 2627F7051935B16F009BCE2D /* catch_result_builder.h */, + ); + name = Assertions; + sourceTree = ""; + }; + 4AC91CBE155C37F800DC5117 /* Registries */ = { + isa = PBXGroup; + children = ( + 4A6D0C4E149B3E3D00DB3EAA /* catch_exception_translator_registry.hpp */, + 4A6D0C5A149B3E3D00DB3EAA /* catch_reporter_registrars.hpp */, + 4A6D0C5B149B3E3D00DB3EAA /* catch_reporter_registry.hpp */, + 4A6D0C63149B3E3D00DB3EAA /* catch_test_registry.hpp */, + ); + name = Registries; + sourceTree = ""; + }; + 4AC91CBF155C381600DC5117 /* Test execution */ = { + isa = PBXGroup; + children = ( + 261488FA184C81130041FBEB /* catch_test_spec.hpp */, + 2656C21F1925E5100040DB02 /* catch_test_spec_parser.hpp */, + 4A6D0C4A149B3E3D00DB3EAA /* catch_config.hpp */, + 4A6D0C51149B3E3D00DB3EAA /* catch_context.h */, + 4A6D0C61149B3E3D00DB3EAA /* catch_test_case_info.h */, + 4A7ADB4314F631E10094FE10 /* catch_totals.hpp */, + 4AB77CB71553B72B00857BF0 /* catch_section_info.hpp */, + 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */, + 26711C91195D47820033EDA2 /* catch_tag_alias.h */, + 26711C94195D4B120033EDA2 /* catch_tag_alias_registry.h */, + ); + name = "Test execution"; + sourceTree = ""; + }; + 4AC91CC0155C384400DC5117 /* Process */ = { + isa = PBXGroup; + children = ( + 4A6D0C58149B3E3D00DB3EAA /* catch_list.hpp */, + 4A6D0C48149B3E3D00DB3EAA /* catch_commandline.hpp */, + 4A6D0C4C149B3E3D00DB3EAA /* catch_default_main.hpp */, + ); + name = Process; + sourceTree = ""; + }; + 4AC91CC1155C387400DC5117 /* Interfaces */ = { + isa = PBXGroup; + children = ( + 4A4B0F9915CE6EC100AE2392 /* catch_interfaces_registry_hub.h */, + 4A6D0C53149B3E3D00DB3EAA /* catch_interfaces_capture.h */, + 4A6D0C54149B3E3D00DB3EAA /* catch_interfaces_exception.h */, + 4A6D0C55149B3E3D00DB3EAA /* catch_interfaces_reporter.h */, + 4A6D0C56149B3E3D00DB3EAA /* catch_interfaces_runner.h */, + 4A6D0C57149B3E3D00DB3EAA /* catch_interfaces_testcase.h */, + 4AFC661D157E96A7009D58CF /* catch_interfaces_config.h */, + 4A90B59B15D0F61A00EF71BC /* catch_interfaces_generators.h */, + 26711C90195D46CD0033EDA2 /* catch_interfaces_tag_alias_registry.h */, + ); + name = Interfaces; + sourceTree = ""; + }; + 4AC91CC2155C388300DC5117 /* Infrastructure */ = { + isa = PBXGroup; + children = ( + 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */, + 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */, + 4A6D0C49149B3E3D00DB3EAA /* catch_common.h */, + 262E739A1846759000CAC268 /* catch_common.hpp */, + 4A6D0C4B149B3E3D00DB3EAA /* catch_debugger.hpp */, + 261488FF184DC4A20041FBEB /* catch_debugger.h */, + 4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */, + 4A6D0C64149B3E3D00DB3EAA /* catch_xmlwriter.hpp */, + 4AB1C73714F97C1300F31DF7 /* catch_console_colour.hpp */, + 4AB77CB51551AEA200857BF0 /* catch_ptr.hpp */, + 4AEE0326161431070071E950 /* catch_streambuf.h */, + 4ACE21C8166CA19700FB5509 /* catch_option.hpp */, + 26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */, + 26DACF2F17206D3400A21326 /* catch_text.h */, + 263FD06117AF8DF200988A20 /* catch_timer.h */, + 26AEAF1617BEA18E009E32C9 /* catch_platform.h */, + 261488FC184D1DC10041FBEB /* catch_stream.h */, + 268F47B018A93F7800D8C14F /* catch_clara.h */, + 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */, + 2656C227192A78410040DB02 /* catch_reenable_warnings.h */, + 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */, + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */, + ); + name = Infrastructure; + sourceTree = ""; + }; + 4AC91CC3155C38D300DC5117 /* Objective-C */ = { + isa = PBXGroup; + children = ( + 4A6D0C59149B3E3D00DB3EAA /* catch_objc.hpp */, + 4ABEA80415C90D2B009F0424 /* catch_objc_arc.hpp */, + ); + name = "Objective-C"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A6D0C1F149B3D3B00DB3EAA /* CatchSelfTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A6D0C2A149B3D3B00DB3EAA /* Build configuration list for PBXNativeTarget "CatchSelfTest" */; + buildPhases = ( + 4A6D0C1C149B3D3B00DB3EAA /* Sources */, + 4A6D0C1D149B3D3B00DB3EAA /* Frameworks */, + 4A6D0C1E149B3D3B00DB3EAA /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CatchSelfTest; + productName = CatchSelfTest; + productReference = 4A6D0C20149B3D3B00DB3EAA /* CatchSelfTest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A6D0C17149B3D3B00DB3EAA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0710; + }; + buildConfigurationList = 4A6D0C1A149B3D3B00DB3EAA /* Build configuration list for PBXProject "CatchSelfTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A6D0C15149B3D3B00DB3EAA; + productRefGroup = 4A6D0C21149B3D3B00DB3EAA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A6D0C1F149B3D3B00DB3EAA /* CatchSelfTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A6D0C1C149B3D3B00DB3EAA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */, + 4A6D0C37149B3D9E00DB3EAA /* ApproxTests.cpp in Sources */, + 4A6D0C38149B3D9E00DB3EAA /* ClassTests.cpp in Sources */, + 4A6D0C39149B3D9E00DB3EAA /* ConditionTests.cpp in Sources */, + 4A6D0C3A149B3D9E00DB3EAA /* ExceptionTests.cpp in Sources */, + 4A6D0C3B149B3D9E00DB3EAA /* GeneratorTests.cpp in Sources */, + 4A6D0C3C149B3D9E00DB3EAA /* MessageTests.cpp in Sources */, + 4A6D0C3D149B3D9E00DB3EAA /* MiscTests.cpp in Sources */, + 4A6D0C3E149B3D9E00DB3EAA /* TestMain.cpp in Sources */, + 4A6D0C3F149B3D9E00DB3EAA /* TrickyTests.cpp in Sources */, + 263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */, + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */, + 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */, + 4AEE032016142F910071E950 /* catch_common.cpp in Sources */, + 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */, + 4AEE032316142FC70071E950 /* catch_debugger.cpp in Sources */, + 4AEE032516142FF10071E950 /* catch_stream.cpp in Sources */, + 4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */, + 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */, + 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */, + 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */, + 2656C2211925E7330040DB02 /* catch_test_spec.cpp in Sources */, + 4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */, + 4A45DA2B16161F79004F8D6B /* catch_interfaces_registry_hub.cpp in Sources */, + 4A45DA2D16161FA2004F8D6B /* catch_interfaces_capture.cpp in Sources */, + 4A45DA3116161FFC004F8D6B /* catch_interfaces_reporter.cpp in Sources */, + 4A45DA3316162047004F8D6B /* catch_interfaces_exception.cpp in Sources */, + 2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */, + 26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */, + 4A45DA3516162071004F8D6B /* catch_interfaces_runner.cpp in Sources */, + 4AB3D99D1616216500C9A0F8 /* catch_interfaces_testcase.cpp in Sources */, + 4AB3D9A01616219100C9A0F8 /* catch_interfaces_config.cpp in Sources */, + 4AB3D9A2161621B500C9A0F8 /* catch_interfaces_generators.cpp in Sources */, + 4ACE21CC166CA1B300FB5509 /* catch_option.cpp in Sources */, + 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */, + 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */, + 266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */, + 266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A6D0C28149B3D3B00DB3EAA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = NO; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "\"$(PROJECT_DIR)/../../../include\""; + }; + name = Debug; + }; + 4A6D0C29149B3D3B00DB3EAA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PEDANTIC = YES; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = ""; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = "\"$(PROJECT_DIR)/../../../include\""; + }; + name = Release; + }; + 4A6D0C2B149B3D3B00DB3EAA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = ( + "-Weverything", + "-Wparentheses", + "-Wno-disabled-macro-expansion", + ); + }; + name = Debug; + }; + 4A6D0C2C149B3D3B00DB3EAA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "compiler-default"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WARNING_CFLAGS = ( + "-Weverything", + "-Wparentheses", + "-Wno-disabled-macro-expansion", + ); + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A6D0C1A149B3D3B00DB3EAA /* Build configuration list for PBXProject "CatchSelfTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A6D0C28149B3D3B00DB3EAA /* Debug */, + 4A6D0C29149B3D3B00DB3EAA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A6D0C2A149B3D3B00DB3EAA /* Build configuration list for PBXNativeTarget "CatchSelfTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A6D0C2B149B3D3B00DB3EAA /* Debug */, + 4A6D0C2C149B3D3B00DB3EAA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A6D0C17149B3D3B00DB3EAA /* Project object */; +} diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..804437d0651 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 new file mode 100644 index 00000000000..28b36e20289 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/CatchSelfTest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 16/12/2011 \" DATE +.Dt CatchSelfTest 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm CatchSelfTest, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp new file mode 100644 index 00000000000..a08e67b3670 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTest/catch_text.cpp @@ -0,0 +1,3 @@ +// This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" +#include "catch_text.h" diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..1eee6eb6b64 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.pbxproj @@ -0,0 +1,258 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A2894D615D3956000E20735 /* ApproxTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894D515D3956000E20735 /* ApproxTests.cpp */; }; + 4AB735FA15D396F400F9F7C3 /* TestMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894E015D3957500E20735 /* TestMain.cpp */; }; + 4AB735FB15D3970C00F9F7C3 /* ClassTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DA15D3957500E20735 /* ClassTests.cpp */; }; + 4AB735FC15D3971100F9F7C3 /* ConditionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DB15D3957500E20735 /* ConditionTests.cpp */; }; + 4AB735FD15D3971600F9F7C3 /* ExceptionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DC15D3957500E20735 /* ExceptionTests.cpp */; }; + 4AB735FE15D3971600F9F7C3 /* GeneratorTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DD15D3957500E20735 /* GeneratorTests.cpp */; }; + 4AB735FF15D3971600F9F7C3 /* MessageTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DE15D3957500E20735 /* MessageTests.cpp */; }; + 4AB7360015D3971600F9F7C3 /* MiscTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894DF15D3957500E20735 /* MiscTests.cpp */; }; + 4AB7360115D3971600F9F7C3 /* TrickyTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A2894E115D3957500E20735 /* TrickyTests.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A90B5D415D2E3E900EF71BC /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 4A2894D515D3956000E20735 /* ApproxTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ApproxTests.cpp; path = ../../../SelfTest/ApproxTests.cpp; sourceTree = ""; }; + 4A2894DA15D3957500E20735 /* ClassTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ClassTests.cpp; path = ../../../SelfTest/ClassTests.cpp; sourceTree = ""; }; + 4A2894DB15D3957500E20735 /* ConditionTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ConditionTests.cpp; path = ../../../SelfTest/ConditionTests.cpp; sourceTree = ""; }; + 4A2894DC15D3957500E20735 /* ExceptionTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionTests.cpp; path = ../../../SelfTest/ExceptionTests.cpp; sourceTree = ""; }; + 4A2894DD15D3957500E20735 /* GeneratorTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GeneratorTests.cpp; path = ../../../SelfTest/GeneratorTests.cpp; sourceTree = ""; }; + 4A2894DE15D3957500E20735 /* MessageTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MessageTests.cpp; path = ../../../SelfTest/MessageTests.cpp; sourceTree = ""; }; + 4A2894DF15D3957500E20735 /* MiscTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MiscTests.cpp; path = ../../../SelfTest/MiscTests.cpp; sourceTree = ""; }; + 4A2894E015D3957500E20735 /* TestMain.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TestMain.cpp; path = ../../../SelfTest/TestMain.cpp; sourceTree = ""; }; + 4A2894E115D3957500E20735 /* TrickyTests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TrickyTests.cpp; path = ../../../SelfTest/TrickyTests.cpp; sourceTree = ""; }; + 4A90B5D615D2E3E900EF71BC /* CatchSelfTestSingle */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CatchSelfTestSingle; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A90B5D315D2E3E900EF71BC /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A2894E215D3957D00E20735 /* Self Test */ = { + isa = PBXGroup; + children = ( + 4A2894E015D3957500E20735 /* TestMain.cpp */, + ); + name = "Self Test"; + sourceTree = ""; + }; + 4A2894E315D3959800E20735 /* Test Cases */ = { + isa = PBXGroup; + children = ( + 4A2894DA15D3957500E20735 /* ClassTests.cpp */, + 4A2894DB15D3957500E20735 /* ConditionTests.cpp */, + 4A2894DC15D3957500E20735 /* ExceptionTests.cpp */, + 4A2894DD15D3957500E20735 /* GeneratorTests.cpp */, + 4A2894DE15D3957500E20735 /* MessageTests.cpp */, + 4A2894DF15D3957500E20735 /* MiscTests.cpp */, + 4A2894E115D3957500E20735 /* TrickyTests.cpp */, + 4A2894D515D3956000E20735 /* ApproxTests.cpp */, + ); + name = "Test Cases"; + sourceTree = ""; + }; + 4A90B5CB15D2E3E900EF71BC = { + isa = PBXGroup; + children = ( + 4A90B5D915D2E3E900EF71BC /* CatchSelfTestSingle */, + 4A90B5D715D2E3E900EF71BC /* Products */, + ); + sourceTree = ""; + }; + 4A90B5D715D2E3E900EF71BC /* Products */ = { + isa = PBXGroup; + children = ( + 4A90B5D615D2E3E900EF71BC /* CatchSelfTestSingle */, + ); + name = Products; + sourceTree = ""; + }; + 4A90B5D915D2E3E900EF71BC /* CatchSelfTestSingle */ = { + isa = PBXGroup; + children = ( + 4A2894E315D3959800E20735 /* Test Cases */, + 4A2894E215D3957D00E20735 /* Self Test */, + ); + path = CatchSelfTestSingle; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A90B5D515D2E3E900EF71BC /* CatchSelfTestSingle */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A90B5E015D2E3E900EF71BC /* Build configuration list for PBXNativeTarget "CatchSelfTestSingle" */; + buildPhases = ( + 4A90B5D215D2E3E900EF71BC /* Sources */, + 4A90B5D315D2E3E900EF71BC /* Frameworks */, + 4A90B5D415D2E3E900EF71BC /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CatchSelfTestSingle; + productName = CatchSelfTestSingle; + productReference = 4A90B5D615D2E3E900EF71BC /* CatchSelfTestSingle */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A90B5CD15D2E3E900EF71BC /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Phil Nash"; + }; + buildConfigurationList = 4A90B5D015D2E3E900EF71BC /* Build configuration list for PBXProject "CatchSelfTestSingle" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A90B5CB15D2E3E900EF71BC; + productRefGroup = 4A90B5D715D2E3E900EF71BC /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A90B5D515D2E3E900EF71BC /* CatchSelfTestSingle */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A90B5D215D2E3E900EF71BC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2894D615D3956000E20735 /* ApproxTests.cpp in Sources */, + 4AB735FA15D396F400F9F7C3 /* TestMain.cpp in Sources */, + 4AB735FB15D3970C00F9F7C3 /* ClassTests.cpp in Sources */, + 4AB735FC15D3971100F9F7C3 /* ConditionTests.cpp in Sources */, + 4AB735FD15D3971600F9F7C3 /* ExceptionTests.cpp in Sources */, + 4AB735FE15D3971600F9F7C3 /* GeneratorTests.cpp in Sources */, + 4AB735FF15D3971600F9F7C3 /* MessageTests.cpp in Sources */, + 4AB7360015D3971600F9F7C3 /* MiscTests.cpp in Sources */, + 4AB7360115D3971600F9F7C3 /* TrickyTests.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A90B5DE15D2E3E900EF71BC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 4A90B5DF15D2E3E900EF71BC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + SDKROOT = macosx; + }; + name = Release; + }; + 4A90B5E115D2E3E900EF71BC /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libc++"; + HEADER_SEARCH_PATHS = "../../../single_include/**"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4A90B5E215D2E3E900EF71BC /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LIBRARY = "libc++"; + HEADER_SEARCH_PATHS = "../../../single_include/**"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A90B5D015D2E3E900EF71BC /* Build configuration list for PBXProject "CatchSelfTestSingle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A90B5DE15D2E3E900EF71BC /* Debug */, + 4A90B5DF15D2E3E900EF71BC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A90B5E015D2E3E900EF71BC /* Build configuration list for PBXNativeTarget "CatchSelfTestSingle" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A90B5E115D2E3E900EF71BC /* Debug */, + 4A90B5E215D2E3E900EF71BC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A90B5CD15D2E3E900EF71BC /* Project object */; +} diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..4fcfc0e62ac --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle/dummy.txt b/3rdparty/sol2/Catch/projects/XCode/CatchSelfTest/CatchSelfTestSingle/dummy.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..6777e8e72c9 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj @@ -0,0 +1,265 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A63D2AB14E3C1A900F615CB /* OCTest.1 */; }; + 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2B214E3C1E600F615CB /* Main.mm */; }; + 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A63D2BF14E4544700F615CB /* Foundation.framework */; }; + 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */; }; + 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C314E454CC00F615CB /* OCTest.mm */; }; + 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C514E454CC00F615CB /* TestObj.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A63D2A314E3C1A900F615CB /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 4A63D2A514E3C1A900F615CB /* OCTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OCTest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A63D2AB14E3C1A900F615CB /* OCTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = OCTest.1; sourceTree = ""; }; + 4A63D2B214E3C1E600F615CB /* Main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Main.mm; sourceTree = ""; }; + 4A63D2BF14E4544700F615CB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CatchOCTestCase.h; sourceTree = ""; }; + 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CatchOCTestCase.mm; sourceTree = ""; }; + 4A63D2C314E454CC00F615CB /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = ""; }; + 4A63D2C414E454CC00F615CB /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = ""; }; + 4A63D2C514E454CC00F615CB /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = ""; }; + 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc.hpp; path = ../../../include/internal/catch_objc.hpp; sourceTree = ""; }; + 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc_arc.hpp; path = ../../../include/internal/catch_objc_arc.hpp; sourceTree = ""; }; + 4ABEA80815C90E38009F0424 /* catch_tostring.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_tostring.hpp; path = ../../../include/internal/catch_tostring.hpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A63D2A214E3C1A900F615CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A63D29A14E3C1A900F615CB = { + isa = PBXGroup; + children = ( + 4AA0D94F154C0A63004B4193 /* Catch */, + 4A63D2BF14E4544700F615CB /* Foundation.framework */, + 4A63D2A814E3C1A900F615CB /* OCTest */, + 4A63D2A614E3C1A900F615CB /* Products */, + ); + sourceTree = ""; + }; + 4A63D2A614E3C1A900F615CB /* Products */ = { + isa = PBXGroup; + children = ( + 4A63D2A514E3C1A900F615CB /* OCTest */, + ); + name = Products; + sourceTree = ""; + }; + 4A63D2A814E3C1A900F615CB /* OCTest */ = { + isa = PBXGroup; + children = ( + 4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */, + 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */, + 4A63D2C314E454CC00F615CB /* OCTest.mm */, + 4A63D2C414E454CC00F615CB /* TestObj.h */, + 4A63D2C514E454CC00F615CB /* TestObj.m */, + 4A63D2B214E3C1E600F615CB /* Main.mm */, + 4A63D2AB14E3C1A900F615CB /* OCTest.1 */, + ); + path = OCTest; + sourceTree = ""; + }; + 4AA0D94F154C0A63004B4193 /* Catch */ = { + isa = PBXGroup; + children = ( + 4ABEA80815C90E38009F0424 /* catch_tostring.hpp */, + 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */, + 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */, + ); + name = Catch; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A63D2A414E3C1A900F615CB /* OCTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */; + buildPhases = ( + 4A63D2A114E3C1A900F615CB /* Sources */, + 4A63D2A214E3C1A900F615CB /* Frameworks */, + 4A63D2A314E3C1A900F615CB /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OCTest; + productName = OCTest; + productReference = 4A63D2A514E3C1A900F615CB /* OCTest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A63D29C14E3C1A900F615CB /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A63D29A14E3C1A900F615CB; + productRefGroup = 4A63D2A614E3C1A900F615CB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A63D2A414E3C1A900F615CB /* OCTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A63D2A114E3C1A900F615CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */, + 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */, + 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */, + 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A63D2AD14E3C1A900F615CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../../include; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 4A63D2AE14E3C1A900F615CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../../include; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 4A63D2B014E3C1A900F615CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + HEADER_SEARCH_PATHS = ../../../include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4A63D2B114E3C1A900F615CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + HEADER_SEARCH_PATHS = ../../../include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A63D2AD14E3C1A900F615CB /* Debug */, + 4A63D2AE14E3C1A900F615CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A63D2B014E3C1A900F615CB /* Debug */, + 4A63D2B114E3C1A900F615CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A63D29C14E3C1A900F615CB /* Project object */; +} diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..119e61c58c7 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h new file mode 100644 index 00000000000..bd26239ae16 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.h @@ -0,0 +1,25 @@ +// +// CatchOCTestCase.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED +#define TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED + +#include "catch.hpp" + +#import +#import "TestObj.h" + +@interface TestFixture : NSObject +{ + TestObj* obj; +} + +@end + +#endif // TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm new file mode 100644 index 00000000000..fb20287b8f0 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm @@ -0,0 +1,83 @@ +// +// CatchOCTestCase.mm +// OCTest +// +// Created by Phil Nash on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#import "CatchOCTestCase.h" + + +@implementation TestFixture + + +-(void) setUp +{ + obj = [[TestObj alloc] init]; +} + +-(void) tearDown +{ + arcSafeRelease( obj ); +} + +OC_TEST_CASE( "OCTest/test1", "This is a test case" ) +{ + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); +} + +OC_TEST_CASE( "OCTest/test2", "This is another test case" ) +{ + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 2; + + REQUIRE( obj.int_val == 2 ); +} + +OC_TEST_CASE( "OCTest/BOOL", "tests a boolean value" ) +{ + CHECK( [obj isTrue] == NO ); + CHECK( [obj isFalse] == YES ); +} + +OC_TEST_CASE( "OCTest/throws/objc", "throws an Objective-C exception" ) +{ + @throw [[NSException alloc] initWithName: NSGenericException + reason: @"Objective-C exception" + userInfo: nil]; +} +OC_TEST_CASE( "OCTest/throws/stdc++", "throws a std c++ exception" ) +{ + throw std::domain_error( "std C++ exception" ); +} + +/////////////////////////////////////////////////////////////////////////// +template +void useObject( const T& object ){} + +template +void useObject( const T* object ){} + +OC_TEST_CASE( "OCTest/matchers", "Matches work with OC types (NSString so far)" ) +{ + REQUIRE_THAT( @"This is a string", Equals( @"This isnt a string" ) ); + REQUIRE_THAT( @"This is a string", Contains( @"is a" ) ); + REQUIRE_THAT( @"This is a string", StartsWith( @"This" ) ); + REQUIRE_THAT( @"This is a string", EndsWith( @"string" ) ); +} + +OC_TEST_CASE( "OCTest/matchers/nil", "nil NSString should not crash the test" ) +{ + CHECK_THAT( (NSString*)nil, Equals( @"This should fail, but not crash" ) ); + CHECK_THAT( (NSString*)nil, StartsWith( @"anything" ) ); +} + +@end diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/Main.mm b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/Main.mm new file mode 100644 index 00000000000..569dc4d9cab --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/Main.mm @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#import "catch.hpp" diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.1 b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.1 new file mode 100644 index 00000000000..7915d02a059 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 09/02/2012 \" DATE +.Dt OCTest 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm OCTest, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.mm b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.mm new file mode 100644 index 00000000000..bfb2ca26d00 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/OCTest.mm @@ -0,0 +1,28 @@ +/* + * OCTest.mm + * OCTest + * + * Created by Phil on 13/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ + +#import "catch.hpp" + +#import "TestObj.h" + +TEST_CASE( "OCTest/TestObj", "tests TestObj" ) +{ + TestObj* obj = [[TestObj alloc] init]; + + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); + + arcSafeRelease( obj ); +} diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.h b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.h new file mode 100644 index 00000000000..8443921ffe4 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.h @@ -0,0 +1,28 @@ +// +// TestObj.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef TWOBLUECUBES_TESTOBJ_H_INCLUDED +#define TWOBLUECUBES_TESTOBJ_H_INCLUDED + +#import + + +@interface TestObj : NSObject { + + int int_val; +} + +-(BOOL) isTrue; +-(BOOL) isFalse; + +@property (nonatomic, assign ) int int_val; + +@end + +#endif // TWOBLUECUBES_TESTOBJ_H_INCLUDED diff --git a/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.m b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.m new file mode 100644 index 00000000000..2c7dc99b8f7 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/OCTest/OCTest/TestObj.m @@ -0,0 +1,25 @@ +// +// TestObj.m +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#import "TestObj.h" + + +@implementation TestObj + +@synthesize int_val; + +-(BOOL) isTrue { + return YES; +} +-(BOOL) isFalse { + return NO; +} + +@end diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj new file mode 100644 index 00000000000..e968cf620fc --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.pbxproj @@ -0,0 +1,299 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 4A73280A14E66CFC0044823F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A73280914E66CFC0044823F /* UIKit.framework */; }; + 4A73280C14E66CFC0044823F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A73280B14E66CFC0044823F /* Foundation.framework */; }; + 4A73280E14E66CFC0044823F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A73280D14E66CFC0044823F /* CoreGraphics.framework */; }; + 4A73281414E66CFC0044823F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4A73281214E66CFC0044823F /* InfoPlist.strings */; }; + 4A73282614E66D8B0044823F /* itChRunnerMain.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A73282514E66D8B0044823F /* itChRunnerMain.mm */; }; + 4AB1C74F14FCC74900F31DF7 /* OCTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1C74C14FCC74900F31DF7 /* OCTest.mm */; }; + 4AB1C75014FCC74900F31DF7 /* TestObj.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AB1C74E14FCC74900F31DF7 /* TestObj.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 4A73280514E66CFC0044823F /* iOSTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A73280914E66CFC0044823F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 4A73280B14E66CFC0044823F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4A73280D14E66CFC0044823F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 4A73281114E66CFC0044823F /* iOSTest-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iOSTest-Info.plist"; sourceTree = ""; }; + 4A73281314E66CFC0044823F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 4A73281714E66CFC0044823F /* iOSTest-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "iOSTest-Prefix.pch"; sourceTree = ""; }; + 4A73282214E66D8B0044823F /* iTchRunnerAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTchRunnerAppDelegate.h; sourceTree = ""; }; + 4A73282314E66D8B0044823F /* iTchRunnerMainView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTchRunnerMainView.h; sourceTree = ""; }; + 4A73282414E66D8B0044823F /* iTchRunnerReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTchRunnerReporter.h; sourceTree = ""; }; + 4A73282514E66D8B0044823F /* itChRunnerMain.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = itChRunnerMain.mm; path = ../../../runners/iTchRunner/itChRunnerMain.mm; sourceTree = ""; }; + 4AB1C74C14FCC74900F31DF7 /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = ""; }; + 4AB1C74D14FCC74900F31DF7 /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = ""; }; + 4AB1C74E14FCC74900F31DF7 /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A73280214E66CFC0044823F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A73280A14E66CFC0044823F /* UIKit.framework in Frameworks */, + 4A73280C14E66CFC0044823F /* Foundation.framework in Frameworks */, + 4A73280E14E66CFC0044823F /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A7327FA14E66CFC0044823F = { + isa = PBXGroup; + children = ( + 4A73280F14E66CFC0044823F /* iOSTest */, + 4A73280814E66CFC0044823F /* Frameworks */, + 4A73280614E66CFC0044823F /* Products */, + ); + sourceTree = ""; + }; + 4A73280614E66CFC0044823F /* Products */ = { + isa = PBXGroup; + children = ( + 4A73280514E66CFC0044823F /* iOSTest.app */, + ); + name = Products; + sourceTree = ""; + }; + 4A73280814E66CFC0044823F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4A73280914E66CFC0044823F /* UIKit.framework */, + 4A73280B14E66CFC0044823F /* Foundation.framework */, + 4A73280D14E66CFC0044823F /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 4A73280F14E66CFC0044823F /* iOSTest */ = { + isa = PBXGroup; + children = ( + 4A73282014E66D6C0044823F /* iTch */, + 4A73281014E66CFC0044823F /* Supporting Files */, + ); + path = iOSTest; + sourceTree = ""; + }; + 4A73281014E66CFC0044823F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 4A73281114E66CFC0044823F /* iOSTest-Info.plist */, + 4A73281214E66CFC0044823F /* InfoPlist.strings */, + 4A73281714E66CFC0044823F /* iOSTest-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 4A73282014E66D6C0044823F /* iTch */ = { + isa = PBXGroup; + children = ( + 4AB1C74C14FCC74900F31DF7 /* OCTest.mm */, + 4AB1C74D14FCC74900F31DF7 /* TestObj.h */, + 4AB1C74E14FCC74900F31DF7 /* TestObj.m */, + 4A73282114E66D8B0044823F /* internal */, + 4A73282514E66D8B0044823F /* itChRunnerMain.mm */, + ); + name = iTch; + sourceTree = ""; + }; + 4A73282114E66D8B0044823F /* internal */ = { + isa = PBXGroup; + children = ( + 4A73282214E66D8B0044823F /* iTchRunnerAppDelegate.h */, + 4A73282314E66D8B0044823F /* iTchRunnerMainView.h */, + 4A73282414E66D8B0044823F /* iTchRunnerReporter.h */, + ); + name = internal; + path = ../../../runners/iTchRunner/internal; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A73280414E66CFC0044823F /* iOSTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A73281D14E66CFC0044823F /* Build configuration list for PBXNativeTarget "iOSTest" */; + buildPhases = ( + 4A73280114E66CFC0044823F /* Sources */, + 4A73280214E66CFC0044823F /* Frameworks */, + 4A73280314E66CFC0044823F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = iOSTest; + productName = iOSTest; + productReference = 4A73280514E66CFC0044823F /* iOSTest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A7327FC14E66CFC0044823F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = 4A7327FF14E66CFC0044823F /* Build configuration list for PBXProject "iOSTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A7327FA14E66CFC0044823F; + productRefGroup = 4A73280614E66CFC0044823F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A73280414E66CFC0044823F /* iOSTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4A73280314E66CFC0044823F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A73281414E66CFC0044823F /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A73280114E66CFC0044823F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A73282614E66D8B0044823F /* itChRunnerMain.mm in Sources */, + 4AB1C74F14FCC74900F31DF7 /* OCTest.mm in Sources */, + 4AB1C75014FCC74900F31DF7 /* TestObj.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 4A73281214E66CFC0044823F /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 4A73281314E66CFC0044823F /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 4A73281B14E66CFC0044823F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_IDENTITY = "iPhone Developer: Phil Nash (4KJCM5XSVL)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PROVISIONING_PROFILE = "95C4758A-E0B8-4714-9DA3-C7E1284444A4"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ../../../include; + }; + name = Debug; + }; + 4A73281C14E66CFC0044823F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_IDENTITY = "iPhone Developer: Phil Nash (4KJCM5XSVL)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + PROVISIONING_PROFILE = "95C4758A-E0B8-4714-9DA3-C7E1284444A4"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ../../../include; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4A73281E14E66CFC0044823F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "iOSTest/iOSTest-Prefix.pch"; + INFOPLIST_FILE = "iOSTest/iOSTest-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 4A73281F14E66CFC0044823F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "iOSTest/iOSTest-Prefix.pch"; + INFOPLIST_FILE = "iOSTest/iOSTest-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A7327FF14E66CFC0044823F /* Build configuration list for PBXProject "iOSTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A73281B14E66CFC0044823F /* Debug */, + 4A73281C14E66CFC0044823F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A73281D14E66CFC0044823F /* Build configuration list for PBXNativeTarget "iOSTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A73281E14E66CFC0044823F /* Debug */, + 4A73281F14E66CFC0044823F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A7327FC14E66CFC0044823F /* Project object */; +} diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..aaadc7d492c --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm new file mode 100644 index 00000000000..d476cb42bf0 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/OCTest.mm @@ -0,0 +1,27 @@ +/* + * OCTest.mm + * OCTest + * + * Created by Phil on 13/11/2010. + * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + * + */ +#include "catch.hpp" + +#import "TestObj.h" + +TEST_CASE( "OCTest/TestObj", "tests TestObj" ) +{ + TestObj* obj = [[TestObj alloc] init]; + + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); + + arcSafeRelease( obj ); +} diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h new file mode 100644 index 00000000000..de6725027a2 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.h @@ -0,0 +1,25 @@ +// +// TestObj.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef TWOBLUECUBES_TESTOBJ_H_INCLUDED +#define TWOBLUECUBES_TESTOBJ_H_INCLUDED + +#import + + +@interface TestObj : NSObject { + + int int_val; +} + +@property (nonatomic, assign ) int int_val; + +@end + +#endif // TWOBLUECUBES_TESTOBJ_H_INCLUDED diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m new file mode 100644 index 00000000000..943f4450837 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/TestObj.m @@ -0,0 +1,18 @@ +// +// TestObj.m +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#import "TestObj.h" + + +@implementation TestObj + +@synthesize int_val; + +@end diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings new file mode 100644 index 00000000000..477b28ff8f8 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist new file mode 100644 index 00000000000..f74b6db0993 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFiles + + CFBundleIdentifier + twobluecubes.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch new file mode 100644 index 00000000000..403e8e45e5e --- /dev/null +++ b/3rdparty/sol2/Catch/projects/XCode/iOSTest/iOSTest/iOSTest-Prefix.pch @@ -0,0 +1,14 @@ +// +// Prefix header for all source files of the 'iOSTest' target in the 'iOSTest' project +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iOS SDK 3.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h b/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h new file mode 100644 index 00000000000..522291a905a --- /dev/null +++ b/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h @@ -0,0 +1,114 @@ +/* + * iTchRunnerAppDelegate.h + * iTchRunner + * + * Created by Phil on 07/02/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + */ +#ifndef TWOBLUECUBES_ITCHRUNNERAPPDELEGATE_H_INCLUDED +#define TWOBLUECUBES_ITCHRUNNERAPPDELEGATE_H_INCLUDED + +#import "iTchRunnerMainView.h" + + + +@interface iTchRunnerAppDelegate : NSObject +{ + UIWindow *window; +} + +@end + + +@implementation iTchRunnerAppDelegate + + +/////////////////////////////////////////////////////////////////////////////// +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + [window setUserInteractionEnabled:YES]; + [window setMultipleTouchEnabled:YES]; + + CGRect screenRect = [[UIScreen mainScreen] applicationFrame]; + iTchRunnerMainView* view = [[iTchRunnerMainView alloc] initWithFrame:screenRect]; + + [window addSubview:view]; + [window makeKeyAndVisible]; + arcSafeRelease( view ); + + return YES; +} + +/////////////////////////////////////////////////////////////////////////////// +- (void)dealloc +{ +#if !CATCH_ARC_ENABLED + [window release]; + [super dealloc]; +#endif +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationWillResignActive:(UIApplication *)application +{ + /* + Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + /* + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + If your application supports background execution, called instead of applicationWillTerminate: when the user quits. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + /* + Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + /* + Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationWillTerminate:(UIApplication *)application +{ + /* + Called when the application is about to terminate. + See also applicationDidEnterBackground:. + */ +} + + +/////////////////////////////////////////////////////////////////////////////// +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application +{ + /* + Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. + */ +} + + + +@end + +#endif // TWOBLUECUBES_ITCHRUNNERAPPDELEGATE_H_INCLUDED diff --git a/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h b/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h new file mode 100644 index 00000000000..c6a6394ea57 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerMainView.h @@ -0,0 +1,189 @@ +/* + * iTchRunnerMainView.h + * iTchRunner + * + * Created by Phil on 07/02/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + */ +#ifndef TWOBLUECUBES_ITCHRUNNERMAINVIEW_H_INCLUDED +#define TWOBLUECUBES_ITCHRUNNERMAINVIEW_H_INCLUDED + +#include "internal/catch_config.hpp" +#include "internal/catch_runner_impl.hpp" +#include "internal/catch_context_impl.hpp" +#include "catch.hpp" + +#include "iTchRunnerReporter.h" + +#import + +@interface iTchRunnerMainView : UIView +{ + UITextField* appName; +} + +-(void) showAlert; + +@end + +@implementation iTchRunnerMainView + + +/////////////////////////////////////////////////////////////////////////////// +-(id) initWithFrame:(CGRect)frame +{ + if ((self = [super initWithFrame:frame])) + { + // Initialization code + self.backgroundColor = [UIColor blackColor]; + + appName = [[UITextField alloc] initWithFrame: CGRectMake( 0, 50, 320, 50 )]; + [self addSubview: appName]; + arcSafeRelease( appName ); + appName.textColor = [[UIColor alloc] initWithRed:0.35 green:0.35 blue:1 alpha:1]; + arcSafeRelease( appName.textColor ); + appName.textAlignment = NSTextAlignmentCenter; + + appName.text = [NSString stringWithFormat:@"CATCH tests"]; +// [self performSelector: @selector(showAlert) withObject:nil afterDelay:0.1]; + [self performSelectorOnMainThread:@selector(showAlert) withObject:nil waitUntilDone:NO]; + + } + return self; +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) dealloc +{ + [appName removeFromSuperview]; +#if !CATCH_ARC_ENABLED + [super dealloc]; +#endif +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) showAlert +{ + UIActionSheet* menu = [[UIActionSheet alloc] initWithTitle:@"Options" + delegate:self + cancelButtonTitle:nil + destructiveButtonTitle:nil + otherButtonTitles:@"Run all tests", nil]; + [menu showInView: self]; + arcSafeRelease( menu ); + +} + +// This is a copy & paste from Catch::Runner2 to get us bootstrapped (this is due to all be +// replaced anyway) +inline Catch::Totals runTestsForGroup( Catch::RunContext& context, const Catch::TestCaseFilters& filterGroup ) { + using namespace Catch; + Totals totals; + std::vector::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin(); + std::vector::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end(); + int testsRunForGroup = 0; + for(; it != itEnd; ++it ) { + if( filterGroup.shouldInclude( *it ) ) { + testsRunForGroup++; + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + } + } + if( testsRunForGroup == 0 ) + std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl; + return totals; + +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) actionSheet: (UIActionSheet*) sheet clickedButtonAtIndex: (NSInteger) index +{ + Catch::Ptr config = new Catch::Config(); + Catch::IReporter* reporter = new Catch::iTchRunnerReporter( self ); + Catch::LegacyReporterAdapter* reporterAdapter = new Catch::LegacyReporterAdapter( reporter ); + Catch::RunContext runner( config.get(), reporterAdapter ); + + + std::vector filterGroups; + Catch::TestCaseFilters filterGroup( "" ); + filterGroups.push_back( filterGroup ); + + Catch::Totals totals; + + std::vector::const_iterator it = filterGroups.begin(); + std::vector::const_iterator itEnd = filterGroups.end(); + + std::size_t groupCount = filterGroups.size(); + std::size_t groupIndex = 0; + for(; it != itEnd && !runner.aborting(); ++it, ++index ) { + runner.testGroupStarting( it->getName(), groupIndex, groupCount ); + totals += runTestsForGroup( runner, *it ); + runner.testGroupEnded( it->getName(), totals, groupIndex, groupCount ); + } + + + if( totals.assertions.failed == 0 ) + { + NSLog( @"no failures" ); + if( totals.assertions.passed > 0 ) + appName.textColor = [[UIColor alloc] initWithRed:0.35 green:1 blue:0.35 alpha:1]; + } + else + { + NSLog( @"%lu failures", totals.assertions.failed ); + appName.textColor = [[UIColor alloc] initWithRed:1 green:0.35 blue:0.35 alpha:1]; + } +} + +/////////////////////////////////////////////////////////////////////////////// +-(void) testWasRun: (const Catch::AssertionResult*) pResultInfo +{ + const Catch::AssertionResult& resultInfo = *pResultInfo; + std::ostringstream oss; + + if( resultInfo.hasExpression() ) + { + oss << resultInfo.getExpression(); + if( resultInfo.isOk() ) + oss << " succeeded"; + else + oss << " failed"; + } + switch( resultInfo.getResultType() ) + { + case Catch::ResultWas::ThrewException: + if( resultInfo.hasExpression() ) + oss << " with unexpected"; + else + oss << "Unexpected"; + oss << " exception with message: '" << resultInfo.getMessage() << "'"; + break; + case Catch::ResultWas::Info: + oss << "info: '" << resultInfo.getMessage() << "'"; + break; + case Catch::ResultWas::Warning: + oss << "warning: '" << resultInfo.getMessage() << "'"; + break; + case Catch::ResultWas::ExplicitFailure: + oss << "failed with message: '" << resultInfo.getMessage() << "'"; + break; + default: + break; + } + + if( resultInfo.hasExpression() ) + { + oss << " for: " << resultInfo.getExpandedExpression(); + } + oss << std::endl; + NSLog( @"%s", oss.str().c_str() ); +} + + +@end + +#endif // TWOBLUECUBES_ITCHRUNNERMAINVIEW_H_INCLUDED diff --git a/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h b/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h new file mode 100644 index 00000000000..d2628861562 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/runners/iTchRunner/internal/iTchRunnerReporter.h @@ -0,0 +1,115 @@ +/* + * iTchRunnerReporter.h + * iTchRunner + * + * Created by Phil on 07/02/2011. + * Copyright 2011 Two Blue Cubes Ltd. All rights reserved. + * + */ +#ifndef TWOBLUECUBES_ITCHRUNNERREPORTER_H_INCLUDED +#define TWOBLUECUBES_ITCHRUNNERREPORTER_H_INCLUDED + +#include "catch.hpp" + +@protocol iTchRunnerDelegate + +-(void) testWasRun: (const Catch::AssertionResult*) result; + +@end + +namespace Catch +{ + class iTchRunnerReporter : public SharedImpl + { + public: + /////////////////////////////////////////////////////////////////////////// + iTchRunnerReporter + ( + id delegate + ) + : m_delegate( delegate ) + { + } + + /////////////////////////////////////////////////////////////////////////// + virtual bool shouldRedirectStdout + () + const + { + return true; + } + + /////////////////////////////////////////////////////////////////////////// + static std::string getDescription + () + { + return "Captures results for iOS runner"; + } + + /////////////////////////////////////////////////////////////////////////// + size_t getSucceeded + () + const + { + return m_totals.assertions.passed; + } + + /////////////////////////////////////////////////////////////////////////// + size_t getFailed + () + const + { + return m_totals.assertions.failed; + } + + /////////////////////////////////////////////////////////////////////////// + void reset() + { + m_totals = Totals(); + } + + private: // IReporter + + /////////////////////////////////////////////////////////////////////////// + virtual void StartTesting + () + {} + + /////////////////////////////////////////////////////////////////////////// + virtual void EndTesting + ( + const Totals& totals + ) + { + m_totals = totals; + } + + /////////////////////////////////////////////////////////////////////////// + virtual void Result + ( + const AssertionResult& result + ) + { + [m_delegate testWasRun: &result]; + } + + /////////////////////////////////////////////////////////////////////////// + // Deliberately unimplemented: + virtual void StartGroup( const std::string& ){} + virtual void EndGroup( const std::string&, const Totals& ){} + virtual void StartTestCase( const TestCaseInfo& ){} + virtual void StartSection( const std::string& sectionName, const std::string& description ) {} + virtual void EndSection( const std::string&, const Counts& ){} + virtual void EndTestCase( const TestCaseInfo&, const Totals&, const std::string&, const std::string& ){} + virtual void Aborted() {} + virtual void NoAssertionsInSection( std::string const& sectionName ) {} + virtual void NoAssertionsInTestCase( std::string const& testName ) {} + + private: + Totals m_totals; + + id m_delegate; + }; +} + +#endif // TWOBLUECUBES_ITCHRUNNERREPORTER_H_INCLUDED diff --git a/3rdparty/sol2/Catch/projects/runners/iTchRunner/itChRunnerMain.mm b/3rdparty/sol2/Catch/projects/runners/iTchRunner/itChRunnerMain.mm new file mode 100644 index 00000000000..cac5faecca4 --- /dev/null +++ b/3rdparty/sol2/Catch/projects/runners/iTchRunner/itChRunnerMain.mm @@ -0,0 +1,27 @@ +// +// iTchRunnerMain.mm +// iTchRunner +// +// Created by Phil on 04/02/2011. +// Copyright Two Blue Cubes Ltd 2011. All rights reserved. +// + +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#import "internal/iTchRunnerAppDelegate.h" + +int main(int argc, char *argv[]) +{ +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int retVal = UIApplicationMain(argc, argv, nil, @"iTchRunnerAppDelegate"); + +#if !CATCH_ARC_ENABLED + [pool release]; +#endif + + return retVal; +} diff --git a/3rdparty/sol2/Catch/projects/runners/iTchRunner/readme b/3rdparty/sol2/Catch/projects/runners/iTchRunner/readme new file mode 100644 index 00000000000..2b2549176ce --- /dev/null +++ b/3rdparty/sol2/Catch/projects/runners/iTchRunner/readme @@ -0,0 +1,6 @@ +* Select Project -> New Target. Select Cocoa Touch -> Application. Click next and name it something like "Unit Tests" +* While the target info is displayed, find: 'User Header Search Paths' and add a path to the Catch folder +* Open the plist file for the target (Unit Test-Info.plist, if you used that name). Delete the entry for "Main nib file base name: MainWindow" +* From the overview drop-down select the new target. +* Add the file Catch/Runner/iTchRunnerMain.mm into your project - but only in the new target +* Write tests (adding files under test into the target as necessary) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/scripts/approvalTests.py b/3rdparty/sol2/Catch/scripts/approvalTests.py new file mode 100644 index 00000000000..618812f888d --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/approvalTests.py @@ -0,0 +1,115 @@ +from __future__ import print_function + +import os +import sys +import subprocess +import re + +from scriptCommon import catchPath + +rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' ) + +filenameParser = re.compile( r'(.*)/(.*\..pp:)(.*)' ) +filelineParser = re.compile( r'(.*\..pp:)([0-9]*)(.*)' ) +pathParser = re.compile( r'(.*?)/(.*\..pp)(.*)' ) +lineNumberParser = re.compile( r'(.*)line="[0-9]*"(.*)' ) +hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' ) +durationsParser = re.compile( r'(.*)time="[0-9]*\.[0-9]*"(.*)' ) +versionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9]*(.*)' ) +devVersionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9]*-develop\.[0-9]*(.*)' ) + +if len(sys.argv) == 2: + cmdPath = sys.argv[1] +else: + cmdPath = os.path.join( catchPath, 'projects/XCode/CatchSelfTest/DerivedData/CatchSelfTest/Build/Products/Debug/CatchSelfTest' ) + +overallResult = 0 + +def filterLine( line ): + m = filenameParser.match( line ) + if m: + line = m.group(2) + m.group(3) + m2 = filelineParser.match( line ) + if m2: + line = m2.group(1) + "" + m2.group(3) + else: + m2 = lineNumberParser.match( line ) + if m2: + line = m2.group(1) + m2.group(2) + m = pathParser.match( line ) + if m: + path = "/" + m.group(2) + if path.startswith( catchPath ): + path = path[1+len(catchPath):] + line = m.group(1) + path + m.group(3) + m = devVersionParser.match( line ) + if m: + line = m.group(1) + "" + m.group(2) + else: + m = versionParser.match( line ) + if m: + line = m.group(1) + "" + m.group(2) + + while True: + m = hexParser.match( line ) + if m: + line = m.group(1) + "0x" + m.group(3) + else: + break + m = durationsParser.match( line ) + if m: + line = m.group(1) + 'time="{duration}"' + m.group(2) + return line + +def approve( baseName, args ): + global overallResult + args[0:0] = [cmdPath] + if not os.path.exists( cmdPath ): + raise Exception( "Executable doesn't exist at " + cmdPath ) + baselinesPath = os.path.join( rootPath, '{0}.approved.txt'.format( baseName ) ) + rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) ) + filteredResultsPath = os.path.join( rootPath, '{0}.unapproved.txt'.format( baseName ) ) + + f = open( rawResultsPath, 'w' ) + subprocess.call( args, stdout=f, stderr=f ) + f.close() + + rawFile = open( rawResultsPath, 'r' ) + filteredFile = open( filteredResultsPath, 'w' ) + for line in rawFile: + filteredFile.write( filterLine( line ).rstrip() + "\n" ) + filteredFile.close() + rawFile.close() + + os.remove( rawResultsPath ) + print() + print( baseName + ":" ) + if os.path.exists( baselinesPath ): + diffResult = subprocess.call([ "diff", baselinesPath, filteredResultsPath ] ) + if diffResult == 0: + os.remove( filteredResultsPath ) + print( " \033[92mResults matched" ) + else: + print( " \n****************************\n \033[91mResults differed" ) + if diffResult > overallResult: + overallResult = diffResult + print( "\033[0m" ) + else: + print( " first approval" ) + if overallResult == 0: + overallResult = 1 + +# Standard console reporter +approve( "console.std", ["~_"] ) +# console reporter, include passes, warn about No Assertions +approve( "console.sw", ["~_", "-s", "-w", "NoAssertions"] ) +# console reporter, include passes, warn about No Assertions, limit failures to first 4 +approve( "console.swa4", ["~_", "-s", "-w", "NoAssertions", "-x", "4"] ) +# junit reporter, include passes, warn about No Assertions +approve( "junit.sw", ["~_", "-s", "-w", "NoAssertions", "-r", "junit"] ) +# xml reporter, include passes, warn about No Assertions +approve( "xml.sw", ["~_", "-s", "-w", "NoAssertions", "-r", "xml"] ) + +if overallResult != 0: + print( "run approve.py to approve new baselines" ) +exit( overallResult) diff --git a/3rdparty/sol2/Catch/scripts/approve.py b/3rdparty/sol2/Catch/scripts/approve.py new file mode 100644 index 00000000000..f4b66aa4a90 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/approve.py @@ -0,0 +1,31 @@ +from __future__ import print_function + +import os +import sys +import shutil +import glob +from scriptCommon import catchPath + +rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' ) + +if len(sys.argv) > 1: + files = [os.path.join( rootPath, f ) for f in sys.argv[1:]] +else: + files = glob.glob( os.path.join( rootPath, "*.unapproved.txt" ) ) + + +def approveFile( approvedFile, unapprovedFile ): + justFilename = unapprovedFile[len(rootPath)+1:] + if os.path.exists( unapprovedFile ): + if os.path.exists( approvedFile ): + os.remove( approvedFile ) + os.rename( unapprovedFile, approvedFile ) + print( "approved " + justFilename ) + else: + print( "approval file " + justFilename + " does not exist" ) + +if len(files) > 0: + for unapprovedFile in files: + approveFile( unapprovedFile.replace( "unapproved.txt", "approved.txt" ), unapprovedFile ) +else: + print( "no files to approve" ) diff --git a/3rdparty/sol2/Catch/scripts/developBuild.py b/3rdparty/sol2/Catch/scripts/developBuild.py new file mode 100644 index 00000000000..c244871ab79 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/developBuild.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementBuildNumber() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) ) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/scripts/fixTrailingWhitespace.py b/3rdparty/sol2/Catch/scripts/fixTrailingWhitespace.py new file mode 100644 index 00000000000..a1b6bbe871b --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/fixTrailingWhitespace.py @@ -0,0 +1,46 @@ +from __future__ import print_function +import os +from scriptCommon import catchPath + +changedFiles = 0 + +def isSourceFile( path ): + return path.endswith( ".cpp" ) or path.endswith( ".h" ) or path.endswith( ".hpp" ) + +def fixAllFilesInDir( dir ): + for f in os.listdir( dir ): + path = os.path.join( dir,f ) + if os.path.isfile( path ): + if isSourceFile( path ): + fixFile( path ) + else: + fixAllFilesInDir( path ) + +def fixFile( path ): + f = open( path, 'r' ) + lines = [] + changed = 0 + for line in f: + trimmed = line.rstrip() + "\n" + if trimmed != line: + changed = changed +1 + lines.append( trimmed ) + f.close() + if changed > 0: + global changedFiles + changedFiles = changedFiles + 1 + print( path + ":" ) + print( " - fixed " + str(changed) + " line(s)" ) + altPath = path + ".backup" + os.rename( path, altPath ) + f2 = open( path, 'w' ) + for line in lines: + f2.write( line ) + f2.close() + os.remove( altPath ) + +fixAllFilesInDir(catchPath) +if changedFiles > 0: + print( "Fixed " + str(changedFiles) + " file(s)" ) +else: + print( "No trailing whitespace found" ) diff --git a/3rdparty/sol2/Catch/scripts/generateSingleHeader.py b/3rdparty/sol2/Catch/scripts/generateSingleHeader.py new file mode 100644 index 00000000000..419633f8328 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/generateSingleHeader.py @@ -0,0 +1,103 @@ +from __future__ import print_function + +import os +import sys +import re +import datetime +import string + +from scriptCommon import catchPath +from releaseCommon import Version + + +includesParser = re.compile( r'\s*#include\s*"(.*)"' ) +guardParser = re.compile( r'\s*#.*TWOBLUECUBES_CATCH_.*_INCLUDED') +defineParser = re.compile( r'\s*#define') +ifParser = re.compile( r'\s*#ifndef TWOBLUECUBES_CATCH_.*_INCLUDED') +endIfParser = re.compile( r'\s*#endif // TWOBLUECUBES_CATCH_.*_INCLUDED') +ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) +commentParser1 = re.compile( r'^\s*/\*') +commentParser2 = re.compile( r'^ \*') +blankParser = re.compile( r'^\s*$') +seenHeaders = set([]) +rootPath = os.path.join( catchPath, 'include/' ) +outputPath = os.path.join( catchPath, 'single_include/catch.hpp' ) + +includeImpl = True + +for arg in sys.argv[1:]: + arg = string.lower(arg) + if arg == "noimpl": + includeImpl = False + print( "Not including impl code" ) + else: + print( "\n** Unrecognised argument: " + arg + " **\n" ) + exit(1) + +out = open( outputPath, 'w' ) +ifdefs = 0 +implIfDefs = -1 + +def write( line ): + if includeImpl or implIfDefs == -1: + out.write( line ) + +def parseFile( path, filename ): + global ifdefs + global implIfDefs + + f = open( path + filename, 'r' ) + blanks = 0 + for line in f: + if ifParser.match( line ): + ifdefs = ifdefs + 1 + elif endIfParser.match( line ): + ifdefs = ifdefs - 1 + if ifdefs == implIfDefs: + implIfDefs = -1 + m = includesParser.match( line ) + if m: + header = m.group(1) + headerPath, sep, headerFile = header.rpartition( "/" ) + if not headerFile in seenHeaders: + if headerFile != "tbc_text_format.h" and headerFile != "clara.h": + seenHeaders.add( headerFile ) + write( "// #included from: {0}\n".format( header ) ) + if( headerPath == "internal" and path.endswith( "internal/" ) ): + headerPath = "" + sep = "" + if os.path.exists( path + headerPath + sep + headerFile ): + parseFile( path + headerPath + sep, headerFile ) + else: + parseFile( rootPath + headerPath + sep, headerFile ) + else: + if ifImplParser.match(line): + implIfDefs = ifdefs + if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ): + if blankParser.match( line ): + blanks = blanks + 1 + else: + blanks = 0 + if blanks < 2: + write( line.rstrip() + "\n" ) + + +v = Version() +out.write( "/*\n" ) +out.write( " * Catch v{0}\n".format( v.getVersionString() ) ) +out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) ) +out.write( " * ----------------------------------------------------------\n" ) +out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" ) +out.write( " * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.\n" ) +out.write( " *\n" ) +out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" ) +out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" ) +out.write( " */\n" ) +out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) +out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) + +parseFile( rootPath, 'catch.hpp' ) + +out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" ) + +print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) ) diff --git a/3rdparty/sol2/Catch/scripts/majorRelease.py b/3rdparty/sol2/Catch/scripts/majorRelease.py new file mode 100644 index 00000000000..03b7e78ec66 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/majorRelease.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementMajorVersion() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) ) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/scripts/minorRelease.py b/3rdparty/sol2/Catch/scripts/minorRelease.py new file mode 100644 index 00000000000..bbd97ed042e --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/minorRelease.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementMinorVersion() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) ) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/scripts/patchRelease.py b/3rdparty/sol2/Catch/scripts/patchRelease.py new file mode 100644 index 00000000000..6abf87af152 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/patchRelease.py @@ -0,0 +1,9 @@ +from __future__ import print_function +from releaseCommon import Version + +v = Version() +v.incrementPatchNumber() +v.updateVersionFile() +v.updateReadmeFile() + +print( "Updated Version.hpp and README to v{0}".format( v.getVersionString() ) ) \ No newline at end of file diff --git a/3rdparty/sol2/Catch/scripts/releaseCommon.py b/3rdparty/sol2/Catch/scripts/releaseCommon.py new file mode 100644 index 00000000000..14eb235e5bf --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/releaseCommon.py @@ -0,0 +1,89 @@ +from __future__ import print_function + +import os +import sys +import re +import string + +from scriptCommon import catchPath + +versionParser = re.compile( r'(\s*Version\slibraryVersion)\s*\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*\"(.*)\"\s*,\s*(.*)\s*\).*' ) +rootPath = os.path.join( catchPath, 'include/' ) +versionPath = os.path.join( rootPath, "internal/catch_version.hpp" ) +readmePath = os.path.join( catchPath, "README.md" ) + +class Version: + def __init__(self): + f = open( versionPath, 'r' ) + for line in f: + m = versionParser.match( line ) + if m: + self.variableDecl = m.group(1) + self.majorVersion = int(m.group(2)) + self.minorVersion = int(m.group(3)) + self.patchNumber = int(m.group(4)) + self.branchName = m.group(5) + self.buildNumber = int(m.group(6)) + f.close() + + def nonDevelopRelease(self): + if self.branchName != "": + self.branchName = "" + self.buildNumber = 0 + def developBuild(self): + if self.branchName == "": + self.branchName = "develop" + self.buildNumber = 0 + + def incrementBuildNumber(self): + self.developBuild() + self.buildNumber = self.buildNumber+1 + + def incrementPatchNumber(self): + self.nonDevelopRelease() + self.patchNumber = self.patchNumber+1 + + def incrementMinorVersion(self): + self.nonDevelopRelease() + self.patchNumber = 0 + self.minorVersion = self.minorVersion+1 + + def incrementMajorVersion(self): + self.nonDevelopRelease() + self.patchNumber = 0 + self.minorVersion = 0 + self.majorVersion = self.majorVersion+1 + + def getVersionString(self): + versionString = '{0}.{1}.{2}'.format( self.majorVersion, self.minorVersion, self.patchNumber ) + if self.branchName != "": + versionString = versionString + '-{0}.{1}'.format( self.branchName, self.buildNumber ) + return versionString + + def updateVersionFile(self): + f = open( versionPath, 'r' ) + lines = [] + for line in f: + m = versionParser.match( line ) + if m: + lines.append( '{0}( {1}, {2}, {3}, "{4}", {5} );'.format( self.variableDecl, self.majorVersion, self.minorVersion, self.patchNumber, self.branchName, self.buildNumber ) ) + else: + lines.append( line.rstrip() ) + f.close() + f = open( versionPath, 'w' ) + for line in lines: + f.write( line + "\n" ) + + def updateReadmeFile(self): + f = open( readmePath, 'r' ) + lines = [] + for line in f: + lines.append( line.rstrip() ) + f.close() + f = open( readmePath, 'w' ) + for line in lines: + if line.startswith( "*v" ): + f.write( '*v{0}*\n'.format( self.getVersionString() ) ) + else: + f.write( line + "\n" ) + diff --git a/3rdparty/sol2/Catch/scripts/releaseNotes.py b/3rdparty/sol2/Catch/scripts/releaseNotes.py new file mode 100644 index 00000000000..e083ec94534 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/releaseNotes.py @@ -0,0 +1,62 @@ +import os +import re +import urllib2 +import json + +from scriptCommon import catchPath +from scriptCommon import runAndCapture + +issueNumberRe = re.compile( r'(.*?)#([0-9]*)([^0-9]?.*)' ) + +rootPath = os.path.join( catchPath, 'include/' ) +versionPath = os.path.join( rootPath, "internal/catch_version.hpp" ) + + +hashes = runAndCapture( ['git', 'log', '-2', '--format="%H"', versionPath] ) +lines = runAndCapture( ['git', 'log', hashes[1] + ".." + hashes[0], catchPath] ) + +prevLine = "" +messages = [] +dates = [] +issues = {} + +def getIssueTitle( issueNumber ): + try: + s = urllib2.urlopen("https://api.github.com/repos/philsquared/catch/issues/" + issueNumber ).read() + except e: + return "#HTTP Error#" + + try: + j = json.loads( s ) + return j["title"] + except e: + return "#JSON Error#" + +for line in lines: + if line.startswith( "commit"): + pass + elif line.startswith( "Author:"): + pass + elif line.startswith( "Date:"): + dates.append( line[5:].lstrip() ) + pass + elif line == "" and prevLine == "": + pass + else: + prevLine = line + match = issueNumberRe.match( line ) + line2 = "" + while match: + issueNumber = match.group(2) + issue = '#{0} ("{1}")'.format( issueNumber, getIssueTitle( issueNumber ) ) + line2 = line2 + match.group(1) + issue + match = issueNumberRe.match( match.group(3) ) + if line2 == "": + messages.append( line ) + else: + messages.append( line2 ) + +print "All changes between {0} and {1}:\n".format( dates[-1], dates[0] ) + +for line in messages: + print line diff --git a/3rdparty/sol2/Catch/scripts/scriptCommon.py b/3rdparty/sol2/Catch/scripts/scriptCommon.py new file mode 100644 index 00000000000..6ac381adcb6 --- /dev/null +++ b/3rdparty/sol2/Catch/scripts/scriptCommon.py @@ -0,0 +1,21 @@ +import os +import sys +import subprocess + +catchPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0]))) + +def runAndCapture( args ): + child = subprocess.Popen(" ".join( args ), shell=True, stdout=subprocess.PIPE) + lines = [] + line = "" + while True: + out = child.stdout.read(1) + if out == '' and child.poll() != None: + break + if out != '': + if out == '\n': + lines.append( line ) + line = "" + else: + line = line + out + return lines \ No newline at end of file diff --git a/3rdparty/sol2/Catch/single_include/catch.hpp b/3rdparty/sol2/Catch/single_include/catch.hpp new file mode 100644 index 00000000000..5cc33a8388e --- /dev/null +++ b/3rdparty/sol2/Catch/single_include/catch.hpp @@ -0,0 +1,10359 @@ +/* + * Catch v1.3.4 + * Generated: 2016-02-10 19:24:03.089683 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// #included from: internal/catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wglobal-constructors" +# pragma clang diagnostic ignored "-Wvariadic-macros" +# pragma clang diagnostic ignored "-Wc99-extensions" +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? +// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +# define CATCH_CPP11_OR_GREATER + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM +# endif + +# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE +# endif + +# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NULLPTR +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_IS_ENUM +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_TUPLE +#endif +#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_LONG_LONG +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { +#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; +#else + NonCopyable( NonCopyable const& info ); + NonCopyable& operator = ( NonCopyable const& ); +#endif + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + bool operator < ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( CATCH_NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = CATCH_NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + +struct AutoReg { + + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + template + class Not : public MatcherImpl, ExpressionT> { + public: + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + private: + Ptr< Matcher > m_matcher; + }; + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + private: + std::vector > > m_matchers; + }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return startsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return endsWith( m_data.adjustString( expr ), m_data.m_str ); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); + + template + ExpressionLhs operator <= ( T const& operand ); + ExpressionLhs operator <= ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); + void handleResult( AssertionResult const& result ); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( nullptr, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, nullptr ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +#ifdef CATCH_CONFIG_CPP11_TUPLE +#include +#endif + +#ifdef CATCH_CONFIG_CPP11_IS_ENUM +#include +#endif + +namespace Catch { + +// Why we're here. +template +std::string toString( T const& value ); + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + +namespace Detail { + + extern const std::string unprintableString; + + struct BorgType { + template BorgType( T const& ); + }; + + struct TrueType { char sizer[1]; }; + struct FalseType { char sizer[2]; }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value + > + struct EnumStringMaker + { + static std::string convert( T const& ) { return unprintableString; } + }; + + template + struct EnumStringMaker + { + static std::string convert( T const& v ) + { + return ::Catch::toString( + static_cast::type>(v) + ); + } + }; +#endif + template + struct StringMakerBase { +#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template + static std::string convert( T const& v ) + { + return EnumStringMaker::convert( v ); + } +#else + template + static std::string convert( T const& ) { return unprintableString; } +#endif + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return "NULL"; + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +//template +//struct StringMaker > { +// static std::string convert( std::vector const& v ) { +// return Detail::rangeToString( v.begin(), v.end() ); +// } +//}; + +template +std::string toString( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); +} + +#ifdef CATCH_CONFIG_CPP11_TUPLE + +// toString for tuples +namespace TupleDetail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct ElementPrinter { + static void print( const Tuple& tuple, std::ostream& os ) + { + os << ( N ? ", " : " " ) + << Catch::toString(std::get(tuple)); + ElementPrinter::print(tuple,os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct ElementPrinter { + static void print( const Tuple&, std::ostream& ) {} + }; + +} + +template +struct StringMaker> { + + static std::string convert( const std::tuple& tuple ) + { + std::ostringstream os; + os << '{'; + TupleDetail::ElementPrinter>::print( tuple, os ); + os << " }"; + return os.str(); + } +}; +#endif // CATCH_CONFIG_CPP11_TUPLE + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << Catch::toString( *first ); + for( ++first ; first != last ; ++first ) + oss << ", " << Catch::toString( *first ); + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + ( __catchResult <= expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && static_cast(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureExpectedException( matcher ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = (matcher).toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( (matcher).match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool allOk() const { + return failed == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedMicroseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +#include + +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( CATCH_NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = CATCH_NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } + + bool operator !() const { return nullableValue == CATCH_NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( CATCH_NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_IMPL +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: ../catch_session.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual bool forceColour() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; +} + +#include +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + forceColour( false ), + filenamesAsTags( false ), + abortAfter( -1 ), + rngSeed( 0 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ), + runOrder( RunTests::InDeclarationOrder ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + bool forceColour; + bool filenamesAsTags; + + int abortAfter; + unsigned int rngSeed; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + RunTests::InWhatOrder runOrder; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + std::vector getReporterNames() const { return m_data.reporterNames; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_stream->stream(); } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } + virtual unsigned int rngSeed() const { return m_data.rngSeed; } + virtual bool forceColour() const { return m_data.forceColour; } + + private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } + ConfigData m_data; + + std::auto_ptr m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Version 0.0.1.1 + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +// ----------- #included from clara_compilers.h ----------- + +#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED +#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// The following features are defined: +// +// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? +// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? +// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods +// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? +// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) + +// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? + +// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? + +// In general each macro has a _NO_ form +// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 + +#ifdef __clang__ + +#if __has_feature(cxx_nullptr) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#if __has_feature(cxx_noexcept) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1600) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// catch all support for C++11 +#if defined(__cplusplus) && __cplusplus >= 201103L + +#define CLARA_CPP11_OR_GREATER + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) +#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT +#endif + +#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS +#endif + +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) +#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE +#endif +#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +#endif + +#endif // __cplusplus >= 201103L + +// Now set the actual defines based on the above + anything the user has configured +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NULLPTR +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_NOEXCEPT +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_GENERATED_METHODS +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_OVERRIDE +#endif +#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) +#define CLARA_CONFIG_CPP11_UNIQUE_PTR +#endif + +// noexcept support: +#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) +#define CLARA_NOEXCEPT noexcept +# define CLARA_NOEXCEPT_IS(x) noexcept(x) +#else +#define CLARA_NOEXCEPT throw() +# define CLARA_NOEXCEPT_IS(x) +#endif + +// nullptr support +#ifdef CLARA_CONFIG_CPP11_NULLPTR +#define CLARA_NULL nullptr +#else +#define CLARA_NULL NULL +#endif + +// override support +#ifdef CLARA_CONFIG_CPP11_OVERRIDE +#define CLARA_OVERRIDE override +#else +#define CLARA_OVERRIDE +#endif + +// unique_ptr support +#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR +# define CLARA_AUTO_PTR( T ) std::unique_ptr +#else +# define CLARA_AUTO_PTR( T ) std::auto_ptr +#endif + +#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED + +// ----------- end of #include from clara_compilers.h ----------- +// ........... back in clara.h + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + // Use this to try and stop compiler from warning about unreachable code + inline bool isTrue( bool value ) { return value; } + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + if( isTrue( true ) ) + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +#endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( CLARA_NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != CLARA_NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const* const argv[], std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg.reset( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const* const argv[] ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const* argv[], ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( errors.empty() && m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + } + inline void setOrder( ConfigData& config, std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); + } + inline void setRngSeed( ConfigData& config, std::string const& seed ) { + if( seed == "time" ) { + config.rngSeed = static_cast( std::time(0) ); + } + else { + std::stringstream ss; + ss << seed; + ss >> config.rngSeed; + if( ss.fail() ) + throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); + } + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &addReporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + cli["--order"] + .describe( "test case order (defaults to decl)" ) + .bind( &setOrder, "decl|lex|rand" ); + + cli["--rng-seed"] + .describe( "set a specific seed for random numbers" ) + .bind( &setRngSeed, "'time'|number" ); + + cli["--force-colour"] + .describe( "force colourised output" ) + .bind( &ConfigData::forceColour ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + }; + + struct IReporterFactory : IShared { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map > FactoryMap; + typedef std::vector > Listeners; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Catch::cout() << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + Catch::cout() << oss.str() << wrapper << "\n"; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + Catch::cout() << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_run_context.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); + assert( section ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// #included from: catch_fatal_condition.hpp +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +namespace Catch { + + // Report the error condition then exit the process + inline void fatal( std::string const& message, int exitCode ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + + if( Catch::alwaysTrue() ) // avoids "no return" warnings + exit( exitCode ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { + + struct FatalConditionHandler { + void reset() {} + }; + +} // namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { + + struct SignalDefs { int id; const char* name; }; + extern SignalDefs signalDefs[]; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + struct FatalConditionHandler { + + static void handleSignal( int sig ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + if( sig == signalDefs[i].id ) + fatal( signalDefs[i].name, -sig ); + fatal( "", -sig ); + } + + FatalConditionHandler() : m_isSet( true ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, handleSignal ); + } + ~FatalConditionHandler() { + reset(); + } + void reset() { + if( m_isSet ) { + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) + signal( signalDefs[i].id, SIG_DFL ); + m_isSet = false; + } + } + + bool m_isSet; + }; + +} // namespace Catch + +#endif // not Windows + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), + m_reporter( reporter ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + + do { + m_trackerContext.startRun(); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + } + // !TBD: deprecated - this will be replaced by indexed trackers + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = CATCH_NULL; + m_testCaseTracker = CATCH_NULL; + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) + return false; + m_activeSections.push_back( §ionTracker ); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 ) + return false; + if( !m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back( endInfo ); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + virtual void handleFatalErrorCondition( std::string const& message ) { + ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); + resultBuilder.setResultType( ResultWas::FatalErrorCondition ); + resultBuilder << message; + resultBuilder.captureExpression(); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); + m_reporter->sectionEnded( testCaseSectionStats ); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + "", + "", + false ) ); + m_totals.testCases.failed++; + testGroupEnded( "", m_totals, 1, 1 ); + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + + seedRng( *m_config ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( Catch::cout(), redirectedCout ); + StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); + invokeActiveTestCase(); + } + else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + makeUnexpectedResultBuilder().useActiveException(); + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + void invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + private: + + ResultBuilder makeUnexpectedResultBuilder() const { + return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + } + + void handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( *it ); + m_unfinishedSections.clear(); + } + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + std::string const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + return reporter; + } + + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + + Totals runTests( Ptr const& config ) { + + Ptr iconfig = config.get(); + + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); + it != itEnd; + ++it ) { + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) + totals += context.runTest( *it ); + else + reporter->skipTest( *it ); + } + + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "#" + filename ); + setTags( test, tags ); + } + } + + class Session : NonCopyable { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + Catch::cerr() << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + Catch::cout() << "\nCatch v" << libraryVersion << "\n"; + + m_cli.usage( Catch::cout(), processName ); + Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( Catch::cout(), m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char const* argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + int run( int argc, char* argv[] ) { + return run( argc, const_cast( argv ) ); + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runTests( m_config ).assertions.failed ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace Catch { + + struct LexSort { + bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() + : m_currentSortOrder( RunTests::InDeclarationOrder ), + m_unnamedCount( 0 ) + {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + virtual std::vector const& getAllTests() const { + return m_functions; + } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); + } + + AutoReg::~AutoReg() {} + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() CATCH_OVERRIDE {} + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return CATCH_NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, Ptr const& factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } + + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + return m_factories; + } + virtual Listeners const& getListeners() const CATCH_OVERRIDE { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = CATCH_NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = CATCH_NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } +#endif +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : CATCH_NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = CATCH_NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = CATCH_NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + Ptr config = getCurrentContext().getConfig(); + return (config && config->forceColour()) || isatty(STDOUT_FILENO) + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = isDebuggerActive() + ? NoColourImpl::instance() + : platformColourInstance(); + impl->use( _colourCode ); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, "." ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + Catch::cerr() + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + Catch::cerr() << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( prop == TestCaseInfo::IsHidden ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.insert( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + std::string const& _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << "." + << version.minorVersion << "." + << version.patchNumber; + + if( !version.branchName.empty() ) { + os << "-" << version.branchName + << "." << version.buildNumber; + } + return os; + } + + Version libraryVersion( 1, 3, 4, "", 0 ); + +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + virtual void skipTest( TestCaseInfo const& ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } + void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency( reinterpret_cast( &hz ) ); + QueryPerformanceCounter( reinterpret_cast( &hzo ) ); + } + uint64_t t; + QueryPerformanceCounter( reinterpret_cast( &t ) ); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,CATCH_NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast(getElapsedMicroseconds()/1000); + } + double Timer::getElapsedSeconds() const { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + return line < other.line || ( line == other.line && file < other.file ); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return Catch::toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return Catch::toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() || secondArg == "\"\"" + ? capturedExpression + : capturedExpression + ", " + secondArg; + } + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + Catch::cerr() << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +#include + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual ~StreamingReporterBase() CATCH_OVERRIDE; + + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + ~CumulativeReporterBase(); + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } + + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; + + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + return false; + } + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public SharedImpl { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = CATCH_NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &Catch::cout() ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + stream() << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_sectionDepth( 0 ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~XmlReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + public: // StreamingReporterBase + + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + StreamingReporterBase::noMatchingTestCases( s ); + } + + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testRunStarting( testInfo ); + m_xml.setStream( stream ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + } + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + const AssertionResult& assertionResult = assertionStats.assertionResult; + + // Print any info messages in tags. + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( it->message ); + } else if ( it->type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( it->message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) + return true; + + // Print the expression if there is one. + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "type", assertionResult.getTestMacroName() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::FatalErrorCondition: + m_xml.scopedElement( "Fatal Error Condition" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + break; + default: + break; + } + + if( assertionResult.hasExpression() ) + m_xml.endElement(); + + return true; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + m_xml.endElement(); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + virtual ~JunitReporter() CATCH_OVERRIDE; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() CATCH_OVERRIDE { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter() CATCH_OVERRIDE; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) + +using Catch::Detail::Approx; + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/3rdparty/sol2/LICENSE.txt b/3rdparty/sol2/LICENSE.txt new file mode 100644 index 00000000000..1b5ff3c1af3 --- /dev/null +++ b/3rdparty/sol2/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013-2016 Rapptz and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/sol2/Optional/CMakeLists.txt b/3rdparty/sol2/Optional/CMakeLists.txt new file mode 100644 index 00000000000..07f38f79932 --- /dev/null +++ b/3rdparty/sol2/Optional/CMakeLists.txt @@ -0,0 +1,11 @@ +project(optional) +cmake_minimum_required(VERSION 2.8) +enable_testing() + +set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra") + +add_executable(test_optional test_optional.cpp) +add_executable(test_type_traits test_type_traits.cpp) + +add_test(test_optional test_optional) +add_test(test_type_traits test_type_traits) diff --git a/3rdparty/sol2/Optional/LICENSE_1_0.txt b/3rdparty/sol2/Optional/LICENSE_1_0.txt new file mode 100644 index 00000000000..36b7cd93cdf --- /dev/null +++ b/3rdparty/sol2/Optional/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/sol2/Optional/README.md b/3rdparty/sol2/Optional/README.md new file mode 100644 index 00000000000..948516d1ba7 --- /dev/null +++ b/3rdparty/sol2/Optional/README.md @@ -0,0 +1,39 @@ +Optional +======== + +A single-header header-only library for representing optional (nullable) objects for C++14 (and C++11 to some extent) and passing them by value. This is the reference implementation of proposal N3793 (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html). Optional is now accepted into Library Fundamentals Technical Specification (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html). The interface is based on Fernando Cacciola's Boost.Optional library (see http://www.boost.org/doc/libs/1_52_0/libs/optional/doc/html/index.html) + + +Usage +----- + +```cpp +optional readInt(); // this function may return int or a not-an-int + +if (optional oi = readInt()) // did I get a real int + cout << "my int is: " << *oi; // use my int +else + cout << "I have no int"; +``` + +For more usage examples and the overview see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html + + +Supported compilers +------------------- + +Clang 3.2, Clang 3.4, G++ 4.7.2, G++ 4.8.1. Tested only with libstdc++, versions 20130531, 20120920, 20110428. Others have reported it also works with libc++. + + + +Known Issues +------------ + + - Currently, the reference (and the only known) implementation of certain pieces of functionality explore what C++11 identifies as undefined behavior (see national body comment FI 15: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15). This is mostly why Optional was removed from C++14 and put into Library Fundamentals TS. Luckily what the Standard identifies as UB is well defined on all known platforms. We expect that the C++14 wil fix this problem, so that our trick becomes well-defined. + - In libstdc++ versions below 20130531 the constructor taking `initializer_list` argument is not `constexpr`. This is because `initializer_list` operations are not `constexpr` in C++11. This works however in version 20130531. It is also not enabled for libc++ because I do not have access to it and do nto know if it provides `constexpr` `initializer_list`. + - In G++ 4.7.2 and 4.8.0 member function `value_or` does not have rvalue reference overload. These compilers do not support rvalue overloding on `*this`. + - In order for the library to work with slightly older compilers, we emulate some missing type traits. On some platforms we cannot correctly detect the available features, and attempts at workarounds for missing type trait definitions can cause compile-time errors. Define macro `TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS` if you know that all the necessary type traits are defined, and no emulation is required. + +License +------- +Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). diff --git a/3rdparty/sol2/Optional/copyright.txt b/3rdparty/sol2/Optional/copyright.txt new file mode 100644 index 00000000000..1641c3cdd0a --- /dev/null +++ b/3rdparty/sol2/Optional/copyright.txt @@ -0,0 +1,10 @@ +Copyright (C) 2011-2012 Andrzej Krzemienski + +Distributed under the Boost Software License, Version 1.0 +(see accompanying file LICENSE_1_0.txt or a copy at +http://www.boost.org/LICENSE_1_0.txt) + +The idea and interface is based on Boost.Optional library +authored by Fernando Luis Cacciola Carballal + +Home at https://github.com/akrzemi1/Optional \ No newline at end of file diff --git a/3rdparty/sol2/Optional/optional.hpp b/3rdparty/sol2/Optional/optional.hpp new file mode 100644 index 00000000000..55b8306d013 --- /dev/null +++ b/3rdparty/sol2/Optional/optional.hpp @@ -0,0 +1,1064 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# ifndef ___SOL_OPTIONAL_HPP___ +# define ___SOL_OPTIONAL_HPP___ + +# include +# include +# include +# include +# include +# include +# include + +# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __GNUC__ // NOTE: GNUC is also defined for Clang +# if (__GNUC__ >= 5) +# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# endif +# endif +# +# if defined __clang_major__ +# if (__clang_major__ == 3 && __clang_minor__ >= 5) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# elif (__clang_major__ > 3) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# endif +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# endif +# endif +# +# if defined _MSC_VER +# if (_MSC_VER >= 1900) +# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# endif +# endif + +# if defined __clang__ +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif + + +# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +# else +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +# define OPTIONAL_CONSTEXPR_INIT_LIST +# endif + +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) +# define OPTIONAL_HAS_MOVE_ACCESSORS 1 +# else +# define OPTIONAL_HAS_MOVE_ACCESSORS 0 +# endif + +# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +# if (defined __cplusplus) && (__cplusplus == 201103L) +# define OPTIONAL_MUTABLE_CONSTEXPR +# else +# define OPTIONAL_MUTABLE_CONSTEXPR constexpr +# endif + +namespace sol{ + +// BEGIN workaround for missing is_trivially_destructible +# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it: it is already there +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + template + using is_trivially_destructible = ::std::has_trivial_destructor; +# endif +// END workaround for missing is_trivially_destructible + +# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + + +// workaround for missing traits in GCC and CLANG +template +struct is_nothrow_move_constructible +{ + constexpr static bool value = ::std::is_nothrow_constructible::value; +}; + + +template +struct is_assignable +{ + template + constexpr static bool has_assign(...) { return false; } + + template () = ::std::declval(), true)) > + // the comma operator is necessary for the cases where operator= returns void + constexpr static bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign(true); +}; + + +template +struct is_nothrow_move_assignable +{ + template + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template + struct has_nothrow_move_assign { + constexpr static bool value = noexcept( ::std::declval() = ::std::declval() ); + }; + + constexpr static bool value = has_nothrow_move_assign::value>::value; +}; +// end workaround + + +# endif + + + +// 20.5.4, optional for object types +template class optional; + +// 20.5.5, optional for lvalue reference types +template class optional; + + +// workaround: std utility functions aren't constexpr yet +template inline constexpr T&& constexpr_forward(typename ::std::remove_reference::type& t) noexcept +{ + return static_cast(t); +} + +template inline constexpr T&& constexpr_forward(typename ::std::remove_reference::type&& t) noexcept +{ + static_assert(!::std::is_lvalue_reference::value, "!!"); + return static_cast(t); +} + +template inline constexpr typename ::std::remove_reference::type&& constexpr_move(T&& t) noexcept +{ + return static_cast::type&&>(t); +} + + +#if defined NDEBUG +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#endif + + +namespace detail_ +{ + +// static_addressof: a constexpr version of addressof +template +struct has_overloaded_addressof +{ + template + constexpr static bool has_overload(...) { return false; } + + template ().operator&()) > + constexpr static bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload(true); +}; + +template )> +constexpr T* static_addressof(T& ref) +{ + return &ref; +} + +template )> +T* static_addressof(T& ref) +{ + return ::std::addressof(ref); +} + + +// the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A +template +constexpr U convert(U v) { return v; } + +} // namespace detail_ + +constexpr struct trivial_init_t {} trivial_init{}; + +// 20.5.7, Disengaged state indicator +struct nullopt_t +{ + struct init{}; + constexpr explicit nullopt_t(init){} +}; +constexpr nullopt_t nullopt{nullopt_t::init()}; + + +// 20.5.8, class bad_optional_access +class bad_optional_access : public ::std::logic_error { +public: + explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{what_arg} {} + explicit bad_optional_access(const char* what_arg) : ::std::logic_error{what_arg} {} +}; + + +template +struct optional_base +{ + bool init_; + char storage_[sizeof(T)]; + + constexpr optional_base() noexcept : init_(false), storage_() {}; + + explicit optional_base(const T& v) : init_(true), storage_() { + new (&storage())T(v); + } + + explicit optional_base(T&& v) : init_(true), storage_() { + new (&storage())T(constexpr_move(v)); + } + + template explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward(args)...); + } + + template >)> + explicit optional_base(in_place_t, ::std::initializer_list il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward(args)...); + } +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return *reinterpret_cast(&storage_[0]); + } + + constexpr const T& storage() const { + return *reinterpret_cast(&storage_[0]); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~optional_base() { if (init_) { storage().T::~T(); } } +}; + +#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ +// Sorry, GCC 4.x; you're just a piece of shit +template +using constexpr_optional_base = optional_base; +#else +template +struct constexpr_optional_base +{ + bool init_; + char storage_[sizeof(T)]; + constexpr constexpr_optional_base() noexcept : init_(false), storage_() {} + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() { + new (&storage())T(v); + } + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() { + new (&storage())T(constexpr_move(v)); + } + + template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward(args)...); + } + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward(args)...); + } + +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return (*reinterpret_cast(&storage_[0])); + } + + constexpr const T& storage() const { + return (*reinterpret_cast(&storage_[0])); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~constexpr_optional_base() = default; +}; +#endif + +template +using OptionalBase = typename ::std::conditional< + ::std::is_trivially_destructible::value, + constexpr_optional_base::type>, + optional_base::type> +>::type; + + + +template +class optional : private OptionalBase +{ + static_assert( !::std::is_same::type, nullopt_t>::value, "bad T" ); + static_assert( !::std::is_same::type, in_place_t>::value, "bad T" ); + + + constexpr bool initialized() const noexcept { return OptionalBase::init_; } + typename ::std::remove_const::type* dataptr() { return ::std::addressof(OptionalBase::storage()); } + constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage()); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase::storage(); } +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase::storage()); } + OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage(); } +# else + T& contained_val() & { return OptionalBase::storage(); } + T&& contained_val() && { return ::std::move(OptionalBase::storage()); } +# endif +# else + constexpr const T& contained_val() const { return OptionalBase::storage(); } + T& contained_val() { return OptionalBase::storage(); } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase::init_ = false; + } + + template + void initialize(Args&&... args) noexcept(noexcept(T(::std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(::std::forward(args)...); + OptionalBase::init_ = true; + } + + template + void initialize(::std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, ::std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(il, ::std::forward(args)...); + OptionalBase::init_ = true; + } + +public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + + optional(const optional& rhs) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(const optional& rhs) : optional() + { + if (rhs) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + + optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible::value) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(::std::move(*rhs)); + OptionalBase::init_ = true; + } + } + + constexpr optional(const T& v) : OptionalBase(v) {} + + constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} + + template + explicit constexpr optional(in_place_t, Args&&... args) + : OptionalBase(in_place, constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list il, Args&&... args) + : OptionalBase(in_place, il, constexpr_forward(args)...) {} + + // 20.5.4.2, Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(::std::is_nothrow_move_assignable::value && ::std::is_nothrow_move_constructible::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs); + return *this; + } + + template + auto operator=(U&& v) + -> typename ::std::enable_if + < + ::std::is_same::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = ::std::forward(v); } + else { initialize(::std::forward(v)); } + return *this; + } + + + template + void emplace(Args&&... args) + { + clear(); + initialize(::std::forward(args)...); + } + + template + void emplace(::std::initializer_list il, Args&&... args) + { + clear(); + initialize(il, ::std::forward(args)...); + } + + // 20.5.4.4, Swap + void swap(optional& rhs) noexcept(::std::is_nothrow_move_constructible::value && noexcept(swap(::std::declval(), ::std::declval()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5, Observers + + explicit constexpr operator bool() const noexcept { return initialized(); } + + constexpr T const* operator ->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const& { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { + assert (initialized()); + return contained_val(); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { + assert (initialized()); + return constexpr_move(contained_val()); + } + + constexpr T const& value() const& { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& value() & { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { + if (!initialized()) throw bad_optional_access("bad optional access"); + return ::std::move(contained_val()); + } + +# else + + T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert (initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + T& value() { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + +# endif + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template + constexpr T value_or(V&& v) const& + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + template + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# else + + template + T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# endif + +# else + + template + constexpr T value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# endif + +}; + + +template +class optional +{ + static_assert( !::std::is_same::value, "bad T" ); + static_assert( !::std::is_same::value, "bad T" ); + T* ref; + +public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + ::std::is_same::type, optional>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + !::std::is_same::type, optional>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = detail_::static_addressof(v); + } + + void emplace(T&&) = delete; + + + void swap(optional& rhs) noexcept + { + ::std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { + return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + template + constexpr T& value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } +}; + + +template +class optional +{ + static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); +}; + + +// 20.5.8, Relational operators +template constexpr bool operator==(const optional& x, const optional& y) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; +} + +template constexpr bool operator!=(const optional& x, const optional& y) +{ + return !(x == y); +} + +template constexpr bool operator<(const optional& x, const optional& y) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template constexpr bool operator>(const optional& x, const optional& y) +{ + return (y < x); +} + +template constexpr bool operator<=(const optional& x, const optional& y) +{ + return !(y < x); +} + +template constexpr bool operator>=(const optional& x, const optional& y) +{ + return !(x < y); +} + + +// 20.5.9, Comparison with nullopt +template constexpr bool operator==(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator==(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + +template constexpr bool operator!=(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator!=(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<(const optional&, nullopt_t) noexcept +{ + return false; +} + +template constexpr bool operator<(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<=(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator<=(nullopt_t, const optional&) noexcept +{ + return true; +} + +template constexpr bool operator>(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator>(nullopt_t, const optional&) noexcept +{ + return false; +} + +template constexpr bool operator>=(const optional&, nullopt_t) noexcept +{ + return true; +} + +template constexpr bool operator>=(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + + + +// 20.5.10, Comparison with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + + +// Comparison of optional with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + +// Comparison of optional with T +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + + +// 20.5.12, Specialized algorithms +template +void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) +{ + x.swap(y); +} + + +template +constexpr optional::type> make_optional(T&& v) +{ + return optional::type>(constexpr_forward(v)); +} + +template +constexpr optional make_optional(::std::reference_wrapper v) +{ + return optional(v.get()); +} + + +} // namespace + +namespace std +{ + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef sol::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash{}(*arg) : result_type{}; + } + }; + + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef sol::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash{}(*arg) : result_type{}; + } + }; +} + +# undef TR2_OPTIONAL_REQUIRES +# undef TR2_OPTIONAL_ASSERTED_EXPRESSION + +# endif //___SOL_OPTIONAL_HPP___ diff --git a/3rdparty/sol2/Optional/test_optional.cpp b/3rdparty/sol2/Optional/test_optional.cpp new file mode 100644 index 00000000000..8ed356a562b --- /dev/null +++ b/3rdparty/sol2/Optional/test_optional.cpp @@ -0,0 +1,1459 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// The idea and interface is based on Boost.Optional library +// authored by Fernando Luis Cacciola Carballal + +# include "optional.hpp" +# include +# include +# include +# include + + + +struct caller { + template caller(T fun) { fun(); } +}; +# define CAT2(X, Y) X ## Y +# define CAT(X, Y) CAT2(X, Y) +# define TEST(NAME) caller CAT(__VAR, __LINE__) = [] + +enum State +{ + sDefaultConstructed, + sValueCopyConstructed, + sValueMoveConstructed, + sCopyConstructed, + sMoveConstructed, + sMoveAssigned, + sCopyAssigned, + sValueCopyAssigned, + sValueMoveAssigned, + sMovedFrom, + sValueConstructed +}; + +struct OracleVal +{ + State s; + int i; + OracleVal(int i = 0) : s(sValueConstructed), i(i) {} +}; + +struct Oracle +{ + State s; + OracleVal val; + + Oracle() : s(sDefaultConstructed) {} + Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {} + Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;} + Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {} + Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;} + + Oracle& operator=(const OracleVal& v) { s = sValueCopyConstructed; val = v; return *this; } + Oracle& operator=(OracleVal&& v) { s = sValueMoveConstructed; val = std::move(v); v.s = sMovedFrom; return *this; } + Oracle& operator=(const Oracle& o) { s = sCopyConstructed; val = o.val; return *this; } + Oracle& operator=(Oracle&& o) { s = sMoveConstructed; val = std::move(o.val); o.s = sMovedFrom; return *this; } +}; + +struct Guard +{ + std::string val; + Guard() : val{} {} + explicit Guard(std::string s, int = 0) : val(s) {} + Guard(const Guard&) = delete; + Guard(Guard&&) = delete; + void operator=(const Guard&) = delete; + void operator=(Guard&&) = delete; +}; + +struct ExplicitStr +{ + std::string s; + explicit ExplicitStr(const char* chp) : s(chp) {}; +}; + +struct Date +{ + int i; + Date() = delete; + Date(int i) : i{i} {}; + Date(Date&& d) : i(d.i) { d.i = 0; } + Date(const Date&) = delete; + Date& operator=(const Date&) = delete; + Date& operator=(Date&& d) { i = d.i; d.i = 0; return *this;}; +}; + +bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; } +bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; } + + +namespace tr2 = std::experimental; + + +TEST(disengaged_ctor) +{ + tr2::optional o1; + assert (!o1); + + tr2::optional o2 = tr2::nullopt; + assert (!o2); + + tr2::optional o3 = o2; + assert (!o3); + + assert (o1 == tr2::nullopt); + assert (o1 == tr2::optional{}); + assert (!o1); + assert (bool(o1) == false); + + assert (o2 == tr2::nullopt); + assert (o2 == tr2::optional{}); + assert (!o2); + assert (bool(o2) == false); + + assert (o3 == tr2::nullopt); + assert (o3 == tr2::optional{}); + assert (!o3); + assert (bool(o3) == false); + + assert (o1 == o2); + assert (o2 == o1); + assert (o1 == o3); + assert (o3 == o1); + assert (o2 == o3); + assert (o3 == o2); +}; + + +TEST(value_ctor) +{ + OracleVal v; + tr2::optional oo1(v); + assert (oo1 != tr2::nullopt); + assert (oo1 != tr2::optional{}); + assert (oo1 == tr2::optional{v}); + assert (!!oo1); + assert (bool(oo1)); + // NA: assert (oo1->s == sValueCopyConstructed); + assert (oo1->s == sMoveConstructed); + assert (v.s == sValueConstructed); + + tr2::optional oo2(std::move(v)); + assert (oo2 != tr2::nullopt); + assert (oo2 != tr2::optional{}); + assert (oo2 == oo1); + assert (!!oo2); + assert (bool(oo2)); + // NA: assert (oo2->s == sValueMoveConstructed); + assert (oo2->s == sMoveConstructed); + assert (v.s == sMovedFrom); + + { + OracleVal v; + tr2::optional oo1{tr2::in_place, v}; + assert (oo1 != tr2::nullopt); + assert (oo1 != tr2::optional{}); + assert (oo1 == tr2::optional{v}); + assert (!!oo1); + assert (bool(oo1)); + assert (oo1->s == sValueCopyConstructed); + assert (v.s == sValueConstructed); + + tr2::optional oo2{tr2::in_place, std::move(v)}; + assert (oo2 != tr2::nullopt); + assert (oo2 != tr2::optional{}); + assert (oo2 == oo1); + assert (!!oo2); + assert (bool(oo2)); + assert (oo2->s == sValueMoveConstructed); + assert (v.s == sMovedFrom); + } +}; + + +TEST(assignment) +{ + tr2::optional oi; + oi = tr2::optional{1}; + assert (*oi == 1); + + oi = tr2::nullopt; + assert (!oi); + + oi = 2; + assert (*oi == 2); + + oi = {}; + assert (!oi); +}; + + +template +struct MoveAware +{ + T val; + bool moved; + MoveAware(T val) : val(val), moved(false) {} + MoveAware(MoveAware const&) = delete; + MoveAware(MoveAware&& rhs) : val(rhs.val), moved(rhs.moved) { + rhs.moved = true; + } + MoveAware& operator=(MoveAware const&) = delete; + MoveAware& operator=(MoveAware&& rhs) { + val = (rhs.val); + moved = (rhs.moved); + rhs.moved = true; + return *this; + } +}; + +TEST(moved_from_state) +{ + // first, test mock: + MoveAware i{1}, j{2}; + assert (i.val == 1); + assert (!i.moved); + assert (j.val == 2); + assert (!j.moved); + + MoveAware k = std::move(i); + assert (k.val == 1); + assert (!k.moved); + assert (i.val == 1); + assert (i.moved); + + k = std::move(j); + assert (k.val == 2); + assert (!k.moved); + assert (j.val == 2); + assert (j.moved); + + // now, test optional + tr2::optional> oi{1}, oj{2}; + assert (oi); + assert (!oi->moved); + assert (oj); + assert (!oj->moved); + + tr2::optional> ok = std::move(oi); + assert (ok); + assert (!ok->moved); + assert (oi); + assert (oi->moved); + + ok = std::move(oj); + assert (ok); + assert (!ok->moved); + assert (oj); + assert (oj->moved); +}; + + +TEST(copy_move_ctor_optional_int) +{ + tr2::optional oi; + tr2::optional oj = oi; + + assert (!oj); + assert (oj == oi); + assert (oj == tr2::nullopt); + assert (!bool(oj)); + + oi = 1; + tr2::optional ok = oi; + assert (!!ok); + assert (bool(ok)); + assert (ok == oi); + assert (ok != oj); + assert (*ok == 1); + + tr2::optional ol = std::move(oi); + assert (!!ol); + assert (bool(ol)); + assert (ol == oi); + assert (ol != oj); + assert (*ol == 1); +}; + + +TEST(optional_optional) +{ + tr2::optional> oi1 = tr2::nullopt; + assert (oi1 == tr2::nullopt); + assert (!oi1); + + { + tr2::optional> oi2 {tr2::in_place}; + assert (oi2 != tr2::nullopt); + assert (bool(oi2)); + assert (*oi2 == tr2::nullopt); + //assert (!(*oi2)); + //std::cout << typeid(**oi2).name() << std::endl; + } + + { + tr2::optional> oi2 {tr2::in_place, tr2::nullopt}; + assert (oi2 != tr2::nullopt); + assert (bool(oi2)); + assert (*oi2 == tr2::nullopt); + assert (!*oi2); + } + + { + tr2::optional> oi2 {tr2::optional{}}; + assert (oi2 != tr2::nullopt); + assert (bool(oi2)); + assert (*oi2 == tr2::nullopt); + assert (!*oi2); + } + + tr2::optional oi; + auto ooi = tr2::make_optional(oi); + static_assert( std::is_same>, decltype(ooi)>::value, ""); + +}; + +TEST(example_guard) +{ + using namespace tr2; + //FAILS: optional ogx(Guard("res1")); + //FAILS: optional ogx = "res1"; + //FAILS: optional ogx("res1"); + optional oga; // Guard is non-copyable (and non-moveable) + optional ogb(in_place, "res1"); // initialzes the contained value with "res1" + assert (bool(ogb)); + assert (ogb->val == "res1"); + + optional ogc(in_place); // default-constructs the contained value + assert (bool(ogc)); + assert (ogc->val == ""); + + oga.emplace("res1"); // initialzes the contained value with "res1" + assert (bool(oga)); + assert (oga->val == "res1"); + + oga.emplace(); // destroys the contained value and + // default-constructs the new one + assert (bool(oga)); + assert (oga->val == ""); + + oga = nullopt; // OK: make disengaged the optional Guard + assert (!(oga)); + //FAILS: ogb = {}; // ERROR: Guard is not Moveable +}; + + +void process(){} +void process(int ){} +void processNil(){} + + +TEST(example1) +{ + using namespace tr2; + optional oi; // create disengaged object + optional oj = nullopt; // alternative syntax + oi = oj; // assign disengaged object + optional ok = oj; // ok is disengaged + + if (oi) assert(false); // 'if oi is engaged...' + if (!oi) assert(true); // 'if oi is disengaged...' + + if (oi != nullopt) assert(false); // 'if oi is engaged...' + if (oi == nullopt) assert(true); // 'if oi is disengaged...' + + assert(oi == ok); // two disengaged optionals compare equal + + /////////////////////////////////////////////////////////////////////////// + optional ol{1}; // ol is engaged; its contained value is 1 + ok = 2; // ok becomes engaged; its contained value is 2 + oj = ol; // oj becomes engaged; its contained value is 1 + + assert(oi != ol); // disengaged != engaged + assert(ok != ol); // different contained values + assert(oj == ol); // same contained value + assert(oi < ol); // disengaged < engaged + assert(ol < ok); // less by contained value + + ///////////////////////////////////////////////////////////////////////////// + optional om{1}; // om is engaged; its contained value is 1 + optional on = om; // on is engaged; its contained value is 1 + om = 2; // om is engaged; its contained value is 2 + assert (on != om); // on still contains 3. They are not pointers + + ///////////////////////////////////////////////////////////////////////////// + int i = *ol; // i obtains the value contained in ol + assert (i == 1); + *ol = 9; // the object contained in ol becomes 9 + assert(*ol == 9); + assert(ol == make_optional(9)); + + /////////////////////////////////// + int p = 1; + optional op = p; + assert(*op == 1); + p = 2; + assert(*op == 1); // value contained in op is separated from p + + //////////////////////////////// + if (ol) + process(*ol); // use contained value if present + else + process(); // proceed without contained value + + if (!om) + processNil(); + else + process(*om); + + ///////////////////////////////////////// + process(ol.value_or(0)); // use 0 if ol is disengaged + + //////////////////////////////////////////// + ok = nullopt; // if ok was engaged calls T's dtor + oj = {}; // assigns a temporary disengaged optional +}; + + +TEST(example_guard) +{ + using std::experimental::optional; + const optional c = 4; + int i = *c; // i becomes 4 + assert (i == 4); + // FAILS: *c = i; // ERROR: cannot assign to const int& +}; + + +TEST(example_ref) +{ + using namespace std::experimental; + int i = 1; + int j = 2; + optional ora; // disengaged optional reference to int + optional orb = i; // contained reference refers to object i + + *orb = 3; // i becomes 3 + // FAILS: ora = j; // ERROR: optional refs do not have assignment from T + // FAILS: ora = {j}; // ERROR: optional refs do not have copy/move assignment + // FAILS: ora = orb; // ERROR: no copy/move assignment + ora.emplace(j); // OK: contained reference refers to object j + ora.emplace(i); // OK: contained reference now refers to object i + + ora = nullopt; // OK: ora becomes disengaged +}; + + +template +T getValue( tr2::optional newVal = tr2::nullopt, tr2::optional storeHere = tr2::nullopt ) +{ + T cached{}; + + if (newVal) { + cached = *newVal; + + if (storeHere) { + *storeHere = *newVal; // LEGAL: assigning T to T + } + } + return cached; +} + +TEST(example_optional_arg) +{ + int iii = 0; + iii = getValue(iii, iii); + iii = getValue(iii); + iii = getValue(); + + { + using namespace std::experimental; + optional grd1{in_place, "res1", 1}; // guard 1 initialized + optional grd2; + + grd2.emplace("res2", 2); // guard 2 initialized + grd1 = nullopt; // guard 1 released + + } // guard 2 released (in dtor) +}; + + +std::tuple getStartMidEnd() { return std::tuple{Date{1}, Date{2}, Date{3}}; } +void run(Date const&, Date const&, Date const&) {} + +TEST(example_date) +{ + using namespace std::experimental; + optional start, mid, end; // Date doesn't have default ctor (no good default date) + + std::tie(start, mid, end) = getStartMidEnd(); + run(*start, *mid, *end); +}; + + +std::experimental::optional readNextChar(){ return{}; } + +void run(std::experimental::optional) {} +void run(std::complex) {} + + +template +void assign_norebind(tr2::optional& optref, T& obj) +{ + if (optref) *optref = obj; + else optref.emplace(obj); +} + +template void unused(T&&) {} + +TEST(example_conceptual_model) +{ + using namespace std::experimental; + + optional oi = 0; + optional oj = 1; + optional ok = nullopt; + + oi = 1; + oj = nullopt; + ok = 0; + + unused(oi == nullopt); + unused(oj == 0); + unused(ok == 1); +}; + +TEST(example_rationale) +{ + using namespace std::experimental; + if (optional ch = readNextChar()) { + unused(ch); + // ... + } + + ////////////////////////////////// + optional opt1 = nullopt; + optional opt2 = {}; + + opt1 = nullopt; + opt2 = {}; + + if (opt1 == nullopt) {} + if (!opt2) {} + if (opt2 == optional{}) {} + + + + //////////////////////////////// + + run(nullopt); // pick the second overload + // FAILS: run({}); // ambiguous + + if (opt1 == nullopt) {} // fine + // FAILS: if (opt2 == {}) {} // ilegal + + //////////////////////////////// + assert (optional{} < optional{0}); + assert (optional{0} < optional{1}); + assert (!(optional{} < optional{}) ); + assert (!(optional{1} < optional{1})); + + assert (optional{} != optional{0}); + assert (optional{0} != optional{1}); + assert (optional{} == optional{} ); + assert (optional{0} == optional{0}); + + ///////////////////////////////// + optional o; + o = make_optional(1); // copy/move assignment + o = 1; // assignment from T + o.emplace(1); // emplacement + + //////////////////////////////////// + int isas = 0, i = 9; + optional asas = i; + assign_norebind(asas, isas); + + ///////////////////////////////////// + ////tr2::optional> ov2 = {2, 3}; + ////assert (bool(ov2)); + ////assert ((*ov2)[1] == 3); + //// + //////////////////////////////// + ////std::vector v = {1, 2, 4, 8}; + ////optional> ov = {1, 2, 4, 8}; + + ////assert (v == *ov); + //// + ////ov = {1, 2, 4, 8}; + + ////std::allocator a; + ////optional> ou { in_place, {1, 2, 4, 8}, a }; + + ////assert (ou == ov); + + ////////////////////////////// + // inconvenient syntax: + { + + tr2::optional> ov2{tr2::in_place, {2, 3}}; + + assert (bool(ov2)); + assert ((*ov2)[1] == 3); + + //////////////////////////// + + std::vector v = {1, 2, 4, 8}; + optional> ov{tr2::in_place, {1, 2, 4, 8}}; + + assert (v == *ov); + + ov.emplace({1, 2, 4, 8}); +/* + std::allocator a; + optional> ou { in_place, {1, 2, 4, 8}, a }; + + assert (ou == ov); +*/ + } + + ///////////////////////////////// + { + typedef int T; + optional> ot {in_place}; + optional> ou {in_place, nullopt}; + optional> ov {optional{}}; + + optional oi; + auto ooi = make_optional(oi); + static_assert( std::is_same>, decltype(ooi)>::value, ""); + } +}; + + +bool fun(std::string , std::experimental::optional oi = std::experimental::nullopt) +{ + return bool(oi); +} + +TEST(example_converting_ctor) +{ + using namespace std::experimental; + + assert (true == fun("dog", 2)); + assert (false == fun("dog")); + assert (false == fun("dog", nullopt)); // just to be explicit +}; + + +TEST(bad_comparison) +{ + tr2::optional oi, oj; + int i; + bool b = (oi == oj); + b = (oi >= i); + b = (oi == i); + unused(b); +}; + + +//// NOT APPLICABLE ANYMORE +////TEST(perfect_ctor) +////{ +//// //tr2::optional ois = "OS"; +//// assert (*ois == "OS"); +//// +//// // FAILS: tr2::optional oes = "OS"; +//// tr2::optional oes{"OS"}; +//// assert (oes->s == "OS"); +////}; + +TEST(value_or) +{ + tr2::optional oi = 1; + int i = oi.value_or(0); + assert (i == 1); + + oi = tr2::nullopt; + assert (oi.value_or(3) == 3); + + tr2::optional os{"AAA"}; + assert (os.value_or("BBB") == "AAA"); + os = {}; + assert (os.value_or("BBB") == "BBB"); +}; + +TEST(mixed_order) +{ + using namespace std::experimental; + + optional oN {nullopt}; + optional o0 {0}; + optional o1 {1}; + + assert ( (oN < 0)); + assert ( (oN < 1)); + assert (!(o0 < 0)); + assert ( (o0 < 1)); + assert (!(o1 < 0)); + assert (!(o1 < 1)); + + assert (!(oN >= 0)); + assert (!(oN >= 1)); + assert ( (o0 >= 0)); + assert (!(o0 >= 1)); + assert ( (o1 >= 0)); + assert ( (o1 >= 1)); + + assert (!(oN > 0)); + assert (!(oN > 1)); + assert (!(o0 > 0)); + assert (!(o0 > 1)); + assert ( (o1 > 0)); + assert (!(o1 > 1)); + + assert ( (oN <= 0)); + assert ( (oN <= 1)); + assert ( (o0 <= 0)); + assert ( (o0 <= 1)); + assert (!(o1 <= 0)); + assert ( (o1 <= 1)); + + assert ( (0 > oN)); + assert ( (1 > oN)); + assert (!(0 > o0)); + assert ( (1 > o0)); + assert (!(0 > o1)); + assert (!(1 > o1)); + + assert (!(0 <= oN)); + assert (!(1 <= oN)); + assert ( (0 <= o0)); + assert (!(1 <= o0)); + assert ( (0 <= o1)); + assert ( (1 <= o1)); + + assert (!(0 < oN)); + assert (!(1 < oN)); + assert (!(0 < o0)); + assert (!(1 < o0)); + assert ( (0 < o1)); + assert (!(1 < o1)); + + assert ( (0 >= oN)); + assert ( (1 >= oN)); + assert ( (0 >= o0)); + assert ( (1 >= o0)); + assert (!(0 >= o1)); + assert ( (1 >= o1)); +}; + +struct BadRelops +{ + int i; +}; + +constexpr bool operator<(BadRelops a, BadRelops b) { return a.i < b.i; } +constexpr bool operator>(BadRelops a, BadRelops b) { return a.i < b.i; } // intentional error! + +TEST(bad_relops) +{ + using namespace std::experimental; + BadRelops a{1}, b{2}; + assert (a < b); + assert (a > b); + + optional oa = a, ob = b; + assert (oa < ob); + assert (!(oa > ob)); + + assert (oa < b); + assert (oa > b); + + optional ra = a, rb = b; + assert (ra < rb); + assert (!(ra > rb)); + + assert (ra < b); + assert (ra > b); +}; + + +TEST(mixed_equality) +{ + using namespace std::experimental; + + assert (make_optional(0) == 0); + assert (make_optional(1) == 1); + assert (make_optional(0) != 1); + assert (make_optional(1) != 0); + + optional oN {nullopt}; + optional o0 {0}; + optional o1 {1}; + + assert (o0 == 0); + assert ( 0 == o0); + assert (o1 == 1); + assert ( 1 == o1); + assert (o1 != 0); + assert ( 0 != o1); + assert (o0 != 1); + assert ( 1 != o0); + + assert ( 1 != oN); + assert ( 0 != oN); + assert (oN != 1); + assert (oN != 0); + assert (!( 1 == oN)); + assert (!( 0 == oN)); + assert (!(oN == 1)); + assert (!(oN == 0)); + + std::string cat{"cat"}, dog{"dog"}; + optional oNil{}, oDog{"dog"}, oCat{"cat"}; + + assert (oCat == cat); + assert ( cat == oCat); + assert (oDog == dog); + assert ( dog == oDog); + assert (oDog != cat); + assert ( cat != oDog); + assert (oCat != dog); + assert ( dog != oCat); + + assert ( dog != oNil); + assert ( cat != oNil); + assert (oNil != dog); + assert (oNil != cat); + assert (!( dog == oNil)); + assert (!( cat == oNil)); + assert (!(oNil == dog)); + assert (!(oNil == cat)); +}; + +TEST(const_propagation) +{ + using namespace std::experimental; + + optional mmi{0}; + static_assert(std::is_same::value, "WTF"); + + const optional cmi{0}; + static_assert(std::is_same::value, "WTF"); + + optional mci{0}; + static_assert(std::is_same::value, "WTF"); + + optional cci{0}; + static_assert(std::is_same::value, "WTF"); +}; + + +static_assert(std::is_base_of::value, ""); + +TEST(safe_value) +{ + using namespace std::experimental; + + try { + optional ovN{}, ov1{1}; + + int& r1 = ov1.value(); + assert (r1 == 1); + + try { + ovN.value(); + assert (false); + } + catch (bad_optional_access const&) { + } + + { // ref variant + int i1 = 1; + optional orN{}, or1{i1}; + + int& r2 = or1.value(); + assert (r2 == 1); + + try { + orN.value(); + assert (false); + } + catch (bad_optional_access const&) { + } + } + } + catch(...) { + assert (false); + } +}; + +TEST(optional_ref) +{ + using namespace tr2; + // FAILS: optional orr; + // FAILS: optional on; + int i = 8; + optional ori; + assert (!ori); + ori.emplace(i); + assert (bool(ori)); + assert (*ori == 8); + assert (&*ori == &i); + *ori = 9; + assert (i == 9); + + // FAILS: int& ir = ori.value_or(i); + int ii = ori.value_or(i); + assert (ii == 9); + ii = 7; + assert (*ori == 9); + + int j = 22; + auto&& oj = make_optional(std::ref(j)); + *oj = 23; + assert (&*oj == &j); + assert (j == 23); +}; + +TEST(optional_ref_const_propagation) +{ + using namespace std::experimental; + + int i = 9; + const optional mi = i; + int& r = *mi; + optional ci = i; + static_assert(std::is_same::value, "WTF"); + static_assert(std::is_same::value, "WTF"); + + unused(r); +}; + +TEST(optional_ref_assign) +{ + using namespace std::experimental; + + int i = 9; + optional ori = i; + + int j = 1; + ori = optional{j}; + ori = {j}; + // FAILS: ori = j; + + optional orx = ori; + ori = orx; + + optional orj = j; + + assert (ori); + assert (*ori == 1); + assert (ori == orj); + assert (i == 9); + + *ori = 2; + assert (*ori == 2); + assert (ori == 2); + assert (2 == ori); + assert (ori != 3); + + assert (ori == orj); + assert (j == 2); + assert (i == 9); + + ori = {}; + assert (!ori); + assert (ori != orj); + assert (j == 2); + assert (i == 9); +}; + + +TEST(optional_ref_swap) +{ + using namespace std::experimental; + int i = 0; + int j = 1; + optional oi = i; + optional oj = j; + + assert (&*oi == &i); + assert (&*oj == &j); + + swap(oi, oj); + assert (&*oi == &j); + assert (&*oj == &i); +}; + +TEST(optional_initialization) +{ + using namespace tr2; + using std::string; + string s = "STR"; + + optional os{s}; + optional ot = s; + optional ou{"STR"}; + optional ov = string{"STR"}; + +}; + +#include + +TEST(optional_hashing) +{ + using namespace tr2; + using std::string; + + std::hash hi; + std::hash> hoi; + std::hash hs; + std::hash> hos; + + assert (hi(0) == hoi(optional{0})); + assert (hi(1) == hoi(optional{1})); + assert (hi(3198) == hoi(optional{3198})); + + assert (hs("") == hos(optional{""})); + assert (hs("0") == hos(optional{"0"})); + assert (hs("Qa1#") == hos(optional{"Qa1#"})); + + std::unordered_set> set; + assert(set.find({"Qa1#"}) == set.end()); + + set.insert({"0"}); + assert(set.find({"Qa1#"}) == set.end()); + + set.insert({"Qa1#"}); + assert(set.find({"Qa1#"}) != set.end()); +}; + + +// optional_ref_emulation +template +struct generic +{ + typedef T type; +}; + +template +struct generic +{ + typedef std::reference_wrapper type; +}; + +template +using Generic = typename generic::type; + +template +bool generic_fun() +{ + std::experimental::optional> op; + return bool(op); +} + +TEST(optional_ref_emulation) +{ + using namespace std::experimental; + optional> oi = 1; + assert (*oi == 1); + + int i = 8; + int j = 4; + optional> ori {i}; + assert (*ori == 8); + assert ((void*)&*ori != (void*)&i); // !DIFFERENT THAN optional + + *ori = j; + assert (*ori == 4); +}; + + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 +TEST(moved_on_value_or) +{ + using namespace tr2; + optional oo{in_place}; + + assert (oo); + assert (oo->s == sDefaultConstructed); + + Oracle o = std::move(oo).value_or( Oracle{OracleVal{}} ); + assert (oo); + assert (oo->s == sMovedFrom); + assert (o.s == sMoveConstructed); + + optional> om {in_place, 1}; + assert (om); + assert (om->moved == false); + + /*MoveAware m =*/ std::move(om).value_or( MoveAware{1} ); + assert (om); + assert (om->moved == true); + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + { + Date d = optional{in_place, 1}.value(); + assert (d.i); // to silence compiler warning + + Date d2 = *optional{in_place, 1}; + assert (d2.i); // to silence compiler warning + } +# endif +}; +# endif + + +TEST(optional_ref_hashing) +{ + using namespace tr2; + using std::string; + + std::hash hi; + std::hash> hoi; + std::hash hs; + std::hash> hos; + + int i0 = 0; + int i1 = 1; + assert (hi(0) == hoi(optional{i0})); + assert (hi(1) == hoi(optional{i1})); + + string s{""}; + string s0{"0"}; + string sCAT{"CAT"}; + assert (hs("") == hos(optional{s})); + assert (hs("0") == hos(optional{s0})); + assert (hs("CAT") == hos(optional{sCAT})); + + std::unordered_set> set; + assert(set.find({sCAT}) == set.end()); + + set.insert({s0}); + assert(set.find({sCAT}) == set.end()); + + set.insert({sCAT}); + assert(set.find({sCAT}) != set.end()); +}; + +struct Combined +{ + int m = 0; + int n = 1; + + constexpr Combined() : m{5}, n{6} {} + constexpr Combined(int m, int n) : m{m}, n{n} {} +}; + +struct Nasty +{ + int m = 0; + int n = 1; + + constexpr Nasty() : m{5}, n{6} {} + constexpr Nasty(int m, int n) : m{m}, n{n} {} + + int operator&() { return n; } + int operator&() const { return n; } +}; + +TEST(arrow_operator) +{ + using namespace std::experimental; + + optional oc1{in_place, 1, 2}; + assert (oc1); + assert (oc1->m == 1); + assert (oc1->n == 2); + + optional on{in_place, 1, 2}; + assert (on); + assert (on->m == 1); + assert (on->n == 2); +}; + +TEST(arrow_wit_optional_ref) +{ + using namespace std::experimental; + + Combined c{1, 2}; + optional oc = c; + assert (oc); + assert (oc->m == 1); + assert (oc->n == 2); + + Nasty n{1, 2}; + Nasty m{3, 4}; + Nasty p{5, 6}; + + optional on{n}; + assert (on); + assert (on->m == 1); + assert (on->n == 2); + + on = {m}; + assert (on); + assert (on->m == 3); + assert (on->n == 4); + + on.emplace(p); + assert (on); + assert (on->m == 5); + assert (on->n == 6); + + optional om{in_place, n}; + assert (om); + assert (om->m == 1); + assert (om->n == 2); +}; + +TEST(no_dangling_reference_in_value) +{ + // this mostly tests compiler warnings + using namespace std::experimental; + optional oi {2}; + unused (oi.value()); + const optional coi {3}; + unused (coi.value()); +}; + +struct CountedObject +{ + static int _counter; + bool _throw; + CountedObject(bool b) : _throw(b) { ++_counter; } + CountedObject(CountedObject const& rhs) : _throw(rhs._throw) { if (_throw) throw int(); } + ~CountedObject() { --_counter; } +}; + +int CountedObject::_counter = 0; + +TEST(exception_safety) +{ + using namespace std::experimental; + try { + optional oo(in_place, true); // throw + optional o1(oo); + } + catch(...) + { + // + } + assert(CountedObject::_counter == 0); + + try { + optional oo(in_place, true); // throw + optional o1(std::move(oo)); // now move + } + catch(...) + { + // + } + assert(CountedObject::_counter == 0); +}; + +//// constexpr tests + +// these 4 classes have different noexcept signatures in move operations +struct NothrowBoth { + NothrowBoth(NothrowBoth&&) noexcept(true) {}; + void operator=(NothrowBoth&&) noexcept(true) {}; +}; +struct NothrowCtor { + NothrowCtor(NothrowCtor&&) noexcept(true) {}; + void operator=(NothrowCtor&&) noexcept(false) {}; +}; +struct NothrowAssign { + NothrowAssign(NothrowAssign&&) noexcept(false) {}; + void operator=(NothrowAssign&&) noexcept(true) {}; +}; +struct NothrowNone { + NothrowNone(NothrowNone&&) noexcept(false) {}; + void operator=(NothrowNone&&) noexcept(false) {}; +}; + +void test_noexcept() +{ + { + tr2::optional b1, b2; + static_assert(noexcept(tr2::optional{tr2::constexpr_move(b1)}), "bad noexcept!"); + static_assert(noexcept(b1 = tr2::constexpr_move(b2)), "bad noexcept!"); + } + { + tr2::optional c1, c2; + static_assert(noexcept(tr2::optional{tr2::constexpr_move(c1)}), "bad noexcept!"); + static_assert(!noexcept(c1 = tr2::constexpr_move(c2)), "bad noexcept!"); + } + { + tr2::optional a1, a2; + static_assert(!noexcept(tr2::optional{tr2::constexpr_move(a1)}), "bad noexcept!"); + static_assert(!noexcept(a1 = tr2::constexpr_move(a2)), "bad noexcept!"); + } + { + tr2::optional n1, n2; + static_assert(!noexcept(tr2::optional{tr2::constexpr_move(n1)}), "bad noexcept!"); + static_assert(!noexcept(n1 = tr2::constexpr_move(n2)), "bad noexcept!"); + } +} + + +void constexpr_test_disengaged() +{ + constexpr tr2::optional g0{}; + constexpr tr2::optional g1{tr2::nullopt}; + static_assert( !g0, "initialized!" ); + static_assert( !g1, "initialized!" ); + + static_assert( bool(g1) == bool(g0), "ne!" ); + + static_assert( g1 == g0, "ne!" ); + static_assert( !(g1 != g0), "ne!" ); + static_assert( g1 >= g0, "ne!" ); + static_assert( !(g1 > g0), "ne!" ); + static_assert( g1 <= g0, "ne!" ); + static_assert( !(g1 = tr2::nullopt, "!" ); + static_assert( !(g1 > tr2::nullopt), "!" ); + + static_assert( (tr2::nullopt == g0), "!" ); + static_assert( !(tr2::nullopt != g0), "!" ); + static_assert( (tr2::nullopt >= g0), "!" ); + static_assert( !(tr2::nullopt > g0), "!" ); + static_assert( (tr2::nullopt <= g0), "!" ); + static_assert( !(tr2::nullopt < g0), "!" ); + + static_assert( (g1 != tr2::optional(1)), "!" ); + static_assert( !(g1 == tr2::optional(1)), "!" ); + static_assert( (g1 < tr2::optional(1)), "!" ); + static_assert( (g1 <= tr2::optional(1)), "!" ); + static_assert( !(g1 > tr2::optional(1)), "!" ); + static_assert( !(g1 > tr2::optional(1)), "!" ); +} + + +constexpr tr2::optional g0{}; +constexpr tr2::optional g2{2}; +static_assert( g2, "not initialized!" ); +static_assert( *g2 == 2, "not 2!" ); +static_assert( g2 == tr2::optional(2), "not 2!" ); +static_assert( g2 != g0, "eq!" ); + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 +static_assert( *tr2::optional{3} == 3, "WTF!" ); +static_assert( tr2::optional{3}.value() == 3, "WTF!" ); +static_assert( tr2::optional{3}.value_or(1) == 3, "WTF!" ); +static_assert( tr2::optional{}.value_or(4) == 4, "WTF!" ); +# endif + +constexpr tr2::optional gc0{tr2::in_place}; +static_assert(gc0->n == 6, "WTF!"); + +// optional refs +int gi = 0; +constexpr tr2::optional gori = gi; +constexpr tr2::optional gorn{}; +constexpr int& gri = *gori; +static_assert(gori, "WTF"); +static_assert(!gorn, "WTF"); +static_assert(gori != tr2::nullopt, "WTF"); +static_assert(gorn == tr2::nullopt, "WTF"); +static_assert(&gri == &*gori, "WTF"); + +constexpr int gci = 1; +constexpr tr2::optional gorci = gci; +constexpr tr2::optional gorcn{}; + +static_assert(gorcn < gorci, "WTF"); +static_assert(gorcn <= gorci, "WTF"); +static_assert(gorci == gorci, "WTF"); +static_assert(*gorci == 1, "WTF"); +static_assert(gorci == gci, "WTF"); + +namespace constexpr_optional_ref_and_arrow +{ + using namespace std::experimental; + constexpr Combined c{1, 2}; + constexpr optional oc = c; + static_assert(oc, "WTF!"); + static_assert(oc->m == 1, "WTF!"); + static_assert(oc->n == 2, "WTF!"); +} + +#if OPTIONAL_HAS_CONSTEXPR_INIT_LIST + +namespace InitList +{ + using namespace std::experimental; + + struct ConstInitLister + { + template + constexpr ConstInitLister(std::initializer_list il) : len (il.size()) {} + size_t len; + }; + + constexpr ConstInitLister CIL {2, 3, 4}; + static_assert(CIL.len == 3, "WTF!"); + + constexpr optional oil {in_place, {4, 5, 6, 7}}; + static_assert(oil, "WTF!"); + static_assert(oil->len == 4, "WTF!"); +} + +#endif // OPTIONAL_HAS_CONSTEXPR_INIT_LIST + +// end constexpr tests + + +#include + + +struct VEC +{ + std::vector v; + template + VEC( X&&...x) : v(std::forward(x)...) {} + + template + VEC(std::initializer_list il, X&&...x) : v(il, std::forward(x)...) {} +}; + + + +int main() { + tr2::optional oi = 1; + assert (bool(oi)); + oi.operator=({}); + assert (!oi); + + VEC v = {5, 6}; + + if (OPTIONAL_HAS_THIS_RVALUE_REFS) + std::cout << "Optional has rvalue references for *this" << std::endl; + else + std::cout << "Optional doesn't have rvalue references for *this" << std::endl; + + if (OPTIONAL_HAS_CONSTEXPR_INIT_LIST) + std::cout << "Optional has constexpr initializer_list" << std::endl; + else + std::cout << "Optional doesn't have constexpr initializer_list" << std::endl; + + if (OPTIONAL_HAS_MOVE_ACCESSORS) + std::cout << "Optional has constexpr move accessors" << std::endl; + else + std::cout << "Optional doesn't have constexpr move accessors" << std::endl; +} + diff --git a/3rdparty/sol2/Optional/test_type_traits.cpp b/3rdparty/sol2/Optional/test_type_traits.cpp new file mode 100644 index 00000000000..8ec82b70871 --- /dev/null +++ b/3rdparty/sol2/Optional/test_type_traits.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2011 - 2012 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if (defined __clang__) + namespace std { class type_info; } +#endif + +# include "optional.hpp" + +namespace std { namespace experimental { + +struct Val +{ + Val(){} + Val( Val const & ){} + Val( Val && ) noexcept {} + + Val & operator=( Val const & ) = delete; + Val & operator=( Val && ) noexcept = delete; +}; + +struct Safe +{ + Safe(){} + Safe( Safe const & ){} + Safe( Safe && ) noexcept {} + + Safe & operator=( Safe const & ){ return *this; } + Safe & operator=( Safe && ) noexcept { return *this; } +}; + +struct Unsafe +{ + Unsafe(){} + Unsafe( Unsafe const & ){} + Unsafe( Unsafe && ){} + + Unsafe & operator=( Unsafe const & ){ return *this; } + Unsafe & operator=( Unsafe && ) { return *this; } +}; + +struct VoidNothrowBoth +{ + VoidNothrowBoth(VoidNothrowBoth&&) noexcept(true) {}; + void operator=(VoidNothrowBoth&&) noexcept(true) {}; // note void return type +}; + + +static_assert(is_nothrow_move_constructible::value, "WTF!"); +static_assert(!is_nothrow_move_constructible::value, "WTF!"); + +static_assert(is_assignable::value, "WTF!"); +static_assert(!is_assignable::value, "WTF!"); + +static_assert(is_nothrow_move_assignable::value, "WTF!"); +static_assert(!is_nothrow_move_assignable::value, "WTF!"); + +static_assert(is_nothrow_move_constructible::value, "WTF!"); +static_assert(is_nothrow_move_assignable::value, "WTF!"); + +}} // namespace std::experimental + +int main() { } diff --git a/3rdparty/sol2/README.md b/3rdparty/sol2/README.md new file mode 100644 index 00000000000..3eb58f6d3de --- /dev/null +++ b/3rdparty/sol2/README.md @@ -0,0 +1,75 @@ +## Sol 2.14 + +[![Build Status](https://travis-ci.org/ThePhD/sol2.svg?branch=develop)](https://travis-ci.org/ThePhD/sol2) +[![Documentation Status](https://readthedocs.org/projects/sol2/badge/?version=latest)](http://sol2.readthedocs.io/en/latest/?badge=latest) + +Sol is a C++ library binding to Lua. It currently supports all Lua versions 5.1+ (LuaJIT 2.x included). Sol aims to be easy to use and easy to add to a project. +The library is header-only for easy integration with projects. + +## Documentation + +Find it [here](http://sol2.rtfd.io/). A run-through kind of tutorial is [here](http://sol2.readthedocs.io/en/latest/tutorial/all-the-things.html)! The API documentation goes over most cases (particularly, the "api/usertype" and "api/proxy" and "api/function" sections) that should still get you off your feet and going, and there's an examples directory [here](https://github.com/ThePhD/sol2/tree/develop/examples) as well. + +## Sneak Peek + +```cpp +#include +#include + +int main() { + sol::state lua; + int x = 0; + lua.set_function("beep", [&x]{ ++x; }); + lua.script("beep()"); + assert(x == 1); +} +``` + +```cpp +#include +#include + +struct vars { + int boop = 0; +}; + +int main() { + sol::state lua; + lua.new_usertype("vars", "boop", &vars::boop); + lua.script("beep = vars.new()\n" + "beep.boop = 1"); + assert(lua.get("beep").boop == 1); +} +``` + +More examples are given in the examples directory. + +## Creating a single header + +You can grab a single header out of the library [here](https://github.com/ThePhD/sol2/tree/develop/single/sol). For stable version, check the releases tab on github for a provided single header file for maximum ease of use. A script called `single.py` is provided in the repository if there's some bleeding edge change that hasn't been published on the releases page. You can run this script to create a single file version of the library so you can only include that part of it. Check `single.py --help` for more info. + +## Features + +- [Fastest in the land](http://sol2.readthedocs.io/en/latest/benchmarks.html) (see: sol2 graph and table entries). +- Supports retrieval and setting of multiple types including `std::string` and `std::map/unordered_map`. +- Lambda, function, and member function bindings are supported. +- Intermediate type for checking if a variable exists. +- Simple API that completely abstracts away the C stack API, including `protected_function` with the ability to use an error-handling function. +- `operator[]`-style manipulation of tables +- C++ type representations in lua userdata as `usertype`s with guaranteed cleanup. +- Customization points to allow your C++ objects to be pushed and retrieved from Lua as multiple consecutive objects, or anything else you desire! +- Overloaded function calls: `my_function(1); my_function("Hello")` in the same lua script route to different function calls based on parameters +- Support for tables, nested tables, table iteration with `table.for_each` / `begin()` and `end()` iterators. + +## Supported Compilers + +Sol makes use of C++11/14 features. GCC 4.9 and Clang 3.4 (with std=c++1z and appropriate standard library) or higher should be able to compile without problems. However, the +officially supported and CI-tested compilers are: + +- GCC 4.9.0+ +- Clang 3.5+ +- Visual Studio 2015 Community (Visual C++ 14.0)+ + +## License + +Sol is distributed with an MIT License. You can see LICENSE.txt for more info. diff --git a/3rdparty/sol2/bootstrap.py b/3rdparty/sol2/bootstrap.py new file mode 100644 index 00000000000..d1e6bfdfdcb --- /dev/null +++ b/3rdparty/sol2/bootstrap.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python + +import ninja_syntax +import os, sys, glob, re +import itertools +import argparse + +# utilities +def flags(*args): + return ' '.join(itertools.chain(*args)) + +def includes(l): + return ['-I"{}"'.format(x) for x in l] + +def library_includes(l): + return ['-L"{}"'.format(x) for x in l] + +def libraries(l): + return ['-l{}'.format(x) for x in l] + +def dependencies(l): + return ['-isystem"{}"'.format(x) for x in l] + +def object_file(f): + (root, ext) = os.path.splitext(f) + return os.path.join(objdir, root + '.o') + +def replace_extension(f, e): + (root, ext) = os.path.splitext(f) + return root + e + +# Default install dir +install_dir = os.path.join('/usr', 'include') if 'linux' in sys.platform else 'include' + +# Compiler: Read from environment or defaulted +cxx = os.environ.get('CXX', "g++") + +# command line stuff +parser = argparse.ArgumentParser() +parser.add_argument('--debug', action='store_true', help='compile with debug flags') +parser.add_argument('--cxx', metavar='', help='compiler name to use (default: env.CXX=%s)' % cxx, default=cxx) +parser.add_argument('--cxx-flags', help='additional flags passed to the compiler', default='') +parser.add_argument('--ci', action='store_true', help=argparse.SUPPRESS) +parser.add_argument('--testing', action='store_true', help=argparse.SUPPRESS) +parser.add_argument('--lua-version', help='Lua version, e.g. lua53', default='lua53') +parser.add_argument('--lua-lib', help='lua library name (without the lib on *nix).', default='lua') +parser.add_argument('--lua-dir', metavar='', help='directory lua is in with include and lib subdirectories') +parser.add_argument('--install-dir', metavar='', help='directory to install the headers to', default=install_dir); +parser.epilog = """In order to install sol, administrative privileges might be required. +Note that installation is done through the 'ninja install' command. To uninstall, the +command used is 'ninja uninstall'. The default installation directory for this +system is {}""".format(install_dir) + +args = parser.parse_args() + +# general variables +include = [ '.', './include' ] +depends = [os.path.join('Catch', 'include')] +cxxflags = [ '-Wall', '-Wextra', '-Wpedantic', '-pedantic', '-pedantic-errors', '-std=c++14', '-ftemplate-depth=1024' ] +cxxflags.extend([p for p in re.split("( |\\\".*?\\\"|'.*?')", args.cxx_flags) if p.strip()]) +example_cxxflags = [ '-Wall', '-Wextra', '-Wpedantic', '-pedantic', '-pedantic-errors', '-std=c++14', '-ftemplate-depth=1024' ] +example_cxxflags.extend([p for p in re.split("( |\\\".*?\\\"|'.*?')", args.cxx_flags) if p.strip()]) +ldflags = [] +script_dir = os.path.dirname(os.path.realpath(sys.argv[0])) +sol_dir = os.path.join(script_dir, 'sol') +sol_file = os.path.join(script_dir, 'sol.hpp') + +copy_command = 'cp -rf {} $in && cp -f {} $in'.format(sol_dir, sol_file) +remove_command = 'rm -rf {} && rm -f {}'.format(os.path.join(args.install_dir, 'sol'), os.path.join(args.install_dir, 'sol.hpp')) +if sys.platform == 'win32': + copy_command = 'robocopy /COPYALL /E {} $in && robocopy /COPYALL {} $in'.format(sol_dir, sol_file) + remove_command = 'rmdir /S /Q {} && erase /F /S /Q /A {}'.format(os.path.join(args.install_dir, 'sol'), + os.path.join(args.install_dir, 'sol.hpp')) + +if not args.lua_lib: + args.lua_lib = 'lua' + +if args.debug: + cxxflags.extend(['-g', '-O0']) +else: + cxxflags.extend(['-DNDEBUG', '-O3']) +example_cxxflags.extend(['-g', '-O0']) + +if args.lua_dir: + include.extend([os.path.join(args.lua_dir, 'include')]) + ldflags.extend(library_includes([os.path.join(args.lua_dir, 'lib')])) + +if 'linux' in sys.platform: + lua_version = os.environ.get('LUA_VERSION', args.lua_version) + if re.match(r'lua5[1-3]', lua_version): + # Using normal lua + lua_lib = lua_version[:-1] + '.' + lua_version[-1] + lua_incl = lua_lib + elif re.match(r'luajit5[1-3]', lua_version): + # luajit + lua_incl = 'luajit-2.0' # I don't get this.. + lua_lib = lua_version[:-2] + '-' + lua_version[-2] + '.' + lua_version[-1] + include.extend(['/usr/include/luajit-2.0/', '/usr/local/include/luajit-2.0/']) + else: + raise Exception('Unknown lua_version={}' % lua_version) + + + include.extend(['/usr/include/' + lua_incl, '/usr/local/include/' + lua_incl]) + ldflags.extend(library_includes(['/usr/local/lib'])) + ldflags.extend(libraries([lua_lib])) +elif 'darwin' in sys.platform: + # OSX + lua_version = os.environ.get('LUA_VERSION', args.lua_version) + if re.match(r'lua5[1-3]', lua_version): + # Using normal lua + lua_incl = lua_version[:-1] + '.' + lua_version[-1] + lua_lib = lua_version[:-2] + '.' + lua_version[-2] + '.' + lua_version[-1] + elif re.match(r'luajit', lua_version): + # luajit + lua_incl = 'luajit-2.0' + lua_lib = 'luajit' + ldflags.extend(['-pagezero_size 10000', '-image_base 100000000']) + elif re.match(r'luajit5[1-3]', lua_version): + # luajit + lua_incl = 'luajit-2.0' + lua_lib = lua_version[:-2] + '-' + lua_version[-2] + '.' + lua_version[-1] + ldflags.extend(['-pagezero_size 10000', '-image_base 100000000']) + else: + raise Exception('Unknown lua_version={}' % lua_version) + + depends.extend(['/usr/include/' + lua_incl, '/usr/local/include/' + lua_incl]) + ldflags.extend(library_includes(['/usr/local/lib'])) + ldflags.extend(libraries([lua_lib])) +else: + ldflags.extend(libraries([args.lua_lib])) + +if args.testing: + cxxflags.append('-Wmissing-declarations') + +if 'linux' in sys.platform: + ldflags.extend(libraries(['dl'])) + +builddir = 'bin' +objdir = 'obj' +if 'win32' in sys.platform: + tests = os.path.join(builddir, 'tests.exe') +else: + tests = os.path.join(builddir, 'tests') + +tests_inputs = [] +tests_object_files = [] +for f in glob.glob('test*.cpp'): + obj = object_file(f) + tests_inputs.append(f) + tests_object_files.append(obj) + +examples = [] +examples_input = [] +for f in glob.glob('examples/*.cpp'): + if 'win32' in sys.platform: + example = os.path.join(builddir, replace_extension(f, '.exe')) + else: + example = os.path.join(builddir, replace_extension(f, '')) + examples_input.append(f) + examples.append(example) + + +# ninja file +ninja = ninja_syntax.Writer(open('build.ninja', 'w')) + +# variables +ninja.variable('ninja_required_version', '1.3') +ninja.variable('builddir', 'bin') +ninja.variable('cxx', args.cxx) +ninja.variable('cxxflags', flags(cxxflags + includes(include) + dependencies(depends))) +ninja.variable('example_cxxflags', flags(example_cxxflags + includes(include) + dependencies(depends))) +ninja.variable('ldflags', flags(ldflags)) +ninja.newline() + +# rules +ninja.rule('bootstrap', command = ' '.join(['python'] + sys.argv), generator = True) +ninja.rule('compile', command = '$cxx -MMD -MF $out.d -c $cxxflags -Werror $in -o $out', + deps = 'gcc', depfile = '$out.d', + description = 'compiling $in to $out') +ninja.rule('link', command = '$cxx $cxxflags $in -o $out $ldflags', description = 'creating $out') +ninja.rule('tests_runner', command = tests) +ninja.rule('examples_runner', command = 'cmd /c ' + (' && '.join(examples)) if 'win32' in sys.platform else ' && '.join(examples) ) +ninja.rule('example', command = '$cxx $example_cxxflags -MMD -MF $out.d $in -o $out $ldflags', + deps = 'gcc', depfile = '$out.d', + description = 'compiling example $in to $out') +ninja.rule('installer', command = copy_command) +ninja.rule('uninstaller', command = remove_command) +ninja.newline() + +# builds +ninja.build('build.ninja', 'bootstrap', implicit = sys.argv[0]) + +for obj, f in zip(tests_object_files, tests_inputs): + ninja.build(obj, 'compile', inputs = f) + +for example, f in zip(examples, examples_input): + ninja.build(example, 'example', inputs = f) + +ninja.build(tests, 'link', inputs = tests_object_files) +ninja.build('tests', 'phony', inputs = tests) +ninja.build('examples', 'phony', inputs = examples) +ninja.build('install', 'installer', inputs = args.install_dir) +ninja.build('uninstall', 'uninstaller') +ninja.build('run', 'tests_runner', implicit = 'tests') +ninja.build('run_examples', 'examples_runner', implicit = 'examples') +ninja.default('run run_examples') diff --git a/3rdparty/sol2/docs/Makefile b/3rdparty/sol2/docs/Makefile new file mode 100644 index 00000000000..ac69fbd7e5d --- /dev/null +++ b/3rdparty/sol2/docs/Makefile @@ -0,0 +1,216 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Sol.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Sol.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Sol" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Sol" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/3rdparty/sol2/docs/make.bat b/3rdparty/sol2/docs/make.bat new file mode 100644 index 00000000000..ab1cb81297b --- /dev/null +++ b/3rdparty/sol2/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +set I18NSPHINXOPTS=%SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 1>NUL 2>NUL +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Sol.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Sol.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/3rdparty/sol2/docs/source/api/api-top.rst b/3rdparty/sol2/docs/source/api/api-top.rst new file mode 100644 index 00000000000..f9b0378b30e --- /dev/null +++ b/3rdparty/sol2/docs/source/api/api-top.rst @@ -0,0 +1,46 @@ +api reference manual +==================== + +Browse the various function and classes :doc:`Sol<../index>` utilizes to make your life easier when working with Lua. + + +.. toctree:: + :caption: Sol API + :name: apitoc + :maxdepth: 2 + + state + table + proxy + as_table + usertype + simple_usertype + usertype_memory + unique_usertype_traits + tie + function + protected_function + coroutine + error + object + userdata + reference + thread + stack_reference + make_reference + optional + this_state + variadic_args + overload + property + var + protect + readonly + as_function + c_call + resolve + stack + user + compatibility + types + metatable_key diff --git a/3rdparty/sol2/docs/source/api/as_function.rst b/3rdparty/sol2/docs/source/api/as_function.rst new file mode 100644 index 00000000000..bb058ba52c7 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/as_function.rst @@ -0,0 +1,67 @@ +as_function +=========== +make sure an object is pushed as a function +------------------------------------------- + +.. code-block:: cpp + + template , typename... Args> + function_argumants as_function ( Args&& ... ); + +This function serves the purpose of ensuring that a callable struct (like a lambda) can be passed to the ``set( key, value )`` calls on :ref:`sol::table` and be treated like a function binding instead of a userdata. It is recommended that one uses the :ref:`sol::table::set_function` call instead, but if for some reason one must use ``set``, then ``as_function`` can help ensure a callable struct is handled like a lambda / callable, and not as just a userdata structure. + +This class can also make it so usertypes bind variable types as functions to for usertype bindings. + +.. code-block:: cpp + + #include + + int main () { + struct callable { + int operator()( int a, bool b ) { + return a + b ? 10 : 20; + } + }; + + + sol::state lua; + // Binds struct as userdata + lua.set( "not_func", callable() ); + // Binds struct as function + lua.set( "func", sol::as_function( callable() ) ); + // equivalent: lua.set_function( "func", callable() ); + // equivalent: lua["func"] = callable(); + } + +Note that if you actually want a userdata, but you want it to be callable, you simply need to create a :ref:`sol::table::new_usertype` and then bind the ``"__call"`` metamethod (or just use ``sol::meta_function::call`` :ref:`enumeration`). + +Here's an example of binding a variable as a function to a usertype: + +.. code-block:: cpp + + #include + + int main () { + class B { + public: + int bvar = 24; + }; + + sol::state lua; + lua.open_libraries(); + lua.new_usertype("B", + // bind as variable + "b", &B::bvar, + // bind as function + "f", sol::as_function(&B::bvar) + ); + + B b; + lua.set("b", &b); + lua.script("x = b:f()"); + lua.script("y = b.b"); + int x = lua["x"]; + int y = lua["y"]; + assert(x == 24); + assert(y == 24); + } diff --git a/3rdparty/sol2/docs/source/api/as_table.rst b/3rdparty/sol2/docs/source/api/as_table.rst new file mode 100644 index 00000000000..58870fa770f --- /dev/null +++ b/3rdparty/sol2/docs/source/api/as_table.rst @@ -0,0 +1,24 @@ +as_table +=========== +make sure an object is pushed as a table +---------------------------------------- + +.. code-block:: cpp + + template + as_table_t { ... }; + + template + as_table_t as_function ( T&& container ); + +This function serves the purpose of ensuring that an object is pushed -- if possible -- like a table into Lua. The container passed here can be a pointer, a reference, a ``std::reference_wrapper`` around a container, or just a plain container value. It must have a begin/end function, and if it has a ``std::pair`` as its ``value_type``, it will be pushed as a dictionary. Otherwise, it's pushed as a sequence. + +.. code-block:: cpp + + sol::state lua; + lua.open_libraries(); + lua.set("my_table", sol::as_table(std::vector{ 1, 2, 3, 4, 5 })); + lua.script("for k, v in ipairs(my_table) do print(k, v) assert(k == v) end"); + + +Note that any caveats with Lua tables apply the moment it is serialized, and the data cannot be gotten out back out in C++ as a vector without explicitly using the ``as_table_t`` marker for your get and conversion operations using Sol. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/c_call.rst b/3rdparty/sol2/docs/source/api/c_call.rst new file mode 100644 index 00000000000..36395eea549 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/c_call.rst @@ -0,0 +1,71 @@ +c_call +====== +Templated type to transport functions through templates +------------------------------------------------------- + +.. code-block:: cpp + + template + int c_call (lua_State* L); + + template + int c_call (lua_State* L); + +The goal of ``sol::c_call<...>`` is to provide a way to wrap a function and transport it through a compile-time context. This enables faster speed at the cost of a much harder to read / poorer interface. ``sol::c_call`` expects a type for its first template argument, and a value of the previously provided type for the second template argument. To make a compile-time transported overloaded function, specify multiple functions in the same ``type, value`` pairing, but put it inside of a ``sol::wrap``. Note that is can also be placed into the argument list for a :doc:`usertype` as well. + +It is advisable for the user to consider making a macro to do the necessary ``decltype( &function_name, ), function_name``. Sol does not provide one because many codebases already have `one similar to this`_. + +Here's an example below of various ways to use ``sol::c_call``: + +.. code-block:: cpp + :linenos: + :caption: Compile-time transported function calls + + #include "sol.hpp" + + int f1(int) { return 32; } + int f2(int, int) { return 1; } + struct fer { + double f3(int, int) { + return 2.5; + } + }; + + + int main() { + + sol::state lua; + // overloaded function f + lua.set("f", sol::c_call, sol::wrap, sol::wrap>); + // singly-wrapped function + lua.set("g", sol::c_call>); + // without the 'sol::wrap' boilerplate + lua.set("h", sol::c_call); + // object used for the 'fer' member function call + lua.set("obj", fer()); + + // call them like any other bound function + lua.script("r1 = f(1)"); + lua.script("r2 = f(1, 2)"); + lua.script("r3 = f(obj, 1, 2)"); + lua.script("r4 = g(1)"); + lua.script("r5 = h(1, 2)"); + + // get the results and see + // if it worked out + int r1 = lua["r1"]; + // r1 == 32 + int r2 = lua["r2"]; + // r2 == 1 + double r3 = lua["r3"]; + // r3 == 2.5 + int r4 = lua["r4"]; + // r4 == 32 + int r5 = lua["r5"]; + // r5 == 1 + + return 0; + } + + +.. _one similar to this: http://stackoverflow.com/a/5628222/5280922 diff --git a/3rdparty/sol2/docs/source/api/compatibility.rst b/3rdparty/sol2/docs/source/api/compatibility.rst new file mode 100644 index 00000000000..3299bff931b --- /dev/null +++ b/3rdparty/sol2/docs/source/api/compatibility.rst @@ -0,0 +1,16 @@ +compatibility.hpp +================= +Lua 5.3/5.2 compatibility for Lua 5.1/LuaJIT +-------------------------------------------- + +This is a detail header used to maintain compatability with the 5.2 and 5.3 APIs. It contains code from the MIT-Licensed `Lua code`_ in some places and also from the `lua-compat`_ repository by KeplerProject. + +It is not fully documented as this header's only purpose is for internal use to make sure Sol compiles across all platforms / distributions with no errors or missing Lua functionality. If you think there's some compatibility features we are missing or if you are running into redefinition errors, please make an `issue in the issue tracker`_. + +If you have this already in your project or you have your own compatibility layer, then please ``#define SOL_NO_COMPAT 1`` before including ``sol.hpp`` or pass this flag on the command line to turn off the compatibility wrapper. + +For the licenses, see :doc:`here<../licenses>` + +.. _issue in the issue tracker: https://github.com/ThePhD/sol2/issues/ +.. _Lua code: http://www.Lua.org/ +.. _lua-compat: https://github.com/keplerproject/lua-compat-5.3 \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/coroutine.rst b/3rdparty/sol2/docs/source/api/coroutine.rst new file mode 100644 index 00000000000..3d03da31f5c --- /dev/null +++ b/3rdparty/sol2/docs/source/api/coroutine.rst @@ -0,0 +1,109 @@ +coroutine +========= +resumable/yielding functions from Lua +------------------------------------- + +A ``coroutine`` is a :doc:`reference` to a function in Lua that can be called multiple times to yield a specific result. It is run on the :doc:`lua_State` that was used to create it (see :doc:`thread` for an example on how to get a coroutine that runs on a thread separate from your usual "main" :doc:`lua_State`). + +The ``coroutine`` object is entirely similar to the :doc:`protected_function` object, with additional member functions to check if a coroutine has yielded (:doc:`call_status::yielded`) and is thus runnable again, whether it has completed (:ref:`call_status::ok`) and thus cannot yield anymore values, or whether it has suffered an error (see :ref:`status()` and :ref:`call_status`'s error codes). + +For example, you can work with a coroutine like this: + +.. code-block:: lua + :caption: co.lua + + function loop() + while counter ~= 30 + do + coroutine.yield(counter); + counter = counter + 1; + end + return counter + end + +This is a function that yields: + +.. code-block:: cpp + :caption: main.cpp + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::coroutine); + lua.script_file("co.lua"); + sol::coroutine cr = lua["loop"]; + + for (int counter = 0; // start from 0 + counter < 10 && cr; // we want 10 values, and we only want to run if the coroutine "cr" is valid + // Alternative: counter < 10 && cr.valid() + ++counter) { + // Call the coroutine, does the computation and then suspends + int value = cr(); + } + +Note that this code doesn't check for errors: to do so, you can call the function and assign it as ``auto result = cr();``, then check ``result.valid()`` as is the case with :doc:`protected_function`. Finally, you can run this coroutine on another thread by doing the following: + +.. code-block:: cpp + :caption: main_with_thread.cpp + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::coroutine); + lua.script_file("co.lua"); + sol::thread runner = sol::thread::create(lua.lua_state()); + sol::state_view runnerstate = runner.state(); + sol::coroutine cr = runnerstate["loop"]; + + for (int counter = 0; counter < 10 && cr; ++counter) { + // Call the coroutine, does the computation and then suspends + int value = cr(); + } + +The following are the members of ``sol::coroutine``: + +members +------- + +.. code-block:: cpp + :caption: function: constructor + + coroutine(lua_State* L, int index = -1); + +Grabs the coroutine at the specified index given a ``lua_State*``. + +.. code-block:: cpp + :caption: returning the coroutine's status + :name: status + + call_status status() const noexcept; + +Returns the status of a coroutine. + + +.. code-block:: cpp + :caption: checks for an error + + bool error() const noexcept; + +Checks if an error occured when the coroutine was run. + +.. _runnable: + +.. code-block:: cpp + :caption: runnable and explicit operator bool + + bool runnable () const noexcept; + explicit operator bool() const noexcept; + +These functions allow you to check if a coroutine can still be called (has more values to yield and has not errored). If you have a coroutine object ``coroutine my_co = /*...*/``, you can either check ``runnable()`` or do ``if ( my_co ) { /* use coroutine */ }``. + +.. code-block:: cpp + :caption: calling a coroutine + + template + protected_function_result operator()( Args&&... args ); + + template + decltype(auto) call( Args&&... args ); + + template + decltype(auto) operator()( types, Args&&... args ); + +Calls the coroutine. The second ``operator()`` lets you specify the templated return types using the ``my_co(sol::types, ...)`` syntax. Check ``status()`` afterwards for more information about the success of the run or just check the coroutine object in an ifs tatement, as shown :ref:`above`. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/error.rst b/3rdparty/sol2/docs/source/api/error.rst new file mode 100644 index 00000000000..4bfe21e91a4 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/error.rst @@ -0,0 +1,15 @@ +error +===== +the single error/exception type +------------------------------- + +.. code-block:: cpp + + class error : public std::runtime_error { + public: + error(const std::string& str): std::runtime_error("Lua: error: " + str) {} + }; + +If an eror is thrown by Sol, it is going to be of this type. We use this in a single place: the default ``at_panic`` function we bind on construction of a :ref:`sol::state`. If you turn :doc:`off exceptions<../exceptions>`, the chances of you seeing this error are nil unless you specifically use it to pull errors out of things such as :doc:`sol::protected_function`. + +As it derives from ``std::runtime_error``, which derives from ``std::exception``, you can catch it with a ``catch (const std::exception& )`` clause in your try/catch blocks. You can retrieve a string error from Lua (Lua pushes all its errors as string returns) by using this type with any of the get or lookup functions in Sol. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/function.rst b/3rdparty/sol2/docs/source/api/function.rst new file mode 100644 index 00000000000..27946117a8c --- /dev/null +++ b/3rdparty/sol2/docs/source/api/function.rst @@ -0,0 +1,89 @@ +function +======== +calling functions bound to Lua +------------------------------ + +.. code-block:: cpp + + class function : public reference; + +Function is a correct-assuming version of :doc:`protected_function`, omitting the need for typechecks and error handling. It is the default function type of Sol. Grab a function directly off the stack using the constructor: + +.. code-block:: cpp + :caption: constructor: function + + function(lua_State* L, int index = -1); + + +When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :ref:`function_result` class that gets implicitly converted to the requested return type. For example: + +.. code-block:: lua + :caption: func_barks.lua + :linenos: + + bark_power = 11; + + function woof ( bark_energy ) + return (bark_energy * (bark_power / 4)) + end + +The following C++ code will call this function from this file and retrieve the return value: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.script_file( "func_barks.lua" ); + + sol::function woof = lua["woof"]; + double numwoof = woof(20); + +The call ``woof(20)`` generates a :ref:`function_result`, which is then implicitly converted to an ``double`` after being called. The intermediate temporary ``function_result`` is then destructed, popping the Lua function call results off the Lua stack. + +You can also return multiple values by using ``std::tuple``, or if you need to bind them to pre-existing variables use ``sol::tie``: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.script( "function f () return 10, 11, 12 end" ); + + sol::function f = lua["f"]; + std::tuple abc = f(); // 10, 11, 12 from Lua + // or + int a, b, c; + sol::tie(a, b, c) = f(); // a = 10, b = 11, c = 12 from Lua + +This makes it much easier to work with multiple return values. Using ``std::tie`` from the C++ standard will result in dangling references or bad behavior because of the very poor way in which C++ tuples/``std::tie`` were specified and implemented: please use ``sol::tie( ... )`` instead to satisfy any multi-return needs. + +.. _function-result-warning: + +.. warning:: + + Do NOT save the return type of a :ref:`function_result` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. Unlike its counterpart :ref:`protected_function_result`, ``function_result`` is NOT safe to store as it assumes that its return types are still at the top of the stack and when its destructor is called will pop the number of results the function was supposed to return off the top of the stack. If you mess with the Lua stack between saving ``function_result`` and it being destructed, you will be subject to an incredible number of surprising and hard-to-track bugs. Don't do it. + +.. code-block:: cpp + :caption: function: call operator / function call + + template + protected_function_result operator()( Args&&... args ); + + template + decltype(auto) call( Args&&... args ); + + template + decltype(auto) operator()( types, Args&&... args ); + +Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types, ...)`` syntax. Function assumes there are no runtime errors, and thusly will call the ``atpanic`` function if an error does occur. + +.. note:: + + All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state` or :doc:`sol::table`, value semantics are not used here. It is forwarding reference semantics, which do not copy/move unless it is specifically done by the receiving functions / specifically done by the user. + + +function call safety +-------------------- + +You can have functions here and on usertypes check to definitely make sure that the types passed to C++ functions are what they're supposed to be by adding a ``#define SOL_CHECK_ARGUMENTS`` before including Sol, or passing it on the command line. Otherwise, for speed reasons, these checks are only used where absolutely necessary (like discriminating between :doc:`overloads`). See :doc:`safety<../safety>` for more information. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/make_reference.rst b/3rdparty/sol2/docs/source/api/make_reference.rst new file mode 100644 index 00000000000..cd39b5a31d9 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/make_reference.rst @@ -0,0 +1,26 @@ +make_object/make_reference +========================== +Create a value on the Lua stack and return it +--------------------------------------------- + +.. code-block:: cpp + :caption: function: make_reference + :name: make-reference + + template + R make_reference(lua_State* L, T&& value); + template + R make_reference(lua_State* L, Args&&... args); + +Makes an ``R`` out of the value. The first overload deduces the type from the passed in argument, the second allows you to specify a template parameter and forward any relevant arguments to ``sol::stack::push``. The type figured out for ``R`` is what is referenced from the stack. This allows you to request arbitrary pop-able types from Sol and have it constructed from ``R(lua_State* L, int stack_index)``. If the template boolean ``should_pop`` is ``true``, the value that was pushed will be popped off the stack. It defaults to popping, but if it encounters a type such as :doc:`sol::stack_reference` (or any of its typically derived types in Sol), it will leave the pushed values on the stack. + +.. code-block:: cpp + :caption: function: make_object + :name: make-object + + template + object make_object(lua_State* L, T&& value); + template + object make_object(lua_State* L, Args&&... args); + +Makes an object out of the value. It pushes it onto the stack, then pops it into the returned ``sol::object``. The first overload deduces the type from the passed in argument, the second allows you to specify a template parameter and forward any relevant arguments to ``sol::stack::push``. The implementation essentially defers to :ref:`sol::make_reference` with the specified arguments, ``R == object`` and ``should_pop == true``. It is preferred that one uses the :ref:`in_place object constructor instead`, since it's probably easier to deal with, but both versions will be supported for forever, since there's really no reason not to and people already have dependencies on ``sol::make_object``. diff --git a/3rdparty/sol2/docs/source/api/metatable_key.rst b/3rdparty/sol2/docs/source/api/metatable_key.rst new file mode 100644 index 00000000000..718eb2b2ffc --- /dev/null +++ b/3rdparty/sol2/docs/source/api/metatable_key.rst @@ -0,0 +1,154 @@ +metatable_key +============= +A key for setting and getting an object's metatable +--------------------------------------------------- + +.. code-block:: cpp + + struct metatable_key_t {}; + const metatable_key_t metatable_key; + +You can use this in conjunction with :doc:`sol::table
` to set/get a metatable. Lua metatables are powerful ways to override default behavior of objects for various kinds of operators, among other things. Here is an entirely complete example, showing getting and working with a :doc:`usertype`'s metatable defined by Sol: + +.. code-block:: cpp + :caption: messing with metatables + :linenos: + + #include + + int main () { + + struct bark { + int operator()(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("bark", + sol::meta_function::call_function, &bark::operator() + ); + + bark b; + lua.set("b", &b); + + sol::table b_as_table = lua["b"]; + sol::table b_metatable = b_as_table[sol::metatable_key]; + sol::function b_call = b_metatable["__call"]; + sol::function b_as_function = lua["b"]; + + int result1 = b_as_function(1); + int result2 = b_call(b, 1); + // result1 == result2 == 1 + } + +It's further possible to have a "Dynamic Getter" (`thanks to billw2012 and Nava2 for this example`_!): + +.. code-block:: cpp + :caption: One way to make dynamic properties (there are others!) + :linenos: + + #include + #include + + struct PropertySet { + sol::object get_property_lua(const char* name, sol::this_state s) + { + auto& var = props[name]; + return sol::make_object(s, var); + } + + void set_property_lua(const char* name, sol::stack_object object) + { + props[name] = object.as(); + } + + std::unordered_map props; + }; + + struct DynamicObject { + PropertySet& get_dynamic_props() { + return dynamic_props; + } + + PropertySet dynamic_props; + }; + + + int main () { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("PropertySet", + sol::meta_function::new_index, &PropertySet::set_property_lua, + sol::meta_function::index, &PropertySet::get_property_lua + ); + + lua.new_usertype("DynamicObject", + "props", sol::property(&DynamicObject::get_dynamic_props) + ); + + lua.script(R"( + obj = DynamicObject:new() + obj.props.name = 'test name' + print('name = ' .. obj.props.name) + )"); + + std::string name = lua["obj"]["props"]["name"]; + // name == "test name"; + } + + +You can even manipulate the ability to set and get items using metatable objects on a usertype or similar: + +.. code-block:: cpp + :caption: messing with metatables - vector type + :linenos: + + #include + + class vector { + public: + double data[3]; + + vector() : data{ 0,0,0 } {} + + double& operator[](int i) + { + return data[i]; + } + + + static double my_index(vector& v, int i) + { + return v[i]; + } + + static void my_new_index(vector& v, int i, double x) + { + v[i] = x; + } + }; + + int main () { + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("vector", sol::constructors>(), + sol::meta_function::index, &vector::my_index, + sol::meta_function::new_index, &vector::my_new_index); + lua.script("v = vector.new()\n" + "print(v[1])\n" + "v[2] = 3\n" + "print(v[2])\n" + ); + + vector& v = lua["v"]; + // v[0] == 0.0; + // v[1] == 0.0; + // v[2] == 3.0; + } + + +.. _thanks to billw2012 and Nava2 for this example: https://github.com/ThePhD/sol2/issues/71#issuecomment-225402055 \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/object.rst b/3rdparty/sol2/docs/source/api/object.rst new file mode 100644 index 00000000000..f38f089cc4d --- /dev/null +++ b/3rdparty/sol2/docs/source/api/object.rst @@ -0,0 +1,70 @@ +object +====== +general-purpose safety reference to an existing object +------------------------------------------------------ + +.. code-block:: cpp + + class object : reference; + + +``object``'s goal is to allow someone to pass around the most generic form of a reference to something in Lua (or propogate a ``nil``). It is the logical extension of :doc:`sol::reference`, and is used in :ref:`sol::table's iterators`. + + +members +------- + +.. code-block:: cpp + :caption: overloaded constructor: object + :name: overloaded-object-constructor + + template + object(T&&); + object(lua_State* L, int index = -1); + template + object(lua_State* L, in_place_t, T&& arg, Args&&... args); + template + object(lua_State* L, in_place_type_t, Args&&... args); + +There are 4 kinds of constructors here. One allows construction of an object from other reference types such as :doc:`sol::table
` and :doc:`sol::stack_reference`. The second creates an object which references the specific element at the given index in the specified ``lua_State*``. The more advanced ``in_place...`` constructors create a single object by pushing the specified type ``T`` onto the stack and then setting it as the object. It gets popped from the stack afterwards (unless this is an instance of ``sol::stack_object``, in which case it is left on the stack). An example of using this and :doc:`sol::make_object` can be found in the `any_return example`_. + +.. code-block:: cpp + :caption: function: type conversion + + template + decltype(auto) as() const; + +Performs a cast of the item this reference refers to into the type ``T`` and returns it. It obeys the same rules as :ref:`sol::stack::get\`. + +.. code-block:: cpp + :caption: function: type check + + template + bool is() const; + +Performs a type check using the :ref:`sol::stack::check` api, after checking if the reference is valid. + + +non-members +----------- + +.. code-block:: cpp + :caption: functions: nil comparators + + bool operator==(const object& lhs, const nil_t&); + bool operator==(const nil_t&, const object& rhs); + bool operator!=(const object& lhs, const nil_t&); + bool operator!=(const nil_t&, const object& rhs); + +These allow a person to compare an ``sol::object`` against :ref:`nil`, which essentially checks if an object references a non-nil value, like so: + +.. code-block:: cpp + + if (myobj == sol::nil) { + // doesn't have anything... + } + +Use this to check objects. + + +.. _any_return example: https://github.com/ThePhD/sol2/blob/develop/examples/any_return.cpp \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/optional.rst b/3rdparty/sol2/docs/source/api/optional.rst new file mode 100644 index 00000000000..f999849bcd9 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/optional.rst @@ -0,0 +1,6 @@ +optional +=========== + +This is an implemention of `optional from the standard library`_. If it detects that a proper optional exists, it will attempt to use it. This is mostly an implementation detail, used in the :ref:`sol::stack::check_get` and :ref:`sol::stack::get\>` and ``optional maybe_value = table["arf"];`` implementations for additional safety reasons. + +.. _optional from the standard library: http://en.cppreference.com/w/cpp/utility/optional \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/overload.rst b/3rdparty/sol2/docs/source/api/overload.rst new file mode 100644 index 00000000000..399b409d1af --- /dev/null +++ b/3rdparty/sol2/docs/source/api/overload.rst @@ -0,0 +1,89 @@ +overload +======== +calling different functions based on argument number/type +--------------------------------------------------------- + +this function helps users make overloaded functions that can be called from Lua using 1 name but multiple arguments. It is meant to replace the spaghetti of code whre users mock this up by doing strange if statemetns and switches on what version of a function to call based on `luaL_check{number/udata/string}`_. Its use is simple: whereever you can pass a function type to Lua, whether its on a :doc:`usertype` or if you are just setting any kind of function with ``set`` or ``set_function`` (for :doc:`table
` or :doc:`state(_view)`), simply wrap up the functions you wish to be considered for overload resolution on one function like so: + +.. code-block:: cpp + + sol::overload( func1, func2, ... funcN ); + + +The functions can be any kind of function / function object (lambda). Given these functions and struct: + +.. code-block:: cpp + :linenos: + + struct pup { + int barks = 0; + + void bark () { + ++barks; // bark! + } + + bool is_cute () const { + return true; + } + }; + + void ultra_bark( pup& p, int barks) { + for (; barks --> 0;) p.bark(); + } + + void picky_bark( pup& p, std::string s) { + if ( s == "bark" ) + p.bark(); + } + +You then use it just like you would for any other part of the api: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.set_function( "bark", sol::overload( + ultra_bark, + []() { return "the bark from nowhere"; } + ) ); + + lua.new_usertype( "pup", + // regular function + "is_cute", &pup::is_cute, + // overloaded function + "bark", sol::overload( &pup::bark, &picky_bark ) + ); + +Thusly, doing the following in Lua: + +.. code-block:: Lua + :caption: pup.lua + :linenos: + + local barker = pup.new() + pup:bark() -- calls member function pup::bark + pup:bark(20) -- calls ultra_bark + pup:bark("meow") -- picky_bark, no bark + pup:bark("bark") -- picky_bark, bark + + bark(pup, 20) -- calls ultra_bark + local nowherebark = bark() -- calls lambda which returns that string + +The actual class produced by ``sol::overload`` is essentially a type-wrapper around ``std::tuple`` that signals to the library that an overload is being created: + +.. code-block:: cpp + :caption: function: create overloaded set + :linenos: + + template + struct overloaded_set : std::tuple { /* ... */ }; + + template + overloaded_set overload( Args&&... args ); + +.. note:: + + Please keep in mind that doing this bears a runtime cost to find the proper overload. The cost scales directly not exactly with the number of overloads, but the number of functions that have the same argument count as each other (Sol will early-eliminate any functions that do not match the argument count). + +.. _luaL_check{number/udata/string}: http://www.Lua.org/manual/5.3/manual.html#luaL_checkinteger diff --git a/3rdparty/sol2/docs/source/api/property.rst b/3rdparty/sol2/docs/source/api/property.rst new file mode 100644 index 00000000000..e3ee02e2353 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/property.rst @@ -0,0 +1,64 @@ +property +======== + +.. code-block:: cpp + + template + decltype(auto) property ( Read&& read_function, Write&& write_function ); + template + decltype(auto) property ( Read&& read_function ); + template + decltype(auto) property ( Write&& write_function ); + +These set of functions create a type which allows a setter and getter pair (or a single getter, or a single setter) to be used to create a variable that is either read-write, read-only, or write-only. When used during :doc:`usertype` construction, it will create a variable that uses the setter/getter member function specified. + +.. code-block:: cpp + :caption: player.hpp + :linenos: + + class Player { + public: + int get_hp() const { + return hp; + } + + void set_hp( int value ) { + hp = value; + } + + int get_max_hp() const { + return hp; + } + + void set_max_hp( int value ) { + maxhp = value; + } + + private: + int hp = 50; + int maxHp = 50; + } + +.. code-block:: cpp + :caption: game.cpp + :linenos: + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set("theplayer", Player()); + + // Yes, you can register after you set a value and it will + // connect up the usertype automatically + lua.new_usertype( "Player", + "hp", sol::property(&Player::get_hp, &Player::set_hp), + "maxHp", sol::property(&Player::get_max_hp, &Player::set_max_hp) + ); + + +.. code-block:: lua + :caption: game-snippet.lua + + -- variable syntax, calls functions + theplayer.hp = 20 + print(theplayer.hp) \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/protect.rst b/3rdparty/sol2/docs/source/api/protect.rst new file mode 100644 index 00000000000..4f14cb0db2a --- /dev/null +++ b/3rdparty/sol2/docs/source/api/protect.rst @@ -0,0 +1,33 @@ +protect +======= +Routine to mark a function / variable as requiring safety +--------------------------------------------------------- + +.. code-block:: cpp + + template + auto protect( T&& value ); + +``sol::protect( my_func )`` allows you to protect a function call or member variable call when it is being set to Lua. It can be used with usertypes or when just setting a function into Sol. Below is an example that demonstrates that a call that would normally not error without :doc:`Safety features turned on<../safety>` that instead errors and makes the Lua safety-call wrapper ``pcall`` fail: + +.. code-block:: cpp + + struct protect_me { + int gen(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("protect_me", + "gen", sol::protect( &protect_me::gen ) + ); + + lua.script(R"__( + pm = protect_me.new() + value = pcall(pm.gen,pm) + )__"); + ); + bool value = lua["value"]; + // value == false diff --git a/3rdparty/sol2/docs/source/api/protected_function.rst b/3rdparty/sol2/docs/source/api/protected_function.rst new file mode 100644 index 00000000000..97d4e09f14f --- /dev/null +++ b/3rdparty/sol2/docs/source/api/protected_function.rst @@ -0,0 +1,185 @@ +protected_function +================== +Lua function calls that trap errors and provide error handling +-------------------------------------------------------------- + +.. code-block:: cpp + + class protected_function : public reference; + +Inspired by a request from `starwing` in the old repository, this class provides the same interface as :doc:`function` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. You can grab a function directly off the stack using the constructor, or pass to it 2 valid functions, which we'll demonstrate a little later. + +When called without the return types being specified by either a ``sol::types<...>`` list or a ``call( ... )`` template type list, it generates a :doc:`protected_function_result` class that gets implicitly converted to the requested return type. For example: + +.. code-block:: lua + :caption: pfunc_barks.lua + :linenos: + + bark_power = 11; + + function got_problems( error_msg ) + return "got_problems handler: " .. error_msg + end + + function woof ( bark_energy ) + if bark_energy < 20 + error("*whine*") + end + return (bark_energy * (bark_power / 4)) + end + + function woofers ( bark_energy ) + if bark_energy < 10 + error("*whine*") + end + return (bark_energy * (bark_power / 4)) + end + +The following C++ code will call this function from this file and retrieve the return value, unless an error occurs, in which case you can bind an error handling function like so: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.open_file( "pfunc_barks.lua" ); + + sol::protected_function problematicwoof = lua["woof"]; + problematicwoof.error_handler = lua["got_problems"]; + + auto firstwoof = problematic_woof(20); + if ( firstwoof.valid() ) { + // Can work with contents + double numwoof = first_woof; + } + else{ + // An error has occured + sol::error err = first_woof; + } + + // errors, calls handler and then returns a string error from Lua at the top of the stack + auto secondwoof = problematic_woof(19); + if (secondwoof.valid()) { + // Call succeeded + double numwoof = secondwoof; + } + else { + // Call failed + // Note that if the handler was successfully called, this will include + // the additional appended error message information of + // "got_problems handler: " ... + sol::error err = secondwoof; + std::string what = err.what(); + } + +This code is much more long-winded than its :doc:`function` counterpart but allows a person to check for errors. The type here for ``auto`` are ``sol::protected_function_result``. They are implicitly convertible to result types, like all :doc:`proxy-style` types are. + +Alternatively, with a bad or good function call, you can use ``sol::optional`` to check if the call succeeded or failed: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.open_file( "pfunc_barks.lua" ); + + sol::protected_function problematicwoof = lua["woof"]; + problematicwoof.error_handler = lua["got_problems"]; + + sol::optional maybevalue = problematicwoof(19); + if (maybevalue) { + // Have a value, use it + double numwoof = maybevalue.value(); + } + else { + // No value! + } + +That makes the code a bit more concise and easy to reason about if you don't want to bother with reading the error. Thankfully, unlike ``sol::function_result``, you can save ``sol::protected_function_result`` in a variable and push/pop things above it on the stack where its returned values are. This makes it a bit more flexible than the rigid, performant ``sol::function_result`` type that comes from calling :doc:`sol::function`. + +If you're confident the result succeeded, you can also just put the type you want (like ``double`` or ``std::string`` right there and it will get it. But, if it doesn't work out, sol can throw and/or panic if you have the :doc:`safety<../safety>` features turned on: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.open_file( "pfunc_barks.lua" ); + + // construct with function + error handler + // shorter than old syntax + sol::protected_function problematicwoof(lua["woof"], lua["got_problems"]); + + // dangerous if things go wrong! + double value = problematicwoof(19); + + +Finally, it is *important* to note you can set a default handler. The function is described below: please use it to avoid having to constantly set error handlers: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.open_file( "pfunc_barks.lua" ); + // sets got_problems as the default + // handler for all protected_function errors + sol::protected_function::set_default_handler(lua["got_problems"]); + + sol::protected_function problematicwoof = lua["woof"]; + sol::protected_function problematicwoofers = lua["woofers"]; + + double value = problematicwoof(19); + double value2 = problematicwoof(9); + + +members +------- + +.. code-block:: cpp + :caption: constructor: protected_function + + template + protected_function( T&& func, reference handler = sol::protected_function::get_default_handler() ); + protected_function( lua_State* L, int index = -1, reference handler = sol::protected_function::get_default_handler() ); + +Constructs a ``protected_function``. Use the 2-argument version to pass a custom error handling function more easily. You can also set the :ref:`member variable error_handler` after construction later. ``protected_function`` will always use the latest error handler set on the variable, which is either what you passed to it or the default *at the time of construction*. + +.. code-block:: cpp + :caption: function: call operator / protected function call + + template + protected_function_result operator()( Args&&... args ); + + template + decltype(auto) call( Args&&... args ); + + template + decltype(auto) operator()( types, Args&&... args ); + +Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types, ...)`` syntax. If you specify no return type in any way, it produces s ``protected_function_result``. + +.. note:: + + All arguments are forwarded. Unlike :doc:`get/set/operator[] on sol::state` or :doc:`sol::table
`, value semantics are not used here. It is forwarding reference semantics, which do not copy/move unless it is specifically done by the receiving functions / specifically done by the user. + + +.. code-block:: cpp + :caption: default handlers + + static const reference& get_default_handler (); + static void set_default_handler( reference& ref ); + +Get and set the Lua entity that is used as the default error handler. The default is a no-ref error handler. You can change that by calling ``protected_function::set_default_handler( lua["my_handler"] );`` or similar: anything that produces a reference should be fine. + +.. code-block:: cpp + :caption: variable: handler + :name: protected-function-error-handler + + reference error_handler; + +The error-handler that is called should a runtime error that Lua can detect occurs. The error handler function needs to take a single string argument (use type std::string if you want to use a C++ function bound to lua as the error handler) and return a single string argument (again, return a std::string or string-alike argument from the C++ function if you're using one as the error handler). If :doc:`exceptions<../exceptions>` are enabled, Sol will attempt to convert the ``.what()`` argument of the exception into a string and then call the error handling function. It is a :doc:`reference`, as it must refer to something that exists in the lua registry or on the Lua stack. This is automatically set to the default error handler when ``protected_function`` is constructed. + +.. note:: + + ``protected_function_result`` safely pops its values off the stack when its destructor is called, keeping track of the index and number of arguments that were supposed to be returned. If you remove items below it using ``lua_remove``, for example, it will not behave as expected. Please do not perform fundamentally stack-rearranging operations until the destructor is called (pushing/popping above it is just fine). diff --git a/3rdparty/sol2/docs/source/api/proxy.rst b/3rdparty/sol2/docs/source/api/proxy.rst new file mode 100644 index 00000000000..897dbbaf7dd --- /dev/null +++ b/3rdparty/sol2/docs/source/api/proxy.rst @@ -0,0 +1,201 @@ +proxy, (protected\_)function_result - proxy_base derivatives +============================================================ +``table[x]`` and ``function(...)`` conversion struct +---------------------------------------------------- + +.. code-block:: c++ + + template + struct proxy_base; + + template + struct proxy : proxy_base<...>; + + struct stack_proxy: proxy_base<...>; + + struct function_result : proxy_base<...>; + + struct protected_function_result: proxy_base<...>; + + +These classes provide implicit assignment operator ``operator=`` (for ``set``) and an implicit conversion operator ``operator T`` (for ``get``) to support items retrieved from the underlying Lua implementation, specifically :doc:`sol::table
` and the results of function calls on :doc:`sol::function` and :doc:`sol::protected_function`. + +.. _proxy: + +proxy +----- + +``proxy`` is returned by lookups into :doc:`sol::table
` and table-like entities. Because it is templated on key and table type, it would be hard to spell: you can capture it using the word ``auto`` if you feel like you need to carry it around for some reason before using it. ``proxy`` evaluates its arguments lazily, when you finally call ``get`` or ``set`` on it. Here are some examples given the following lua script. + +.. code-block:: lua + :linenos: + :caption: lua nested table script + + bark = { + woof = { + [2] = "arf!" + } + } + + +After loading that file in or putting it in a string and reading the string directly in lua (see :doc:`state`), you can start kicking around with it in C++ like so: + +.. code-block:: c++ + :linenos: + + sol::state lua; + + // produces proxy, implicitly converts to std::string, quietly destroys proxy + std::string x = lua["bark"]["woof"][2]; + + +``proxy`` lazy evaluation: + +.. code-block:: c++ + :linenos: + :caption: multi-get + + auto x = lua["bark"]; + auto y = x["woof"]; + auto z = x[2]; + // retrivies value inside of lua table above + std::string value = z; // "arf!" + // Can change the value later... + z = 20; + // Yay, lazy-evaluation! + int changed_value = z; // now it's 20! + + +We don't recommend the above to be used across classes or between function: it's more of something you can do to save a reference to a value you like, call a script or run a lua function, and then get it afterwards. You can also set functions (and function objects :ref:`*`) this way, and retrieve them as well. + +.. code-block:: c++ + :linenos: + + lua["bark_value"] = 24; + lua["chase_tail"] = floof::chase_tail; // chase_tail is a free function + + +members +------- + +.. code-block:: c++ + :caption: functions: [overloaded] implicit conversion get + :name: implicit-get + + requires( sol::is_primitive_type::value == true ) + template + operator T() const; + + requires( sol::is_primitive_type::value == false ) + template + operator T&() const; + +Gets the value associated with the keys the proxy was generated and convers it to the type ``T``. Note that this function will always return ``T&``, a non-const reference, to types which are not based on :doc:`sol::reference` and not a :doc:`primitive lua type` + +.. code-block:: c++ + :caption: function: get a value + :name: regular-get + + template + decltype(auto) get( ) const; + +Gets the value associated with the keys and converts it to the type ``T``. + +.. code-block:: c++ + :caption: function: optionally get a value + :name: regular-get-or + + template + optional get_or( Otherwise&& otherise ) const; + +Gets the value associated with the keys and converts it to the type ``T``. If it is not of the proper type, it will return a ``sol::nullopt`` instead. + +``operator[]`` proxy-only members +--------------------------------- + +.. code-block:: c++ + :caption: function: valid + :name: proxy-valid + + bool valid () const; + +Returns whether this proxy actually refers to a valid object. It uses :ref:`sol::stack::probe_get_field` to determine whether or not its valid. + +.. code-block:: c++ + :caption: functions: [overloaded] implicit set + :name: implicit-set + + requires( sol::detail::Function == false ) + template + proxy& operator=( T&& value ); + + requires( sol::detail::Function == true ) + template + proxy& operator=( Fx&& function ); + +Sets the value associated with the keys the proxy was generated with to ``value``. If this is a function, calls ``set_function``. If it is not, just calls ``set``. Does not exist on :ref:`function_result` or :ref:`protected_function_result`. See :ref:`note` for caveats. + +.. code-block:: c++ + :caption: function: set a callable + :name: regular-set-function + + template + proxy& set_function( Fx&& fx ); + +Sets the value associated with the keys the proxy was generated with to a function ``fx``. Does not exist on :ref:`function_result` or :ref:`protected_function_result`. + + +.. code-block:: c++ + :caption: function: set a value + :name: regular-set + + template + proxy& set( T&& value ); + +Sets the value associated with the keys the proxy was generated with to ``value``. Does not exist on :ref:`function_result` or :ref:`protected_function_result`. + +stack_proxy +----------- + +``sol::stack_proxy`` is what gets returned by :doc:`sol::variadic_args` and other parts of the framework. It is similar to proxy, but is meant to alias a stack index and not a named variable. + +.. _function-result: + +function_result +--------------- + +``function_result`` is a temporary-only, intermediate-only implicit conversion worker for when :doc:`function` is called. It is *NOT* meant to be stored or captured with ``auto``. It provides fast access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=``, as is present on :ref:`proxy`. + + +.. _protected-function-result: + +protected_function_result +------------------------- + +``protected_function_result`` is a nicer version of ``function_result`` that can be used to detect errors. Its gives safe access to the desired underlying value. It does not implement ``set`` / ``set_function`` / templated ``operator=`` as is present on :ref:`proxy`. + + +.. _note 1: + +on function objects and proxies +------------------------------- + +Consider the following: + +.. code-block:: cpp + :linenos: + :caption: Note 1 Case + + struct doge { + int bark; + + void operator()() { + bark += 1; + } + }; + + sol::state lua; + lua["object"] = doge{}; // bind constructed doge to "object" + // but it binds as a function + +When you use the ``lua["object"] = doge{};`` from above, keep in mind that Sol detects if this is a function *callable with any kind of arguments*. Since ``doge`` has overriden ``return_type operator()( argument_types... )`` on itself, it results in satisfying the ``requires`` constraint from above. This means that if you have a user-defined type you want to bind as a :doc:`userdata with usertype semantics` with this syntax, it might get bound as a function and not as a user-defined type (d'oh!). use ``lua["object"].set(doge)`` directly to avoid this, or ``lua["object"].set_function(doge{})`` to perform this explicitly. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/readonly.rst b/3rdparty/sol2/docs/source/api/readonly.rst new file mode 100644 index 00000000000..3a9517f1058 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/readonly.rst @@ -0,0 +1,11 @@ +readonly +======== +Routine to mark a member variable as read-only +---------------------------------------------- + +.. code-block:: cpp + + template + auto readonly( T&& value ); + +The goal of read-only is to protect a variable set on a usertype or a function. Simply wrap it around a member variable, e.g. ``sol::readonly( &my_class::my_member_variable )`` in the appropriate place to use it. If someone tries to set it, it will throw an error. diff --git a/3rdparty/sol2/docs/source/api/reference.rst b/3rdparty/sol2/docs/source/api/reference.rst new file mode 100644 index 00000000000..37886dc2300 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/reference.rst @@ -0,0 +1,75 @@ +reference +========= +general purpose reference to Lua object in registry +--------------------------------------------------- + +.. code-block:: cpp + :caption: reference + + class reference; + +This type keeps around a reference to something that was on the stack and places it in the Lua registry. It is the backbone for all things that reference items on the stack and needs to keep them around beyond their appearance and lifetime on said Lua stack. Its progeny include :doc:`sol::coroutine`, :doc:`sol::function`, :doc:`sol::protected_function`, :doc:`sol::object`, :doc:`sol::table
`/:doc:`sol::global_table
`, :doc:`sol::thread`, and :doc:`sol::userdata`. + +For all of these types, there's also a ``stack_{x}`` version of them, such as ``stack_table`` + + +members +------- + +.. code-block:: cpp + :caption: constructor: reference + + reference(lua_State* L, int index = -1); + +Creates a reference from the Lua stack at the specified index, saving it into the metatable registry. This constructor is exposed on all types that derive from ``sol::reference``. + +.. code-block:: cpp + :caption: function: push referred-to element from the stack + + int push() const noexcept; + +This function pushes the referred-to data onto the stack and returns how many things were pushed. Typically, it returns 1. + +.. code-block:: cpp + :caption: function: reference value + + int registry_index() const noexcept; + +The value of the reference in the registry. + +.. code-block:: cpp + :caption: functions: non-nil, non-null check + + bool valid () const noexcept; + explicit operator bool () const noexcept; + +These functions check if the reference at ``T`` is valid: that is, if it is not :ref:`nil` and if it is not non-existing (doesn't refer to anything, including nil) reference. The explicit operator bool allows you to use it in the context of an ``if ( my_obj )`` context. + +.. code-block:: cpp + :caption: function: retrieves the type + + type get_type() const noexcept; + +Gets the :doc:`sol::type` of the reference; that is, the Lua reference. + +.. code-block:: cpp + :caption: function: lua_State* of the reference + + lua_State* lua_state() const noexcept; + +Gets the ``lua_State*`` this reference exists in. + + +non-members +----------- + +.. code-block:: cpp + :caption: functions: reference comparators + + bool operator==(const reference&, const reference&); + bool operator!=(const reference&, const reference&); + +Compares two references using the Lua API's `lua_compare`_ for equality. + + +.. _lua_compare: https://www.lua.org/manual/5.3/manual.html#lua_compare diff --git a/3rdparty/sol2/docs/source/api/resolve.rst b/3rdparty/sol2/docs/source/api/resolve.rst new file mode 100644 index 00000000000..d8811d43f5c --- /dev/null +++ b/3rdparty/sol2/docs/source/api/resolve.rst @@ -0,0 +1,39 @@ +resolve +======= +utility to pick overloaded C++ function calls +--------------------------------------------- + +.. code-block:: cpp + :caption: function: resolve C++ overload + + template + auto resolve( F f ); + +``resolve`` is a function that is meant to help users pick a single function out of a group of overloaded functions in C++. You can use it to pick overloads by specifying the signature as the first template argument. Given a collection of overloaded functions: + +.. code-block:: cpp + :linenos: + + int overloaded(int x); + int overloaded(int x, int y); + int overloaded(int x, int y, int z); + +You can disambiguate them using ``resolve``: + +.. code-block:: cpp + :linenos: + + auto one_argument_func = resolve( overloaded ); + auto two_argument_func = resolve( overloaded ); + auto three_argument_func = resolve( overloaded ); + +This resolution becomes useful when setting functions on a :doc:`table
` or :doc:`state_view`: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.set_function("a", resolve( overloaded ) ); + lua.set_function("b", resolve( overloaded )); + lua.set_function("c", resolve( overloaded )); diff --git a/3rdparty/sol2/docs/source/api/simple_usertype.rst b/3rdparty/sol2/docs/source/api/simple_usertype.rst new file mode 100644 index 00000000000..e030ed92985 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/simple_usertype.rst @@ -0,0 +1,16 @@ +simple_usertype +================== +structures and classes from C++ made available to Lua code (simpler) +-------------------------------------------------------------------- + + +This type is no different from :doc:`regular usertype`, but allows much of its work to be done at runtime instead of compile-time. You can reduce compilation times from a plain `usertype` when you have an exceedingly bulky registration listing. + +You can set functions incrementally to reduce compile-time burden with ``simple_usertype`` as well, as shown in `this example`_. + +Some developers used ``simple_usertype`` to have variables automatically be functions. To achieve this behavior, wrap the desired variable into :doc:`sol::as_function`. + +The performance `seems to be good enough`_ to not warn about any implications of having to serialize things at runtime. You do run the risk of using (slightly?) more memory, however, since variables and functions need to be stored differently and separately from the metatable data itself like with a regular ``usertype``. The goal here was to avoid compiler complaints about too-large usertypes (some individuals needed to register 190+ functions, and the compiler choked from the templated implementation of ``usertype``). As of Sol 2.14, this implementation has been heavily refactored to allow for all the same syntax and uses of usertype to apply here, with no caveats/exceptions. + +.. _seems to be good enough: https://github.com/ThePhD/sol2/issues/202#issuecomment-246767629 +.. _this example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/stack.rst b/3rdparty/sol2/docs/source/api/stack.rst new file mode 100644 index 00000000000..0ebb2d2e40b --- /dev/null +++ b/3rdparty/sol2/docs/source/api/stack.rst @@ -0,0 +1,199 @@ +stack namespace +=============== +the nitty-gritty core abstraction layer over Lua +------------------------------------------------ + +.. code-block:: cpp + + namespace stack + +If you find that the higher level abstractions are not meeting your needs, you may want to delve into the ``stack`` namespace to try and get more out of Sol. ``stack.hpp`` and the ``stack`` namespace define several utilities to work with Lua, including pushing / popping utilities, getters, type checkers, Lua call helpers and more. This namespace is not thoroughly documented as the majority of its interface is mercurial and subject to change between releases to either heavily boost performance or improve the Sol :doc:`api`. + +There are, however, a few :ref:`template customization points` that you may use for your purposes and a handful of potentially handy functions. These may help if you're trying to slim down the code you have to write, or if you want to make your types behave differently throughout the Sol stack. Note that overriding the defaults **can** throw out many of the safety guarantees Sol provides: therefore, modify the :ref:`extension points` at your own discretion. + +structures +---------- + +.. code-block:: cpp + :caption: struct: record + :name: stack-record + + struct record { + int last; + int used; + + void use(int count); + }; + +This structure is for advanced usage with :ref:`stack::get` and :ref:`stack::check_get`. When overriding the customization points, it is important to call the ``use`` member function on this class with the amount of things you are pulling from the stack. ``used`` contains the total accumulation of items produced. ``last`` is the number of items gotten from the stack with the last operation (not necessarily popped from the stack). In all trivial cases for types, ``last == 1`` and ``used == 1`` after an operation; structures such as ``std::pair`` and ``std::tuple`` may pull more depending on the classes it contains. + +When overriding the :doc:`customization points<../tutorial/customization>`, please note that this structure should enable you to push multiple return values and get multiple return values to the stack, and thus be able to seamlessly pack/unpack return values from Lua into a single C++ struct, and vice-versa. This functionality is only recommended for people who need to customize the library further than the basics. It is also a good way to add support for the type and propose it back to the original library so that others may benefit from your work. + +Note that customizations can also be put up on a separate page here, if individuals decide to make in-depth custom ones for their framework or other places. + +members +------- + +.. code-block:: cpp + :caption: function: get + :name: stack-get + + template + auto get( lua_State* L, int index = -1 ) + template + auto get( lua_State* L, int index, record& tracking ) + +Retrieves the value of the object at ``index`` in the stack. The return type varies based on ``T``: with primitive types, it is usually ``T``: for all unrecognized ``T``, it is generally a ``T&`` or whatever the extension point :ref:`stack::getter\` implementation returns. The type ``T`` has top-level ``const`` qualifiers and reference modifiers removed before being forwarded to the extension point :ref:`stack::getter\` struct. ``stack::get`` will default to forwarding all arguments to the :ref:`stack::check_get` function with a handler of ``type_panic`` to strongly alert for errors, if you ask for the :doc:`safety<../safety>`. + +`record` + +You may also retrieve an :doc:`sol::optional\` from this as well, to have it attempt to not throw errors when performing the get and the type is not correct. + +.. code-block:: cpp + :caption: function: check + :name: stack-check + + template + bool check( lua_State* L, int index = -1 ) + + template + bool check( lua_State* L, int index, Handler&& handler ) + +Checks if the object at ``index`` is of type ``T``. If it is not, it will call the ``handler`` function with ``lua_State*``, ``int index``, ``type`` expected, and ``type`` actual as arguments. + +.. code-block:: cpp + :caption: function: check_get + :name: stack-check-get + + template + auto check_get( lua_State* L, int index = -1 ) + template + auto check_get( lua_State* L, int index, Handler&& handler, record& tracking ) + +Retrieves the value of the object at ``index`` in the stack, but does so safely. It returns an ``optional``, where ``U`` in this case is the return type deduced from ``stack::get``. This allows a person to properly check if the type they're getting is what they actually want, and gracefully handle errors when working with the stack if they so choose to. You can define ``SOL_CHECK_ARGUMENTS`` to turn on additional :doc:`safety<../safety>`, in which ``stack::get`` will default to calling this version of the function with a handler of ``type_panic`` to strongly alert for errors and help you track bugs if you suspect something might be going wrong in your system. + +.. code-block:: cpp + :caption: function: push + :name: stack-push + + // push T inferred from call site, pass args... through to extension point + template + int push( lua_State* L, T&& item, Args&&... args ) + + // push T that is explicitly specified, pass args... through to extension point + template + int push( lua_State* L, Arg&& arg, Args&&... args ) + + // recursively call the the above "push" with T inferred, one for each argument + template + int multi_push( lua_State* L, Args&&... args ) + +Based on how it is called, pushes a variable amount of objects onto the stack. in 99% of cases, returns for 1 object pushed onto the stack. For the case of a ``std::tuple<...>``, it recursively pushes each object contained inside the tuple, from left to right, resulting in a variable number of things pushed onto the stack (this enables multi-valued returns when binding a C++ function to a Lua). Can be called with ``sol::stack::push( L, args... )`` to have arguments different from the type that wants to be pushed, or ``sol::stack::push( L, arg, args... )`` where ``T`` will be inferred from ``arg``. The final form of this function is ``sol::stack::multi_push``, which will call one ``sol::stack::push`` for each argument. The ``T`` that describes what to push is first sanitized by removing top-level ``const`` qualifiers and reference qualifiers before being forwarded to the extension point :ref:`stack::pusher\` struct. + +.. code-block:: cpp + :caption: function: set_field + + template + void set_field( lua_State* L, Key&& k, Value&& v ); + + template + void set_field( lua_State* L, Key&& k, Value&& v, int objectindex); + +Sets the field referenced by the key ``k`` to the given value ``v``, by pushing the key onto the stack, pushing the value onto the stack, and then doing the equivalent of ``lua_setfield`` for the object at the given ``objectindex``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global. + +.. code-block:: cpp + :caption: function: get_field + + template + void get_field( lua_State* L, Key&& k [, int objectindex] ); + +Gets the field referenced by the key ``k``, by pushing the key onto the stack, and then doing the equivalent of ``lua_getfield``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global. + +This function leaves the retrieved value on the stack. + +.. code-block:: cpp + :caption: function: probe_get_field + :name: stack-probe-get-field + + template + probe probe_get_field( lua_State* L, Key&& k [, int objectindex] ); + +Gets the field referenced by the key ``k``, by pushing the key onto the stack, and then doing the equivalent of ``lua_getfield``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global. Furthermore, it does this safely by only going in as many levels deep as is possible: if the returned value is not something that can be indexed into, then traversal queries with ``std::tuple``/``std::pair`` will stop early and return probing information with the :ref:`probe struct`. + +This function leaves the retrieved value on the stack. + +.. code-block:: cpp + :caption: struct: probe + :name: stack-probe-struct + + struct probe { + bool success; + int levels; + + probe(bool s, int l); + operator bool() const; + }; + +This struct is used for showing whether or not a :ref:`probing get_field` was successful or not. + +.. _extension_points: + +objects (extension points) +-------------------------- + +You can customize the way Sol handles different structures and classes by following the information provided in the :doc:`adding your own types<../tutorial/customization>`. + +Below is more extensive information for the curious. + +The structs below are already overriden for a handful of types. If you try to mess with them for the types ``sol`` has already overriden them for, you're in for a world of thick template error traces and headaches. Overriding them for your own user defined types should be just fine, however. + +.. code-block:: cpp + :caption: struct: getter + :name: getter + + template + struct getter { + static T get (lua_State* L, int index, record& tracking) { + // ... + return // T, or something related to T. + } + }; + +This is an SFINAE-friendly struct that is meant to expose static function ``get`` that returns a ``T``, or something convertible to it. The default implementation assumes ``T`` is a usertype and pulls out a userdata from Lua before attempting to cast it to the desired ``T``. There are implementations for getting numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata_value` and anything as upvalues with :doc:`upvalue_index`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``std::function``. It is also defined for anything that derives from :doc:`sol::reference`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory`). + +.. code-block:: cpp + :caption: struct: pusher + :name: pusher + + template + struct pusher { + template + static int push ( lua_State* L, T&&, ... ) { + // can optionally take more than just 1 argument + // ... + return // number of things pushed onto the stack + } + }; + +This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a :ref:`usertype_traits\` metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata` and raw upvalues with :doc:`upvalue`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference`. It also has a special implementation for the 2 standard library smart pointers (see :doc:`usertype memory`). + +.. code-block:: cpp + :caption: struct: checker + :name: checker + + template , typename = void> + struct checker { + template + static bool check ( lua_State* L, int index, Handler&& handler, record& tracking ) { + // if the object in the Lua stack at index is a T, return true + if ( ... ) return true; + // otherwise, call the handler function, + // with the required 4 arguments, then return false + handler(L, index, expected, indextype); + return false; + } + }; + +This is an SFINAE-friendly struct that is meant to expose static function ``check`` that returns the number of things pushed onto the stack. The default implementation simply checks whether the expected type passed in through the template is equal to the type of the object at the specified index in the Lua stack. The default implementation for types which are considered ``userdata`` go through a myriad of checks to support checking if a type is *actually* of type ``T`` or if its the base class of what it actually stored as a userdata in that index. Down-casting from a base class to a more derived type is, unfortunately, impossible to do. + +.. _lua_CFunction: http://www.Lua.org/manual/5.3/manual.html#lua_CFunction \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/stack_reference.rst b/3rdparty/sol2/docs/source/api/stack_reference.rst new file mode 100644 index 00000000000..db5359d11aa --- /dev/null +++ b/3rdparty/sol2/docs/source/api/stack_reference.rst @@ -0,0 +1,8 @@ +stack_reference +=============== +zero-overhead object on the stack +--------------------------------- + +When you work with a :doc:`sol::reference`, the object gotten from the stack has a reference to it made in the registry, keeping it alive. If you want to work with the Lua stack directly without having any additional references made, ``sol::stack_reference`` is for you. Its API is identical to ``sol::reference`` in every way, except it contains a ``int stack_index()`` member function that allows you to retrieve the stack index. + +All of the base types have ``stack`` versions of themselves, and the APIs are identical to their non-stack forms. This includes :doc:`sol::stack_table
`, :doc:`sol::stack_function`, :doc:`sol::stack_protected_function`, :doc:`sol::stack_(light\_)userdata` and :doc:`sol::stack_object`. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/state.rst b/3rdparty/sol2/docs/source/api/state.rst new file mode 100644 index 00000000000..b593d5cc810 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/state.rst @@ -0,0 +1,121 @@ +state +===== +owning and non-owning state holders for registry and globals +------------------------------------------------------------ + +.. code-block:: cpp + + class state_view; + + class state : state_view, std::unique_ptr; + +The most important class here is ``state_view``. This structure takes a ``lua_State*`` that was already created and gives you simple, easy access to Lua's interfaces without taking ownership. ``state`` derives from ``state_view``, inheriting all of this functionality, but has the additional purpose of creating a fresh ``lua_State*`` and managing its lifetime for you in the default constructor. + +The majority of the members between ``state_view`` and :doc:`sol::table
` are identical, with added for this higher-level type. Therefore, all of the examples and notes in :doc:`sol::table
` apply here as well. + +enumerations +------------ + +.. code-block:: cpp + :caption: in-lua libraries + :name: lib-enum + + enum class lib : char { + base, + package, + coroutine, + string, + os, + math, + table, + debug, + bit32, + io, + ffi, + jit, + count // do not use + }; + +This enumeration details the various base libraries that come with Lua. See the `standard lua libraries`_ for details about the various standard libraries. + + +members +------- + +.. code-block:: cpp + :caption: function: open standard libraries/modules + :name: open-libraries + + template + void open_libraries(Args&&... args); + +This function takes a number of :ref:`sol::lib` as arguments and opens up the associated Lua core libraries. + +.. code-block:: cpp + :caption: function: script / script_file + + sol::function_result script(const std::string& code); + sol::function_result script_file(const std::string& filename); + +These functions run the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run isolated: any scripts or code run will affect code in the ``lua_State*`` the object uses as well (unless ``local`` is applied to a variable declaration, as specified by the Lua language). Code ran in this fashion is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques. + +If your script returns a value, you can capture it from the returned :ref:`function_result`. + +.. code-block:: cpp + :caption: function: require / require_file + :name: state-require-function + + sol::object require(const std::string& key, lua_CFunction open_function, bool create_global = true); + sol::object require_script(const std::string& key, const std::string& code, bool create_global = true); + sol::object require_file(const std::string& key, const std::string& file, bool create_global = true); + +These functions play a role similar to `luaL_requiref`_ except that they make this functionality available for loading a one-time script or a single file. The code here checks if a module has already been loaded, and if it has not, will either load / execute the file or execute the string of code passed in. If ``create_global`` is set to true, it will also link the name ``key`` to the result returned from the open function, the code or the file. Regardless or whether a fresh load happens or not, the returned module is given as a single :doc:`sol::object` for you to use as you see fit. + +Thanks to `Eric (EToreo) for the suggestion on this one`_! + +.. code-block:: cpp + :caption: function: load / load_file + :name: state-load-code + + sol::load_result load(const std::string& code); + sol::load_result load_file(const std::string& filename); + +These functions *load* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run: it returns a ``load_result`` proxy that can be called to actually run the code, turned into a ``sol::function``, a ``sol::protected_function``, or some other abstraction. If it is called, it will run on the object's current ``lua_State*``: it is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques. + +.. code-block:: cpp + :caption: function: global table / registry table + + sol::global_table globals() const; + sol::table registry() const; + +Get either the global table or the Lua registry as a :doc:`sol::table
`, which allows you to modify either of them directly. Note that getting the global table from a ``state``/``state_view`` is usually unnecessary as it has all the exact same functions as a :doc:`sol::table
` anyhow. + + +.. code-block:: cpp + :caption: function: Lua set_panic + :name: set-panic + + void set_panic(lua_CFunction panic); + +Overrides the panic function Lua calls when something unrecoverable or unexpected happens in the Lua VM. Must be a function of the that matches the ``int(*)(lua_State*)`` function signature. + +.. code-block:: cpp + :caption: function: make a table + + sol::table create_table(int narr = 0, int nrec = 0); + template + sol::table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args); + + + template + sol::table create_table_with(Args&&... args); + + static sol::table create_table(lua_State* L, int narr = 0, int nrec = 0); + template + static sol::table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args); + +Creates a table. Forwards its arguments to :ref:`table::create`. + +.. _standard lua libraries: http://www.lua.org/manual/5.3/manual.html#6 +.. _luaL_requiref: https://www.lua.org/manual/5.3/manual.html#luaL_requiref +.. _Eric (EToreo) for the suggestion on this one: https://github.com/ThePhD/sol2/issues/90 \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/table.rst b/3rdparty/sol2/docs/source/api/table.rst new file mode 100644 index 00000000000..b5a946487de --- /dev/null +++ b/3rdparty/sol2/docs/source/api/table.rst @@ -0,0 +1,208 @@ +table +===== +a representation of a Lua (meta)table +------------------------------------- + +.. code-block:: cpp + + template + class table_core; + + typedef table_core table; + typedef table_core global_table; + +``sol::table`` is an extremely efficient manipulator of state that brings most of the magic of the Sol abstraction. Capable of doing multiple sets at once, multiple gets into a ``std::tuple``, being indexed into using ``[key]`` syntax and setting keys with a similar syntax (see: :doc:`here`), ``sol::table`` is the corner of the interaction between Lua and C++. + +There are two kinds of tables: the global table and non-global tables: however, both have the exact same interface and all ``sol::global_table`` s are convertible to regular ``sol::table`` s. + +Tables are the core of Lua, and they are very much the core of Sol. + + +members +------- + +.. code-block:: cpp + :caption: constructor: table + + table(lua_State* L, int index = -1); + +Takes a table from the Lua stack at the specified index and allows a person to use all of the abstractions therein. + +.. code-block:: cpp + :caption: function: get / traversing get + + template + decltype(auto) get(Keys&&... keys) const; + + template + decltype(auto) traverse_get(Keys&&... keys) const; + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const; + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const; + + +These functions retrieve items from the table. The first one (``get``) can pull out *multiple* values, 1 for each key value passed into the function. In the case of multiple return values, it is returned in a ``std::tuple``. It is similar to doing ``return table["a"], table["b"], table["c"]``. Because it returns a ``std::tuple``, you can use ``std::tie``/``std::make_tuple`` on a multi-get to retrieve all of the necessary variables. The second one (``traverse_get``) pulls out a *single* value, using each successive key provided to do another lookup into the last. It is similar to doing ``x = table["a"]["b"]["c"][...]``. + +If the keys within nested queries try to traverse into a table that doesn't exist, the second lookup into the nil-returned variable and belong will cause a panic to be fired by the lua C API. If you need to check for keys, check with ``auto x = table.get>( std::tie("a", "b", "c" ) );``, and then use the :doc:`optional` interface to check for errors. As a short-hand, easy method for returning a default if a value doesn't exist, you can use ``get_or`` instead. + +.. code-block:: cpp + :caption: function: set / traversing set + :name: set-value + + template + table& set(Args&&... args); + + template + table& traverse_set(Args&&... args); + +These functions set items into the table. The first one (``set``) can set *multiple* values, in the form ``key_a, value_a, key_b, value_b, ...``. It is similar to ``table[key_a] = value_a; table[key_b] = value_b, ...``. The second one (``traverse_set``) sets a *single* value, using all but the last argument as keys to do another lookup into the value retrieved prior to it. It is equivalent to ``table[key_a][key_b][...] = value;``. + +.. note:: + + Value semantics are applied to all set operations. If you do not ``std::ref( obj )`` or specifically make a pointer with ``std::addressof( obj )`` or ``&obj``, it will copy / move. This is different from how :doc:`sol::function` behaves with its call operator. + +.. code-block:: cpp + :caption: function: set a function with the specified key into lua + :name: set-function + + template + state_view& set_function(Key&& key, Fx&& fx, [...]); + +Sets the desired function to the specified key value. Note that it also allows for passing a member function plus a member object or just a single member function: however, using a lambda is almost always better when you want to bind a member function + class instance to a single function call in Lua. + +.. code-block:: cpp + :caption: function: add + + template + table& add(Args&&... args); + +This function appends a value to a table. The definition of appends here is only well-defined for a table which has a perfectly sequential (and integral) ordering of numeric keys with associated non-null values (the same requirement for the :ref:`size` function). Otherwise, this falls to the implementation-defined behavior of your Lua VM, whereupon is may add keys into empty 'holes' in the array (e.g., the first empty non-sequential integer key it gets to from ``size``) or perhaps at the very "end" of the "array". Do yourself the favor of making sure your keys are sequential. + +Each argument is appended to the list one at a time. + +.. code-block:: cpp + :caption: function: size + :name: size-function + + std::size_t size() const; + +This function returns the size of a table. It is only well-defined in the case of a Lua table which has a perfectly sequential (and integral) ordering of numeric keys with associated non-null values. + +.. code-block:: cpp + :caption: function: setting a usertype + :name: new-usertype + + template + table& new_usertype(const std::string& name, Args&&... args); + template + table& new_usertype(const std::string& name, Args&&... args); + template + table& new_usertype(const std::string& name, constructors ctor, Args&&... args); + +This class of functions creates a new :doc:`usertype` with the specified arguments, providing a few extra details for constructors. After creating a usertype with the specified argument, it passes it to :ref:`set_usertype`. + +.. code-block:: cpp + :caption: function: setting a simple usertype + :name: new-simple-usertype + + template + table& new_simple_usertype(const std::string& name, Args&&... args); + template + table& new_simple_usertype(const std::string& name, Args&&... args); + template + table& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args); + +This class of functions creates a new :doc:`simple usertype` with the specified arguments, providing a few extra details for constructors and passing the ``sol::simple`` tag as well. After creating a usertype with the specified argument, it passes it to :ref:`set_usertype`. + +.. code-block:: cpp + :caption: function: creating an enum + :name: new-enum + + template + basic_table_core& new_enum(const std::string& name, Args&&... args); + +Use this function to create an enumeration type in Lua. By default, the enum will be made read-only, which creates a tiny performance hit to make the values stored in this table behave exactly like a read-only enumeration in C++. If you plan on changing the enum values in Lua, set the ``read_only`` template parameter in your ``new_enum`` call to false. The arguments are expected to come in ``key, value, key, value, ...`` list. + +.. _set_usertype: + +.. code-block:: cpp + :caption: function: setting a pre-created usertype + :name: set-usertype + + template + table& set_usertype(usertype& user); + template + table& set_usertype(Key&& key, usertype& user); + +Sets a previously created usertype with the specified ``key`` into the table. Note that if you do not specify a key, the implementation falls back to setting the usertype with a ``key`` of ``usertype_traits::name``, which is an implementation-defined name that tends to be of the form ``{namespace_name 1}_[{namespace_name 2 ...}_{class name}``. + +.. code-block:: cpp + :caption: function: begin / end for iteration + :name: table-iterators + + table_iterator begin () const; + table_iterator end() const; + table_iterator cbegin() const; + table_iterator cend() const; + +Provides `input iterators`_ for a table. This allows tables to work with single-pass, input-only algorithms (like ``std::for_each``). + +.. code-block:: cpp + :caption: function: iteration with a function + :name: table-for-each + + template + void for_each(Fx&& fx); + +A functional ``for_each`` loop that calls the desired function. The passed in function must take either ``sol::object key, sol::object value`` or take a ``std::pair key_value_pair``. This version can be a bit safer as allows the implementation to definitively pop the key/value off the Lua stack after each call of the function. + +.. code-block:: cpp + :caption: function: operator[] access + + template + proxy operator[](T&& key); + template + proxy operator[](T&& key) const; + +Generates a :doc:`proxy` that is templated on the table type and the key type. Enables lookup of items and their implicit conversion to a desired type. + +.. code-block:: cpp + :caption: function: create a table with defaults + :name: table-create + + table create(int narr = 0, int nrec = 0); + template + table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args); + + static table create(lua_State* L, int narr = 0, int nrec = 0); + template + static table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args); + +Creates a table, optionally with the specified values pre-set into the table. If ``narr`` or ``nrec`` are 0, then compile-time shenanigans are used to guess the amount of array entries (e.g., integer keys) and the amount of hashable entries (e.g., all other entries). + +.. code-block:: cpp + :caption: function: create a table with compile-time defaults assumed + :name: table-create-with + + template + table create_with(Args&&... args); + template + static table create_with(lua_State* L, Args&&... args); + + +Creates a table, optionally with the specified values pre-set into the table. It checks every 2nd argument (the keys) and generates hints for how many array or map-style entries will be placed into the table. + +.. code-block:: cpp + :caption: function: create a named table with compile-time defaults assumed + :name: table-create-named + + template + table create_named(Name&& name, Args&&... args); + + +Creates a table, optionally with the specified values pre-set into the table, and sets it as the key ``name`` in the table. + +.. _input iterators: http://en.cppreference.com/w/cpp/concept/InputIterator \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/this_state.rst b/3rdparty/sol2/docs/source/api/this_state.rst new file mode 100644 index 00000000000..c4c6b3b7f75 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/this_state.rst @@ -0,0 +1,31 @@ +this_state +========== +transparent state argument for the current state +------------------------------------------------ + +.. code-block:: cpp + + struct this_state; + +This class is a transparent type that is meant to be gotten in functions to get the current lua state a bound function or usertype method is being called from. It does not actually retrieve anything from lua nor does it increment the argument count, making it "invisible" to function calls in lua and calls through ``std::function<...>`` and :doc:`sol::function` on this type. It can be put in any position in the argument list of a function: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.set_function("bark", []( sol::this_state s, int a, int b ){ + lua_State* L = s; // current state + return a + b + lua_gettop(L); + }); + + lua.script("first = bark(2, 2)"); // only takes 2 arguments, NOT 3 + + // Can be at the end, too, or in the middle: doesn't matter + lua.set_function("bark", []( int a, int b, sol::this_state s ){ + lua_State* L = s; // current state + return a + b + lua_gettop(L); + }); + + lua.script("second = bark(2, 2)"); // only takes 2 arguments + \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/thread.rst b/3rdparty/sol2/docs/source/api/thread.rst new file mode 100644 index 00000000000..1a713f973b4 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/thread.rst @@ -0,0 +1,52 @@ +thread +====== +a separate state that can contain and run functions +--------------------------------------------------- + +.. code-block:: cpp + + class thread : public reference { /* ... */ }; + +``sol::thread`` is a separate runnable part of the Lua VM that can be used to execute work separately from the main thread, such as with :doc:`coroutines`. To take a table or a coroutine and run it specifically on the ``sol::thread`` you either pulled out of lua or created, just get that function through the :ref:`state of the thread` + +members +------- + +.. code-block:: cpp + :caption: constructor: thread + + thread(lua_State* L, int index = -1); + +Takes a thread from the Lua stack at the specified index and allows a person to use all of the abstractions therein. + +.. code-block:: cpp + :caption: function: view into thread_state()'s state + + state_view state() const; + +This retrieves the current state of the thread, producing a :doc:`state_view` that can be manipulated like any other. :doc:`Coroutines` pulled from Lua using the thread's state will be run on that thread specifically. + +.. _thread_state: + +.. code-block:: cpp + :caption: function: retrieve thread state object + + lua_State* thread_state () const; + +This function retrieves the ``lua_State*`` that represents the thread. + +.. code-block:: cpp + :caption: current thread status + + thread_status status () const; + +Retrieves the :doc:`thread status` that describes the current state of the thread. + +.. code-block:: cpp + :caption: function: thread creation + :name: thread-create + + thread create(); + static thread create (lua_State* L); + +Creates a new thread from the given a ``lua_State*``. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/tie.rst b/3rdparty/sol2/docs/source/api/tie.rst new file mode 100644 index 00000000000..080c8a1cc4f --- /dev/null +++ b/3rdparty/sol2/docs/source/api/tie.rst @@ -0,0 +1,26 @@ +tie +=== +An improved version of ``std::tie`` +----------------------------------- + +`std::tie()`_ does not work well with :doc:`sol::function`'s ``sol::function_result`` returns. Use ``sol::tie`` instead. Because they're both named `tie`, you'll need to be explicit when you use Sol's by naming it with the namespace (``sol::tie``), even with a ``using namespace sol;``. Here's an example: + +.. code-block:: cpp + + sol::state lua; + lua.open_libraries(sol::lib::base); + + const auto& code = R"( + function test() + return 1, 2, 3 + end + )"; + lua.script(code); + + int a, b, c; + //std::tie(a, b, c) = lua["test"](); + // will error: use the line below + sol::tie(a, b, c) = lua["test"](); + + +.. _std::tie(): http://en.cppreference.com/w/cpp/utility/tuple/tie diff --git a/3rdparty/sol2/docs/source/api/types.rst b/3rdparty/sol2/docs/source/api/types.rst new file mode 100644 index 00000000000..9f761ee25b9 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/types.rst @@ -0,0 +1,207 @@ +types +===== +nil, lua_primitive type traits, and other fundamentals +------------------------------------------------------ + +The ``types.hpp`` header contains various fundamentals and utilities of Sol. + + +enumerations +------------ + +.. code-block:: cpp + :caption: syntax of a function called by Lua + :name: call-syntax + + enum class call_syntax { + dot = 0, + colon = 1 + }; + +This enumeration indicates the syntax a function was called with in a specific scenario. There are two ways to call a function: with ``obj:func_name( ... )`` or ``obj.func_name( ... );`` The first one passes "obj" as the first argument: the second one does not. In the case of usertypes, this is used to determine whether the call to a :doc:`constructor/initializer` was called with a ``:`` or a ``.``, and not misalign the arguments. + +.. code-block:: cpp + :caption: status of a Lua function call + :name: call-status + + enum class call_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + handler = LUA_ERRERR, + gc = LUA_ERRGCMM + }; + +This strongly-typed enumeration contains the errors potentially generated by a call to a :doc:`protected function` or a :doc:`coroutine`. + +.. code-block:: cpp + :caption: status of a Lua thread + :name: thread-status + + enum class thread_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + handler = LUA_ERRERR, + dead, + }; + +This enumeration contains the status of a thread. The ``thread_status::dead`` state is generated when the thread has nothing on its stack and it is not running anything. + +.. code-block:: cpp + :caption: status of a Lua load operation + :name: load-status + + enum class load_status : int { + ok = LUA_OK, + runtime = LUA_ERRSYNTAX, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + file = LUA_ERRFILE, + }; + +This enumeration contains the status of a load operation from :ref:`state::load(_file)`. + +.. code-block:: cpp + :caption: type enumeration + :name: type-enum + + enum class type : int { + none = LUA_TNONE, + nil = LUA_TNIL, + string = LUA_TSTRING, + number = LUA_TNUMBER, + thread = LUA_TTHREAD, + boolean = LUA_TBOOLEAN, + function = LUA_TFUNCTION, + userdata = LUA_TUSERDATA, + lightuserdata = LUA_TLIGHTUSERDATA, + table = LUA_TTABLE, + poly = none | nil | string | number | thread | + table | boolean | function | userdata | lightuserdata + }; + +The base types that Lua natively communicates in and understands. Note that "poly" isn't really a true type, it's just a symbol used in Sol for something whose type hasn't been checked (and you should almost never see it). + + +type traits +----------- + +.. code-block:: cpp + :caption: lua_type_of trait + :name: lua-type-of + + template + struct lua_type_of; + +This type trait maps a C++ type to a :ref:`type enumeration` value. The default value is ``type::userdata``. + +.. code-block:: cpp + :caption: primitive checking traits + :name: is-primitive + + template + struct is_lua_primitive; + + template + struct is_proxy_primitive; + + +This trait is used by :doc:`proxy` to know which types should be returned as references to internal Lua memory (e.g., ``userdata`` types) and which ones to return as values (strings, numbers, :doc:`references`). ``std::reference_wrapper``, ``std::tuple<...>`` are returned as values, but their contents can be references. The default value is false. + +special types +------------- + +.. code-block:: cpp + :caption: nil + :name: nil + + strunil_t {}; + const nil_t nil {}; + bool operator==(nil_t, nil_t); + bool operator!=(nil_t, nil_t); + +``nil`` is a constant used to signify Lua's ``nil``, which is a type and object that something does not exist. It is comparable to itself, :doc:`sol::object` and :doc:`proxy values`. + + +.. code-block:: cpp + :caption: non_null + + template + struct non_null {}; + +A tag type that, when used with :doc:`stack::get\>`, does not perform a ``nil`` check when attempting to retrieve the userdata pointer. + + +.. code-block:: cpp + :caption: type list + :name: type-list + + template + struct types; + +A type list that, unlike ``std::tuple``, does not actually contain anything. Used to indicate types and groups of types all over Sol. + + +functions +--------- + +.. code-block:: cpp + :caption: type_of + + template + type type_of(); + + type type_of(lua_State* L, int index); + + +These functions get the type of a C++ type ``T``; or the type at the specified index on the Lua stack. + +.. code-block:: cpp + :caption: type checking convenience functions + + int type_panic(lua_State* L, int index, type expected, type actual); + + int no_panic(lua_State*, int, type, type) noexcept; + + void type_error(lua_State* L, int expected, int actual); + + void type_error(lua_State* L, type expected, type actual); + + void type_assert(lua_State* L, int index, type expected, type actual); + + void type_assert(lua_State* L, int index, type expected); + +The purpose of these functions is to assert / throw / crash / error (or do nothing, as is the case with ``no_panic``). They're mostly used internally in the framework, but they're provided here if you should need them. + +.. code-block:: cpp + :caption: type name retrieval + + std::string type_name(lua_State*L, type t); + +Gets the Lua-specified name of the :ref:`type`. + +structs +------- + +.. code-block:: cpp + + struct userdata_value { + void* value; + }; + + struct light_userdata_value { + void* value; + }; + + struct up_value_index { + int index; + }; + + +Types that differentiate between the two kinds of ``void*`` Lua hands back from its API: full userdata and light userdata, as well as a type that modifies the index passed to ``get`` to refer to `up values`_ These types can be used to trigger different underlying API calls to Lua when working with :doc:`stack` namespace and the ``push``/``get``/``pop``/``check`` functions. + +.. _up values: http://www.Lua.org/manual/5.3/manual.html#4.4 \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/unique_usertype_traits.rst b/3rdparty/sol2/docs/source/api/unique_usertype_traits.rst new file mode 100644 index 00000000000..4568b11349c --- /dev/null +++ b/3rdparty/sol2/docs/source/api/unique_usertype_traits.rst @@ -0,0 +1,44 @@ +unique_usertype_traits +========================= +A trait for hooking special handles / pointers +---------------------------------------------- + +.. code-block:: cpp + :caption: unique_usertype + :name: unique-usertype + + template + struct unique_usertype_traits { + typedef T type; + typedef T actual_type; + static const bool value = false; + + static bool is_null(const actual_type&) {...} + + static type* get (const actual_type&) {...} + }; + +This is a customization point for users who need to *work with special kinds of pointers/handles*. For generic customization, please review the :doc:`customization tutorial<../tutorial/customization>` A traits type for alerting the library that a certain type is to be pushed as a special userdata with special deletion / destruction semantics. It is already defined for ``std::unique_ptr`` and ``std::shared_ptr``. You can specialize this to get ``unique_usertype_traits`` semantics with your code, for example with ``boost::shared_ptr`` like so: + +.. code-block:: cpp + + namespace sol { + template + struct unique_usertype_traits> { + typedef T type; + typedef boost::shared_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& value) { + return value == nullptr; + } + + static type* get (const actual_type& p) { + return p.get(); + } + } + } + +This will allow the framework to properly handle ``boost::shared_ptr``, with ref-counting and all. The `type` is the type that lua and sol will interact with, and will allow you to pull out a non-owning reference / pointer to the data when you just ask for a plain `T*` or `T&` or `T` using the getter functions and properties of Sol. + +Note that if ``is_null`` triggers, a ``nil`` value will be pushed into Sol. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/user.rst b/3rdparty/sol2/docs/source/api/user.rst new file mode 100644 index 00000000000..9a0905d76bd --- /dev/null +++ b/3rdparty/sol2/docs/source/api/user.rst @@ -0,0 +1,19 @@ +light/user +================ +Utility class for the cheapest form of (light) userdata +------------------------------------------------------- + +.. code-block:: cpp + + template + struct user; + + template + struct light; + + +``sol::user`` and ``sol::light`` are two utility classes that do not participate in the full :doc:`sol::usertype\` system. The goal of these classes is to provide the most minimal memory footprint and overhead for putting a single item and getting a single item out of Lua. ``sol::user``, when pushed into Lua, will create a thin, unnamed metatable for that instance specifically which will be for calling its destructor. ``sol::light`` specifically pushes a reference / pointer into Lua as a ``sol::type::lightuserdata``. + +If you feel that you do not need to have something participate in the full :doc:`usertype\` system, use the utility functions ``sol::make_user( ... )`` and ``sol::make_light( ... )`` to create these types and store them into Lua. You can get them off the Lua stack / out of the Lua system by using the same retrieval techniques on ``get`` and ``operator[]`` on tables and with stack operations. + +Both have implicit conversion operators to ``T*`` and ``T&``, so you can set them immediately to their respective pointer and reference types if you need them. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/userdata.rst b/3rdparty/sol2/docs/source/api/userdata.rst new file mode 100644 index 00000000000..6bc64791552 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/userdata.rst @@ -0,0 +1,13 @@ +userdata +======== +reference to a userdata +----------------------- + +.. code-block:: cpp + :caption: (light\_)userdata reference + + class userdata : public reference; + + class light_userdata : public reference; + +These type is meant to hold a reference to a (light) userdata from Lua and make it easy to push an existing userdata onto the stack. It is essentially identical to :doc:`reference` in every way, just with a definitive C++ type. diff --git a/3rdparty/sol2/docs/source/api/usertype.rst b/3rdparty/sol2/docs/source/api/usertype.rst new file mode 100644 index 00000000000..d3282cd5c64 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/usertype.rst @@ -0,0 +1,329 @@ +usertype +=========== +structures and classes from C++ made available to Lua code +---------------------------------------------------------- + +*Note: ``T`` refers to the type being turned into a usertype.* + +While other frameworks extend lua's syntax or create Data Structure Languages (DSLs) to create classes in lua, :doc:`sol<../index>` instead offers the ability to generate easy bindings. These use metatables and userdata in lua for their implementation. Given this C++ class: + +.. code-block:: cpp + :linenos: + + struct ship { + int bullets = 20; + int life = 100; + + bool shoot () { + if (bullets > 0) { + --bullets; + // successfully shot + return true; + } + // cannot shoot + return false; + } + + bool hurt (int by) { + life -= by; + // have we died? + return life < 1; + } + }; + +You can bind the it to Lua using the following C++ code: + +.. code-block:: cpp + :linenos: + + sol::state lua; + + lua.new_usertype( "ship", // the name of the class, as you want it to be used in lua + // List the member functions you wish to bind: + // "name_of_item", &class_name::function_or_variable + "shoot", &ship::shoot, + "hurt", &ship::hurt, + // bind variable types, too + "life", &ship::bullets + // names in lua don't have to be the same as C++, + // but it probably helps if they're kept the same, + // here we change it just to show its possible + "bullet_count", &ship::bullets + ); + + +Equivalently, you can also write: + +.. code-block:: cpp + :linenos: + :emphasize-lines: 4,12 + + sol::state lua; + + // Use constructor directly + usertype shiptype( + "shoot", &ship::shoot, + "hurt", &ship::hurt, + "life", &ship::bullets + "bullet_count", &ship::bullets + ); + + // set usertype explicitly, with the given name + lua.set_usertype( "ship", shiptype ); + + // shiptype is now a useless skeleton type, just let it destruct naturally and don't use it again. + + +Note that here, because the C++ class is default-constructible, it will automatically generate a creation function that can be called in lua called "new" that takes no arguments. You can use it like this in lua code: + +.. code-block:: lua + :linenos: + + fwoosh = ship.new() + -- note the ":" that is there: this is mandatory for member function calls + -- ":" means "pass self" in Lua + local success = fwoosh:shoot() + local is_dead = fwoosh:hurt(20) + -- check if it works + print(is_dead) -- the ship is not dead at this point + print(fwoosh.life .. "life left") -- 80 life left + print(fwoosh.bullet_count) -- 19 + + +There are more advanced use cases for how to create and use a usertype, which are all based on how to use its constructor (see below). + +enumerations +------------ + +.. _meta_function_enum: + +.. code-block:: cpp + :caption: meta_function enumeration for names + :linenos: + + enum class meta_function { + construct, + index, + new_index, + mode, + call, + metatable, + to_string, + length, + unary_minus, + addition, + subtraction, + multiplication, + division, + modulus, + power_of, + involution = power_of, + concatenation, + equal_to, + less_than, + less_than_or_equal_to, + garbage_collect, + call_function, + }; + + +Use this enumeration to specify names in a manner friendlier than memorizing the special lua metamethod names for each of these. Each binds to a specific operation indicated by the descriptive name of the enum. + +members +------- + +.. code-block:: cpp + :caption: function: usertype constructor + :name: usertype-constructor + + template + usertype(Args&&... args); + + +The constructor of usertype takes a variable number of arguments. It takes an even number of arguments (except in the case where the very first argument is passed as the :ref:`constructor list type`). Names can either be strings, :ref:`special meta_function enumerations`, or one of the special indicators for initializers. + + +usertype constructor options +++++++++++++++++++++++++++++ + +If you don't specify any constructor options at all and the type is `default_constructible`_, Sol will generate a ``new`` for you. Otherwise, the following are special ways to handle the construction of a usertype: + +.. _constructor: + +* ``"{name}", constructors`` + - ``Type-List-N`` must be a ``sol::types``, where ``Args...`` is a list of types that a constructor takes. Supports overloading by default + - If you pass the ``constructors<...>`` argument first when constructing the usertype, then it will automatically be given a ``"{name}"`` of ``"new"`` +* ``"{name}", sol::initializers( func1, func2, ... )`` + - Used to handle *initializer functions* that need to initialize the memory itself (but not actually allocate the memory, since that comes as a userdata block from Lua) + - Given one or more functions, provides an overloaded Lua function for creating a the specified type + + The function must have the argument signature ``func( T*, Arguments... )`` or ``func( T&, Arguments... )``, where the pointer or reference will point to a place of allocated memory that has an uninitialized ``T``. Note that Lua controls the memory, so performing a ``new`` and setting it to the ``T*`` or ``T&`` is a bad idea: instead, use ``placement new`` to invoke a constructor, or deal with the memory exactly as you see fit +* ``{anything}, sol::factories( func1, func2, ... )`` + - Used to indicate that a factory function (e.g., something that produces a ``std::unique_ptr``, ``std::shared_ptr``, ``T``, or similar) will be creating the object type + - Given one or more functions, provides an overloaded function for invoking + + The functions can take any form and return anything, since they're just considered to be some plain function and no placement new or otherwise needs to be done. Results from this function will be pushed into Lua according to the same rules as everything else. + + Can be used to stop the generation of a ``.new()`` default constructor since a ``sol::factories`` entry will be recognized as a constructor for the usertype + + If this is not sufficient, see next 2 entries on how to specifically block a constructor +* ``{anything}, sol::no_constructor`` + - Specifically tells Sol not to create a ``.new()`` if one is not specified and the type is default-constructible + - ``{anything}`` should probably be ``"new"``, which will specifically block its creation and give a proper warning if someone calls ``new`` (otherwise it will just give a nil value error) + - *Combine with the next one to only allow a factory function for your function type* +* ``{anything}, {some_factory_function}`` + - Essentially binds whatever the function is to name ``{anything}`` + - When used WITH the ``sol::no_constructor`` option above (e.g. ``"new", sol::no_constructor`` and after that having ``"create", &my_creation_func``), one can remove typical constructor avenues and then only provide specific factory functions. Note that this combination is similar to using the ``sol::factories`` method mentioned earlier in this list. To control the destructor as well, see further below +* ``sol::call_constructor, {valid function / constructor / initializer / factory}`` + - The purpose of this is to enable the syntax ``local v = my_class( 24 )`` and have that call a constructor; it has no other purpose + - This is compatible with luabind, kaguya and other Lua library syntaxes and looks similar to C++ syntax, but the general consensus in Programming with Lua and other places is to use a function named ``new`` + +usertype destructor options ++++++++++++++++++++++++++++ + +If you don't specify anything at all and the type is `destructible`_, then a destructor will be bound to the garbage collection metamethod. Otherwise, the following are special ways to handle the destruction of a usertype: + +* ``"__gc", sol::destructor( func )`` or ``sol::meta_function::garbage_collect, sol::destructor( func )`` + - Creates a custom destructor that takes an argument ``T*`` or ``T&`` and expects it to be destructed/destroyed. Note that lua controls the memory and thusly will deallocate the necessary space AFTER this function returns (e.g., do not call ``delete`` as that will attempt to deallocate memory you did not ``new``) + - If you just want the default constructor, you can replace the second argument with ``sol::default_destructor`` + - The usertype will error / throw if you specify a destructor specifically but do not map it to ``sol::meta_function::gc`` or a string equivalent to ``"__gc"`` + +usertype regular function options ++++++++++++++++++++++++++++++++++ + +If you don't specify anything at all and the type ``T`` supports ``operator <``, ``operator <=``, or ``operator==`` (``const`` or non-``const`` qualified): + +* for ``operator <`` and ``operator <=`` + - These two ``sol::meta_function::less_than(_or_equal_to)`` are generated for you and overriden in Lua. +* for ``operator==`` + - An equality operator will always be generated, doing pointer comparison if ``operator==`` on the two value types is not supported or doing a reference comparison and a value comparison if ``operator==`` is supported +* heterogenous operators cannot be supported for equality, as Lua specifically checks if they use the same function to do the comparison: if they do not, then the equality method is not invoked; one way around this would be to write one ``int super_equality_function(lua_State* L) { ... }``, pull out arguments 1 and 2 from the stack for your type, and check all the types and then invoke ``operator==`` yourself after getting the types out of Lua (possibly using :ref:`sol::stack::get` and :ref:`sol::stack::check_get`) + +Otherwise, the following is used to specify functions to bind on the specific usertype for ``T``. + +* ``"{name}", &free_function`` + - Binds a free function / static class function / function object (lambda) to ``"{name}"``. If the first argument is ``T*`` or ``T&``, then it will bind it as a member function. If it is not, it will be bound as a "static" function on the lua table +* ``"{name}", &type::function_name`` or ``"{name}", &type::member_variable`` + - Binds a typical member function or variable to ``"{name}"``. In the case of a member variable or member function, ``type`` must be ``T`` or a base of ``T`` +* ``"{name}", sol::readonly( &type::member_variable )`` + - Binds a typical variable to ``"{name}"``. Similar to the above, but the variable will be read-only, meaning an error will be generated if anything attemps to write to this variable +* ``"{name}", sol::as_function( &type::member_variable )`` + - Binds a typical variable to ``"{name}"`` *but forces the syntax to be callable like a function*. This produces a getter and a setter accessible by ``obj:name()`` to get and ``obj::name(value)`` to set. +* ``"{name}", sol::property( getter_func, setter_func )`` + - Binds a typical variable to ``"{name}"``, but gets and sets using the specified setter and getter functions. Not that if you do not pass a setter function, the variable will be read-only. Also not that if you do not pass a getter function, it will be write-only +* ``"{name}", sol::var( some_value )`` or ``"{name}", sol::var( std::ref( some_value ) )`` + - Binds a typical variable to ``"{name}"``, optionally by reference (e.g., refers to the same memory in C++). This is useful for global variables / static class variables and the like +* ``"{name}", sol::overloaded( Func1, Func2, ... )`` + - Creates an oveloaded member function that discriminates on number of arguments and types. +* ``sol::base_classes, sol::bases`` + - Tells a usertype what its base classes are. You need this to have derived-to-base conversions work properly. See :ref:`inheritance` + + +usertype arguments - simple usertype +++++++++++++++++++++++++++++++++++++ + +* ``sol::simple`` + - Only allowed as the first argument to the usertype constructor, must be accompanied by a ``lua_State*`` + - This tag triggers the :doc:`simple usertype` changes / optimizations + - Only supported when directly invoking the constructor (e.g. not when calling ``sol::table::new_usertype`` or ``sol::table::new_simple_usertype``) + - Should probably not be used directly. Use ``sol::table::new_usertype`` or ``sol::table::new_simple_usertype`` instead + + + +overloading +----------- + +Functions set on a usertype support overloading. See :doc:`here` for an example. + + +.. _usertype-inheritance: + +inheritance +----------- + +Sol can adjust pointers from derived classes to base classes at runtime, but it has some caveats based on what you compile with: + +If your class has no complicated™ virtual inheritance or multiple inheritance, than you can try to sneak away with a performance boost from not specifying any base classes and doing any casting checks. (What does "complicated™" mean? Ask your compiler's documentation, if you're in that deep.) + +For the rest of us safe individuals out there: You must specify the ``sol::base_classes`` tag with the ``sol::bases()`` argument, where ``Types...`` are all the base classes of the single type ``T`` that you are making a usertype out of. + +.. note:: + + Always specify your bases if you plan to retrieve a base class using the Sol abstraction directly and not casting yourself. + +.. code-block:: cpp + :linenos: + + struct A { + int a = 10; + virtual int call() { return 0; } + }; + struct B : A { + int b = 11; + virtual int call() override { return 20; } + }; + +Then, to register the base classes explicitly: + +.. code-block:: cpp + :linenos: + :emphasize-lines: 5 + + sol::state lua; + + lua.new_usertype( "B", + "call", &B::call, + sol::base_classes, sol::bases() + ); + +.. note:: + + You must list ALL base classes, including (if there were any) the base classes of A, and the base classes of those base classes, etc. if you want Sol/Lua to handle them automagically. + +.. note:: + + Sol does not support down-casting from a base class to a derived class at runtime. + +.. warning:: + + Specify all base class member variables and member functions to avoid current implementation caveats regarding automatic base member lookup. Sol currently attempts to link base class methods and variables with their derived classes with an undocumented, unsupported feature, provided you specify ``sol::base_classes<...>``. Unfortunately, this can come at the cost of performance, depending on how "far" the base is from the derived class in the bases lookup list. If you do not want to suffer the performance degradation while we iron out the kinks in the implementation (and want it to stay performant forever), please specify all the base methods on the derived class in the method listing you write. In the future, we hope that with reflection we will not have to worry about this. + + +inheritance + overloading +------------------------- + +While overloading is supported regardless of inheritance caveats or not, the current version of Sol has a first-match, first-call style of overloading when it comes to inheritance. Put the functions with the most derived arguments first to get the kind of matching you expect or cast inside of an intermediary C++ function and call the function you desire. + +traits +------ + +.. code-block:: cpp + :caption: usertype_traits + :name: usertype-traits + + template + struct usertype_traits { + static const std::string name; + static const std::string metatable; + static const std::string variable_metatable; + static const std::string gc_table; + }; + + +This trait is used to provide names for the various metatables and global tables used to perform cleanup and lookup. They are automagically generated at runtime. Sol attempts to parse the output of ``__PRETTY_FUCNTION__`` (``g++``/``clang++``) or ``_FUNCDSIG`` (``vc++``) to get the proper type name. If you have a special need you can override the names for your specific type. If you notice a bug in a class name when you don't manually specify it during setting a usertype, feel free to open an issue request or send an e-mail! + + +compilation speed +----------------- + +.. note:: + + If you find that compilation times are too long and you're only binding member functions, consider perhaps using :doc:`simple usertypes`. This can reduce compile times (but may cost memory size and speed). See the simple usertypes documentation for more details. + + +performance note +---------------- + +.. note:: + + Note that performance for member function calls goes down by a fixed overhead if you also bind variables as well as member functions. This is purely a limitation of the Lua implementation and there is, unfortunately, nothing that can be done about it. If you bind only functions and no variables, however, Sol will automatically optimize the Lua runtime and give you the maximum performance possible. *Please consider ease of use and maintenance of code before you make everything into functions.* + + +.. _destructible: http://en.cppreference.com/w/cpp/types/is_destructible +.. _default_constructible: http://en.cppreference.com/w/cpp/types/is_constructible \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/usertype_memory.rst b/3rdparty/sol2/docs/source/api/usertype_memory.rst new file mode 100644 index 00000000000..55734f7e543 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/usertype_memory.rst @@ -0,0 +1,47 @@ +usertype memory +=============== + +.. note:: + + Sol does not take ownership of raw pointers, returned from functions or set through the ``set`` functions. Return a value, a ``std::unique_ptr``, a ``std::shared_ptr`` of some kind, or hook up the :doc:`unique usertypes traits` to work for some specific handle structure you use (AKA, for ``boost::shared_ptr``). + +The userdata generated by Sol has a specific layout, depending on how Sol recognizes userdata passed into it. All of the referred to metatable names are generated from :ref:`usertype_traits\` + +In general, we always insert a T* in the first `sizeof(T*)` bytes, so the any framework that pulls out those first bytes expecting a pointer will work. The rest of the data has some different alignments and contents based on what it's used for and how it's used. + +For ``T`` +--------- + +These are classified with the metatable name from :ref:`usertype_traits\`. + +The data layout for references is as follows:: + + | T* | T | + ^-sizeof(T*) bytes-^-sizeof(T) bytes, actual data-^ + +Lua will clean up the memory itself but does not know about any destruction semantics T may have imposed, so when we destroy this data we simply call the destructor to destroy the object and leave the memory changes to for lua to handle after the "__gc" method exits. + + +For ``T*`` +---------- + +These are classified as a separate ``T*`` metatable, essentially the "reference" table. Things passed to Sol as a pointer or as a ``std::reference`` are considered to be references, and thusly do not have a ``__gc`` (garbage collection) method by default. All raw pointers are non-owning pointers in C++. If you're working with a C API, provide a wrapper around pointers that are supposed to own data and use the constructor/destructor idioms (e.g., with an internal ``std::unique_ptr``) to keep things clean. + +The data layout for data that only refers is as follows:: + + | T* | + ^-sizeof(T*) bytes-^ + +That is it. No destruction semantics need to be called. + +For ``std::unique_ptr`` and ``std::shared_ptr`` +-------------------------------------------------------- + +These are classified as :ref:`"unique usertypes"`, and have a special metatable for them as well. The special metatable is either generated when you add the usertype to Lua using :ref:`set_usertype` or when you first push one of these special types. In addition to the data, a deleter function that understands the following layout is injected into the usertype. + +The data layout for these kinds of types is as follows:: + + | T* | void(*)(void*) function_pointer | T | + ^-sizeof(T*) bytes-^-sizeof(void(*)(void*)) bytes, deleter-^- sizeof(T) bytes, actal data -^ + +Note that we put a special deleter function before the actual data. This is because the custom deleter must know where the offset to the data is, not the rest of the library. Sol just needs to know about ``T*`` and the userdata (and userdata metatable) to work, everything else is for preserving construction / destruction semantics. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/api/var.rst b/3rdparty/sol2/docs/source/api/var.rst new file mode 100644 index 00000000000..9e9bcec57d9 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/var.rst @@ -0,0 +1,49 @@ +var +=== +For hooking up static / global variables to Lua usertypes +--------------------------------------------------------- + +The sole purpose of this tagging type is to work with :doc:`usertypes` to provide ``my_class.my_static_var`` access, and to also provide reference-based access as well. + +.. code-block:: cpp + + #include + + struct test { + static int muh_variable; + }; + int test::muh_variable = 25; + + + int main () { + sol::state lua; + lua.open_libraries(); + lua.new_usertype("test", + "direct", sol::var(2), + "global", sol::var(test::muh_variable), + "ref_global", sol::var(std::ref(test::muh_variable)) + ); + + int direct_value = lua["test"]["direct"]; + // direct_value == 2 + + int global = lua["test"]["global"]; + // global == 25 + int global2 = lua["test"]["ref_global"]; + // global2 == 25 + + test::muh_variable = 542; + + global = lua["test"]["global"]; + // global == 25 + // global is its own memory: was passed by value + + global2 = lua["test"]["ref_global"]; + // global2 == 542 + // global2 was passed through std::ref + // global2 holds a reference to muh_variable + // if muh_variable goes out of scope or is deleted + // problems could arise, so be careful! + + return 0; + } diff --git a/3rdparty/sol2/docs/source/api/variadic_args.rst b/3rdparty/sol2/docs/source/api/variadic_args.rst new file mode 100644 index 00000000000..5d3e0c10282 --- /dev/null +++ b/3rdparty/sol2/docs/source/api/variadic_args.rst @@ -0,0 +1,49 @@ +variadic_args +============= +transparent argument to deal with multiple parameters to a function +------------------------------------------------------------------- + + +.. code-block:: cpp + + struct variadic_args; + +This class is meant to represent every single argument at its current index and beyond in a function list. It does not increment the argument count and is thus transparent. You can place it anywhere in the argument list, and it will represent all of the objects in a function call that come after it, whether they are listed explicitly or not. + +``variadic_args`` also has ``begin()`` and ``end()`` functions that return (almost) random-acess iterators. These return a proxy type that can be implicitly converted, much like the :doc:`table proxy type`. + +.. code-block:: cpp + :linenos: + + #include + + int main () { + + sol::state lua; + + // Function requires 2 arguments + // rest can be variadic, but: + // va will include everything after "a" argument, + // which means "b" will be part of the varaidic_args list too + // at position 0 + lua.set_function("v", [](int a, sol::variadic_args va, int b) { + int r = 0; + for (auto v : va) { + int value = v; // get argument out (implicit conversion) + // can also do int v = va.get(i); with index i + r += value; + } + // Only have to add a, b was included + return r + a; + }); + + lua.script("x = v(25, 25)"); + lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); + lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); + // will error: not enough arguments + //lua.script("x4 = v(1)"); + + lua.script("print(x)"); // 50 + lua.script("print(x2)"); // 600 + lua.script("print(x3)"); // 21 + } diff --git a/3rdparty/sol2/docs/source/benchmarks.rst b/3rdparty/sol2/docs/source/benchmarks.rst new file mode 100644 index 00000000000..f85277b6df1 --- /dev/null +++ b/3rdparty/sol2/docs/source/benchmarks.rst @@ -0,0 +1,94 @@ +benchmarks +========== +because somebody is going to ask eventually... +---------------------------------------------- + + +Here are measurements of the *overhead that libraries impose around the Lua C API*: that is, the cost of abstracting / wrapping the plain Lua C API. Measurements are (at the time of writing) done with all libraries compiled against a DLL version of Lua 5.3.3 to make sure each Lua call has the same overhead between libraries (no Link Time Optimizations or other static library optimizations). + +These are some informal and formal benchmarks done by both the developers of sol and other library developers / users. We leave you to interpret the data as you see fit. + +* `lua_binding_benchmarks`_ by satoren (developer of `kaguya`_) (`Sol`_ is the "sol2" entry) +* `lua-bench`_ by ThePhD (developer of `Sol`_) + +As of the writing of this documentation (August 12th, 2016), :doc:`Sol` (Sol2) seems to take the cake in most categories for speed! Below are some graphs from `lua-bench`_. You can read the benchmarking code there if you think something was done wrong, and submit a pull requests or comment on something to make sure that ThePhD is being honest about his work. All categories are the performance of things described at the top of the :doc:`feature table`. + +Note that Sol here makes use of its more performant variants (see :doc:`c_call`), and ThePhD also does his best to make use of the most performant variants for other frameworks by disabling type checks where possible as well (Thanks to Liam Devine of OOLua for explaining how to turn off type checks in OOLua). + +Bars go up to the average execution time. Lower is better. Reported times are for the desired operation run through `nonius`_. Results are sorted from top to bottom by best to worst. Note that there are error bars to show potential variance in performance: generally, same-sized errors bars plus very close average execution time implies no significant difference in speed, despite the vastly different abstraction techniques used. + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20function%20calls.png + :alt: bind several member functions to an object and call them in Lua code + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20variable.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20variable.png + :alt: bind a variable to an object and call it in Lua code + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20member%20variable.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20many%20member%20variables.png + :alt: bind MANY variables to an object and call it in Lua code + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function%20through%20lua.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function%20through%20lua.png + :alt: retrieve a C function bound in Lua and call it from C++ + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20stateful%20c%20function.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20stateful%20c%20function.png + :alt: bind a stateful C function (e.g., a mutable lambda), retrieve it, and call it from C++ + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20c%20function.png + :alt: call a C function through Lua code + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20lua%20function.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20lua%20function.png + :alt: retrieve a plain Lua function and call it from C++ + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20multi%20return.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20multi%20return.png + :alt: return mutliple objects from C++ using std::tuple or through a library-defined mechanism + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20get.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20get.png + :alt: retrieve a value from the global table + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20set.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20global%20set.png + :alt: set a value into the global table + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20get.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20get.png + :alt: measures the cost of doing consecutive lookups into a table that exists from C++; some libraries fail here because they do not do lazy evaluation or chaining properly + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20get.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20get.png + :alt: measures the cost of retrieving a value from a table in C++; this nests 1 level so as to not be equivalent to any measured global table get optimzations + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20set.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20chained%20set.png + :alt: measures the cost of doing consecutive lookups into a table that exists from C++ and setting the final value; some libraries fail here because they do not do lazy evaluation or chaining properly + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20set.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20table%20set.png + :alt: measures the cost of setting a value into a table in C++; this nests 1 level so as to not be equivalent to any measured global table set optimzations + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20return%20userdata.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20return%20userdata.png + :alt: bind a C function which returns a custom class by-value and call it through Lua code + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20get%20optional.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20get%20optional.png + :alt: retrieve an item from a table that does not exist in Lua and check for its existence (testing the cost of the failure case) + +.. image:: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20base%20from%20derived.png + :target: https://raw.githubusercontent.com/ThePhD/lua-bench/master/lua%20-%20results/lua%20bench%20graph%20-%20base%20from%20derived.png + :alt: retrieve base class pointer out of Lua without knowing exact derived at compile-time, and have it be correct for multiple-inheritance + + + +.. _lua-bench: https://github.com/ThePhD/lua-bench +.. _lua_binding_benchmarks: http://satoren.github.io/lua_binding_benchmark/ +.. _kaguya: https://github.com/satoren/kaguya +.. _Sol: https://github.com/ThePhD/sol2 +.. _nonius: https://github.com/rmartinho/nonius/ diff --git a/3rdparty/sol2/docs/source/cmake.rst b/3rdparty/sol2/docs/source/cmake.rst new file mode 100644 index 00000000000..2d9e378d7e6 --- /dev/null +++ b/3rdparty/sol2/docs/source/cmake.rst @@ -0,0 +1,54 @@ +CMake Script +============ + +Thanks to `Kevin Brightwell`_, you can drop this CMake Script into your CMake Projects to have Sol part of one of its builds: + +.. code-block:: cmake + :caption: CMake Build Script + :name: cmake-build-script + + # Needed for ExternalProject_Add() + include(ExternalProject) + + # Needed for building single header for sol2 + find_package(PythonInterp 3 REQUIRED) + + # Configuration data for What sol2 version to use and where to put it + set(SOL2_TAG v2.5.6) + set(SOL2_HPP "${CMAKE_BINARY_DIR}/include/sol.hpp") + + # Download and "install" sol2 + ExternalProject_add( + sol2 + PREFIX ${VENDOR_PATH} # Set this value yourself + + GIT_REPOSITORY "https://github.com/ThePhD/sol2.git" + GIT_TAG ${SOL2_TAG} + + # No CMake commands to run, so tell CMake not to configure + CONFIGURE_COMMAND "" + + # Generate the single header and put it in ${SOL2_HPP} + BINARY_DIR ${VENDOR_PREFIX}/src/sol2 + BUILD_COMMAND + ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/include + COMMAND + ${PYTHON_EXECUTABLE} ./single.py -o "${SOL2_HPP}" + + # No install or test command for the library + INSTALL_COMMAND "" + TEST_COMMAND "") + + # Conditionally turn on SOL_CHECK_ARGUMENTS if using Debug mode + if (CMAKE_BUILD_TYPE MATCHES "[Dd]ebug") + if (VERBOSE) + message(STATUS "Turning on SOL_CHECK_ARGUMENTS in Debug mode.") + endif() + add_definitions(-DSOL_CHECK_ARGUMENTS) + endif() + + # Make sure sol2 is found as a system directory + include_directories(SYSTEM ${CMAKE_BINARY_DIR}/include) + + +.. _Kevin Brightwell: https://github.com/ThePhD/sol2/issues/89 diff --git a/3rdparty/sol2/docs/source/codecvt.rst b/3rdparty/sol2/docs/source/codecvt.rst new file mode 100644 index 00000000000..ff901edea1e --- /dev/null +++ b/3rdparty/sol2/docs/source/codecvt.rst @@ -0,0 +1,8 @@ +std::(w/u16/u32)string support +============================== +because this is surprisingly hard using standard C++ +---------------------------------------------------- + +Individuals using Visual Studio 2015, or on Windows with the VC++ and MinGW compilers (possibly Clang++ on Windows as well) have ```` headers, and thusly Sol will attempt to include it. Individuals on GC 4.9.x, Clang 3.5.x, Clang 3.6.x do not seem to have ```` shipped with the standard library that comes with installation of these compilers. If you want ``std::wstring``, ``std::u16string``, ``std::u32string`` automatic handling then you need to make sure you have those headers and then define ``SOL_CODECVT_SUPPORT``. + +ThePhD did not want this to have to be a thing, but slow implementations and such force their hand. When GCC 7.x comes out, ThePhD will consider removing the effect of defining this macro and leaving support in at all times. diff --git a/3rdparty/sol2/docs/source/conf.py b/3rdparty/sol2/docs/source/conf.py new file mode 100644 index 00000000000..63733022b90 --- /dev/null +++ b/3rdparty/sol2/docs/source/conf.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Sol documentation build configuration file, created by +# sphinx-quickstart on Mon Feb 29 21:49:51 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.todo' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'Sol' +copyright = '2016, ThePhD' +author = 'ThePhD' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '2.14' +# The full version, including alpha/beta/rc tags. +release = '2.14.8' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# The default highlighting language: default is python +highlight_language = 'c++' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "haiku" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ["_themes", ] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (relative to this directory) to use as a favicon of +# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Soldoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'Sol.tex', 'Sol Documentation', + 'ThePhD', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'sol', 'Sol Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'Sol', 'Sol Documentation', + author, 'Sol', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/3rdparty/sol2/docs/source/eevee_code_after.jpg b/3rdparty/sol2/docs/source/eevee_code_after.jpg new file mode 100644 index 0000000000000000000000000000000000000000..33594ce5e0ba84fa576c63c21b0fbd150e1f2517 GIT binary patch literal 9593 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 XhV?=$EoOVB@dbLM{}02~|33d8ncZT> literal 0 HcmV?d00001 diff --git a/3rdparty/sol2/docs/source/exceptions.rst b/3rdparty/sol2/docs/source/exceptions.rst new file mode 100644 index 00000000000..13be8b9a667 --- /dev/null +++ b/3rdparty/sol2/docs/source/exceptions.rst @@ -0,0 +1,51 @@ +exceptions +========== +since somebody is going to ask about it... +------------------------------------------ + +Yes, you can turn off exceptions in Sol with ``#define SOL_NO_EXCEPTIONS`` before including or by passing the command line argument that defines ``SOL_NO_EXCEPTIONS``. We don't recommend it unless you're playing with a Lua distro that also doesn't play nice with exceptions (like non-x64 versions of :ref:`LuaJIT` ). + +If you turn this off, the default `at_panic`_ function :doc:`state` set for you will not throw. Instead, the default Lua behavior of aborting will take place (and give you no chance of escape unless you implement your own at_panic function and decide to try ``longjmp`` out). + +To make this not be the case, you can set a panic function directly with ``lua_atpanic( lua, my_panic_function );`` or when you create the ``sol::state`` with ``sol::state lua(my_panic_function);``. Here's an example ``my_panic_function`` you can have that prints out its errors: + +.. code-block:: cpp + :caption: regular panic function + + #include + #include + + int my_panic_function( lua_State* L ) { + // error message is at the top of the stack + const char* message = lua_tostring(L, -1); + // message can be null, so don't crash + // us with nullptr-constructed-string if it is + std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic"; + // Weee + std::cerr << err << std::endl; + // When this function exits, Lua will exhibit default behavior and abort() + } + + int main () { + sol::state lua(my_panic_function); + } + + +Note that ``SOL_NO_EXCEPTIONS`` will also disable :doc:`protected_function`'s ability to catch C++ errors you throw from C++ functions bound to Lua that you are calling through that API. So, only turn off exceptions in Sol if you're sure you're never going to use exceptions ever. Of course, if you are ALREADY not using Exceptions, you don't have to particularly worry about this and now you can use Sol! + +If there is a place where a throw statement is called or a try/catch is used and it is not hidden behind a ``#ifndef SOL_NO_EXCEPTIONS`` block, please file an issue at `issue`_ or submit your very own pull request so everyone can benefit! + + +.. _LuaJIT and exceptions: + +LuaJIT and exceptions +--------------------- + +It is important to note that a popular 5.1 distribution of Lua, LuaJIT, has some serious `caveats regarding exceptions`_. LuaJIT's exception promises are flaky at best on x64 (64-bit) platforms, and entirely terrible on non-x64 (32-bit, ARM, etc.) platorms. The trampolines we have in place for all functions bound through conventional means in Sol will catch exceptions and turn them into Lua errors so that LuaJIT remainds unperturbed, but if you link up a C function directly yourself and throw, chances are you might have screwed the pooch. + +Testing in `this closed issue`_ that it doesn't play nice on 64-bit Linux in many cases either, especially when it hits an error internal to the interpreter (and does not go through Sol). We do have tests, however, that compile for our continuous integration check-ins that check this functionality across several compilers and platforms to keep you protected and given hard, strong guarantees for what happens if you throw in a function bound by Sol. If you stray outside the realm of Sol's protection, however... Good luck. + +.. _issue: https://github.com/ThePhD/sol2/issues/ +.. _at_panic: http://www.Lua.org/manual/5.3/manual.html#4.6 +.. _caveats regarding exceptions: http://luajit.org/extensions.html#exceptions +.. _this closed issue: https://github.com/ThePhD/sol2/issues/28 \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/features.rst b/3rdparty/sol2/docs/source/features.rst new file mode 100644 index 00000000000..527398af374 --- /dev/null +++ b/3rdparty/sol2/docs/source/features.rst @@ -0,0 +1,258 @@ +features +======== +what does Sol (and other libraries) support? +-------------------------------------------- + +The goal of Sol is to provide an incredibly clean API that provides high performance (comparable or better than the C it was written on) and extreme ease of use. That is, users should be able to say: "this works pretty much how I expected it to." + +For the hard technical components of Lua and its ecosystem we support, here is the full rundown: + +what Sol supports +----------------- + +* Support for Lua 5.1, 5.2, and 5.3. We achieve this through our "doc:`compatibility` header. + +* :doc:`Table` support: setting values, getting values of multiple (different) types + - :doc:`Lazy evaluation` for nested/chained queries + ``table["a"]["b"]["c"] = 24;`` + - Implicit conversion to the types you want + ``double b = table["computed_value"];`` + +* :doc:`Optional` support: setting values, getting values of multiple (different) types + - :doc:`Lazy evaluation` for nested/chained queries + ``optional maybe_number = table["a"]["b"]["invalid_key"];`` + - Turns on safety when you want it: speed when you don't + +* Support for callables (functions, lambdas, member functions) + - Pull out any Lua function with :doc:`sol::function` + ``sol::function fx = table["socket_send"];`` + - Can also set callables into :doc:`operator[] proxies` + ``table["move_dude"] = engine::move_dude;`` + - Safety: use :doc:`sol::protected_function` to catch any kind of error + + ANY kind: C++ exception or Lua erors are trapped and run through the optional ``error_handler`` variable + - *Advanced:* Overloading of a single function so you don't need to do boring typechecks + +* User-Defined Type (:doc:`sol::usertype` in the API) support: + - Set member functions to be called + - Set member variables + - Set variables on a class that are based on setter/getter functions + - Use free-functions that take the Type as a first argument (pointer or reference) + - Support for "Factory" classes that do not expose constructor or destructor + - Modifying memory of userdata in C++ directly affects Lua without copying, and + - Modifying userdata in Lua directly affects C++ references/pointers + ``my_class& a = table["a"];`` + ``my_class* a_ptr = table["a"];`` + - If you want a copy, just use value semantics and get copies: + ``my_class a = table["a"];`` + +* Thread/Coroutine support + - Use, resume, and play with :doc:`coroutines` like regular functions + - Get and use them even on a separate Lua :doc:`thread` + - Monitor status and get check errors + +* *Advanced:* Customizable and extensible to your own types if you override :doc:`getter/pusher/checker` template struct definitions. + + +The Feature Matrix™ +------------------- + +The below feature table checks for the presence of something. It, however, does not actually account for any kind of laborious syntax. + +✔ full support: works as you'd expect (operator[] on tables, etc...) + +~ partial support / wonky support: this means its either supported through some other fashion (not with the desired syntax, serious caveats, etc.). Sometimes means dropping down to use the plain C API (at which point, what was the point of the abstraction?). + +✗ no support: feature doesn't work or, if it's there, it REALLY sucks to use + +Implementation notes from using the libraries are below the tables. + + +category explanations +--------------------- + +Explanations for a few categories are below (rest are self-explanatory). + +* optional: Support for getting an element, or potentially not (and not forcing the default construction of what amounts to a bogus/dead object). Usually comes with ``std(::experimental)::optional``. It's a fairly new class, so a hand-rolled class internal to the library with similar semantics is also acceptable +* tables: Some sort of abstraction for dealing with tables. Ideal support is ``mytable["some_key"] = value``, and everything that the syntax implies. +* table chaining: In conjunction with tables, having the ability to query deeply into tables ``mytable["key1"]["key2"]["key3"]``. Note that this becomes a tripping point for some libraries: crashing if ``"key1"`` doesn't exist while trying to access ``"key2"`` (Sol avoids this specifically when you use ``sol::optional``), and sometimes it's also a heavy performance bottleneck as expressions are not lazy-evaluated by a library. +* arbitrary keys: Letting C++ code use userdata, other tables, integers, etc. as keys for into a table. +* user-defined types (udts): C++ types given form and function in Lua code. +* udts - member functions: C++ member functions on a type, usually callable with ``my_object:foo(1)`` or similar in Lua. +* udts - variables: C++ member variables, manipulated by ``my_object.var = 24`` and friends +* function binding: Support for binding all types of functions. Lambdas, member functions, free functions, in different contexts, etc... +* protected function: Use of ``lua_pcall`` to call a function, which offers error-handling and trampolining (as well as the ability to opt-in / opt-out of this behavior) +* multi-return: returning multiple values from and to Lua (generally through ``std::tuple<...>`` or in some other way) +* variadic/variant argument: being able to accept "anything" from Lua, and even return "anything" to Lua (``object`` abstraction, variadic arguments, etc...) +* inheritance: allowing some degree of subtyping or inheritance on classes / userdata from Lua - this generally means that you can retrieve a base pointer from Lua even if you hand the library a derived pointer +* overloading: the ability to call overloaded functions, matched based on arity or type (``foo( 1 )`` from lua calls a different function then ``foo( "bark" )``). +* Lua thread: basic wrapping of the lua thread API; ties in with coroutine. +* coroutines: allowing a function to be called multiple times, resuming the execution of a Lua coroutine each time + ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| | plain C | luawrapper | lua-intf | luabind | Selene | Sol2 | oolua | lua-api-pp | kaguya | SLB3 | SWIG | luacppinterface | luwra | +| | | | | | | | | | | | | | | ++===========================+=============+============+==========+=========+==========+===========+===========+================+==========+==========+===========+=================+========+ +| optional | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| tables | ~ | ~ | ~ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✗ | ✗ | ~ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| table chaining | ~ | ~ | ~ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✗ | ✗ | ~ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| arbitrary keys | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ~ | ✔ | ✗ | ✗ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| user-defined types (udts) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| udts: member functions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| udts: variables | ~ | ~ | ~ | ~ | ~ | ✔ | ~ | ~ | ~ | ✗ | ✔ | ✗ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| stack abstractions | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✗ | ~ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| lua callables from C(++) | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| function binding | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ~ | ~ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| protected call | ~ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | ~ | ~ | ~ | ~ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| multi-return | ~ | ✗ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| variadic/variant argument | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ~ | ~ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| inheritance | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | ~ | ✔ | ~ | ✔ | ~ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| overloading | ~ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| Lua thread | ~ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| coroutines | ~ | ✗ | ~ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| no-rtti support | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| no-exception support | ✔ | ✗ | ✔ | ~ | ✗ | ✔ | ✔ | ✗ | ✔ | ✔ | ~ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| Lua 5.1 | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| Lua 5.2 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| Lua 5.3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| luajit | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✗ | ✔ | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +| distribution | compile | header | both | compile | header | header | compile | compile | header | compile | generated | compile | header | ++---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ + + +notes on implementations +------------------------ + +Plain C - + +* Obviously you can do anything you want with Plain C, but the effort involved is astronomical in comparison to what frameworks offer +* Does not scale very well (in terms of developer ease of use) +* Compilation (or package manager use) is obviously required for your platform and required to use ANY of these libraries, but that's okay because all libraries need some version of Lua anyways, so you always have this! + +kaguya - + +* member variables are automatically turned into ``obj:x( value )`` to set and ``obj:x()`` to get +* Has optional support +* Inspired coroutine support for Sol +* Library author (satoren) is a nice guy! +* C++11/14, or boostified (which makes it C++03 compatible) +* Class registration is a bit verbose, but not as offensive as OOLua or lua-intf or others + +Sol - + +* One of the few libraries with optional support! +* Basically the fastest in almomst all respects: http://sol2.readthedocs.io/en/latest/benchmarks.html +* Overloading support can get messy with inheritance, see :doc:`here` +* C++14/"C++1y" (-std=c++14, -std=c++1y, =std=c++1z) flags are used (available since GCC 4.9 and Clang 3.5) +* Active issues, active individuals +* Deserves lots of love! + +lua-intf - + +* Can be both header-only or compiled +* Has optional support +* C++11 +* Macro-based registration (strange pseudo-language) +* Fairly fast in most regards +* Registering classes/"modules" in using C++ code is extremely verbose +* In order to chain lookups, one has to do ``mykey.mykey2`` on the ``operator[]`` lookup (e.g., you can't nest them arbitrarily, you have to pre-compose the proper lookup string) (fails miserably for non-string lookups!). +* Not too shabby! + +Selene - + +* member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get +* Registering classes/"modules" using C++ code is extremely verbose, similar to lua-intf's style +* Eats crap when it comes to performance, most of the time (see :doc:`benchmarks`) +* Lots of users (blogpost etc. made it popular), but the Repository is kinda stagnant... + +luawrapper - + +* Takes the approach of writing and reading tables using ``readVariable`` and ``writeVariable`` functions +* C++11, no macros! +* The interface can be clunky (no table-like data structures: most things go though ``readVariable`` / ``writeVariable``) +* Internal Compiler errors in Visual Studio 2015 - submitted a PR to fix it, hopefully it'll get picked up + +SWIG (3.0) - + +* Very comprehensive for binding concepts of C++ (classes, variables, etc.) to Lua +* Helps with literally nothing else (tables, threads, stack abstractions, etc.) +* Not really a good, full-featured Library... +* Requires preprocessing step (but it's not a... TERRIBLY complicated preprocessing step); some boilerplate in writing additional classes that you've already declared + +luacppinterface - + +* The branch that fixes VC++ warnings and introduces some new work has type checker issues, so use the stable branch only +* No member variable support +* Actually has tables (but no operator[]) +* Does not support arbitrary keys + +luabind - + +* One of the older frameworks, but has many people updating it and providing "deboostified" versions +* Strange in-lua keywords and parsing to allow for classes to be written in lua + - not sure if good feature; vendor lock-in to that library to depend on this specific class syntax? +* Comprehensive lua bindings (can even bind "properties") +* There's some code that produces an ICE in Visual C++: I submitted a fix to the library in the hopes that it'll get accepted +* Wonky table support: no basic conversion functions on ``luabind::object``; have to push object then use lua API to get what you want + +lua-api-pp - + +* Compiled, but the recommendation is to add the source files directly to your project +* Userdata registration with thick setup-macros: LUAPP_USERDATA( ... ) plus a bunch of free functions that take a ``T& self`` argument + - You can bind member functions directly but only if you override metatable entries + - Otherwise, COMPLICATED self-registration that makes you wonder why you're using the framework +* You have to create a context and then call it to start accessing the lua state (adding more boilerplate... thanks) + - Thankfully, unlike many libraries, it actually has a Table type that can be used semi-easily. FINALLY +* C++11-ish in some regards +* Sad face, thanks to the way userdata registration is handled + +SLB3 - + +* Old code exported to github from dying google code +* ".NET Style" - to override functionality, derive from class -- boilerplate (isn't that what we're trying to get rid of?) +* Pointers everywhere: ownership semantics unclear +* Piss-poor documentation, ugh! +* Least favorite to work with, for sure! + +oolua - + +* The syntax for this library is thicker than a brick. No, seriously. `Go read the docs`_ +* The worst in terms of how to use it: may have docs, but the DSL is extraordinarily crappy with thick, hard-to-debug/hard-to-error-check macros + - Same problem as lua-api-pp: cannot have the declaration macros anywhere but the toplevel namespace because of template declaration macro +* Supports not having exceptions or rtti turned on (shiny!) +* Poor RAII support: default-construct-and-get style (requires some form of initalization to perform a ``get`` of an object, and it's hard to extend) + - The library author has informed me that he does personally advises individuals do not use the ``Table`` abstraction in OOLua... Do I likewise tell people to consider its table abstractions defunct? +* Member variables are turned into function calls (``get_x`` and ``set_x`` by default) + +luwra - + +* How do you store stateful functors / lambas? So far, no support for such. +* Cannot pull functions without first leaving them on the stack: manual cleanup becomes a thing +* Doesn't understand ``std::function`` conversions and the like (but with some extra code can get it to work) +* Recently improved by a lot: can chain tables and such, even if performance is a bit sad for that use case +* When you do manage to set function calls with the macros they are fast (can a template solution do just as good? Sol is going to find out!) +* No member variable support - get turned into getter/setter functions, similar to kaguya + +.. _Go read the docs: https://oolua.org/docs/index.html diff --git a/3rdparty/sol2/docs/source/index.rst b/3rdparty/sol2/docs/source/index.rst new file mode 100644 index 00000000000..b1ec3a4f276 --- /dev/null +++ b/3rdparty/sol2/docs/source/index.rst @@ -0,0 +1,123 @@ +.. Sol documentation master file, created by + sphinx-quickstart on Mon Feb 29 21:49:51 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. image:: sol.png + :target: https://github.com/ThePhD/sol2 + :alt: sol2 repository + +Sol 2.14 +======== +a fast, simple C++ and Lua Binding +---------------------------------- + +When you need to hit the ground running with Lua and C++, `Sol`_ is the go-to framework for high-performance binding with an easy to use API. + +.. image:: https://travis-ci.org/ThePhD/sol2.svg?branch=develop + :target: https://travis-ci.org/ThePhD/sol2 + :alt: build status + +get going: +---------- + +.. toctree:: + :maxdepth: 1 + :name: mastertoc + + tutorial/all-the-things + tutorial/tutorial-top + features + api/api-top + mentions + benchmarks + performance + safety + exceptions + rtti + codecvt + cmake + licenses + origin + + +"I need feature X, maybe you have it?" +-------------------------------------- +Take a look at the :doc:`Features` page: it links to much of the API. You can also just straight up browse the :doc:`api` or ease in with the :doc:`tutorials`. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker. + + +the basics: +----------- + +.. note:: + More examples can be found in the `examples directory`_ + + +.. code-block:: c++ + :caption: functions + :linenos: + + #include + #include + + int main() { + sol::state lua; + int x = 0; + lua.set_function("beep", [&x]{ ++x; }); + lua.script("beep()"); + assert(x == 1); + + sol::function beep = lua["beep"]; + beep(); + assert(x == 2); + + return 0; + } + + +.. code-block:: c++ + :caption: linking C++ structures to Lua + :linenos: + + #include + #include + + struct vars { + int boop = 0; + + int bop () const { + return boop + 1; + } + }; + + int main() { + sol::state lua; + lua.new_usertype("vars", + "boop", &vars::boop + "bop", &vars::bop); + lua.script("beep = vars.new()\n" + "beep.boop = 1\n" + "bopvalue = beep:bop()"); + + vars& beep = lua["beep"]; + int bopvalue = lua["bopvalue"]; + + assert(beep.boop == 1); + assert(lua.get("beep").boop == 1); + assert(beep.bop() == 2); + assert(bopvalue == 2); + + return 0; + } + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` + +.. _Sol: https://github.com/ThePhD/sol2 +.. _issues: https://github.com/ThePhD/sol2/issues +.. _examples directory: https://github.com/ThePhD/sol2/tree/develop/examples \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/licenses.rst b/3rdparty/sol2/docs/source/licenses.rst new file mode 100644 index 00000000000..f43d97b5e3a --- /dev/null +++ b/3rdparty/sol2/docs/source/licenses.rst @@ -0,0 +1,47 @@ +licenses +======== + +The following licenses cover all of the code in Sol. Spoiler: they're all `MIT`_ and it's safe to use in commercial code: feel free to copy/paste the below right into your own attributions / licenses file. + +Sol - ThePhD/sol2: +------------------ + + The MIT License (MIT) + + Copyright (c) 2013-2016 Rapptz, ThePhD, and contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Lua-compat-5.3 - keplerproject/Lua-compat-5.3: +---------------------------------------------- + + The MIT License (MIT) + + Copyright (c) 2015 Kepler Project. + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Lua - Lua.org: +-------------- + + The MIT License (MIT) + + Copyright © 1994–2015 Lua.org, PUC-Rio. + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + .. _MIT: http://opensource.org/licenses/MIT \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/mentions.rst b/3rdparty/sol2/docs/source/mentions.rst new file mode 100644 index 00000000000..7b920150181 --- /dev/null +++ b/3rdparty/sol2/docs/source/mentions.rst @@ -0,0 +1,50 @@ +mentions +======== +so does anyone cool use this thing...? +-------------------------------------- + +Okay, so the features don't convince you, the documentation doesn't convince you, you want to see what *other* people think about Sol? Well, aside from the well-wishes that come through in the issue tracker, here's a few things floating around about sol2 that I occasionally get pinged about: + +`eevee`_ demonstrating the sheer code reduction by using sol2: + + +.. |before| image:: eevee_code_before.jpg + :target: https://twitter.com/eevee/status/762039984085798913 + :alt: Plain C API + :align: middle + +.. |after| image:: eevee_code_after.jpg + :target: https://twitter.com/eevee/status/762039984085798913 + :alt: Now with sol2! + :align: middle + ++----------+---------+ +| |before| | |after| | ++----------+---------+ + + +* (CppNow) sol2 was mentioned in a comparison to other scripting languages by ChaiScript developer, Jason Turner (@lefticus), at a conference! + - https://github.com/lefticus/presentations/blob/master/HowAndWhyToAddScripting.md +* (CppCast) Showed up in CppCast with Elias Daler! + - https://eliasdaler.github.io/cppcast#read-more + - http://cppcast.com/2016/07/elias-daler/ +* (Eevee) A really nice and neat developer/artist/howaretheysotalented person is attempting to use it for zdoom! + - https://eev.ee/dev/2016/08/07/weekly-roundup-three-big-things/ +* (Twitter) Twitter has some people that link it: + - https://twitter.com/eevee/status/762039984085798913 + - https://twitter.com/thephantomderp/status/762043162835709952 + - https://twitter.com/EliasDaler/status/739082026679173120 + - https://twitter.com/racodslair/status/754031870640267264 +* (Reddit) Posts on reddit about it! + - https://www.reddit.com/r/cpp/comments/4a8gy7/sol2_lua_c_binding_framework/ + - https://www.reddit.com/r/cpp/comments/4x82hd/plain_c_versus_lua_libraries_benchmarking_speed/ +* Somehow landed on a Torque3D thread... + - http://forums.torque3d.org/viewtopic.php?f=32&t=629&p=5246&sid=8e759990ab1ce38a48e896fc9fd62653#p5241 + + +`Tell me about your uses!`_ + +Are you using sol2 for something neat? Want it to be featured here or think it's unfair that ThePhD hasn't found it yet? Well, drop an issue in the repo or send an e-mail! + +.. _Tell me about your uses!: https://github.com/ThePhD/sol2/issues/189 +.. _eevee: https://twitter.com/eevee \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/origin.rst b/3rdparty/sol2/docs/source/origin.rst new file mode 100644 index 00000000000..cc2e3d72467 --- /dev/null +++ b/3rdparty/sol2/docs/source/origin.rst @@ -0,0 +1,28 @@ +origin +====== + +In the beginning, there was Sir Dennis Ritchie. And Ritchie saw the void, and outstretched his hand, and commanded "Let there be water." And lo, it was so, and there was the C. And with the C, other entities dared to venture on the void given form. Lord Bjarne Stroustrup too did outstretch his hands and say "Let there be an abundance." And lo, into the sea was cast a double portion of surplus of all the things that swam. And for a while, it was good. But other entities were still curious about what yet lay undefined, and one such pantheon, PUC-RIO, saw that it fitting to create the moon. And with the waters and sea made and the moon cast in a starry night sky, PUC-RIO and Dennis and Stroustrup saw that they did good. They oversaw the moon and the sea and gave sound council and it grew. But as the time grew, humanity grew... discontent. No longer were the simple fishing rods and the flowing tides and the dark sky enough lit by a pale moon, no matter how miraculously they were made, enough. They sought out more. + +They sought out the light. + +And lo, `Danny Y., Rapptz`_ did stand firm in the sea and cast his hands to the sky and said "Let there be Light!". And in the sky was cast a sun. It was an early sun, a growing sun, and many gathered to its warmth, marveling at a life they never knew. And he saw that it was good... + + +seriously +--------- + +Sol was originally started by many moon cycles ago to interop with Lua and C++. `Rapptz`_ It was very successful and many rejoiced at having an easy to use abstraction on top of the Lua API. Rapptz continued to make a number of great projects and has been busy with other things, so upon seeing the repository grow stagnant and tired in the last very long while (over a year), `ThePhD`_ forked it into Sol2 and rebooted the code with the hopes of reaching the Milestone and the documentation you have today. + +To get to the old repo, head over `here`_. + + +the name +-------- + +Sol means sun. The moon (Lua) needs a sun, because without it only the bleak night of copy-paste programming and off-by-one errors would prevail. + + +.. _here: https://github.com/Rapptz/sol +.. _ThePhD: https://github.com/ThePhD +.. _Danny Y., Rapptz: https://github.com/Rapptz +.. _Rapptz: https://github.com/Rapptz \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/performance.rst b/3rdparty/sol2/docs/source/performance.rst new file mode 100644 index 00000000000..cdfaa9614e6 --- /dev/null +++ b/3rdparty/sol2/docs/source/performance.rst @@ -0,0 +1,15 @@ +getting performance +=================== +things to make Sol as fast as possible +-------------------------------------- + + +As shown by the :doc:`benchmarks`, Sol is very performant with its abstractions. However, in the case where you need every last drop of performance from Sol, a number of tips and API usage tricks will be documented here. PLEASE benchmark / profile your code before you start invoking these, as some of them trade in readability / clarity for performance. + +* If you have a bound function call / bound member function that you are going to call in a very tight, performance-heavy loop, considering using :doc:`sol::c_call` +* It is currently undocumented that usertypes will "inherit" member function / member variables from bound classes, mostly because the semantics are unclear and it is not the most performant (although it is flexible: you can register base classes after / whenever you want in relation to the derived class, provided that derived class has its bases listed). Specifying all member functions / member variables for the usertype constructor / ``new_usertype`` function call and not relying on base lookup will boost performance of member lookup +* Specifying base classes can make getting the usertype out of Sol a bit slower since we have to check and cast; if you know the exact type wherever you're retrieving it, considering not specifying the bases, retrieving the exact type from Sol, and then casting to a base type yourself +* Member variables can sometimes cost an extra lookup to occur within the Lua system (as mentioned :doc:`bottom of the usertype page`); until we find out a safe way around this, member variables will always incur that extra lookup cost + + +That's it as far as different performance options are avilable to make Sol run faster. Again, please make sure to invoke these only when you know Sol is the bottleneck. If you find some form of the performance unacceptable to you, also feel free to open an issue at the github. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/rtti.rst b/3rdparty/sol2/docs/source/rtti.rst new file mode 100644 index 00000000000..91aad3e939b --- /dev/null +++ b/3rdparty/sol2/docs/source/rtti.rst @@ -0,0 +1,14 @@ +run-time type information (rtti) +================================ +because somebody's going to want to shut this off, too... +--------------------------------------------------------- + +Sol does not use RTTI anymore. + +*THE BELOW IS NO LONGER NEEDED.* + +Not compiling with C++'s run-time type information? Do a ``#define SOL_NO_RTII`` before you include ``sol.hpp`` or define ``SOL_NO_RTTI`` on your command line. Be sure to understand the :ref:`implications` of doing so if you also turn off exceptions. + +If you come across bugs or can't compile because there's a stray `typeid` or `typeinfo` that wasn't hidden behind a ``#ifndef SOL_NO_RTTI``, please file `an issue`_ or even make a pull request so it can be fixed for everyone. + +.. _an issue: https://github.com/ThePhD/sol2/issues \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/safety.rst b/3rdparty/sol2/docs/source/safety.rst new file mode 100644 index 00000000000..8e01113f2a1 --- /dev/null +++ b/3rdparty/sol2/docs/source/safety.rst @@ -0,0 +1,22 @@ +safety +====== + +Sol was designed to be correct and fast, and in the pursuit of both uses the regular ``lua_to{x}`` functions of Lua rather than the checking versions (``lua_check{X}``) functions. The API defaults to paranoidly-safe alternatives if you have a ``#define SOL_CHECK_ARGUMENTS`` before you include Sol, or if you pass the ``SOL_CHECK_ARGUMENTS`` define on the build command for your build system. By default, it is off and remains off unless you define this, even in debug mode. The same goes for ``#define SOL_SAFE_USERTYPE``. + +Note that you can obtain safety with regards to functions you bind by using the :doc:`protect` wrapper around function/variable bindings you set into Lua. + +``SOL_SAFE_USERTYPE`` triggers the following change: + * If the userdata to a usertype function is nil, will trigger an error instead of letting things go through and letting the system segfault. + +``SOL_CHECK_ARGUMENTS`` triggers the following changes: + * ``sol::stack::get`` (used everywhere) defaults to using ``sol::stack::check_get`` and dereferencing the argument. It uses ``sol::type_panic`` as the handler if something goes wrong. + * ``sol::stack::call`` and its variants will, if no templated boolean is specified, check all of the arguments for a function call. + * If ``SOL_SAFE_USERTYPE`` is not defined, it gets defined to turn being on. + +Remember that if you want these features, you must explicitly turn them on. Additionally, you can have basic boolean checks when using the API by just converting to a :doc:`sol::optional\` when necessary. Tests are compiled with this on to ensure everythign is going as expected. + +Finally, some warnings that may help with errors when working with Sol: + +.. warning:: + + Do NOT save the return type of a :ref:`function_result` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. See :ref:`here`. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/sol.png b/3rdparty/sol2/docs/source/sol.png new file mode 100644 index 0000000000000000000000000000000000000000..eedee2ed3d039267227ef7e9fbf0d33ab5d627b5 GIT binary patch literal 14482 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 literal 0 HcmV?d00001 diff --git a/3rdparty/sol2/docs/source/sol.psd b/3rdparty/sol2/docs/source/sol.psd new file mode 100644 index 0000000000000000000000000000000000000000..84865d5198be3b0da7ea731c72fa1dd215f7b34d GIT binary patch literal 121930 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/``#include "sol.hpp"`` somewhere in your code. Sol is header-only, so you don't need to compile anything. + +opening a state +--------------- + +.. code-block:: cpp + + int main (int argc, char* argv[]) { + sol::state lua; + // open some common libraries + lua.open_libraries(sol::lib::base, sol::lib::package); + lua.script( "print('bark bark bark!')" ); + } + + +sol::state on lua_State* +------------------------ + +For your system/game that already has lua, but you'd like something nice: + +.. code-block:: cpp + + int pre_existing_system( lua_State* L ) { + sol::state_view lua(L); + lua.script( "print('bark bark bark!')" ); + return 0; + } + + +running lua code +---------------- + +.. code-block:: cpp + + sol::state lua; + // load and execute from string + lua.script("a = 'test'"); + // load and execute from file + lua.script_file("path/to/luascript.lua"); + + // run a script, get the result + int value = lua.script("return 54"); + // value == 54 + + // load file without execute + sol::load_result script1 = lua.load_file("path/to/luascript.lua"); + script1(); //execute + // load string without execute + sol::load_result script2 = lua.load("a = 'test'"); + script2(); //execute + + sol::load_result script3 = lua.load("return 24"); + int value2 = script3(); // execute, get return value + // value2 == 24 + + +set and get variables +--------------------- + +You can set/get everything. + +.. code-block:: cpp + + sol::lua_state lua; + + lua.open_libraries(sol::lib::base); + + // integer types + lua.set("number", 24); + + // floating point numbers + lua["number2"] = 24.5; + + // string types + lua["important_string"] = "woof woof"; + + // non-recognized types is stored as userdata + // is callable, therefore gets stored as a function + lua["a_function"] = [](){ return 100; }; + + // make a table + lua["some_table"] = lua.create_table_wth("value", 24); + + +Equivalent to loading a lua file with: + +.. code-block:: lua + + number = 24 + number2 = 24.5 + important_string = "woof woof" + a_function = function () return 100 end + some_table = { value = 24 } + +Retrieve these variables using this syntax: + +.. code-block:: cpp + + // implicit conversion + int number = lua["number"]; + + // explicit get + auto number2 = lua.get("number2"); + + // strings too + std::string important_string = lua["important_string"]; + + // dig into a table + int value = lua["value"]["value"]; + + // get a function + sol::function a_function = lua["a_function"]; + int value_is_100 = a_function(); + + // get a std::function + std::function a_std_function = lua["a_function"]; + int value_is_still_100 = a_std_function(); + +Retrieve Lua types using ``object`` and other ``sol::`` types. + +.. code-block:: cpp + + sol::state lua; + + // ... everything from before + + sol::object number_obj = lua.get( "number" ); + // sol::type::number + sol::type t1 = number_obj.get_type(); + + sol::object function_obj = lua[ "a_function" ]; + // sol::type::function + sol::type t2 = function_obj.get_type(); + bool is_it_really = function_obj.is(); // true + + // will not contain data + sol::optional check_for_me = lua["a_function"]; + + +You can erase things by setting it to ``nullptr`` or ``sol::nil``. + +.. code-block:: cpp + + sol::state lua; + + lua.script("exists = 250"); + + int first_try = lua.get_or( 322 ); + // first_try == 250 + + lua.set("exists", sol::nil); + + int second_try = lua.get_or( 322 ); + // second_try == 322 + + +Note that if its a :doc:`userdata/usertype<../api/usertype>` for a C++ type, the destructor will run only when the garbage collector deems it appropriate to destroy the memory. If you are relying on the destructor being run when its set to ``sol::nil``, you're probably committing a mistake. + +tables +------ + +:doc:`sol::state<../api/state>` is a table too. + +.. code-block:: cpp + + sol::state lua; + + // Raw string literal for easy multiline + lua.script( R"( + abc = { [0] = 24 } + def = { + ghi = { + bark = 50, + woof = abc + } + } + )" + ); + + sol::table abc = lua["abc"]; + sol::table def = lua["def"]; + sol::table ghi = lua["def"]["ghi"]; + + int bark1 = def["ghi"]["bark"]; + int bark2 = lua["def"]["ghi"]["bark"]; + // bark1 == bark2 == 50 + + int abcval1 = abc[0]; + int abcval2 = ghi["woof"][0]; + // abcval1 == abcval2 == 24 + +If you're going deep, be safe: + +.. code-block:: cpp + + sol::state lua; + + sol::optional will_not_error = lua["abc"]["DOESNOTEXIST"]["ghi"]; + // will_not_error == sol::nullopt + int will_not_error2 = lua["abc"]["def"]["ghi"]["jklm"].get_or(25); + // is 25 + + // if you don't go safe, + // will throw (or do at_panic if no exceptions) + int aaaahhh = lua["abc"]["hope_u_liek_crash"]; + + +make tables +----------- + +Make some: + +.. code-block:: cpp + + sol::state lua; + + lua["abc"] = lua.create_table_with( + 0, 24 + ); + + lua.create_named_table("def", + "ghi", lua.create_table_with( + "bark", 50, + // can reference other existing stuff too + "woof", lua["abc"] + ) + ); + +Equivalent Lua code: + +.. code-block:: lua + + abc = { [0] = 24 } + def = { + ghi = { + bark = 50, + woof = abc + } + } + + +You can put anything you want in tables as values or keys, including strings, numbers, functions, other tables. + +Note that this idea that things can be nested is important and will help later when you get into :ref:`namespacing`. + + +functions +--------- + +They're great. Use them: + +.. code-block:: cpp + + sol::state lua; + + lua.script("function f (a, b, c, d) return 1 end"); + lua.script("function g (a, b) return a + b end"); + + // fixed signature std::function<...> + std::function stdfx = lua["f"]; + // sol::function is often easier: + // takes a variable number/types of arguments... + sol::function fx = lua["f"]; + + int is_one = stdfx(1, 34.5, 3, "bark"); + int is_also_one = fx(1, "boop", 3, "bark"); + + // call through operator[] + int is_three = lua["g"](1, 2); + // is_three == 3 + double is_4_8 = lua["g"](2.4, 2.4); + // is_4_8 == 4.8 + +If you need to protect against errors and parser problems and you're not ready to deal with Lua's `longjmp` problems (if you compiled with C), use :doc:`sol::protected_function<../api/protected_function>`. + +You can bind member variables as functions too, as well as all KINDS of function-like things: + +.. code-block:: cpp + + void some_function () { + std::cout << "some function!" << std::endl; + } + + void some_other_function () { + std::cout << "some other function!" << std::endl; + } + + struct some_class { + int variable = 30; + + double member_function () { + return 24.5; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // put an instance of "some_class" into lua + // (we'll go into more detail about this later + // just know here that it works and is + // put into lua as a userdata + lua.set("sc", some_class()); + + // binds a plain function + lua["f1"] = some_function; + lua.set_function("f2", &some_other_function); + + // binds just the member function + lua["m1"] = &some_class::member_function; + + // binds the class to the type + lua.set_function("m2", &some_class::member_function, some_class{}); + + // binds just the member variable as a function + lua["v1"] = &some_class::variable; + + // binds class with member variable as function + lua.set_function("v2", &some_class::variable, some_class{}); + +The lua code to call these things is: + +.. code-block:: lua + + f1() -- some function! + f2() -- some other function! + + -- need class instance if you don't bind it with the function + print(m1(sc)) -- 24.5 + -- does not need class instance: was bound to lua with one + print(m2()) -- 24.5 + + -- need class instance if you + -- don't bind it with the function + print(v1(sc)) -- 30 + -- does not need class instance: + -- it was bound with one + print(v2()) -- 30 + + -- can set, still + -- requires instance + v1(sc, 212) + -- can set, does not need + -- class instance: was bound with one + v2(254) + + print(v1(sc)) -- 212 + print(v2()) -- 254 + +Can use ``sol::readonly( &some_class::variable )`` to make a variable readonly and error if someone tries to write to it. + + +self call +--------- + +You can pass the 'self' argument through C++ to emulate 'member function' calls in Lua. + +.. code-block:: cpp + + sol::state lua; + + lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table); + + // a small script using 'self' syntax + lua.script(R"( + some_table = { some_val = 100 } + + function some_table:add_to_some_val(value) + self.some_val = self.some_val + value + end + + function print_some_val() + print("some_table.some_val = " .. some_table.some_val) + end + )"); + + // do some printing + lua["print_some_val"](); + // 100 + + sol::table self = lua["some_table"]; + self["add_to_some_val"](self, 10); + lua["print_some_val"](); + + + +multiple returns from lua +------------------------- + +.. code-block:: cpp + + sol::state lua; + + lua.script("function f (a, b, c) return a, b, c end"); + + std::tuple result; + result = lua["f"](100, 200, 300); + // result == { 100, 200, 300 } + int a, int b; + std::string c; + sol::tie( a, b, c ) = lua["f"](100, 200, "bark"); + // a == 100 + // b == 200 + // c == "bark" + + +multiple returns to lua +----------------------- + +.. code-block:: cpp + + sol::state lua; + + lua["f"] = [](int a, int b, sol::object c) { + // sol::object can be anything here: just pass it through + return std::make_tuple( a, b, c ); + }; + + std::tuple result = lua["f"](100, 200, 300); + // result == { 100, 200, 300 } + + std::tuple result2; + result2 = lua["f"](100, 200, "BARK BARK BARK!") + // result2 == { 100, 200, "BARK BARK BARK!" } + + int a, int b; + std::string c; + sol::tie( a, b, c ) = lua["f"](100, 200, "bark"); + // a == 100 + // b == 200 + // c == "bark" + + +C++ classes from C++ +-------------------- + +Everything that is not a: + + * primitive type: ``bool``, ``char/short/int/long/long long``, ``float/double`` + * string type: ``std::string``, ``const char*`` + * function type: function pointers, ``lua_CFunction``, ``std::function``, :doc:`sol::function/sol::protected_function<../api/function>`, :doc:`sol::coroutine<../api/coroutine>`, member variable, member function + * designated sol type: :doc:`sol::table<../api/table>`, :doc:`sol::thread<../api/thread>`, :doc:`sol::error<../api/error>`, :doc:`sol::object<../api/object>` + * transparent argument type: :doc:`sol::variadic_arg<../api/variadic_args>`, :doc:`sol::this_state<../api/this_state>` + * usertype class: :doc:`sol::usertype<../api/usertype>` + +Is set as a :doc:`userdata + usertype<../api/usertype>`. + +.. code-block:: cpp + + struct Doge { + int tailwag = 50; + } + + Doge dog{}; + + // Copy into lua: destroyed by Lua VM during garbage collection + lua["dog"] = dog; + // OR: move semantics - will call move constructor if present instead + // Again, owned by Lua + lua["dog"] = std::move( dog ); + lua["dog"] = Doge{}; + lua["dog"] = std::make_unique(); + lua["dog"] = std::make_shared(); + // Identical to above + + Doge dog2{}; + + lua.set("dog", dog2); + lua.set("dog", std::move(dog2)); + lua.set("dog", Doge{}); + lua.set("dog", std::unique_ptr(new Doge())); + lua.set("dog", std::shared_ptr(new Doge())); + +``std::unique_ptr``/``std::shared_ptr``'s reference counts / deleters will :doc:`be respected<../api/unique_usertype_traits>`. If you want it to refer to something, whose memory you know won't die in C++, do the following: + +.. code-block:: cpp + + struct Doge { + int tailwag = 50; + } + + sol::state lua; + lua.open_libraries(sol::lib::base); + + Doge dog{}; // Kept alive somehow + + // Later... + // The following stores a reference, and does not copy/move + // lifetime is same as dog in C++ + // (access after it is destroyed is bad) + lua["dog"] = &dog; + // Same as above: respects std::reference_wrapper + lua["dog"] = std::ref(dog); + // These two are identical to above + lua.set( "dog", &dog ); + lua.set( "dog", std::ref( dog ) ); + +Get userdata in the same way as everything else: + +.. code-block:: cpp + + struct Doge { + int tailwag = 50; + } + + sol::state lua; + lua.open_libraries(sol::lib::base); + + Doge& dog = lua["dog"]; // References Lua memory + Doge* dog_pointer = lua["dog"]; // References Lua memory + Doge dog_copy = lua["dog"]; // Copies, will not affect lua + +Note that you can change the data of usertype variables and it will affect things in lua if you get a pointer or a reference from Sol: + +.. code-block:: cpp + + struct Doge { + int tailwag = 50; + } + + sol::state lua; + lua.open_libraries(sol::lib::base); + + Doge& dog = lua["dog"]; // References Lua memory + Doge* dog_pointer = lua["dog"]; // References Lua memory + Doge dog_copy = lua["dog"]; // Copies, will not affect lua + + dog_copy.tailwag = 525; + // Still 50 + lua.script("assert(dog.tailwag == 50)"); + + dog.tailwag = 100; + // Now 100 + lua.script("assert(dog.tailwag == 100)"); + + +C++ classes put into Lua +------------------------ + +See this :doc:`section here` and after perhaps see if :doc:`simple usertypes suit your needs<../api/simple_usertype>`. Also check out some `a basic example`_, `special functions`_ and `initializers`_, + + +.. _namespacing: + +namespacing +----------- + +You can emulate namespacing by having a table and giving it the namespace names you want before registering enums or usertypes: + +.. code-block:: cpp + + struct my_class { + int b = 24; + + int f () const { + return 24; + } + + void g () { + ++b; + } + }; + + sol::state lua; + lua.open_libraries(); + + // set up table + sol::table bark = lua.create_named_table("bark"); + + bark.new_usertype( "my_class", + "f", &my_class::f, + "g", &my_class::g + ); // the usual + + // 'bark' namespace + lua.script("obj = bark.my_class.new()" ); + lua.script("obj:g()"); + my_class& obj = lua["obj"]; + // obj.b == 25 + + +This technique can be used to register namespace-like functions and classes. It can be as deep as you want. Just make a table and name it appropriately, in either Lua script or using the equivalent Sol code. As long as the table FIRST exists (e.g., make it using a script or with one of Sol's methods or whatever you like), you can put anything you want specifically into that table using :doc:`sol::table's<../api/table>` abstractions. + +advanced +-------- + +Some more advanced things you can do/read about: + * :doc:`metatable manipulations<../api/metatable_key>` allow a user to change how indexing, function calls, and other things work on a single type. + * :doc:`ownership semantics` are described for how lua deals with (raw) pointers. + * :doc:`stack manipulation<../api/stack>` to safely play with the stack. You can also define customization points for ``stack::get``/``stack::check``/``stack::push`` for your type. + * :doc:`make_reference/make_object convenience function<../api/make_reference>` to get the same benefits and conveniences as the low-level stack API but put into objects you can specify. + * :doc:`stack references<../api/stack_reference>` to have zero-overhead Sol abstractions while not copying to the Lua registry. + * :doc:`unique usertype traits<../api/unique_usertype_traits>` allows you to specialize handle/RAII types from other frameworks, like boost, and Unreal, to work with Sol. + * :doc:`variadic arguments<../api/variadic_args>` in functions with ``sol::variadic_args``. + * :doc:`this_state<../api/this_state>` to get the current ``lua_State*``. + * :doc:`resolve<../api/resolve>` overloads in case you have overloaded functions; a cleaner casting utility. + +.. _a basic example: https://github.com/ThePhD/sol2/blob/develop/examples/usertype.cpp +.. _special functions: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_special_functions.cpp +.. _initializers: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_initializers.cpp + diff --git a/3rdparty/sol2/docs/source/tutorial/customization.rst b/3rdparty/sol2/docs/source/tutorial/customization.rst new file mode 100644 index 00000000000..31fcad46568 --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/customization.rst @@ -0,0 +1,114 @@ +adding your own types +===================== + +Sometimes, overriding Sol to make it handle certain ``struct``'s and ``class``'es as something other than just userdata is desirable. The way to do this is to take advantage of the 4 customization points for Sol. These are ``sol::lua_size``, ``sol::stack::pusher``, ``sol::stack::getter``, ``sol::stack::checker``. + +These are template class/structs, so you'll override them using a technique C++ calls *class/struct specialization*. Below is an example of a struct that gets broken apart into 2 pieces when going in the C++ --> Lua direction, and then pulled back into a struct when going in the Lua --> C++: + +.. code-block:: cpp + :caption: two_things.hpp + :name: customization-overriding + + #include + + struct two_things { + int a; + bool b; + }; + + namespace sol { + + // First, the expected size + // Specialization of a struct + // We expect 2, so use 2 + template <> + struct lua_size : std::integral_constant {}; + + // Now, specialize various stack structures + namespace stack { + + template <> + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + // indices can be negative to count backwards from the top of the stack, + // rather than the bottom up + // to deal with this, we adjust the index to + // its absolute position using the lua_absindex function + int absolute_index = lua_absindex(L, index); + // Check first and second second index for being the proper types + bool success = stack::check(L, absolute_index - 1, handler) + && stack::check(L, absolute_index, handler); + tracking.use(2); + return success; + } + }; + + template <> + struct getter { + static two_things get(lua_State* L, int index, record& tracking) { + int absolute_index = lua_absindex(L, index); + // Get the first element + int a = stack::get(L, absolute_index - 1); + // Get the second element, + // in the +1 position from the first + bool b = stack::get(L, absolute_index); + // we use 2 slots, each of the previous takes 1 + tracking.use(2); + return two_things{ a, b }; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, const two_things& things) { + int amount = stack::push(L, things.a); + // amount will be 1: int pushes 1 item + amount += stack::push(L, things.b); + // amount 2 now, since bool pushes a single item + // Return 2 things + return amount; + } + }; + + } + } + + +This is the base formula that you can follow to extend to your own classes. Using it in the rest of the library should then be seamless: + +.. code-block:: cpp + :caption: customization: using it + :name: customization-using + + #include + #include + + int main () { + + sol::state lua; + + // Create a pass-through style of function + lua.script("function f ( a, b ) return a, b end"); + + // get the function out of Lua + sol::function f = lua["f"]; + + two_things things = f(two_things{24, true}); + // things.a == 24 + // things.b == true + + return 0; + } + + +And that's it! + +A few things of note about the implementation: First, there's an auxiliary parameter of type :doc:`sol::stack::record<../api/stack>` for the getters and checkers. This keeps track of what the last complete operation performed. Since we retrieved 2 members, we use ``tracking.use(2);`` to indicate that we used 2 stack positions (one for ``bool``, one for ``int``). The second thing to note here is that we made sure to use the ``index`` parameter, and then proceeded to add 1 to it for the next one. + +You can make something pushable into Lua, but not get-able in the same way if you only specialize one part of the system. If you need to retrieve it (as a return using one or multiple values from Lua), you should specialize the ``sol::stack::getter`` template class and the ``sol::stack::checker`` template class. If you need to push it into Lua at some point, then you'll want to specialize the ``sol::stack::pusher`` template class. The ``sol::lua_size`` template class trait needs to be specialized for both cases, unless it only pushes 1 item, in which case the default implementation will assume 1. + + +In general, this is fine since most getters/checkers only use 1 stack point. But, if you're doing more complex nested classes, it would be useful to use ``tracking.last`` to understand how many stack indices the last getter/checker operation did and increment it by ``index + tracking.last`` after using a ``stack::check<..>( L, index, tracking)`` call. + +You can read more about the structs themselves :ref:`over on the API page for stack`, and if there's something that goes wrong or you have anymore questions, please feel free to drop a line on the Github Issues page or send an e-mail! \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst b/3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst new file mode 100644 index 00000000000..dac47dfb228 --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/cxx-in-lua.rst @@ -0,0 +1,138 @@ +C++ in Lua +========== + +Using user defined types ("usertype"s, or just "udt"s) is simple with Sol. If you don't call any member variables or functions, then you don't even have to 'register' the usertype at all: just pass it through. But if you want variables and functions on your usertype inside of Lua, you need to register it. We're going to give a short example here that includes a bunch of information on how to work with things. + +Take this ``player`` struct in C++ in a header file: + +.. code-block:: cpp + :caption: test_player.hpp + + struct player { + public: + int bullets; + int speed; + + player() + : player(3, 100) { + + } + + player(int ammo) + : player(ammo, 100) { + + } + + player(int ammo, int hitpoints) + : bullets(ammo), hp(hitpoints) { + + } + + void boost () { + speed += 10; + } + + bool shoot () { + if (bullets < 1) + return false; + --bullets; + return true; + } + + void set_hp(int value) { + hp = value; + } + + int get_hp() const { + return hp; + } + + private: + int hp; + }; + + +It's a fairly minimal class, but we don't want to have to rewrite this with metatables in Lua. We want this to be part of Lua easily. The following is the Lua code that we'd like to have work properly: + +.. code-block:: lua + :caption: player_script.lua + + -- call single argument integer constructor + p1 = player.new(2) + + -- p2 is still here from being + -- set with lua["p2"] = player(0); + -- in cpp file + local p2shoots = p2:shoot() + assert(not p2shoots) + -- had 0 ammo + + -- set variable property setter + p1.hp = 545; + -- get variable through property getter + print(p1.hp); + + local did_shoot_1 = p1:shoot() + print(did_shoot_1) + print(p1.bullets) + local did_shoot_2 = p1:shoot() + print(did_shoot_2) + print(p1.bullets) + local did_shoot_3 = p1:shoot() + print(did_shoot_3) + + -- can read + print(p1.bullets) + -- would error: is a readonly variable, cannot write + -- p1.bullets = 20 + + p1:boost() + +To do this, you bind things using the ``new_usertype`` and ``set_usertype`` methods as shown below. These methods are on both :doc:`table<../api/table>` and :doc:`state(_view)<../api/state>`, but we're going to just use it on ``state``: + +.. code-block:: cpp + :caption: player_script.cpp + + #include + + int main () { + sol::state lua; + + // note that you can set a + // userdata before you register a usertype, + // and it will still carry + // the right metatable if you register it later + + // set a variable "p2" of type "player" with 0 ammo + lua["p2"] = player(0); + + // make usertype metatable + lua.new_usertype( "player", + + // 3 constructors + sol::constructors, sol::types, sol::types>(), + + // typical member function that returns a variable + "shoot", &player::shoot, + // typical member function + "boost", &player::boost, + + // gets or set the value using member variable syntax + "hp", sol::property(&player::get_hp, &player::set_hp), + + // read and write variable + "speed", &player::speed, + // can only read from, not write to + "bullets", sol::readonly( &player::bullets ) + ); + + lua.script_file("player_script.lua"); + } + +That script should run fine now, and you can observe and play around with the values. Even more stuff :doc:`you can do<../api/usertype>` is described elsewhere, like initializer functions (private constructors / destructors support), "static" functions callable with ``name.my_function( ... )``, and overloaded member functions. You can even bind global variables (even by reference with ``std::ref``) with ``sol::var``. There's a lot to try out! + +This is a powerful way to allow reuse of C++ code from Lua beyond just registering functions, and should get you on your way to having more complex classes and data structures! In the case that you need more customization than just usertypes, however, you can customize Sol to behave more fit to your desires by using the desired :doc:`customization and extension structures`. + +You can check out this code and more complicated code at the `examples directory`_ by looking at the ``usertype_``-prefixed examples. + +.. _examples directory: https://github.com/ThePhD/sol2/tree/develop/examples \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/existing.rst b/3rdparty/sol2/docs/source/tutorial/existing.rst new file mode 100644 index 00000000000..89a83f8078d --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/existing.rst @@ -0,0 +1,27 @@ +integrating into existing code +============================== + +If you're already using lua and you just want to use ``sol`` in some places, you can use ``state_view``: + +.. code-block:: cpp + :linenos: + :caption: using state_view + :name: state-view-snippet + + void something_in_my_system (lua_State* L) { + // start using Sol with a pre-existing system + sol::state_view lua(L); // non-owning + + lua.script("print('bark bark bark!')"); + + sol::table expected_table(L); // get the table off the top of the stack + // start using it... + } + +:doc:`sol::state_view<../api/state>` is exactly like ``sol::state``, but it doesn't manage the lifetime of a ``lua_State*``. Therefore, you get all the goodies that come with a ``sol::state`` without any of the ownership implications. Sol has no initialization components that need to deliberately remain alive for the duration of the program. It's entirely self-containing and uses lua's garbage collectors and various implementation techniques to require no state C++-side. After you do that, all of the power of `Sol` is available to you, and then some! + +You may also want to call ``require`` and supply a string of a script file or something that returns an object that you set equal to something in C++. For that, you can use the :ref:`require functionality`. + +Remember that Sol can be as lightweight as you want it: almost all of Sol's types take the ``lua_State*`` argument and then a second ``int index`` stack index argument, meaning you can use :doc:`tables<../api/table>`, :doc:`lua functions<../api/function>`, :doc:`coroutines<../api/coroutine>`, and other reference-derived objects that expose the proper constructor for your use. You can also set :doc:`usertypes<../api/usertype>` and other things you need without changing your entire architecture. + +Note that you can also make non-standard pointer and reference types with custom reference counting and such also play nice with the system. See :doc:`unique_usertype_traits\<../api/unique_usertype_traits>` to see how! Custom types is also mentioned in the :doc:`customization tutorial`. \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/functions.rst b/3rdparty/sol2/docs/source/tutorial/functions.rst new file mode 100644 index 00000000000..2b2f0e3ba61 --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/functions.rst @@ -0,0 +1,341 @@ +functions and You +================= + +Sol can register all kinds of functions. Many are shown in the :doc:`quick 'n' dirty`, but here we will discuss many of the additional ways you can register functions into a sol-wrapped Lua system. + +Setting a new function +---------------------- + +Given a C++ function, you can drop it into Sol in several equivalent ways, working similar to how :ref:`setting variables` works: + +.. code-block:: cpp + :linenos: + :caption: Registering C++ functions + :name: writing-functions + + #include + + std::string my_function( int a, std::string b ) { + // Create a string with the letter 'D' "a" times, + // append it to 'b' + return b + std::string( 'D', a ); + } + + int main () { + + sol::state lua; + + lua["my_func"] = my_function; // way 1 + lua.set("my_func", my_function); // way 2 + lua.set_function("my_func", my_function); // way 3 + + // This function is now accessible as 'my_func' in + // lua scripts / code run on this state: + lua.script("some_str = my_func(1, "Da"); + + // Read out the global variable we stored in 'some_str' in the + // quick lua code we just executed + std::string some_str = lua["some_str"]; + // some_str == "DaD" + } + +The same code works with all sorts of functions, from member function/variable pointers you have on a class as well as lambdas: + +.. code-block:: cpp + :linenos: + :caption: Registering C++ member functions + :name: writing-member-functions + + struct my_class { + int a = 0; + + my_class(int x) : a(x) { + + } + + int func() { + ++a; // increment a by 1 + return a; + } + }; + + int main () { + + sol::state lua; + + // Here, we are binding the member function and a class instance: it will call the function on + // the given class instance + lua.set_function("my_class_func", &my_class::func, my_class()); + + // We do not pass a class instance here: + // the function will need you to pass an instance of "my_class" to it + // in lua to work, as shown below + lua.set_function("my_class_func_2", &my_class::func); + + // With a pre-bound instance: + lua.script(R"( + first_value = my_class_func() + second_value = my_class_func() + )"); + // first_value == 1 + // second_value == 2 + + // With no bound instance: + lua.set("obj", my_class(24)); + // Calls "func" on the class instance + // referenced by "obj" in Lua + lua.script(R"( + third_value = my_class_func_2(obj) + fourth_value = my_class_func_2(obj) + )"); + // first_value == 25 + // second_value == 26 + } + +Member class functions and member class variables will both be turned into functions when set in this manner. You can get intuitive variable with the ``obj.a = value`` access after this section when you learn about :doc:`usertypes to have C++ in Lua`, but for now we're just dealing with functions! + + +Another question a lot of people have is about function templates. Function templates -- member functions or free functions -- cannot be registered because they do not exist until you instantiate them in C++. Therefore, given a templated function such as: + +.. code-block:: cpp + :linenos: + :caption: A C++ templated function + :name: writing-templated-functions-the-func + + template + auto my_add( A a, B b ) { + return a + b; + } + + +You must specify all the template arguments in order to bind and use it, like so: + +.. code-block:: cpp + :linenos: + :caption: Registering function template instantiations + :name: writing-templated-functions + + + int main () { + + sol::state lua; + + // adds 2 integers + lua["my_int_add"] = my_add; + + // concatenates 2 strings + lua["my_string_combine"] = my_add; + + lua.script("my_num = my_int_add(1, 2)"); + int my_num = lua["my_num"]; + // my_num == 3 + + lua.script("my_str = my_string_combine('bark bark', ' woof woof')"); + std::string my_str = lua["my_str"]; + // my_str == "bark bark woof woof" + } + +Notice here that we bind two separate functions. What if we wanted to bind only one function, but have it behave differently based on what arguments it is called with? This is called Overloading, and it can be done with :doc:`sol::overload<../api/overload>` like so: + +.. code-block:: cpp + :linenos: + :caption: Registering C++ function template instantiations + :name: writing-templated-functions-overloaded + + + int main () { + + sol::state lua; + + // adds 2 integers + lua["my_combine"] = sol::overload( my_add, my_add ); + + lua.script("my_num = my_combine(1, 2)"); + lua.script("my_str = my_combine('bark bark', ' woof woof')"); + int my_num = lua["my_num"]; + std::string my_str = lua["my_str"]; + // my_num == 3 + // my_str == "bark bark woof woof" + } + +This is useful for functions which can take multiple types and need to behave differently based on those types. You can set as many overloads as you want, and they can be of many different types. + +.. note:: + + Function object ``obj`` -- a struct with a ``return_type operator()( ... )`` member defined on them, like all C++ lambdas -- are not interpreted as functions when you use ``set`` for ``mytable.set( key, value )``. This only happens automagically with ``mytable[key] = obj``. To be explicit about wanting a struct to be interpreted as a function, use ``mytable.set_function( key, func_value );``. You can be explicit about wanting a function as well by using the :doc:`sol::as_function<../api/as_function>` call. + + +Getting a function from Lua +--------------------------- + +There are 2 ways to get a function from Lua. One is with :doc:`sol::function<../api/function>` and the other is a more advanced wrapper with :doc:`sol::protected_function<../api/protected_function>`. Use them to retrieve callables from Lua and call the underlying function, in two ways: + +.. code-block:: cpp + :linenos: + :caption: Retrieving a sol::function + :name: reading-functions + + int main () { + + sol::state lua; + + lua.script(R"( + function f (a) + return a + 5 + end + )"); + + // Get and immediately call + int x = lua["f"](30); + // x == 35 + + // Store it into a variable first, then call + sol::function f = lua["f"]; + int y = f(20); + // y == 25 + } + +You can get anything that's a callable in Lua, including C++ functions you bind using ``set_function`` or similar. ``sol::protected_function`` behaves similarly to ``sol::function``, but has a :ref:`error_handler` variable you can set to a Lua function. This catches all errors and runs them through the error-handling function: + + +.. code-block:: cpp + :linenos: + :caption: Retrieving a sol::protected_function + :name: reading-protected-functions + + int main () { + sol::state lua; + + lua.script(R"( + function handler (message) + return "Handled this message: " .. message + end + + function f (a) + if a < 0 then + error("negative number detected") + end + return a + 5 + end + )"); + + sol::protected_function f = lua["f"]; + f.error_handler = lua["handler"]; + + sol::protected_function_result result = f(-500); + if (result.valid()) { + // Call succeeded + int x = result; + } + else { + // Call failed + sol::error err = result; + std::string what = err.what(); + // 'what' Should read + // "Handled this message: negative number detected" + } + } + + +Multiple returns to and from Lua +-------------------------------- + +You can return multiple items to and from Lua using ``std::tuple``/``std::pair`` classes provided by C++. These enable you to also use :doc:`sol::tie<../api/tie>` to set return values into pre-declared items. To recieve multiple returns, just ask for a ``std::tuple`` type from the result of a function's computation, or ``sol::tie`` a bunch of pre-declared variables together and set the result equal to that: + +.. code-block:: cpp + :linenos: + :caption: Multiple returns from Lua + :name: multi-return-lua-functions + + int main () { + sol::state lua; + + lua.script("function f (a, b, c) return a, b, c end"); + + std::tuple result; + result = lua["f"](1, 2, 3); + // result == { 1, 2, 3 } + int a, int b; + std::string c; + sol::tie( a, b, c ) = lua["f"](1, 2, "bark"); + // a == 1 + // b == 2 + // c == "bark" + } + +You can also return mutiple items yourself from a C++-bound function. Here, we're going to bind a C++ lambda into Lua, and then call it through Lua and get a ``std::tuple`` out on the other side: + +.. code-block:: cpp + :linenos: + :caption: Multiple returns into Lua + :name: multi-return-cxx-functions + + int main () { + sol::state lua; + + lua["f"] = [](int a, int b, sol::object c) { + // sol::object can be anything here: just pass it through + return std::make_tuple( a, b, c ); + }; + + std::tuple result = lua["f"](1, 2, 3); + // result == { 1, 2, 3 } + + std::tuple result2; + result2 = lua["f"](1, 2, "Arf?") + // result2 == { 1, 2, "Arf?" } + + int a, int b; + std::string c; + sol::tie( a, b, c ) = lua["f"](1, 2, "meow"); + // a == 1 + // b == 2 + // c == "meow" + } + + +Note here that we use :doc:`sol::object<../api/object>` to transport through "any value" that can come from Lua. You can also use ``sol::make_object`` to create an object from some value, so that it can be returned into Lua as well. + + +Any return to and from Lua +-------------------------- + +It was hinted at in the previous code example, but ``sol::object`` is a good way to pass "any type" back into Lua (while we all wait for ``std::variant<...>`` to get implemented and shipped by C++ compiler/library implementers). + +It can be used like so, inconjunction with ``sol::this_state``: + +.. code-block:: cpp + :linenos: + :caption: Return anything into Lua + :name: object-return-cxx-functions + + sol::object fancy_func (sol::object a, sol::object b, sol::this_state s) { + sol::state_view lua(s); + if (a.is() && b.is()) { + return sol::make_object(lua, a.as() + b.as()); + } + else if (a.is()) { + bool do_triple = a.as(); + return sol::make_object(lua, b.as() * ( do_triple ? 3 : 1 ) ); + } + return sol::make_object(lua, sol::nil); + } + + int main () { + sol::state lua; + + lua["f"] = fancy_func; + + int result = lua["f"](1, 2); + // result == 3 + double result2 = lua["f"](false, 2.5); + // result2 == 2.5 + + // call in Lua, get result + lua.script("result3 = f(true, 5.5)"); + double result3 = lua["result3"]; + // result3 == 16.5 + } + + +This covers almost everything you need to know about Functions and how they interact with Sol. For some advanced tricks and neat things, check out :doc:`sol::this_state<../api/this_state>` and :doc:`sol::variadic_args<../api/variadic_args>`. The next stop in this tutorial is about :doc:`C++ types (usertypes) in Lua`! \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/getting-started.rst b/3rdparty/sol2/docs/source/tutorial/getting-started.rst new file mode 100644 index 00000000000..fd83e4fcb93 --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/getting-started.rst @@ -0,0 +1,84 @@ +getting started +=============== + +Let's get you going with Sol! To start, you'll need to use a lua distribution of some sort. Sol doesn't provide that: it only wraps the API that comes with it, so you can pick whatever distribution you like for your application. There are lots, but the two popular ones are `vanilla Lua`_ and speedy `LuaJIT`_ . We recommend vanilla Lua if you're getting started, LuaJIT if you need speed and can handle some caveats: the interface for Sol doesn't change no matter what Lua version you're using. + +If you need help getting or building Lua, check out the `Lua page on getting started`_. Note that for Visual Studio, one can simply download the sources, include all the Lua library files in that project, and then build for debug/release, x86/x64/ARM rather easily and with minimal interference. Just make sure to adjust the Project Property page to build as a static library (or a DLL with the proper define set in the ``Preprocessor`` step). + +After that, make sure you grab either the `single header file release`_, or just perform a clone of the `github repository here`_ and set your include paths up so that you can get at ``sol.hpp`` somehow. Note that we also have the latest version of the single header file with all dependencies included kept in the `repository as well`_. We recommend the single-header-file release, since it's easier to move around, manage and update if you commit it with some form of version control. If you use the github clone method and do not point to the `single/sol/sol.hpp`_ on your include files, you *must* update submodules in order to make sure Optional is present in the repository. Clone with: + +>>> git clone https://github.com/ThePhD/sol2.git +>>> git submodule update --init + +or, just run + +>>> git clone --recursive https://github.com/ThePhD/sol2.git + +When you're ready, try compiling this short snippet: + +.. code-block:: cpp + :linenos: + :caption: test.cpp: the first snippet + :name: the-first-snippet + + #include // or #include "sol.hpp", whichever suits your needs + + int main (int argc, char* argv[]) { + + sol::state lua; + lua.open_libraries( sol::lib::base ); + + lua.script( "print('bark bark bark!')" ); + + return 0; + } + +Using this simple command line: + +>>> g++ -std=c++14 test.cpp -I"path/to/lua/include" -L"path/to/lua/lib" -llua + +Or using your favorite IDE / tool after setting up your include paths and library paths to Lua according to the documentation of the Lua distribution you got. Remember your linked lua library (``-llua``) and include / library paths will depend on your OS, file system, Lua distribution and your installation / compilation method of your Lua distribution. + +.. note:: + + If you get an avalanche of errors (particularly referring to ``auto``), you may not have enabled C++14 / C++17 mode for your compiler. Add one of ``std=c++14``, ``std=c++1z`` OR ``std=c++1y`` to your compiler options. By default, this is always-on for VC++ compilers in Visual Studio and friends, but g++ and clang++ require a flag (unless you're on `GCC 6.0`_). + +If this works, you're ready to start! The first line creates the ``lua_State`` and will hold onto it for the duration of the scope its declared in (e.g., from the opening ``{`` to the closing ``}``). It will automatically close / cleanup that lua state when it gets destructed. The second line opens a single lua-provided library, "base". There are several other libraries that come with lua that you can open by default, and those are included in the :ref:`sol::lib` enumeration. You can open multiple base libraries by specifying multiple ``sol::lib`` arguments: + +.. code-block:: cpp + :linenos: + :caption: test.cpp: the first snippet + :name: the-second-snippet + + #include + + int main (int argc, char* argv[]) { + + sol::state lua; + lua.open_libraries( sol::lib::base, sol::lib::coroutine, sol::lib::string, sol::lib::io ); + + lua.script( "print('bark bark bark!')" ); + + return 0; + } + +If you're interested in integrating Sol with a project that already uses some other library or Lua in the codebase, check out the :doc:`existing example` to see how to work with Sol when you add it to a project (the existing example covers ``require`` as well)! + +Next, let's start :doc:`reading/writing some variables` from Lua into C++, and vice-versa! + + +.. _vanilla Lua: https://www.lua.org/ + +.. _LuaJIT: http://luajit.org/ + +.. _GCC 6.0: https://gcc.gnu.org/gcc-6/changes.html + +.. _single header file release: https://github.com/ThePhD/sol2/releases + +.. _repository as well: https://github.com/ThePhD/sol2/blob/develop/single/sol/sol.hpp + +.. _single/sol/sol.hpp: https://github.com/ThePhD/sol2/blob/develop/single/sol/sol.hpp + +.. _github repository here: https://github.com/ThePhD/sol2 + +.. _Lua page on getting started: https://www.lua.org/start.html \ No newline at end of file diff --git a/3rdparty/sol2/docs/source/tutorial/ownership.rst b/3rdparty/sol2/docs/source/tutorial/ownership.rst new file mode 100644 index 00000000000..96eb350da78 --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/ownership.rst @@ -0,0 +1,94 @@ +ownership +========= + +Sol will not take ownership of raw pointers: raw pointers do not own anything. + +.. code-block:: cpp + + struct my_type { + void stuff () {} + }; + + sol::state lua; + + // AAAHHH BAD + // dangling pointer! + lua["my_func"] = []() -> my_type* { + return new my_type(); + }; + + // AAAHHH! + lua.set("something", new my_type()); + + // AAAAAAHHH!!! + lua["something_else"] = new my_type(); + +Use/return a ``unique_ptr`` or ``shared_ptr`` instead or just return a value: + +.. code-block:: cpp + + // :ok: + lua["my_func"] = []() -> std::unique_ptr { + return std::make_unique(); + }; + + // :ok: + lua["my_func"] = []() -> std::shared_ptr { + return std::make_shared(); + }; + + // :ok: + lua["my_func"] = []() -> my_type { + return my_type(); + }; + + // :ok: + lua.set("something", std::unique_ptr(new my_type())); + + std::shared_ptr my_shared = std::make_shared(); + // :ok: + lua.set("something_else", my_shared); + + auto my_unique = std::make_unique(); + lua["other_thing"] = std::move(my_unique); + +If you have something you know is going to last and you just want to give it to Lua as a reference, then it's fine too: + +.. code-block:: cpp + + // :ok: + lua["my_func"] = []() -> my_type* { + static my_type mt; + return &mt; + }; + + +Sol can detect ``nullptr``, so if you happen to return it there won't be any dangling because a ``sol::nil`` will be pushed. + +.. code-block:: cpp + + struct my_type { + void stuff () {} + }; + + sol::state lua; + + // BUT THIS IS STILL BAD DON'T DO IT AAAHHH BAD + // return a unique_ptr still or something! + lua["my_func"] = []() -> my_type* { + return nullptr; + }; + + lua["my_func_2"] = [] () -> std::unique_ptr { + // default-constructs as a nullptr, + // gets pushed as nil to Lua + return std::unique_ptr(); + // same happens for std::shared_ptr + } + + // Acceptable, it will set 'something' to nil + // (and delete it on next GC if there's no more references) + lua.set("something", nullptr); + + // Also fine + lua["something_else"] = nullptr; diff --git a/3rdparty/sol2/docs/source/tutorial/tutorial-top.rst b/3rdparty/sol2/docs/source/tutorial/tutorial-top.rst new file mode 100644 index 00000000000..730423fdb5a --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/tutorial-top.rst @@ -0,0 +1,21 @@ +tutorial +======== + +Take some time to learn the framework with thse tutorials. But, if you need to get going FAST, try using the :doc:`quick 'n' dirty` approach and your browser's / editors search function. It will also serve you well to look at all the `examples`_, which have recently gotten a bit of an overhaul to contain more relevant working examples. + + +.. toctree:: + :caption: Sol Tutorial + :name: tutorialtoc + :maxdepth: 2 + + all-the-things + getting-started + existing + variables + functions + cxx-in-lua + ownership + customization + +.. _examples: https://github.com/ThePhD/sol2/tree/develop/examples diff --git a/3rdparty/sol2/docs/source/tutorial/variables.rst b/3rdparty/sol2/docs/source/tutorial/variables.rst new file mode 100644 index 00000000000..20105bf8003 --- /dev/null +++ b/3rdparty/sol2/docs/source/tutorial/variables.rst @@ -0,0 +1,202 @@ +variables +========= + +Working with variables is easy with Sol, and behaves pretty much like any associative array / map structure you've dealt with previously. Given this lua file that gets loaded into Sol: + +reading +------- + +.. code-block:: lua + :caption: variables.lua + + config = { + fullscreen = false, + resolution = { x = 1024, y = 768 } + } + +.. code-block:: cpp + :caption: main.cpp + :name: variables-main-cpp + + #include + + int main () { + + sol::state lua; + lua.script_file( variables.lua ); + + return 0; + } + +You can interact with the variables like this: + +.. code-block:: cpp + :caption: main.cpp extended + :name: extended-variables-main-cpp + + #include + #include + #include // for std::pair + + int main () { + + sol::state lua; + lua.script_file( variables.lua ); + + // the type "state" behaves exactly like a table! + bool isfullscreen = lua["config"]["fullscreen"]; // can get nested variables + sol::table config = lua["config"]; + + // can also get it using the "get" member function + // auto replaces the unqualified type name + auto resolution = config.get( "config" ); + + // table and state can have multiple things pulled out of it too + std::pair xyresolution = resolution.get( "x", "y" ); + // As an example, you can also pull out a tuple as well + std::tuple xyresolutiontuple = resolution.get( "x", "y" ); + + + return 0; + } + +From this example, you can see that there's many ways to pull out the varaibles you want. You can get For example, to determine if a nested variable exists or not, you can use ``auto`` to capture the value of a ``table[key]`` lookup, and then use the ``.valid()`` method: + +.. code-block:: cpp + :caption: safe lookup + + auto bark = lua["config"]["bark"]; + if (bark.valid()) { + // branch not taken: config / bark is not a variable + } + else { + // Branch taken: config is a not a variable + } + +This comes in handy when you want to check if a nested variable exists. You can also check if a toplevel variable is present or not by using ``sol::optional``, which also checks if A) the keys you're going into exist and B) the type you're trying to get is of a specific type: + +.. code-block:: cpp + :caption: optional lookup + + sol::optional not_an_integer = lua["config"]["fullscreen"]; + if (not_an_integer) { + // Branch not taken: value is not an integer + } + + sol::optoinal is_a_boolean = lua["config"]["fullscreen"]; + if (is_a_boolean) { + // Branch taken: the value is a boolean + } + + sol::optional does_not_exist = lua["not_a_variable"]; + if (does_not_exist) { + // Branch not taken: that variable is not present + } + +This can come in handy when, even in optimized or release modes, you still want the safety of checking. You can also use the `get_or` methods to, if a certain value may be present but you just want to default the value to something else: + +.. code-block:: cpp + :caption: get_or lookup + + // this will result in a value of '24' + int is_defaulted = lua["config"]["fullscreen"].get_or( 24 ); + + // This will result in the value of the config, which is 'false' + bool is_not_defaulted = lua["config"]["fullscreen"]; + +That's all it takes to read variables! + + +writing +------- + +Writing gets a lot simpler. Even without scripting a file or a string, you can read and write variables into lua as you please: + +.. code-block:: cpp + :caption: main.cpp + :name: writing-main-cpp + + #include + #include + + int main () { + + sol::state lua; + + // open those basic lua libraries again, like print() etc. + lua.open_libraries( sol::lib::base ); + + // value in the global table + lua["bark"] = 50; + + // a table being created in the global table + lua["some_table"] = lua.create_table_with( + "key0", 24, + "key1", 25, + lua["bark"], "the key is 50 and this string is its value!" + ); + + // Run a plain ol' string of lua code + // Note you can interact with things set through Sol in C++ with lua! + // Using a "Raw String Literal" to have multi-line goodness: http://en.cppreference.com/w/cpp/language/string_literal + lua.script(R"( + + print(some_table[50]) + print(some_table["key0"]) + print(some_table["key1"]) + + -- a lua comment: access a global in a lua script with the _G table + print(_G["bark"]) + + )"); + + return 0; + } + +This example pretty much sums up what can be done. Note that the syntax ``lua["non_existing_key_1"] = 1`` will make that variable, but if you tunnel too deep without first creating a table, the Lua API will panic (e.g., ``lua["does_not_exist"]["b"] = 20`` will trigger a panic). You can also be lazy with reading / writing values: + +.. code-block:: cpp + :caption: main.cpp + :name: lazy-main-cpp + + #include + #include + + int main () { + + sol::state lua; + + auto barkkey = lua["bark"]; + if (barkkey.valid()) { + // Branch not taken: doesn't exist yet + std::cout << "How did you get in here, arf?!" << std::endl; + } + + barkkey = 50; + if (barkkey.valid()) { + // Branch taken: value exists! + std::cout << "Bark Bjork Wan Wan Wan" << std::endl; + } + } + +Finally, it's possible to erase a reference/variable by setting it to ``nil``, using the constant ``sol::nil`` in C++: + +.. code-block:: cpp + :caption: main.cpp + :name: erase-main-cpp + + #include + + int main () { + + sol::state lua; + lua["bark"] = 50; + sol::optional x = lua["bark"]; + // x will have a value + + lua["bark"] = sol::nil; + sol::optional y = lua["bark"]; + // y will not have a value + } + +It's easy to see that there's a lot of options to do what you want here. But, these are just traditional numbers and strings. What if we want more power, more capabilities than what these limited types can offer us? Let's throw some :doc:`functions in there` :doc:`C++ classes into the mix`! \ No newline at end of file diff --git a/3rdparty/sol2/examples/any_return.cpp b/3rdparty/sol2/examples/any_return.cpp new file mode 100644 index 00000000000..f286071b8d8 --- /dev/null +++ b/3rdparty/sol2/examples/any_return.cpp @@ -0,0 +1,46 @@ +#include + +#include +#include + +// Uses some of the fancier bits of sol2, including the "transparent argument", +// sol::this_state, which gets the current state and does not increment +// function arguments +sol::object fancy_func(sol::object a, sol::object b, sol::this_state s) { + sol::state_view lua(s); + if (a.is() && b.is()) { + return sol::object(lua, sol::in_place, a.as() + b.as()); + } + else if (a.is()) { + bool do_triple = a.as(); + return sol::object(lua, sol::in_place, b.as() * (do_triple ? 3 : 1)); + } + // Can also use make_object + return sol::make_object(lua, sol::nil); +} + +int main() { + sol::state lua; + + lua["f"] = fancy_func; + + int result = lua["f"](1, 2); + // result == 3 + assert(result == 3); + double result2 = lua["f"](false, 2.5); + // result2 == 2.5 + assert(result2 == 2.5); + + // call in Lua, get result + // notice we only need 2 arguments here, not 3 (sol::this_state is transparent) + lua.script("result3 = f(true, 5.5)"); + double result3 = lua["result3"]; + // result3 == 16.5 + assert(result3 == 16.5); + + std::cout << "=== any_return example ===" << std::endl; + std::cout << "result : " << result << std::endl; + std::cout << "result2: " << result2 << std::endl; + std::cout << "result3: " << result3 << std::endl; + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/basic.cpp b/3rdparty/sol2/examples/basic.cpp new file mode 100644 index 00000000000..cf00ee70ab2 --- /dev/null +++ b/3rdparty/sol2/examples/basic.cpp @@ -0,0 +1,19 @@ +#include + +#include + +int main() { + // create an empty lua state + sol::state lua; + + // by default, libraries are not opened + // you can open libraries by using open_libraries + // the libraries reside in the sol::lib enum class + lua.open_libraries(sol::lib::base); + + // call lua code directly + std::cout << "=== basic example ===" << std::endl; + lua.script("print('hello world')"); + + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/config.cpp b/3rdparty/sol2/examples/config.cpp new file mode 100644 index 00000000000..d899de385ca --- /dev/null +++ b/3rdparty/sol2/examples/config.cpp @@ -0,0 +1,39 @@ +#include +#include +#include + +// shows how to load basic data to a struct + +struct config { + std::string name; + int width; + int height; + + void print() { + std::cout << "Name: " << name << '\n' + << "Width: " << width << '\n' + << "Height: " << height << '\n'; + } +}; + +int main() { + sol::state lua; + config screen; + // To use the file, uncomment here and make sure it is in local dir + //lua.script_file("config.lua"); + lua.script(R"( +name = "Asus" +width = 1920 +height = 1080 +)"); + screen.name = lua.get("name"); + screen.width = lua.get("width"); + screen.height = lua.get("height"); + assert(screen.name == "Asus"); + assert(screen.width == 1920); + assert(screen.height == 1080); + + std::cout << "=== config example ===" << std::endl; + screen.print(); + std::cout << std::endl; +} diff --git a/3rdparty/sol2/examples/config.lua b/3rdparty/sol2/examples/config.lua new file mode 100644 index 00000000000..0144f989a84 --- /dev/null +++ b/3rdparty/sol2/examples/config.lua @@ -0,0 +1,3 @@ +name = "Asus" +width = 1920 +height = 1080 diff --git a/3rdparty/sol2/examples/customization.cpp b/3rdparty/sol2/examples/customization.cpp new file mode 100644 index 00000000000..45280e5989b --- /dev/null +++ b/3rdparty/sol2/examples/customization.cpp @@ -0,0 +1,91 @@ +#include + +#include +#include +#include + +struct two_things { + int a; + bool b; +}; + +namespace sol { + + // First, the expected size + // Specialization of a struct + template <> + struct lua_size : std::integral_constant {}; + + // Now, specialize various stack structures + namespace stack { + + template <> + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + // indices can be negative to count backwards from the top of the stack, + // rather than the bottom up + // to deal with this, we adjust the index to + // its absolute position using the lua_absindex function + int absolute_index = lua_absindex(L, index); + // Check first and second second index for being the proper types + bool success = stack::check(L, absolute_index + 1, handler) + && stack::check(L, absolute_index, handler); + tracking.use(2); + return success; + } + }; + + template <> + struct getter { + static two_things get(lua_State* L, int index, record& tracking) { + int absolute_index = lua_absindex(L, index); + // Get the first element + int a = stack::get(L, absolute_index); + // Get the second element, + // in the +1 position from the first + bool b = stack::get(L, absolute_index + 1); + // we use 2 slots, each of the previous takes 1 + tracking.use(2); + return two_things{ a, b }; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, const two_things& things) { + int amount = stack::push(L, things.a); + // amount will be 1: int pushes 1 item + amount += stack::push(L, things.b); + // amount 2 now, since bool pushes a single item + // Return 2 things + return amount; + } + }; + + } +} + +int main() { + sol::state lua; + + // Create a pass-through style of function + lua.script("function f ( a, b ) return a, b end"); + + // get the function out of Lua + sol::function f = lua["f"]; + + two_things things = f(two_things{ 24, true }); + assert(things.a == 24); + assert(things.b == true); + // things.a == 24 + // things.b == true + + std::cout << "=== customization example ===" << std::endl; + std::cout << std::boolalpha; + std::cout << "things.a: " << things.a << std::endl; + std::cout << "things.b: " << things.b << std::endl; + std::cout << std::endl; + + return 0; +} diff --git a/3rdparty/sol2/examples/functions.cpp b/3rdparty/sol2/examples/functions.cpp new file mode 100644 index 00000000000..b4f9a1da140 --- /dev/null +++ b/3rdparty/sol2/examples/functions.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +inline int my_add(int x, int y) { + return x + y; +} + +struct multiplier { + int operator()(int x) { + return x * 10; + } + + static int by_five(int x) { + return x * 5; + } +}; + +inline std::string make_string( std::string input ) { + return "string: " + input; +} + +int main() { + std::cout << "=== functions example ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // setting a function is simple + lua.set_function("my_add", my_add); + + // you could even use a lambda + lua.set_function("my_mul", [](double x, double y) { return x * y; }); + + // member function pointers and functors as well + lua.set_function("mult_by_ten", multiplier{}); + lua.set_function("mult_by_five", &multiplier::by_five); + + // assert that the functions work + lua.script("assert(my_add(10, 11) == 21)"); + lua.script("assert(my_mul(4.5, 10) == 45)"); + lua.script("assert(mult_by_ten(50) == 500)"); + lua.script("assert(mult_by_five(10) == 50)"); + + // using lambdas, functions can have state. + int x = 0; + lua.set_function("inc", [&x]() { x += 10; }); + + // calling a stateful lambda modifies the value + lua.script("inc()"); + assert(x == 10); + if (x == 10) { + // Do something based on this information + std::cout << "Yahoo! x is " << x << std::endl; + } + + // this can be done as many times as you want + lua.script(R"( +inc() +inc() +inc() +)"); + assert(x == 40); + if (x == 40) { + // Do something based on this information + std::cout << "Yahoo! x is " << x << std::endl; + } + // retrieval of a function is done similarly + // to other variables, using sol::function + sol::function add = lua["my_add"]; + int value = add(10, 11); + // second way to call the function + int value2 = add.call(10, 11); + assert(value == 21); + assert(value2 == 21); + if (value == 21 && value2 == 21) { + std::cout << "Woo, value is 21!" << std::endl; + } + + // multi-return functions are supported using + // std::tuple as the interface. + lua.set_function("multi", [] { return std::make_tuple(10, "goodbye"); }); + lua.script("x, y = multi()"); + lua.script("assert(x == 10 and y == 'goodbye')"); + + auto multi = lua.get("multi"); + int first; + std::string second; + sol::tie(first, second) = multi(); + + // use the values + assert(first == 10); + assert(second == "goodbye"); + + // you can even overload functions + // just pass in the different functions + // you want to pack into a single name: + // make SURE they take different types! + + lua.set_function("func", sol::overload([](int x) { return x; }, make_string, my_add)); + + // All these functions are now overloaded through "func" + lua.script(R"( +print(func(1)) +print(func("bark")) +print(func(1,2)) +)"); + + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/namespacing.cpp b/3rdparty/sol2/examples/namespacing.cpp new file mode 100644 index 00000000000..8d32744eb64 --- /dev/null +++ b/3rdparty/sol2/examples/namespacing.cpp @@ -0,0 +1,33 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include + +int main() { + struct my_class { + int b = 24; + + int f() const { + return 24; + } + + void g() { + ++b; + } + }; + + sol::state lua; + lua.open_libraries(); + + sol::table bark = lua.create_named_table("bark"); + bark.new_usertype("my_class", + "f", &my_class::f, + "g", &my_class::g + ); // the usual + + lua.script("obj = bark.my_class.new()"); // this works + lua.script("obj:g()"); + my_class& obj = lua["obj"]; + assert(obj.b == 25); + + return 0; +} diff --git a/3rdparty/sol2/examples/player_script.lua b/3rdparty/sol2/examples/player_script.lua new file mode 100644 index 00000000000..432983e02a7 --- /dev/null +++ b/3rdparty/sol2/examples/player_script.lua @@ -0,0 +1,29 @@ +-- call single argument integer constructor +p1 = player.new(2) + +-- p2 is still here from being +-- set with lua["p2"] = player(0); below +local p2shoots = p2:shoot() +assert(not p2shoots) +-- had 0 ammo + +-- set variable property setter +p1.hp = 545; +-- get variable through property getter +print(p1.hp); + +local did_shoot_1 = p1:shoot() +print(did_shoot_1) +print(p1.bullets) +local did_shoot_2 = p1:shoot() +print(did_shoot_2) +print(p1.bullets) +local did_shoot_3 = p1:shoot() +print(did_shoot_3) + +-- can read +print(p1.bullets) +-- would error: is a readonly variable, cannot write +-- p1.bullets = 20 + +p1:boost() \ No newline at end of file diff --git a/3rdparty/sol2/examples/protected_functions.cpp b/3rdparty/sol2/examples/protected_functions.cpp new file mode 100644 index 00000000000..340f0134d63 --- /dev/null +++ b/3rdparty/sol2/examples/protected_functions.cpp @@ -0,0 +1,47 @@ +#include + +#include + +int main() { + std::cout << "=== protected_functions example ===" << std::endl; + + sol::state lua; + + // A complicated function which can error out + // We define both in terms of Lua code + + lua.script(R"( + function handler (message) + return "Handled this message: " .. message + end + + function f (a) + if a < 0 then + error("negative number detected") + end + return a + 5 + end + )"); + + // Get a protected function out of Lua + sol::protected_function f = lua["f"]; + // Set a non-default error handler + f.error_handler = lua["handler"]; + + sol::protected_function_result result = f(-500); + if (result.valid()) { + // Call succeeded + int x = result; + std::cout << "call succeeded, result is " << x << std::endl; + } + else { + // Call failed + sol::error err = result; + std::string what = err.what(); + std::cout << "call failed, sol::error::what() is " << what << std::endl; + // 'what' Should read + // "Handled this message: negative number detected" + } + + std::cout << std::endl; +} diff --git a/3rdparty/sol2/examples/require.cpp b/3rdparty/sol2/examples/require.cpp new file mode 100644 index 00000000000..a94765b9453 --- /dev/null +++ b/3rdparty/sol2/examples/require.cpp @@ -0,0 +1,47 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include + +#include + +struct some_class { + int bark = 2012; +}; + +sol::table open_mylib(sol::this_state s) { + sol::state_view lua(s); + + sol::table module = lua.create_table(); + module["func"] = []() { /* super cool function here */ }; + // register a class too + module.new_usertype("some_class", + "bark", &some_class::bark + ); + + return module; +} + +int main() { + std::cout << "=== require example ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::package); + // sol::c_call takes functions at the template level + // and turns it into a lua_CFunction + // alternatively, one can use sol::c_call> to make the call + // if it's a constexpr struct + lua.require("my_lib", sol::c_call); + + // do ALL THE THINGS YOU LIKE + lua.script(R"( +s = my_lib.some_class.new() +s.bark = 20; +)"); + some_class& s = lua["s"]; + assert(s.bark == 20); + std::cout << "s.bark = " << s.bark << std::endl; + + std::cout << std::endl; + + return 0; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/self_call.cpp b/3rdparty/sol2/examples/self_call.cpp new file mode 100644 index 00000000000..c64ded34133 --- /dev/null +++ b/3rdparty/sol2/examples/self_call.cpp @@ -0,0 +1,35 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include +#include + +int main() { + std::cout << "=== self_call example ===" << std::endl; + + sol::state lua; + + lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table); + + // a small script using 'self' syntax + lua.script(R"( + some_table = { some_val = 100 } + + function some_table:add_to_some_val(value) + self.some_val = self.some_val + value + end + + function print_some_val() + print("some_table.some_val = " .. some_table.some_val) + end + )"); + + // do some printing + lua["print_some_val"](); + // 100 + + sol::table self = lua["some_table"]; + self["add_to_some_val"](self, 10); + lua["print_some_val"](); + + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/static_variables.cpp b/3rdparty/sol2/examples/static_variables.cpp new file mode 100644 index 00000000000..c101e824484 --- /dev/null +++ b/3rdparty/sol2/examples/static_variables.cpp @@ -0,0 +1,61 @@ +#include + +#include +#include + +struct test { + static int muh_variable; +}; +int test::muh_variable = 25; + + +int main() { + std::cout << "=== static_variables example ===" << std::endl; + + sol::state lua; + lua.open_libraries(); + lua.new_usertype("test", + "direct", sol::var(2), + "global", sol::var(test::muh_variable), + "ref_global", sol::var(std::ref(test::muh_variable)) + ); + + int direct_value = lua["test"]["direct"]; + // direct_value == 2 + assert(direct_value == 2); + std::cout << "direct_value: " << direct_value << std::endl; + + int global = lua["test"]["global"]; + int global2 = lua["test"]["ref_global"]; + // global == 25 + // global2 == 25 + assert(global == 25); + assert(global2 == 25); + + std::cout << "First round of values --" << std::endl; + std::cout << global << std::endl; + std::cout << global2 << std::endl; + + test::muh_variable = 542; + + global = lua["test"]["global"]; + // global == 25 + // global is its own memory: was passed by value + + global2 = lua["test"]["ref_global"]; + // global2 == 542 + // global2 was passed through std::ref + // global2 holds a reference to muh_variable + // if muh_variable goes out of scope or is deleted + // problems could arise, so be careful! + + assert(global == 25); + assert(global2 == 542); + + std::cout << "Second round of values --" << std::endl; + std::cout << "global : " << global << std::endl; + std::cout << "global2: " << global2 << std::endl; + std::cout << std::endl; + + return 0; +} diff --git a/3rdparty/sol2/examples/tables.cpp b/3rdparty/sol2/examples/tables.cpp new file mode 100644 index 00000000000..41798d3b0b4 --- /dev/null +++ b/3rdparty/sol2/examples/tables.cpp @@ -0,0 +1,59 @@ +#include +#include +#include + +// this example shows how to read data in from a lua table + +int main() { + std::cout << "=== tables example ===" << std::endl; + + sol::state lua; + // table used as an array + lua.script("table1 = {\"hello\", \"table\"}"); + // table with a nested table and the key value syntax + lua.script("table2 = {" + "[\"nestedTable\"] = {" + "[\"key1\"] = \"value1\"," + "[\"key2\"]= \"value2\"" + "}," + "[\"name\"]= \"table2\"" + "}"); + + + /* Shorter Syntax: */ + // using the values stored in table1 + /*std::cout << (std::string)lua["table1"][1] << " " + << (std::string)lua["table1"][2] << '\n'; + */ + // some retrieval of values from the nested table + // the cleaner way of doing things + // chain off the the get<>() / [] results + auto t2 = lua.get("table2"); + auto nestedTable = t2.get("nestedTable"); + // Alternatively: + //sol::table t2 = lua["table2"]; + //sol::table nestedTable = t2["nestedTable"]; + + std::string x = lua["table2"]["nestedTable"]["key2"]; + std::cout << "nested table: key1 : " << nestedTable.get("key1") << ", key2: " + << x + << '\n'; + std::cout << "name of t2: " << t2.get("name") << '\n'; + std::string t2name = t2["name"]; + std::cout << "name of t2: " << t2name << '\n'; + + /* Longer Syntax: */ + // using the values stored in table1 + std::cout << lua.get("table1").get(1) << " " + << lua.get("table1").get(2) << '\n'; + + // some retrieval of values from the nested table + // the cleaner way of doing things + std::cout << "nested table: key1 : " << nestedTable.get("key1") << ", key2: " + // yes you can chain the get<>() results + << lua.get("table2").get("nestedTable").get("key2") + << '\n'; + std::cout << "name of t2: " << t2.get("name") << '\n'; + + std::cout << std::endl; +} diff --git a/3rdparty/sol2/examples/usertype.cpp b/3rdparty/sol2/examples/usertype.cpp new file mode 100644 index 00000000000..496a0b763d3 --- /dev/null +++ b/3rdparty/sol2/examples/usertype.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +struct foo { +private: + std::string name; +public: + foo(std::string name): name(std::string(name)) {} + + void print() { + std::cout << name << '\n'; + } + + int test(int x) { + return name.length() + x; + } +}; + +struct vector { +private: + float x = 0; + float y = 0; +public: + vector() = default; + vector(float x): x(x) {} + vector(float x, float y): x(x), y(y) {} + + bool is_unit() const { + return (x * x + y * y) == 1.f; + } +}; + +struct variables { + bool low_gravity = false; + int boost_level = 0; + +}; + +int main() { + std::cout << "=== usertype example ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::math); + + // the simplest way to create a class is through + // sol::state::new_userdata + // the first template is the class type + // the rest are the constructor parameters + // using new_userdata you can only have one constructor + + + // you must make sure that the name of the function + // goes before the member function pointer + lua.new_usertype("foo", "print", &foo::print, "test", &foo::test); + + // making the class from lua is simple + // same with calling member functions + lua.script("x = foo.new('test')\n" + "x:print()\n" + "y = x:test(10)"); + + auto y = lua.get("y"); + std::cout << y << std::endl; // show 14 + + // if you want a class to have more than one constructor + // the way to do so is through set_userdata and creating + // a userdata yourself with constructor types + + { + // Notice the brace: this means we're in a new scope + // first, define the different types of constructors + sol::constructors, sol::types, sol::types> ctor; + + // the only template parameter is the class type + // the first argument of construction is the name + // second is the constructor types + // then the rest are function name and member function pointer pairs + sol::usertype utype(ctor, "is_unit", &vector::is_unit); + + // then you must register it + lua.set_usertype("vector", utype); + // You can throw away the usertype after you set it: you do NOT + // have to keep it around + // cleanup happens automagically + } + // calling it is the same as new_userdata + + lua.script("v = vector.new()\n" + "v = vector.new(12)\n" + "v = vector.new(10, 10)\n" + "assert(not v:is_unit())\n"); + + // You can even have C++-like member-variable-access + // just pass is public member variables in the same style as functions + lua.new_usertype("variables", "low_gravity", &variables::low_gravity, "boost_level", &variables::boost_level); + + // making the class from lua is simple + // same with calling member functions/variables + lua.script("local vars = variables.new()\n" + "assert(not vars.low_gravity)\n" + "vars.low_gravity = true\n" + "local x = vars.low_gravity\n" + "assert(x)"); + + std::cout << std::endl; + +} diff --git a/3rdparty/sol2/examples/usertype_advanced.cpp b/3rdparty/sol2/examples/usertype_advanced.cpp new file mode 100644 index 00000000000..32679089844 --- /dev/null +++ b/3rdparty/sol2/examples/usertype_advanced.cpp @@ -0,0 +1,121 @@ +#include + +#include + +struct player { +public: + int bullets; + int speed; + + player() + : player(3, 100) { + + } + + player(int ammo) + : player(ammo, 100) { + + } + + player(int ammo, int hitpoints) + : bullets(ammo), hp(hitpoints) { + + } + + void boost() { + speed += 10; + } + + bool shoot() { + if (bullets < 1) + return false; + --bullets; + return true; + } + + void set_hp(int value) { + hp = value; + } + + int get_hp() const { + return hp; + } + +private: + int hp; +}; + +int main() { + std::cout << "=== usertype_advanced example ===" << std::endl; + sol::state lua; + + lua.open_libraries(sol::lib::base); + + // note that you can set a + // userdata before you register a usertype, + // and it will still carry + // the right metatable if you register it later + + // set a variable "p2" of type "player" with 0 ammo + lua["p2"] = player(0); + + // make usertype metatable + lua.new_usertype("player", + + // 3 constructors + sol::constructors, sol::types, sol::types>(), + + // typical member function that returns a variable + "shoot", &player::shoot, + // typical member function + "boost", &player::boost, + + // gets or set the value using member variable syntax + "hp", sol::property(&player::get_hp, &player::set_hp), + + // read and write variable + "speed", &player::speed, + // can only read from, not write to + "bullets", sol::readonly(&player::bullets) + ); + + std::string player_script = R"( +-- call single argument integer constructor +p1 = player.new(2) + +-- p2 is still here from being +-- set with lua["p2"] = player(0); below +local p2shoots = p2:shoot() +assert(not p2shoots) +-- had 0 ammo + +-- set variable property setter +p1.hp = 545 +-- get variable through property getter +print(p1.hp) +assert(p1.hp == 545) + +local did_shoot_1 = p1:shoot() +print(did_shoot_1) +print(p1.bullets) +local did_shoot_2 = p1:shoot() +print(did_shoot_2) +print(p1.bullets) +local did_shoot_3 = p1:shoot() +print(did_shoot_3) + +-- can read +print(p1.bullets) +-- would error: is a readonly variable, cannot write +-- p1.bullets = 20 + +p1:boost() +)"; + + // Uncomment and use the file to try that out, too! + // Make sure it's in the local directory of the executable after you build, or adjust the filename path + // Or whatever else you like! + //lua.script_file("player_script.lua"); + lua.script(player_script); + std::cout << std::endl; +} diff --git a/3rdparty/sol2/examples/usertype_initializers.cpp b/3rdparty/sol2/examples/usertype_initializers.cpp new file mode 100644 index 00000000000..10f1f68cb94 --- /dev/null +++ b/3rdparty/sol2/examples/usertype_initializers.cpp @@ -0,0 +1,67 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include +#include +#include + +struct holy { +private: + holy() : data() {} + holy(int value) : data(value) {} + ~holy() {} + +public: + struct deleter { + void operator()(holy* p) const { + destroy(*p); + } + }; + + const int data; + + static std::unique_ptr create() { + std::cout << "creating 'holy' unique_ptr directly and letting sol/Lua handle it" << std::endl; + return std::unique_ptr(new holy(50)); + } + + static void initialize(holy& uninitialized_memory) { + std::cout << "initializing 'holy' userdata at " << static_cast(&uninitialized_memory) << std::endl; + // receive uninitialized memory from Lua: + // properly set it by calling a constructor + // on it + // "placement new" + new (&uninitialized_memory) holy(); + } + + static void destroy(holy& memory_from_lua) { + std::cout << "destroying 'holy' userdata at " << static_cast(&memory_from_lua) << std::endl; + memory_from_lua.~holy(); + } +}; + +int main() { + std::cout << "=== usertype_initializers example ===" << std::endl; + { // additional scope to make usertype destroy earlier + sol::state lua; + lua.open_libraries(); + + lua.new_usertype("holy", + "new", sol::initializers(&holy::initialize), + "create", sol::factories(&holy::create), + sol::meta_function::garbage_collect, sol::destructor(&holy::destroy), + "data", &holy::data + ); + + lua.script(R"( +h1 = holy.create() +h2 = holy.new() +print('h1.data is ' .. h1.data) +print('h2.data is ' .. h2.data) +)"); + holy& h1 = lua["h1"]; + holy& h2 = lua["h2"]; + assert(h1.data == 50); + assert(h2.data == 0); + } + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/usertype_simple.cpp b/3rdparty/sol2/examples/usertype_simple.cpp new file mode 100644 index 00000000000..1b64e3b403f --- /dev/null +++ b/3rdparty/sol2/examples/usertype_simple.cpp @@ -0,0 +1,95 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include +#include +#include + +class generator { +private: + int data = 2; + +public: + int get_data() const { return data; } + void set_data(int value) { data = value % 10; } + + std::vector generate_list() { + return { data, data * 2, data * 3, data * 4, data * 5 }; + } +}; + +struct my_data { + int first = 4; + int second = 8; + int third = 12; +}; + +int main() { + std::cout << "=== usertype_simple example ===" << std::endl; + + sol::state lua; + lua.open_libraries(); + + // simple_usertype acts and behaves like + // a regular usertype + lua.new_simple_usertype("my_data", + "first", &my_data::first, + "second", &my_data::second, + "third", &my_data::third + ); + + { + // But, simple_usertype also has a `set` function + // where you can append things to the + // method listing after doing `create_simple_usertype`. + auto generator_registration = lua.create_simple_usertype(); + generator_registration.set("data", sol::property(&generator::get_data, &generator::set_data)); + // you MUST set the usertype after + // creating it + lua.set_usertype("generator", generator_registration); + } + + // Can update a simple_usertype at runtime, after registration + lua["generator"]["generate_list"] = [](generator& self) { return self.generate_list(); }; + // can set 'static methods' (no self) as well + lua["generator"]["get_num"] = []() { return 100; }; + + // Mix it all together! + lua.script(R"( +mdata = my_data.new() + +local g = generator.new() +g.data = mdata.first +list1 = g:generate_list() +g.data = mdata.second +list2 = g:generate_list() +g.data = mdata.third +list3 = g:generate_list() + +print("From lua: ") +for i = 1, #list1 do + print("\tlist1[" .. i .. "] = " .. list1[i]) +end +for i = 1, #list2 do + print("\tlist2[" .. i .. "] = " .. list2[i]) +end +for i = 1, #list3 do + print("\tlist3[" .. i .. "] = " .. list3[i]) +end + +)"); + my_data& mdata = lua["mdata"]; + std::vector& list1 = lua["list1"]; + std::vector& list2 = lua["list2"]; + std::vector& list3 = lua["list3"]; + assert(list1.size() == 5); + assert(list2.size() == 5); + assert(list3.size() == 5); + for (int i = 1; i <= 5; ++i) { + assert(list1[i - 1] == (mdata.first % 10) * i); + assert(list2[i - 1] == (mdata.second % 10) * i); + assert(list3[i - 1] == (mdata.third % 10) * i); + } + + std::cout << std::endl; + return 0; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/usertype_special_functions.cpp b/3rdparty/sol2/examples/usertype_special_functions.cpp new file mode 100644 index 00000000000..ef1492dfc76 --- /dev/null +++ b/3rdparty/sol2/examples/usertype_special_functions.cpp @@ -0,0 +1,70 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include +#include +#include + +struct vec { + double x; + double y; + + vec() : x(0), y(0) {} + vec(double x, double y) : x(x), y(y) {} + + vec operator-(const vec& right) const { + return vec(x - right.x, y - right.y); + } +}; + +double dot(const vec& left, const vec& right) { + return left.x * right.x + left.x * right.x; +} + +vec operator+(const vec& left, const vec& right) { + return vec(left.x + right.x, left.y + right.y); +} + +int main() { + sol::state lua; + lua.open_libraries(); + + lua.new_usertype("vec", + sol::constructors, sol::types>(), + "dot", &dot, + "norm", [](const vec& self) { double len = std::sqrt(dot(self, self)); return vec(self.x / len, self.y / len); }, + // we use `sol::resolve` because other operator+ can exist + // in the (global) namespace + sol::meta_function::addition, sol::resolve(::operator+), + sol::meta_function::subtraction, &vec::operator- + ); + + lua.script(R"( + v1 = vec.new(1, 0) + v2 = vec.new(0, 1) + -- as "member function" + d1 = v1:dot(v2) + -- as "static" / "free function" + d2 = vec.dot(v1, v2) + assert(d1 == d2) + + -- doesn't matter if + -- bound as free function + -- or member function: + a1 = v1 + v2 + s1 = v1 - v2 +)"); + + vec& a1 = lua["a1"]; + vec& s1 = lua["s1"]; + + assert(a1.x == 1 && a1.y == 1); + assert(s1.x == 1 && s1.y == -1); + + lua["a2"] = lua["a1"]; + + lua.script(R"( + assert(a1 == a2) + )"); + + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/usertype_var.cpp b/3rdparty/sol2/examples/usertype_var.cpp new file mode 100644 index 00000000000..9f56490aa29 --- /dev/null +++ b/3rdparty/sol2/examples/usertype_var.cpp @@ -0,0 +1,45 @@ +#define SOL_CHECK_ARGUMENTS +#include +#include + +struct test { + static int number; +}; +int test::number = 25; + + +int main() { + sol::state lua; + lua.open_libraries(); + lua.new_usertype("test", + "direct", sol::var(2), + "number", sol::var(test::number), + "ref_number", sol::var(std::ref(test::number)) + ); + + int direct_value = lua["test"]["direct"]; + assert(direct_value == 2); + // direct_value == 2 + + int number = lua["test"]["number"]; + assert(number == 25); + int ref_number = lua["test"]["ref_number"]; + assert(ref_number == 25); + + test::number = 542; + + assert(lua["test"]["number"] == 25); + // number is its own memory: was passed by value + // So does not change + + assert(lua["test"]["ref_number"] == 542); + // ref_number is just test::number + // passed through std::ref + // so, it holds a reference + // which can be updated + // be careful about referencing local variables, + // if they go out of scope but are still reference + // you'll suffer dangling reference bugs! + + return 0; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/variables.cpp b/3rdparty/sol2/examples/variables.cpp new file mode 100644 index 00000000000..ece88915703 --- /dev/null +++ b/3rdparty/sol2/examples/variables.cpp @@ -0,0 +1,37 @@ +#include +#include + +int main() { + std::cout << "=== variables example ===" << std::endl; + + sol::state lua; + + // need the base library for assertions + lua.open_libraries(sol::lib::base); + + // basic setting of a variable + // through multiple ways + lua["x"] = 10; + lua.set("y", "hello"); + + // assert values are as given + lua.script("assert(x == 10)"); + lua.script("assert(y == 'hello')"); + + + // basic retrieval of a variable + // through multiple ways + int x = lua["x"]; + auto y = lua.get("y"); + + int x2; + std::string y2; + std::tie(x2, y2) = lua.get("x", "y"); + + // show the values + std::cout << x << std::endl; + std::cout << y << std::endl; + std::cout << x2 << std::endl; + std::cout << y2 << std::endl; + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/examples/variadic_args.cpp b/3rdparty/sol2/examples/variadic_args.cpp new file mode 100644 index 00000000000..918e33ec790 --- /dev/null +++ b/3rdparty/sol2/examples/variadic_args.cpp @@ -0,0 +1,40 @@ +#include + +#include + +int main() { + std::cout << "=== variadic_args example ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // Function requires 2 arguments + // rest can be variadic, but: + // va will include everything after "a" argument, + // which means "b" will be part of the varaidic_args list too + // at position 0 + lua.set_function("v", [](int a, sol::variadic_args va, int /*b*/) { + int r = 0; + for (auto v : va) { + int value = v; // get argument out (implicit conversion) + // can also do int v = va.get(i); with index i + r += value; + } + // Only have to add a, b was included from variadic_args and beyond + return r + a; + }); + + lua.script("x = v(25, 25)"); + lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); + lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); + // will error: not enough arguments + //lua.script("x4 = v(1)"); + + lua.script("assert(x == 50)"); + lua.script("assert(x2 == 600)"); + lua.script("assert(x3 == 21)"); + lua.script("print(x)"); // 50 + lua.script("print(x2)"); // 600 + lua.script("print(x3)"); // 21 + std::cout << std::endl; +} \ No newline at end of file diff --git a/3rdparty/sol2/install.deps.sh b/3rdparty/sol2/install.deps.sh new file mode 100644 index 00000000000..b3571190663 --- /dev/null +++ b/3rdparty/sol2/install.deps.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +# This script installs and configures the dependencies for the project + +case `uname` in + Darwin) export OS_NAME="osx" ;; + Linux) export OS_NAME="linux" ;; +esac + +echo "Building on: ${OS_NAME}" + +if env | grep -qE '^(?:TRAVIS|CI)='; then +# We're on Travis, intialize variables: + echo "Detected CI Build -> CI=${CI}" +else +# We're building locally + export CI=false + echo "Detected Local Build -> CI=${CI}" +fi + +export_compiler_vars() { + case ${COMPILER} in + appleclang*) + export CC=clang + export CXX=clang++ + ;; + + clang*) + export CC=$(echo ${COMPILER} | sed 's/\+//g') + export CXX=${COMPILER} + ;; + + g++-*) + export CC=$(echo ${COMPILER} | sed 's/\+/c/g') + export CXX=${COMPILER} + ;; + + *) echo "Invalid compiler version" ; exit 2 ;; + esac + + echo "CC=${CC}" + $CC --version + + echo "CXX=${CXX}" + $CXX --version +} + +install_os_deps() { + # Install all of the OS specific OS dependencies + echo "Install: os-based dependencies" + + local wd=`pwd` + + case ${OS_NAME} in + osx) + export HOMEBREW_NO_EMOJI=1 + + echo "brew update ..."; brew update > /dev/null + + case ${COMPILER} in + appleclang*) ;; + + g++-5) + brew install gcc5 + brew link gcc5 --overwrite --force + ;; + + g++-4.9) ;; + + *) echo "Invalid compiler version" ; exit 2 ;; + esac + + brew install ninja + + local lua_pkg + case ${LUA_VERSION} in + lua53) lua_pkg=lua53 ;; + lua52) lua_pkg=lua ;; + lua51) lua_pkg=lua51 ;; + luajit52) lua_pkg=luajit ;; + luajit) lua_pkg=luajit ;; + *) echo "Invalid Lua Version for OSX" + exit 2 + ;; + esac + + brew install ${lua_pkg} + ;; + + linux) + # no extras currently + ;; + esac + + cd ${wd} +} diff --git a/3rdparty/sol2/ninja_syntax.py b/3rdparty/sol2/ninja_syntax.py new file mode 100644 index 00000000000..14b932ff4c8 --- /dev/null +++ b/3rdparty/sol2/ninja_syntax.py @@ -0,0 +1,156 @@ +#!/usr/bin/python + +"""Python module for generating .ninja files. + +Note that this is emphatically not a required piece of Ninja; it's +just a helpful utility for build-file-generation systems that already +use Python. +""" + +import textwrap + +def escape_path(word): + return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') + +class Writer(object): + def __init__(self, output, width=78): + self.output = output + self.width = width + + def newline(self): + self.output.write('\n') + + def comment(self, text): + for line in textwrap.wrap(text, self.width - 2): + self.output.write('# ' + line + '\n') + + def variable(self, key, value, indent=0): + if value is None: + return + if isinstance(value, list): + value = ' '.join(filter(None, value)) # Filter out empty strings. + self._line('%s = %s' % (key, value), indent) + + def pool(self, name, depth): + self._line('pool %s' % name) + self.variable('depth', depth, indent=1) + + def rule(self, name, command, description=None, depfile=None, + generator=False, pool=None, restat=False, rspfile=None, + rspfile_content=None, deps=None): + self._line('rule %s' % name) + self.variable('command', command, indent=1) + if description: + self.variable('description', description, indent=1) + if depfile: + self.variable('depfile', depfile, indent=1) + if generator: + self.variable('generator', '1', indent=1) + if pool: + self.variable('pool', pool, indent=1) + if restat: + self.variable('restat', '1', indent=1) + if rspfile: + self.variable('rspfile', rspfile, indent=1) + if rspfile_content: + self.variable('rspfile_content', rspfile_content, indent=1) + if deps: + self.variable('deps', deps, indent=1) + + def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, + variables=None): + outputs = self._as_list(outputs) + out_outputs = [escape_path(x) for x in outputs] + all_inputs = [escape_path(x) for x in self._as_list(inputs)] + + if implicit: + implicit = [escape_path(x) for x in self._as_list(implicit)] + all_inputs.append('|') + all_inputs.extend(implicit) + if order_only: + order_only = [escape_path(x) for x in self._as_list(order_only)] + all_inputs.append('||') + all_inputs.extend(order_only) + + self._line('build %s: %s' % (' '.join(out_outputs), + ' '.join([rule] + all_inputs))) + + if variables: + if isinstance(variables, dict): + iterator = iter(variables.items()) + else: + iterator = iter(variables) + + for key, val in iterator: + self.variable(key, val, indent=1) + + return outputs + + def include(self, path): + self._line('include %s' % path) + + def subninja(self, path): + self._line('subninja %s' % path) + + def default(self, paths): + self._line('default %s' % ' '.join(self._as_list(paths))) + + def _count_dollars_before_index(self, s, i): + """Returns the number of '$' characters right in front of s[i].""" + dollar_count = 0 + dollar_index = i - 1 + while dollar_index > 0 and s[dollar_index] == '$': + dollar_count += 1 + dollar_index -= 1 + return dollar_count + + def _line(self, text, indent=0): + """Write 'text' word-wrapped at self.width characters.""" + leading_space = ' ' * indent + while len(leading_space) + len(text) > self.width: + # The text is too wide; wrap if possible. + + # Find the rightmost space that would obey our width constraint and + # that's not an escaped space. + available_space = self.width - len(leading_space) - len(' $') + space = available_space + while True: + space = text.rfind(' ', 0, space) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break + + if space < 0: + # No such space; just use the first unescaped space we can find. + space = available_space - 1 + while True: + space = text.find(' ', space + 1) + if (space < 0 or + self._count_dollars_before_index(text, space) % 2 == 0): + break + if space < 0: + # Give up on breaking. + break + + self.output.write(leading_space + text[0:space] + ' $\n') + text = text[space+1:] + + # Subsequent lines are continuations, so indent them. + leading_space = ' ' * (indent+2) + + self.output.write(leading_space + text + '\n') + + def _as_list(self, input): + if input is None: + return [] + if isinstance(input, list): + return input + return [input] + + +def escape(string): + """Escape a string such that it can be embedded into a Ninja file without + further interpretation.""" + assert '\n' not in string, 'Ninja syntax does not allow newlines' + # We only have one special metacharacter: '$'. + return string.replace('$', '$$') diff --git a/3rdparty/sol2/single.py b/3rdparty/sol2/single.py new file mode 100644 index 00000000000..f53a9410320 --- /dev/null +++ b/3rdparty/sol2/single.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python + +import argparse +import os, sys +import re +import datetime as dt + +# python 3 compatibility +try: + import cStringIO as sstream +except ImportError: + from io import StringIO + +description = "Converts sol to a single file for convenience." + +# command line parser +parser = argparse.ArgumentParser(usage='%(prog)s [options...]', description=description) +parser.add_argument('--output', '-o', help='name and location of where to place file', metavar='file', default='sol.hpp') +parser.add_argument('--quiet', help='suppress all output', action='store_true') +args = parser.parse_args() + +script_path = os.path.normpath(os.path.dirname(os.path.realpath(__file__))) +working_dir = os.getcwd() +os.chdir(script_path) + +intro = """// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated {time} UTC +// This header was generated with sol {version} (revision {revision}) +// https://github.com/ThePhD/sol2 + +#ifndef {guard} +#define {guard} + +""" + +module_path = os.path.join(script_path) + +includes = set([]) +standard_include = re.compile(r'#include <(.*?)>') +local_include = re.compile(r'#include "(.*?)"') +ifndef_cpp = re.compile(r'#ifndef SOL_.*?_HPP') +define_cpp = re.compile(r'#define SOL_.*?_HPP') +endif_cpp = re.compile(r'#endif // SOL_.*?_HPP') + +def get_include(line, base_path): + local_match = local_include.match(line) + if local_match: + # local include found + full_path = os.path.normpath(os.path.join(base_path, local_match.group(1))).replace('\\', '/') + return full_path + + return None + + +def is_include_guard(line): + return ifndef_cpp.match(line) or define_cpp.match(line) or endif_cpp.match(line) + +def get_revision(): + return os.popen('git rev-parse --short HEAD').read().strip() + +def get_version(): + return os.popen('git describe --tags --abbrev=0').read().strip() + +def process_file(filename, out): + global includes + filename = os.path.normpath(filename) + relativefilename = filename.replace(script_path + os.sep, "").replace("\\", "/") + + if filename in includes: + return + + includes.add(filename) + + if not args.quiet: + print('processing {}'.format(filename)) + + out.write('// beginning of {}\n\n'.format(relativefilename)) + empty_line_state = True + + with open(filename, 'r', encoding='utf-8') as f: + for line in f: + # skip comments + if line.startswith('//'): + continue + + # skip include guard non-sense + if is_include_guard(line): + continue + + # get relative directory + base_path = os.path.dirname(filename) + + # check if it's a standard file + std = standard_include.search(line) + if std: + std_file = os.path.join('std', std.group(0)) + if std_file in includes: + continue + includes.add(std_file) + + # see if it's an include file + name = get_include(line, base_path) + + if name: + process_file(name, out) + continue + + empty_line = len(line.strip()) == 0 + + if empty_line and empty_line_state: + continue + + empty_line_state = empty_line + + # line is fine + out.write(line) + + out.write('// end of {}\n\n'.format(relativefilename)) + + +version = get_version() +revision = get_revision() +include_guard = 'SOL_SINGLE_INCLUDE_HPP' + +if not args.quiet: + print('Creating single header for sol') + print('Current version: {version} (revision {revision})\n'.format(version = version, revision = revision)) + + +processed_files = [os.path.join(script_path, 'sol', x) for x in ('state.hpp', 'object.hpp', 'function.hpp', 'coroutine.hpp')] +result = '' + +ss = StringIO() +ss.write(intro.format(time=dt.datetime.utcnow(), revision=revision, version=version, guard=include_guard)) +for processed_file in processed_files: + process_file(processed_file, ss) + +ss.write('#endif // {}\n'.format(include_guard)) +result = ss.getvalue() +ss.close() + +with open(args.output, 'w', encoding='utf-8') as f: + f.write(result) + diff --git a/3rdparty/sol2/single/sol/sol.hpp b/3rdparty/sol2/single/sol/sol.hpp new file mode 100644 index 00000000000..c2c8a328bc3 --- /dev/null +++ b/3rdparty/sol2/single/sol/sol.hpp @@ -0,0 +1,12323 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2016-10-06 00:53:22.017715 UTC +// This header was generated with sol v2.14.9 (revision 0ba4650) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_HPP +#define SOL_SINGLE_INCLUDE_HPP + +// beginning of sol/state.hpp + +// beginning of sol/state_view.hpp + +// beginning of sol/error.hpp + +#include +#include + +namespace sol { + namespace detail { + struct direct_error_tag {}; + const auto direct_error = direct_error_tag{}; + } // detail + + class error : public std::runtime_error { + private: + // Because VC++ is a fuccboi + std::string w; + public: + error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} + error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} + error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} + + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return w.c_str(); + } + }; + +} // sol + +// end of sol/error.hpp + +// beginning of sol/table.hpp + +// beginning of sol/table_core.hpp + +// beginning of sol/proxy.hpp + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +#include +#include + +namespace sol { + namespace detail { + using swallow = std::initializer_list; + } // detail + + template + struct types { typedef std::make_index_sequence indices; static constexpr std::size_t size() { return sizeof...(Args); } }; + namespace meta { + namespace detail { + template + struct tuple_types_ { typedef types type; }; + + template + struct tuple_types_> { typedef types type; }; + } // detail + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + template + using tuple_types = typename detail::tuple_types_::type; + + template + struct pop_front_type; + + template + using pop_front_type_t = typename pop_front_type::type; + + template + struct pop_front_type> { typedef void front_type; typedef types type; }; + + template + struct pop_front_type> { typedef Arg front_type; typedef types type; }; + + template + using tuple_element = std::tuple_element>; + + template + using tuple_element_t = std::tuple_element_t>; + + template + using unqualified_tuple_element = unqualified>; + + template + using unqualified_tuple_element_t = unqualified_t>; + + } // meta +} // sol + +// end of sol/tuple.hpp + +// beginning of sol/bind_traits.hpp + +namespace sol { + namespace meta { + namespace meta_detail { + + template + struct check_deducible_signature { + struct nat {}; + template + static auto test(int) -> decltype(&G::operator(), void()); + template + static auto test(...)->nat; + + using type = std::is_void(0))>; + }; + } // meta_detail + + template + struct has_deducible_signature : meta_detail::check_deducible_signature::type { }; + + namespace meta_detail { + + template + struct void_tuple_element : meta::tuple_element {}; + + template + struct void_tuple_element> { typedef void type; }; + + template + using void_tuple_element_t = typename void_tuple_element::type; + + template + struct basic_traits { + private: + typedef std::conditional_t::value, int, T>& first_type; + + public: + static const bool is_member_function = std::is_void::value; + static const bool has_c_var_arg = has_c_variadic; + static const std::size_t arity = sizeof...(Args); + static const std::size_t free_arity = sizeof...(Args)+static_cast(!std::is_void::value); + typedef types args_list; + typedef std::tuple args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types returns_list; + typedef R(function_type)(Args...); + typedef std::conditional_t::value, args_list, types> free_args_list; + typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef std::conditional_t::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t signature_type; + template + using arg_at = void_tuple_element_t; + }; + + template::value> + struct fx_traits : basic_traits {}; + + // Free Functions + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + // Member Functions + /* C-Style Variadics */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; + }; + + template + struct fx_traits : fx_traits::function_type, false> {}; + + template::value> + struct callable_traits : fx_traits> { + + }; + + template + struct callable_traits { + typedef R Arg; + typedef T object_type; + using signature_type = R(T::*); + static const bool is_member_function = false; + static const std::size_t arity = 1; + static const std::size_t free_arity = 2; + typedef std::tuple args_tuple; + typedef R return_type; + typedef types args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + typedef R(function_type)(T&, R); + typedef R(*function_pointer_type)(T&, R); + typedef R(*free_function_pointer_type)(T&, R); + template + using arg_at = void_tuple_element_t; + }; + } // meta_detail + + template + struct bind_traits : meta_detail::callable_traits {}; + + template + using function_args_t = typename bind_traits::args_list; + + template + using function_signature_t = typename bind_traits::signature_type; + + template + using function_return_t = typename bind_traits::return_type; + + } // meta +} // sol + +// end of sol/bind_traits.hpp + +#include +#include +#include + +namespace sol { + template + using index_value = std::integral_constant; + + namespace meta { + template + struct identity { typedef T type; }; + + template + using identity_t = typename identity::type; + + template + struct is_tuple : std::false_type { }; + + template + struct is_tuple> : std::true_type { }; + + template + struct unwrapped { + typedef T type; + }; + + template + struct unwrapped> { + typedef T type; + }; + + template + using unwrapped_t = typename unwrapped::type; + + template + struct unwrap_unqualified : unwrapped> {}; + + template + using unwrap_unqualified_t = typename unwrap_unqualified::type; + + template + struct remove_member_pointer; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + using remove_member_pointer_t = remove_member_pointer; + + template class Templ, typename T> + struct is_specialization_of : std::false_type { }; + template class Templ> + struct is_specialization_of> : std::true_type { }; + + template + struct all_same : std::true_type { }; + + template + struct all_same : std::integral_constant ::value && all_same::value> { }; + + template + struct any_same : std::false_type { }; + + template + struct any_same : std::integral_constant ::value || any_same::value> { }; + + template + using invoke_t = typename T::type; + + template + using boolean = std::integral_constant; + + template + using neg = boolean; + + template + using condition = std::conditional_t; + + template + struct all : boolean {}; + + template + struct all : condition, boolean> {}; + + template + struct any : boolean {}; + + template + struct any : condition, any> {}; + + enum class enable_t { + _ + }; + + constexpr const auto enabler = enable_t::_; + + template + using disable_if_t = std::enable_if_t; + + template + using enable = std::enable_if_t::value, enable_t>; + + template + using disable = std::enable_if_t>::value, enable_t>; + + template + using disable_any = std::enable_if_t>::value, enable_t>; + + template + struct find_in_pack_v : boolean { }; + + template + struct find_in_pack_v : any, find_in_pack_v> { }; + + namespace meta_detail { + template + struct index_in_pack : std::integral_constant { }; + + template + struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> { }; + } + + template + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct index_in : meta_detail::index_in_pack<0, T, List> { }; + + template + struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct at_in_pack {}; + + template + using at_in_pack_t = typename at_in_pack::type; + + template + struct at_in_pack : std::conditional> {}; + + template + struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; + + namespace meta_detail { + template class Pred, typename... Ts> + struct count_for_pack : std::integral_constant {}; + template class Pred, typename T, typename... Ts> + struct count_for_pack : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, + std::integral_constant(Limit != 0 && Pred::value)>, + count_for_pack(Pred::value), Pred, Ts...> + > { }; + template class Pred, typename... Ts> + struct count_2_for_pack : std::integral_constant {}; + template class Pred, typename T, typename U, typename... Ts> + struct count_2_for_pack : std::conditional_t(Pred::value)>, + count_2_for_pack(Pred::value), Pred, Ts...> + > { }; + } // meta_detail + + template class Pred, typename... Ts> + struct count_for_pack : meta_detail::count_for_pack { }; + + template class Pred, typename List> + struct count_for; + + template class Pred, typename... Args> + struct count_for> : count_for_pack {}; + + template class Pred, typename... Ts> + struct count_for_to_pack : meta_detail::count_for_pack { }; + + template class Pred, typename... Ts> + struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; + + template + struct return_type { + typedef std::tuple type; + }; + + template + struct return_type { + typedef T type; + }; + + template<> + struct return_type<> { + typedef void type; + }; + + template + using return_type_t = typename return_type::type; + + namespace meta_detail { + template struct always_true : std::true_type {}; + struct is_invokable_tester { + template + always_true()(std::declval()...))> static test(int); + template + std::false_type static test(...); + }; + } // meta_detail + + template + struct is_invokable; + template + struct is_invokable : decltype(meta_detail::is_invokable_tester::test(0)) {}; + + namespace meta_detail { + + template>::value> + struct is_callable : std::is_function> {}; + + template + struct is_callable { + using yes = char; + using no = struct { char s[2]; }; + + struct F { void operator()(); }; + struct Derived : T, F {}; + template struct Check; + + template + static no test(Check*); + + template + static yes test(...); + + static const bool value = sizeof(test(0)) == sizeof(yes); + }; + + struct has_begin_end_impl { + template, + typename B = decltype(std::declval().begin()), + typename E = decltype(std::declval().end())> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_key_value_pair_impl { + template, + typename V = typename U::value_type, + typename F = decltype(std::declval().first), + typename S = decltype(std::declval().second)> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + template () < std::declval())> + std::true_type supports_op_less_test(const T&); + std::false_type supports_op_less_test(...); + template () == std::declval())> + std::true_type supports_op_equal_test(const T&); + std::false_type supports_op_equal_test(...); + template () <= std::declval())> + std::true_type supports_op_less_equal_test(const T&); + std::false_type supports_op_less_equal_test(...); + + } // meta_detail + + template + using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval())); + template + using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval())); + template + using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval())); + + template + struct is_callable : boolean::value> {}; + + template + struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test(0)) {}; + + template + struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; + + template + using is_string_constructible = any, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; + + template + using is_c_str = any< + std::is_same>, const char*>, + std::is_same>, char*>, + std::is_same, std::string> + >; + + template + struct is_move_only : all< + neg>, + neg>>, + std::is_move_constructible> + > {}; + + template + using is_not_move_only = neg>; + + namespace meta_detail { + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward_as_tuple(std::forward(x)); + } + + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward(x); + } + } // meta_detail + + template + decltype(auto) tuplefy(X&&... x) { + return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); + } + } // meta + namespace detail { + template + decltype(auto) forward_get(Tuple&& tuple) { + return std::forward>(std::get(tuple)); + } + + template + auto forward_tuple_impl(std::index_sequence, Tuple&& tuple) -> decltype(std::tuple(tuple))...>(forward_get(tuple)...)) { + return std::tuple(tuple))...>(std::move(std::get(tuple))...); + } + + template + auto forward_tuple(Tuple&& tuple) { + auto x = forward_tuple_impl(std::make_index_sequence>::value>(), std::forward(tuple)); + return x; + } + + template + auto unwrap(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + T& unwrap(std::reference_wrapper arg) { + return arg.get(); + } + + template + auto deref(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + inline T& deref(T* item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::shared_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::shared_ptr& item) { + return *item; + } + + template + inline T* ptr(T& val) { + return std::addressof(val); + } + + template + inline T* ptr(std::reference_wrapper val) { + return std::addressof(val.get()); + } + + template + inline T* ptr(T* val) { + return val; + } + } // detail +} // sol + +// end of sol/traits.hpp + +// beginning of sol/object.hpp + +// beginning of sol/optional.hpp + +// beginning of sol/in_place.hpp + +namespace sol { + + namespace detail { + struct in_place_of {}; + template + struct in_place_of_i {}; + template + struct in_place_of_t {}; + } // detail + + struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; }; + constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); } + template + constexpr inline in_place_tag in_place(detail::in_place_of_t) { return in_place_tag(in_place_tag::init()); } + template + constexpr inline in_place_tag in_place(detail::in_place_of_i) { return in_place_tag(in_place_tag::init()); } + + using in_place_t = in_place_tag(&)(detail::in_place_of); + template + using in_place_type_t = in_place_tag(&)(detail::in_place_of_t); + template + using in_place_index_t = in_place_tag(&)(detail::in_place_of_i); + +} // sol + +// end of sol/in_place.hpp + +#if defined(SOL_USE_BOOST) +#include +#else +// beginning of Optional/optional.hpp + +# ifndef ___SOL_OPTIONAL_HPP___ +# define ___SOL_OPTIONAL_HPP___ + +# include +# include +# include +# include +# include +# include +# include + +# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __GNUC__ // NOTE: GNUC is also defined for Clang +# if (__GNUC__ >= 5) +# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# endif +# endif +# +# if defined __clang_major__ +# if (__clang_major__ == 3 && __clang_minor__ >= 5) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# elif (__clang_major__ > 3) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# endif +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# endif +# endif +# +# if defined _MSC_VER +# if (_MSC_VER >= 1900) +# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# endif +# endif + +# if defined __clang__ +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif + +# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +# else +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +# define OPTIONAL_CONSTEXPR_INIT_LIST +# endif + +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) +# define OPTIONAL_HAS_MOVE_ACCESSORS 1 +# else +# define OPTIONAL_HAS_MOVE_ACCESSORS 0 +# endif + +# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +# if (defined __cplusplus) && (__cplusplus == 201103L) +# define OPTIONAL_MUTABLE_CONSTEXPR +# else +# define OPTIONAL_MUTABLE_CONSTEXPR constexpr +# endif + +namespace sol{ + +# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it: it is already there +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + template + using is_trivially_destructible = ::std::has_trivial_destructor; +# endif + +# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + +template +struct is_nothrow_move_constructible +{ + constexpr static bool value = ::std::is_nothrow_constructible::value; +}; + +template +struct is_assignable +{ + template + constexpr static bool has_assign(...) { return false; } + + template () = ::std::declval(), true)) > + // the comma operator is necessary for the cases where operator= returns void + constexpr static bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign(true); +}; + +template +struct is_nothrow_move_assignable +{ + template + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template + struct has_nothrow_move_assign { + constexpr static bool value = noexcept( ::std::declval() = ::std::declval() ); + }; + + constexpr static bool value = has_nothrow_move_assign::value>::value; +}; + +# endif + +template class optional; + +template class optional; + +template inline constexpr T&& constexpr_forward(typename ::std::remove_reference::type& t) noexcept +{ + return static_cast(t); +} + +template inline constexpr T&& constexpr_forward(typename ::std::remove_reference::type&& t) noexcept +{ + static_assert(!::std::is_lvalue_reference::value, "!!"); + return static_cast(t); +} + +template inline constexpr typename ::std::remove_reference::type&& constexpr_move(T&& t) noexcept +{ + return static_cast::type&&>(t); +} + +#if defined NDEBUG +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#endif + +namespace detail_ +{ + +template +struct has_overloaded_addressof +{ + template + constexpr static bool has_overload(...) { return false; } + + template ().operator&()) > + constexpr static bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload(true); +}; + +template )> +constexpr T* static_addressof(T& ref) +{ + return &ref; +} + +template )> +T* static_addressof(T& ref) +{ + return ::std::addressof(ref); +} + +template +constexpr U convert(U v) { return v; } + +} // namespace detail_ + +constexpr struct trivial_init_t {} trivial_init{}; + +struct nullopt_t +{ + struct init{}; + constexpr explicit nullopt_t(init){} +}; +constexpr nullopt_t nullopt{nullopt_t::init()}; + +class bad_optional_access : public ::std::logic_error { +public: + explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{what_arg} {} + explicit bad_optional_access(const char* what_arg) : ::std::logic_error{what_arg} {} +}; + +template +struct optional_base +{ + bool init_; + char storage_[sizeof(T)]; + + constexpr optional_base() noexcept : init_(false), storage_() {}; + + explicit optional_base(const T& v) : init_(true), storage_() { + new (&storage())T(v); + } + + explicit optional_base(T&& v) : init_(true), storage_() { + new (&storage())T(constexpr_move(v)); + } + + template explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward(args)...); + } + + template >)> + explicit optional_base(in_place_t, ::std::initializer_list il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward(args)...); + } +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return *reinterpret_cast(&storage_[0]); + } + + constexpr const T& storage() const { + return *reinterpret_cast(&storage_[0]); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~optional_base() { if (init_) { storage().T::~T(); } } +}; + +#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ +template +using constexpr_optional_base = optional_base; +#else +template +struct constexpr_optional_base +{ + bool init_; + char storage_[sizeof(T)]; + constexpr constexpr_optional_base() noexcept : init_(false), storage_() {} + + explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_() { + new (&storage())T(v); + } + + explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_() { + new (&storage())T(constexpr_move(v)); + } + + template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward(args)...); + } + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward(args)...); + } + +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return (*reinterpret_cast(&storage_[0])); + } + + constexpr const T& storage() const { + return (*reinterpret_cast(&storage_[0])); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~constexpr_optional_base() = default; +}; +#endif + +template +using OptionalBase = typename ::std::conditional< + ::std::is_trivially_destructible::value, + constexpr_optional_base::type>, + optional_base::type> +>::type; + +template +class optional : private OptionalBase +{ + static_assert( !::std::is_same::type, nullopt_t>::value, "bad T" ); + static_assert( !::std::is_same::type, in_place_t>::value, "bad T" ); + + constexpr bool initialized() const noexcept { return OptionalBase::init_; } + typename ::std::remove_const::type* dataptr() { return ::std::addressof(OptionalBase::storage()); } + constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage()); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase::storage(); } +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase::storage()); } + OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage(); } +# else + T& contained_val() & { return OptionalBase::storage(); } + T&& contained_val() && { return ::std::move(OptionalBase::storage()); } +# endif +# else + constexpr const T& contained_val() const { return OptionalBase::storage(); } + T& contained_val() { return OptionalBase::storage(); } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase::init_ = false; + } + + template + void initialize(Args&&... args) noexcept(noexcept(T(::std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(::std::forward(args)...); + OptionalBase::init_ = true; + } + + template + void initialize(::std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, ::std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(il, ::std::forward(args)...); + OptionalBase::init_ = true; + } + +public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + + optional(const optional& rhs) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(const optional& rhs) : optional() + { + if (rhs) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible::value) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(::std::move(*rhs)); + OptionalBase::init_ = true; + } + } + + constexpr optional(const T& v) : OptionalBase(v) {} + + constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} + + template + explicit constexpr optional(in_place_t, Args&&... args) + : OptionalBase(in_place, constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list il, Args&&... args) + : OptionalBase(in_place, il, constexpr_forward(args)...) {} + + // 20.5.4.2, Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(::std::is_nothrow_move_assignable::value && ::std::is_nothrow_move_constructible::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs); + return *this; + } + + template + auto operator=(U&& v) + -> typename ::std::enable_if + < + ::std::is_same::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = ::std::forward(v); } + else { initialize(::std::forward(v)); } + return *this; + } + + template + void emplace(Args&&... args) + { + clear(); + initialize(::std::forward(args)...); + } + + template + void emplace(::std::initializer_list il, Args&&... args) + { + clear(); + initialize(il, ::std::forward(args)...); + } + + // 20.5.4.4, Swap + void swap(optional& rhs) noexcept(::std::is_nothrow_move_constructible::value && noexcept(swap(::std::declval(), ::std::declval()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5, Observers + + explicit constexpr operator bool() const noexcept { return initialized(); } + + constexpr T const* operator ->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const& { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { + assert (initialized()); + return contained_val(); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { + assert (initialized()); + return constexpr_move(contained_val()); + } + + constexpr T const& value() const& { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& value() & { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { + if (!initialized()) throw bad_optional_access("bad optional access"); + return ::std::move(contained_val()); + } + +# else + + T* operator ->() { + assert (initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert (initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + + T& value() { + return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); + } + +# endif + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template + constexpr T value_or(V&& v) const& + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + template + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# else + + template + T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# endif + +# else + + template + constexpr T value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# endif + +}; + +template +class optional +{ + static_assert( !::std::is_same::value, "bad T" ); + static_assert( !::std::is_same::value, "bad T" ); + T* ref; + +public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + ::std::is_same::type, optional>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + !::std::is_same::type, optional>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = detail_::static_addressof(v); + } + + void emplace(T&&) = delete; + + void swap(optional& rhs) noexcept + { + ::std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { + return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + template + constexpr T& value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } +}; + +template +class optional +{ + static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); +}; + +template constexpr bool operator==(const optional& x, const optional& y) +{ + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; +} + +template constexpr bool operator!=(const optional& x, const optional& y) +{ + return !(x == y); +} + +template constexpr bool operator<(const optional& x, const optional& y) +{ + return (!y) ? false : (!x) ? true : *x < *y; +} + +template constexpr bool operator>(const optional& x, const optional& y) +{ + return (y < x); +} + +template constexpr bool operator<=(const optional& x, const optional& y) +{ + return !(y < x); +} + +template constexpr bool operator>=(const optional& x, const optional& y) +{ + return !(x < y); +} + +template constexpr bool operator==(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator==(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + +template constexpr bool operator!=(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator!=(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<(const optional&, nullopt_t) noexcept +{ + return false; +} + +template constexpr bool operator<(nullopt_t, const optional& x) noexcept +{ + return bool(x); +} + +template constexpr bool operator<=(const optional& x, nullopt_t) noexcept +{ + return (!x); +} + +template constexpr bool operator<=(nullopt_t, const optional&) noexcept +{ + return true; +} + +template constexpr bool operator>(const optional& x, nullopt_t) noexcept +{ + return bool(x); +} + +template constexpr bool operator>(nullopt_t, const optional&) noexcept +{ + return false; +} + +template constexpr bool operator>=(const optional&, nullopt_t) noexcept +{ + return true; +} + +template constexpr bool operator>=(nullopt_t, const optional& x) noexcept +{ + return (!x); +} + +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + +template constexpr bool operator==(const optional& x, const T& v) +{ + return bool(x) ? *x == v : false; +} + +template constexpr bool operator==(const T& v, const optional& x) +{ + return bool(x) ? v == *x : false; +} + +template constexpr bool operator!=(const optional& x, const T& v) +{ + return bool(x) ? *x != v : true; +} + +template constexpr bool operator!=(const T& v, const optional& x) +{ + return bool(x) ? v != *x : true; +} + +template constexpr bool operator<(const optional& x, const T& v) +{ + return bool(x) ? *x < v : true; +} + +template constexpr bool operator>(const T& v, const optional& x) +{ + return bool(x) ? v > *x : true; +} + +template constexpr bool operator>(const optional& x, const T& v) +{ + return bool(x) ? *x > v : false; +} + +template constexpr bool operator<(const T& v, const optional& x) +{ + return bool(x) ? v < *x : false; +} + +template constexpr bool operator>=(const optional& x, const T& v) +{ + return bool(x) ? *x >= v : false; +} + +template constexpr bool operator<=(const T& v, const optional& x) +{ + return bool(x) ? v <= *x : false; +} + +template constexpr bool operator<=(const optional& x, const T& v) +{ + return bool(x) ? *x <= v : true; +} + +template constexpr bool operator>=(const T& v, const optional& x) +{ + return bool(x) ? v >= *x : true; +} + +template +void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) +{ + x.swap(y); +} + +template +constexpr optional::type> make_optional(T&& v) +{ + return optional::type>(constexpr_forward(v)); +} + +template +constexpr optional make_optional(::std::reference_wrapper v) +{ + return optional(v.get()); +} + +} // namespace + +namespace std +{ + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef sol::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash{}(*arg) : result_type{}; + } + }; + + template + struct hash> + { + typedef typename hash::result_type result_type; + typedef sol::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash{}(*arg) : result_type{}; + } + }; +} + +# undef TR2_OPTIONAL_REQUIRES +# undef TR2_OPTIONAL_ASSERTED_EXPRESSION + +# endif //___SOL_OPTIONAL_HPP___ +// end of Optional/optional.hpp + +#endif // Boost vs. Better optional + +namespace sol { + +#if defined(SOL_USE_BOOST) + template + using optional = boost::optional; + using nullopt_t = boost::none_t; + const nullopt_t nullopt = boost::none; +#endif // Boost vs. Better optional + +} // sol + +// end of sol/optional.hpp + +// beginning of sol/reference.hpp + +// beginning of sol/types.hpp + +// beginning of sol/compatibility.hpp + +// beginning of sol/compatibility/version.hpp + +#include + +#if defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // sol codecvt support +#elif defined(__GNUC__) +#if __GNUC__ >= 5 +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // codecvt support +#endif // g++ 5.x.x +#else +#endif // Windows/VC++ vs. g++ vs Others + +#ifdef LUAJIT_VERSION +#ifndef SOL_LUAJIT +#define SOL_LUAJIT +#define SOL_LUAJIT_VERSION LUAJIT_VERSION_NUM +#endif // sol luajit +#endif // luajit + +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 +#define SOL_LUA_VERSION LUA_VERSION_NUM +#elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 +#define SOL_LUA_VERSION LUA_VERSION_NUM +#elif !defined(LUA_VERSION_NUM) +#define SOL_LUA_VERSION 500 +#else +#define SOL_LUA_VERSION 502 +#endif // Lua Version 502, 501 || luajit, 500 + +#ifdef _MSC_VER +#ifdef _DEBUG +#ifndef NDEBUG +#ifndef SOL_CHECK_ARGUMENTS +#endif // Check Arguments +#ifndef SOL_SAFE_USERTYPE +#define SOL_SAFE_USERTYPE +#endif // Safe Usertypes +#endif // NDEBUG +#endif // Debug + +#ifndef _CPPUNWIND +#ifndef SOL_NO_EXCEPTIONS +#define SOL_NO_EXCEPTIONS 1 +#endif +#endif // Automatic Exceptions + +#ifndef _CPPRTTI +#ifndef SOL_NO_RTTI +#define SOL_NO_RTTI 1 +#endif +#endif // Automatic RTTI + +#elif defined(__GNUC__) || defined(__clang__) + +#ifndef NDEBUG +#ifndef __OPTIMIZE__ +#ifndef SOL_CHECK_ARGUMENTS +#endif // Check Arguments +#ifndef SOL_SAFE_USERTYPE +#define SOL_SAFE_USERTYPE +#endif // Safe Usertypes +#endif // g++ optimizer flag +#endif // Not Debug + +#ifndef __EXCEPTIONS +#ifndef SOL_NO_EXCEPTIONS +#define SOL_NO_EXCEPTIONS 1 +#endif +#endif // No Exceptions + +#ifndef __GXX_RTTI +#ifndef SOL_NO_RTII +#define SOL_NO_RTTI 1 +#endif +#endif // No RTTI + +#endif // vc++ || clang++/g++ + +#ifndef SOL_SAFE_USERTYPE +#ifdef SOL_CHECK_ARGUMENTS +#define SOL_SAFE_USERTYPE +#endif // Turn on Safety for all +#endif // Safe Usertypes + +// end of sol/compatibility/version.hpp + +#ifndef SOL_NO_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif +// beginning of sol/compatibility/5.1.0.h + +#ifndef SOL_5_1_0_H +#define SOL_5_1_0_H + +#if SOL_LUA_VERSION == 501 +/* Lua 5.1 */ + +#include +#include +#include + +/* LuaJIT doesn't define these unofficial macros ... */ +#if !defined(LUAI_INT32) +#include +#if INT_MAX-20 < 32760 +#define LUAI_INT32 long +#define LUAI_UINT32 unsigned long +#elif INT_MAX > 2147483640L +#define LUAI_INT32 int +#define LUAI_UINT32 unsigned int +#else +#error "could not detect suitable lua_Unsigned datatype" +#endif +#endif + +/* LuaJIT does not have the updated error codes for thread status/function returns */ +#ifndef LUA_ERRGCMM +#define LUA_ERRGCMM (LUA_ERRERR + 1) +#endif // LUA_ERRGCMM + +/* LuaJIT does not support continuation contexts / return error codes? */ +#ifndef LUA_KCONTEXT +#define LUA_KCONTEXT std::ptrdiff_t +typedef LUA_KCONTEXT lua_KContext; +typedef int(*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); +#endif // LUA_KCONTEXT + +#define LUA_OPADD 0 +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +typedef LUAI_UINT32 lua_Unsigned; + +typedef struct luaL_Buffer_52 { + luaL_Buffer b; /* make incorrect code crash! */ + char *ptr; + size_t nelems; + size_t capacity; + lua_State *L2; +} luaL_Buffer_52; +#define luaL_Buffer luaL_Buffer_52 + +#define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) + +#define lua_rawlen(L, i) lua_objlen(L, i) + +inline void lua_callk(lua_State *L, int nargs, int nresults, lua_KContext, lua_KFunction) { + // should probably warn the user of Lua 5.1 that continuation isn't supported... + lua_call(L, nargs, nresults); +} +inline int lua_pcallk(lua_State *L, int nargs, int nresults, int errfunc, lua_KContext, lua_KFunction) { + // should probably warn the user of Lua 5.1 that continuation isn't supported... + return lua_pcall(L, nargs, nresults, errfunc); +} +void lua_arith(lua_State *L, int op); +int lua_compare(lua_State *L, int idx1, int idx2, int op); +void lua_pushunsigned(lua_State *L, lua_Unsigned n); +lua_Unsigned luaL_checkunsigned(lua_State *L, int i); +lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum); +lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def); +lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); +void lua_len(lua_State *L, int i); +int luaL_len(lua_State *L, int i); +const char *luaL_tolstring(lua_State *L, int idx, size_t *len); +void luaL_requiref(lua_State *L, char const* modname, lua_CFunction openf, int glb); + +#define luaL_buffinit luaL_buffinit_52 +void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B); + +#define luaL_prepbuffsize luaL_prepbuffsize_52 +char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s); + +#define luaL_addlstring luaL_addlstring_52 +void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l); + +#define luaL_addvalue luaL_addvalue_52 +void luaL_addvalue(luaL_Buffer_52 *B); + +#define luaL_pushresult luaL_pushresult_52 +void luaL_pushresult(luaL_Buffer_52 *B); + +#undef luaL_buffinitsize +#define luaL_buffinitsize(L, B, s) \ + (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) + +#undef luaL_prepbuffer +#define luaL_prepbuffer(B) \ + luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +#undef luaL_addchar +#define luaL_addchar(B, c) \ + ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ + ((B)->ptr[(B)->nelems++] = (c))) + +#undef luaL_addsize +#define luaL_addsize(B, s) \ + ((B)->nelems += (s)) + +#undef luaL_addstring +#define luaL_addstring(B, s) \ + luaL_addlstring(B, s, strlen(s)) + +#undef luaL_pushresultsize +#define luaL_pushresultsize(B, s) \ + (luaL_addsize(B, s), luaL_pushresult(B)) + +typedef struct kepler_lua_compat_get_string_view { + const char *s; + size_t size; +} kepler_lua_compat_get_string_view; + +inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t* size) { + kepler_lua_compat_get_string_view* ls = (kepler_lua_compat_get_string_view*) ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + +#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 020100) <= 0) + +inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { + kepler_lua_compat_get_string_view ls; + ls.s = buff; + ls.size = size; + return lua_load(L, kepler_lua_compat_get_string, &ls, name/*, mode*/); +} + +#endif // LuaJIT 2.1.x beta and beyond + +#endif /* Lua 5.1 */ + +#endif // SOL_5_1_0_H// end of sol/compatibility/5.1.0.h + +// beginning of sol/compatibility/5.0.0.h + +#ifndef SOL_5_0_0_H +#define SOL_5_0_0_H + +#if SOL_LUA_VERSION < 501 +/* Lua 5.0 */ + +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + +#define luaL_Reg luaL_reg + +#define luaL_opt(L, f, n, d) \ + (lua_isnoneornil(L, n) ? (d) : f(L, n)) + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#endif // Lua 5.0 + +#endif // SOL_5_0_0_H +// end of sol/compatibility/5.0.0.h + +// beginning of sol/compatibility/5.x.x.h + +#ifndef SOL_5_X_X_H +#define SOL_5_X_X_H + +#if SOL_LUA_VERSION < 502 + +#define LUA_RIDX_GLOBALS LUA_GLOBALSINDEX + +#define LUA_OK 0 + +#define lua_pushglobaltable(L) \ + lua_pushvalue(L, LUA_GLOBALSINDEX) + +#define luaL_newlib(L, l) \ + (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) + +void luaL_checkversion(lua_State *L); + +int lua_absindex(lua_State *L, int i); +void lua_copy(lua_State *L, int from, int to); +void lua_rawgetp(lua_State *L, int i, const void *p); +void lua_rawsetp(lua_State *L, int i, const void *p); +void *luaL_testudata(lua_State *L, int i, const char *tname); +lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); +void lua_getuservalue(lua_State *L, int i); +void lua_setuservalue(lua_State *L, int i); +void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); +void luaL_setmetatable(lua_State *L, const char *tname); +int luaL_getsubtable(lua_State *L, int i, const char *name); +void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); +int luaL_fileresult(lua_State *L, int stat, const char *fname); + +#endif // Lua 5.1 and below + +#endif // SOL_5_X_X_H +// end of sol/compatibility/5.x.x.h + +// beginning of sol/compatibility/5.x.x.inl + +#ifndef SOL_5_X_X_INL +#define SOL_5_X_X_INL + +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 + +#include + +#define PACKAGE_KEY "_sol.package" + +inline int lua_absindex(lua_State *L, int i) { + if (i < 0 && i > LUA_REGISTRYINDEX) + i += lua_gettop(L) + 1; + return i; +} + +inline void lua_copy(lua_State *L, int from, int to) { + int abs_to = lua_absindex(L, to); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, from); + lua_replace(L, abs_to); +} + +inline void lua_rawgetp(lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + lua_pushlightuserdata(L, (void*)p); + lua_rawget(L, abs_i); +} + +inline void lua_rawsetp(lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, (void*)p); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + +inline void *luaL_testudata(lua_State *L, int i, const char *tname) { + void *p = lua_touserdata(L, i); + luaL_checkstack(L, 2, "not enough stack slots"); + if (p == NULL || !lua_getmetatable(L, i)) + return NULL; + else { + int res = 0; + luaL_getmetatable(L, tname); + res = lua_rawequal(L, -1, -2); + lua_pop(L, 2); + if (!res) + p = NULL; + } + return p; +} + +inline lua_Number lua_tonumberx(lua_State *L, int i, int *isnum) { + lua_Number n = lua_tonumber(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +inline static void push_package_table(lua_State *L) { + lua_pushliteral(L, PACKAGE_KEY); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + /* try to get package table from globals */ + lua_pushliteral(L, "package"); + lua_rawget(L, LUA_GLOBALSINDEX); + if (lua_istable(L, -1)) { + lua_pushliteral(L, PACKAGE_KEY); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } +} + +inline void lua_getuservalue(lua_State *L, int i) { + luaL_checktype(L, i, LUA_TUSERDATA); + luaL_checkstack(L, 2, "not enough stack slots"); + lua_getfenv(L, i); + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 1); + lua_pushnil(L); + lua_replace(L, -2); + } + else { + lua_pop(L, 1); + push_package_table(L); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 1); + lua_pushnil(L); + lua_replace(L, -2); + } + else + lua_pop(L, 1); + } +} + +inline void lua_setuservalue(lua_State *L, int i) { + luaL_checktype(L, i, LUA_TUSERDATA); + if (lua_isnil(L, -1)) { + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_replace(L, -2); + } + lua_setfenv(L, i); +} + +/* +** Adapted from Lua 5.2.0 +*/ +inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup + 1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ + } + lua_pop(L, nup); /* remove upvalues */ +} + +inline void luaL_setmetatable(lua_State *L, const char *tname) { + luaL_checkstack(L, 1, "not enough stack slots"); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +inline int luaL_getsubtable(lua_State *L, int i, const char *name) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushstring(L, name); + lua_gettable(L, abs_i); + if (lua_istable(L, -1)) + return 1; + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + +#ifndef SOL_LUAJIT +inline static int countlevels(lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le) / 2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + +inline static int findfield(lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + +inline static int pushglobalfuncname(lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +inline static void pushfuncname(lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +inline void luaL_traceback(lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} +#endif + +inline const lua_Number *lua_version(lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + // TODO: wonky hacks to get at the inside of the incomplete type lua_State? + //else return L->l_G->version; + else return &version; +} + +inline static void luaL_checkversion_(lua_State *L, lua_Number ver) { + const lua_Number* v = lua_version(L); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + +inline void luaL_checkversion(lua_State* L) { + luaL_checkversion_(L, LUA_VERSION_NUM); +} + +#ifndef SOL_LUAJIT +inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + char buf[1024]; +#ifdef __GLIBC__ + strerror_r(en, buf, 1024); +#else + strerror_s(buf, 1024, en); +#endif + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, buf); + else + lua_pushstring(L, buf); + lua_pushnumber(L, (lua_Number)en); + return 3; + } +} +#endif // luajit +#endif // Lua 5.0 or Lua 5.1 + +#if SOL_LUA_VERSION == 501 + +typedef LUAI_INT32 LUA_INT32; + +/********************************************************************/ +/* extract of 5.2's luaconf.h */ +/* detects proper defines for faster unsigned<->number conversion */ +/* see copyright notice at the end of this file */ +/********************************************************************/ + +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ +#endif + +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ + +/* Microsoft compiler on a Pentium (32 bit) ? */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ + +#define LUA_MSASMTRICK +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 32 bits? */ +#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEELL +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 64 bits? */ +#elif defined(__x86_64) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 0 + +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 1 + +#else /* }{ */ + +/* assume IEEE754 and a 32-bit integer type */ +#define LUA_IEEE754TRICK + +#endif /* } */ + +#endif /* } */ + +/********************************************************************/ +/* extract of 5.2's llimits.h */ +/* gives us lua_number2unsigned and lua_unsigned2number */ +/* see copyright notice just below this one here */ +/********************************************************************/ + +/********************************************************************* +* This file contains parts of Lua 5.2's source code: +* +* Copyright (C) 1994-2013 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*********************************************************************/ + +#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ +/* trick with Microsoft assembler for X86 */ + +#define lua_number2unsigned(i,n) \ + {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} + +#elif defined(LUA_IEEE754TRICK) /* }{ */ +/* the next trick should work on any machine using IEEE754 with +a 32-bit int type */ + +union compat52_luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union compat52_luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) +#else +#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union compat52_luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } + +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) + +#endif /* } */ + +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2unsigned) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) +#include +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define lua_number2unsigned(i,n) \ + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) +#else +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#endif +#endif /* } */ + +#if !defined(lua_unsigned2number) +/* on several machines, coercion from unsigned to double is slow, +so it may be worth to avoid */ +#define lua_unsigned2number(u) \ + (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) +#endif + +/********************************************************************/ + +inline static void compat52_call_lua(lua_State *L, char const code[], size_t len, + int nargs, int nret) { + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, code, len, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); + } + lua_insert(L, -nargs - 1); + lua_call(L, nargs, nret); +} + +static const char compat52_arith_code[] = { + "local op,a,b=...\n" + "if op==0 then return a+b\n" + "elseif op==1 then return a-b\n" + "elseif op==2 then return a*b\n" + "elseif op==3 then return a/b\n" + "elseif op==4 then return a%b\n" + "elseif op==5 then return a^b\n" + "elseif op==6 then return -a\n" + "end\n" +}; + +inline void lua_arith(lua_State *L, int op) { + if (op < LUA_OPADD || op > LUA_OPUNM) + luaL_error(L, "invalid 'op' argument for lua_arith"); + luaL_checkstack(L, 5, "not enough stack slots"); + if (op == LUA_OPUNM) + lua_pushvalue(L, -1); + lua_pushnumber(L, op); + lua_insert(L, -3); + compat52_call_lua(L, compat52_arith_code, + sizeof(compat52_arith_code) - 1, 3, 1); +} + +static const char compat52_compare_code[] = { + "local a,b=...\n" + "return a<=b\n" +}; + +inline int lua_compare(lua_State *L, int idx1, int idx2, int op) { + int result = 0; + switch (op) { + case LUA_OPEQ: + return lua_equal(L, idx1, idx2); + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + case LUA_OPLE: + luaL_checkstack(L, 5, "not enough stack slots"); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + compat52_call_lua(L, compat52_compare_code, + sizeof(compat52_compare_code) - 1, 2, 1); + result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + default: + luaL_error(L, "invalid 'op' argument for lua_compare"); + } + return 0; +} + +inline void lua_pushunsigned(lua_State *L, lua_Unsigned n) { + lua_pushnumber(L, lua_unsigned2number(n)); +} + +inline lua_Unsigned luaL_checkunsigned(lua_State *L, int i) { + lua_Unsigned result; + lua_Number n = lua_tonumber(L, i); + if (n == 0 && !lua_isnumber(L, i)) + luaL_checktype(L, i, LUA_TNUMBER); + lua_number2unsigned(result, n); + return result; +} + +inline lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum) { + lua_Unsigned result; + lua_Number n = lua_tonumberx(L, i, isnum); + lua_number2unsigned(result, n); + return result; +} + +inline lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, i, def); +} + +inline lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum) { + lua_Integer n = lua_tointeger(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +inline void lua_len(lua_State *L, int i) { + switch (lua_type(L, i)) { + case LUA_TSTRING: /* fall through */ + case LUA_TTABLE: + if (!luaL_callmeta(L, i, "__len")) + lua_pushnumber(L, (int)lua_objlen(L, i)); + break; + case LUA_TUSERDATA: + if (luaL_callmeta(L, i, "__len")) + break; + /* maybe fall through */ + default: + luaL_error(L, "attempt to get length of a %s value", + lua_typename(L, lua_type(L, i))); + } +} + +inline int luaL_len(lua_State *L, int i) { + int res = 0, isnum = 0; + luaL_checkstack(L, 1, "not enough stack slots"); + lua_len(L, i); + res = (int)lua_tointegerx(L, -1, &isnum); + lua_pop(L, 1); + if (!isnum) + luaL_error(L, "object length is not a number"); + return res; +} + +inline const char *luaL_tolstring(lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { + int t = lua_type(L, idx); + switch (t) { + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + case LUA_TSTRING: + case LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + if (lua_toboolean(L, idx)) + lua_pushliteral(L, "true"); + else + lua_pushliteral(L, "false"); + break; + default: + lua_pushfstring(L, "%s: %p", lua_typename(L, t), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + +inline void luaL_requiref(lua_State *L, char const* modname, + lua_CFunction openf, int glb) { + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_getglobal(L, "package"); + if (lua_istable(L, -1) == 0) { + lua_pop(L, 1); + lua_createtable(L, 0, 16); + lua_setglobal(L, "package"); + lua_getglobal(L, "package"); + } + lua_getfield(L, -1, "loaded"); + if (lua_istable(L, -1) == 0) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_setfield(L, -2, "loaded"); + lua_getfield(L, -1, "loaded"); + } + lua_replace(L, -2); + lua_pushvalue(L, -2); + lua_setfield(L, -2, modname); + lua_pop(L, 1); + if (glb) { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } +} + +inline void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B) { + /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ + B->b.p = NULL; + B->b.L = NULL; + B->b.lvl = 0; + /* reuse the buffer from the 5.1-style luaL_Buffer though! */ + B->ptr = B->b.buffer; + B->capacity = LUAL_BUFFERSIZE; + B->nelems = 0; + B->L2 = L; +} + +inline char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s) { + if (B->capacity - B->nelems < s) { /* needs to grow */ + char* newptr = NULL; + size_t newcap = B->capacity * 2; + if (newcap - B->nelems < s) + newcap = B->nelems + s; + if (newcap < B->capacity) /* overflow */ + luaL_error(B->L2, "buffer too large"); + newptr = (char*)lua_newuserdata(B->L2, newcap); + memcpy(newptr, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove old buffer */ + B->ptr = newptr; + B->capacity = newcap; + } + return B->ptr + B->nelems; +} + +inline void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l) { + memcpy(luaL_prepbuffsize(B, l), s, l); + luaL_addsize(B, l); +} + +inline void luaL_addvalue(luaL_Buffer_52 *B) { + size_t len = 0; + const char *s = lua_tolstring(B->L2, -1, &len); + if (!s) + luaL_error(B->L2, "cannot convert value to string"); + if (B->ptr != B->b.buffer) + lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ + luaL_addlstring(B, s, len); + lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); +} + +inline void luaL_pushresult(luaL_Buffer_52 *B) { + lua_pushlstring(B->L2, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove userdata buffer */ +} + +#endif /* SOL_LUA_VERSION == 501 */ + +#endif // SOL_5_X_X_INL +// end of sol/compatibility/5.x.x.inl + +#ifdef __cplusplus +} +#endif + +#endif // SOL_NO_COMPAT + +// end of sol/compatibility.hpp + +// beginning of sol/string_shim.hpp + +#pragma once + +namespace sol { + namespace string_detail { + struct string_shim { + std::size_t s; + const char* p; + + string_shim(const std::string& r) : string_shim(r.data(), r.size()) {} + string_shim(const char* p) : string_shim(p, std::char_traits::length(p)) {} + string_shim(const char* p, std::size_t s) : s(s), p(p) {} + + static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) { + int result = std::char_traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); + if (result != 0) + return result; + if (lhs_sz < rhs_sz) + return -1; + if (lhs_sz > rhs_sz) + return 1; + return 0; + } + + const char* c_str() const { + return p; + } + + const char* data() const { + return p; + } + + std::size_t size() const { + return s; + } + + bool operator==(const string_shim& r) const { + return compare(p, s, r.data(), r.size()) == 0; + } + + bool operator==(const char* r) const { + return compare(r, std::char_traits::length(r), p, s) == 0; + } + + bool operator==(const std::string& r) const { + return compare(r.data(), r.size(), p, s) == 0; + } + + bool operator!=(const string_shim& r) const { + return !(*this == r); + } + + bool operator!=(const char* r) const { + return !(*this == r); + } + + bool operator!=(const std::string& r) const { + return !(*this == r); + } + }; + } +}// end of sol/string_shim.hpp + +#include + +namespace sol { + namespace detail { +#ifdef SOL_NO_EXCEPTIONS + template + int static_trampoline(lua_State* L) { + return f(L); + } + + template + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + return f(L, std::forward(args)...); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#else + template + int static_trampoline(lua_State* L) { + try { + return f(L); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } + catch (...) { + lua_pushstring(L, "caught (...) exception"); + } + return lua_error(L); + } + + template + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + try { + return f(L, std::forward(args)...); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } + catch (...) { + lua_pushstring(L, "caught (...) exception"); + } + return lua_error(L); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#endif // Exceptions vs. No Exceptions + + template + struct unique_usertype {}; + + template + struct implicit_wrapper { + T& item; + implicit_wrapper(T* item) : item(*item) {} + implicit_wrapper(T& item) : item(item) {} + operator T& () { + return item; + } + operator T* () { + return std::addressof(item); + } + }; + } // detail + + struct nil_t {}; + const nil_t nil{}; + inline bool operator==(nil_t, nil_t) { return true; } + inline bool operator!=(nil_t, nil_t) { return false; } + + struct metatable_key_t {}; + const metatable_key_t metatable_key = {}; + + struct no_metatable_t {}; + const no_metatable_t no_metatable = {}; + + typedef std::remove_pointer_t lua_r_CFunction; + + template + struct unique_usertype_traits { + typedef T type; + typedef T actual_type; + static const bool value = false; + + template + static bool is_null(U&&) { + return false; + } + + template + static auto get(U&& value) { + return std::addressof(detail::deref(value)); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::shared_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::unique_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct non_null {}; + + template + struct function_sig {}; + + struct upvalue_index { + int index; + upvalue_index(int idx) : index(lua_upvalueindex(idx)) {} + operator int() const { return index; } + }; + + struct raw_index { + int index; + raw_index(int i) : index(i) {} + operator int() const { return index; } + }; + + struct absolute_index { + int index; + absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {} + operator int() const { return index; } + }; + + struct lightuserdata_value { + void* value; + lightuserdata_value(void* data) : value(data) {} + operator void*() const { return value; } + }; + + struct userdata_value { + void* value; + userdata_value(void* data) : value(data) {} + operator void*() const { return value; } + }; + + template + struct light { + L* value; + + light(L& x) : value(std::addressof(x)) {} + light(L* x) : value(x) {} + light(void* x) : value(static_cast(x)) {} + operator L* () const { return value; } + operator L& () const { return *value; } + }; + + template + auto make_light(T& l) { + typedef meta::unwrapped_t>> L; + return light(l); + } + + template + struct user { + U value; + + user(U x) : value(std::move(x)) {} + operator U* () { return std::addressof(value); } + operator U& () { return value; } + operator const U& () const { return value; } + }; + + template + auto make_user(T&& u) { + typedef meta::unwrapped_t> U; + return user(std::forward(u)); + } + + template + struct metatable_registry_key { + T key; + + metatable_registry_key(T key) : key(std::forward(key)) {} + }; + + template + auto meta_registry_key(T&& key) { + typedef meta::unqualified_t K; + return metatable_registry_key(std::forward(key)); + } + + template + struct closure { + lua_CFunction c_function; + std::tuple upvalues; + closure(lua_CFunction f, Upvalues... upvalues) : c_function(f), upvalues(std::forward(upvalues)...) {} + }; + + template <> + struct closure<> { + lua_CFunction c_function; + int upvalues; + closure(lua_CFunction f, int upvalues = 0) : c_function(f), upvalues(upvalues) {} + }; + + typedef closure<> c_closure; + + template + closure make_closure(lua_CFunction f, Args&&... args) { + return closure(f, std::forward(args)...); + } + + template + struct function_arguments { + std::tuple arguments; + template , function_arguments>> = meta::enabler> + function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward(arg), std::forward(args)...) {} + }; + + template , typename... Args> + auto as_function(Args&&... args) { + return function_arguments...>(std::forward(args)...); + } + + template , typename... Args> + auto as_function_reference(Args&&... args) { + return function_arguments(std::forward(args)...); + } + + template + struct as_table_t { + T source; + template + as_table_t(Args&&... args) : source(std::forward(args)...) {} + + operator std::add_lvalue_reference_t () { + return source; + } + }; + + template + as_table_t as_table(T&& container) { + return as_table_t(std::forward(container)); + } + + struct this_state { + lua_State* L; + operator lua_State* () const { + return L; + } + lua_State* operator-> () const { + return L; + } + }; + + enum class call_syntax { + dot = 0, + colon = 1 + }; + + enum class call_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + handler = LUA_ERRERR, + gc = LUA_ERRGCMM + }; + + enum class thread_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + handler = LUA_ERRERR, + dead, + }; + + enum class load_status : int { + ok = LUA_OK, + syntax = LUA_ERRSYNTAX, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + file = LUA_ERRFILE, + }; + + enum class type : int { + none = LUA_TNONE, + nil = LUA_TNIL, + string = LUA_TSTRING, + number = LUA_TNUMBER, + thread = LUA_TTHREAD, + boolean = LUA_TBOOLEAN, + function = LUA_TFUNCTION, + userdata = LUA_TUSERDATA, + lightuserdata = LUA_TLIGHTUSERDATA, + table = LUA_TTABLE, + poly = none | nil | string | number | thread | + table | boolean | function | userdata | lightuserdata + }; + + enum class meta_function { + construct, + index, + new_index, + mode, + call, + metatable, + to_string, + length, + unary_minus, + addition, + subtraction, + multiplication, + division, + modulus, + power_of, + involution = power_of, + concatenation, + equal_to, + less_than, + less_than_or_equal_to, + garbage_collect, + call_function = call, + }; + + typedef meta_function meta_method; + + const std::array meta_variable_names = { { + "__index", + "__newindex", + } }; + + const std::array meta_function_names = { { + "new", + "__index", + "__newindex", + "__mode", + "__call", + "__metatable", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", + } }; + + inline const std::string& name_of(meta_function mf) { + return meta_function_names[static_cast(mf)]; + } + + inline type type_of(lua_State* L, int index) { + return static_cast(lua_type(L, index)); + } + + inline int type_panic(lua_State* L, int index, type expected, type actual) { + return luaL_error(L, "stack index %d, expected %s, received %s", index, + expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), + expected == type::poly ? "anything" : lua_typename(L, static_cast(actual)) + ); + } + + // Specify this function as the handler for lua::check if you know there's nothing wrong + inline int no_panic(lua_State*, int, type, type) noexcept { + return 0; + } + + inline void type_error(lua_State* L, int expected, int actual) { + luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); + } + + inline void type_error(lua_State* L, type expected, type actual) { + type_error(L, static_cast(expected), static_cast(actual)); + } + + inline void type_assert(lua_State* L, int index, type expected, type actual) { + if (expected != type::poly && expected != actual) { + type_panic(L, index, expected, actual); + } + } + + inline void type_assert(lua_State* L, int index, type expected) { + type actual = type_of(L, index); + type_assert(L, index, expected, actual); + } + + inline std::string type_name(lua_State* L, type t) { + return lua_typename(L, static_cast(t)); + } + + class reference; + class stack_reference; + template + struct proxy; + template + class usertype; + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + typedef table_core table; + typedef table_core global_table; + typedef stack_table_core stack_table; + typedef stack_table_core stack_global_table; + template + class basic_function; + template + class basic_protected_function; + using function = basic_function; + using protected_function = basic_protected_function; + using stack_function = basic_function; + using stack_protected_function = basic_protected_function; + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + struct variadic_args; + using object = basic_object; + using stack_object = basic_object; + using userdata = basic_userdata; + using stack_userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using stack_lightuserdata = basic_lightuserdata; + class coroutine; + class thread; + struct variadic_args; + struct this_state; + + namespace detail { + template + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template + struct lua_type_of> : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of::value>> : std::integral_constant {}; + + template + struct lua_type_of::value>> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template class V, typename... Args> + struct accumulate : std::integral_constant {}; + + template class V, typename T, typename... Args> + struct accumulate : accumulate::value, V, Args...> {}; + } // detail + + template + struct is_unique_usertype : std::integral_constant::value> {}; + + template + struct lua_type_of : detail::lua_type_of {}; + + template + struct lua_size : std::integral_constant { }; + + template + struct lua_size> : std::integral_constant::value + lua_size::value> { }; + + template + struct lua_size> : std::integral_constant::value> { }; + + template + struct is_lua_primitive : std::integral_constant>::value + || (lua_size::value > 1) + || std::is_base_of>::value + || std::is_base_of>::value + || meta::is_specialization_of>::value + || meta::is_specialization_of>::value + > { }; + + template + struct is_lua_reference : std::integral_constant>::value + || std::is_base_of>::value + || meta::is_specialization_of>::value + > { }; + + template + struct is_lua_primitive : std::true_type {}; + template + struct is_lua_primitive> : std::true_type { }; + template + struct is_lua_primitive> : std::true_type { }; + template + struct is_lua_primitive> : is_lua_primitive { }; + template + struct is_lua_primitive> : std::true_type {}; + template <> + struct is_lua_primitive : std::true_type {}; + template <> + struct is_lua_primitive : std::true_type {}; + template + struct is_lua_primitive> : is_lua_primitive {}; + + template + struct is_proxy_primitive : is_lua_primitive { }; + + template + struct is_transparent_argument : std::false_type {}; + + template <> + struct is_transparent_argument : std::true_type {}; + + template <> + struct is_transparent_argument : std::true_type {}; + + template + struct lua_bind_traits : meta::bind_traits { + private: + typedef meta::bind_traits base_t; + public: + static const std::size_t true_arity = base_t::arity; + static const std::size_t arity = base_t::arity - meta::count_for::value; + static const std::size_t true_free_arity = base_t::free_arity; + static const std::size_t free_arity = base_t::free_arity - meta::count_for::value; + }; + + template + struct is_table : std::false_type {}; + template + struct is_table> : std::true_type {}; + + template + struct is_function : std::false_type {}; + template + struct is_function> : std::true_type {}; + template + struct is_function> : std::true_type {}; + + template + struct is_lightuserdata : std::false_type {}; + template + struct is_lightuserdata> : std::true_type {}; + + template + struct is_userdata : std::false_type {}; + template + struct is_userdata> : std::true_type {}; + + template + inline type type_of() { + return lua_type_of>::value; + } +} // sol + +// end of sol/types.hpp + +// beginning of sol/stack_reference.hpp + +namespace sol { + class stack_reference { + private: + lua_State* L = nullptr; + int index = 0; + + protected: + int registry_index() const noexcept { + return LUA_NOREF; + } + + public: + stack_reference() noexcept = default; + stack_reference(nil_t) noexcept : stack_reference() {}; + stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {} + stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {} + stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {} + stack_reference(stack_reference&& o) noexcept = default; + stack_reference& operator=(stack_reference&&) noexcept = default; + stack_reference(const stack_reference&) noexcept = default; + stack_reference& operator=(const stack_reference&) noexcept = default; + + int push() const noexcept { + lua_pushvalue(L, index); + return 1; + } + + void pop(int n = 1) const noexcept { + lua_pop(lua_state(), n); + } + + int stack_index() const noexcept { + return index; + } + + type get_type() const noexcept { + int result = lua_type(L, index); + return static_cast(result); + } + + lua_State* lua_state() const noexcept { + return L; + } + + bool valid() const noexcept { + type t = get_type(); + return t != type::nil && t != type::none; + } + }; + + inline bool operator== (const stack_reference& l, const stack_reference& r) { + return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0; + } + + inline bool operator!= (const stack_reference& l, const stack_reference& r) { + return !operator==(l, r); + } +} // sol + +// end of sol/stack_reference.hpp + +namespace sol { + namespace stack { + template + struct push_popper_n { + lua_State* L; + int t; + push_popper_n(lua_State* L, int x) : L(L), t(x) { } + ~push_popper_n() { lua_pop(L, t); } + }; + template <> + struct push_popper_n { + push_popper_n(lua_State*, int) { } + }; + template + struct push_popper { + T t; + push_popper(T x) : t(x) { t.push(); } + ~push_popper() { t.pop(); } + }; + template + struct push_popper { + push_popper(T) {} + ~push_popper() {} + }; + template + push_popper push_pop(T&& x) { + return push_popper(std::forward(x)); + } + template + push_popper_n pop_n(lua_State* L, int x) { + return push_popper_n(L, x); + } + } // stack + + namespace detail { + struct global_tag { } const global_{}; + } // detail + + class reference { + private: + lua_State* L = nullptr; // non-owning + int ref = LUA_NOREF; + + int copy() const noexcept { + if (ref == LUA_NOREF) + return LUA_NOREF; + push(); + return luaL_ref(L, LUA_REGISTRYINDEX); + } + + protected: + reference(lua_State* L, detail::global_tag) noexcept : L(L) { + lua_pushglobaltable(L); + ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + int stack_index() const noexcept { + return -1; + } + + public: + reference() noexcept = default; + reference(nil_t) noexcept : reference() {} + reference(const stack_reference& r) noexcept : reference(r.lua_state(), r.stack_index()) {} + reference(stack_reference&& r) noexcept : reference(r.lua_state(), r.stack_index()) {} + reference(lua_State* L, int index = -1) noexcept : L(L) { + lua_pushvalue(L, index); + ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + virtual ~reference() noexcept { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + } + + reference(reference&& o) noexcept { + L = o.L; + ref = o.ref; + + o.L = nullptr; + o.ref = LUA_NOREF; + } + + reference& operator=(reference&& o) noexcept { + L = o.L; + ref = o.ref; + + o.L = nullptr; + o.ref = LUA_NOREF; + + return *this; + } + + reference(const reference& o) noexcept { + L = o.L; + ref = o.copy(); + } + + reference& operator=(const reference& o) noexcept { + L = o.L; + ref = o.copy(); + return *this; + } + + int push() const noexcept { + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + return 1; + } + + void pop(int n = 1) const noexcept { + lua_pop(lua_state(), n); + } + + int registry_index() const noexcept { + return ref; + } + + bool valid() const noexcept { + return !(ref == LUA_NOREF || ref == LUA_REFNIL); + } + + explicit operator bool() const noexcept { + return valid(); + } + + type get_type() const noexcept { + auto pp = stack::push_pop(*this); + int result = lua_type(L, -1); + return static_cast(result); + } + + lua_State* lua_state() const noexcept { + return L; + } + }; + + inline bool operator== (const reference& l, const reference& r) { + auto ppl = stack::push_pop(l); + auto ppr = stack::push_pop(r); + return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; + } + + inline bool operator!= (const reference& l, const reference& r) { + return !operator==(l, r); + } +} // sol + +// end of sol/reference.hpp + +// beginning of sol/stack.hpp + +// beginning of sol/stack_core.hpp + +// beginning of sol/userdata.hpp + +namespace sol { + template + class basic_userdata : public base_t { + public: + basic_userdata() noexcept = default; + template , basic_userdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_userdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::userdata); + } +#endif // Safety + } + basic_userdata(const basic_userdata&) = default; + basic_userdata(basic_userdata&&) = default; + basic_userdata& operator=(const basic_userdata&) = default; + basic_userdata& operator=(basic_userdata&&) = default; + basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {} + basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {} + basic_userdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::userdata); +#endif // Safety + } + }; + + template + class basic_lightuserdata : public base_t { + public: + basic_lightuserdata() noexcept = default; + template , basic_lightuserdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_lightuserdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } + basic_lightuserdata(const basic_lightuserdata&) = default; + basic_lightuserdata(basic_lightuserdata&&) = default; + basic_lightuserdata& operator=(const basic_lightuserdata&) = default; + basic_lightuserdata& operator=(basic_lightuserdata&&) = default; + basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::lightuserdata); +#endif // Safety + } + }; + +} // sol + +// end of sol/userdata.hpp + +// beginning of sol/tie.hpp + +namespace sol { + + namespace detail { + template + struct is_speshul : std::false_type {}; + } + + template + struct tie_size : std::tuple_size {}; + + template + struct is_tieable : std::integral_constant::value > 0)> {}; + + template + struct tie_t : public std::tuple...> { + private: + typedef std::tuple...> base_t; + + template + void set(std::false_type, T&& target) { + std::get<0>(*this) = std::forward(target); + } + + template + void set(std::true_type, T&& target) { + typedef tie_size> value_size; + typedef tie_size> tie_size; + typedef std::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; + typedef std::make_index_sequence indices; + set_extra(detail::is_speshul>(), indices(), std::forward(target)); + } + + template + void set_extra(std::true_type, std::index_sequence, T&& target) { + using std::get; + (void)detail::swallow{ 0, + (get(*this) = get(types(), target), 0)... + , 0 }; + } + + template + void set_extra(std::false_type, std::index_sequence, T&& target) { + using std::get; + (void)detail::swallow{ 0, + (get(*this) = get(target), 0)... + , 0 }; + } + + public: + using base_t::base_t; + + template + tie_t& operator= (T&& value) { + typedef is_tieable> tieable; + set(tieable(), std::forward(value)); + return *this; + } + + }; + + template + struct tie_size< tie_t > : std::tuple_size< std::tuple > { }; + + namespace adl_barrier_detail { + template + inline tie_t...> tie(Tn&&... argn) { + return tie_t...>(std::forward(argn)...); + } + } + + using namespace adl_barrier_detail; + +} // sol + +// end of sol/tie.hpp + +// beginning of sol/stack_guard.hpp + +namespace sol { + namespace detail { + inline void stack_fail(int, int) { +#ifndef SOL_NO_EXCEPTIONS + throw error(detail::direct_error, "imbalanced stack after operation finish"); +#else + // Lol, what do you want, an error printout? :3c + // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so + // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. +#endif // No Exceptions + } + } // detail + + struct stack_guard { + lua_State* L; + int top; + std::function on_mismatch; + + stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {} + stack_guard(lua_State* L, int top, std::function fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {} + bool check_stack(int modification = 0) const { + int bottom = lua_gettop(L) + modification; + if (top == bottom) { + return true; + } + on_mismatch(top, bottom); + return false; + } + ~stack_guard() { + check_stack(); + } + }; +} // sol + +// end of sol/stack_guard.hpp + +#include + +namespace sol { + namespace detail { + struct as_reference_tag {}; + template + struct as_pointer_tag {}; + template + struct as_value_tag {}; + + using special_destruct_func = void(*)(void*); + + template + inline void special_destruct(void* memory) { + T** pointerpointer = static_cast(memory); + special_destruct_func* dx = static_cast(static_cast(pointerpointer + 1)); + Real* target = static_cast(static_cast(dx + 1)); + target->~Real(); + } + + template + inline int unique_destruct(lua_State* L) { + void* memory = lua_touserdata(L, 1); + T** pointerpointer = static_cast(memory); + special_destruct_func& dx = *static_cast(static_cast(pointerpointer + 1)); + (dx)(memory); + return 0; + } + + template + inline int user_alloc_destroy(lua_State* L) { + void* rawdata = lua_touserdata(L, upvalue_index(1)); + T* data = static_cast(rawdata); + std::allocator alloc; + alloc.destroy(data); + return 0; + } + + template + inline int usertype_alloc_destroy(lua_State* L) { + void* rawdata = lua_touserdata(L, 1); + T** pdata = static_cast(rawdata); + T* data = *pdata; + std::allocator alloc{}; + alloc.destroy(data); + return 0; + } + + template + void reserve(T&, std::size_t) {} + + template + void reserve(std::vector& arr, std::size_t hint) { + arr.reserve(hint); + } + + template + void reserve(std::basic_string& arr, std::size_t hint) { + arr.reserve(hint); + } + } // detail + + namespace stack { + + template + struct field_getter; + template + struct probe_field_getter; + template + struct field_setter; + template + struct getter; + template + struct popper; + template + struct pusher; + template::value, typename = void> + struct checker; + template + struct check_getter; + + struct probe { + bool success; + int levels; + + probe(bool s, int l) : success(s), levels(l) {} + + operator bool() const { return success; }; + }; + + struct record { + int last; + int used; + + record() : last(), used() {} + void use(int count) { + last = count; + used += count; + } + }; + + namespace stack_detail { + template + struct strip { + typedef T type; + }; + template + struct strip> { + typedef T& type; + }; + template + struct strip> { + typedef T& type; + }; + template + struct strip> { + typedef T type; + }; + template + using strip_t = typename strip::type; + const bool default_check_arguments = +#ifdef SOL_CHECK_ARGUMENTS + true; +#else + false; +#endif + template + inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { + return getter>{}.get(L, index, tracking); + } + } // stack_detail + + inline bool maybe_indexable(lua_State* L, int index = -1) { + type t = type_of(L, index); + return t == type::userdata || t == type::table; + } + + template + inline int push(lua_State* L, T&& t, Args&&... args) { + return pusher>{}.push(L, std::forward(t), std::forward(args)...); + } + + // overload allows to use a pusher of a specific type, but pass in any kind of args + template::value>> + inline int push(lua_State* L, Arg&& arg, Args&&... args) { + return pusher>{}.push(L, std::forward(arg), std::forward(args)...); + } + + template + inline int push_reference(lua_State* L, T&& t, Args&&... args) { + typedef meta::all< + std::is_lvalue_reference, + meta::neg>, + meta::neg>>, + meta::neg>> + > use_reference_tag; + return pusher>>{}.push(L, std::forward(t), std::forward(args)...); + } + + inline int multi_push(lua_State*) { + // do nothing + return 0; + } + + template + inline int multi_push(lua_State* L, T&& t, Args&&... args) { + int pushcount = push(L, std::forward(t)); + void(sol::detail::swallow{ (pushcount += sol::stack::push(L, std::forward(args)), 0)... }); + return pushcount; + } + + inline int multi_push_reference(lua_State*) { + // do nothing + return 0; + } + + template + inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { + int pushcount = push_reference(L, std::forward(t)); + void(sol::detail::swallow{ (pushcount += sol::stack::push_reference(L, std::forward(args)), 0)... }); + return pushcount; + } + + template + bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + typedef meta::unqualified_t Tu; + checker c; + // VC++ has a bad warning here: shut it up + (void)c; + return c.check(L, index, std::forward(handler), tracking); + } + + template + bool check(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return check(L, index, std::forward(handler), tracking); + } + + template + bool check(lua_State* L, int index = -lua_size>::value) { + auto handler = no_panic; + return check(L, index, handler); + } + + template + inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { + return check_getter>{}.get(L, index, std::forward(handler), tracking); + } + + template + inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return check_get(L, index, handler, tracking); + } + + template + inline decltype(auto) check_get(lua_State* L, int index = -lua_size>::value) { + auto handler = no_panic; + return check_get(L, index, handler); + } + + namespace stack_detail { + +#ifdef SOL_CHECK_ARGUMENTS + template + inline auto tagged_get(types, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get(L, index, tracking)) { + auto op = check_get(L, index, type_panic, tracking); + return *op; + } +#else + template + inline decltype(auto) tagged_get(types, lua_State* L, int index, record& tracking) { + return stack_detail::unchecked_get(L, index, tracking); + } +#endif + + template + inline decltype(auto) tagged_get(types>, lua_State* L, int index, record& tracking) { + return stack_detail::unchecked_get>(L, index, tracking); + } + + template + struct check_types { + template + static bool check(types, lua_State* L, int firstargument, Handler&& handler, record& tracking) { + if (!stack::check(L, firstargument + tracking.used, handler, tracking)) + return false; + return check(types(), L, firstargument, std::forward(handler), tracking); + } + + template + static bool check(types<>, lua_State*, int, Handler&&, record&) { + return true; + } + }; + + template <> + struct check_types { + template + static bool check(types, lua_State*, int, Handler&&, record&) { + return true; + } + }; + + } // stack_detail + + template + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack_detail::check_types{}.check(types...>(), L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return multi_check(L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index) { + auto handler = no_panic; + return multi_check(L, index, handler); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return multi_check(L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler) { + return multi_check(L, index, std::forward(handler)); + } + + template + bool multi_check(lua_State* L, int index) { + return multi_check(L, index); + } + + template + inline decltype(auto) get(lua_State* L, int index, record& tracking) { + return stack_detail::tagged_get(types(), L, index, tracking); + } + + template + inline decltype(auto) get(lua_State* L, int index = -lua_size>::value) { + record tracking{}; + return get(L, index, tracking); + } + + template + inline decltype(auto) pop(lua_State* L) { + return popper>{}.pop(L); + } + + template + void get_field(lua_State* L, Key&& key) { + field_getter, global, raw>{}.get(L, std::forward(key)); + } + + template + void get_field(lua_State* L, Key&& key, int tableindex) { + field_getter, global, raw>{}.get(L, std::forward(key), tableindex); + } + + template + void raw_get_field(lua_State* L, Key&& key) { + get_field(L, std::forward(key)); + } + + template + void raw_get_field(lua_State* L, Key&& key, int tableindex) { + get_field(L, std::forward(key), tableindex); + } + + template + probe probe_get_field(lua_State* L, Key&& key) { + return probe_field_getter, global, raw>{}.get(L, std::forward(key)); + } + + template + probe probe_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_field_getter, global, raw>{}.get(L, std::forward(key), tableindex); + } + + template + probe probe_raw_get_field(lua_State* L, Key&& key) { + return probe_get_field(L, std::forward(key)); + } + + template + probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_get_field(L, std::forward(key), tableindex); + } + + template + void set_field(lua_State* L, Key&& key, Value&& value) { + field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value)); + } + + template + void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value), tableindex); + } + + template + void raw_set_field(lua_State* L, Key&& key, Value&& value) { + set_field(L, std::forward(key), std::forward(value)); + } + + template + void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + set_field(L, std::forward(key), std::forward(value), tableindex); + } + } // stack +} // sol + +// end of sol/stack_core.hpp + +// beginning of sol/stack_check.hpp + +// beginning of sol/usertype_traits.hpp + +// beginning of sol/demangle.hpp + +#include + +namespace sol { + namespace detail { +#ifdef _MSC_VER + template + inline std::string ctti_get_type_name() { + const static std::array removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } }; + std::string name = __FUNCSIG__; + std::size_t start = name.find("get_type_name"); + if (start == std::string::npos) + start = 0; + else + start += 13; + if (start < name.size() - 1) + start += 1; + std::size_t end = name.find_last_of('>'); + if (end == std::string::npos) + end = name.size(); + name = name.substr(start, end - start); + if (name.find("struct", 0) == 0) + name.replace(0, 6, "", 0); + if (name.find("class", 0) == 0) + name.replace(0, 5, "", 0); + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); + while (!name.empty() && std::isblank(name.back())) name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } +#elif defined(__GNUC__) || defined(__clang__) + template + inline std::string ctti_get_type_name() { + const static std::array removals = { { "{anonymous}", "(anonymous namespace)" } }; + std::string name = __PRETTY_FUNCTION__; + std::size_t start = name.find_first_of('['); + start = name.find_first_of('=', start); + std::size_t end = name.find_last_of(']'); + if (end == std::string::npos) + end = name.size(); + if (start == std::string::npos) + start = 0; + if (start < name.size() - 1) + start += 1; + name = name.substr(start, end - start); + start = name.rfind("seperator_mark"); + if (start != std::string::npos) { + name.erase(start - 2, name.length()); + } + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); + while (!name.empty() && std::isblank(name.back())) name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } +#else +#error Compiler not supported for demangling +#endif // compilers + + template + inline std::string demangle_once() { + std::string realname = ctti_get_type_name(); + return realname; + } + + template + inline std::string short_demangle_once() { + std::string realname = ctti_get_type_name(); + // This isn't the most complete but it'll do for now...? + static const std::array ops = { { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" } }; + int level = 0; + std::ptrdiff_t idx = 0; + for (idx = static_cast(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { + if (level == 0 && realname[idx] == ':') { + break; + } + bool isleft = realname[idx] == '<'; + bool isright = realname[idx] == '>'; + if (!isleft && !isright) + continue; + bool earlybreak = false; + for (const auto& op : ops) { + std::size_t nisop = realname.rfind(op, idx); + if (nisop == std::string::npos) + continue; + std::size_t nisopidx = idx - op.size() + 1; + if (nisop == nisopidx) { + idx = static_cast(nisopidx); + earlybreak = true; + } + break; + } + if (earlybreak) { + continue; + } + level += isleft ? -1 : 1; + } + if (idx > 0) { + realname.erase(0, realname.length() < static_cast(idx) ? realname.length() : idx + 1); + } + return realname; + } + + template + inline std::string demangle() { + static const std::string d = demangle_once(); + return d; + } + + template + inline std::string short_demangle() { + static const std::string d = short_demangle_once(); + return d; + } + } // detail +} // sol + +// end of sol/demangle.hpp + +namespace sol { + + template + struct usertype_traits { + static const std::string name; + static const std::string qualified_name; + static const std::string metatable; + static const std::string user_gc_metatable; + static const std::string gc_table; + }; + + template + const std::string usertype_traits::name = detail::short_demangle(); + + template + const std::string usertype_traits::qualified_name = detail::demangle(); + + template + const std::string usertype_traits::metatable = std::string("sol.").append(detail::demangle()); + + template + const std::string usertype_traits::user_gc_metatable = std::string("sol.").append(detail::demangle()).append(".user\xE2\x99\xBB"); + + template + const std::string usertype_traits::gc_table = std::string("sol.").append(detail::demangle().append(".\xE2\x99\xBB")); + +} + +// end of sol/usertype_traits.hpp + +// beginning of sol/inheritance.hpp + +#include + +namespace sol { + template + struct base_list { }; + template + using bases = base_list; + + typedef bases<> base_classes_tag; + const auto base_classes = base_classes_tag(); + + namespace detail { + + template + struct has_derived { + static bool value; + }; + + template + bool has_derived::value = false; + + inline std::size_t unique_id() { + static std::atomic x(0); + return ++x; + } + + template + struct id_for { + static const std::size_t value; + }; + + template + const std::size_t id_for::value = unique_id(); + + inline decltype(auto) base_class_check_key() { + static const auto& key = "class_check"; + return key; + } + + inline decltype(auto) base_class_cast_key() { + static const auto& key = "class_cast"; + return key; + } + + inline decltype(auto) base_class_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; + return key; + } + + inline decltype(auto) base_class_new_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; + return key; + } + + template + struct inheritance { + static bool type_check_bases(types<>, std::size_t) { + return false; + } + + template + static bool type_check_bases(types, std::size_t ti) { + return ti == id_for::value || type_check_bases(types(), ti); + } + + static bool type_check(std::size_t ti) { + return ti == id_for::value || type_check_bases(types(), ti); + } + + static void* type_cast_bases(types<>, T*, std::size_t) { + return nullptr; + } + + template + static void* type_cast_bases(types, T* data, std::size_t ti) { + // Make sure to convert to T first, and then dynamic cast to the proper type + return ti != id_for::value ? type_cast_bases(types(), data, ti) : static_cast(static_cast(data)); + } + + static void* type_cast(void* voiddata, std::size_t ti) { + T* data = static_cast(voiddata); + return static_cast(ti != id_for::value ? type_cast_bases(types(), data, ti) : data); + } + }; + + using inheritance_check_function = decltype(&inheritance::type_check); + using inheritance_cast_function = decltype(&inheritance::type_cast); + + } // detail +} // sol + +// end of sol/inheritance.hpp + +#include + +namespace sol { + namespace stack { + namespace stack_detail { + template + inline bool check_metatable(lua_State* L, int index = -2) { + const auto& metakey = usertype_traits::metatable; + luaL_getmetatable(L, &metakey[0]); + const type expectedmetatabletype = static_cast(lua_type(L, -1)); + if (expectedmetatabletype != type::nil) { + if (lua_rawequal(L, -1, index) == 1) { + lua_pop(L, 1 + static_cast(poptable)); + return true; + } + } + lua_pop(L, 1); + return false; + } + + template + struct basic_check { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = check_func(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, expected, type_of(L, index)); + } + return success; + } + }; + } // stack_detail + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + const type indextype = type_of(L, index); + bool success = expected == indextype; + if (!success) { + // expected type, actual type + handler(L, index, expected, indextype); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + bool success = lua_isnil(L, index); + if (success) { + tracking.use(1); + return success; + } + tracking.use(0); + success = lua_isnone(L, index); + if (!success) { + // expected type, actual type + handler(L, index, expected, type_of(L, index)); + } + return success; + } + }; + + template + struct checker : checker {}; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = !lua_isnone(L, index); + if (!success) { + // expected type, actual type + handler(L, index, type::none, type_of(L, index)); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + bool success = t == type::userdata || t == type::lightuserdata; + if (!success) { + // expected type, actual type + handler(L, index, type::lightuserdata, t); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + bool success = t == type::userdata; + if (!success) { + // expected type, actual type + handler(L, index, type::userdata, t); + } + return success; + } + }; + + template + struct checker, type::userdata, C> : checker, type::lightuserdata, C> {}; + + template + struct checker, type::userdata, C> : checker::value, C> {}; + + template + struct checker : stack_detail::basic_check {}; + template + struct checker, type::function, C> : checker {}; + template + struct checker : checker {}; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::nil || t == type::none || t == type::function) { + // allow for nil to be returned + return true; + } + if (t != type::userdata && t != type::table) { + handler(L, index, type::function, t); + return false; + } + // Do advanced check for call-style userdata? + static const auto& callkey = name_of(meta_function::call); + if (lua_getmetatable(L, index) == 0) { + // No metatable, no __call key possible + handler(L, index, type::function, t); + return false; + } + if (lua_isnoneornil(L, -1)) { + lua_pop(L, 1); + handler(L, index, type::function, t); + return false; + } + lua_getfield(L, -1, &callkey[0]); + if (lua_isnoneornil(L, -1)) { + lua_pop(L, 2); + handler(L, index, type::function, t); + return false; + } + // has call, is definitely a function + lua_pop(L, 2); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::table) { + return true; + } + if (t != type::userdata) { + handler(L, index, type::function, t); + return false; + } + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + // Allow nil to be transformed to nullptr + if (indextype == type::nil) { + tracking.use(1); + return true; + } + return checker, type::userdata, C>{}.check(types>(), L, indextype, index, std::forward(handler), tracking); + } + }; + + template + struct checker { + template + static bool check(types, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (indextype != type::userdata) { + handler(L, index, type::userdata, indextype); + return false; + } + if (meta::any, std::is_same, std::is_same, std::is_same>::value) + return true; + if (lua_getmetatable(L, index) == 0) { + return true; + } + int metatableindex = lua_gettop(L); + if (stack_detail::check_metatable(L, metatableindex)) + return true; + if (stack_detail::check_metatable(L, metatableindex)) + return true; + if (stack_detail::check_metatable>(L, metatableindex)) + return true; + bool success = false; + if (detail::has_derived::value) { + auto pn = stack::pop_n(L, 1); + lua_pushstring(L, &detail::base_class_check_key()[0]); + lua_rawget(L, metatableindex); + if (type_of(L, -1) != type::nil) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata; + success = ic(detail::id_for::value); + } + } + if (!success) { + lua_pop(L, 1); + handler(L, index, type::userdata, indextype); + return false; + } + lua_pop(L, 1); + return true; + } + + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + return check(types(), L, indextype, index, std::forward(handler), tracking); + } + }; + + template + struct checker::value>> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return checker::type, type::userdata>{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::userdata, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return checker{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::multi_check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::multi_check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + type t = type_of(L, index); + if (t == type::none) { + tracking.use(0); + return true; + } + return t == type::nil || stack::check(L, index, std::forward(handler), tracking); + } + }; + } // stack +} // sol + +// end of sol/stack_check.hpp + +// beginning of sol/stack_get.hpp + +// beginning of sol/overload.hpp + +namespace sol { + template + struct overload_set { + std::tuple functions; + template >> = meta::enabler> + overload_set (Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + overload_set(const overload_set&) = default; + overload_set(overload_set&&) = default; + overload_set& operator=(const overload_set&) = default; + overload_set& operator=(overload_set&&) = default; + }; + + template + decltype(auto) overload(Args&&... args) { + return overload_set...>(std::forward(args)...); + } +} + +// end of sol/overload.hpp + +#ifdef SOL_CODECVT_SUPPORT +#include +#include +#endif + +namespace sol { + namespace stack { + + template + struct getter { + static T& get(lua_State* L, int index, record& tracking) { + return getter{}.get(L, index, tracking); + } + }; + + template + struct getter::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tonumber(L, index)); + } + }; + + template + struct getter, std::is_signed>::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointeger(L, index)); + } + }; + + template + struct getter, std::is_unsigned>::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointeger(L, index)); + } + }; + + template + struct getter::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointegerx(L, index, nullptr)); + } + }; + + template + struct getter, std::enable_if_t>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type V; + tracking.use(1); + + index = lua_absindex(L, index); + T arr; + get_field(L, static_cast(-1), index); + int isnum; + std::size_t sizehint = static_cast(lua_tointegerx(L, -1, &isnum)); + if (isnum != 0) { + detail::reserve(arr, sizehint); + } + lua_pop(L, 1); +#if SOL_LUA_VERSION >= 503 + // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 + for (lua_Integer i = 0; ; i += lua_size::value, lua_pop(L, lua_size::value)) { + for (int vi = 0; vi < lua_size::value; ++vi) { + type t = static_cast(lua_geti(L, index, i + vi)); + if (t == type::nil) { + if (i == 0) { + continue; + } + else { + lua_pop(L, (vi + 1)); + return arr; + } + } + } + arr.push_back(stack::get(L, -lua_size::value)); + } +#else + // Zzzz slower but necessary thanks to the lower version API and missing functions qq + for (lua_Integer i = 0; ; i += lua_size::value, lua_pop(L, lua_size::value)) { + for (int vi = 0; vi < lua_size::value; ++vi) { + lua_pushinteger(L, i); + lua_gettable(L, index); + type t = type_of(L, -1); + if (t == type::nil) { + if (i == 0) { + continue; + } + else { + lua_pop(L, (vi + 1)); + return arr; + } + } + } + arr.push_back(stack::get(L, -1)); + } +#endif + return arr; + } + }; + + template + struct getter, std::enable_if_t>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + tracking.use(1); + + T associative; + index = lua_absindex(L, index); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + decltype(auto) key = stack::check_get(L, -2); + if (!key) { + lua_pop(L, 1); + continue; + } + associative.emplace(std::forward(*key), stack::get(L, -1)); + lua_pop(L, 1); + } + return associative; + } + }; + + template + struct getter::value || std::is_base_of::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return T(L, index); + } + }; + + template<> + struct getter { + static userdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return userdata_value(lua_touserdata(L, index)); + } + }; + + template<> + struct getter { + static lightuserdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lightuserdata_value(lua_touserdata(L, index)); + } + }; + + template + struct getter> { + static light get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return light(static_cast(lua_touserdata(L, index))); + } + }; + + template + struct getter> { + static T& get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return *static_cast(lua_touserdata(L, index)); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_touserdata(L, index)); + } + }; + + template<> + struct getter { + static type get(lua_State *L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_type(L, index)); + } + }; + + template<> + struct getter { + static bool get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_toboolean(L, index) != 0; + } + }; + + template<> + struct getter { + static std::string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + std::size_t len; + auto str = lua_tolstring(L, index, &len); + return std::string( str, len ); + } + }; + + template <> + struct getter { + string_detail::string_shim get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + const char* p = lua_tolstring(L, index, &len); + return string_detail::string_shim(p, len); + } + }; + + template<> + struct getter { + static const char* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tostring(L, index); + } + }; + + template<> + struct getter { + static char get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + return len > 0 ? str[0] : '\0'; + } + }; + +#ifdef SOL_CODECVT_SUPPORT + template<> + struct getter { + static std::wstring get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::wstring(); + if (sizeof(wchar_t) == 2) { + std::wstring_convert> convert; + std::wstring r = convert.from_bytes(str, str + len); +#ifdef __MINGW32__ + // Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug + // https://sourceforge.net/p/mingw-w64/bugs/538/ + // http://chat.stackoverflow.com/transcript/message/32271369#32271369 + for (auto& c : r) { + uint8_t* b = reinterpret_cast(&c); + std::swap(b[0], b[1]); + } +#endif + return r; + } + std::wstring_convert> convert; + std::wstring r = convert.from_bytes(str, str + len); + return r; + } + }; + + template<> + struct getter { + static std::u16string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::u16string(); +#ifdef _MSC_VER + std::wstring_convert, int16_t> convert; + auto intd = convert.from_bytes(str, str + len); + std::u16string r(intd.size(), '\0'); + std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); +#else + std::wstring_convert, char16_t> convert; + std::u16string r = convert.from_bytes(str, str + len); +#endif // VC++ is a shit + return r; + } + }; + + template<> + struct getter { + static std::u32string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::u32string(); +#ifdef _MSC_VER + std::wstring_convert, int32_t> convert; + auto intd = convert.from_bytes(str, str + len); + std::u32string r(intd.size(), '\0'); + std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); +#else + std::wstring_convert, char32_t> convert; + std::u32string r = convert.from_bytes(str, str + len); +#endif // VC++ is a shit + return r; + } + }; + + template<> + struct getter { + static wchar_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : wchar_t(0); + } + }; + + template<> + struct getter { + static char16_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : char16_t(0); + } + }; + + template<> + struct getter { + static char32_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : char32_t(0); + } + }; +#endif // codecvt header support + + template<> + struct getter { + static meta_function get(lua_State *L, int index, record& tracking) { + tracking.use(1); + const char* name = getter{}.get(L, index, tracking); + for (std::size_t i = 0; i < meta_function_names.size(); ++i) + if (meta_function_names[i] == name) + return static_cast(i); + return meta_function::construct; + } + }; + + template<> + struct getter { + static nil_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nil; + } + }; + + template<> + struct getter { + static std::nullptr_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullptr; + } + }; + + template<> + struct getter { + static nullopt_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullopt; + } + }; + + template<> + struct getter { + static this_state get(lua_State* L, int, record& tracking) { + tracking.use(0); + return this_state{ L }; + } + }; + + template<> + struct getter { + static lua_CFunction get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tocfunction(L, index); + } + }; + + template<> + struct getter { + static c_closure get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return c_closure(lua_tocfunction(L, index), -1); + } + }; + + template<> + struct getter { + static error get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz = 0; + const char* err = lua_tolstring(L, index, &sz); + if (err == nullptr) { + return error(detail::direct_error, ""); + } + return error(detail::direct_error, std::string(err, sz)); + } + }; + + template<> + struct getter { + static void* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_touserdata(L, index); + } + }; + + template + struct getter { + static T* get_no_nil(lua_State* L, int index, record& tracking) { + tracking.use(1); + void** pudata = static_cast(lua_touserdata(L, index)); + void* udata = *pudata; + return get_no_nil_from(L, udata, index, tracking); + } + + static T* get_no_nil_from(lua_State* L, void* udata, int index, record&) { + if (detail::has_derived::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata; + // use the casting function to properly adjust the pointer for the desired T + udata = ic(udata, detail::id_for::value); + lua_pop(L, 1); + } + T* obj = static_cast(udata); + return obj; + } + + static T* get(lua_State* L, int index, record& tracking) { + type t = type_of(L, index); + if (t == type::nil) { + tracking.use(1); + return nullptr; + } + return get_no_nil(L, index, tracking); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + return getter::get_no_nil(L, index, tracking); + } + }; + + template + struct getter { + static T& get(lua_State* L, int index, record& tracking) { + return *getter::get_no_nil(L, index, tracking); + } + }; + + template + struct getter::value>> { + typedef typename unique_usertype_traits::type P; + typedef typename unique_usertype_traits::actual_type Real; + + static Real& get(lua_State* L, int index, record& tracking) { + tracking.use(1); + P** pref = static_cast(lua_touserdata(L, index)); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); + Real* mem = static_cast(static_cast(fx + 1)); + return *mem; + } + }; + + template + struct getter> { + static T& get(lua_State* L, int index, record& tracking) { + return getter{}.get(L, index, tracking); + } + }; + + template + struct getter> { + typedef std::tuple(nullptr, 0))...> R; + + template + static R apply(std::index_sequence<>, lua_State*, int, record&, TArgs&&... args) { + // Fuck you too, VC++ + return R{std::forward(args)...}; + } + + template + static R apply(std::index_sequence, lua_State* L, int index, record& tracking, TArgs&&... args) { + // Fuck you too, VC++ + typedef std::tuple_element_t> T; + return apply(std::index_sequence(), L, index, tracking, std::forward(args)..., stack::get(L, index + tracking.used, tracking)); + } + + static R get(lua_State* L, int index, record& tracking) { + return apply(std::make_index_sequence(), L, index, tracking); + } + }; + + template + struct getter> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return std::pair(L, index)), decltype(stack::get(L, index))>{stack::get(L, index, tracking), stack::get(L, index + tracking.used, tracking)}; + } + }; + + } // stack +} // sol + +// end of sol/stack_get.hpp + +// beginning of sol/stack_check_get.hpp + +namespace sol { + namespace stack { + template + struct check_getter { + typedef decltype(stack_detail::unchecked_get(nullptr, 0, std::declval())) R; + + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + if (!check(L, index, std::forward(handler))) { + tracking.use(static_cast(!lua_isnone(L, index))); + return nullopt; + } + return stack_detail::unchecked_get(L, index, tracking); + } + }; + + template + struct check_getter> { + template + static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) { + return check_get(L, index, no_panic, tracking); + } + }; + + template + struct check_getter::value && lua_type_of::value == type::number>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct check_getter::value && !meta::any_same::value>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct check_getter::value>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Number value = lua_tonumberx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct getter> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return check_get(L, index, no_panic, tracking); + } + }; + } // stack +} // sol + +// end of sol/stack_check_get.hpp + +// beginning of sol/stack_push.hpp + +// beginning of sol/raii.hpp + +namespace sol { + namespace detail { + struct default_construct { + template + static void construct(T&& obj, Args&&... args) { + std::allocator> alloc{}; + alloc.construct(obj, std::forward(args)...); + } + + template + void operator()(T&& obj, Args&&... args) const { + construct(std::forward(obj), std::forward(args)...); + } + }; + + struct default_destruct { + template + static void destroy(T&& obj) { + std::allocator> alloc{}; + alloc.destroy(obj); + } + + template + void operator()(T&& obj) const { + destroy(std::forward(obj)); + } + }; + + struct deleter { + template + void operator()(T* p) const { + delete p; + } + }; + + template + inline std::unique_ptr make_unique_deleter(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } + + template + struct tagged { + T value; + template , tagged>> = meta::enabler> + tagged(Arg&& arg, Args&&... args) : value(std::forward(arg), std::forward(args)...) {} + }; + } // detail + + template + struct constructor_list {}; + + template + using constructors = constructor_list; + + const auto default_constructor = constructors>{}; + + struct no_construction {}; + const auto no_constructor = no_construction{}; + + struct call_construction {}; + const auto call_constructor = call_construction{}; + + template + struct constructor_wrapper { + std::tuple functions; + template , constructor_wrapper>> = meta::enabler> + constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + }; + + template + inline auto initializers(Functions&&... functions) { + return constructor_wrapper...>(std::forward(functions)...); + } + + template + struct factory_wrapper { + std::tuple functions; + template , factory_wrapper>> = meta::enabler> + factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + }; + + template + inline auto factories(Functions&&... functions) { + return factory_wrapper...>(std::forward(functions)...); + } + + template + struct destructor_wrapper { + Function fx; + destructor_wrapper(Function f) : fx(std::move(f)) {} + }; + + template <> + struct destructor_wrapper {}; + + const destructor_wrapper default_destructor{}; + + template + inline auto destructor(Fx&& fx) { + return destructor_wrapper>(std::forward(fx)); + } + +} // sol + +// end of sol/raii.hpp + +#ifdef SOL_CODECVT_SUPPORT +#endif + +namespace sol { + namespace stack { + template + struct pusher> { + template + static int push_fx(lua_State* L, F&& f, Args&&... args) { + // Basically, we store all user-data like this: + // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new + // data in the first sizeof(T*) bytes, and then however many bytes it takes to + // do the actual object. Things that are std::ref or plain T* are stored as + // just the sizeof(T*), and nothing else. + T** pointerpointer = static_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& referencereference = *pointerpointer; + T* allocationtarget = reinterpret_cast(pointerpointer + 1); + referencereference = allocationtarget; + std::allocator alloc{}; + alloc.construct(allocationtarget, std::forward(args)...); + f(); + return 1; + } + + template + static int push_keyed(lua_State* L, K&& k, Args&&... args) { + return push_fx(L, [&L, &k]() { + luaL_newmetatable(L, &k[0]); + lua_setmetatable(L, -2); + }, std::forward(args)...); + } + + template + static int push(lua_State* L, Args&&... args) { + return push_keyed(L, usertype_traits::metatable, std::forward(args)...); + } + }; + + template + struct pusher> { + template + static int push_fx(lua_State* L, F&& f, T* obj) { + if (obj == nullptr) + return stack::push(L, nil); + T** pref = static_cast(lua_newuserdata(L, sizeof(T*))); + *pref = obj; + f(); + return 1; + } + + template + static int push_keyed(lua_State* L, K&& k, T* obj) { + return push_fx(L, [&L, &k]() { + luaL_newmetatable(L, &k[0]); + lua_setmetatable(L, -2); + }, obj); + } + + static int push(lua_State* L, T* obj) { + return push_keyed(L, usertype_traits*>::metatable, obj); + } + }; + + template <> + struct pusher { + template + static int push(lua_State* L, T&& obj) { + return stack::push(L, detail::ptr(obj)); + } + }; + + template + struct pusher { + template + static int push(lua_State* L, Args&&... args) { + return pusher>{}.push(L, std::forward(args)...); + } + }; + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + template + static int push(lua_State* L, Args&&... args) { + return pusher>{}.push(L, std::forward(args)...); + } + }; + + template + struct pusher::value>> { + typedef typename unique_usertype_traits::type P; + typedef typename unique_usertype_traits::actual_type Real; + + template >> = meta::enabler> + static int push(lua_State* L, Arg&& arg) { + if (unique_usertype_traits::is_null(arg)) + return stack::push(L, nil); + return push_deep(L, std::forward(arg)); + } + + template + static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) { + return push_deep(L, std::forward(arg0), std::forward(arg1), std::forward(args)...); + } + + template + static int push_deep(lua_State* L, Args&&... args) { + P** pref = static_cast(lua_newuserdata(L, sizeof(P*) + sizeof(detail::special_destruct_func) + sizeof(Real))); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); + Real* mem = static_cast(static_cast(fx + 1)); + *fx = detail::special_destruct; + detail::default_construct::construct(mem, std::forward(args)...); + *pref = unique_usertype_traits::get(*mem); + if (luaL_newmetatable(L, &usertype_traits>::metatable[0]) == 1) { + set_field(L, "__gc", detail::unique_destruct

); + } + lua_setmetatable(L, -2); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, const std::reference_wrapper& t) { + return stack::push(L, std::addressof(detail::deref(t.get()))); + } + }; + + template + struct pusher::value>> { + static int push(lua_State* L, const T& value) { + lua_pushnumber(L, value); + return 1; + } + }; + + template + struct pusher, std::is_signed>::value>> { + static int push(lua_State* L, const T& value) { + lua_pushinteger(L, static_cast(value)); + return 1; + } + }; + + template + struct pusher::value>> { + static int push(lua_State* L, const T& value) { + if (std::is_same::value) { + return stack::push(L, static_cast(value)); + } + return stack::push(L, static_cast>(value)); + } + }; + + template + struct pusher, std::is_unsigned>::value>> { + static int push(lua_State* L, const T& value) { + lua_pushinteger(L, static_cast(value)); + return 1; + } + }; + + template + struct pusher, std::enable_if_t>>::value>> { + static int push(lua_State* L, const as_table_t& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont.source)); + lua_createtable(L, static_cast(cont.size()), 0); + int tableindex = lua_gettop(L); + std::size_t index = 1; + for (const auto& i : cont) { +#if SOL_LUA_VERSION >= 503 + int p = stack::push(L, i); + for (int pi = 0; pi < p; ++pi) { + lua_seti(L, tableindex, static_cast(index++)); + } +#else + lua_pushinteger(L, static_cast(index)); + int p = stack::push(L, i); + if (p == 1) { + ++index; + lua_settable(L, tableindex); + } + else { + int firstindex = tableindex + 1 + 1; + for (int pi = 0; pi < p; ++pi) { + stack::push(L, index); + lua_pushvalue(L, firstindex); + lua_settable(L, tableindex); + ++index; + ++firstindex; + } + lua_pop(L, 1 + p); + } +#endif + } + // TODO: figure out a better way to do this...? + //set_field(L, -1, cont.size()); + return 1; + } + }; + + template + struct pusher, std::enable_if_t>>::value>> { + static int push(lua_State* L, const as_table_t& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont.source)); + lua_createtable(L, static_cast(cont.size()), 0); + int tableindex = lua_gettop(L); + for (const auto& pair : cont) { + set_field(L, pair.first, pair.second, tableindex); + } + return 1; + } + }; + + template + struct pusher::value || std::is_base_of::value>> { + static int push(lua_State*, const T& ref) { + return ref.push(); + } + + static int push(lua_State*, T&& ref) { + return ref.push(); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, bool b) { + lua_pushboolean(L, b); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, nil_t) { + lua_pushnil(L); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, metatable_key_t) { + lua_pushlstring(L, "__mt", 4); + return 1; + } + }; + + template<> + struct pusher> { + static int push(lua_State* L, lua_CFunction func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lua_CFunction func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, c_closure cc) { + lua_pushcclosure(L, cc.c_function, cc.upvalues); + return 1; + } + }; + + template + struct pusher> { + template + static int push(std::index_sequence, lua_State* L, T&& c) { + int pushcount = multi_push(L, detail::forward_get(c.upvalues)...); + return stack::push(L, c_closure(c.c_function, pushcount)); + } + + template + static int push(lua_State* L, T&& c) { + return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward(c)); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, void* userdata) { + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lightuserdata_value userdata) { + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, light l) { + lua_pushlightuserdata(L, static_cast(l.value)); + return 1; + } + }; + + template + struct pusher> { + template + static int push_with(lua_State* L, Key&& name, Args&&... args) { + // A dumb pusher + void* rawdata = lua_newuserdata(L, sizeof(T)); + T* data = static_cast(rawdata); + std::allocator alloc; + alloc.construct(data, std::forward(args)...); + if (with_meta) { + lua_CFunction cdel = detail::user_alloc_destroy; + // Make sure we have a plain GC set for this data + if (luaL_newmetatable(L, name) != 0) { + lua_pushlightuserdata(L, rawdata); + lua_pushcclosure(L, cdel, 1); + lua_setfield(L, -2, "__gc"); + } + lua_setmetatable(L, -2); + } + return 1; + } + + template , no_metatable_t, metatable_key_t>> = meta::enabler> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::forward(arg), std::forward(args)...); + } + + template + static int push(lua_State* L, no_metatable_t, Args&&... args) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::forward(args)...); + } + + template + static int push(lua_State* L, metatable_key_t, Key&& key, Args&&... args) { + const auto name = &key[0]; + return push_with(L, name, std::forward(args)...); + } + + static int push(lua_State* L, const user& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, user&& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::move(u.value)); + } + + static int push(lua_State* L, no_metatable_t, const user& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, no_metatable_t, user&& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::move(u.value)); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, userdata_value data) { + void** ud = static_cast(lua_newuserdata(L, sizeof(void*))); + *ud = data.value; + return 1; + } + }; + + template<> + struct pusher { + static int push_sized(lua_State* L, const char* str, std::size_t len) { + lua_pushlstring(L, str, len); + return 1; + } + + static int push(lua_State* L, const char* str) { + return push_sized(L, str, std::char_traits::length(str)); + } + + static int push(lua_State* L, const char* strb, const char* stre) { + return push_sized(L, strb, stre - strb); + } + + static int push(lua_State* L, const char* str, std::size_t len) { + return push_sized(L, str, len); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char(&str)[N]) { + lua_pushlstring(L, str, N - 1); + return 1; + } + + static int push(lua_State* L, const char(&str)[N], std::size_t sz) { + lua_pushlstring(L, str, sz); + return 1; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char c) { + const char str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::string& str) { + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + + static int push(lua_State* L, const std::string& str, std::size_t sz) { + lua_pushlstring(L, str.c_str(), sz); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, meta_function m) { + const std::string& str = name_of(m); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + }; + +#ifdef SOL_CODECVT_SUPPORT + template<> + struct pusher { + static int push(lua_State* L, const wchar_t* wstr) { + return push(L, wstr, std::char_traits::length(wstr)); + } + + static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { + return push(L, wstr, wstr + sz); + } + + static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { + if (sizeof(wchar_t) == 2) { + std::wstring_convert> convert; + std::string u8str = convert.to_bytes(strb, stre); + return stack::push(L, u8str); + } + std::wstring_convert> convert; + std::string u8str = convert.to_bytes(strb, stre); + return stack::push(L, u8str); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const char16_t* u16str) { + return push(L, u16str, std::char_traits::length(u16str)); + } + + static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { + return push(L, u16str, u16str + sz); + } + + static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { +#ifdef _MSC_VER + std::wstring_convert, int16_t> convert; + std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); +#else + std::wstring_convert, char16_t> convert; + std::string u8str = convert.to_bytes(strb, stre); +#endif // VC++ is a shit + return stack::push(L, u8str); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const char32_t* u32str) { + return push(L, u32str, u32str + std::char_traits::length(u32str)); + } + + static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { + return push(L, u32str, u32str + sz); + } + + static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { +#ifdef _MSC_VER + std::wstring_convert, int32_t> convert; + std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); +#else + std::wstring_convert, char32_t> convert; + std::string u8str = convert.to_bytes(strb, stre); +#endif // VC++ is a shit + return stack::push(L, u8str); + } + }; + + template + struct pusher { + static int push(lua_State* L, const wchar_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const wchar_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char16_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const char16_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char32_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const char32_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, wchar_t c) { + const wchar_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char16_t c) { + const char16_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char32_t c) { + const char32_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::wstring& wstr) { + return push(L, wstr.data(), wstr.size()); + } + + static int push(lua_State* L, const std::wstring& wstr, std::size_t sz) { + return stack::push(L, wstr.data(), wstr.data() + sz); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::u16string& u16str) { + return push(L, u16str, u16str.size()); + } + + static int push(lua_State* L, const std::u16string& u16str, std::size_t sz) { + return stack::push(L, u16str.data(), u16str.data() + sz); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::u32string& u32str) { + return push(L, u32str, u32str.size()); + } + + static int push(lua_State* L, const std::u32string& u32str, std::size_t sz) { + return stack::push(L, u32str.data(), u32str.data() + sz); + } + }; +#endif // codecvt Header Support + + template + struct pusher> { + template + static int push(std::index_sequence, lua_State* L, T&& t) { + int pushcount = 0; + (void)detail::swallow{ 0, (pushcount += stack::push(L, + detail::forward_get(t) + ), 0)... }; + return pushcount; + } + + template + static int push(lua_State* L, T&& t) { + return push(std::index_sequence_for(), L, std::forward(t)); + } + }; + + template + struct pusher> { + template + static int push(lua_State* L, T&& t) { + int pushcount = stack::push(L, detail::forward_get<0>(t)); + pushcount += stack::push(L, detail::forward_get<1>(t)); + return pushcount; + } + }; + + template + struct pusher> { + template + static int push(lua_State* L, T&& t) { + if (t == nullopt) { + return stack::push(L, nullopt); + } + return stack::push(L, t.value()); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, nullopt_t) { + return stack::push(L, nil); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, std::nullptr_t) { + return stack::push(L, nil); + } + }; + + template<> + struct pusher { + static int push(lua_State*, const this_state&) { + return 0; + } + }; + } // stack +} // sol + +// end of sol/stack_push.hpp + +// beginning of sol/stack_pop.hpp + +namespace sol { + namespace stack { + template + struct popper { + inline static decltype(auto) pop(lua_State* L) { + record tracking{}; + decltype(auto) r = get(L, -lua_size::value, tracking); + lua_pop(L, tracking.used); + return r; + } + }; + + template + struct popper>::value>> { + static_assert(meta::neg>>::value, "You cannot pop something that derives from stack_reference: it will not remain on the stack and thusly will go out of scope!"); + }; + } // stack +} // sol + +// end of sol/stack_pop.hpp + +// beginning of sol/stack_field.hpp + +namespace sol { + namespace stack { + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_gettable(L, tableindex); + } + }; + + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_rawget(L, tableindex); + } + }; + + template + struct field_getter { + void get(lua_State* L, metatable_key_t, int tableindex = -1) { + if (lua_getmetatable(L, tableindex) == 0) + push(L, nil); + } + }; + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int = -1) { + lua_getglobal(L, &key[0]); + } + }; + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_getfield(L, tableindex, &key[0]); + } + }; + +#if SOL_LUA_VERSION >= 503 + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_geti(L, tableindex, static_cast(key)); + } + }; +#endif // Lua 5.3.x + +#if SOL_LUA_VERSION >= 502 + template + struct field_getter { + void get(lua_State* L, void* key, int tableindex = -1) { + lua_rawgetp(L, tableindex, key); + } + }; +#endif // Lua 5.3.x + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_rawgeti(L, tableindex, static_cast(key)); + } + }; + + template + struct field_getter, b, raw, C> { + template + void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { + get_field(L, detail::forward_get<0>(keys), tableindex); + void(detail::swallow{ (get_field(L, detail::forward_get(keys)), 0)... }); + reference saved(L, -1); + lua_pop(L, static_cast(sizeof...(I))); + saved.push(); + } + + template + void get(lua_State* L, Keys&& keys) { + apply(std::make_index_sequence(), L, std::forward(keys), lua_absindex(L, -1)); + } + + template + void get(lua_State* L, Keys&& keys, int tableindex) { + apply(std::make_index_sequence(), L, std::forward(keys), tableindex); + } + }; + + template + struct field_getter, b, raw, C> { + template + void get(lua_State* L, Keys&& keys, int tableindex) { + get_field(L, detail::forward_get<0>(keys), tableindex); + get_field(L, detail::forward_get<1>(keys)); + reference saved(L, -1); + lua_pop(L, static_cast(2)); + saved.push(); + } + + template + void get(lua_State* L, Keys&& keys) { + get_field(L, detail::forward_get<0>(keys)); + get_field(L, detail::forward_get<1>(keys)); + reference saved(L, -1); + lua_pop(L, static_cast(2)); + saved.push(); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { + push(L, std::forward(key)); + push(L, std::forward(value)); + lua_settable(L, tableindex); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { + push(L, std::forward(key)); + push(L, std::forward(value)); + lua_rawset(L, tableindex); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, metatable_key_t, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_setmetatable(L, tableindex); + } + }; + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int = -2) { + push(L, std::forward(value)); + lua_setglobal(L, &key[0]); + } + }; + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_setfield(L, tableindex, &key[0]); + } + }; + +#if SOL_LUA_VERSION >= 503 + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_seti(L, tableindex, static_cast(key)); + } + }; +#endif // Lua 5.3.x + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_rawseti(L, tableindex, static_cast(key)); + } + }; + +#if SOL_LUA_VERSION >= 502 + template + struct field_setter { + template + void set(lua_State* L, void* key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_rawsetp(L, tableindex, key); + } + }; +#endif // Lua 5.2.x + + template + struct field_setter, b, raw, C> { + template + void apply(std::index_sequence, lua_State* L, Key&& keys, Value&& value, int tableindex) { + I < 1 ? + set_field(L, detail::forward_get(keys), std::forward(value), tableindex) : + set_field(L, detail::forward_get(keys), std::forward(value)); + } + + template + void apply(std::index_sequence, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + I0 < 1 ? get_field(L, detail::forward_get(keys), tableindex) : get_field(L, detail::forward_get(keys), -1); + apply(std::index_sequence(), L, std::forward(keys), std::forward(value), -1); + } + + template + void top_apply(std::index_sequence, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + apply(std::index_sequence(), L, std::forward(keys), std::forward(value), tableindex); + lua_pop(L, static_cast(sizeof...(I))); + } + + template + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { + top_apply(std::make_index_sequence(), L, std::forward(keys), std::forward(value), tableindex); + } + }; + + template + struct field_setter, b, raw, C> { + template + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { + get_field(L, detail::forward_get<0>(keys), tableindex); + set_field(L, detail::forward_get<1>(keys), std::forward(value)); + lua_pop(L, 1); + } + }; + } // stack +} // sol + +// end of sol/stack_field.hpp + +// beginning of sol/stack_probe.hpp + +namespace sol { + namespace stack { + template + struct probe_field_getter { + template + probe get(lua_State* L, Key&& key, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field(L, std::forward(key), tableindex); + return probe(!check(L), 1); + } + }; + + template + struct probe_field_getter, b, raw, C> { + template + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field(L, std::get<0>(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, 1); + } + get_field(L, std::get<1>(keys), tableindex); + return probe(!check(L), 2); + } + }; + + template + struct probe_field_getter, b, raw, C> { + template + probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I < 1 && b, raw>(L, std::get(keys), tableindex); + return probe(!check(L), sofar); + } + + template + probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I < 1 && b, raw>(L, std::get(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, sofar); + } + return apply(std::index_sequence(), sofar + 1, L, std::forward(keys), -1); + } + + template + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); + } + }; + } // stack +} // sol + +// end of sol/stack_probe.hpp + +#include + +namespace sol { + namespace stack { + namespace stack_detail { + template + inline int push_as_upvalues(lua_State* L, T& item) { + typedef std::decay_t TValue; + const static std::size_t itemsize = sizeof(TValue); + const static std::size_t voidsize = sizeof(void*); + const static std::size_t voidsizem1 = voidsize - 1; + const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; + typedef std::array data_t; + + data_t data{ {} }; + std::memcpy(&data[0], std::addressof(item), itemsize); + int pushcount = 0; + for (auto&& v : data) { + pushcount += push(L, lightuserdata_value(v)); + } + return pushcount; + } + + template + inline std::pair get_as_upvalues(lua_State* L, int index = 1) { + const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); + typedef std::array data_t; + data_t voiddata{ {} }; + for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { + voiddata[i] = get(L, upvalue_index(index++)); + } + return std::pair(*reinterpret_cast(static_cast(voiddata.data())), index); + } + + struct evaluator { + template + static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) { + return std::forward(fx)(std::forward(args)...); + } + + template + static decltype(auto) eval(types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { + return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); + } + }; + + template ::value>> + inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { +#ifndef _MSC_VER + static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); +#endif // This compiler make me so fucking sad + multi_check(L, start, type_panic); + record tracking{}; + return evaluator{}.eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { +#ifndef _MSC_VER + static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); +#endif // This compiler make me so fucking sad + multi_check(L, start, type_panic); + record tracking{}; + evaluator{}.eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + } // stack_detail + + template + int set_ref(lua_State* L, T&& arg, int tableindex = -2) { + push(L, std::forward(arg)); + return luaL_ref(L, tableindex); + } + + inline void remove(lua_State* L, int index, int count) { + if (count < 1) + return; + int top = lua_gettop(L); + if (index == -1 || top == index) { + // Slice them right off the top + lua_pop(L, static_cast(count)); + return; + } + + // Remove each item one at a time using stack operations + // Probably slower, maybe, haven't benchmarked, + // but necessary + if (index < 0) { + index = lua_gettop(L) + (index + 1); + } + int last = index + count; + for (int i = index; i < last; ++i) { + lua_remove(L, i); + } + } + + template ::value>> + inline decltype(auto) call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + typedef std::make_index_sequence args_indices; + return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + + template ::value>> + inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + typedef std::make_index_sequence args_indices; + stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + + template ::value>> + inline decltype(auto) call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + return call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); + } + + template + inline void call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); + } + + template + inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); + lua_settop(L, 0); + return 0; + } + + template>::value>> + inline int call_into_lua(types, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + lua_settop(L, 0); + return push_reference(L, std::forward(r)); + } + + template + inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + typedef lua_bind_traits> traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::returns_list returns_list; + return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); + } + + inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) { + luaL_getmetatable(L, key.c_str()); + auto pn = pop_n(L, 1); + if (lua_compare(L, -1, index, LUA_OPEQ) == 1) { + return call_syntax::colon; + } + return call_syntax::dot; + } + + inline void script(lua_State* L, const std::string& code) { + if (luaL_dostring(L, code.c_str())) { + lua_error(L); + } + } + + inline void script_file(lua_State* L, const std::string& filename) { + if (luaL_dofile(L, filename.c_str())) { + lua_error(L); + } + } + + inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { +#ifdef SOL_LUAJIT + lua_pushlightuserdata(L, (void*)handler); + auto pn = pop_n(L, 1); + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); +#else + (void)L; + (void)handler; +#endif + } + + inline void luajit_exception_off(lua_State* L) { +#ifdef SOL_LUAJIT + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); +#else + (void)L; +#endif + } + } // stack +} // sol + +// end of sol/stack.hpp + +// beginning of sol/variadic_args.hpp + +// beginning of sol/stack_proxy.hpp + +// beginning of sol/function.hpp + +// beginning of sol/function_result.hpp + +// beginning of sol/proxy_base.hpp + +namespace sol { + template + struct proxy_base { + operator std::string() const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + + template>, is_proxy_primitive>> = meta::enabler> + operator T () const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + + template>, meta::neg>>> = meta::enabler> + operator T& () const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + }; +} // sol + +// end of sol/proxy_base.hpp + +#include + +namespace sol { + struct function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + + public: + function_result() = default; + function_result(lua_State* L, int index = -1, int returncount = 0) : L(L), index(index), returncount(returncount) { + + } + function_result(const function_result&) = default; + function_result& operator=(const function_result&) = default; + function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + } + function_result& operator=(function_result&& o) { + L = o.L; + index = o.index; + returncount = o.returncount; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + return *this; + } + + template + decltype(auto) get() const { + return stack::get(L, index); + } + + call_status status() const noexcept { + return call_status::ok; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + + ~function_result() { + lua_pop(L, returncount); + } + }; +} // sol + +// end of sol/function_result.hpp + +// beginning of sol/function_types.hpp + +// beginning of sol/function_types_core.hpp + +// beginning of sol/wrapper.hpp + +namespace sol { + + template + struct wrapper { + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) call(F& f, Args&&... args) { + return f(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward(args)...); + } + }; + }; + + template + struct wrapper>>::value>> { + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) invoke(Args&&... args) { + return fx(std::forward(args)...); + } + + template + static decltype(auto) call(F& fx, Args&&... args) { + return fx(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + }; + }; + + template + struct wrapper>::value>> { + typedef lua_bind_traits traits_type; + typedef typename traits_type::object_type object_type; + typedef typename traits_type::return_type return_type; + typedef typename traits_type::args_list args_list; + typedef types free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) invoke(object_type& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + template + static decltype(auto) call(Fx&& fx, object_type& mem) { + return (mem.*fx); + } + + template + static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { + (mem.*fx) = std::forward(arg); + } + + struct caller { + template + decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { + return call(std::forward(fx), mem, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + }; + }; + + template + struct member_function_wrapper { + typedef O object_type; + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + + template + static R invoke(O& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + template + static R call(Fx&& fx, O& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { + return call(std::forward(fx), mem, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(O& mem, Args&&... args) const { + return invoke(mem, std::forward(args)...); + } + }; + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + +} // sol + +// end of sol/wrapper.hpp + +namespace sol { + namespace function_detail { + template + inline int call(lua_State* L) { + Fx& fx = stack::get>(L, upvalue_index(1)); + return fx(L); + } + } // function_detail +} // sol + +// end of sol/function_types_core.hpp + +// beginning of sol/function_types_templated.hpp + +// beginning of sol/call.hpp + +// beginning of sol/protect.hpp + +namespace sol { + + template + struct protect_t { + T value; + + template >> = meta::enabler> + protect_t(Arg&& arg, Args&&... args) : value(std::forward(arg), std::forward(args)...) {} + + protect_t(const protect_t&) = default; + protect_t(protect_t&&) = default; + protect_t& operator=(const protect_t&) = default; + protect_t& operator=(protect_t&&) = default; + + }; + + template + auto protect(T&& value) { + return protect_t>(std::forward(value)); + } + +} // sol + +// end of sol/protect.hpp + +// beginning of sol/property.hpp + +namespace sol { + + struct no_prop { }; + + template + struct property_wrapper { + typedef std::integral_constant::value> can_read; + typedef std::integral_constant::value> can_write; + typedef std::conditional_t Read; + typedef std::conditional_t Write; + Read read; + Write write; + + template + property_wrapper(Rx&& r, Wx&& w) : read(std::forward(r)), write(std::forward(w)) {} + }; + + namespace property_detail { + template + inline decltype(auto) property(std::true_type, R&& read, W&& write) { + return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); + } + template + inline decltype(auto) property(std::false_type, W&& write, R&& read) { + return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); + } + template + inline decltype(auto) property(std::true_type, R&& read) { + return property_wrapper, void>(std::forward(read), no_prop()); + } + template + inline decltype(auto) property(std::false_type, W&& write) { + return property_wrapper>(no_prop(), std::forward(write)); + } + } // property_detail + + template + inline decltype(auto) property(F&& f, G&& g) { + typedef lua_bind_traits> left_traits; + typedef lua_bind_traits> right_traits; + return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward(f), std::forward(g)); + } + + template + inline decltype(auto) property(F&& f) { + typedef lua_bind_traits> left_traits; + return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward(f)); + } + + template + inline decltype(auto) readonly_property(F&& f) { + return property_detail::property(std::true_type(), std::forward(f)); + } + + // Allow someone to make a member variable readonly (const) + template + inline auto readonly(R T::* v) { + typedef const R C; + return static_cast(v); + } + + template + struct var_wrapper { + T value; + template + var_wrapper(Args&&... args) : value(std::forward(args)...) {} + var_wrapper(const var_wrapper&) = default; + var_wrapper(var_wrapper&&) = default; + var_wrapper& operator=(const var_wrapper&) = default; + var_wrapper& operator=(var_wrapper&&) = default; + }; + + template + inline auto var(V&& v) { + typedef meta::unqualified_t T; + return var_wrapper(std::forward(v)); + } + +} // sol + +// end of sol/property.hpp + +namespace sol { + namespace call_detail { + + template + inline auto& pick(std::true_type, property_wrapper& f) { + return f.read; + } + + template + inline auto& pick(std::false_type, property_wrapper& f) { + return f.write; + } + + template + struct void_call; + + template + struct void_call> { + static void call(Args...) {} + }; + + template + struct constructor_match { + T* obj; + + constructor_match(T* obj) : obj(obj) {} + + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start) const { + detail::default_construct func{}; + return stack::call_into_lua(r, a, L, start, func, obj); + } + }; + + namespace overload_detail { + template + inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence, Match&&, lua_State* L, int, int, Args&&...) { + return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); + } + + template + inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v, index_value...>::value) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + stack::record tracking{}; + if (!stack::stack_detail::check_types{}.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + } // overload_detail + + template + inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_detail::overload_match_arity(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { + int fxarity = lua_gettop(L) - (start - 1); + return overload_match_arity(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + // use same overload resolution matching as all other parts of the framework + return overload_match_arity::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct(lua_State* L) { + static const auto& meta = usertype_traits::metatable; + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot; + argcount -= static_cast(syntax); + + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + reference userdataref(L, -1); + userdataref.pop(); + + construct_match(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); + + userdataref.push(); + luaL_getmetatable(L, &meta[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return luaL_error(L, "sol: unable to get usertype metatable"); + } + + lua_setmetatable(L, -2); + return 1; + } + + template + struct agnostic_lua_call_wrapper { + template + static int call(lua_State* L, Fx&& f, Args&&... args) { + typedef wrapper> wrap; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::free_args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); + } + }; + + template + struct agnostic_lua_call_wrapper, true, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return stack::push_reference(L, detail::unwrap(f.value)); + } + }; + + template + struct agnostic_lua_call_wrapper, false, is_variable, checked, boost, C> { + template + static int call_assign(std::true_type, lua_State* L, V&& f) { + detail::unwrap(f.value) = stack::get>(L, boost + (is_variable ? 3 : 1)); + return 0; + } + + template + static int call_assign(std::false_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + template + static int call_const(std::false_type, lua_State* L, Args&&... args) { + typedef meta::unwrapped_t R; + return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); + } + + template + static int call_const(std::true_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + template + static int call(lua_State* L, V&& f) { + return call_const(std::is_const>(), L, f); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_r_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const no_prop&) { + return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const no_construction&) { + return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); + } + }; + + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, C> { + static int call(lua_State*, const bases&) { + // Uh. How did you even call this, lul + return 0; + } + }; + + template + struct lua_call_wrapper : agnostic_lua_call_wrapper {}; + + template + struct lua_call_wrapper::value>> { + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, Fx&& f, object_type& o) { + typedef typename wrap::returns_list returns_list; + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward(f), o); + } + + template + static int call(lua_State* L, Fx&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* o = static_cast(stack::get(L, 1)); + if (o == nullptr) { + return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); + } + return call(L, std::forward(f), *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, std::forward(f), o); +#endif // Safety + } + }; + + template + struct lua_call_wrapper::value>> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(types(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); + } + + template + static int call_assign(std::true_type, lua_State* L, V&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* o = static_cast(stack::get(L, 1)); + if (o == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); + } + return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + } + return call_assign(std::true_type(), L, f, *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call_assign(std::true_type(), L, f, o); +#endif // Safety + } + + template + static int call_assign(std::false_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + template + static int call_const(std::false_type, lua_State* L, Args&&... args) { + typedef typename traits_type::return_type R; + return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); + } + + template + static int call_const(std::true_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + template + static int call(lua_State* L, V&& f) { + return call_const(std::is_const(), L, f); + } + + template + static int call(lua_State* L, V&& f, object_type& o) { + return call_const(std::is_const(), L, f, o); + } + }; + + template + struct lua_call_wrapper::value>> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, V&& f, object_type& o) { + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); + } + + template + static int call(lua_State* L, V&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* o = static_cast(stack::get(L, 1)); + if (o == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)"); + } + return call(L, f, *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, f, o); +#endif // Safety + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef constructor_list F; + + static int call(lua_State* L, F&) { + const auto& metakey = usertype_traits::metatable; + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot; + argcount -= static_cast(syntax); + + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + + construct_match(constructor_match(obj), L, argcount, boost + 1 + static_cast(syntax)); + + userdataref.push(); + luaL_getmetatable(L, &metakey[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return luaL_error(L, "sol: unable to get usertype metatable"); + } + + lua_setmetatable(L, -2); + return 1; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef constructor_wrapper F; + + struct onmatch { + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start, F& f) { + const auto& metakey = usertype_traits::metatable; + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + + auto& func = std::get(f.functions); + stack::call_into_lua(r, a, L, boost + start, func, detail::implicit_wrapper(obj)); + + userdataref.push(); + luaL_getmetatable(L, &metakey[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + std::string err = "sol: unable to get usertype metatable for "; + err += usertype_traits::name; + return luaL_error(L, err.c_str()); + } + lua_setmetatable(L, -2); + + return 1; + } + }; + + static int call(lua_State* L, F& f) { + call_syntax syntax = stack::get_call_syntax(L, usertype_traits::metatable); + int syntaxval = static_cast(syntax); + int argcount = lua_gettop(L) - syntaxval; + return construct_match>...>(onmatch(), L, argcount, 1 + syntaxval, f); + } + + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, std::enable_if_t::value>> { + typedef destructor_wrapper F; + + static int call(lua_State* L, const F&) { + return detail::usertype_alloc_destroy(L); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, std::enable_if_t::value>> { + typedef destructor_wrapper F; + + static int call(lua_State* L, const F& f) { + T& obj = stack::get(L); + f.fx(detail::implicit_wrapper(obj)); + return 0; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef overload_set F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.functions); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef factory_wrapper F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.functions); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef std::conditional_t P; + typedef meta::unqualified_t

U; + typedef lua_bind_traits traits_type; + + template + static int self_call(lua_State* L, F&& f) { + typedef wrapper wrap; + typedef meta::unqualified_t> object_type; + typedef meta::pop_front_type_t args_list; + typedef T Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* po = static_cast(stack::get(L, 1)); + if (po == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)"); + } + object_type& o = *po; +#else + object_type& o = static_cast(*stack::get>(L, 1)); +#endif // Safety + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, o); + } + + template + static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { + return self_call(L, pick(meta::boolean(), f), std::forward(args)...); + } + + template + static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { + auto& p = pick(meta::boolean(), std::forward(f)); + return lua_call_wrapper, is_index, is_variable, checked, boost>{}.call(L, p, std::forward(args)...); + } + + template + static int call(lua_State* L, F&& f, Args&&... args) { + typedef meta::any< + std::is_void, + std::is_same, + meta::is_specialization_of, + meta::is_specialization_of, + meta::is_specialization_of, + std::is_member_pointer + > is_specialized; + return defer_call(is_specialized(), L, std::forward(f), std::forward(args)...); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef protect_t F; + + template + static int call(lua_State* L, F& fx, Args&&... args) { + return lua_call_wrapper{}.call(L, fx.value, std::forward(args)...); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::get<0>(f.arguments)); + } + }; + + template + inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward(fx), std::forward(args)...); + } + + template + inline int call_user(lua_State* L) { + auto& fx = stack::get>(L, upvalue_index(1)); + return call_wrapped(L, fx); + } + + template + struct is_var_bind : std::false_type {}; + + template + struct is_var_bind::value>> : std::true_type {}; + + template <> + struct is_var_bind : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + } // call_detail + + template + struct is_variable_binding : call_detail::is_var_bind> {}; + + template + struct is_function_binding : meta::neg> {}; + +} // sol + +// end of sol/call.hpp + +namespace sol { + namespace function_detail { + template + inline int call_wrapper_variable(std::false_type, lua_State* L) { + typedef meta::bind_traits> traits_type; + typedef typename traits_type::args_list args_list; + typedef meta::tuple_types return_type; + return stack::call_into_lua(return_type(), args_list(), L, 1, fx); + } + + template + inline int call_set_assignable(std::false_type, T&&, lua_State* L) { + return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); + } + + template + inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { + (mem.*variable) = stack::get(L, 2); + return 0; + } + + template + inline int call_set_variable(std::false_type, lua_State* L, T&&) { + return luaL_error(L, "cannot write to a const variable"); + } + + template + inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { + return call_set_assignable(std::is_assignable, R>(), L, std::forward(mem)); + } + + template + inline int call_wrapper_variable(std::true_type, lua_State* L) { + typedef meta::bind_traits> traits_type; + typedef typename traits_type::object_type T; + typedef typename traits_type::return_type R; + auto& mem = stack::get(L, 1); + switch (lua_gettop(L)) { + case 1: { + decltype(auto) r = (mem.*variable); + stack::push_reference(L, std::forward(r)); + return 1; } + case 2: + return call_set_variable(meta::neg>(), L, mem); + default: + return luaL_error(L, "incorrect number of arguments to member variable function call"); + } + } + + template + inline int call_wrapper_function(std::false_type, lua_State* L) { + return call_wrapper_variable(std::is_member_object_pointer(), L); + } + + template + inline int call_wrapper_function(std::true_type, lua_State* L) { + return call_detail::call_wrapped(L, fx); + } + + template + int call_wrapper_entry(lua_State* L) { + return call_wrapper_function(std::is_member_function_pointer>(), L); + } + + template + struct c_call_matcher { + template + int operator()(types, index_value, types, types, lua_State* L, int, int) const { + typedef meta::at_in_pack_t target; + return target::call(L); + } + }; + + } // function_detail + + template + inline int c_call(lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, function_detail::call_wrapper_entry); +#else + return detail::static_trampoline<(&function_detail::call_wrapper_entry)>(L); +#endif // fuck you clang :c + } + + template + struct wrap { + typedef F type; + + static int call(lua_State* L) { + return c_call(L); + } + }; + + template + inline int c_call(lua_State* L) { + if (sizeof...(Fxs) < 2) { + return meta::at_in_pack_t<0, Fxs...>::call(L); + } + else { + return call_detail::overload_match_arity(function_detail::c_call_matcher(), L, lua_gettop(L), 1); + } + } + +} // sol + +// end of sol/function_types_templated.hpp + +// beginning of sol/function_types_stateless.hpp + +namespace sol { + namespace function_detail { + template + struct upvalue_free_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + auto udata = stack::stack_detail::get_as_upvalues(L); + function_type* fx = udata.first; + return call_detail::call_wrapped(L, fx); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member function pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + function_type& memfx = memberdata.first; + auto& item = *objdata.first; + return call_detail::call_wrapped(L, memfx, item); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + auto& mem = *objdata.first; + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped(L, var, mem); + case 1: + return call_detail::call_wrapped(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_this_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& memfx = memberdata.first; + return call_detail::call_wrapped(L, memfx); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_this_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + return call_detail::call_wrapped(L, var); + case 2: + return call_detail::call_wrapped(L, var); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + } // function_detail +} // sol + +// end of sol/function_types_stateless.hpp + +// beginning of sol/function_types_stateful.hpp + +namespace sol { + namespace function_detail { + template + struct functor_function { + typedef meta::unwrapped_t> Function; + typedef decltype(&Function::operator()) function_type; + typedef meta::function_return_t return_type; + typedef meta::function_args_t args_lists; + Function fx; + + template + functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} + + int call(lua_State* L) { + return call_detail::call_wrapped(L, fx); + } + + int operator()(lua_State* L) { + auto f = [&](lua_State* L) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + + template + struct member_function { + typedef std::remove_pointer_t> function_type; + typedef meta::function_return_t return_type; + typedef meta::function_args_t args_lists; + function_type invocation; + T member; + + template + member_function(function_type f, Args&&... args) : invocation(std::move(f)), member(std::forward(args)...) {} + + int call(lua_State* L) { + return call_detail::call_wrapped(L, invocation, detail::unwrap(detail::deref(member))); + } + + int operator()(lua_State* L) { + auto f = [&](lua_State* L) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + + template + struct member_variable { + typedef std::remove_pointer_t> function_type; + typedef typename meta::bind_traits::return_type return_type; + typedef typename meta::bind_traits::args_list args_lists; + function_type var; + T member; + typedef std::add_lvalue_reference_t>> M; + + template + member_variable(function_type v, Args&&... args) : var(std::move(v)), member(std::forward(args)...) {} + + int call(lua_State* L) { + M mem = detail::unwrap(detail::deref(member)); + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped(L, var, mem); + case 1: + return call_detail::call_wrapped(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + int operator()(lua_State* L) { + auto f = [&](lua_State* L) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + } // function_detail +} // sol + +// end of sol/function_types_stateful.hpp + +// beginning of sol/function_types_overloaded.hpp + +namespace sol { + namespace function_detail { + template + struct overloaded_function { + typedef std::tuple overload_list; + typedef std::make_index_sequence indices; + overload_list overloads; + + overloaded_function(overload_list set) + : overloads(std::move(set)) {} + + overloaded_function(Functions... fxs) + : overloads(fxs...) { + + } + + template + int call(types, index_value, types, types, lua_State* L, int, int) { + auto& func = std::get(overloads); + return call_detail::call_wrapped(L, func); + } + + int operator()(lua_State* L) { + auto mfx = [&](auto&&... args) { return this->call(std::forward(args)...); }; + return call_detail::overload_match(mfx, L, 1); + } + }; + } // function_detail +} // sol + +// end of sol/function_types_overloaded.hpp + +// beginning of sol/resolve.hpp + +namespace sol { + namespace detail { + template(Args...)>> + inline auto resolve_i(types, F&&)->R(meta::unqualified_t::*)(Args...) { + using Sig = R(Args...); + typedef meta::unqualified_t Fu; + return static_cast(&Fu::operator()); + } + + template> + inline auto resolve_f(std::true_type, F&& f) + -> decltype(resolve_i(types>(), std::forward(f))) { + return resolve_i(types>(), std::forward(f)); + } + + template + inline void resolve_f(std::false_type, F&&) { + static_assert(meta::has_deducible_signature::value, + "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + } + + template> + inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature(), std::forward(f))) { + return resolve_f(meta::has_deducible_signature {}, std::forward(f)); + } + + template> + inline auto resolve_i(types, F&& f) -> decltype(resolve_i(types(), std::forward(f))) { + return resolve_i(types(), std::forward(f)); + } + + template + inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { + return mem_func_ptr; + } + + template + inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { + return mem_variable_ptr; + } + } // detail + + template + inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) { + return fun_ptr; + } + + template + inline Sig* resolve(Sig* fun_ptr) { + return fun_ptr; + } + + template + inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { + return mem_ptr; + } + + template + inline Sig C::* resolve(Sig C::* mem_ptr) { + return detail::resolve_v(std::is_member_object_pointer(), mem_ptr); + } + + template + inline auto resolve(F&& f) -> decltype(detail::resolve_i(types(), std::forward(f))) { + return detail::resolve_i(types(), std::forward(f)); + } +} // sol + +// end of sol/resolve.hpp + +namespace sol { + namespace stack { + template + struct pusher> { + template + static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::functor_function F; + set_fx(L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { + using fx_ptr_t = R(*)(A...); + fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); + select_function(std::true_type(), L, fxptr, std::forward(args)...); + } + + template + static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::decay_t> raw_fx_t; + typedef R(*fx_ptr_t)(A...); + typedef std::is_convertible is_convertible; + select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { + typedef meta::function_signature_t> Sig; + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::member_variable, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t clean_fx; + typedef function_detail::member_function, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { + std::decay_t target(std::forward(fx), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_free_function::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, target); + stack::push(L, c_closure(freefunc, upvalues)); + } + + static void select_function(std::true_type, lua_State* L, lua_CFunction f) { + stack::push(L, f); + } + + template + static void select(lua_State* L, Fx&& fx, Args&&... args) { + select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void set_fx(lua_State* L, Args&&... args) { + lua_CFunction freefunc = function_detail::call>; + + stack::push>(L, std::forward(args)...); + stack::push(L, c_closure(freefunc, 1)); + } + + template + static int push(lua_State* L, Args&&... args) { + // Set will always place one thing (function) on the stack + select(L, std::forward(args)...); + return 1; + } + }; + + template + struct pusher> { + template + static int push_func(std::index_sequence, lua_State* L, FP&& fp) { + return stack::push(L, detail::forward_get(fp.arguments)...); + } + + static int push(lua_State* L, const function_arguments& fp) { + return push_func(std::make_index_sequence(), L, fp); + } + + static int push(lua_State* L, function_arguments&& fp) { + return push_func(std::make_index_sequence(), L, std::move(fp)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, std::function fx) { + return pusher>{}.push(L, std::move(fx)); + } + }; + + template + struct pusher::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; + + template + struct pusher, meta::neg>, meta::neg>>>::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, overload_set&& set) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, std::move(set.functions)); + return 1; + } + + static int push(lua_State* L, const overload_set& set) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, set.functions); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, protect_t&& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::move(pw.value)); + return stack::push(L, c_closure(cf, closures)); + } + + static int push(lua_State* L, const protect_t& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, pw.value); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher, std::enable_if_t::value && !std::is_void::value>> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, sol::overload(pw.read, pw.write)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.read)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.read); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.write)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.write); + } + }; + + template + struct pusher> { + static int push(lua_State* L, var_wrapper&& vw) { + return stack::push(L, std::move(vw.value)); + } + static int push(lua_State* L, const var_wrapper& vw) { + return stack::push(L, vw.value); + } + }; + + template + struct pusher> { + static int push(lua_State* L, const factory_wrapper& fw) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, fw.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper&& fw) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, std::move(fw.functions)); + return 1; + } + }; + + template + struct pusher>> { + static int push(lua_State* L, detail::tagged>) { + lua_CFunction cf = call_detail::construct; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + template + static int push(lua_State* L, C&& c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::forward(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper) { + lua_CFunction cf = detail::usertype_alloc_destroy; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>(L, std::move(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + } // stack +} // sol + +// end of sol/function_types.hpp + +namespace sol { + template + class basic_function : public base_t { + private: + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { + lua_callk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), 0, nullptr); + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, lua_size>::value); + return stack::pop>(base_t::lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, lua_size::value); + return stack::pop(base_t::lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, 0); + } + + function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { + int stacksize = lua_gettop(base_t::lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(base_t::lua_state()); + int returncount = poststacksize - (firstreturn - 1); + return function_result(base_t::lua_state(), firstreturn, returncount); + } + + public: + basic_function() = default; + template , basic_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_function(const basic_function&) = default; + basic_function& operator=(const basic_function&) = default; + basic_function(basic_function&&) = default; + basic_function& operator=(basic_function&&) = default; + basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + template + function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) const { + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; + + namespace stack { + template + struct getter> { + typedef meta::bind_traits fx_t; + typedef typename fx_t::args_list args_lists; + typedef meta::tuple_types return_types; + + template + static std::function get_std_func(types, types, lua_State* L, int index) { + sol::function f(L, index); + auto fx = [f, L, index](Args&&... args) -> meta::return_type_t { + return f.call(std::forward(args)...); + }; + return std::move(fx); + } + + template + static std::function get_std_func(types, types, lua_State* L, int index) { + sol::function f(L, index); + auto fx = [f, L, index](FxArgs&&... args) -> void { + f(std::forward(args)...); + }; + return std::move(fx); + } + + template + static std::function get_std_func(types<>, types t, lua_State* L, int index) { + return get_std_func(types(), t, L, index); + } + + static std::function get(lua_State* L, int index, record& tracking) { + tracking.last = 1; + tracking.used += 1; + type t = type_of(L, index); + if (t == type::none || t == type::nil) { + return nullptr; + } + return get_std_func(return_types(), args_lists(), L, index); + } + }; + } // stack +} // sol + +// end of sol/function.hpp + +// beginning of sol/protected_function.hpp + +// beginning of sol/protected_function_result.hpp + +namespace sol { + struct protected_function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + int popcount; + call_status err; + + template + decltype(auto) tagged_get(types>) const { + if (!valid()) { + return sol::optional(nullopt); + } + return stack::get>(L, index); + } + + template + decltype(auto) tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (!valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return stack::get(L, index); + } + + optional tagged_get(types>) const { + if (valid()) { + return nullopt; + } + return error(detail::direct_error, stack::get(L, index)); + } + + error tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return error(detail::direct_error, stack::get(L, index)); + } + + public: + protected_function_result() = default; + protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status err = call_status::ok) noexcept : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { + + } + protected_function_result(const protected_function_result&) = default; + protected_function_result& operator=(const protected_function_result&) = default; + protected_function_result(protected_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = call_status::runtime; + } + protected_function_result& operator=(protected_function_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = call_status::runtime; + return *this; + } + + call_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + template + decltype(auto) get() const { + return tagged_get(types>()); + } + + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; + + ~protected_function_result() { + stack::remove(L, index, popcount); + } + }; +} // sol + +// end of sol/protected_function_result.hpp + +#include + +namespace sol { + namespace detail { + inline reference& handler_storage() { + static sol::reference h; + return h; + } + + struct handler { + const reference& target; + int stackindex; + handler(const reference& target) : target(target), stackindex(0) { + if (target.valid()) { + stackindex = lua_gettop(target.lua_state()) + 1; + target.push(); + } + } + bool valid() const { return stackindex != 0; } + ~handler() { + if (valid()) { + lua_remove(target.lua_state(), stackindex); + } + } + }; + } + + template + class basic_protected_function : public base_t { + public: + static reference& get_default_handler() { + return detail::handler_storage(); + } + + static void set_default_handler(const reference& ref) { + detail::handler_storage() = ref; + } + + static void set_default_handler(reference&& ref) { + detail::handler_storage() = std::move(ref); + } + + private: + call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler& h) const { + return static_cast(lua_pcallk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), h.stackindex, 0, nullptr)); + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, sizeof...(Ret), h); + return stack::pop>(base_t::lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, 1, h); + return stack::pop(base_t::lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, 0, h); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler& h) const { + int stacksize = lua_gettop(base_t::lua_state()); + int poststacksize = stacksize; + int firstreturn = 1; + int returncount = 0; + call_status code = call_status::ok; +#ifndef SOL_NO_EXCEPTIONS + auto onexcept = [&](const char* error) { + h.stackindex = 0; + if (h.target.valid()) { + h.target.push(); + stack::push(base_t::lua_state(), error); + lua_call(base_t::lua_state(), 1, 1); + } + else { + stack::push(base_t::lua_state(), error); + } + }; + try { +#endif // No Exceptions + firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid()))); + code = luacall(n, LUA_MULTRET, h); + poststacksize = lua_gettop(base_t::lua_state()) - static_cast(h.valid()); + returncount = poststacksize - (firstreturn - 1); +#ifndef SOL_NO_EXCEPTIONS + } + // Handle C++ errors thrown from C++ functions bound inside of lua + catch (const char* error) { + onexcept(error); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (const std::exception& error) { + onexcept(error.what()); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (...) { + onexcept("caught (...) unknown error during protected_function call"); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } +#endif // No Exceptions + return protected_function_result(base_t::lua_state(), firstreturn, returncount, returncount, code); + } + + public: + reference error_handler; + + basic_protected_function() = default; + template , basic_protected_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_protected_function(const basic_protected_function&) = default; + basic_protected_function& operator=(const basic_protected_function&) = default; + basic_protected_function(basic_protected_function&&) = default; + basic_protected_function& operator=(basic_protected_function&&) = default; + basic_protected_function(const basic_function& b, reference eh = get_default_handler()) : base_t(b), error_handler(std::move(eh)) {} + basic_protected_function(basic_function&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} + basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + template + basic_protected_function(proxy_base&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} + template + basic_protected_function(const proxy_base& p, reference eh = get_default_handler()) : basic_protected_function(static_cast>(p), std::move(eh)) {} + basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + template + protected_function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) const { + detail::handler h(error_handler); + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount, h); + } + }; +} // sol + +// end of sol/protected_function.hpp + +namespace sol { + struct stack_proxy : public proxy_base { + private: + lua_State* L; + int index; + + public: + stack_proxy() : L(nullptr), index(0) {} + stack_proxy(lua_State* L, int index) : L(L), index(index) {} + + template + decltype(auto) get() const { + return stack::get(L, stack_index()); + } + + int push() const { + lua_pushvalue(L, index); + return 1; + } + + lua_State* lua_state() const { return L; } + int stack_index() const { return index; } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + }; + + namespace stack { + template <> + struct getter { + static stack_proxy get(lua_State* L, int index = -1) { + return stack_proxy(L, index); + } + }; + + template <> + struct pusher { + static int push(lua_State*, const stack_proxy& ref) { + return ref.push(); + } + }; + } // stack + + namespace detail { + template <> + struct is_speshul : std::true_type {}; + template <> + struct is_speshul : std::true_type {}; + + template + stack_proxy get(types, index_value<0>, index_value, const T& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template 0)>> = meta::enabler> + stack_proxy get(types, index_value, index_value, const T& fr) { + return get(types(), index_value(), index_value::value>(), fr); + } + } + + template <> + struct tie_size : std::integral_constant {}; + + template + stack_proxy get(const function_result& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template + stack_proxy get(types t, const function_result& fr) { + return detail::get(t, index_value(), index_value<0>(), fr); + } + + template <> + struct tie_size : std::integral_constant {}; + + template + stack_proxy get(const protected_function_result& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template + stack_proxy get(types t, const protected_function_result& fr) { + return detail::get(t, index_value(), index_value<0>(), fr); + } +} // sol + +// end of sol/stack_proxy.hpp + +#include +#include + +namespace sol { + template + struct va_iterator : std::iterator, std::ptrdiff_t, std::conditional_t, std::conditional_t> { + typedef std::iterator, std::ptrdiff_t, std::conditional_t, std::conditional_t> base_t; + typedef typename base_t::reference reference; + typedef typename base_t::pointer pointer; + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::iterator_category iterator_category; + lua_State* L; + int index; + int stacktop; + stack_proxy sp; + + va_iterator() : L(nullptr), index((std::numeric_limits::max)()), stacktop((std::numeric_limits::max)()) {} + va_iterator(lua_State* L, int index, int stacktop) : L(L), index(index), stacktop(stacktop), sp(L, index) {} + + reference operator*() { + return stack_proxy(L, index); + } + + pointer operator->() { + sp = stack_proxy(L, index); + return &sp; + } + + va_iterator& operator++ () { + ++index; + return *this; + } + + va_iterator operator++ (int) { + auto r = *this; + this->operator ++(); + return r; + } + + va_iterator& operator-- () { + --index; + return *this; + } + + va_iterator operator-- (int) { + auto r = *this; + this->operator --(); + return r; + } + + va_iterator& operator+= (difference_type idx) { + index += static_cast(idx); + return *this; + } + + va_iterator& operator-= (difference_type idx) { + index -= static_cast(idx); + return *this; + } + + difference_type operator- (const va_iterator& r) const { + return index - r.index; + } + + va_iterator operator+ (difference_type idx) const { + va_iterator r = *this; + r += idx; + return r; + } + + reference operator[](difference_type idx) { + return stack_proxy(L, index + static_cast(idx)); + } + + bool operator==(const va_iterator& r) const { + if (stacktop == (std::numeric_limits::max)()) { + return r.index == r.stacktop; + } + else if (r.stacktop == (std::numeric_limits::max)()) { + return index == stacktop; + } + return index == r.index; + } + + bool operator != (const va_iterator& r) const { + return !(this->operator==(r)); + } + + bool operator < (const va_iterator& r) const { + return index < r.index; + } + + bool operator > (const va_iterator& r) const { + return index > r.index; + } + + bool operator <= (const va_iterator& r) const { + return index <= r.index; + } + + bool operator >= (const va_iterator& r) const { + return index >= r.index; + } + }; + + template + inline va_iterator operator+(typename va_iterator::difference_type n, const va_iterator& r) { + return r + n; + } + + struct variadic_args { + private: + lua_State* L; + int index; + int stacktop; + + public: + typedef stack_proxy reference_type; + typedef stack_proxy value_type; + typedef stack_proxy* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef va_iterator iterator; + typedef va_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + variadic_args() = default; + variadic_args(lua_State* L, int index = -1) : L(L), index(lua_absindex(L, index)), stacktop(lua_gettop(L)) {} + variadic_args(const variadic_args&) = default; + variadic_args& operator=(const variadic_args&) = default; + variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + } + variadic_args& operator=(variadic_args&& o) { + L = o.L; + index = o.index; + stacktop = o.stacktop; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + return *this; + } + + iterator begin() { return iterator(L, index, stacktop + 1); } + iterator end() { return iterator(L, stacktop + 1, stacktop + 1); } + const_iterator begin() const { return const_iterator(L, index, stacktop + 1); } + const_iterator end() const { return const_iterator(L, stacktop + 1, stacktop + 1); } + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + reverse_iterator rbegin() { return std::reverse_iterator(begin()); } + reverse_iterator rend() { return std::reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return std::reverse_iterator(begin()); } + const_reverse_iterator rend() const { return std::reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return std::reverse_iterator(cbegin()); } + const_reverse_iterator crend() const { return std::reverse_iterator(cend()); } + + int push() const { + int pushcount = 0; + for (int i = index; i <= stacktop; ++i) { + lua_pushvalue(L, i); + pushcount += 1; + } + return pushcount; + } + + template + decltype(auto) get(difference_type start = 0) const { + return stack::get(L, index + static_cast(start)); + } + + stack_proxy operator[](difference_type start) const { + return stack_proxy(L, index + static_cast(start)); + } + + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + int leftover_count() const { return stacktop - (index - 1); } + int top() const { return stacktop; } + }; + + namespace stack { + template <> + struct getter { + static variadic_args get(lua_State* L, int index, record& tracking) { + tracking.last = 0; + return variadic_args(L, index); + } + }; + + template <> + struct pusher { + static int push(lua_State*, const variadic_args& ref) { + return ref.push(); + } + }; + } // stack +} // sol + +// end of sol/variadic_args.hpp + +namespace sol { + + template ::value, typename T> + R make_reference(lua_State* L, T&& value) { + int backpedal = stack::push(L, std::forward(value)); + R r = stack::get(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template ::value, typename... Args> + R make_reference(lua_State* L, Args&&... args) { + int backpedal = stack::push(L, std::forward(args)...); + R r = stack::get(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template + class basic_object : public base_t { + private: + template + decltype(auto) as_stack(std::true_type) const { + return stack::get(base_t::lua_state(), base_t::stack_index()); + } + + template + decltype(auto) as_stack(std::false_type) const { + base_t::push(); + return stack::pop(base_t::lua_state()); + } + + template + bool is_stack(std::true_type) const { + return stack::check(base_t::lua_state(), base_t::stack_index(), no_panic); + } + + template + bool is_stack(std::false_type) const { + auto pp = stack::push_pop(*this); + return stack::check(base_t::lua_state(), -1, no_panic); + } + + template + basic_object(std::integral_constant, lua_State* L, int index = -1) noexcept : base_t(L, index) { + if (invert_and_pop) { + lua_pop(L, -index); + } + } + + public: + basic_object() noexcept = default; + template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_object(T&& r) : base_t(std::forward(r)) {} + basic_object(nil_t r) : base_t(r) {} + basic_object(const basic_object&) = default; + basic_object(basic_object&&) = default; + basic_object& operator=(const basic_object&) = default; + basic_object& operator=(basic_object&&) = default; + basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } + basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } + basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} + basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} + template + basic_object(const proxy_base& r) noexcept : basic_object(r.operator basic_object()) {} + template + basic_object(proxy_base&& r) noexcept : basic_object(r.operator basic_object()) {} + template + basic_object& operator=(const proxy_base& r) { this->operator=(r.operator basic_object()); return *this; } + template + basic_object& operator=(proxy_base&& r) { this->operator=(r.operator basic_object()); return *this; } + basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} + template + basic_object(lua_State* L, in_place_type_t, Args&&... args) noexcept : basic_object(std::integral_constant::value>(), L, -stack::push(L, std::forward(args)...)) {} + template + basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place, std::forward(arg), std::forward(args)...) {} + + template + decltype(auto) as() const { + return as_stack(std::is_same()); + } + + template + bool is() const { + if (!base_t::valid()) + return false; + return is_stack(std::is_same()); + } + }; + + template + object make_object(lua_State* L, T&& value) { + return make_reference(L, std::forward(value)); + } + + template + object make_object(lua_State* L, Args&&... args) { + return make_reference(L, std::forward(args)...); + } + + inline bool operator==(const object& lhs, const nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const nil_t&, const object& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const object& lhs, const nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const nil_t&, const object& rhs) { + return rhs.valid(); + } +} // sol + +// end of sol/object.hpp + +namespace sol { + template + struct proxy : public proxy_base> { + private: + typedef meta::condition, Key, std::tuple>, Key&, meta::unqualified_t>>> key_type; + + template + decltype(auto) tuple_get(std::index_sequence) const { + return tbl.template traverse_get(std::get(key)...); + } + + template + void tuple_set(std::index_sequence, T&& value) { + tbl.traverse_set(std::get(key)..., std::forward(value)); + } + + public: + Table tbl; + key_type key; + + template + proxy(Table table, T&& key) : tbl(table), key(std::forward(key)) {} + + template + proxy& set(T&& item) { + tuple_set(std::make_index_sequence>::value>(), std::forward(item)); + return *this; + } + + template + proxy& set_function(Args&&... args) { + tbl.set_function(key, std::forward(args)...); + return *this; + } + + template>>, meta::is_callable>> = meta::enabler> + proxy& operator=(U&& other) { + return set_function(std::forward(other)); + } + + template>>, meta::is_callable>> = meta::enabler> + proxy& operator=(U&& other) { + return set(std::forward(other)); + } + + template + decltype(auto) get() const { + return tuple_get(std::make_index_sequence>::value>()); + } + + template + decltype(auto) get_or(T&& otherwise) const { + typedef decltype(get()) U; + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) operator[](K&& k) const { + auto keys = meta::tuplefy(key, std::forward(k)); + return proxy(tbl, std::move(keys)); + } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + bool valid() const { + stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); + lua_pop(tbl.lua_state(), p.levels); + return p; + } + }; + + template + inline bool operator==(T&& left, const proxy& right) { + return left == right.template get>(); + } + + template + inline bool operator==(const proxy& right, T&& left) { + return right.template get>() == left; + } + + template + inline bool operator!=(T&& left, const proxy& right) { + return right.template get>() != left; + } + + template + inline bool operator!=(const proxy& right, T&& left) { + return right.template get>() != left; + } + + template + inline bool operator==(nil_t, const proxy& right) { + return !right.valid(); + } + + template + inline bool operator==(const proxy& right, nil_t) { + return !right.valid(); + } + + template + inline bool operator!=(nil_t, const proxy& right) { + return right.valid(); + } + + template + inline bool operator!=(const proxy& right, nil_t) { + return right.valid(); + } + + namespace stack { + template + struct pusher> { + static int push(lua_State*, const proxy& p) { + sol::reference r = p; + return r.push(); + } + }; + } // stack +} // sol + +// end of sol/proxy.hpp + +// beginning of sol/usertype.hpp + +// beginning of sol/usertype_metatable.hpp + +// beginning of sol/deprecate.hpp + +#ifndef SOL_DEPRECATED + #ifdef _MSC_VER + #define SOL_DEPRECATED __declspec(deprecated) + #elif __GNUC__ + #define SOL_DEPRECATED __attribute__((deprecated)) + #else + #define SOL_DEPRECATED [[deprecated]] + #endif // compilers +#endif // SOL_DEPRECATED + +namespace sol { + namespace detail { + template + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; + } // detail +} // sol + +// end of sol/deprecate.hpp + +#include +#include + +namespace sol { + namespace usertype_detail { + struct no_comp { + template + bool operator()(A&&, B&&) const { + return false; + } + }; + + typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); + typedef int(*member_search)(lua_State*, void*); + + struct find_call_pair { + member_search first; + member_search second; + + find_call_pair(member_search first, member_search second) : first(first), second(second) {} + }; + + inline bool is_indexer(string_detail::string_shim s) { + return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); + } + + inline bool is_indexer(meta_function mf) { + return mf == meta_function::index || mf == meta_function::new_index; + } + + inline bool is_indexer(call_construction) { + return false; + } + + inline bool is_indexer(base_classes_tag) { + return false; + } + + inline auto make_shim(string_detail::string_shim s) { + return s; + } + + inline auto make_shim(call_construction) { + return string_detail::string_shim(name_of(meta_function::call_function)); + } + + inline auto make_shim(meta_function mf) { + return string_detail::string_shim(name_of(mf)); + } + + inline auto make_shim(base_classes_tag) { + return string_detail::string_shim(detail::base_class_cast_key()); + } + + template + inline std::string make_string(Arg&& arg) { + string_detail::string_shim s = make_shim(arg); + return std::string(s.c_str(), s.size()); + } + + template + inline luaL_Reg make_reg(N&& n, lua_CFunction f) { + luaL_Reg l{ make_shim(std::forward(n)).c_str(), f }; + return l; + } + + struct registrar { + virtual int push_um(lua_State* L) = 0; + virtual ~registrar() {} + }; + + template + inline int indexing_fail(lua_State* L) { + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + if (is_index) + return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + else + return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + } + + template + static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { + if (found) + return; + const char* metakey = &usertype_traits::metatable[0]; + const char* gcmetakey = &usertype_traits::gc_table[0]; + const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); + + luaL_getmetatable(L, metakey); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return; + } + + stack::get_field(L, basewalkkey); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 2); + return; + } + lua_CFunction basewalkfunc = stack::pop(L); + lua_pop(L, 1); + + stack::get_field(L, gcmetakey); + int value = basewalkfunc(L); + if (value > -1) { + found = true; + ret = value; + } + } + + template + static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { + (void)L; + (void)found; + (void)ret; + (void)accessor; + (void)detail::swallow{ 0, (walk_single_base(L, found, ret, accessor), 0)... }; + } + + template + inline int operator_wrap(lua_State* L) { + auto maybel = stack::check_get(L, 1); + if (maybel) { + auto mayber = stack::check_get(L, 2); + if (mayber) { + auto& l = *maybel; + auto& r = *mayber; + if (std::is_same::value) { + return stack::push(L, detail::ptr(l) == detail::ptr(r)); + } + else { + Op op; + return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); + } + } + } + return stack::push(L, false); + } + + template = meta::enabler> + inline void make_reg_op(Regs& l, int& index, const char* name) { + l[index] = { name, &operator_wrap }; + ++index; + } + + template = meta::enabler> + inline void make_reg_op(Regs&, int&, const char*) { + // Do nothing if there's no support + } + + struct add_destructor_tag {}; + struct check_destructor_tag {}; + struct verified_tag {} const verified{}; + + template + struct is_constructor : std::false_type {}; + + template + struct is_constructor> : std::true_type {}; + + template + struct is_constructor> : std::true_type {}; + + template + struct is_constructor> : std::true_type {}; + + template <> + struct is_constructor : std::true_type {}; + + template + using has_constructor = meta::any>...>; + + template + struct is_destructor : std::false_type {}; + + template + struct is_destructor> : std::true_type {}; + + template + using has_destructor = meta::any>...>; + + } // usertype_detail + + template + struct clean_type { + typedef std::conditional_t>::value, T&, std::decay_t> type; + }; + + template + using clean_type_t = typename clean_type::type; + + template + struct usertype_metatable : usertype_detail::registrar {}; + + template + struct usertype_metatable, Tn...> : usertype_detail::registrar { + typedef std::make_index_sequence indices; + typedef std::index_sequence half_indices; + typedef std::array regs_t; + typedef std::tuple RawTuple; + typedef std::tuple ...> Tuple; + template + struct check_binding : is_variable_binding> {}; + typedef std::unordered_map mapping_t; + Tuple functions; + mapping_t mapping; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + lua_CFunction destructfunc; + lua_CFunction callconstructfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool mustindex; + bool secondarymeta; + bool hasequals; + bool hasless; + bool haslessequals; + + template >> = meta::enabler> + inline lua_CFunction make_func() { + return std::get(functions); + } + + template >> = meta::enabler> + inline lua_CFunction make_func() { + return call; + } + + static bool contains_variable() { + typedef meta::any...> has_variables; + return has_variables::value; + } + + bool contains_index() const { + bool idx = false; + (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get(functions))), 0) ... }; + return idx; + } + + int finish_regs(regs_t& l, int& index) { + if (!hasless) { + const char* name = name_of(meta_function::less_than).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less>(l, index, name); + } + if (!haslessequals) { + const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less_equal>(l, index, name); + } + if (!hasequals) { + const char* name = name_of(meta_function::equal_to).c_str(); + usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); + } + if (destructfunc != nullptr) { + l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; + ++index; + } + return index; + } + + template + void make_regs(regs_t&, int&, call_construction, F&&) { + callconstructfunc = call; + secondarymeta = true; + } + + template + void make_regs(regs_t&, int&, base_classes_tag, bases) { + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::value = true), 0)... }; + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + + template , base_classes_tag, call_construction>::value>> + void make_regs(regs_t& l, int& index, N&& n, F&&) { + if (is_variable_binding>::value) { + return; + } + luaL_Reg reg = usertype_detail::make_reg(std::forward(n), make_func()); + // Returnable scope + // That would be a neat keyword for C++ + // returnable { ... }; + if (reg.name == name_of(meta_function::equal_to)) { + hasequals = true; + } + if (reg.name == name_of(meta_function::less_than)) { + hasless = true; + } + if (reg.name == name_of(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + if (reg.name == name_of(meta_function::garbage_collect)) { + destructfunc = reg.func; + return; + } + else if (reg.name == name_of(meta_function::index)) { + indexfunc = reg.func; + mustindex = true; + return; + } + else if (reg.name == name_of(meta_function::new_index)) { + newindexfunc = reg.func; + mustindex = true; + return; + } + l[index] = reg; + ++index; + } + + template > + usertype_metatable(Args&&... args) : functions(std::forward(args)...), + mapping(), + indexfunc(usertype_detail::indexing_fail), newindexfunc(usertype_detail::indexing_fail), + destructfunc(nullptr), callconstructfunc(nullptr), + indexbase(&core_indexing_call), newindexbase(&core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()), + hasequals(false), hasless(false), haslessequals(false) { + std::initializer_list ilist{ { + std::pair( + usertype_detail::make_string(std::get(functions)), + usertype_detail::find_call_pair(&usertype_metatable::real_find_call, + &usertype_metatable::real_find_call) + ) + }... }; + mapping.insert(ilist); + } + + template + static int real_find_call(lua_State* L, void* um) { + auto& f = *static_cast(um); + if (is_variable_binding(f.functions))>::value) { + return real_call_with(L, f); + } + return stack::push(L, c_closure(call, stack::push(L, light(f)))); + } + + template + static int core_indexing_call(lua_State* L) { + usertype_metatable& f = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + static const int keyidx = -2 + static_cast(is_index); + if (toplevel && stack::get(L, keyidx) != type::string) { + return is_index ? f.indexfunc(L) : f.newindexfunc(L); + } + std::string name = stack::get(L, keyidx); + auto memberit = f.mapping.find(name); + if (memberit != f.mapping.cend()) { + auto& member = is_index ? memberit->second.second : memberit->second.first; + return (member)(L, static_cast(&f)); + } + string_detail::string_shim accessor = name; + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) + f.indexbaseclasspropogation(L, found, ret, accessor); + else + f.newindexbaseclasspropogation(L, found, ret, accessor); + if (found) { + return ret; + } + return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; + } + + static int real_index_call(lua_State* L) { + return core_indexing_call(L); + } + + static int real_new_index_call(lua_State* L) { + return core_indexing_call(L); + } + + template + static int real_call(lua_State* L) { + usertype_metatable& f = stack::get>(L, upvalue_index(1)); + return real_call_with(L, f); + } + + template + static int real_call_with(lua_State* L, usertype_metatable& um) { + auto& f = std::get(um.functions); + return call_detail::call_wrapped(L, f); + } + + template + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + template + static int call_with(lua_State* L) { + return detail::static_trampoline<(&real_call_with)>(L); + } + + static int index_call(lua_State* L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State* L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + + virtual int push_um(lua_State* L) override { + return stack::push(L, std::move(*this)); + } + + ~usertype_metatable() override { + + } + }; + + namespace stack { + + template + struct pusher, Args...>> { + typedef usertype_metatable, Args...> umt_t; + typedef typename umt_t::regs_t regs_t; + + static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { + // ensure some sort of uniqueness + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable; + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table[0]; + // Make sure userdata's memory is properly in lua first, + // otherwise all the light userdata we make later will become invalid + stack::push>(L, metatable_key, uniquegcmetakey, std::move(umx)); + // Create the top level thing that will act as our deleter later on + stack_reference umt(L, -1); + stack::set_field(L, gcmetakey, umt); + umt.pop(); + + stack::get_field(L, gcmetakey); + return stack::pop>(L); + } + + static int push(lua_State* L, umt_t&& umx) { + + umt_t& um = make_cleanup(L, std::move(umx)); + regs_t value_table{ {} }; + int lastreg = 0; + (void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... }; + um.finish_regs(value_table, lastreg); + value_table[lastreg] = { nullptr, nullptr }; + regs_t ref_table = value_table; + regs_t unique_table = value_table; + bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; + if (hasdestructor) { + ref_table[lastreg - 1] = { nullptr, nullptr }; + unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct }; + } + + // Now use um + const bool& mustindex = um.mustindex; + for (std::size_t i = 0; i < 3; ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + luaL_Reg* metaregs = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable[0]; + metaregs = ref_table.data(); + break; + case 1: + metakey = &usertype_traits>::metatable[0]; + metaregs = unique_table.data(); + break; + case 2: + default: + metakey = &usertype_traits::metatable[0]; + metaregs = value_table.data(); + break; + } + luaL_newmetatable(L, metakey); + stack_reference t(L, -1); + stack::push(L, make_light(um)); + luaL_setfuncs(L, metaregs, 1); + + if (um.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); + } + if (um.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); + } + + stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um)), t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um)), t.stack_index()); + + if (mustindex) { + // Basic index pushing: specialize + // index and newindex to give variables and stuff + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), t.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), t.stack_index()); + } + else { + // If there's only functions, we can use the fast index version + stack::set_field(L, meta_function::index, t, t.stack_index()); + } + // metatable on the metatable + // for call constructor purposes and such + lua_createtable(L, 0, 1); + stack_reference metabehind(L, -1); + if (um.callconstructfunc != nullptr) { + stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); + } + if (um.secondarymeta) { + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); + } + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + // We want to just leave the table + // in the registry only, otherwise we return it + if (i < 2) { + t.pop(); + } + } + + return 1; + } + }; + + } // stack + +} // sol + +// end of sol/usertype_metatable.hpp + +// beginning of sol/simple_usertype_metatable.hpp + +namespace sol { + + namespace usertype_detail { + struct variable_wrapper { + virtual int index(lua_State* L) = 0; + virtual int new_index(lua_State* L) = 0; + virtual ~variable_wrapper() {}; + }; + + template + struct callable_binding : variable_wrapper { + F fx; + + template + callable_binding(Arg&& arg) : fx(std::forward(arg)) {} + + virtual int index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + + virtual int new_index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + }; + + typedef std::unordered_map> variable_map; + typedef std::unordered_map function_map; + + struct simple_map { + const char* metakey; + variable_map variables; + function_map functions; + base_walk indexbaseclasspropogation; + base_walk newindexbaseclasspropogation; + + simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} + }; + + template + inline int simple_metatable_newindex(lua_State* L) { + if (stack::stack_detail::check_metatable(L, 1)) { + stack::set_field(L, stack_reference(L, 2), stack_reference(L, 3), 1); + lua_settop(L, 0); + return 0; + } + lua_pop(L, 1); + return indexing_fail(L); + } + + template + inline int simple_core_indexing_call(lua_State* L) { + simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + variable_map& variables = sm.variables; + function_map& functions = sm.functions; + static const int keyidx = -2 + static_cast(is_index); + if (toplevel) { + if (stack::get(L, keyidx) != type::string) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + } + string_detail::string_shim accessor = stack::get(L, keyidx); + std::string accessorkey = accessor.c_str(); + auto vit = variables.find(accessorkey); + if (vit != variables.cend()) { + auto& varwrap = *(vit->second); + if (is_index) { + return varwrap.index(L); + } + return varwrap.new_index(L); + } + auto fit = functions.find(accessorkey); + if (fit != functions.cend()) { + auto& func = (fit->second); + return stack::push(L, func); + } + // Check table storage first for a method that works + luaL_getmetatable(L, sm.metakey); + if (type_of(L, -1) != type::nil) { + stack::get_field(L, accessor.c_str(), lua_gettop(L)); + if (type_of(L, -1) != type::nil) { + // Woo, we found it? + lua_remove(L, -2); + return 1; + } + lua_pop(L, 1); + } + lua_pop(L, 1); + + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) { + sm.indexbaseclasspropogation(L, found, ret, accessor); + } + else { + sm.newindexbaseclasspropogation(L, found, ret, accessor); + } + if (found) { + return ret; + } + if (toplevel) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + return -1; + } + + inline int simple_real_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + inline int simple_real_new_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + inline int simple_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_index_call)>(L); + } + + inline int simple_new_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_new_index_call)>(L); + } + } + + struct simple_tag {} const simple{}; + + template + struct simple_usertype_metatable : usertype_detail::registrar { + public: + usertype_detail::function_map registrations; + usertype_detail::variable_map varmap; + object callconstructfunc; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool mustindex; + bool secondarymeta; + + template + void insert(N&& n, object&& o) { + std::string key = usertype_detail::make_string(std::forward(n)); + auto hint = registrations.find(key); + if (hint == registrations.cend()) { + registrations.emplace_hint(hint, std::move(key), std::move(o)); + return; + } + hint->second = std::move(o); + } + + template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + insert(std::forward(n), make_object(L, as_function_reference(std::forward(f)))); + } + + template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + object o = make_object(L, std::forward(f)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template >> = meta::enabler> + void add(lua_State* L, N&& n, F&& f) { + add_function(L, std::forward(n), std::forward(f)); + } + + template >> = meta::enabler> + void add(lua_State*, N&& n, F&& f) { + mustindex = true; + secondarymeta = true; + std::string key = usertype_detail::make_string(std::forward(n)); + auto o = std::make_unique>>(std::forward(f)); + auto hint = varmap.find(key); + if (hint == varmap.cend()) { + varmap.emplace_hint(hint, std::move(key), std::move(o)); + return; + } + hint->second = std::move(o); + } + + template + void add(lua_State* L, N&& n, constructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, constructor_list c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, destructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, destructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State*, base_classes_tag, bases) { + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform"); + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::value = true), 0)... }; + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + + private: + template + simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) + : callconstructfunc(nil), + indexfunc(&usertype_detail::indexing_fail), newindexfunc(&usertype_detail::simple_metatable_newindex), + indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + mustindex(true), secondarymeta(true) { + (void)detail::swallow{ 0, + (add(L, detail::forward_get(args), detail::forward_get(args)),0)... + }; + } + + template + simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence(), L, std::forward_as_tuple(std::forward(args)...)) {} + + template + simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward(args)..., "__gc", default_destructor) {} + + template + simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition, meta::neg>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward(args)...) {} + + public: + simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(L, meta::condition>, decltype(default_constructor), usertype_detail::check_destructor_tag>()) {} + + template, + usertype_detail::verified_tag, + usertype_detail::add_destructor_tag, + usertype_detail::check_destructor_tag + >, + meta::is_specialization_of>, + meta::is_specialization_of> + > = meta::enabler> + simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition, meta::neg>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward(arg), std::forward(args)...) {} + + template + simple_usertype_metatable(lua_State* L, constructors constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + simple_usertype_metatable(lua_State* L, constructor_wrapper constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + virtual int push_um(lua_State* L) override { + return stack::push(L, std::move(*this)); + } + }; + + namespace stack { + template + struct pusher> { + typedef simple_usertype_metatable umt_t; + + static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable; + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table[0]; + stack::push>(L, metatable_key, uniquegcmetakey, &usertype_traits::metatable[0], umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, std::move(umx.varmap), std::move(umx.registrations)); + stack_reference stackvarmap(L, -1); + stack::set_field(L, gcmetakey, stackvarmap); + stackvarmap.pop(); + + stack::get_field(L, gcmetakey); + usertype_detail::simple_map& varmap = stack::pop>(L); + return varmap; + } + + static int push(lua_State* L, umt_t&& umx) { + auto& varmap = make_cleanup(L, umx); + bool hasequals = false; + bool hasless = false; + bool haslessequals = false; + for (std::size_t i = 0; i < 3; ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable[0]; + break; + case 1: + metakey = &usertype_traits>::metatable[0]; + break; + case 2: + default: + metakey = &usertype_traits::metatable[0]; + break; + } + luaL_newmetatable(L, metakey); + stack_reference t(L, -1); + for (auto& kvp : varmap.functions) { + auto& first = std::get<0>(kvp); + auto& second = std::get<1>(kvp); + if (first == name_of(meta_function::equal_to)) { + hasequals = true; + } + else if (first == name_of(meta_function::less_than)) { + hasless = true; + } + else if (first == name_of(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + else if (first == name_of(meta_function::index)) { + umx.indexfunc = second.template as(); + } + else if (first == name_of(meta_function::new_index)) { + umx.newindexfunc = second.template as(); + } + switch (i) { + case 0: + if (first == name_of(meta_function::garbage_collect)) { + continue; + } + break; + case 1: + if (first == name_of(meta_function::garbage_collect)) { + stack::set_field(L, first, detail::unique_destruct, t.stack_index()); + continue; + } + break; + case 2: + default: + break; + } + stack::set_field(L, first, second, t.stack_index()); + } + luaL_Reg opregs[4]{}; + int opregsindex = 0; + if (!hasless) { + const char* name = name_of(meta_function::less_than).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less>(opregs, opregsindex, name); + } + if (!haslessequals) { + const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less_equal>(opregs, opregsindex, name); + } + if (!hasequals) { + const char* name = name_of(meta_function::equal_to).c_str(); + usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); + } + t.push(); + luaL_setfuncs(L, opregs, 0); + t.pop(); + + if (umx.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); + } + if (umx.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); + } + + // Base class propagation features + stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); + + if (umx.mustindex) { + // use indexing function + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report."); + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), t.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), t.stack_index()); + } + else { + // Metatable indexes itself + stack::set_field(L, meta_function::index, t, t.stack_index()); + } + // metatable on the metatable + // for call constructor purposes and such + lua_createtable(L, 0, 1); + stack_reference metabehind(L, -1); + if (umx.callconstructfunc.valid()) { + stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); + } + if (umx.secondarymeta) { + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), metabehind.stack_index()); + } + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + + if (i < 2) + t.pop(); + } + return 1; + } + }; + } // stack +} // sol + +// end of sol/simple_usertype_metatable.hpp + +// beginning of sol/container_usertype_metatable.hpp + +namespace sol { + + namespace detail { + + template + struct has_find { + private: + typedef std::array one; + typedef std::array two; + + template static one test(decltype(&C::find)); + template static two test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + T& get_first(const T& t) { + return std::forward(t); + } + + template + decltype(auto) get_first(const std::pair& t) { + return t.first; + } + + template >> = meta::enabler> + auto find(C& c, I&& i) { + return c.find(std::forward(i)); + } + + template >> = meta::enabler> + auto find(C& c, I&& i) { + using std::begin; + using std::end; + return std::find_if(begin(c), end(c), [&i](auto&& x) { + return i == get_first(x); + }); + } + + } + + template + struct container_usertype_metatable { + typedef meta::unqualified_t T; + typedef std::size_t K; + typedef typename T::value_type V; + typedef typename T::iterator I; + typedef std::remove_reference_t())> IR; + + struct iter { + T& source; + I it; + + iter(T& source, I it) : source(source), it(std::move(it)) {} + }; + + static auto& get_src(lua_State* L) { +#ifdef SOL_SAFE_USERTYPE + auto p = stack::get(L, 1); + if (p == nullptr) { + luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument or call on proper type)"); + } + return *p; +#else + return stack::get(L, 1); +#endif + } + + static int real_index_call(lua_State* L) { + auto& src = get_src(L); +#ifdef SOL_SAFE_USERTYPE + auto maybek = stack::check_get(L, 2); + if (maybek) { + using std::begin; + auto it = begin(src); + K k = *maybek; + if (k <= src.size() && k > 0) { + --k; + std::advance(it, k); + return stack::push_reference(L, *it); + } + } + return stack::push(L, nil); +#else + using std::begin; + auto it = begin(src); + K k = stack::get(L, 2); + --k; + std::advance(it, k); + return stack::push_reference(L, *it); +#endif // Safety + } + + template > = meta::enabler> + static int real_new_index_call_const(std::integral_constant, lua_State* L) { + luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); + return 0; + } + + template > = meta::enabler> + static int real_new_index_call_const(std::integral_constant, lua_State* L) { + auto& src = get_src(L); +#ifdef SOL_SAFE_USERTYPE + auto maybek = stack::check_get(L, 2); + if (maybek) { + K k = *maybek; + if (k <= src.size() && k > 0) { + --k; + using std::begin; + auto it = begin(src); + std::advance(it, k); + *it = stack::get(L, 3); + } + } +#else + using std::begin; + auto it = begin(src); + K k = stack::get(L, 2); + --k; + std::advance(it, k); + *it = stack::get(L, 3); +#endif + return 0; + } + + static int real_new_index_call(lua_State* L) { + return real_new_index_call_const(meta::neg, std::is_const>>(), L); + } + + static int real_pairs_next_call(lua_State* L) { + using std::end; + iter& i = stack::get>(L, 1); + auto& source = i.source; + auto& it = i.it; + K k = stack::get(L, 2); + if (it == end(source)) { + return 0; + } + int p = stack::multi_push_reference(L, k + 1, *it); + std::advance(it, 1); + return p; + } + + static int real_pairs_call(lua_State* L) { + auto& src = get_src(L); + using std::begin; + stack::push(L, pairs_next_call); + stack::push>(L, src, begin(src)); + stack::push(L, 0); + return 3; + } + + static int real_length_call(lua_State*L) { + auto& src = get_src(L); + return stack::push(L, src.size()); + } + +#if 0 + static int real_push_back_call(lua_State*L) { + auto& src = get_src(L); + src.push_back(stack::get(L, 2)); + return 0; + } + + static int real_insert_call(lua_State*L) { + using std::begin; + auto& src = get_src(L); + src.insert(std::next(begin(src), stack::get(L, 2)), stack::get(L, 3)); + return 0; + } + + static int push_back_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int insert_call(lua_State*L) { + return detail::static_trampoline<(&real_insert_call)>(L); + } +#endif // Sometime later, in a distant universe... + + static int length_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int pairs_next_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_next_call)>(L); + } + + static int pairs_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_call)>(L); + } + + static int index_call(lua_State*L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State*L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + }; + + template + struct container_usertype_metatable>::value>> { + typedef meta::unqualified_t T; + typedef typename T::value_type KV; + typedef typename KV::first_type K; + typedef typename KV::second_type V; + typedef typename T::iterator I; + struct iter { + T& source; + I it; + + iter(T& source, I it) : source(source), it(std::move(it)) {} + }; + + static auto& get_src(lua_State* L) { +#ifdef SOL_SAFE_USERTYPE + auto p = stack::get(L, 1); + if (p == nullptr) { + luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument or call on proper type)"); + } + return *p; +#else + return stack::get(L, 1); +#endif + } + + static int real_index_call(lua_State* L) { + auto& src = get_src(L); + auto k = stack::check_get(L, 2); + if (k) { + using std::end; + auto it = detail::find(src, *k); + if (it != end(src)) { + auto& v = *it; + return stack::push_reference(L, v.second); + } + } + return stack::push(L, nil); + } + + static int real_new_index_call_const(std::false_type, lua_State* L) { + luaL_error(L, "sol: cannot write to a const value type"); + return 0; + } + + static int real_new_index_call_const(std::true_type, lua_State* L) { + auto& src = get_src(L); + auto k = stack::check_get(L, 2); + if (k) { + using std::end; + auto it = detail::find(src, *k); + if (it != end(src)) { + auto& v = *it; + v.second = stack::get(L, 3); + } + else { + src.insert(it, { std::move(*k), stack::get(L, 3) }); + } + } + return 0; + } + + static int real_new_index_call(lua_State* L) { + return real_new_index_call_const(meta::neg>(), L); + } + + static int real_pairs_next_call(lua_State* L) { + using std::end; + iter& i = stack::get>(L, 1); + auto& source = i.source; + auto& it = i.it; + std::advance(it, 1); + if (it == end(source)) { + return 0; + } + return stack::multi_push_reference(L, it->first, it->second); + } + + static int real_pairs_call(lua_State* L) { + auto& src = get_src(L); + using std::begin; + stack::push(L, pairs_next_call); + stack::push>(L, src, begin(src)); + stack::push(L, 1); + return 3; + } + + static int real_length_call(lua_State*L) { + auto& src = get_src(L); + return stack::push(L, src.size()); + } + + static int length_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int pairs_next_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_next_call)>(L); + } + + static int pairs_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_call)>(L); + } + + static int index_call(lua_State*L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State*L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + }; + + namespace stack { + + template + struct pusher, meta::neg, std::is_base_of>>>::value>> { + typedef container_usertype_metatable cumt; + static int push(lua_State* L, const T& cont) { + auto fx = [&L]() { + const char* metakey = &usertype_traits::metatable[0]; + if (luaL_newmetatable(L, metakey) == 1) { + luaL_Reg reg[] = { + { "__index", &cumt::index_call }, + { "__newindex", &cumt::new_index_call }, + { "__pairs", &cumt::pairs_call }, + { "__len", &cumt::length_call }, + { "__gc", &detail::usertype_alloc_destroy }, + { nullptr, nullptr } + }; + luaL_setfuncs(L, reg, 0); + } + lua_setmetatable(L, -2); + }; + return pusher>{}.push_fx(L, fx, cont); + } + + static int push(lua_State* L, T&& cont) { + auto fx = [&L]() { + const char* metakey = &usertype_traits::metatable[0]; + if (luaL_newmetatable(L, metakey) == 1) { + luaL_Reg reg[] = { + { "__index", &cumt::index_call }, + { "__newindex", &cumt::new_index_call }, + { "__pairs", &cumt::pairs_call }, + { "__len", &cumt::length_call }, + { "__gc", &detail::usertype_alloc_destroy }, + { nullptr, nullptr } + }; + luaL_setfuncs(L, reg, 0); + } + lua_setmetatable(L, -2); + }; + return pusher>{}.push_fx(L, fx, std::move(cont)); + } + }; + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + typedef container_usertype_metatable cumt; + static int push(lua_State* L, T* cont) { + auto fx = [&L]() { + const char* metakey = &usertype_traits*>::metatable[0]; + if (luaL_newmetatable(L, metakey) == 1) { + luaL_Reg reg[] = { + { "__index", &cumt::index_call }, + { "__newindex", &cumt::new_index_call }, + { "__pairs", &cumt::pairs_call }, + { "__len", &cumt::length_call }, + { nullptr, nullptr } + }; + luaL_setfuncs(L, reg, 0); + } + lua_setmetatable(L, -2); + }; + return pusher>{}.push_fx(L, fx, cont); + } + }; + } // stack + +} // sol + +// end of sol/container_usertype_metatable.hpp + +namespace sol { + + template + class usertype { + private: + std::unique_ptr metatableregister; + + template + usertype(usertype_detail::verified_tag, Args&&... args) : metatableregister(detail::make_unique_deleter, Args...>, detail::deleter>(std::forward(args)...)) {} + + template + usertype(usertype_detail::add_destructor_tag, Args&&... args) : usertype(usertype_detail::verified, std::forward(args)..., "__gc", default_destructor) {} + + template + usertype(usertype_detail::check_destructor_tag, Args&&... args) : usertype(meta::condition, meta::neg>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward(args)...) {} + + public: + + template + usertype(Args&&... args) : usertype(meta::condition, meta::neg>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward(args)...) {} + + template + usertype(constructors constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + usertype(constructor_wrapper constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter, detail::deleter>(L, std::forward(args)...)) {} + + usertype_detail::registrar* registrar_data() { + return metatableregister.get(); + } + + int push(lua_State* L) { + return metatableregister->push_um(L); + } + }; + + template + class simple_usertype : public usertype { + private: + typedef usertype base_t; + lua_State* state; + + public: + template + simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward(args)...), state(L) {} + + template + void set(N&& n, F&& f) { + auto meta = static_cast*>(base_t::registrar_data()); + meta->add(state, n, f); + } + }; + + namespace stack { + template + struct pusher> { + static int push(lua_State* L, usertype& user) { + return user.push(L); + } + }; + } // stack +} // sol + +// end of sol/usertype.hpp + +// beginning of sol/table_iterator.hpp + +namespace sol { + + template + class basic_table_iterator : public std::iterator> { + private: + typedef std::iterator> base_t; + public: + typedef object key_type; + typedef object mapped_type; + typedef base_t::value_type value_type; + typedef base_t::iterator_category iterator_category; + typedef base_t::difference_type difference_type; + typedef base_t::pointer pointer; + typedef base_t::reference reference; + typedef const value_type& const_reference; + + private: + std::pair kvp; + reference_type ref; + int tableidx = 0; + int keyidx = 0; + std::ptrdiff_t idx = 0; + + public: + + basic_table_iterator() : keyidx(-1), idx(-1) { + + } + + basic_table_iterator(reference_type x) : ref(std::move(x)) { + ref.push(); + tableidx = lua_gettop(ref.lua_state()); + stack::push(ref.lua_state(), nil); + this->operator++(); + if (idx == -1) { + return; + } + --idx; + } + + basic_table_iterator& operator++() { + if (idx == -1) + return *this; + + if (lua_next(ref.lua_state(), tableidx) == 0) { + idx = -1; + keyidx = -1; + return *this; + } + ++idx; + kvp.first = object(ref.lua_state(), -2); + kvp.second = object(ref.lua_state(), -1); + lua_pop(ref.lua_state(), 1); + // leave key on the stack + keyidx = lua_gettop(ref.lua_state()); + return *this; + } + + basic_table_iterator operator++(int) { + auto saved = *this; + this->operator++(); + return saved; + } + + reference operator*() { + return kvp; + } + + const_reference operator*() const { + return kvp; + } + + bool operator== (const basic_table_iterator& right) const { + return idx == right.idx; + } + + bool operator!= (const basic_table_iterator& right) const { + return idx != right.idx; + } + + ~basic_table_iterator() { + if (keyidx != -1) { + stack::remove(ref.lua_state(), keyidx, 1); + } + if (ref.valid()) { + stack::remove(ref.lua_state(), tableidx, 1); + } + } + }; + +} // sol + +// end of sol/table_iterator.hpp + +namespace sol { + namespace detail { + template + struct clean { lua_State* L; clean(lua_State* L) : L(L) {} ~clean() { lua_pop(L, static_cast(n)); } }; + struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* L, int& n) : L(L), n(n) {} ~ref_clean() { lua_pop(L, static_cast(n)); } }; + inline int fail_on_newindex(lua_State* L) { + return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); + } + } + + template + class basic_table_core : public base_t { + friend class state; + friend class state_view; + + template + using is_global = meta::all, meta::is_c_str...>; + + template + void for_each(std::true_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), nil); + while (lua_next(base_t::lua_state(), -2)) { + sol::object key(base_t::lua_state(), -2); + sol::object value(base_t::lua_state(), -1); + std::pair keyvalue(key, value); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(keyvalue); + } + } + + template + void for_each(std::false_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), nil); + while (lua_next(base_t::lua_state(), -2)) { + sol::object key(base_t::lua_state(), -2); + sol::object value(base_t::lua_state(), -1); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(key, value); + } + } + + template + auto tuple_get(types, std::index_sequence<0, 1, I...>, Keys&& keys) const + -> decltype(stack::pop>(nullptr)) { + typedef decltype(stack::pop>(nullptr)) Tup; + return Tup( + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get<0>(keys)), + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get<1>(keys)), + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get(keys))... + ); + } + + template + decltype(auto) tuple_get(types, std::index_sequence, Keys&& keys) const { + return traverse_get_optional(meta::is_specialization_of>(), detail::forward_get(keys)); + } + + template + void tuple_set(std::index_sequence, Pairs&& pairs) { + auto pp = stack::push_pop(pairs))...>::value)>(*this); + void(detail::swallow{ (stack::set_field(base_t::lua_state(), + detail::forward_get(pairs), + detail::forward_get(pairs), + lua_gettop(base_t::lua_state()) + ), 0)... }); + } + + template + decltype(auto) traverse_get_deep(Key&& key) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { + typedef decltype(stack::get(base_t::lua_state())) R; + auto p = stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return R(nullopt); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { + auto p = I > 0 ? stack::probe_get_field(base_t::lua_state(), std::forward(key), -1) : stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return T(nullopt); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { + detail::clean c(base_t::lua_state()); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { + int popcount = 0; + detail::ref_clean c(base_t::lua_state(), popcount); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + void traverse_set_deep(Key&& key, Value&& value) const { + stack::set_field(base_t::lua_state(), std::forward(key), std::forward(value)); + } + + template + void traverse_set_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + traverse_set_deep(std::forward(keys)...); + } + + basic_table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { } + + public: + typedef basic_table_iterator iterator; + typedef iterator const_iterator; + + basic_table_core() noexcept : base_t() { } + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_table_core(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_table>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_table_core(const basic_table_core&) = default; + basic_table_core(basic_table_core&&) = default; + basic_table_core& operator=(const basic_table_core&) = default; + basic_table_core& operator=(basic_table_core&&) = default; + basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {} + basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {} + basic_table_core(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + iterator begin() const { + return iterator(*this); + } + + iterator end() const { + return iterator(); + } + + const_iterator cbegin() const { + return begin(); + } + + const_iterator cend() const { + return end(); + } + + template + decltype(auto) get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + auto pp = stack::push_pop::value>(*this); + return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + typedef decltype(get("")) U; + sol::optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + sol::optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + auto pp = stack::push_pop::value>(*this); + return traverse_get_optional(meta::is_specialization_of>(), std::forward(keys)...); + } + + template + basic_table_core& traverse_set(Keys&&... keys) { + auto pp = stack::push_pop::value>(*this); + auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys)-2)); + traverse_set_deep(std::forward(keys)...); + return *this; + } + + template + basic_table_core& set(Args&&... args) { + tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); + return *this; + } + + template + basic_table_core& set_usertype(usertype& user) { + return set_usertype(usertype_traits::name, user); + } + + template + basic_table_core& set_usertype(Key&& key, usertype& user) { + return set(std::forward(key), user); + } + + template + basic_table_core& new_usertype(const std::string& name, Args&&... args) { + usertype utype(std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_usertype(const std::string& name, Args&&... args) { + constructors> ctor{}; + return new_usertype(name, ctor, std::forward(args)...); + } + + template + basic_table_core& new_usertype(const std::string& name, constructors ctor, Args&&... args) { + usertype utype(ctor, std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { + simple_usertype utype(base_t::lua_state(), std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { + constructors> ctor{}; + return new_simple_usertype(name, ctor, std::forward(args)...); + } + + template + basic_table_core& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args) { + simple_usertype utype(base_t::lua_state(), ctor, std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + simple_usertype utype(base_t::lua_state(), std::forward(args)...); + return utype; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + constructors> ctor{}; + return create_simple_usertype(ctor, std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(constructors ctor, Args&&... args) { + simple_usertype utype(base_t::lua_state(), ctor, std::forward(args)...); + return utype; + } + + template + basic_table_core& new_enum(const std::string& name, Args&&... args) { + if (read_only) { + table idx = create_with(std::forward(args)...); + table x = create_with( + meta_function::new_index, detail::fail_on_newindex, + meta_function::index, idx + ); + table target = create_named(name); + target[metatable_key] = x; + } + else { + create_named(name, std::forward(args)...); + } + return *this; + } + + template + void for_each(Fx&& fx) const { + typedef meta::is_invokable)> is_paired; + for_each(is_paired(), std::forward(fx)); + } + + size_t size() const { + auto pp = stack::push_pop(*this); + lua_len(base_t::lua_state(), -1); + return stack::pop(base_t::lua_state()); + } + + bool empty() const { + return cbegin() == cend(); + } + + template + proxy operator[](T&& key) & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) const & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) && { + return proxy(*this, std::forward(key)); + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& add(Args&&... args) { + auto pp = stack::push_pop(*this); + (void)detail::swallow{0, + (stack::set_ref(base_t::lua_state(), std::forward(args)), 0)... + }; + return *this; + } + + private: + template> + void set_fx(types, Key&& key, Fx&& fx) { + set_resolved_function(std::forward(key), std::forward(fx)); + } + + template>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward(key), std::forward(fx)); + } + + template>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward(key), as_function_reference(std::forward(fx), std::forward(args)...)); + } + + template + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward(key), as_function_reference>(std::forward(args)...)); + } + + public: + static inline table create(lua_State* L, int narr = 0, int nrec = 0) { + lua_createtable(L, narr, nrec); + table result(L); + lua_pop(L, 1); + return result; + } + + template + static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + lua_createtable(L, narr, nrec); + table result(L); + result.set(std::forward(key), std::forward(value), std::forward(args)...); + lua_pop(L, 1); + return result; + } + + template + static inline table create_with(lua_State* L, Args&&... args) { + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(L, narr, static_cast((sizeof...(Args) / 2) - narr), std::forward(args)...); + } + + table create(int narr = 0, int nrec = 0) { + return create(base_t::lua_state(), narr, nrec); + } + + template + table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create(Name&& name, int narr = 0, int nrec = 0) { + table x = create(base_t::lua_state(), narr, nrec); + this->set(std::forward(name), x); + return x; + } + + template + table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + table x = create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + this->set(std::forward(name), x); + return x; + } + + template + table create_with(Args&&... args) { + return create_with(base_t::lua_state(), std::forward(args)...); + } + + template + table create_named(Name&& name, Args&&... args) { + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(std::forward(name), narr, sizeof...(Args) / 2 - narr, std::forward(args)...); + } + }; +} // sol + +// end of sol/table_core.hpp + +namespace sol { + typedef table_core table; +} // sol + +// end of sol/table.hpp + +// beginning of sol/load_result.hpp + +namespace sol { + struct load_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + int popcount; + load_status err; + + template + decltype(auto) tagged_get(types>) const { + if (!valid()) { + return sol::optional(nullopt); + } + return stack::get>(L, index); + } + + template + decltype(auto) tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (!valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return stack::get(L, index); + } + + sol::optional tagged_get(types>) const { + if (valid()) { + return nullopt; + } + return sol::error(detail::direct_error, stack::get(L, index)); + } + + sol::error tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return sol::error(detail::direct_error, stack::get(L, index)); + } + + public: + load_result() = default; + load_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, load_status err = load_status::ok) noexcept : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { + + } + load_result(const load_result&) = default; + load_result& operator=(const load_result&) = default; + load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + } + load_result& operator=(load_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + return *this; + } + + load_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == load_status::ok; + } + + template + T get() const { + return tagged_get(types>()); + } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; + + ~load_result() { + stack::remove(L, index, popcount); + } + }; +} // sol + +// end of sol/load_result.hpp + +namespace sol { + enum class lib : char { + base, + package, + coroutine, + string, + os, + math, + table, + debug, + bit32, + io, + ffi, + jit, + utf8, + count + }; + + class state_view { + private: + lua_State* L; + table reg; + global_table global; + + optional is_loaded_package(const std::string& key) { + auto loaded = reg.traverse_get>("_LOADED", key); + bool is53mod = loaded && !(loaded->is() && !loaded->as()); + if (is53mod) + return loaded; +#if SOL_LUA_VERSION <= 501 + auto loaded51 = global.traverse_get>("package", "loaded", key); + bool is51mod = loaded51 && !(loaded51->is() && !loaded51->as()); + if (is51mod) + return loaded51; +#endif + return nullopt; + } + + template + void ensure_package(const std::string& key, T&& sr) { +#if SOL_LUA_VERSION <= 501 + auto pkg = global["package"]; + if (!pkg.valid()) { + pkg = create_table_with("loaded", create_table_with(key, sr)); + } + else { + auto ld = pkg["loaded"]; + if (!ld.valid()) { + ld = create_table_with(key, sr); + } + else { + ld[key] = sr; + } + } +#endif + auto loaded = reg["_LOADED"]; + if (!loaded.valid()) { + loaded = create_table_with(key, sr); + } + else { + loaded[key] = sr; + } + } + + template + object require_core(const std::string& key, Fx&& action, bool create_global = true) { + optional loaded = is_loaded_package(key); + if (loaded && loaded->valid()) + return std::move(*loaded); + action(); + auto sr = stack::get(L); + if (create_global) + set(key, sr); + ensure_package(key, sr); + return stack::pop(L); + } + + public: + typedef global_table::iterator iterator; + typedef global_table::const_iterator const_iterator; + + state_view(lua_State* L) : + L(L), + reg(L, LUA_REGISTRYINDEX), + global(L, detail::global_) { + + } + + lua_State* lua_state() const { + return L; + } + + template + void open_libraries(Args&&... args) { + static_assert(meta::all_same::value, "all types must be libraries"); + if (sizeof...(args) == 0) { + luaL_openlibs(L); + return; + } + + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; + + for (auto&& library : libraries) { + switch (library) { +#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) + case lib::coroutine: +#endif // luajit opens coroutine base stuff + case lib::base: + luaL_requiref(L, "base", luaopen_base, 1); + lua_pop(L, 1); + break; + case lib::package: + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + break; +#if !defined(SOL_LUAJIT) + case lib::coroutine: +#if SOL_LUA_VERSION > 501 + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); +#endif // Lua 5.2+ only + break; +#endif // Not LuaJIT + case lib::string: + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + break; + case lib::table: + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + break; + case lib::math: + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + break; + case lib::bit32: +#ifdef SOL_LUAJIT + luaL_requiref(L, "bit32", luaopen_bit, 1); + lua_pop(L, 1); +#elif SOL_LUA_VERSION == 502 + luaL_requiref(L, "bit32", luaopen_bit32, 1); + lua_pop(L, 1); +#else +#endif // Lua 5.2 only (deprecated in 5.3 (503)) + break; + case lib::io: + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + break; + case lib::os: + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + break; + case lib::debug: + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + break; + case lib::utf8: +#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); +#endif // Lua 5.3+ only + break; + case lib::ffi: +#ifdef SOL_LUAJIT + luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); +#endif + break; + case lib::jit: +#ifdef SOL_LUAJIT + luaL_requiref(L, "jit", luaopen_jit, 1); + lua_pop(L, 1); +#endif + break; + case lib::count: + default: + break; + } + } + } + + object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { + luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); + return stack::pop(L); + } + + object require_script(const std::string& key, const std::string& code, bool create_global = true) { + return require_core(key, [this, &code]() {stack::script(L, code); }, create_global); + } + + object require_file(const std::string& key, const std::string& filename, bool create_global = true) { + return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); + } + + function_result script(const std::string& code) { + int index = (::std::max)(lua_gettop(L), 1); + stack::script(L, code); + int returns = lua_gettop(L) - (index - 1); + return function_result(L, index, returns); + } + + function_result script_file(const std::string& filename) { + int index = (::std::max)(lua_gettop(L), 1); + stack::script_file(L, filename); + int returns = lua_gettop(L) - (index - 1); + return function_result(L, index, returns); + } + + load_result load(const std::string& code) { + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + load_result load_file(const std::string& filename) { + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + load_result load_buffer(const char *buff, size_t size, const char *name, const char* mode = nullptr) { + load_status x = static_cast(luaL_loadbufferx(L, buff, size, name, mode)); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + iterator begin() const { + return global.begin(); + } + + iterator end() const { + return global.end(); + } + + const_iterator cbegin() const { + return global.cbegin(); + } + + const_iterator cend() const { + return global.cend(); + } + + global_table globals() const { + return global; + } + + table registry() const { + return reg; + } + + operator lua_State* () const { + return lua_state(); + } + + void set_panic(lua_CFunction panic) { + lua_atpanic(L, panic); + } + + template + decltype(auto) get(Keys&&... keys) const { + return global.get(std::forward(keys)...); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + return global.get_or(std::forward(key), std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + return global.get_or(std::forward(key), std::forward(otherwise)); + } + + template + state_view& set(Args&&... args) { + global.set(std::forward(args)...); + return *this; + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + return global.traverse_get(std::forward(keys)...); + } + + template + state_view& traverse_set(Args&&... args) { + global.traverse_set(std::forward(args)...); + return *this; + } + + template + state_view& set_usertype(usertype& user) { + return set_usertype(usertype_traits::name, user); + } + + template + state_view& set_usertype(Key&& key, usertype& user) { + global.set_usertype(std::forward(key), user); + return *this; + } + + template + state_view& new_usertype(const std::string& name, Args&&... args) { + global.new_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_usertype(const std::string& name, Args&&... args) { + global.new_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_usertype(const std::string& name, constructors ctor, Args&&... args) { + global.new_usertype(name, ctor, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, Args&&... args) { + global.new_simple_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, Args&&... args) { + global.new_simple_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args) { + global.new_simple_usertype(name, ctor, std::forward(args)...); + return *this; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + return global.create_simple_usertype(std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + return global.create_simple_usertype(std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(constructors ctor, Args&&... args) { + return global.create_simple_usertype(ctor, std::forward(args)...); + } + + template + state_view& new_enum(const std::string& name, Args&&... args) { + global.new_enum(name, std::forward(args)...); + return *this; + } + + template + void for_each(Fx&& fx) { + global.for_each(std::forward(fx)); + } + + template + proxy operator[](T&& key) { + return global[std::forward(key)]; + } + + template + proxy operator[](T&& key) const { + return global[std::forward(key)]; + } + + template + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward(key), std::forward(args)...); + return *this; + } + + template + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward(key), std::forward(args)...); + return *this; + } + + template + table create_table(Name&& name, int narr = 0, int nrec = 0) { + return global.create(std::forward(name), narr, nrec); + } + + template + table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global.create(std::forward(name), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create_named_table(Name&& name, Args&&... args) { + table x = global.create_with(std::forward(args)...); + global.set(std::forward(name), x); + return x; + } + + table create_table(int narr = 0, int nrec = 0) { + return create_table(lua_state(), narr, nrec); + } + + template + table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create_table(lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create_table_with(Args&&... args) { + return create_table_with(lua_state(), std::forward(args)...); + } + + static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { + return global_table::create(L, narr, nrec); + } + + template + static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global_table::create(L, narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + static inline table create_table_with(lua_State* L, Args&&... args) { + return global_table::create_with(L, std::forward(args)...); + } + }; +} // sol + +// end of sol/state_view.hpp + +namespace sol { + inline int default_at_panic(lua_State* L) { +#ifdef SOL_NO_EXCEPTIONS + (void)L; + return -1; +#else + const char* message = lua_tostring(L, -1); + std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic"; + throw error(err); +#endif + } + + class state : private std::unique_ptr, public state_view { + private: + typedef std::unique_ptr unique_base; + public: + state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), + state_view(unique_base::get()) { + set_panic(panic); + stack::luajit_exception_handler(unique_base::get()); + } + + state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close), + state_view(unique_base::get()) { + set_panic(panic); + stack::luajit_exception_handler(unique_base::get()); + } + + using state_view::get; + }; +} // sol + +// end of sol/state.hpp + +// beginning of sol/coroutine.hpp + +// beginning of sol/thread.hpp + +namespace sol { + class thread : public reference { + public: + thread() noexcept = default; + thread(const thread&) = default; + thread(thread&&) = default; + thread(const stack_reference& r) : thread(r.lua_state(), r.stack_index()) {}; + thread(stack_reference&& r) : thread(r.lua_state(), r.stack_index()) {}; + thread& operator=(const thread&) = default; + thread& operator=(thread&&) = default; + thread(lua_State* L, int index = -1) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::thread); +#endif // Safety + } + + state_view state() const { + return state_view(this->thread_state()); + } + + lua_State* thread_state() const { + auto pp = stack::push_pop(*this); + lua_State* lthread = lua_tothread(lua_state(), -1); + return lthread; + } + + thread_status status() const { + lua_State* lthread = thread_state(); + thread_status lstat = static_cast(lua_status(lthread)); + if (lstat != thread_status::ok && lua_gettop(lthread) == 0) { + // No thing on the thread's stack means its dead + return thread_status::dead; + } + return lstat; + } + + thread create() { + return create(lua_state()); + } + + static thread create(lua_State* L) { + lua_newthread(L); + thread result(L); + lua_pop(L, 1); + return result; + } + }; +} // sol + +// end of sol/thread.hpp + +namespace sol { + class coroutine : public reference { + private: + call_status stats = call_status::yielded; + + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { +#if SOL_LUA_VERSION < 502 + stats = static_cast(lua_resume(lua_state(), static_cast(argcount))); +#else + stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount))); +#endif // Lua 5.1 compat + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, sizeof...(Ret)); + return stack::pop>(lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 1); + return stack::pop(lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 0); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { + int stacksize = lua_gettop(lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(lua_state()); + int returncount = poststacksize - (firstreturn - 1); + if (error()) { + return protected_function_result(lua_state(), lua_absindex(lua_state(), -1), 1, returncount, status()); + } + return protected_function_result(lua_state(), firstreturn, returncount, returncount, status()); + } + + public: + coroutine() noexcept = default; + coroutine(const coroutine&) noexcept = default; + coroutine& operator=(const coroutine&) noexcept = default; + coroutine(lua_State* L, int index = -1) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + call_status status() const noexcept { + return stats; + } + + bool error() const noexcept { + call_status cs = status(); + return cs != call_status::ok && cs != call_status::yielded; + } + + bool runnable() const noexcept { + return valid() + && (status() == call_status::yielded); + } + + explicit operator bool() const noexcept { + return runnable(); + } + + template + protected_function_result operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) { + push(); + int pushcount = stack::multi_push(lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; +} // sol + +// end of sol/coroutine.hpp + +#endif // SOL_SINGLE_INCLUDE_HPP diff --git a/3rdparty/sol2/sol.hpp b/3rdparty/sol2/sol.hpp new file mode 100644 index 00000000000..fcde72bbdef --- /dev/null +++ b/3rdparty/sol2/sol.hpp @@ -0,0 +1,50 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_HPP +#define SOL_HPP + +#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) +#define SOL_INSIDE_UNREAL +#endif // Unreal Engine 4 bullshit + +#ifdef SOL_INSIDE_UNREAL +#ifdef check +#define SOL_INSIDE_UNREAL_REMOVED_CHECK +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#include "sol/state.hpp" +#include "sol/object.hpp" +#include "sol/function.hpp" +#include "sol/protected_function.hpp" +#include "sol/state.hpp" +#include "sol/coroutine.hpp" +#include "sol/variadic_args.hpp" + +#ifdef SOL_INSIDE_UNREAL +#ifdef SOL_INSIDE_UNREAL_REMOVED_CHECK +#define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } }} +#endif +#endif // Unreal Engine 4 Bullshit + +#endif // SOL_HPP diff --git a/3rdparty/sol2/sol/bind_traits.hpp b/3rdparty/sol2/sol/bind_traits.hpp new file mode 100644 index 00000000000..a78cb6a3ee1 --- /dev/null +++ b/3rdparty/sol2/sol/bind_traits.hpp @@ -0,0 +1,243 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rappt1101010z, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_BIND_TRAITS_HPP +#define SOL_BIND_TRAITS_HPP + +#include "tuple.hpp" + +namespace sol { + namespace meta { + namespace meta_detail { + + template + struct check_deducible_signature { + struct nat {}; + template + static auto test(int) -> decltype(&G::operator(), void()); + template + static auto test(...)->nat; + + using type = std::is_void(0))>; + }; + } // meta_detail + + template + struct has_deducible_signature : meta_detail::check_deducible_signature::type { }; + + namespace meta_detail { + + template + struct void_tuple_element : meta::tuple_element {}; + + template + struct void_tuple_element> { typedef void type; }; + + template + using void_tuple_element_t = typename void_tuple_element::type; + + template + struct basic_traits { + private: + typedef std::conditional_t::value, int, T>& first_type; + + public: + static const bool is_member_function = std::is_void::value; + static const bool has_c_var_arg = has_c_variadic; + static const std::size_t arity = sizeof...(Args); + static const std::size_t free_arity = sizeof...(Args)+static_cast(!std::is_void::value); + typedef types args_list; + typedef std::tuple args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types returns_list; + typedef R(function_type)(Args...); + typedef std::conditional_t::value, args_list, types> free_args_list; + typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef std::conditional_t::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t signature_type; + template + using arg_at = void_tuple_element_t; + }; + + template::value> + struct fx_traits : basic_traits {}; + + // Free Functions + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + // Member Functions + /* C-Style Variadics */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; + }; + + template + struct fx_traits : fx_traits::function_type, false> {}; + + template::value> + struct callable_traits : fx_traits> { + + }; + + template + struct callable_traits { + typedef R Arg; + typedef T object_type; + using signature_type = R(T::*); + static const bool is_member_function = false; + static const std::size_t arity = 1; + static const std::size_t free_arity = 2; + typedef std::tuple args_tuple; + typedef R return_type; + typedef types args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + typedef R(function_type)(T&, R); + typedef R(*function_pointer_type)(T&, R); + typedef R(*free_function_pointer_type)(T&, R); + template + using arg_at = void_tuple_element_t; + }; + } // meta_detail + + template + struct bind_traits : meta_detail::callable_traits {}; + + template + using function_args_t = typename bind_traits::args_list; + + template + using function_signature_t = typename bind_traits::signature_type; + + template + using function_return_t = typename bind_traits::return_type; + + } // meta +} // sol + +#endif // SOL_BIND_TRAITS_HPP diff --git a/3rdparty/sol2/sol/call.hpp b/3rdparty/sol2/sol/call.hpp new file mode 100644 index 00000000000..0abeeefaa18 --- /dev/null +++ b/3rdparty/sol2/sol/call.hpp @@ -0,0 +1,573 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_CALL_HPP +#define SOL_CALL_HPP + +#include "protect.hpp" +#include "wrapper.hpp" +#include "property.hpp" +#include "stack.hpp" + +namespace sol { + namespace call_detail { + + template + inline auto& pick(std::true_type, property_wrapper& f) { + return f.read; + } + + template + inline auto& pick(std::false_type, property_wrapper& f) { + return f.write; + } + + template + struct void_call; + + template + struct void_call> { + static void call(Args...) {} + }; + + template + struct constructor_match { + T* obj; + + constructor_match(T* obj) : obj(obj) {} + + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start) const { + detail::default_construct func{}; + return stack::call_into_lua(r, a, L, start, func, obj); + } + }; + + namespace overload_detail { + template + inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence, Match&&, lua_State* L, int, int, Args&&...) { + return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); + } + + template + inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v, index_value...>::value) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (traits::free_arity != fxarity) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + stack::record tracking{}; + if (!stack::stack_detail::check_types{}.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + } // overload_detail + + template + inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_detail::overload_match_arity(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { + int fxarity = lua_gettop(L) - (start - 1); + return overload_match_arity(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + // use same overload resolution matching as all other parts of the framework + return overload_match_arity::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct(lua_State* L) { + static const auto& meta = usertype_traits::metatable; + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, meta, 1) : call_syntax::dot; + argcount -= static_cast(syntax); + + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + reference userdataref(L, -1); + userdataref.pop(); + + construct_match(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); + + userdataref.push(); + luaL_getmetatable(L, &meta[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return luaL_error(L, "sol: unable to get usertype metatable"); + } + + lua_setmetatable(L, -2); + return 1; + } + + template + struct agnostic_lua_call_wrapper { + template + static int call(lua_State* L, Fx&& f, Args&&... args) { + typedef wrapper> wrap; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::free_args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); + } + }; + + template + struct agnostic_lua_call_wrapper, true, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return stack::push_reference(L, detail::unwrap(f.value)); + } + }; + + template + struct agnostic_lua_call_wrapper, false, is_variable, checked, boost, C> { + template + static int call_assign(std::true_type, lua_State* L, V&& f) { + detail::unwrap(f.value) = stack::get>(L, boost + (is_variable ? 3 : 1)); + return 0; + } + + template + static int call_assign(std::false_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + template + static int call_const(std::false_type, lua_State* L, Args&&... args) { + typedef meta::unwrapped_t R; + return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); + } + + template + static int call_const(std::true_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + template + static int call(lua_State* L, V&& f) { + return call_const(std::is_const>(), L, f); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_r_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const no_prop&) { + return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const no_construction&) { + return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); + } + }; + + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, C> { + static int call(lua_State*, const bases&) { + // Uh. How did you even call this, lul + return 0; + } + }; + + template + struct lua_call_wrapper : agnostic_lua_call_wrapper {}; + + template + struct lua_call_wrapper::value>> { + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, Fx&& f, object_type& o) { + typedef typename wrap::returns_list returns_list; + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward(f), o); + } + + template + static int call(lua_State* L, Fx&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* o = static_cast(stack::get(L, 1)); + if (o == nullptr) { + return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); + } + return call(L, std::forward(f), *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, std::forward(f), o); +#endif // Safety + } + }; + + template + struct lua_call_wrapper::value>> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(types(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); + } + + template + static int call_assign(std::true_type, lua_State* L, V&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* o = static_cast(stack::get(L, 1)); + if (o == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); + } + return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + } + return call_assign(std::true_type(), L, f, *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call_assign(std::true_type(), L, f, o); +#endif // Safety + } + + template + static int call_assign(std::false_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + template + static int call_const(std::false_type, lua_State* L, Args&&... args) { + typedef typename traits_type::return_type R; + return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); + } + + template + static int call_const(std::true_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + template + static int call(lua_State* L, V&& f) { + return call_const(std::is_const(), L, f); + } + + template + static int call(lua_State* L, V&& f, object_type& o) { + return call_const(std::is_const(), L, f, o); + } + }; + + template + struct lua_call_wrapper::value>> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, V&& f, object_type& o) { + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); + } + + template + static int call(lua_State* L, V&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* o = static_cast(stack::get(L, 1)); + if (o == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)"); + } + return call(L, f, *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, f, o); +#endif // Safety + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef constructor_list F; + + static int call(lua_State* L, F&) { + const auto& metakey = usertype_traits::metatable; + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, metakey, 1) : call_syntax::dot; + argcount -= static_cast(syntax); + + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + + construct_match(constructor_match(obj), L, argcount, boost + 1 + static_cast(syntax)); + + userdataref.push(); + luaL_getmetatable(L, &metakey[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return luaL_error(L, "sol: unable to get usertype metatable"); + } + + lua_setmetatable(L, -2); + return 1; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef constructor_wrapper F; + + struct onmatch { + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start, F& f) { + const auto& metakey = usertype_traits::metatable; + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + + auto& func = std::get(f.functions); + stack::call_into_lua(r, a, L, boost + start, func, detail::implicit_wrapper(obj)); + + userdataref.push(); + luaL_getmetatable(L, &metakey[0]); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + std::string err = "sol: unable to get usertype metatable for "; + err += usertype_traits::name; + return luaL_error(L, err.c_str()); + } + lua_setmetatable(L, -2); + + return 1; + } + }; + + static int call(lua_State* L, F& f) { + call_syntax syntax = stack::get_call_syntax(L, usertype_traits::metatable); + int syntaxval = static_cast(syntax); + int argcount = lua_gettop(L) - syntaxval; + return construct_match>...>(onmatch(), L, argcount, 1 + syntaxval, f); + } + + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, std::enable_if_t::value>> { + typedef destructor_wrapper F; + + static int call(lua_State* L, const F&) { + return detail::usertype_alloc_destroy(L); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, std::enable_if_t::value>> { + typedef destructor_wrapper F; + + static int call(lua_State* L, const F& f) { + T& obj = stack::get(L); + f.fx(detail::implicit_wrapper(obj)); + return 0; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef overload_set F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.functions); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef factory_wrapper F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.functions); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef std::conditional_t P; + typedef meta::unqualified_t

U; + typedef lua_bind_traits traits_type; + + template + static int self_call(lua_State* L, F&& f) { + typedef wrapper wrap; + typedef meta::unqualified_t> object_type; + typedef meta::pop_front_type_t args_list; + typedef T Ta; +#ifdef SOL_SAFE_USERTYPE + object_type* po = static_cast(stack::get(L, 1)); + if (po == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)"); + } + object_type& o = *po; +#else + object_type& o = static_cast(*stack::get>(L, 1)); +#endif // Safety + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, o); + } + + template + static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { + return self_call(L, pick(meta::boolean(), f), std::forward(args)...); + } + + template + static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { + auto& p = pick(meta::boolean(), std::forward(f)); + return lua_call_wrapper, is_index, is_variable, checked, boost>{}.call(L, p, std::forward(args)...); + } + + template + static int call(lua_State* L, F&& f, Args&&... args) { + typedef meta::any< + std::is_void, + std::is_same, + meta::is_specialization_of, + meta::is_specialization_of, + meta::is_specialization_of, + std::is_member_pointer + > is_specialized; + return defer_call(is_specialized(), L, std::forward(f), std::forward(args)...); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef protect_t F; + + template + static int call(lua_State* L, F& fx, Args&&... args) { + return lua_call_wrapper{}.call(L, fx.value, std::forward(args)...); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::get<0>(f.arguments)); + } + }; + + template + inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward(fx), std::forward(args)...); + } + + template + inline int call_user(lua_State* L) { + auto& fx = stack::get>(L, upvalue_index(1)); + return call_wrapped(L, fx); + } + + template + struct is_var_bind : std::false_type {}; + + template + struct is_var_bind::value>> : std::true_type {}; + + template <> + struct is_var_bind : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + } // call_detail + + template + struct is_variable_binding : call_detail::is_var_bind> {}; + + template + struct is_function_binding : meta::neg> {}; + +} // sol + +#endif // SOL_CALL_HPP diff --git a/3rdparty/sol2/sol/compatibility.hpp b/3rdparty/sol2/sol/compatibility.hpp new file mode 100644 index 00000000000..81e7742df0c --- /dev/null +++ b/3rdparty/sol2/sol/compatibility.hpp @@ -0,0 +1,47 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_COMPATIBILITY_HPP +#define SOL_COMPATIBILITY_HPP + +// The various pieces of the compatibility layer +// comes from https://github.com/keplerproject/lua-compat-5.2 +// but has been modified in many places for use with Sol and luajit, +// though the core abstractions remain the same + +#include "compatibility/version.hpp" + +#ifndef SOL_NO_COMPAT + +#ifdef __cplusplus +extern "C" { +#endif +#include "compatibility/5.1.0.h" +#include "compatibility/5.0.0.h" +#include "compatibility/5.x.x.h" +#include "compatibility/5.x.x.inl" +#ifdef __cplusplus +} +#endif + +#endif // SOL_NO_COMPAT + +#endif // SOL_COMPATIBILITY_HPP diff --git a/3rdparty/sol2/sol/compatibility/5.0.0.h b/3rdparty/sol2/sol/compatibility/5.0.0.h new file mode 100644 index 00000000000..549badba962 --- /dev/null +++ b/3rdparty/sol2/sol/compatibility/5.0.0.h @@ -0,0 +1,44 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_5_0_0_H +#define SOL_5_0_0_H + +#include "version.hpp" + +#if SOL_LUA_VERSION < 501 +/* Lua 5.0 */ + +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + +#define luaL_Reg luaL_reg + +#define luaL_opt(L, f, n, d) \ + (lua_isnoneornil(L, n) ? (d) : f(L, n)) + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#endif // Lua 5.0 + +#endif // SOL_5_0_0_H diff --git a/3rdparty/sol2/sol/compatibility/5.1.0.h b/3rdparty/sol2/sol/compatibility/5.1.0.h new file mode 100644 index 00000000000..0050b24eca4 --- /dev/null +++ b/3rdparty/sol2/sol/compatibility/5.1.0.h @@ -0,0 +1,175 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_5_1_0_H +#define SOL_5_1_0_H + +#include "version.hpp" + +#if SOL_LUA_VERSION == 501 +/* Lua 5.1 */ + +#include +#include +#include +#include + +/* LuaJIT doesn't define these unofficial macros ... */ +#if !defined(LUAI_INT32) +#include +#if INT_MAX-20 < 32760 +#define LUAI_INT32 long +#define LUAI_UINT32 unsigned long +#elif INT_MAX > 2147483640L +#define LUAI_INT32 int +#define LUAI_UINT32 unsigned int +#else +#error "could not detect suitable lua_Unsigned datatype" +#endif +#endif + +/* LuaJIT does not have the updated error codes for thread status/function returns */ +#ifndef LUA_ERRGCMM +#define LUA_ERRGCMM (LUA_ERRERR + 1) +#endif // LUA_ERRGCMM + +/* LuaJIT does not support continuation contexts / return error codes? */ +#ifndef LUA_KCONTEXT +#define LUA_KCONTEXT std::ptrdiff_t +typedef LUA_KCONTEXT lua_KContext; +typedef int(*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); +#endif // LUA_KCONTEXT + +#define LUA_OPADD 0 +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +typedef LUAI_UINT32 lua_Unsigned; + +typedef struct luaL_Buffer_52 { + luaL_Buffer b; /* make incorrect code crash! */ + char *ptr; + size_t nelems; + size_t capacity; + lua_State *L2; +} luaL_Buffer_52; +#define luaL_Buffer luaL_Buffer_52 + +#define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) + +#define lua_rawlen(L, i) lua_objlen(L, i) + +inline void lua_callk(lua_State *L, int nargs, int nresults, lua_KContext, lua_KFunction) { + // should probably warn the user of Lua 5.1 that continuation isn't supported... + lua_call(L, nargs, nresults); +} +inline int lua_pcallk(lua_State *L, int nargs, int nresults, int errfunc, lua_KContext, lua_KFunction) { + // should probably warn the user of Lua 5.1 that continuation isn't supported... + return lua_pcall(L, nargs, nresults, errfunc); +} +void lua_arith(lua_State *L, int op); +int lua_compare(lua_State *L, int idx1, int idx2, int op); +void lua_pushunsigned(lua_State *L, lua_Unsigned n); +lua_Unsigned luaL_checkunsigned(lua_State *L, int i); +lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum); +lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def); +lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); +void lua_len(lua_State *L, int i); +int luaL_len(lua_State *L, int i); +const char *luaL_tolstring(lua_State *L, int idx, size_t *len); +void luaL_requiref(lua_State *L, char const* modname, lua_CFunction openf, int glb); + +#define luaL_buffinit luaL_buffinit_52 +void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B); + +#define luaL_prepbuffsize luaL_prepbuffsize_52 +char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s); + +#define luaL_addlstring luaL_addlstring_52 +void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l); + +#define luaL_addvalue luaL_addvalue_52 +void luaL_addvalue(luaL_Buffer_52 *B); + +#define luaL_pushresult luaL_pushresult_52 +void luaL_pushresult(luaL_Buffer_52 *B); + +#undef luaL_buffinitsize +#define luaL_buffinitsize(L, B, s) \ + (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) + +#undef luaL_prepbuffer +#define luaL_prepbuffer(B) \ + luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +#undef luaL_addchar +#define luaL_addchar(B, c) \ + ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ + ((B)->ptr[(B)->nelems++] = (c))) + +#undef luaL_addsize +#define luaL_addsize(B, s) \ + ((B)->nelems += (s)) + +#undef luaL_addstring +#define luaL_addstring(B, s) \ + luaL_addlstring(B, s, strlen(s)) + +#undef luaL_pushresultsize +#define luaL_pushresultsize(B, s) \ + (luaL_addsize(B, s), luaL_pushresult(B)) + +typedef struct kepler_lua_compat_get_string_view { + const char *s; + size_t size; +} kepler_lua_compat_get_string_view; + +inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t* size) { + kepler_lua_compat_get_string_view* ls = (kepler_lua_compat_get_string_view*) ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + +#if !defined(SOL_LUAJIT) || ((SOL_LUAJIT_VERSION - 020100) <= 0) +// Luajit 2.1.0 has this function already + +inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { + kepler_lua_compat_get_string_view ls; + ls.s = buff; + ls.size = size; + return lua_load(L, kepler_lua_compat_get_string, &ls, name/*, mode*/); +} + +#endif // LuaJIT 2.1.x beta and beyond + +#endif /* Lua 5.1 */ + +#endif // SOL_5_1_0_H \ No newline at end of file diff --git a/3rdparty/sol2/sol/compatibility/5.x.x.h b/3rdparty/sol2/sol/compatibility/5.x.x.h new file mode 100644 index 00000000000..95f48792a00 --- /dev/null +++ b/3rdparty/sol2/sol/compatibility/5.x.x.h @@ -0,0 +1,57 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_5_X_X_H +#define SOL_5_X_X_H + +#include "version.hpp" + +#if SOL_LUA_VERSION < 502 + +#define LUA_RIDX_GLOBALS LUA_GLOBALSINDEX + +#define LUA_OK 0 + +#define lua_pushglobaltable(L) \ + lua_pushvalue(L, LUA_GLOBALSINDEX) + +#define luaL_newlib(L, l) \ + (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) + +void luaL_checkversion(lua_State *L); + +int lua_absindex(lua_State *L, int i); +void lua_copy(lua_State *L, int from, int to); +void lua_rawgetp(lua_State *L, int i, const void *p); +void lua_rawsetp(lua_State *L, int i, const void *p); +void *luaL_testudata(lua_State *L, int i, const char *tname); +lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); +void lua_getuservalue(lua_State *L, int i); +void lua_setuservalue(lua_State *L, int i); +void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); +void luaL_setmetatable(lua_State *L, const char *tname); +int luaL_getsubtable(lua_State *L, int i, const char *name); +void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); +int luaL_fileresult(lua_State *L, int stat, const char *fname); + +#endif // Lua 5.1 and below + +#endif // SOL_5_X_X_H diff --git a/3rdparty/sol2/sol/compatibility/5.x.x.inl b/3rdparty/sol2/sol/compatibility/5.x.x.inl new file mode 100644 index 00000000000..1d420e3f3f6 --- /dev/null +++ b/3rdparty/sol2/sol/compatibility/5.x.x.inl @@ -0,0 +1,707 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_5_X_X_INL +#define SOL_5_X_X_INL + +#include "version.hpp" +#include "5.1.0.h" +#include "5.0.0.h" +#include "5.x.x.h" + +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 + +#include +#include + +#define PACKAGE_KEY "_sol.package" + +inline int lua_absindex(lua_State *L, int i) { + if (i < 0 && i > LUA_REGISTRYINDEX) + i += lua_gettop(L) + 1; + return i; +} + +inline void lua_copy(lua_State *L, int from, int to) { + int abs_to = lua_absindex(L, to); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, from); + lua_replace(L, abs_to); +} + +inline void lua_rawgetp(lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + lua_pushlightuserdata(L, (void*)p); + lua_rawget(L, abs_i); +} + +inline void lua_rawsetp(lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, (void*)p); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + +inline void *luaL_testudata(lua_State *L, int i, const char *tname) { + void *p = lua_touserdata(L, i); + luaL_checkstack(L, 2, "not enough stack slots"); + if (p == NULL || !lua_getmetatable(L, i)) + return NULL; + else { + int res = 0; + luaL_getmetatable(L, tname); + res = lua_rawequal(L, -1, -2); + lua_pop(L, 2); + if (!res) + p = NULL; + } + return p; +} + +inline lua_Number lua_tonumberx(lua_State *L, int i, int *isnum) { + lua_Number n = lua_tonumber(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +inline static void push_package_table(lua_State *L) { + lua_pushliteral(L, PACKAGE_KEY); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + /* try to get package table from globals */ + lua_pushliteral(L, "package"); + lua_rawget(L, LUA_GLOBALSINDEX); + if (lua_istable(L, -1)) { + lua_pushliteral(L, PACKAGE_KEY); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } +} + +inline void lua_getuservalue(lua_State *L, int i) { + luaL_checktype(L, i, LUA_TUSERDATA); + luaL_checkstack(L, 2, "not enough stack slots"); + lua_getfenv(L, i); + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 1); + lua_pushnil(L); + lua_replace(L, -2); + } + else { + lua_pop(L, 1); + push_package_table(L); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 1); + lua_pushnil(L); + lua_replace(L, -2); + } + else + lua_pop(L, 1); + } +} + +inline void lua_setuservalue(lua_State *L, int i) { + luaL_checktype(L, i, LUA_TUSERDATA); + if (lua_isnil(L, -1)) { + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_replace(L, -2); + } + lua_setfenv(L, i); +} + +/* +** Adapted from Lua 5.2.0 +*/ +inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup + 1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ + } + lua_pop(L, nup); /* remove upvalues */ +} + +inline void luaL_setmetatable(lua_State *L, const char *tname) { + luaL_checkstack(L, 1, "not enough stack slots"); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +inline int luaL_getsubtable(lua_State *L, int i, const char *name) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushstring(L, name); + lua_gettable(L, abs_i); + if (lua_istable(L, -1)) + return 1; + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + +#ifndef SOL_LUAJIT +inline static int countlevels(lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le) / 2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + +inline static int findfield(lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + +inline static int pushglobalfuncname(lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +inline static void pushfuncname(lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +inline void luaL_traceback(lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} +#endif + +inline const lua_Number *lua_version(lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + // TODO: wonky hacks to get at the inside of the incomplete type lua_State? + //else return L->l_G->version; + else return &version; +} + +inline static void luaL_checkversion_(lua_State *L, lua_Number ver) { + const lua_Number* v = lua_version(L); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + +inline void luaL_checkversion(lua_State* L) { + luaL_checkversion_(L, LUA_VERSION_NUM); +} + +#ifndef SOL_LUAJIT +inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + char buf[1024]; +#ifdef __GLIBC__ + strerror_r(en, buf, 1024); +#else + strerror_s(buf, 1024, en); +#endif + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, buf); + else + lua_pushstring(L, buf); + lua_pushnumber(L, (lua_Number)en); + return 3; + } +} +#endif // luajit +#endif // Lua 5.0 or Lua 5.1 + + +#if SOL_LUA_VERSION == 501 +#include + +typedef LUAI_INT32 LUA_INT32; + +/********************************************************************/ +/* extract of 5.2's luaconf.h */ +/* detects proper defines for faster unsigned<->number conversion */ +/* see copyright notice at the end of this file */ +/********************************************************************/ + +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ +#endif + + +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ + +/* Microsoft compiler on a Pentium (32 bit) ? */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ + +#define LUA_MSASMTRICK +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 32 bits? */ +#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEELL +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 64 bits? */ +#elif defined(__x86_64) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 0 + +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 1 + +#else /* }{ */ + +/* assume IEEE754 and a 32-bit integer type */ +#define LUA_IEEE754TRICK + +#endif /* } */ + +#endif /* } */ + + +/********************************************************************/ +/* extract of 5.2's llimits.h */ +/* gives us lua_number2unsigned and lua_unsigned2number */ +/* see copyright notice just below this one here */ +/********************************************************************/ + +/********************************************************************* +* This file contains parts of Lua 5.2's source code: +* +* Copyright (C) 1994-2013 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*********************************************************************/ + +#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ +/* trick with Microsoft assembler for X86 */ + +#define lua_number2unsigned(i,n) \ + {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} + + +#elif defined(LUA_IEEE754TRICK) /* }{ */ +/* the next trick should work on any machine using IEEE754 with +a 32-bit int type */ + +union compat52_luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union compat52_luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) +#else +#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union compat52_luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } + +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) + +#endif /* } */ + + +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2unsigned) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) +#include +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define lua_number2unsigned(i,n) \ + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) +#else +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#endif +#endif /* } */ + + +#if !defined(lua_unsigned2number) +/* on several machines, coercion from unsigned to double is slow, +so it may be worth to avoid */ +#define lua_unsigned2number(u) \ + (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) +#endif + +/********************************************************************/ + +inline static void compat52_call_lua(lua_State *L, char const code[], size_t len, + int nargs, int nret) { + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, code, len, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); + } + lua_insert(L, -nargs - 1); + lua_call(L, nargs, nret); +} + +static const char compat52_arith_code[] = { + "local op,a,b=...\n" + "if op==0 then return a+b\n" + "elseif op==1 then return a-b\n" + "elseif op==2 then return a*b\n" + "elseif op==3 then return a/b\n" + "elseif op==4 then return a%b\n" + "elseif op==5 then return a^b\n" + "elseif op==6 then return -a\n" + "end\n" +}; + +inline void lua_arith(lua_State *L, int op) { + if (op < LUA_OPADD || op > LUA_OPUNM) + luaL_error(L, "invalid 'op' argument for lua_arith"); + luaL_checkstack(L, 5, "not enough stack slots"); + if (op == LUA_OPUNM) + lua_pushvalue(L, -1); + lua_pushnumber(L, op); + lua_insert(L, -3); + compat52_call_lua(L, compat52_arith_code, + sizeof(compat52_arith_code) - 1, 3, 1); +} + +static const char compat52_compare_code[] = { + "local a,b=...\n" + "return a<=b\n" +}; + +inline int lua_compare(lua_State *L, int idx1, int idx2, int op) { + int result = 0; + switch (op) { + case LUA_OPEQ: + return lua_equal(L, idx1, idx2); + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + case LUA_OPLE: + luaL_checkstack(L, 5, "not enough stack slots"); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + compat52_call_lua(L, compat52_compare_code, + sizeof(compat52_compare_code) - 1, 2, 1); + result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + default: + luaL_error(L, "invalid 'op' argument for lua_compare"); + } + return 0; +} + +inline void lua_pushunsigned(lua_State *L, lua_Unsigned n) { + lua_pushnumber(L, lua_unsigned2number(n)); +} + +inline lua_Unsigned luaL_checkunsigned(lua_State *L, int i) { + lua_Unsigned result; + lua_Number n = lua_tonumber(L, i); + if (n == 0 && !lua_isnumber(L, i)) + luaL_checktype(L, i, LUA_TNUMBER); + lua_number2unsigned(result, n); + return result; +} + +inline lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum) { + lua_Unsigned result; + lua_Number n = lua_tonumberx(L, i, isnum); + lua_number2unsigned(result, n); + return result; +} + +inline lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, i, def); +} + +inline lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum) { + lua_Integer n = lua_tointeger(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +inline void lua_len(lua_State *L, int i) { + switch (lua_type(L, i)) { + case LUA_TSTRING: /* fall through */ + case LUA_TTABLE: + if (!luaL_callmeta(L, i, "__len")) + lua_pushnumber(L, (int)lua_objlen(L, i)); + break; + case LUA_TUSERDATA: + if (luaL_callmeta(L, i, "__len")) + break; + /* maybe fall through */ + default: + luaL_error(L, "attempt to get length of a %s value", + lua_typename(L, lua_type(L, i))); + } +} + +inline int luaL_len(lua_State *L, int i) { + int res = 0, isnum = 0; + luaL_checkstack(L, 1, "not enough stack slots"); + lua_len(L, i); + res = (int)lua_tointegerx(L, -1, &isnum); + lua_pop(L, 1); + if (!isnum) + luaL_error(L, "object length is not a number"); + return res; +} + +inline const char *luaL_tolstring(lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { + int t = lua_type(L, idx); + switch (t) { + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + case LUA_TSTRING: + case LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + if (lua_toboolean(L, idx)) + lua_pushliteral(L, "true"); + else + lua_pushliteral(L, "false"); + break; + default: + lua_pushfstring(L, "%s: %p", lua_typename(L, t), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + +inline void luaL_requiref(lua_State *L, char const* modname, + lua_CFunction openf, int glb) { + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_getglobal(L, "package"); + if (lua_istable(L, -1) == 0) { + lua_pop(L, 1); + lua_createtable(L, 0, 16); + lua_setglobal(L, "package"); + lua_getglobal(L, "package"); + } + lua_getfield(L, -1, "loaded"); + if (lua_istable(L, -1) == 0) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_setfield(L, -2, "loaded"); + lua_getfield(L, -1, "loaded"); + } + lua_replace(L, -2); + lua_pushvalue(L, -2); + lua_setfield(L, -2, modname); + lua_pop(L, 1); + if (glb) { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } +} + +inline void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B) { + /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ + B->b.p = NULL; + B->b.L = NULL; + B->b.lvl = 0; + /* reuse the buffer from the 5.1-style luaL_Buffer though! */ + B->ptr = B->b.buffer; + B->capacity = LUAL_BUFFERSIZE; + B->nelems = 0; + B->L2 = L; +} + +inline char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s) { + if (B->capacity - B->nelems < s) { /* needs to grow */ + char* newptr = NULL; + size_t newcap = B->capacity * 2; + if (newcap - B->nelems < s) + newcap = B->nelems + s; + if (newcap < B->capacity) /* overflow */ + luaL_error(B->L2, "buffer too large"); + newptr = (char*)lua_newuserdata(B->L2, newcap); + memcpy(newptr, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove old buffer */ + B->ptr = newptr; + B->capacity = newcap; + } + return B->ptr + B->nelems; +} + +inline void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l) { + memcpy(luaL_prepbuffsize(B, l), s, l); + luaL_addsize(B, l); +} + +inline void luaL_addvalue(luaL_Buffer_52 *B) { + size_t len = 0; + const char *s = lua_tolstring(B->L2, -1, &len); + if (!s) + luaL_error(B->L2, "cannot convert value to string"); + if (B->ptr != B->b.buffer) + lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ + luaL_addlstring(B, s, len); + lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); +} + +inline void luaL_pushresult(luaL_Buffer_52 *B) { + lua_pushlstring(B->L2, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove userdata buffer */ +} + +#endif /* SOL_LUA_VERSION == 501 */ + +#endif // SOL_5_X_X_INL diff --git a/3rdparty/sol2/sol/compatibility/version.hpp b/3rdparty/sol2/sol/compatibility/version.hpp new file mode 100644 index 00000000000..5ddc23d91e6 --- /dev/null +++ b/3rdparty/sol2/sol/compatibility/version.hpp @@ -0,0 +1,121 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_VERSION_HPP +#define SOL_VERSION_HPP + +#include + +#if defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // sol codecvt support +#elif defined(__GNUC__) +#if __GNUC__ >= 5 +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // codecvt support +#endif // g++ 5.x.x +#else +// Clang sucks and doesn't really utilize codecvt support, +// not without checking the library versions explicitly (and we're not gonna do that, so fuck you) +#endif // Windows/VC++ vs. g++ vs Others + +#ifdef LUAJIT_VERSION +#ifndef SOL_LUAJIT +#define SOL_LUAJIT +#define SOL_LUAJIT_VERSION LUAJIT_VERSION_NUM +#endif // sol luajit +#endif // luajit + +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 +#define SOL_LUA_VERSION LUA_VERSION_NUM +#elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 +#define SOL_LUA_VERSION LUA_VERSION_NUM +#elif !defined(LUA_VERSION_NUM) +// Definitely 5.0 +#define SOL_LUA_VERSION 500 +#else +// ??? Not sure, assume 502? +#define SOL_LUA_VERSION 502 +#endif // Lua Version 502, 501 || luajit, 500 + +#ifdef _MSC_VER +#ifdef _DEBUG +#ifndef NDEBUG +#ifndef SOL_CHECK_ARGUMENTS +// Do not define by default: let user turn it on +//#define SOL_CHECK_ARGUMENTS +#endif // Check Arguments +#ifndef SOL_SAFE_USERTYPE +#define SOL_SAFE_USERTYPE +#endif // Safe Usertypes +#endif // NDEBUG +#endif // Debug + +#ifndef _CPPUNWIND +#ifndef SOL_NO_EXCEPTIONS +#define SOL_NO_EXCEPTIONS 1 +#endif +#endif // Automatic Exceptions + +#ifndef _CPPRTTI +#ifndef SOL_NO_RTTI +#define SOL_NO_RTTI 1 +#endif +#endif // Automatic RTTI + +#elif defined(__GNUC__) || defined(__clang__) + +#ifndef NDEBUG +#ifndef __OPTIMIZE__ +#ifndef SOL_CHECK_ARGUMENTS +// Do not define by default: let user choose +//#define SOL_CHECK_ARGUMENTS +// But do check userdata by default: +#endif // Check Arguments +#ifndef SOL_SAFE_USERTYPE +#define SOL_SAFE_USERTYPE +#endif // Safe Usertypes +#endif // g++ optimizer flag +#endif // Not Debug + +#ifndef __EXCEPTIONS +#ifndef SOL_NO_EXCEPTIONS +#define SOL_NO_EXCEPTIONS 1 +#endif +#endif // No Exceptions + +#ifndef __GXX_RTTI +#ifndef SOL_NO_RTII +#define SOL_NO_RTTI 1 +#endif +#endif // No RTTI + +#endif // vc++ || clang++/g++ + +#ifndef SOL_SAFE_USERTYPE +#ifdef SOL_CHECK_ARGUMENTS +#define SOL_SAFE_USERTYPE +#endif // Turn on Safety for all +#endif // Safe Usertypes + +#endif // SOL_VERSION_HPP diff --git a/3rdparty/sol2/sol/container_usertype_metatable.hpp b/3rdparty/sol2/sol/container_usertype_metatable.hpp new file mode 100644 index 00000000000..a07b85be851 --- /dev/null +++ b/3rdparty/sol2/sol/container_usertype_metatable.hpp @@ -0,0 +1,412 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_CONTAINER_USERTYPE_HPP +#define SOL_CONTAINER_USERTYPE_HPP + +#include "stack.hpp" + +namespace sol { + + namespace detail { + + template + struct has_find { + private: + typedef std::array one; + typedef std::array two; + + template static one test(decltype(&C::find)); + template static two test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + T& get_first(const T& t) { + return std::forward(t); + } + + template + decltype(auto) get_first(const std::pair& t) { + return t.first; + } + + template >> = meta::enabler> + auto find(C& c, I&& i) { + return c.find(std::forward(i)); + } + + template >> = meta::enabler> + auto find(C& c, I&& i) { + using std::begin; + using std::end; + return std::find_if(begin(c), end(c), [&i](auto&& x) { + return i == get_first(x); + }); + } + + } + + template + struct container_usertype_metatable { + typedef meta::unqualified_t T; + typedef std::size_t K; + typedef typename T::value_type V; + typedef typename T::iterator I; + typedef std::remove_reference_t())> IR; + + struct iter { + T& source; + I it; + + iter(T& source, I it) : source(source), it(std::move(it)) {} + }; + + static auto& get_src(lua_State* L) { +#ifdef SOL_SAFE_USERTYPE + auto p = stack::get(L, 1); + if (p == nullptr) { + luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument or call on proper type)"); + } + return *p; +#else + return stack::get(L, 1); +#endif + } + + static int real_index_call(lua_State* L) { + auto& src = get_src(L); +#ifdef SOL_SAFE_USERTYPE + auto maybek = stack::check_get(L, 2); + if (maybek) { + using std::begin; + auto it = begin(src); + K k = *maybek; + if (k <= src.size() && k > 0) { + --k; + std::advance(it, k); + return stack::push_reference(L, *it); + } + } + return stack::push(L, nil); +#else + using std::begin; + auto it = begin(src); + K k = stack::get(L, 2); + --k; + std::advance(it, k); + return stack::push_reference(L, *it); +#endif // Safety + } + + template > = meta::enabler> + static int real_new_index_call_const(std::integral_constant, lua_State* L) { + luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); + return 0; + } + + template > = meta::enabler> + static int real_new_index_call_const(std::integral_constant, lua_State* L) { + auto& src = get_src(L); +#ifdef SOL_SAFE_USERTYPE + auto maybek = stack::check_get(L, 2); + if (maybek) { + K k = *maybek; + if (k <= src.size() && k > 0) { + --k; + using std::begin; + auto it = begin(src); + std::advance(it, k); + *it = stack::get(L, 3); + } + } +#else + using std::begin; + auto it = begin(src); + K k = stack::get(L, 2); + --k; + std::advance(it, k); + *it = stack::get(L, 3); +#endif + return 0; + } + + static int real_new_index_call(lua_State* L) { + return real_new_index_call_const(meta::neg, std::is_const>>(), L); + } + + static int real_pairs_next_call(lua_State* L) { + using std::end; + iter& i = stack::get>(L, 1); + auto& source = i.source; + auto& it = i.it; + K k = stack::get(L, 2); + if (it == end(source)) { + return 0; + } + int p = stack::multi_push_reference(L, k + 1, *it); + std::advance(it, 1); + return p; + } + + static int real_pairs_call(lua_State* L) { + auto& src = get_src(L); + using std::begin; + stack::push(L, pairs_next_call); + stack::push>(L, src, begin(src)); + stack::push(L, 0); + return 3; + } + + static int real_length_call(lua_State*L) { + auto& src = get_src(L); + return stack::push(L, src.size()); + } + +#if 0 + static int real_push_back_call(lua_State*L) { + auto& src = get_src(L); + src.push_back(stack::get(L, 2)); + return 0; + } + + static int real_insert_call(lua_State*L) { + using std::begin; + auto& src = get_src(L); + src.insert(std::next(begin(src), stack::get(L, 2)), stack::get(L, 3)); + return 0; + } + + static int push_back_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int insert_call(lua_State*L) { + return detail::static_trampoline<(&real_insert_call)>(L); + } +#endif // Sometime later, in a distant universe... + + static int length_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int pairs_next_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_next_call)>(L); + } + + static int pairs_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_call)>(L); + } + + static int index_call(lua_State*L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State*L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + }; + + template + struct container_usertype_metatable>::value>> { + typedef meta::unqualified_t T; + typedef typename T::value_type KV; + typedef typename KV::first_type K; + typedef typename KV::second_type V; + typedef typename T::iterator I; + struct iter { + T& source; + I it; + + iter(T& source, I it) : source(source), it(std::move(it)) {} + }; + + static auto& get_src(lua_State* L) { +#ifdef SOL_SAFE_USERTYPE + auto p = stack::get(L, 1); + if (p == nullptr) { + luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument or call on proper type)"); + } + return *p; +#else + return stack::get(L, 1); +#endif + } + + static int real_index_call(lua_State* L) { + auto& src = get_src(L); + auto k = stack::check_get(L, 2); + if (k) { + using std::end; + auto it = detail::find(src, *k); + if (it != end(src)) { + auto& v = *it; + return stack::push_reference(L, v.second); + } + } + return stack::push(L, nil); + } + + static int real_new_index_call_const(std::false_type, lua_State* L) { + luaL_error(L, "sol: cannot write to a const value type"); + return 0; + } + + static int real_new_index_call_const(std::true_type, lua_State* L) { + auto& src = get_src(L); + auto k = stack::check_get(L, 2); + if (k) { + using std::end; + auto it = detail::find(src, *k); + if (it != end(src)) { + auto& v = *it; + v.second = stack::get(L, 3); + } + else { + src.insert(it, { std::move(*k), stack::get(L, 3) }); + } + } + return 0; + } + + static int real_new_index_call(lua_State* L) { + return real_new_index_call_const(meta::neg>(), L); + } + + static int real_pairs_next_call(lua_State* L) { + using std::end; + iter& i = stack::get>(L, 1); + auto& source = i.source; + auto& it = i.it; + std::advance(it, 1); + if (it == end(source)) { + return 0; + } + return stack::multi_push_reference(L, it->first, it->second); + } + + static int real_pairs_call(lua_State* L) { + auto& src = get_src(L); + using std::begin; + stack::push(L, pairs_next_call); + stack::push>(L, src, begin(src)); + stack::push(L, 1); + return 3; + } + + static int real_length_call(lua_State*L) { + auto& src = get_src(L); + return stack::push(L, src.size()); + } + + static int length_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int pairs_next_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_next_call)>(L); + } + + static int pairs_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_call)>(L); + } + + static int index_call(lua_State*L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State*L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + }; + + namespace stack { + + template + struct pusher, meta::neg, std::is_base_of>>>::value>> { + typedef container_usertype_metatable cumt; + static int push(lua_State* L, const T& cont) { + auto fx = [&L]() { + const char* metakey = &usertype_traits::metatable[0]; + if (luaL_newmetatable(L, metakey) == 1) { + luaL_Reg reg[] = { + { "__index", &cumt::index_call }, + { "__newindex", &cumt::new_index_call }, + { "__pairs", &cumt::pairs_call }, + { "__len", &cumt::length_call }, + { "__gc", &detail::usertype_alloc_destroy }, + { nullptr, nullptr } + }; + luaL_setfuncs(L, reg, 0); + } + lua_setmetatable(L, -2); + }; + return pusher>{}.push_fx(L, fx, cont); + } + + static int push(lua_State* L, T&& cont) { + auto fx = [&L]() { + const char* metakey = &usertype_traits::metatable[0]; + if (luaL_newmetatable(L, metakey) == 1) { + luaL_Reg reg[] = { + { "__index", &cumt::index_call }, + { "__newindex", &cumt::new_index_call }, + { "__pairs", &cumt::pairs_call }, + { "__len", &cumt::length_call }, + { "__gc", &detail::usertype_alloc_destroy }, + { nullptr, nullptr } + }; + luaL_setfuncs(L, reg, 0); + } + lua_setmetatable(L, -2); + }; + return pusher>{}.push_fx(L, fx, std::move(cont)); + } + }; + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + typedef container_usertype_metatable cumt; + static int push(lua_State* L, T* cont) { + auto fx = [&L]() { + const char* metakey = &usertype_traits*>::metatable[0]; + if (luaL_newmetatable(L, metakey) == 1) { + luaL_Reg reg[] = { + { "__index", &cumt::index_call }, + { "__newindex", &cumt::new_index_call }, + { "__pairs", &cumt::pairs_call }, + { "__len", &cumt::length_call }, + { nullptr, nullptr } + }; + luaL_setfuncs(L, reg, 0); + } + lua_setmetatable(L, -2); + }; + return pusher>{}.push_fx(L, fx, cont); + } + }; + } // stack + +} // sol + +#endif // SOL_CONTAINER_USERTYPE_HPP diff --git a/3rdparty/sol2/sol/coroutine.hpp b/3rdparty/sol2/sol/coroutine.hpp new file mode 100644 index 00000000000..4abfa78ec2a --- /dev/null +++ b/3rdparty/sol2/sol/coroutine.hpp @@ -0,0 +1,119 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_COROUTINE_HPP +#define SOL_COROUTINE_HPP + +#include "reference.hpp" +#include "stack.hpp" +#include "function_result.hpp" +#include "thread.hpp" + +namespace sol { + class coroutine : public reference { + private: + call_status stats = call_status::yielded; + + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { +#if SOL_LUA_VERSION < 502 + stats = static_cast(lua_resume(lua_state(), static_cast(argcount))); +#else + stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount))); +#endif // Lua 5.1 compat + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, sizeof...(Ret)); + return stack::pop>(lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 1); + return stack::pop(lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 0); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { + int stacksize = lua_gettop(lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(lua_state()); + int returncount = poststacksize - (firstreturn - 1); + if (error()) { + return protected_function_result(lua_state(), lua_absindex(lua_state(), -1), 1, returncount, status()); + } + return protected_function_result(lua_state(), firstreturn, returncount, returncount, status()); + } + + public: + coroutine() noexcept = default; + coroutine(const coroutine&) noexcept = default; + coroutine& operator=(const coroutine&) noexcept = default; + coroutine(lua_State* L, int index = -1) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + call_status status() const noexcept { + return stats; + } + + bool error() const noexcept { + call_status cs = status(); + return cs != call_status::ok && cs != call_status::yielded; + } + + bool runnable() const noexcept { + return valid() + && (status() == call_status::yielded); + } + + explicit operator bool() const noexcept { + return runnable(); + } + + template + protected_function_result operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) { + push(); + int pushcount = stack::multi_push(lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; +} // sol + +#endif // SOL_COUROUTINE_HPP diff --git a/3rdparty/sol2/sol/debug.hpp b/3rdparty/sol2/sol/debug.hpp new file mode 100644 index 00000000000..1219484df3b --- /dev/null +++ b/3rdparty/sol2/sol/debug.hpp @@ -0,0 +1,54 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_DEBUG_HPP +#define SOL_DEBUG_HPP + +#include "stack.hpp" +#include + +namespace sol { + namespace detail { + namespace debug { + inline std::string dump_types(lua_State* L) { + std::string visual; + std::size_t size = lua_gettop(L) + 1; + for (std::size_t i = 1; i < size; ++i) { + if (i != 1) { + visual += " | "; + } + visual += type_name(L, stack::get(L, static_cast(i))); + } + return visual; + } + + inline void print_stack(lua_State* L) { + std::cout << dump_types(L) << std::endl; + } + + inline void print_section(const std::string& message, lua_State* L) { + std::cout << "-- " << message << " -- [ " << dump_types(L) << " ]" << std::endl; + } + } // detail + } // debug +} // sol + +#endif // SOL_DEBUG_HPP diff --git a/3rdparty/sol2/sol/demangle.hpp b/3rdparty/sol2/sol/demangle.hpp new file mode 100644 index 00000000000..2d3bc518aeb --- /dev/null +++ b/3rdparty/sol2/sol/demangle.hpp @@ -0,0 +1,158 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_DEMANGLE_HPP +#define SOL_DEMANGLE_HPP + +#include +#include +#include + +namespace sol { + namespace detail { +#ifdef _MSC_VER + template + inline std::string ctti_get_type_name() { + const static std::array removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } }; + std::string name = __FUNCSIG__; + std::size_t start = name.find("get_type_name"); + if (start == std::string::npos) + start = 0; + else + start += 13; + if (start < name.size() - 1) + start += 1; + std::size_t end = name.find_last_of('>'); + if (end == std::string::npos) + end = name.size(); + name = name.substr(start, end - start); + if (name.find("struct", 0) == 0) + name.replace(0, 6, "", 0); + if (name.find("class", 0) == 0) + name.replace(0, 5, "", 0); + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); + while (!name.empty() && std::isblank(name.back())) name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } +#elif defined(__GNUC__) || defined(__clang__) + template + inline std::string ctti_get_type_name() { + const static std::array removals = { { "{anonymous}", "(anonymous namespace)" } }; + std::string name = __PRETTY_FUNCTION__; + std::size_t start = name.find_first_of('['); + start = name.find_first_of('=', start); + std::size_t end = name.find_last_of(']'); + if (end == std::string::npos) + end = name.size(); + if (start == std::string::npos) + start = 0; + if (start < name.size() - 1) + start += 1; + name = name.substr(start, end - start); + start = name.rfind("seperator_mark"); + if (start != std::string::npos) { + name.erase(start - 2, name.length()); + } + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); + while (!name.empty() && std::isblank(name.back())) name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } +#else +#error Compiler not supported for demangling +#endif // compilers + + template + inline std::string demangle_once() { + std::string realname = ctti_get_type_name(); + return realname; + } + + template + inline std::string short_demangle_once() { + std::string realname = ctti_get_type_name(); + // This isn't the most complete but it'll do for now...? + static const std::array ops = { { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" } }; + int level = 0; + std::ptrdiff_t idx = 0; + for (idx = static_cast(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { + if (level == 0 && realname[idx] == ':') { + break; + } + bool isleft = realname[idx] == '<'; + bool isright = realname[idx] == '>'; + if (!isleft && !isright) + continue; + bool earlybreak = false; + for (const auto& op : ops) { + std::size_t nisop = realname.rfind(op, idx); + if (nisop == std::string::npos) + continue; + std::size_t nisopidx = idx - op.size() + 1; + if (nisop == nisopidx) { + idx = static_cast(nisopidx); + earlybreak = true; + } + break; + } + if (earlybreak) { + continue; + } + level += isleft ? -1 : 1; + } + if (idx > 0) { + realname.erase(0, realname.length() < static_cast(idx) ? realname.length() : idx + 1); + } + return realname; + } + + template + inline std::string demangle() { + static const std::string d = demangle_once(); + return d; + } + + template + inline std::string short_demangle() { + static const std::string d = short_demangle_once(); + return d; + } + } // detail +} // sol + +#endif // SOL_DEMANGLE_HPP diff --git a/3rdparty/sol2/sol/deprecate.hpp b/3rdparty/sol2/sol/deprecate.hpp new file mode 100644 index 00000000000..0d9551a33b0 --- /dev/null +++ b/3rdparty/sol2/sol/deprecate.hpp @@ -0,0 +1,44 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_DEPRECATE_HPP +#define SOL_DEPRECATE_HPP + +#ifndef SOL_DEPRECATED + #ifdef _MSC_VER + #define SOL_DEPRECATED __declspec(deprecated) + #elif __GNUC__ + #define SOL_DEPRECATED __attribute__((deprecated)) + #else + #define SOL_DEPRECATED [[deprecated]] + #endif // compilers +#endif // SOL_DEPRECATED + +namespace sol { + namespace detail { + template + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; + } // detail +} // sol + +#endif // SOL_DEPRECATE_HPP diff --git a/3rdparty/sol2/sol/error.hpp b/3rdparty/sol2/sol/error.hpp new file mode 100644 index 00000000000..0458e0a5f65 --- /dev/null +++ b/3rdparty/sol2/sol/error.hpp @@ -0,0 +1,55 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_ERROR_HPP +#define SOL_ERROR_HPP + +#include +#include + +namespace sol { + namespace detail { + struct direct_error_tag {}; + const auto direct_error = direct_error_tag{}; + } // detail + + class error : public std::runtime_error { + private: + // Because VC++ is a fuccboi + std::string w; + public: + error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} + error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} + error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} + + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return w.c_str(); + } + }; + +} // sol + +#endif // SOL_ERROR_HPP diff --git a/3rdparty/sol2/sol/function.hpp b/3rdparty/sol2/sol/function.hpp new file mode 100644 index 00000000000..1ec9afb1104 --- /dev/null +++ b/3rdparty/sol2/sol/function.hpp @@ -0,0 +1,151 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_HPP +#define SOL_FUNCTION_HPP + +#include "reference.hpp" +#include "stack.hpp" +#include "function_result.hpp" +#include "function_types.hpp" +#include +#include +#include + +namespace sol { + template + class basic_function : public base_t { + private: + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { + lua_callk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), 0, nullptr); + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, lua_size>::value); + return stack::pop>(base_t::lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, lua_size::value); + return stack::pop(base_t::lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, 0); + } + + function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { + int stacksize = lua_gettop(base_t::lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(base_t::lua_state()); + int returncount = poststacksize - (firstreturn - 1); + return function_result(base_t::lua_state(), firstreturn, returncount); + } + + public: + basic_function() = default; + template , basic_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_function(const basic_function&) = default; + basic_function& operator=(const basic_function&) = default; + basic_function(basic_function&&) = default; + basic_function& operator=(basic_function&&) = default; + basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + template + function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) const { + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; + + namespace stack { + template + struct getter> { + typedef meta::bind_traits fx_t; + typedef typename fx_t::args_list args_lists; + typedef meta::tuple_types return_types; + + template + static std::function get_std_func(types, types, lua_State* L, int index) { + sol::function f(L, index); + auto fx = [f, L, index](Args&&... args) -> meta::return_type_t { + return f.call(std::forward(args)...); + }; + return std::move(fx); + } + + template + static std::function get_std_func(types, types, lua_State* L, int index) { + sol::function f(L, index); + auto fx = [f, L, index](FxArgs&&... args) -> void { + f(std::forward(args)...); + }; + return std::move(fx); + } + + template + static std::function get_std_func(types<>, types t, lua_State* L, int index) { + return get_std_func(types(), t, L, index); + } + + static std::function get(lua_State* L, int index, record& tracking) { + tracking.last = 1; + tracking.used += 1; + type t = type_of(L, index); + if (t == type::none || t == type::nil) { + return nullptr; + } + return get_std_func(return_types(), args_lists(), L, index); + } + }; + } // stack +} // sol + +#endif // SOL_FUNCTION_HPP diff --git a/3rdparty/sol2/sol/function_result.hpp b/3rdparty/sol2/sol/function_result.hpp new file mode 100644 index 00000000000..e7c0e6c1e99 --- /dev/null +++ b/3rdparty/sol2/sol/function_result.hpp @@ -0,0 +1,88 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_RESULT_HPP +#define SOL_FUNCTION_RESULT_HPP + +#include "reference.hpp" +#include "tuple.hpp" +#include "stack.hpp" +#include "proxy_base.hpp" +#include + +namespace sol { + struct function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + + public: + function_result() = default; + function_result(lua_State* L, int index = -1, int returncount = 0) : L(L), index(index), returncount(returncount) { + + } + function_result(const function_result&) = default; + function_result& operator=(const function_result&) = default; + function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + } + function_result& operator=(function_result&& o) { + L = o.L; + index = o.index; + returncount = o.returncount; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + return *this; + } + + template + decltype(auto) get() const { + return stack::get(L, index); + } + + call_status status() const noexcept { + return call_status::ok; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + + ~function_result() { + lua_pop(L, returncount); + } + }; +} // sol + +#endif // SOL_FUNCTION_RESULT_HPP diff --git a/3rdparty/sol2/sol/function_types.hpp b/3rdparty/sol2/sol/function_types.hpp new file mode 100644 index 00000000000..7c76b8d6ed0 --- /dev/null +++ b/3rdparty/sol2/sol/function_types.hpp @@ -0,0 +1,342 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_HPP +#define SOL_FUNCTION_TYPES_HPP + +#include "function_types_core.hpp" +#include "function_types_templated.hpp" +#include "function_types_stateless.hpp" +#include "function_types_stateful.hpp" +#include "function_types_overloaded.hpp" +#include "resolve.hpp" +#include "call.hpp" + +namespace sol { + namespace stack { + template + struct pusher> { + template + static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::functor_function F; + set_fx(L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { + using fx_ptr_t = R(*)(A...); + fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); + select_function(std::true_type(), L, fxptr, std::forward(args)...); + } + + template + static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::decay_t> raw_fx_t; + typedef R(*fx_ptr_t)(A...); + typedef std::is_convertible is_convertible; + select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { + typedef meta::function_signature_t> Sig; + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::member_variable, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t clean_fx; + typedef function_detail::member_function, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { + std::decay_t target(std::forward(fx), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_free_function::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, target); + stack::push(L, c_closure(freefunc, upvalues)); + } + + static void select_function(std::true_type, lua_State* L, lua_CFunction f) { + stack::push(L, f); + } + + template + static void select(lua_State* L, Fx&& fx, Args&&... args) { + select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void set_fx(lua_State* L, Args&&... args) { + lua_CFunction freefunc = function_detail::call>; + + stack::push>(L, std::forward(args)...); + stack::push(L, c_closure(freefunc, 1)); + } + + template + static int push(lua_State* L, Args&&... args) { + // Set will always place one thing (function) on the stack + select(L, std::forward(args)...); + return 1; + } + }; + + template + struct pusher> { + template + static int push_func(std::index_sequence, lua_State* L, FP&& fp) { + return stack::push(L, detail::forward_get(fp.arguments)...); + } + + static int push(lua_State* L, const function_arguments& fp) { + return push_func(std::make_index_sequence(), L, fp); + } + + static int push(lua_State* L, function_arguments&& fp) { + return push_func(std::make_index_sequence(), L, std::move(fp)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, std::function fx) { + return pusher>{}.push(L, std::move(fx)); + } + }; + + template + struct pusher::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; + + template + struct pusher, meta::neg>, meta::neg>>>::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, overload_set&& set) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, std::move(set.functions)); + return 1; + } + + static int push(lua_State* L, const overload_set& set) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, set.functions); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, protect_t&& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::move(pw.value)); + return stack::push(L, c_closure(cf, closures)); + } + + static int push(lua_State* L, const protect_t& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, pw.value); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher, std::enable_if_t::value && !std::is_void::value>> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, sol::overload(pw.read, pw.write)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.read)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.read); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.write)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.write); + } + }; + + template + struct pusher> { + static int push(lua_State* L, var_wrapper&& vw) { + return stack::push(L, std::move(vw.value)); + } + static int push(lua_State* L, const var_wrapper& vw) { + return stack::push(L, vw.value); + } + }; + + template + struct pusher> { + static int push(lua_State* L, const factory_wrapper& fw) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, fw.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper&& fw) { + typedef function_detail::overloaded_function F; + pusher>{}.set_fx(L, std::move(fw.functions)); + return 1; + } + }; + + template + struct pusher>> { + static int push(lua_State* L, detail::tagged>) { + lua_CFunction cf = call_detail::construct; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + template + static int push(lua_State* L, C&& c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::forward(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper) { + lua_CFunction cf = detail::usertype_alloc_destroy; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>(L, std::move(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + } // stack +} // sol + +#endif // SOL_FUNCTION_TYPES_HPP diff --git a/3rdparty/sol2/sol/function_types_core.hpp b/3rdparty/sol2/sol/function_types_core.hpp new file mode 100644 index 00000000000..24169ea7faf --- /dev/null +++ b/3rdparty/sol2/sol/function_types_core.hpp @@ -0,0 +1,39 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_CORE_HPP +#define SOL_FUNCTION_TYPES_CORE_HPP + +#include "stack.hpp" +#include "wrapper.hpp" +#include + +namespace sol { + namespace function_detail { + template + inline int call(lua_State* L) { + Fx& fx = stack::get>(L, upvalue_index(1)); + return fx(L); + } + } // function_detail +} // sol + +#endif // SOL_FUNCTION_TYPES_CORE_HPP diff --git a/3rdparty/sol2/sol/function_types_overloaded.hpp b/3rdparty/sol2/sol/function_types_overloaded.hpp new file mode 100644 index 00000000000..cfcfdebec68 --- /dev/null +++ b/3rdparty/sol2/sol/function_types_overloaded.hpp @@ -0,0 +1,59 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_OVERLOAD_HPP +#define SOL_FUNCTION_TYPES_OVERLOAD_HPP + +#include "overload.hpp" +#include "call.hpp" +#include "function_types_core.hpp" + +namespace sol { + namespace function_detail { + template + struct overloaded_function { + typedef std::tuple overload_list; + typedef std::make_index_sequence indices; + overload_list overloads; + + overloaded_function(overload_list set) + : overloads(std::move(set)) {} + + overloaded_function(Functions... fxs) + : overloads(fxs...) { + + } + + template + int call(types, index_value, types, types, lua_State* L, int, int) { + auto& func = std::get(overloads); + return call_detail::call_wrapped(L, func); + } + + int operator()(lua_State* L) { + auto mfx = [&](auto&&... args) { return this->call(std::forward(args)...); }; + return call_detail::overload_match(mfx, L, 1); + } + }; + } // function_detail +} // sol + +#endif // SOL_FUNCTION_TYPES_OVERLOAD_HPP \ No newline at end of file diff --git a/3rdparty/sol2/sol/function_types_stateful.hpp b/3rdparty/sol2/sol/function_types_stateful.hpp new file mode 100644 index 00000000000..6846ed87474 --- /dev/null +++ b/3rdparty/sol2/sol/function_types_stateful.hpp @@ -0,0 +1,103 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_STATEFUL_HPP +#define SOL_FUNCTION_TYPES_STATEFUL_HPP + +#include "function_types_core.hpp" + +namespace sol { + namespace function_detail { + template + struct functor_function { + typedef meta::unwrapped_t> Function; + typedef decltype(&Function::operator()) function_type; + typedef meta::function_return_t return_type; + typedef meta::function_args_t args_lists; + Function fx; + + template + functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} + + int call(lua_State* L) { + return call_detail::call_wrapped(L, fx); + } + + int operator()(lua_State* L) { + auto f = [&](lua_State* L) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + + template + struct member_function { + typedef std::remove_pointer_t> function_type; + typedef meta::function_return_t return_type; + typedef meta::function_args_t args_lists; + function_type invocation; + T member; + + template + member_function(function_type f, Args&&... args) : invocation(std::move(f)), member(std::forward(args)...) {} + + int call(lua_State* L) { + return call_detail::call_wrapped(L, invocation, detail::unwrap(detail::deref(member))); + } + + int operator()(lua_State* L) { + auto f = [&](lua_State* L) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + + template + struct member_variable { + typedef std::remove_pointer_t> function_type; + typedef typename meta::bind_traits::return_type return_type; + typedef typename meta::bind_traits::args_list args_lists; + function_type var; + T member; + typedef std::add_lvalue_reference_t>> M; + + template + member_variable(function_type v, Args&&... args) : var(std::move(v)), member(std::forward(args)...) {} + + int call(lua_State* L) { + M mem = detail::unwrap(detail::deref(member)); + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped(L, var, mem); + case 1: + return call_detail::call_wrapped(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + int operator()(lua_State* L) { + auto f = [&](lua_State* L) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + } // function_detail +} // sol + +#endif // SOL_FUNCTION_TYPES_STATEFUL_HPP diff --git a/3rdparty/sol2/sol/function_types_stateless.hpp b/3rdparty/sol2/sol/function_types_stateless.hpp new file mode 100644 index 00000000000..0b6e9072ddd --- /dev/null +++ b/3rdparty/sol2/sol/function_types_stateless.hpp @@ -0,0 +1,163 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_STATELESS_HPP +#define SOL_FUNCTION_TYPES_STATELESS_HPP + +#include "stack.hpp" + +namespace sol { + namespace function_detail { + template + struct upvalue_free_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + auto udata = stack::stack_detail::get_as_upvalues(L); + function_type* fx = udata.first; + return call_detail::call_wrapped(L, fx); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member function pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + function_type& memfx = memberdata.first; + auto& item = *objdata.first; + return call_detail::call_wrapped(L, memfx, item); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + auto& mem = *objdata.first; + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped(L, var, mem); + case 1: + return call_detail::call_wrapped(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_this_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& memfx = memberdata.first; + return call_detail::call_wrapped(L, memfx); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_this_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + return call_detail::call_wrapped(L, var); + case 2: + return call_detail::call_wrapped(L, var); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + } // function_detail +} // sol + +#endif // SOL_FUNCTION_TYPES_STATELESS_HPP diff --git a/3rdparty/sol2/sol/function_types_templated.hpp b/3rdparty/sol2/sol/function_types_templated.hpp new file mode 100644 index 00000000000..80989408ad8 --- /dev/null +++ b/3rdparty/sol2/sol/function_types_templated.hpp @@ -0,0 +1,132 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_FUNCTION_TYPES_TEMPLATED_HPP +#define SOL_FUNCTION_TYPES_TEMPLATED_HPP + +#include "call.hpp" + +namespace sol { + namespace function_detail { + template + inline int call_wrapper_variable(std::false_type, lua_State* L) { + typedef meta::bind_traits> traits_type; + typedef typename traits_type::args_list args_list; + typedef meta::tuple_types return_type; + return stack::call_into_lua(return_type(), args_list(), L, 1, fx); + } + + template + inline int call_set_assignable(std::false_type, T&&, lua_State* L) { + return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); + } + + template + inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { + (mem.*variable) = stack::get(L, 2); + return 0; + } + + template + inline int call_set_variable(std::false_type, lua_State* L, T&&) { + return luaL_error(L, "cannot write to a const variable"); + } + + template + inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { + return call_set_assignable(std::is_assignable, R>(), L, std::forward(mem)); + } + + template + inline int call_wrapper_variable(std::true_type, lua_State* L) { + typedef meta::bind_traits> traits_type; + typedef typename traits_type::object_type T; + typedef typename traits_type::return_type R; + auto& mem = stack::get(L, 1); + switch (lua_gettop(L)) { + case 1: { + decltype(auto) r = (mem.*variable); + stack::push_reference(L, std::forward(r)); + return 1; } + case 2: + return call_set_variable(meta::neg>(), L, mem); + default: + return luaL_error(L, "incorrect number of arguments to member variable function call"); + } + } + + template + inline int call_wrapper_function(std::false_type, lua_State* L) { + return call_wrapper_variable(std::is_member_object_pointer(), L); + } + + template + inline int call_wrapper_function(std::true_type, lua_State* L) { + return call_detail::call_wrapped(L, fx); + } + + template + int call_wrapper_entry(lua_State* L) { + return call_wrapper_function(std::is_member_function_pointer>(), L); + } + + template + struct c_call_matcher { + template + int operator()(types, index_value, types, types, lua_State* L, int, int) const { + typedef meta::at_in_pack_t target; + return target::call(L); + } + }; + + } // function_detail + + template + inline int c_call(lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, function_detail::call_wrapper_entry); +#else + return detail::static_trampoline<(&function_detail::call_wrapper_entry)>(L); +#endif // fuck you clang :c + } + + template + struct wrap { + typedef F type; + + static int call(lua_State* L) { + return c_call(L); + } + }; + + template + inline int c_call(lua_State* L) { + if (sizeof...(Fxs) < 2) { + return meta::at_in_pack_t<0, Fxs...>::call(L); + } + else { + return call_detail::overload_match_arity(function_detail::c_call_matcher(), L, lua_gettop(L), 1); + } + } + +} // sol + +#endif // SOL_FUNCTION_TYPES_TEMPLATED_HPP diff --git a/3rdparty/sol2/sol/in_place.hpp b/3rdparty/sol2/sol/in_place.hpp new file mode 100644 index 00000000000..2410fb96791 --- /dev/null +++ b/3rdparty/sol2/sol/in_place.hpp @@ -0,0 +1,50 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_IN_PLACE_HPP +#define SOL_IN_PLACE_HPP + +namespace sol { + + namespace detail { + struct in_place_of {}; + template + struct in_place_of_i {}; + template + struct in_place_of_t {}; + } // detail + + struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; }; + constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); } + template + constexpr inline in_place_tag in_place(detail::in_place_of_t) { return in_place_tag(in_place_tag::init()); } + template + constexpr inline in_place_tag in_place(detail::in_place_of_i) { return in_place_tag(in_place_tag::init()); } + + using in_place_t = in_place_tag(&)(detail::in_place_of); + template + using in_place_type_t = in_place_tag(&)(detail::in_place_of_t); + template + using in_place_index_t = in_place_tag(&)(detail::in_place_of_i); + +} // sol + +#endif // SOL_IN_PLACE_HPP diff --git a/3rdparty/sol2/sol/inheritance.hpp b/3rdparty/sol2/sol/inheritance.hpp new file mode 100644 index 00000000000..f2583495bc4 --- /dev/null +++ b/3rdparty/sol2/sol/inheritance.hpp @@ -0,0 +1,117 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_INHERITANCE_HPP +#define SOL_INHERITANCE_HPP + +#include "types.hpp" +#include + +namespace sol { + template + struct base_list { }; + template + using bases = base_list; + + typedef bases<> base_classes_tag; + const auto base_classes = base_classes_tag(); + + namespace detail { + + template + struct has_derived { + static bool value; + }; + + template + bool has_derived::value = false; + + inline std::size_t unique_id() { + static std::atomic x(0); + return ++x; + } + + template + struct id_for { + static const std::size_t value; + }; + + template + const std::size_t id_for::value = unique_id(); + + inline decltype(auto) base_class_check_key() { + static const auto& key = "class_check"; + return key; + } + + inline decltype(auto) base_class_cast_key() { + static const auto& key = "class_cast"; + return key; + } + + inline decltype(auto) base_class_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; + return key; + } + + inline decltype(auto) base_class_new_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; + return key; + } + + template + struct inheritance { + static bool type_check_bases(types<>, std::size_t) { + return false; + } + + template + static bool type_check_bases(types, std::size_t ti) { + return ti == id_for::value || type_check_bases(types(), ti); + } + + static bool type_check(std::size_t ti) { + return ti == id_for::value || type_check_bases(types(), ti); + } + + static void* type_cast_bases(types<>, T*, std::size_t) { + return nullptr; + } + + template + static void* type_cast_bases(types, T* data, std::size_t ti) { + // Make sure to convert to T first, and then dynamic cast to the proper type + return ti != id_for::value ? type_cast_bases(types(), data, ti) : static_cast(static_cast(data)); + } + + static void* type_cast(void* voiddata, std::size_t ti) { + T* data = static_cast(voiddata); + return static_cast(ti != id_for::value ? type_cast_bases(types(), data, ti) : data); + } + }; + + using inheritance_check_function = decltype(&inheritance::type_check); + using inheritance_cast_function = decltype(&inheritance::type_cast); + + } // detail +} // sol + +#endif // SOL_INHERITANCE_HPP diff --git a/3rdparty/sol2/sol/load_result.hpp b/3rdparty/sol2/sol/load_result.hpp new file mode 100644 index 00000000000..1a91cc6f3dc --- /dev/null +++ b/3rdparty/sol2/sol/load_result.hpp @@ -0,0 +1,139 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_LOAD_RESULT_HPP +#define SOL_LOAD_RESULT_HPP + +#include "stack.hpp" +#include "function.hpp" +#include "proxy_base.hpp" +#include + +namespace sol { + struct load_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + int popcount; + load_status err; + + template + decltype(auto) tagged_get(types>) const { + if (!valid()) { + return sol::optional(nullopt); + } + return stack::get>(L, index); + } + + template + decltype(auto) tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (!valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return stack::get(L, index); + } + + sol::optional tagged_get(types>) const { + if (valid()) { + return nullopt; + } + return sol::error(detail::direct_error, stack::get(L, index)); + } + + sol::error tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return sol::error(detail::direct_error, stack::get(L, index)); + } + + public: + load_result() = default; + load_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, load_status err = load_status::ok) noexcept : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { + + } + load_result(const load_result&) = default; + load_result& operator=(const load_result&) = default; + load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + } + load_result& operator=(load_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + return *this; + } + + load_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == load_status::ok; + } + + template + T get() const { + return tagged_get(types>()); + } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; + + ~load_result() { + stack::remove(L, index, popcount); + } + }; +} // sol + +#endif // SOL_LOAD_RESULT_HPP diff --git a/3rdparty/sol2/sol/object.hpp b/3rdparty/sol2/sol/object.hpp new file mode 100644 index 00000000000..42b46f9c41e --- /dev/null +++ b/3rdparty/sol2/sol/object.hpp @@ -0,0 +1,152 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_OBJECT_HPP +#define SOL_OBJECT_HPP + +#include "optional.hpp" +#include "reference.hpp" +#include "stack.hpp" +#include "userdata.hpp" +#include "variadic_args.hpp" + +namespace sol { + + template ::value, typename T> + R make_reference(lua_State* L, T&& value) { + int backpedal = stack::push(L, std::forward(value)); + R r = stack::get(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template ::value, typename... Args> + R make_reference(lua_State* L, Args&&... args) { + int backpedal = stack::push(L, std::forward(args)...); + R r = stack::get(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template + class basic_object : public base_t { + private: + template + decltype(auto) as_stack(std::true_type) const { + return stack::get(base_t::lua_state(), base_t::stack_index()); + } + + template + decltype(auto) as_stack(std::false_type) const { + base_t::push(); + return stack::pop(base_t::lua_state()); + } + + template + bool is_stack(std::true_type) const { + return stack::check(base_t::lua_state(), base_t::stack_index(), no_panic); + } + + template + bool is_stack(std::false_type) const { + auto pp = stack::push_pop(*this); + return stack::check(base_t::lua_state(), -1, no_panic); + } + + template + basic_object(std::integral_constant, lua_State* L, int index = -1) noexcept : base_t(L, index) { + if (invert_and_pop) { + lua_pop(L, -index); + } + } + + public: + basic_object() noexcept = default; + template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_object(T&& r) : base_t(std::forward(r)) {} + basic_object(nil_t r) : base_t(r) {} + basic_object(const basic_object&) = default; + basic_object(basic_object&&) = default; + basic_object& operator=(const basic_object&) = default; + basic_object& operator=(basic_object&&) = default; + basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } + basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } + basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} + basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} + template + basic_object(const proxy_base& r) noexcept : basic_object(r.operator basic_object()) {} + template + basic_object(proxy_base&& r) noexcept : basic_object(r.operator basic_object()) {} + template + basic_object& operator=(const proxy_base& r) { this->operator=(r.operator basic_object()); return *this; } + template + basic_object& operator=(proxy_base&& r) { this->operator=(r.operator basic_object()); return *this; } + basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} + template + basic_object(lua_State* L, in_place_type_t, Args&&... args) noexcept : basic_object(std::integral_constant::value>(), L, -stack::push(L, std::forward(args)...)) {} + template + basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place, std::forward(arg), std::forward(args)...) {} + + template + decltype(auto) as() const { + return as_stack(std::is_same()); + } + + template + bool is() const { + if (!base_t::valid()) + return false; + return is_stack(std::is_same()); + } + }; + + template + object make_object(lua_State* L, T&& value) { + return make_reference(L, std::forward(value)); + } + + template + object make_object(lua_State* L, Args&&... args) { + return make_reference(L, std::forward(args)...); + } + + inline bool operator==(const object& lhs, const nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const nil_t&, const object& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const object& lhs, const nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const nil_t&, const object& rhs) { + return rhs.valid(); + } +} // sol + +#endif // SOL_OBJECT_HPP diff --git a/3rdparty/sol2/sol/optional.hpp b/3rdparty/sol2/sol/optional.hpp new file mode 100644 index 00000000000..823bdc3d5c3 --- /dev/null +++ b/3rdparty/sol2/sol/optional.hpp @@ -0,0 +1,43 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_OPTIONAL_HPP +#define SOL_OPTIONAL_HPP + +#include "in_place.hpp" +#if defined(SOL_USE_BOOST) +#include +#else +#include "../Optional/optional.hpp" +#endif // Boost vs. Better optional + +namespace sol { + +#if defined(SOL_USE_BOOST) + template + using optional = boost::optional; + using nullopt_t = boost::none_t; + const nullopt_t nullopt = boost::none; +#endif // Boost vs. Better optional + +} // sol + +#endif // SOL_OPTIONAL_HPP diff --git a/3rdparty/sol2/sol/overload.hpp b/3rdparty/sol2/sol/overload.hpp new file mode 100644 index 00000000000..316a3322ba3 --- /dev/null +++ b/3rdparty/sol2/sol/overload.hpp @@ -0,0 +1,45 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_OVERLOAD_HPP +#define SOL_OVERLOAD_HPP + +#include + +namespace sol { + template + struct overload_set { + std::tuple functions; + template >> = meta::enabler> + overload_set (Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + overload_set(const overload_set&) = default; + overload_set(overload_set&&) = default; + overload_set& operator=(const overload_set&) = default; + overload_set& operator=(overload_set&&) = default; + }; + + template + decltype(auto) overload(Args&&... args) { + return overload_set...>(std::forward(args)...); + } +} + +#endif // SOL_OVERLOAD_HPP \ No newline at end of file diff --git a/3rdparty/sol2/sol/property.hpp b/3rdparty/sol2/sol/property.hpp new file mode 100644 index 00000000000..703cac925d2 --- /dev/null +++ b/3rdparty/sol2/sol/property.hpp @@ -0,0 +1,105 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_PROPERTY_HPP +#define SOL_PROPERTY_HPP + +namespace sol { + + struct no_prop { }; + + template + struct property_wrapper { + typedef std::integral_constant::value> can_read; + typedef std::integral_constant::value> can_write; + typedef std::conditional_t Read; + typedef std::conditional_t Write; + Read read; + Write write; + + template + property_wrapper(Rx&& r, Wx&& w) : read(std::forward(r)), write(std::forward(w)) {} + }; + + namespace property_detail { + template + inline decltype(auto) property(std::true_type, R&& read, W&& write) { + return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); + } + template + inline decltype(auto) property(std::false_type, W&& write, R&& read) { + return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); + } + template + inline decltype(auto) property(std::true_type, R&& read) { + return property_wrapper, void>(std::forward(read), no_prop()); + } + template + inline decltype(auto) property(std::false_type, W&& write) { + return property_wrapper>(no_prop(), std::forward(write)); + } + } // property_detail + + template + inline decltype(auto) property(F&& f, G&& g) { + typedef lua_bind_traits> left_traits; + typedef lua_bind_traits> right_traits; + return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward(f), std::forward(g)); + } + + template + inline decltype(auto) property(F&& f) { + typedef lua_bind_traits> left_traits; + return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward(f)); + } + + template + inline decltype(auto) readonly_property(F&& f) { + return property_detail::property(std::true_type(), std::forward(f)); + } + + // Allow someone to make a member variable readonly (const) + template + inline auto readonly(R T::* v) { + typedef const R C; + return static_cast(v); + } + + template + struct var_wrapper { + T value; + template + var_wrapper(Args&&... args) : value(std::forward(args)...) {} + var_wrapper(const var_wrapper&) = default; + var_wrapper(var_wrapper&&) = default; + var_wrapper& operator=(const var_wrapper&) = default; + var_wrapper& operator=(var_wrapper&&) = default; + }; + + template + inline auto var(V&& v) { + typedef meta::unqualified_t T; + return var_wrapper(std::forward(v)); + } + +} // sol + +#endif // SOL_PROPERTY_HPP diff --git a/3rdparty/sol2/sol/protect.hpp b/3rdparty/sol2/sol/protect.hpp new file mode 100644 index 00000000000..42655c6b74b --- /dev/null +++ b/3rdparty/sol2/sol/protect.hpp @@ -0,0 +1,51 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_PROTECT_HPP +#define SOL_PROTECT_HPP + +#include "traits.hpp" +#include + +namespace sol { + + template + struct protect_t { + T value; + + template >> = meta::enabler> + protect_t(Arg&& arg, Args&&... args) : value(std::forward(arg), std::forward(args)...) {} + + protect_t(const protect_t&) = default; + protect_t(protect_t&&) = default; + protect_t& operator=(const protect_t&) = default; + protect_t& operator=(protect_t&&) = default; + + }; + + template + auto protect(T&& value) { + return protect_t>(std::forward(value)); + } + +} // sol + +#endif // SOL_PROTECT_HPP diff --git a/3rdparty/sol2/sol/protected_function.hpp b/3rdparty/sol2/sol/protected_function.hpp new file mode 100644 index 00000000000..583a8dd931f --- /dev/null +++ b/3rdparty/sol2/sol/protected_function.hpp @@ -0,0 +1,190 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_PROTECTED_FUNCTION_HPP +#define SOL_PROTECTED_FUNCTION_HPP + +#include "reference.hpp" +#include "stack.hpp" +#include "protected_function_result.hpp" +#include +#include + +namespace sol { + namespace detail { + inline reference& handler_storage() { + static sol::reference h; + return h; + } + + struct handler { + const reference& target; + int stackindex; + handler(const reference& target) : target(target), stackindex(0) { + if (target.valid()) { + stackindex = lua_gettop(target.lua_state()) + 1; + target.push(); + } + } + bool valid() const { return stackindex != 0; } + ~handler() { + if (valid()) { + lua_remove(target.lua_state(), stackindex); + } + } + }; + } + + template + class basic_protected_function : public base_t { + public: + static reference& get_default_handler() { + return detail::handler_storage(); + } + + static void set_default_handler(const reference& ref) { + detail::handler_storage() = ref; + } + + static void set_default_handler(reference&& ref) { + detail::handler_storage() = std::move(ref); + } + + private: + call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler& h) const { + return static_cast(lua_pcallk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), h.stackindex, 0, nullptr)); + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, sizeof...(Ret), h); + return stack::pop>(base_t::lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, 1, h); + return stack::pop(base_t::lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, 0, h); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler& h) const { + int stacksize = lua_gettop(base_t::lua_state()); + int poststacksize = stacksize; + int firstreturn = 1; + int returncount = 0; + call_status code = call_status::ok; +#ifndef SOL_NO_EXCEPTIONS + auto onexcept = [&](const char* error) { + h.stackindex = 0; + if (h.target.valid()) { + h.target.push(); + stack::push(base_t::lua_state(), error); + lua_call(base_t::lua_state(), 1, 1); + } + else { + stack::push(base_t::lua_state(), error); + } + }; + try { +#endif // No Exceptions + firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid()))); + code = luacall(n, LUA_MULTRET, h); + poststacksize = lua_gettop(base_t::lua_state()) - static_cast(h.valid()); + returncount = poststacksize - (firstreturn - 1); +#ifndef SOL_NO_EXCEPTIONS + } + // Handle C++ errors thrown from C++ functions bound inside of lua + catch (const char* error) { + onexcept(error); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (const std::exception& error) { + onexcept(error.what()); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (...) { + onexcept("caught (...) unknown error during protected_function call"); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } +#endif // No Exceptions + return protected_function_result(base_t::lua_state(), firstreturn, returncount, returncount, code); + } + + public: + reference error_handler; + + basic_protected_function() = default; + template , basic_protected_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_protected_function(const basic_protected_function&) = default; + basic_protected_function& operator=(const basic_protected_function&) = default; + basic_protected_function(basic_protected_function&&) = default; + basic_protected_function& operator=(basic_protected_function&&) = default; + basic_protected_function(const basic_function& b, reference eh = get_default_handler()) : base_t(b), error_handler(std::move(eh)) {} + basic_protected_function(basic_function&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} + basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + template + basic_protected_function(proxy_base&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} + template + basic_protected_function(const proxy_base& p, reference eh = get_default_handler()) : basic_protected_function(static_cast>(p), std::move(eh)) {} + basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + template + protected_function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) const { + detail::handler h(error_handler); + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount, h); + } + }; +} // sol + +#endif // SOL_FUNCTION_HPP diff --git a/3rdparty/sol2/sol/protected_function_result.hpp b/3rdparty/sol2/sol/protected_function_result.hpp new file mode 100644 index 00000000000..bac0fc0fb62 --- /dev/null +++ b/3rdparty/sol2/sol/protected_function_result.hpp @@ -0,0 +1,130 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_PROTECTED_FUNCTION_RESULT_HPP +#define SOL_PROTECTED_FUNCTION_RESULT_HPP + +#include "reference.hpp" +#include "tuple.hpp" +#include "stack.hpp" +#include "proxy_base.hpp" +#include + +namespace sol { + struct protected_function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + int popcount; + call_status err; + + template + decltype(auto) tagged_get(types>) const { + if (!valid()) { + return sol::optional(nullopt); + } + return stack::get>(L, index); + } + + template + decltype(auto) tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (!valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return stack::get(L, index); + } + + optional tagged_get(types>) const { + if (valid()) { + return nullopt; + } + return error(detail::direct_error, stack::get(L, index)); + } + + error tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return error(detail::direct_error, stack::get(L, index)); + } + + public: + protected_function_result() = default; + protected_function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_status err = call_status::ok) noexcept : L(L), index(index), returncount(returncount), popcount(popcount), err(err) { + + } + protected_function_result(const protected_function_result&) = default; + protected_function_result& operator=(const protected_function_result&) = default; + protected_function_result(protected_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = call_status::runtime; + } + protected_function_result& operator=(protected_function_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = call_status::runtime; + return *this; + } + + call_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + template + decltype(auto) get() const { + return tagged_get(types>()); + } + + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; + + ~protected_function_result() { + stack::remove(L, index, popcount); + } + }; +} // sol + +#endif // SOL_PROTECTED_FUNCTION_RESULT_HPP diff --git a/3rdparty/sol2/sol/proxy.hpp b/3rdparty/sol2/sol/proxy.hpp new file mode 100644 index 00000000000..22247a8d818 --- /dev/null +++ b/3rdparty/sol2/sol/proxy.hpp @@ -0,0 +1,175 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_PROXY_HPP +#define SOL_PROXY_HPP + +#include "traits.hpp" +#include "object.hpp" +#include "function.hpp" +#include "protected_function.hpp" +#include "proxy_base.hpp" + +namespace sol { + template + struct proxy : public proxy_base> { + private: + typedef meta::condition, Key, std::tuple>, Key&, meta::unqualified_t>>> key_type; + + template + decltype(auto) tuple_get(std::index_sequence) const { + return tbl.template traverse_get(std::get(key)...); + } + + template + void tuple_set(std::index_sequence, T&& value) { + tbl.traverse_set(std::get(key)..., std::forward(value)); + } + + public: + Table tbl; + key_type key; + + template + proxy(Table table, T&& key) : tbl(table), key(std::forward(key)) {} + + template + proxy& set(T&& item) { + tuple_set(std::make_index_sequence>::value>(), std::forward(item)); + return *this; + } + + template + proxy& set_function(Args&&... args) { + tbl.set_function(key, std::forward(args)...); + return *this; + } + + template>>, meta::is_callable>> = meta::enabler> + proxy& operator=(U&& other) { + return set_function(std::forward(other)); + } + + template>>, meta::is_callable>> = meta::enabler> + proxy& operator=(U&& other) { + return set(std::forward(other)); + } + + template + decltype(auto) get() const { + return tuple_get(std::make_index_sequence>::value>()); + } + + template + decltype(auto) get_or(T&& otherwise) const { + typedef decltype(get()) U; + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) operator[](K&& k) const { + auto keys = meta::tuplefy(key, std::forward(k)); + return proxy(tbl, std::move(keys)); + } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + bool valid() const { + stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); + lua_pop(tbl.lua_state(), p.levels); + return p; + } + }; + + template + inline bool operator==(T&& left, const proxy& right) { + return left == right.template get>(); + } + + template + inline bool operator==(const proxy& right, T&& left) { + return right.template get>() == left; + } + + template + inline bool operator!=(T&& left, const proxy& right) { + return right.template get>() != left; + } + + template + inline bool operator!=(const proxy& right, T&& left) { + return right.template get>() != left; + } + + template + inline bool operator==(nil_t, const proxy& right) { + return !right.valid(); + } + + template + inline bool operator==(const proxy& right, nil_t) { + return !right.valid(); + } + + template + inline bool operator!=(nil_t, const proxy& right) { + return right.valid(); + } + + template + inline bool operator!=(const proxy& right, nil_t) { + return right.valid(); + } + + namespace stack { + template + struct pusher> { + static int push(lua_State*, const proxy& p) { + sol::reference r = p; + return r.push(); + } + }; + } // stack +} // sol + +#endif // SOL_PROXY_HPP diff --git a/3rdparty/sol2/sol/proxy_base.hpp b/3rdparty/sol2/sol/proxy_base.hpp new file mode 100644 index 00000000000..959f6e6b281 --- /dev/null +++ b/3rdparty/sol2/sol/proxy_base.hpp @@ -0,0 +1,51 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_PROXY_BASE_HPP +#define SOL_PROXY_BASE_HPP + +#include "reference.hpp" +#include "tuple.hpp" +#include "stack.hpp" + +namespace sol { + template + struct proxy_base { + operator std::string() const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + + template>, is_proxy_primitive>> = meta::enabler> + operator T () const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + + template>, meta::neg>>> = meta::enabler> + operator T& () const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + }; +} // sol + +#endif // SOL_PROXY_BASE_HPP diff --git a/3rdparty/sol2/sol/raii.hpp b/3rdparty/sol2/sol/raii.hpp new file mode 100644 index 00000000000..c7b20a69613 --- /dev/null +++ b/3rdparty/sol2/sol/raii.hpp @@ -0,0 +1,132 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_RAII_HPP +#define SOL_RAII_HPP + +#include +#include "traits.hpp" + +namespace sol { + namespace detail { + struct default_construct { + template + static void construct(T&& obj, Args&&... args) { + std::allocator> alloc{}; + alloc.construct(obj, std::forward(args)...); + } + + template + void operator()(T&& obj, Args&&... args) const { + construct(std::forward(obj), std::forward(args)...); + } + }; + + struct default_destruct { + template + static void destroy(T&& obj) { + std::allocator> alloc{}; + alloc.destroy(obj); + } + + template + void operator()(T&& obj) const { + destroy(std::forward(obj)); + } + }; + + struct deleter { + template + void operator()(T* p) const { + delete p; + } + }; + + template + inline std::unique_ptr make_unique_deleter(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } + + template + struct tagged { + T value; + template , tagged>> = meta::enabler> + tagged(Arg&& arg, Args&&... args) : value(std::forward(arg), std::forward(args)...) {} + }; + } // detail + + template + struct constructor_list {}; + + template + using constructors = constructor_list; + + const auto default_constructor = constructors>{}; + + struct no_construction {}; + const auto no_constructor = no_construction{}; + + struct call_construction {}; + const auto call_constructor = call_construction{}; + + template + struct constructor_wrapper { + std::tuple functions; + template , constructor_wrapper>> = meta::enabler> + constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + }; + + template + inline auto initializers(Functions&&... functions) { + return constructor_wrapper...>(std::forward(functions)...); + } + + template + struct factory_wrapper { + std::tuple functions; + template , factory_wrapper>> = meta::enabler> + factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + }; + + template + inline auto factories(Functions&&... functions) { + return factory_wrapper...>(std::forward(functions)...); + } + + template + struct destructor_wrapper { + Function fx; + destructor_wrapper(Function f) : fx(std::move(f)) {} + }; + + template <> + struct destructor_wrapper {}; + + const destructor_wrapper default_destructor{}; + + template + inline auto destructor(Fx&& fx) { + return destructor_wrapper>(std::forward(fx)); + } + +} // sol + +#endif // SOL_RAII_HPP diff --git a/3rdparty/sol2/sol/reference.hpp b/3rdparty/sol2/sol/reference.hpp new file mode 100644 index 00000000000..c7c9d823d59 --- /dev/null +++ b/3rdparty/sol2/sol/reference.hpp @@ -0,0 +1,174 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_REFERENCE_HPP +#define SOL_REFERENCE_HPP + +#include "types.hpp" +#include "stack_reference.hpp" + +namespace sol { + namespace stack { + template + struct push_popper_n { + lua_State* L; + int t; + push_popper_n(lua_State* L, int x) : L(L), t(x) { } + ~push_popper_n() { lua_pop(L, t); } + }; + template <> + struct push_popper_n { + push_popper_n(lua_State*, int) { } + }; + template + struct push_popper { + T t; + push_popper(T x) : t(x) { t.push(); } + ~push_popper() { t.pop(); } + }; + template + struct push_popper { + push_popper(T) {} + ~push_popper() {} + }; + template + push_popper push_pop(T&& x) { + return push_popper(std::forward(x)); + } + template + push_popper_n pop_n(lua_State* L, int x) { + return push_popper_n(L, x); + } + } // stack + + namespace detail { + struct global_tag { } const global_{}; + } // detail + + class reference { + private: + lua_State* L = nullptr; // non-owning + int ref = LUA_NOREF; + + int copy() const noexcept { + if (ref == LUA_NOREF) + return LUA_NOREF; + push(); + return luaL_ref(L, LUA_REGISTRYINDEX); + } + + protected: + reference(lua_State* L, detail::global_tag) noexcept : L(L) { + lua_pushglobaltable(L); + ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + int stack_index() const noexcept { + return -1; + } + + public: + reference() noexcept = default; + reference(nil_t) noexcept : reference() {} + reference(const stack_reference& r) noexcept : reference(r.lua_state(), r.stack_index()) {} + reference(stack_reference&& r) noexcept : reference(r.lua_state(), r.stack_index()) {} + reference(lua_State* L, int index = -1) noexcept : L(L) { + lua_pushvalue(L, index); + ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + virtual ~reference() noexcept { + luaL_unref(L, LUA_REGISTRYINDEX, ref); + } + + reference(reference&& o) noexcept { + L = o.L; + ref = o.ref; + + o.L = nullptr; + o.ref = LUA_NOREF; + } + + reference& operator=(reference&& o) noexcept { + L = o.L; + ref = o.ref; + + o.L = nullptr; + o.ref = LUA_NOREF; + + return *this; + } + + reference(const reference& o) noexcept { + L = o.L; + ref = o.copy(); + } + + reference& operator=(const reference& o) noexcept { + L = o.L; + ref = o.copy(); + return *this; + } + + int push() const noexcept { + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + return 1; + } + + void pop(int n = 1) const noexcept { + lua_pop(lua_state(), n); + } + + int registry_index() const noexcept { + return ref; + } + + bool valid() const noexcept { + return !(ref == LUA_NOREF || ref == LUA_REFNIL); + } + + explicit operator bool() const noexcept { + return valid(); + } + + type get_type() const noexcept { + auto pp = stack::push_pop(*this); + int result = lua_type(L, -1); + return static_cast(result); + } + + lua_State* lua_state() const noexcept { + return L; + } + }; + + inline bool operator== (const reference& l, const reference& r) { + auto ppl = stack::push_pop(l); + auto ppr = stack::push_pop(r); + return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; + } + + inline bool operator!= (const reference& l, const reference& r) { + return !operator==(l, r); + } +} // sol + +#endif // SOL_REFERENCE_HPP diff --git a/3rdparty/sol2/sol/resolve.hpp b/3rdparty/sol2/sol/resolve.hpp new file mode 100644 index 00000000000..7445a8150a9 --- /dev/null +++ b/3rdparty/sol2/sol/resolve.hpp @@ -0,0 +1,96 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_RESOLVE_HPP +#define SOL_RESOLVE_HPP + +#include "traits.hpp" +#include "tuple.hpp" + +namespace sol { + namespace detail { + template(Args...)>> + inline auto resolve_i(types, F&&)->R(meta::unqualified_t::*)(Args...) { + using Sig = R(Args...); + typedef meta::unqualified_t Fu; + return static_cast(&Fu::operator()); + } + + template> + inline auto resolve_f(std::true_type, F&& f) + -> decltype(resolve_i(types>(), std::forward(f))) { + return resolve_i(types>(), std::forward(f)); + } + + template + inline void resolve_f(std::false_type, F&&) { + static_assert(meta::has_deducible_signature::value, + "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + } + + template> + inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature(), std::forward(f))) { + return resolve_f(meta::has_deducible_signature {}, std::forward(f)); + } + + template> + inline auto resolve_i(types, F&& f) -> decltype(resolve_i(types(), std::forward(f))) { + return resolve_i(types(), std::forward(f)); + } + + template + inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { + return mem_func_ptr; + } + + template + inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { + return mem_variable_ptr; + } + } // detail + + template + inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) { + return fun_ptr; + } + + template + inline Sig* resolve(Sig* fun_ptr) { + return fun_ptr; + } + + template + inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { + return mem_ptr; + } + + template + inline Sig C::* resolve(Sig C::* mem_ptr) { + return detail::resolve_v(std::is_member_object_pointer(), mem_ptr); + } + + template + inline auto resolve(F&& f) -> decltype(detail::resolve_i(types(), std::forward(f))) { + return detail::resolve_i(types(), std::forward(f)); + } +} // sol + +#endif // SOL_RESOLVE_HPP diff --git a/3rdparty/sol2/sol/simple_usertype_metatable.hpp b/3rdparty/sol2/sol/simple_usertype_metatable.hpp new file mode 100644 index 00000000000..586e0d18527 --- /dev/null +++ b/3rdparty/sol2/sol/simple_usertype_metatable.hpp @@ -0,0 +1,494 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_SIMPLE_USERTYPE_METATABLE_HPP +#define SOL_SIMPLE_USERTYPE_METATABLE_HPP + +#include "usertype_metatable.hpp" +#include "object.hpp" +#include +#include +#include + +namespace sol { + + namespace usertype_detail { + struct variable_wrapper { + virtual int index(lua_State* L) = 0; + virtual int new_index(lua_State* L) = 0; + virtual ~variable_wrapper() {}; + }; + + template + struct callable_binding : variable_wrapper { + F fx; + + template + callable_binding(Arg&& arg) : fx(std::forward(arg)) {} + + virtual int index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + + virtual int new_index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + }; + + typedef std::unordered_map> variable_map; + typedef std::unordered_map function_map; + + struct simple_map { + const char* metakey; + variable_map variables; + function_map functions; + base_walk indexbaseclasspropogation; + base_walk newindexbaseclasspropogation; + + simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} + }; + + template + inline int simple_metatable_newindex(lua_State* L) { + if (stack::stack_detail::check_metatable(L, 1)) { + stack::set_field(L, stack_reference(L, 2), stack_reference(L, 3), 1); + lua_settop(L, 0); + return 0; + } + lua_pop(L, 1); + return indexing_fail(L); + } + + template + inline int simple_core_indexing_call(lua_State* L) { + simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + variable_map& variables = sm.variables; + function_map& functions = sm.functions; + static const int keyidx = -2 + static_cast(is_index); + if (toplevel) { + if (stack::get(L, keyidx) != type::string) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + } + string_detail::string_shim accessor = stack::get(L, keyidx); + std::string accessorkey = accessor.c_str(); + auto vit = variables.find(accessorkey); + if (vit != variables.cend()) { + auto& varwrap = *(vit->second); + if (is_index) { + return varwrap.index(L); + } + return varwrap.new_index(L); + } + auto fit = functions.find(accessorkey); + if (fit != functions.cend()) { + auto& func = (fit->second); + return stack::push(L, func); + } + // Check table storage first for a method that works + luaL_getmetatable(L, sm.metakey); + if (type_of(L, -1) != type::nil) { + stack::get_field(L, accessor.c_str(), lua_gettop(L)); + if (type_of(L, -1) != type::nil) { + // Woo, we found it? + lua_remove(L, -2); + return 1; + } + lua_pop(L, 1); + } + lua_pop(L, 1); + + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) { + sm.indexbaseclasspropogation(L, found, ret, accessor); + } + else { + sm.newindexbaseclasspropogation(L, found, ret, accessor); + } + if (found) { + return ret; + } + if (toplevel) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + return -1; + } + + inline int simple_real_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + inline int simple_real_new_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + inline int simple_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_index_call)>(L); + } + + inline int simple_new_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_new_index_call)>(L); + } + } + + struct simple_tag {} const simple{}; + + template + struct simple_usertype_metatable : usertype_detail::registrar { + public: + usertype_detail::function_map registrations; + usertype_detail::variable_map varmap; + object callconstructfunc; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool mustindex; + bool secondarymeta; + + template + void insert(N&& n, object&& o) { + std::string key = usertype_detail::make_string(std::forward(n)); + auto hint = registrations.find(key); + if (hint == registrations.cend()) { + registrations.emplace_hint(hint, std::move(key), std::move(o)); + return; + } + hint->second = std::move(o); + } + + template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + insert(std::forward(n), make_object(L, as_function_reference(std::forward(f)))); + } + + template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + object o = make_object(L, std::forward(f)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template >> = meta::enabler> + void add(lua_State* L, N&& n, F&& f) { + add_function(L, std::forward(n), std::forward(f)); + } + + template >> = meta::enabler> + void add(lua_State*, N&& n, F&& f) { + mustindex = true; + secondarymeta = true; + std::string key = usertype_detail::make_string(std::forward(n)); + auto o = std::make_unique>>(std::forward(f)); + auto hint = varmap.find(key); + if (hint == varmap.cend()) { + varmap.emplace_hint(hint, std::move(key), std::move(o)); + return; + } + hint->second = std::move(o); + } + + template + void add(lua_State* L, N&& n, constructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, constructor_list c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, destructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, destructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State*, base_classes_tag, bases) { + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform"); + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::value = true), 0)... }; + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + + private: + template + simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) + : callconstructfunc(nil), + indexfunc(&usertype_detail::indexing_fail), newindexfunc(&usertype_detail::simple_metatable_newindex), + indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + mustindex(true), secondarymeta(true) { + (void)detail::swallow{ 0, + (add(L, detail::forward_get(args), detail::forward_get(args)),0)... + }; + } + + template + simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence(), L, std::forward_as_tuple(std::forward(args)...)) {} + + template + simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward(args)..., "__gc", default_destructor) {} + + template + simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition, meta::neg>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward(args)...) {} + + public: + simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(L, meta::condition>, decltype(default_constructor), usertype_detail::check_destructor_tag>()) {} + + template, + usertype_detail::verified_tag, + usertype_detail::add_destructor_tag, + usertype_detail::check_destructor_tag + >, + meta::is_specialization_of>, + meta::is_specialization_of> + > = meta::enabler> + simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition, meta::neg>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward(arg), std::forward(args)...) {} + + template + simple_usertype_metatable(lua_State* L, constructors constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + simple_usertype_metatable(lua_State* L, constructor_wrapper constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + virtual int push_um(lua_State* L) override { + return stack::push(L, std::move(*this)); + } + }; + + namespace stack { + template + struct pusher> { + typedef simple_usertype_metatable umt_t; + + static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable; + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table[0]; + stack::push>(L, metatable_key, uniquegcmetakey, &usertype_traits::metatable[0], umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, std::move(umx.varmap), std::move(umx.registrations)); + stack_reference stackvarmap(L, -1); + stack::set_field(L, gcmetakey, stackvarmap); + stackvarmap.pop(); + + stack::get_field(L, gcmetakey); + usertype_detail::simple_map& varmap = stack::pop>(L); + return varmap; + } + + static int push(lua_State* L, umt_t&& umx) { + auto& varmap = make_cleanup(L, umx); + bool hasequals = false; + bool hasless = false; + bool haslessequals = false; + for (std::size_t i = 0; i < 3; ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable[0]; + break; + case 1: + metakey = &usertype_traits>::metatable[0]; + break; + case 2: + default: + metakey = &usertype_traits::metatable[0]; + break; + } + luaL_newmetatable(L, metakey); + stack_reference t(L, -1); + for (auto& kvp : varmap.functions) { + auto& first = std::get<0>(kvp); + auto& second = std::get<1>(kvp); + if (first == name_of(meta_function::equal_to)) { + hasequals = true; + } + else if (first == name_of(meta_function::less_than)) { + hasless = true; + } + else if (first == name_of(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + else if (first == name_of(meta_function::index)) { + umx.indexfunc = second.template as(); + } + else if (first == name_of(meta_function::new_index)) { + umx.newindexfunc = second.template as(); + } + switch (i) { + case 0: + if (first == name_of(meta_function::garbage_collect)) { + continue; + } + break; + case 1: + if (first == name_of(meta_function::garbage_collect)) { + stack::set_field(L, first, detail::unique_destruct, t.stack_index()); + continue; + } + break; + case 2: + default: + break; + } + stack::set_field(L, first, second, t.stack_index()); + } + luaL_Reg opregs[4]{}; + int opregsindex = 0; + if (!hasless) { + const char* name = name_of(meta_function::less_than).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less>(opregs, opregsindex, name); + } + if (!haslessequals) { + const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less_equal>(opregs, opregsindex, name); + } + if (!hasequals) { + const char* name = name_of(meta_function::equal_to).c_str(); + usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); + } + t.push(); + luaL_setfuncs(L, opregs, 0); + t.pop(); + + if (umx.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); + } + if (umx.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); + } + + // Base class propagation features + stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); + + if (umx.mustindex) { + // use indexing function + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "The size of this data pointer is too small to fit the base class index propagation key: file a bug report."); + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), t.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), t.stack_index()); + } + else { + // Metatable indexes itself + stack::set_field(L, meta_function::index, t, t.stack_index()); + } + // metatable on the metatable + // for call constructor purposes and such + lua_createtable(L, 0, 1); + stack_reference metabehind(L, -1); + if (umx.callconstructfunc.valid()) { + stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); + } + if (umx.secondarymeta) { + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), metabehind.stack_index()); + } + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + + if (i < 2) + t.pop(); + } + return 1; + } + }; + } // stack +} // sol + +#endif // SOL_SIMPLE_USERTYPE_METATABLE_HPP diff --git a/3rdparty/sol2/sol/stack.hpp b/3rdparty/sol2/sol/stack.hpp new file mode 100644 index 00000000000..f612d483f82 --- /dev/null +++ b/3rdparty/sol2/sol/stack.hpp @@ -0,0 +1,226 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_HPP +#define SOL_STACK_HPP + +#include "stack_core.hpp" +#include "stack_reference.hpp" +#include "stack_check.hpp" +#include "stack_get.hpp" +#include "stack_check_get.hpp" +#include "stack_push.hpp" +#include "stack_pop.hpp" +#include "stack_field.hpp" +#include "stack_probe.hpp" +#include +#include + +namespace sol { + namespace stack { + namespace stack_detail { + template + inline int push_as_upvalues(lua_State* L, T& item) { + typedef std::decay_t TValue; + const static std::size_t itemsize = sizeof(TValue); + const static std::size_t voidsize = sizeof(void*); + const static std::size_t voidsizem1 = voidsize - 1; + const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; + typedef std::array data_t; + + data_t data{ {} }; + std::memcpy(&data[0], std::addressof(item), itemsize); + int pushcount = 0; + for (auto&& v : data) { + pushcount += push(L, lightuserdata_value(v)); + } + return pushcount; + } + + template + inline std::pair get_as_upvalues(lua_State* L, int index = 1) { + const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); + typedef std::array data_t; + data_t voiddata{ {} }; + for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { + voiddata[i] = get(L, upvalue_index(index++)); + } + return std::pair(*reinterpret_cast(static_cast(voiddata.data())), index); + } + + struct evaluator { + template + static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) { + return std::forward(fx)(std::forward(args)...); + } + + template + static decltype(auto) eval(types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { + return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); + } + }; + + template ::value>> + inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { +#ifndef _MSC_VER + static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); +#endif // This compiler make me so fucking sad + multi_check(L, start, type_panic); + record tracking{}; + return evaluator{}.eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { +#ifndef _MSC_VER + static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); +#endif // This compiler make me so fucking sad + multi_check(L, start, type_panic); + record tracking{}; + evaluator{}.eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + } // stack_detail + + template + int set_ref(lua_State* L, T&& arg, int tableindex = -2) { + push(L, std::forward(arg)); + return luaL_ref(L, tableindex); + } + + inline void remove(lua_State* L, int index, int count) { + if (count < 1) + return; + int top = lua_gettop(L); + if (index == -1 || top == index) { + // Slice them right off the top + lua_pop(L, static_cast(count)); + return; + } + + // Remove each item one at a time using stack operations + // Probably slower, maybe, haven't benchmarked, + // but necessary + if (index < 0) { + index = lua_gettop(L) + (index + 1); + } + int last = index + count; + for (int i = index; i < last; ++i) { + lua_remove(L, i); + } + } + + template ::value>> + inline decltype(auto) call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + typedef std::make_index_sequence args_indices; + return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + + template ::value>> + inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + typedef std::make_index_sequence args_indices; + stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + + template ::value>> + inline decltype(auto) call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + return call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); + } + + template + inline void call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); + } + + template + inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); + lua_settop(L, 0); + return 0; + } + + template>::value>> + inline int call_into_lua(types, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + lua_settop(L, 0); + return push_reference(L, std::forward(r)); + } + + template + inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + typedef lua_bind_traits> traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::returns_list returns_list; + return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); + } + + inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) { + luaL_getmetatable(L, key.c_str()); + auto pn = pop_n(L, 1); + if (lua_compare(L, -1, index, LUA_OPEQ) == 1) { + return call_syntax::colon; + } + return call_syntax::dot; + } + + inline void script(lua_State* L, const std::string& code) { + if (luaL_dostring(L, code.c_str())) { + lua_error(L); + } + } + + inline void script_file(lua_State* L, const std::string& filename) { + if (luaL_dofile(L, filename.c_str())) { + lua_error(L); + } + } + + inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { +#ifdef SOL_LUAJIT + lua_pushlightuserdata(L, (void*)handler); + auto pn = pop_n(L, 1); + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); +#else + (void)L; + (void)handler; +#endif + } + + inline void luajit_exception_off(lua_State* L) { +#ifdef SOL_LUAJIT + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); +#else + (void)L; +#endif + } + } // stack +} // sol + +#endif // SOL_STACK_HPP diff --git a/3rdparty/sol2/sol/stack_check.hpp b/3rdparty/sol2/sol/stack_check.hpp new file mode 100644 index 00000000000..bf9faa1ed52 --- /dev/null +++ b/3rdparty/sol2/sol/stack_check.hpp @@ -0,0 +1,350 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_CHECK_HPP +#define SOL_STACK_CHECK_HPP + +#include "stack_core.hpp" +#include "usertype_traits.hpp" +#include "inheritance.hpp" +#include +#include +#include + +namespace sol { + namespace stack { + namespace stack_detail { + template + inline bool check_metatable(lua_State* L, int index = -2) { + const auto& metakey = usertype_traits::metatable; + luaL_getmetatable(L, &metakey[0]); + const type expectedmetatabletype = static_cast(lua_type(L, -1)); + if (expectedmetatabletype != type::nil) { + if (lua_rawequal(L, -1, index) == 1) { + lua_pop(L, 1 + static_cast(poptable)); + return true; + } + } + lua_pop(L, 1); + return false; + } + + template + struct basic_check { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = check_func(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, expected, type_of(L, index)); + } + return success; + } + }; + } // stack_detail + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + const type indextype = type_of(L, index); + bool success = expected == indextype; + if (!success) { + // expected type, actual type + handler(L, index, expected, indextype); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + bool success = lua_isnil(L, index); + if (success) { + tracking.use(1); + return success; + } + tracking.use(0); + success = lua_isnone(L, index); + if (!success) { + // expected type, actual type + handler(L, index, expected, type_of(L, index)); + } + return success; + } + }; + + template + struct checker : checker {}; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = !lua_isnone(L, index); + if (!success) { + // expected type, actual type + handler(L, index, type::none, type_of(L, index)); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + bool success = t == type::userdata || t == type::lightuserdata; + if (!success) { + // expected type, actual type + handler(L, index, type::lightuserdata, t); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + bool success = t == type::userdata; + if (!success) { + // expected type, actual type + handler(L, index, type::userdata, t); + } + return success; + } + }; + + template + struct checker, type::userdata, C> : checker, type::lightuserdata, C> {}; + + template + struct checker, type::userdata, C> : checker::value, C> {}; + + template + struct checker : stack_detail::basic_check {}; + template + struct checker, type::function, C> : checker {}; + template + struct checker : checker {}; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::nil || t == type::none || t == type::function) { + // allow for nil to be returned + return true; + } + if (t != type::userdata && t != type::table) { + handler(L, index, type::function, t); + return false; + } + // Do advanced check for call-style userdata? + static const auto& callkey = name_of(meta_function::call); + if (lua_getmetatable(L, index) == 0) { + // No metatable, no __call key possible + handler(L, index, type::function, t); + return false; + } + if (lua_isnoneornil(L, -1)) { + lua_pop(L, 1); + handler(L, index, type::function, t); + return false; + } + lua_getfield(L, -1, &callkey[0]); + if (lua_isnoneornil(L, -1)) { + lua_pop(L, 2); + handler(L, index, type::function, t); + return false; + } + // has call, is definitely a function + lua_pop(L, 2); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::table) { + return true; + } + if (t != type::userdata) { + handler(L, index, type::function, t); + return false; + } + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + // Allow nil to be transformed to nullptr + if (indextype == type::nil) { + tracking.use(1); + return true; + } + return checker, type::userdata, C>{}.check(types>(), L, indextype, index, std::forward(handler), tracking); + } + }; + + template + struct checker { + template + static bool check(types, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (indextype != type::userdata) { + handler(L, index, type::userdata, indextype); + return false; + } + if (meta::any, std::is_same, std::is_same, std::is_same>::value) + return true; + if (lua_getmetatable(L, index) == 0) { + return true; + } + int metatableindex = lua_gettop(L); + if (stack_detail::check_metatable(L, metatableindex)) + return true; + if (stack_detail::check_metatable(L, metatableindex)) + return true; + if (stack_detail::check_metatable>(L, metatableindex)) + return true; + bool success = false; + if (detail::has_derived::value) { + auto pn = stack::pop_n(L, 1); + lua_pushstring(L, &detail::base_class_check_key()[0]); + lua_rawget(L, metatableindex); + if (type_of(L, -1) != type::nil) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata; + success = ic(detail::id_for::value); + } + } + if (!success) { + lua_pop(L, 1); + handler(L, index, type::userdata, indextype); + return false; + } + lua_pop(L, 1); + return true; + } + + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + return check(types(), L, indextype, index, std::forward(handler), tracking); + } + }; + + template + struct checker::value>> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return checker::type, type::userdata>{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::userdata, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return checker{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::multi_check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::multi_check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + type t = type_of(L, index); + if (t == type::none) { + tracking.use(0); + return true; + } + return t == type::nil || stack::check(L, index, std::forward(handler), tracking); + } + }; + } // stack +} // sol + +#endif // SOL_STACK_CHECK_HPP diff --git a/3rdparty/sol2/sol/stack_check_get.hpp b/3rdparty/sol2/sol/stack_check_get.hpp new file mode 100644 index 00000000000..728d7d9a448 --- /dev/null +++ b/3rdparty/sol2/sol/stack_check_get.hpp @@ -0,0 +1,114 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_CHECK_GET_HPP +#define SOL_STACK_CHECK_GET_HPP + +#include "stack_core.hpp" +#include "stack_get.hpp" +#include "stack_check.hpp" +#include "optional.hpp" + +namespace sol { + namespace stack { + template + struct check_getter { + typedef decltype(stack_detail::unchecked_get(nullptr, 0, std::declval())) R; + + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + if (!check(L, index, std::forward(handler))) { + tracking.use(static_cast(!lua_isnone(L, index))); + return nullopt; + } + return stack_detail::unchecked_get(L, index, tracking); + } + }; + + template + struct check_getter> { + template + static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) { + return check_get(L, index, no_panic, tracking); + } + }; + + template + struct check_getter::value && lua_type_of::value == type::number>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct check_getter::value && !meta::any_same::value>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct check_getter::value>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Number value = lua_tonumberx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct getter> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return check_get(L, index, no_panic, tracking); + } + }; + } // stack +} // sol + +#endif // SOL_STACK_CHECK_GET_HPP diff --git a/3rdparty/sol2/sol/stack_core.hpp b/3rdparty/sol2/sol/stack_core.hpp new file mode 100644 index 00000000000..910399f3793 --- /dev/null +++ b/3rdparty/sol2/sol/stack_core.hpp @@ -0,0 +1,410 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_CORE_HPP +#define SOL_STACK_CORE_HPP + +#include "types.hpp" +#include "reference.hpp" +#include "stack_reference.hpp" +#include "userdata.hpp" +#include "tuple.hpp" +#include "traits.hpp" +#include "tie.hpp" +#include "stack_guard.hpp" +#include +#include + +namespace sol { + namespace detail { + struct as_reference_tag {}; + template + struct as_pointer_tag {}; + template + struct as_value_tag {}; + + using special_destruct_func = void(*)(void*); + + template + inline void special_destruct(void* memory) { + T** pointerpointer = static_cast(memory); + special_destruct_func* dx = static_cast(static_cast(pointerpointer + 1)); + Real* target = static_cast(static_cast(dx + 1)); + target->~Real(); + } + + template + inline int unique_destruct(lua_State* L) { + void* memory = lua_touserdata(L, 1); + T** pointerpointer = static_cast(memory); + special_destruct_func& dx = *static_cast(static_cast(pointerpointer + 1)); + (dx)(memory); + return 0; + } + + template + inline int user_alloc_destroy(lua_State* L) { + void* rawdata = lua_touserdata(L, upvalue_index(1)); + T* data = static_cast(rawdata); + std::allocator alloc; + alloc.destroy(data); + return 0; + } + + template + inline int usertype_alloc_destroy(lua_State* L) { + void* rawdata = lua_touserdata(L, 1); + T** pdata = static_cast(rawdata); + T* data = *pdata; + std::allocator alloc{}; + alloc.destroy(data); + return 0; + } + + template + void reserve(T&, std::size_t) {} + + template + void reserve(std::vector& arr, std::size_t hint) { + arr.reserve(hint); + } + + template + void reserve(std::basic_string& arr, std::size_t hint) { + arr.reserve(hint); + } + } // detail + + namespace stack { + + template + struct field_getter; + template + struct probe_field_getter; + template + struct field_setter; + template + struct getter; + template + struct popper; + template + struct pusher; + template::value, typename = void> + struct checker; + template + struct check_getter; + + struct probe { + bool success; + int levels; + + probe(bool s, int l) : success(s), levels(l) {} + + operator bool() const { return success; }; + }; + + struct record { + int last; + int used; + + record() : last(), used() {} + void use(int count) { + last = count; + used += count; + } + }; + + namespace stack_detail { + template + struct strip { + typedef T type; + }; + template + struct strip> { + typedef T& type; + }; + template + struct strip> { + typedef T& type; + }; + template + struct strip> { + typedef T type; + }; + template + using strip_t = typename strip::type; + const bool default_check_arguments = +#ifdef SOL_CHECK_ARGUMENTS + true; +#else + false; +#endif + template + inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { + return getter>{}.get(L, index, tracking); + } + } // stack_detail + + inline bool maybe_indexable(lua_State* L, int index = -1) { + type t = type_of(L, index); + return t == type::userdata || t == type::table; + } + + template + inline int push(lua_State* L, T&& t, Args&&... args) { + return pusher>{}.push(L, std::forward(t), std::forward(args)...); + } + + // overload allows to use a pusher of a specific type, but pass in any kind of args + template::value>> + inline int push(lua_State* L, Arg&& arg, Args&&... args) { + return pusher>{}.push(L, std::forward(arg), std::forward(args)...); + } + + template + inline int push_reference(lua_State* L, T&& t, Args&&... args) { + typedef meta::all< + std::is_lvalue_reference, + meta::neg>, + meta::neg>>, + meta::neg>> + > use_reference_tag; + return pusher>>{}.push(L, std::forward(t), std::forward(args)...); + } + + inline int multi_push(lua_State*) { + // do nothing + return 0; + } + + template + inline int multi_push(lua_State* L, T&& t, Args&&... args) { + int pushcount = push(L, std::forward(t)); + void(sol::detail::swallow{ (pushcount += sol::stack::push(L, std::forward(args)), 0)... }); + return pushcount; + } + + inline int multi_push_reference(lua_State*) { + // do nothing + return 0; + } + + template + inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { + int pushcount = push_reference(L, std::forward(t)); + void(sol::detail::swallow{ (pushcount += sol::stack::push_reference(L, std::forward(args)), 0)... }); + return pushcount; + } + + template + bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + typedef meta::unqualified_t Tu; + checker c; + // VC++ has a bad warning here: shut it up + (void)c; + return c.check(L, index, std::forward(handler), tracking); + } + + template + bool check(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return check(L, index, std::forward(handler), tracking); + } + + template + bool check(lua_State* L, int index = -lua_size>::value) { + auto handler = no_panic; + return check(L, index, handler); + } + + template + inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { + return check_getter>{}.get(L, index, std::forward(handler), tracking); + } + + template + inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return check_get(L, index, handler, tracking); + } + + template + inline decltype(auto) check_get(lua_State* L, int index = -lua_size>::value) { + auto handler = no_panic; + return check_get(L, index, handler); + } + + namespace stack_detail { + +#ifdef SOL_CHECK_ARGUMENTS + template + inline auto tagged_get(types, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get(L, index, tracking)) { + auto op = check_get(L, index, type_panic, tracking); + return *op; + } +#else + template + inline decltype(auto) tagged_get(types, lua_State* L, int index, record& tracking) { + return stack_detail::unchecked_get(L, index, tracking); + } +#endif + + template + inline decltype(auto) tagged_get(types>, lua_State* L, int index, record& tracking) { + return stack_detail::unchecked_get>(L, index, tracking); + } + + template + struct check_types { + template + static bool check(types, lua_State* L, int firstargument, Handler&& handler, record& tracking) { + if (!stack::check(L, firstargument + tracking.used, handler, tracking)) + return false; + return check(types(), L, firstargument, std::forward(handler), tracking); + } + + template + static bool check(types<>, lua_State*, int, Handler&&, record&) { + return true; + } + }; + + template <> + struct check_types { + template + static bool check(types, lua_State*, int, Handler&&, record&) { + return true; + } + }; + + } // stack_detail + + template + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack_detail::check_types{}.check(types...>(), L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return multi_check(L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index) { + auto handler = no_panic; + return multi_check(L, index, handler); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return multi_check(L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler) { + return multi_check(L, index, std::forward(handler)); + } + + template + bool multi_check(lua_State* L, int index) { + return multi_check(L, index); + } + + template + inline decltype(auto) get(lua_State* L, int index, record& tracking) { + return stack_detail::tagged_get(types(), L, index, tracking); + } + + template + inline decltype(auto) get(lua_State* L, int index = -lua_size>::value) { + record tracking{}; + return get(L, index, tracking); + } + + template + inline decltype(auto) pop(lua_State* L) { + return popper>{}.pop(L); + } + + template + void get_field(lua_State* L, Key&& key) { + field_getter, global, raw>{}.get(L, std::forward(key)); + } + + template + void get_field(lua_State* L, Key&& key, int tableindex) { + field_getter, global, raw>{}.get(L, std::forward(key), tableindex); + } + + template + void raw_get_field(lua_State* L, Key&& key) { + get_field(L, std::forward(key)); + } + + template + void raw_get_field(lua_State* L, Key&& key, int tableindex) { + get_field(L, std::forward(key), tableindex); + } + + template + probe probe_get_field(lua_State* L, Key&& key) { + return probe_field_getter, global, raw>{}.get(L, std::forward(key)); + } + + template + probe probe_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_field_getter, global, raw>{}.get(L, std::forward(key), tableindex); + } + + template + probe probe_raw_get_field(lua_State* L, Key&& key) { + return probe_get_field(L, std::forward(key)); + } + + template + probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_get_field(L, std::forward(key), tableindex); + } + + template + void set_field(lua_State* L, Key&& key, Value&& value) { + field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value)); + } + + template + void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value), tableindex); + } + + template + void raw_set_field(lua_State* L, Key&& key, Value&& value) { + set_field(L, std::forward(key), std::forward(value)); + } + + template + void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + set_field(L, std::forward(key), std::forward(value), tableindex); + } + } // stack +} // sol + +#endif // SOL_STACK_CORE_HPP diff --git a/3rdparty/sol2/sol/stack_field.hpp b/3rdparty/sol2/sol/stack_field.hpp new file mode 100644 index 00000000000..ca52f3dbdb7 --- /dev/null +++ b/3rdparty/sol2/sol/stack_field.hpp @@ -0,0 +1,261 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_FIELD_HPP +#define SOL_STACK_FIELD_HPP + +#include "stack_core.hpp" +#include "stack_push.hpp" +#include "stack_get.hpp" +#include "stack_check_get.hpp" + +namespace sol { + namespace stack { + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_gettable(L, tableindex); + } + }; + + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_rawget(L, tableindex); + } + }; + + template + struct field_getter { + void get(lua_State* L, metatable_key_t, int tableindex = -1) { + if (lua_getmetatable(L, tableindex) == 0) + push(L, nil); + } + }; + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int = -1) { + lua_getglobal(L, &key[0]); + } + }; + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_getfield(L, tableindex, &key[0]); + } + }; + +#if SOL_LUA_VERSION >= 503 + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_geti(L, tableindex, static_cast(key)); + } + }; +#endif // Lua 5.3.x + +#if SOL_LUA_VERSION >= 502 + template + struct field_getter { + void get(lua_State* L, void* key, int tableindex = -1) { + lua_rawgetp(L, tableindex, key); + } + }; +#endif // Lua 5.3.x + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_rawgeti(L, tableindex, static_cast(key)); + } + }; + + template + struct field_getter, b, raw, C> { + template + void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { + get_field(L, detail::forward_get<0>(keys), tableindex); + void(detail::swallow{ (get_field(L, detail::forward_get(keys)), 0)... }); + reference saved(L, -1); + lua_pop(L, static_cast(sizeof...(I))); + saved.push(); + } + + template + void get(lua_State* L, Keys&& keys) { + apply(std::make_index_sequence(), L, std::forward(keys), lua_absindex(L, -1)); + } + + template + void get(lua_State* L, Keys&& keys, int tableindex) { + apply(std::make_index_sequence(), L, std::forward(keys), tableindex); + } + }; + + template + struct field_getter, b, raw, C> { + template + void get(lua_State* L, Keys&& keys, int tableindex) { + get_field(L, detail::forward_get<0>(keys), tableindex); + get_field(L, detail::forward_get<1>(keys)); + reference saved(L, -1); + lua_pop(L, static_cast(2)); + saved.push(); + } + + template + void get(lua_State* L, Keys&& keys) { + get_field(L, detail::forward_get<0>(keys)); + get_field(L, detail::forward_get<1>(keys)); + reference saved(L, -1); + lua_pop(L, static_cast(2)); + saved.push(); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { + push(L, std::forward(key)); + push(L, std::forward(value)); + lua_settable(L, tableindex); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { + push(L, std::forward(key)); + push(L, std::forward(value)); + lua_rawset(L, tableindex); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, metatable_key_t, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_setmetatable(L, tableindex); + } + }; + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int = -2) { + push(L, std::forward(value)); + lua_setglobal(L, &key[0]); + } + }; + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_setfield(L, tableindex, &key[0]); + } + }; + +#if SOL_LUA_VERSION >= 503 + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_seti(L, tableindex, static_cast(key)); + } + }; +#endif // Lua 5.3.x + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_rawseti(L, tableindex, static_cast(key)); + } + }; + +#if SOL_LUA_VERSION >= 502 + template + struct field_setter { + template + void set(lua_State* L, void* key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_rawsetp(L, tableindex, key); + } + }; +#endif // Lua 5.2.x + + template + struct field_setter, b, raw, C> { + template + void apply(std::index_sequence, lua_State* L, Key&& keys, Value&& value, int tableindex) { + I < 1 ? + set_field(L, detail::forward_get(keys), std::forward(value), tableindex) : + set_field(L, detail::forward_get(keys), std::forward(value)); + } + + template + void apply(std::index_sequence, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + I0 < 1 ? get_field(L, detail::forward_get(keys), tableindex) : get_field(L, detail::forward_get(keys), -1); + apply(std::index_sequence(), L, std::forward(keys), std::forward(value), -1); + } + + template + void top_apply(std::index_sequence, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + apply(std::index_sequence(), L, std::forward(keys), std::forward(value), tableindex); + lua_pop(L, static_cast(sizeof...(I))); + } + + template + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { + top_apply(std::make_index_sequence(), L, std::forward(keys), std::forward(value), tableindex); + } + }; + + template + struct field_setter, b, raw, C> { + template + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { + get_field(L, detail::forward_get<0>(keys), tableindex); + set_field(L, detail::forward_get<1>(keys), std::forward(value)); + lua_pop(L, 1); + } + }; + } // stack +} // sol + +#endif // SOL_STACK_FIELD_HPP diff --git a/3rdparty/sol2/sol/stack_get.hpp b/3rdparty/sol2/sol/stack_get.hpp new file mode 100644 index 00000000000..52c52efa10e --- /dev/null +++ b/3rdparty/sol2/sol/stack_get.hpp @@ -0,0 +1,537 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_GET_HPP +#define SOL_STACK_GET_HPP + +#include "stack_core.hpp" +#include "usertype_traits.hpp" +#include "inheritance.hpp" +#include "overload.hpp" +#include "error.hpp" +#include +#include +#include +#ifdef SOL_CODECVT_SUPPORT +#include +#include +#endif + +namespace sol { + namespace stack { + + template + struct getter { + static T& get(lua_State* L, int index, record& tracking) { + return getter{}.get(L, index, tracking); + } + }; + + template + struct getter::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tonumber(L, index)); + } + }; + + template + struct getter, std::is_signed>::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointeger(L, index)); + } + }; + + template + struct getter, std::is_unsigned>::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointeger(L, index)); + } + }; + + template + struct getter::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointegerx(L, index, nullptr)); + } + }; + + template + struct getter, std::enable_if_t>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type V; + tracking.use(1); + + index = lua_absindex(L, index); + T arr; + get_field(L, static_cast(-1), index); + int isnum; + std::size_t sizehint = static_cast(lua_tointegerx(L, -1, &isnum)); + if (isnum != 0) { + detail::reserve(arr, sizehint); + } + lua_pop(L, 1); +#if SOL_LUA_VERSION >= 503 + // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 + for (lua_Integer i = 0; ; i += lua_size::value, lua_pop(L, lua_size::value)) { + for (int vi = 0; vi < lua_size::value; ++vi) { + type t = static_cast(lua_geti(L, index, i + vi)); + if (t == type::nil) { + if (i == 0) { + continue; + } + else { + lua_pop(L, (vi + 1)); + return arr; + } + } + } + arr.push_back(stack::get(L, -lua_size::value)); + } +#else + // Zzzz slower but necessary thanks to the lower version API and missing functions qq + for (lua_Integer i = 0; ; i += lua_size::value, lua_pop(L, lua_size::value)) { + for (int vi = 0; vi < lua_size::value; ++vi) { + lua_pushinteger(L, i); + lua_gettable(L, index); + type t = type_of(L, -1); + if (t == type::nil) { + if (i == 0) { + continue; + } + else { + lua_pop(L, (vi + 1)); + return arr; + } + } + } + arr.push_back(stack::get(L, -1)); + } +#endif + return arr; + } + }; + + template + struct getter, std::enable_if_t>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + tracking.use(1); + + T associative; + index = lua_absindex(L, index); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + decltype(auto) key = stack::check_get(L, -2); + if (!key) { + lua_pop(L, 1); + continue; + } + associative.emplace(std::forward(*key), stack::get(L, -1)); + lua_pop(L, 1); + } + return associative; + } + }; + + template + struct getter::value || std::is_base_of::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return T(L, index); + } + }; + + template<> + struct getter { + static userdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return userdata_value(lua_touserdata(L, index)); + } + }; + + template<> + struct getter { + static lightuserdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lightuserdata_value(lua_touserdata(L, index)); + } + }; + + template + struct getter> { + static light get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return light(static_cast(lua_touserdata(L, index))); + } + }; + + template + struct getter> { + static T& get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return *static_cast(lua_touserdata(L, index)); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_touserdata(L, index)); + } + }; + + template<> + struct getter { + static type get(lua_State *L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_type(L, index)); + } + }; + + template<> + struct getter { + static bool get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_toboolean(L, index) != 0; + } + }; + + template<> + struct getter { + static std::string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + std::size_t len; + auto str = lua_tolstring(L, index, &len); + return std::string( str, len ); + } + }; + + template <> + struct getter { + string_detail::string_shim get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + const char* p = lua_tolstring(L, index, &len); + return string_detail::string_shim(p, len); + } + }; + + template<> + struct getter { + static const char* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tostring(L, index); + } + }; + + template<> + struct getter { + static char get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + return len > 0 ? str[0] : '\0'; + } + }; + +#ifdef SOL_CODECVT_SUPPORT + template<> + struct getter { + static std::wstring get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::wstring(); + if (sizeof(wchar_t) == 2) { + std::wstring_convert> convert; + std::wstring r = convert.from_bytes(str, str + len); +#ifdef __MINGW32__ + // Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug + // https://sourceforge.net/p/mingw-w64/bugs/538/ + // http://chat.stackoverflow.com/transcript/message/32271369#32271369 + for (auto& c : r) { + uint8_t* b = reinterpret_cast(&c); + std::swap(b[0], b[1]); + } +#endif + return r; + } + std::wstring_convert> convert; + std::wstring r = convert.from_bytes(str, str + len); + return r; + } + }; + + template<> + struct getter { + static std::u16string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::u16string(); +#ifdef _MSC_VER + std::wstring_convert, int16_t> convert; + auto intd = convert.from_bytes(str, str + len); + std::u16string r(intd.size(), '\0'); + std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); +#else + std::wstring_convert, char16_t> convert; + std::u16string r = convert.from_bytes(str, str + len); +#endif // VC++ is a shit + return r; + } + }; + + template<> + struct getter { + static std::u32string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::u32string(); +#ifdef _MSC_VER + std::wstring_convert, int32_t> convert; + auto intd = convert.from_bytes(str, str + len); + std::u32string r(intd.size(), '\0'); + std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); +#else + std::wstring_convert, char32_t> convert; + std::u32string r = convert.from_bytes(str, str + len); +#endif // VC++ is a shit + return r; + } + }; + + template<> + struct getter { + static wchar_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : wchar_t(0); + } + }; + + template<> + struct getter { + static char16_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : char16_t(0); + } + }; + + template<> + struct getter { + static char32_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : char32_t(0); + } + }; +#endif // codecvt header support + + template<> + struct getter { + static meta_function get(lua_State *L, int index, record& tracking) { + tracking.use(1); + const char* name = getter{}.get(L, index, tracking); + for (std::size_t i = 0; i < meta_function_names.size(); ++i) + if (meta_function_names[i] == name) + return static_cast(i); + return meta_function::construct; + } + }; + + template<> + struct getter { + static nil_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nil; + } + }; + + template<> + struct getter { + static std::nullptr_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullptr; + } + }; + + template<> + struct getter { + static nullopt_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullopt; + } + }; + + template<> + struct getter { + static this_state get(lua_State* L, int, record& tracking) { + tracking.use(0); + return this_state{ L }; + } + }; + + template<> + struct getter { + static lua_CFunction get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tocfunction(L, index); + } + }; + + template<> + struct getter { + static c_closure get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return c_closure(lua_tocfunction(L, index), -1); + } + }; + + template<> + struct getter { + static error get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz = 0; + const char* err = lua_tolstring(L, index, &sz); + if (err == nullptr) { + return error(detail::direct_error, ""); + } + return error(detail::direct_error, std::string(err, sz)); + } + }; + + template<> + struct getter { + static void* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_touserdata(L, index); + } + }; + + template + struct getter { + static T* get_no_nil(lua_State* L, int index, record& tracking) { + tracking.use(1); + void** pudata = static_cast(lua_touserdata(L, index)); + void* udata = *pudata; + return get_no_nil_from(L, udata, index, tracking); + } + + static T* get_no_nil_from(lua_State* L, void* udata, int index, record&) { + if (detail::has_derived::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata; + // use the casting function to properly adjust the pointer for the desired T + udata = ic(udata, detail::id_for::value); + lua_pop(L, 1); + } + T* obj = static_cast(udata); + return obj; + } + + static T* get(lua_State* L, int index, record& tracking) { + type t = type_of(L, index); + if (t == type::nil) { + tracking.use(1); + return nullptr; + } + return get_no_nil(L, index, tracking); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + return getter::get_no_nil(L, index, tracking); + } + }; + + template + struct getter { + static T& get(lua_State* L, int index, record& tracking) { + return *getter::get_no_nil(L, index, tracking); + } + }; + + template + struct getter::value>> { + typedef typename unique_usertype_traits::type P; + typedef typename unique_usertype_traits::actual_type Real; + + static Real& get(lua_State* L, int index, record& tracking) { + tracking.use(1); + P** pref = static_cast(lua_touserdata(L, index)); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); + Real* mem = static_cast(static_cast(fx + 1)); + return *mem; + } + }; + + template + struct getter> { + static T& get(lua_State* L, int index, record& tracking) { + return getter{}.get(L, index, tracking); + } + }; + + template + struct getter> { + typedef std::tuple(nullptr, 0))...> R; + + template + static R apply(std::index_sequence<>, lua_State*, int, record&, TArgs&&... args) { + // Fuck you too, VC++ + return R{std::forward(args)...}; + } + + template + static R apply(std::index_sequence, lua_State* L, int index, record& tracking, TArgs&&... args) { + // Fuck you too, VC++ + typedef std::tuple_element_t> T; + return apply(std::index_sequence(), L, index, tracking, std::forward(args)..., stack::get(L, index + tracking.used, tracking)); + } + + static R get(lua_State* L, int index, record& tracking) { + return apply(std::make_index_sequence(), L, index, tracking); + } + }; + + template + struct getter> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return std::pair(L, index)), decltype(stack::get(L, index))>{stack::get(L, index, tracking), stack::get(L, index + tracking.used, tracking)}; + } + }; + + } // stack +} // sol + +#endif // SOL_STACK_GET_HPP diff --git a/3rdparty/sol2/sol/stack_guard.hpp b/3rdparty/sol2/sol/stack_guard.hpp new file mode 100644 index 00000000000..54e359fecb8 --- /dev/null +++ b/3rdparty/sol2/sol/stack_guard.hpp @@ -0,0 +1,63 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_GUARD_HPP +#define SOL_STACK_GUARD_HPP + +#include "compatibility/version.hpp" +#include "error.hpp" +#include + +namespace sol { + namespace detail { + inline void stack_fail(int, int) { +#ifndef SOL_NO_EXCEPTIONS + throw error(detail::direct_error, "imbalanced stack after operation finish"); +#else + // Lol, what do you want, an error printout? :3c + // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so + // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. +#endif // No Exceptions + } + } // detail + + struct stack_guard { + lua_State* L; + int top; + std::function on_mismatch; + + stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {} + stack_guard(lua_State* L, int top, std::function fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {} + bool check_stack(int modification = 0) const { + int bottom = lua_gettop(L) + modification; + if (top == bottom) { + return true; + } + on_mismatch(top, bottom); + return false; + } + ~stack_guard() { + check_stack(); + } + }; +} // sol + +#endif // SOL_STACK_GUARD_HPP diff --git a/3rdparty/sol2/sol/stack_pop.hpp b/3rdparty/sol2/sol/stack_pop.hpp new file mode 100644 index 00000000000..f69701311e5 --- /dev/null +++ b/3rdparty/sol2/sol/stack_pop.hpp @@ -0,0 +1,49 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_POP_HPP +#define SOL_STACK_POP_HPP + +#include "stack_core.hpp" +#include "stack_get.hpp" +#include +#include + +namespace sol { + namespace stack { + template + struct popper { + inline static decltype(auto) pop(lua_State* L) { + record tracking{}; + decltype(auto) r = get(L, -lua_size::value, tracking); + lua_pop(L, tracking.used); + return r; + } + }; + + template + struct popper>::value>> { + static_assert(meta::neg>>::value, "You cannot pop something that derives from stack_reference: it will not remain on the stack and thusly will go out of scope!"); + }; + } // stack +} // sol + +#endif // SOL_STACK_POP_HPP diff --git a/3rdparty/sol2/sol/stack_probe.hpp b/3rdparty/sol2/sol/stack_probe.hpp new file mode 100644 index 00000000000..05836da4ad2 --- /dev/null +++ b/3rdparty/sol2/sol/stack_probe.hpp @@ -0,0 +1,87 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_PROBE_HPP +#define SOL_STACK_PROBE_HPP + +#include "stack_core.hpp" +#include "stack_field.hpp" +#include "stack_check.hpp" + +namespace sol { + namespace stack { + template + struct probe_field_getter { + template + probe get(lua_State* L, Key&& key, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field(L, std::forward(key), tableindex); + return probe(!check(L), 1); + } + }; + + template + struct probe_field_getter, b, raw, C> { + template + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field(L, std::get<0>(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, 1); + } + get_field(L, std::get<1>(keys), tableindex); + return probe(!check(L), 2); + } + }; + + template + struct probe_field_getter, b, raw, C> { + template + probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I < 1 && b, raw>(L, std::get(keys), tableindex); + return probe(!check(L), sofar); + } + + template + probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I < 1 && b, raw>(L, std::get(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, sofar); + } + return apply(std::index_sequence(), sofar + 1, L, std::forward(keys), -1); + } + + template + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); + } + }; + } // stack +} // sol + +#endif // SOL_STACK_PROBE_HPP \ No newline at end of file diff --git a/3rdparty/sol2/sol/stack_proxy.hpp b/3rdparty/sol2/sol/stack_proxy.hpp new file mode 100644 index 00000000000..c1959233b63 --- /dev/null +++ b/3rdparty/sol2/sol/stack_proxy.hpp @@ -0,0 +1,124 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_PROXY_HPP +#define SOL_STACK_PROXY_HPP + +#include "stack.hpp" +#include "function.hpp" +#include "protected_function.hpp" +#include "proxy_base.hpp" + +namespace sol { + struct stack_proxy : public proxy_base { + private: + lua_State* L; + int index; + + public: + stack_proxy() : L(nullptr), index(0) {} + stack_proxy(lua_State* L, int index) : L(L), index(index) {} + + template + decltype(auto) get() const { + return stack::get(L, stack_index()); + } + + int push() const { + lua_pushvalue(L, index); + return 1; + } + + lua_State* lua_state() const { return L; } + int stack_index() const { return index; } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + }; + + namespace stack { + template <> + struct getter { + static stack_proxy get(lua_State* L, int index = -1) { + return stack_proxy(L, index); + } + }; + + template <> + struct pusher { + static int push(lua_State*, const stack_proxy& ref) { + return ref.push(); + } + }; + } // stack + + namespace detail { + template <> + struct is_speshul : std::true_type {}; + template <> + struct is_speshul : std::true_type {}; + + template + stack_proxy get(types, index_value<0>, index_value, const T& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template 0)>> = meta::enabler> + stack_proxy get(types, index_value, index_value, const T& fr) { + return get(types(), index_value(), index_value::value>(), fr); + } + } + + template <> + struct tie_size : std::integral_constant {}; + + template + stack_proxy get(const function_result& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template + stack_proxy get(types t, const function_result& fr) { + return detail::get(t, index_value(), index_value<0>(), fr); + } + + template <> + struct tie_size : std::integral_constant {}; + + template + stack_proxy get(const protected_function_result& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template + stack_proxy get(types t, const protected_function_result& fr) { + return detail::get(t, index_value(), index_value<0>(), fr); + } +} // sol + +#endif // SOL_STACK_PROXY_HPP diff --git a/3rdparty/sol2/sol/stack_push.hpp b/3rdparty/sol2/sol/stack_push.hpp new file mode 100644 index 00000000000..27d28fc081e --- /dev/null +++ b/3rdparty/sol2/sol/stack_push.hpp @@ -0,0 +1,693 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_PUSH_HPP +#define SOL_STACK_PUSH_HPP + +#include "stack_core.hpp" +#include "raii.hpp" +#include "optional.hpp" +#include +#ifdef SOL_CODECVT_SUPPORT +#include +#include +#endif + +namespace sol { + namespace stack { + template + struct pusher> { + template + static int push_fx(lua_State* L, F&& f, Args&&... args) { + // Basically, we store all user-data like this: + // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new + // data in the first sizeof(T*) bytes, and then however many bytes it takes to + // do the actual object. Things that are std::ref or plain T* are stored as + // just the sizeof(T*), and nothing else. + T** pointerpointer = static_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& referencereference = *pointerpointer; + T* allocationtarget = reinterpret_cast(pointerpointer + 1); + referencereference = allocationtarget; + std::allocator alloc{}; + alloc.construct(allocationtarget, std::forward(args)...); + f(); + return 1; + } + + template + static int push_keyed(lua_State* L, K&& k, Args&&... args) { + return push_fx(L, [&L, &k]() { + luaL_newmetatable(L, &k[0]); + lua_setmetatable(L, -2); + }, std::forward(args)...); + } + + template + static int push(lua_State* L, Args&&... args) { + return push_keyed(L, usertype_traits::metatable, std::forward(args)...); + } + }; + + template + struct pusher> { + template + static int push_fx(lua_State* L, F&& f, T* obj) { + if (obj == nullptr) + return stack::push(L, nil); + T** pref = static_cast(lua_newuserdata(L, sizeof(T*))); + *pref = obj; + f(); + return 1; + } + + template + static int push_keyed(lua_State* L, K&& k, T* obj) { + return push_fx(L, [&L, &k]() { + luaL_newmetatable(L, &k[0]); + lua_setmetatable(L, -2); + }, obj); + } + + static int push(lua_State* L, T* obj) { + return push_keyed(L, usertype_traits*>::metatable, obj); + } + }; + + template <> + struct pusher { + template + static int push(lua_State* L, T&& obj) { + return stack::push(L, detail::ptr(obj)); + } + }; + + template + struct pusher { + template + static int push(lua_State* L, Args&&... args) { + return pusher>{}.push(L, std::forward(args)...); + } + }; + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + template + static int push(lua_State* L, Args&&... args) { + return pusher>{}.push(L, std::forward(args)...); + } + }; + + template + struct pusher::value>> { + typedef typename unique_usertype_traits::type P; + typedef typename unique_usertype_traits::actual_type Real; + + template >> = meta::enabler> + static int push(lua_State* L, Arg&& arg) { + if (unique_usertype_traits::is_null(arg)) + return stack::push(L, nil); + return push_deep(L, std::forward(arg)); + } + + template + static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) { + return push_deep(L, std::forward(arg0), std::forward(arg1), std::forward(args)...); + } + + template + static int push_deep(lua_State* L, Args&&... args) { + P** pref = static_cast(lua_newuserdata(L, sizeof(P*) + sizeof(detail::special_destruct_func) + sizeof(Real))); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); + Real* mem = static_cast(static_cast(fx + 1)); + *fx = detail::special_destruct; + detail::default_construct::construct(mem, std::forward(args)...); + *pref = unique_usertype_traits::get(*mem); + if (luaL_newmetatable(L, &usertype_traits>::metatable[0]) == 1) { + set_field(L, "__gc", detail::unique_destruct

); + } + lua_setmetatable(L, -2); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, const std::reference_wrapper& t) { + return stack::push(L, std::addressof(detail::deref(t.get()))); + } + }; + + template + struct pusher::value>> { + static int push(lua_State* L, const T& value) { + lua_pushnumber(L, value); + return 1; + } + }; + + template + struct pusher, std::is_signed>::value>> { + static int push(lua_State* L, const T& value) { + lua_pushinteger(L, static_cast(value)); + return 1; + } + }; + + template + struct pusher::value>> { + static int push(lua_State* L, const T& value) { + if (std::is_same::value) { + return stack::push(L, static_cast(value)); + } + return stack::push(L, static_cast>(value)); + } + }; + + template + struct pusher, std::is_unsigned>::value>> { + static int push(lua_State* L, const T& value) { + lua_pushinteger(L, static_cast(value)); + return 1; + } + }; + + template + struct pusher, std::enable_if_t>>::value>> { + static int push(lua_State* L, const as_table_t& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont.source)); + lua_createtable(L, static_cast(cont.size()), 0); + int tableindex = lua_gettop(L); + std::size_t index = 1; + for (const auto& i : cont) { +#if SOL_LUA_VERSION >= 503 + int p = stack::push(L, i); + for (int pi = 0; pi < p; ++pi) { + lua_seti(L, tableindex, static_cast(index++)); + } +#else + lua_pushinteger(L, static_cast(index)); + int p = stack::push(L, i); + if (p == 1) { + ++index; + lua_settable(L, tableindex); + } + else { + int firstindex = tableindex + 1 + 1; + for (int pi = 0; pi < p; ++pi) { + stack::push(L, index); + lua_pushvalue(L, firstindex); + lua_settable(L, tableindex); + ++index; + ++firstindex; + } + lua_pop(L, 1 + p); + } +#endif + } + // TODO: figure out a better way to do this...? + //set_field(L, -1, cont.size()); + return 1; + } + }; + + template + struct pusher, std::enable_if_t>>::value>> { + static int push(lua_State* L, const as_table_t& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont.source)); + lua_createtable(L, static_cast(cont.size()), 0); + int tableindex = lua_gettop(L); + for (const auto& pair : cont) { + set_field(L, pair.first, pair.second, tableindex); + } + return 1; + } + }; + + template + struct pusher::value || std::is_base_of::value>> { + static int push(lua_State*, const T& ref) { + return ref.push(); + } + + static int push(lua_State*, T&& ref) { + return ref.push(); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, bool b) { + lua_pushboolean(L, b); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, nil_t) { + lua_pushnil(L); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, metatable_key_t) { + lua_pushlstring(L, "__mt", 4); + return 1; + } + }; + + template<> + struct pusher> { + static int push(lua_State* L, lua_CFunction func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lua_CFunction func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, c_closure cc) { + lua_pushcclosure(L, cc.c_function, cc.upvalues); + return 1; + } + }; + + template + struct pusher> { + template + static int push(std::index_sequence, lua_State* L, T&& c) { + int pushcount = multi_push(L, detail::forward_get(c.upvalues)...); + return stack::push(L, c_closure(c.c_function, pushcount)); + } + + template + static int push(lua_State* L, T&& c) { + return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward(c)); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, void* userdata) { + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lightuserdata_value userdata) { + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, light l) { + lua_pushlightuserdata(L, static_cast(l.value)); + return 1; + } + }; + + template + struct pusher> { + template + static int push_with(lua_State* L, Key&& name, Args&&... args) { + // A dumb pusher + void* rawdata = lua_newuserdata(L, sizeof(T)); + T* data = static_cast(rawdata); + std::allocator alloc; + alloc.construct(data, std::forward(args)...); + if (with_meta) { + lua_CFunction cdel = detail::user_alloc_destroy; + // Make sure we have a plain GC set for this data + if (luaL_newmetatable(L, name) != 0) { + lua_pushlightuserdata(L, rawdata); + lua_pushcclosure(L, cdel, 1); + lua_setfield(L, -2, "__gc"); + } + lua_setmetatable(L, -2); + } + return 1; + } + + template , no_metatable_t, metatable_key_t>> = meta::enabler> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::forward(arg), std::forward(args)...); + } + + template + static int push(lua_State* L, no_metatable_t, Args&&... args) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::forward(args)...); + } + + template + static int push(lua_State* L, metatable_key_t, Key&& key, Args&&... args) { + const auto name = &key[0]; + return push_with(L, name, std::forward(args)...); + } + + static int push(lua_State* L, const user& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, user&& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::move(u.value)); + } + + static int push(lua_State* L, no_metatable_t, const user& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, no_metatable_t, user&& u) { + const auto name = &usertype_traits>::user_gc_metatable[0]; + return push_with(L, name, std::move(u.value)); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, userdata_value data) { + void** ud = static_cast(lua_newuserdata(L, sizeof(void*))); + *ud = data.value; + return 1; + } + }; + + template<> + struct pusher { + static int push_sized(lua_State* L, const char* str, std::size_t len) { + lua_pushlstring(L, str, len); + return 1; + } + + static int push(lua_State* L, const char* str) { + return push_sized(L, str, std::char_traits::length(str)); + } + + static int push(lua_State* L, const char* strb, const char* stre) { + return push_sized(L, strb, stre - strb); + } + + static int push(lua_State* L, const char* str, std::size_t len) { + return push_sized(L, str, len); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char(&str)[N]) { + lua_pushlstring(L, str, N - 1); + return 1; + } + + static int push(lua_State* L, const char(&str)[N], std::size_t sz) { + lua_pushlstring(L, str, sz); + return 1; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char c) { + const char str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::string& str) { + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + + static int push(lua_State* L, const std::string& str, std::size_t sz) { + lua_pushlstring(L, str.c_str(), sz); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, meta_function m) { + const std::string& str = name_of(m); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + }; + +#ifdef SOL_CODECVT_SUPPORT + template<> + struct pusher { + static int push(lua_State* L, const wchar_t* wstr) { + return push(L, wstr, std::char_traits::length(wstr)); + } + + static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { + return push(L, wstr, wstr + sz); + } + + static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { + if (sizeof(wchar_t) == 2) { + std::wstring_convert> convert; + std::string u8str = convert.to_bytes(strb, stre); + return stack::push(L, u8str); + } + std::wstring_convert> convert; + std::string u8str = convert.to_bytes(strb, stre); + return stack::push(L, u8str); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const char16_t* u16str) { + return push(L, u16str, std::char_traits::length(u16str)); + } + + static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { + return push(L, u16str, u16str + sz); + } + + static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { +#ifdef _MSC_VER + std::wstring_convert, int16_t> convert; + std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); +#else + std::wstring_convert, char16_t> convert; + std::string u8str = convert.to_bytes(strb, stre); +#endif // VC++ is a shit + return stack::push(L, u8str); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const char32_t* u32str) { + return push(L, u32str, u32str + std::char_traits::length(u32str)); + } + + static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { + return push(L, u32str, u32str + sz); + } + + static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { +#ifdef _MSC_VER + std::wstring_convert, int32_t> convert; + std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); +#else + std::wstring_convert, char32_t> convert; + std::string u8str = convert.to_bytes(strb, stre); +#endif // VC++ is a shit + return stack::push(L, u8str); + } + }; + + template + struct pusher { + static int push(lua_State* L, const wchar_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const wchar_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char16_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const char16_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char32_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const char32_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, wchar_t c) { + const wchar_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char16_t c) { + const char16_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char32_t c) { + const char32_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::wstring& wstr) { + return push(L, wstr.data(), wstr.size()); + } + + static int push(lua_State* L, const std::wstring& wstr, std::size_t sz) { + return stack::push(L, wstr.data(), wstr.data() + sz); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::u16string& u16str) { + return push(L, u16str, u16str.size()); + } + + static int push(lua_State* L, const std::u16string& u16str, std::size_t sz) { + return stack::push(L, u16str.data(), u16str.data() + sz); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::u32string& u32str) { + return push(L, u32str, u32str.size()); + } + + static int push(lua_State* L, const std::u32string& u32str, std::size_t sz) { + return stack::push(L, u32str.data(), u32str.data() + sz); + } + }; +#endif // codecvt Header Support + + template + struct pusher> { + template + static int push(std::index_sequence, lua_State* L, T&& t) { + int pushcount = 0; + (void)detail::swallow{ 0, (pushcount += stack::push(L, + detail::forward_get(t) + ), 0)... }; + return pushcount; + } + + template + static int push(lua_State* L, T&& t) { + return push(std::index_sequence_for(), L, std::forward(t)); + } + }; + + template + struct pusher> { + template + static int push(lua_State* L, T&& t) { + int pushcount = stack::push(L, detail::forward_get<0>(t)); + pushcount += stack::push(L, detail::forward_get<1>(t)); + return pushcount; + } + }; + + template + struct pusher> { + template + static int push(lua_State* L, T&& t) { + if (t == nullopt) { + return stack::push(L, nullopt); + } + return stack::push(L, t.value()); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, nullopt_t) { + return stack::push(L, nil); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, std::nullptr_t) { + return stack::push(L, nil); + } + }; + + template<> + struct pusher { + static int push(lua_State*, const this_state&) { + return 0; + } + }; + } // stack +} // sol + +#endif // SOL_STACK_PUSH_HPP diff --git a/3rdparty/sol2/sol/stack_reference.hpp b/3rdparty/sol2/sol/stack_reference.hpp new file mode 100644 index 00000000000..1b3403dedd9 --- /dev/null +++ b/3rdparty/sol2/sol/stack_reference.hpp @@ -0,0 +1,84 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STACK_REFERENCE_HPP +#define SOL_STACK_REFERENCE_HPP + +namespace sol { + class stack_reference { + private: + lua_State* L = nullptr; + int index = 0; + + protected: + int registry_index() const noexcept { + return LUA_NOREF; + } + + public: + stack_reference() noexcept = default; + stack_reference(nil_t) noexcept : stack_reference() {}; + stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {} + stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {} + stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {} + stack_reference(stack_reference&& o) noexcept = default; + stack_reference& operator=(stack_reference&&) noexcept = default; + stack_reference(const stack_reference&) noexcept = default; + stack_reference& operator=(const stack_reference&) noexcept = default; + + int push() const noexcept { + lua_pushvalue(L, index); + return 1; + } + + void pop(int n = 1) const noexcept { + lua_pop(lua_state(), n); + } + + int stack_index() const noexcept { + return index; + } + + type get_type() const noexcept { + int result = lua_type(L, index); + return static_cast(result); + } + + lua_State* lua_state() const noexcept { + return L; + } + + bool valid() const noexcept { + type t = get_type(); + return t != type::nil && t != type::none; + } + }; + + inline bool operator== (const stack_reference& l, const stack_reference& r) { + return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0; + } + + inline bool operator!= (const stack_reference& l, const stack_reference& r) { + return !operator==(l, r); + } +} // sol + +#endif // SOL_STACK_REFERENCE_HPP diff --git a/3rdparty/sol2/sol/state.hpp b/3rdparty/sol2/sol/state.hpp new file mode 100644 index 00000000000..18c32db5010 --- /dev/null +++ b/3rdparty/sol2/sol/state.hpp @@ -0,0 +1,59 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STATE_HPP +#define SOL_STATE_HPP + +#include "state_view.hpp" + +namespace sol { + inline int default_at_panic(lua_State* L) { +#ifdef SOL_NO_EXCEPTIONS + (void)L; + return -1; +#else + const char* message = lua_tostring(L, -1); + std::string err = message ? message : "An unexpected error occurred and forced the lua state to call atpanic"; + throw error(err); +#endif + } + + class state : private std::unique_ptr, public state_view { + private: + typedef std::unique_ptr unique_base; + public: + state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), + state_view(unique_base::get()) { + set_panic(panic); + stack::luajit_exception_handler(unique_base::get()); + } + + state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close), + state_view(unique_base::get()) { + set_panic(panic); + stack::luajit_exception_handler(unique_base::get()); + } + + using state_view::get; + }; +} // sol + +#endif // SOL_STATE_HPP diff --git a/3rdparty/sol2/sol/state_view.hpp b/3rdparty/sol2/sol/state_view.hpp new file mode 100644 index 00000000000..3efb3674d25 --- /dev/null +++ b/3rdparty/sol2/sol/state_view.hpp @@ -0,0 +1,460 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_STATE_VIEW_HPP +#define SOL_STATE_VIEW_HPP + +#include "error.hpp" +#include "table.hpp" +#include "load_result.hpp" +#include + +namespace sol { + enum class lib : char { + base, + package, + coroutine, + string, + os, + math, + table, + debug, + bit32, + io, + ffi, + jit, + utf8, + count + }; + + class state_view { + private: + lua_State* L; + table reg; + global_table global; + + optional is_loaded_package(const std::string& key) { + auto loaded = reg.traverse_get>("_LOADED", key); + bool is53mod = loaded && !(loaded->is() && !loaded->as()); + if (is53mod) + return loaded; +#if SOL_LUA_VERSION <= 501 + auto loaded51 = global.traverse_get>("package", "loaded", key); + bool is51mod = loaded51 && !(loaded51->is() && !loaded51->as()); + if (is51mod) + return loaded51; +#endif + return nullopt; + } + + template + void ensure_package(const std::string& key, T&& sr) { +#if SOL_LUA_VERSION <= 501 + auto pkg = global["package"]; + if (!pkg.valid()) { + pkg = create_table_with("loaded", create_table_with(key, sr)); + } + else { + auto ld = pkg["loaded"]; + if (!ld.valid()) { + ld = create_table_with(key, sr); + } + else { + ld[key] = sr; + } + } +#endif + auto loaded = reg["_LOADED"]; + if (!loaded.valid()) { + loaded = create_table_with(key, sr); + } + else { + loaded[key] = sr; + } + } + + template + object require_core(const std::string& key, Fx&& action, bool create_global = true) { + optional loaded = is_loaded_package(key); + if (loaded && loaded->valid()) + return std::move(*loaded); + action(); + auto sr = stack::get(L); + if (create_global) + set(key, sr); + ensure_package(key, sr); + return stack::pop(L); + } + + public: + typedef global_table::iterator iterator; + typedef global_table::const_iterator const_iterator; + + state_view(lua_State* L) : + L(L), + reg(L, LUA_REGISTRYINDEX), + global(L, detail::global_) { + + } + + lua_State* lua_state() const { + return L; + } + + template + void open_libraries(Args&&... args) { + static_assert(meta::all_same::value, "all types must be libraries"); + if (sizeof...(args) == 0) { + luaL_openlibs(L); + return; + } + + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; + + for (auto&& library : libraries) { + switch (library) { +#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) + case lib::coroutine: +#endif // luajit opens coroutine base stuff + case lib::base: + luaL_requiref(L, "base", luaopen_base, 1); + lua_pop(L, 1); + break; + case lib::package: + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + break; +#if !defined(SOL_LUAJIT) + case lib::coroutine: +#if SOL_LUA_VERSION > 501 + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); +#endif // Lua 5.2+ only + break; +#endif // Not LuaJIT + case lib::string: + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + break; + case lib::table: + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + break; + case lib::math: + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + break; + case lib::bit32: +#ifdef SOL_LUAJIT + luaL_requiref(L, "bit32", luaopen_bit, 1); + lua_pop(L, 1); +#elif SOL_LUA_VERSION == 502 + luaL_requiref(L, "bit32", luaopen_bit32, 1); + lua_pop(L, 1); +#else +#endif // Lua 5.2 only (deprecated in 5.3 (503)) + break; + case lib::io: + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + break; + case lib::os: + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + break; + case lib::debug: + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + break; + case lib::utf8: +#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); +#endif // Lua 5.3+ only + break; + case lib::ffi: +#ifdef SOL_LUAJIT + luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); +#endif + break; + case lib::jit: +#ifdef SOL_LUAJIT + luaL_requiref(L, "jit", luaopen_jit, 1); + lua_pop(L, 1); +#endif + break; + case lib::count: + default: + break; + } + } + } + + object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { + luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); + return stack::pop(L); + } + + object require_script(const std::string& key, const std::string& code, bool create_global = true) { + return require_core(key, [this, &code]() {stack::script(L, code); }, create_global); + } + + object require_file(const std::string& key, const std::string& filename, bool create_global = true) { + return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); + } + + function_result script(const std::string& code) { + int index = (::std::max)(lua_gettop(L), 1); + stack::script(L, code); + int returns = lua_gettop(L) - (index - 1); + return function_result(L, index, returns); + } + + function_result script_file(const std::string& filename) { + int index = (::std::max)(lua_gettop(L), 1); + stack::script_file(L, filename); + int returns = lua_gettop(L) - (index - 1); + return function_result(L, index, returns); + } + + load_result load(const std::string& code) { + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + load_result load_file(const std::string& filename) { + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + load_result load_buffer(const char *buff, size_t size, const char *name, const char* mode = nullptr) { + load_status x = static_cast(luaL_loadbufferx(L, buff, size, name, mode)); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + iterator begin() const { + return global.begin(); + } + + iterator end() const { + return global.end(); + } + + const_iterator cbegin() const { + return global.cbegin(); + } + + const_iterator cend() const { + return global.cend(); + } + + global_table globals() const { + return global; + } + + table registry() const { + return reg; + } + + operator lua_State* () const { + return lua_state(); + } + + void set_panic(lua_CFunction panic) { + lua_atpanic(L, panic); + } + + template + decltype(auto) get(Keys&&... keys) const { + return global.get(std::forward(keys)...); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + return global.get_or(std::forward(key), std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + return global.get_or(std::forward(key), std::forward(otherwise)); + } + + template + state_view& set(Args&&... args) { + global.set(std::forward(args)...); + return *this; + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + return global.traverse_get(std::forward(keys)...); + } + + template + state_view& traverse_set(Args&&... args) { + global.traverse_set(std::forward(args)...); + return *this; + } + + template + state_view& set_usertype(usertype& user) { + return set_usertype(usertype_traits::name, user); + } + + template + state_view& set_usertype(Key&& key, usertype& user) { + global.set_usertype(std::forward(key), user); + return *this; + } + + template + state_view& new_usertype(const std::string& name, Args&&... args) { + global.new_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_usertype(const std::string& name, Args&&... args) { + global.new_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_usertype(const std::string& name, constructors ctor, Args&&... args) { + global.new_usertype(name, ctor, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, Args&&... args) { + global.new_simple_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, Args&&... args) { + global.new_simple_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args) { + global.new_simple_usertype(name, ctor, std::forward(args)...); + return *this; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + return global.create_simple_usertype(std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + return global.create_simple_usertype(std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(constructors ctor, Args&&... args) { + return global.create_simple_usertype(ctor, std::forward(args)...); + } + + template + state_view& new_enum(const std::string& name, Args&&... args) { + global.new_enum(name, std::forward(args)...); + return *this; + } + + template + void for_each(Fx&& fx) { + global.for_each(std::forward(fx)); + } + + template + proxy operator[](T&& key) { + return global[std::forward(key)]; + } + + template + proxy operator[](T&& key) const { + return global[std::forward(key)]; + } + + template + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward(key), std::forward(args)...); + return *this; + } + + template + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward(key), std::forward(args)...); + return *this; + } + + template + table create_table(Name&& name, int narr = 0, int nrec = 0) { + return global.create(std::forward(name), narr, nrec); + } + + template + table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global.create(std::forward(name), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create_named_table(Name&& name, Args&&... args) { + table x = global.create_with(std::forward(args)...); + global.set(std::forward(name), x); + return x; + } + + table create_table(int narr = 0, int nrec = 0) { + return create_table(lua_state(), narr, nrec); + } + + template + table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create_table(lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create_table_with(Args&&... args) { + return create_table_with(lua_state(), std::forward(args)...); + } + + static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { + return global_table::create(L, narr, nrec); + } + + template + static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global_table::create(L, narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + static inline table create_table_with(lua_State* L, Args&&... args) { + return global_table::create_with(L, std::forward(args)...); + } + }; +} // sol + +#endif // SOL_STATE_VIEW_HPP diff --git a/3rdparty/sol2/sol/string_shim.hpp b/3rdparty/sol2/sol/string_shim.hpp new file mode 100644 index 00000000000..b1e685bddc8 --- /dev/null +++ b/3rdparty/sol2/sol/string_shim.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include +#include + +namespace sol { + namespace string_detail { + struct string_shim { + std::size_t s; + const char* p; + + string_shim(const std::string& r) : string_shim(r.data(), r.size()) {} + string_shim(const char* p) : string_shim(p, std::char_traits::length(p)) {} + string_shim(const char* p, std::size_t s) : s(s), p(p) {} + + static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) { + int result = std::char_traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); + if (result != 0) + return result; + if (lhs_sz < rhs_sz) + return -1; + if (lhs_sz > rhs_sz) + return 1; + return 0; + } + + const char* c_str() const { + return p; + } + + const char* data() const { + return p; + } + + std::size_t size() const { + return s; + } + + bool operator==(const string_shim& r) const { + return compare(p, s, r.data(), r.size()) == 0; + } + + bool operator==(const char* r) const { + return compare(r, std::char_traits::length(r), p, s) == 0; + } + + bool operator==(const std::string& r) const { + return compare(r.data(), r.size(), p, s) == 0; + } + + bool operator!=(const string_shim& r) const { + return !(*this == r); + } + + bool operator!=(const char* r) const { + return !(*this == r); + } + + bool operator!=(const std::string& r) const { + return !(*this == r); + } + }; + } +} \ No newline at end of file diff --git a/3rdparty/sol2/sol/table.hpp b/3rdparty/sol2/sol/table.hpp new file mode 100644 index 00000000000..fd556a6117d --- /dev/null +++ b/3rdparty/sol2/sol/table.hpp @@ -0,0 +1,31 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TABLE_HPP +#define SOL_TABLE_HPP + +#include "table_core.hpp" + +namespace sol { + typedef table_core table; +} // sol + +#endif // SOL_TABLE_HPP diff --git a/3rdparty/sol2/sol/table_core.hpp b/3rdparty/sol2/sol/table_core.hpp new file mode 100644 index 00000000000..918f3d4ad76 --- /dev/null +++ b/3rdparty/sol2/sol/table_core.hpp @@ -0,0 +1,462 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TABLE_CORE_HPP +#define SOL_TABLE_CORE_HPP + +#include "proxy.hpp" +#include "stack.hpp" +#include "function_types.hpp" +#include "usertype.hpp" +#include "table_iterator.hpp" + +namespace sol { + namespace detail { + template + struct clean { lua_State* L; clean(lua_State* L) : L(L) {} ~clean() { lua_pop(L, static_cast(n)); } }; + struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* L, int& n) : L(L), n(n) {} ~ref_clean() { lua_pop(L, static_cast(n)); } }; + inline int fail_on_newindex(lua_State* L) { + return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); + } + } + + template + class basic_table_core : public base_t { + friend class state; + friend class state_view; + + template + using is_global = meta::all, meta::is_c_str...>; + + template + void for_each(std::true_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), nil); + while (lua_next(base_t::lua_state(), -2)) { + sol::object key(base_t::lua_state(), -2); + sol::object value(base_t::lua_state(), -1); + std::pair keyvalue(key, value); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(keyvalue); + } + } + + template + void for_each(std::false_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), nil); + while (lua_next(base_t::lua_state(), -2)) { + sol::object key(base_t::lua_state(), -2); + sol::object value(base_t::lua_state(), -1); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(key, value); + } + } + + template + auto tuple_get(types, std::index_sequence<0, 1, I...>, Keys&& keys) const + -> decltype(stack::pop>(nullptr)) { + typedef decltype(stack::pop>(nullptr)) Tup; + return Tup( + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get<0>(keys)), + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get<1>(keys)), + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get(keys))... + ); + } + + template + decltype(auto) tuple_get(types, std::index_sequence, Keys&& keys) const { + return traverse_get_optional(meta::is_specialization_of>(), detail::forward_get(keys)); + } + + template + void tuple_set(std::index_sequence, Pairs&& pairs) { + auto pp = stack::push_pop(pairs))...>::value)>(*this); + void(detail::swallow{ (stack::set_field(base_t::lua_state(), + detail::forward_get(pairs), + detail::forward_get(pairs), + lua_gettop(base_t::lua_state()) + ), 0)... }); + } + + template + decltype(auto) traverse_get_deep(Key&& key) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { + typedef decltype(stack::get(base_t::lua_state())) R; + auto p = stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return R(nullopt); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { + auto p = I > 0 ? stack::probe_get_field(base_t::lua_state(), std::forward(key), -1) : stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return T(nullopt); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { + detail::clean c(base_t::lua_state()); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { + int popcount = 0; + detail::ref_clean c(base_t::lua_state(), popcount); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + void traverse_set_deep(Key&& key, Value&& value) const { + stack::set_field(base_t::lua_state(), std::forward(key), std::forward(value)); + } + + template + void traverse_set_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + traverse_set_deep(std::forward(keys)...); + } + + basic_table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { } + + public: + typedef basic_table_iterator iterator; + typedef iterator const_iterator; + + basic_table_core() noexcept : base_t() { } + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_table_core(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_table>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_table_core(const basic_table_core&) = default; + basic_table_core(basic_table_core&&) = default; + basic_table_core& operator=(const basic_table_core&) = default; + basic_table_core& operator=(basic_table_core&&) = default; + basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {} + basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {} + basic_table_core(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + + iterator begin() const { + return iterator(*this); + } + + iterator end() const { + return iterator(); + } + + const_iterator cbegin() const { + return begin(); + } + + const_iterator cend() const { + return end(); + } + + template + decltype(auto) get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + auto pp = stack::push_pop::value>(*this); + return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + typedef decltype(get("")) U; + sol::optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + sol::optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + auto pp = stack::push_pop::value>(*this); + return traverse_get_optional(meta::is_specialization_of>(), std::forward(keys)...); + } + + template + basic_table_core& traverse_set(Keys&&... keys) { + auto pp = stack::push_pop::value>(*this); + auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys)-2)); + traverse_set_deep(std::forward(keys)...); + return *this; + } + + template + basic_table_core& set(Args&&... args) { + tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); + return *this; + } + + template + basic_table_core& set_usertype(usertype& user) { + return set_usertype(usertype_traits::name, user); + } + + template + basic_table_core& set_usertype(Key&& key, usertype& user) { + return set(std::forward(key), user); + } + + template + basic_table_core& new_usertype(const std::string& name, Args&&... args) { + usertype utype(std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_usertype(const std::string& name, Args&&... args) { + constructors> ctor{}; + return new_usertype(name, ctor, std::forward(args)...); + } + + template + basic_table_core& new_usertype(const std::string& name, constructors ctor, Args&&... args) { + usertype utype(ctor, std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { + simple_usertype utype(base_t::lua_state(), std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { + constructors> ctor{}; + return new_simple_usertype(name, ctor, std::forward(args)...); + } + + template + basic_table_core& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args) { + simple_usertype utype(base_t::lua_state(), ctor, std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + simple_usertype utype(base_t::lua_state(), std::forward(args)...); + return utype; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + constructors> ctor{}; + return create_simple_usertype(ctor, std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(constructors ctor, Args&&... args) { + simple_usertype utype(base_t::lua_state(), ctor, std::forward(args)...); + return utype; + } + + template + basic_table_core& new_enum(const std::string& name, Args&&... args) { + if (read_only) { + table idx = create_with(std::forward(args)...); + table x = create_with( + meta_function::new_index, detail::fail_on_newindex, + meta_function::index, idx + ); + table target = create_named(name); + target[metatable_key] = x; + } + else { + create_named(name, std::forward(args)...); + } + return *this; + } + + template + void for_each(Fx&& fx) const { + typedef meta::is_invokable)> is_paired; + for_each(is_paired(), std::forward(fx)); + } + + size_t size() const { + auto pp = stack::push_pop(*this); + lua_len(base_t::lua_state(), -1); + return stack::pop(base_t::lua_state()); + } + + bool empty() const { + return cbegin() == cend(); + } + + template + proxy operator[](T&& key) & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) const & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) && { + return proxy(*this, std::forward(key)); + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& add(Args&&... args) { + auto pp = stack::push_pop(*this); + (void)detail::swallow{0, + (stack::set_ref(base_t::lua_state(), std::forward(args)), 0)... + }; + return *this; + } + + private: + template> + void set_fx(types, Key&& key, Fx&& fx) { + set_resolved_function(std::forward(key), std::forward(fx)); + } + + template>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward(key), std::forward(fx)); + } + + template>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward(key), as_function_reference(std::forward(fx), std::forward(args)...)); + } + + template + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward(key), as_function_reference>(std::forward(args)...)); + } + + public: + static inline table create(lua_State* L, int narr = 0, int nrec = 0) { + lua_createtable(L, narr, nrec); + table result(L); + lua_pop(L, 1); + return result; + } + + template + static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + lua_createtable(L, narr, nrec); + table result(L); + result.set(std::forward(key), std::forward(value), std::forward(args)...); + lua_pop(L, 1); + return result; + } + + template + static inline table create_with(lua_State* L, Args&&... args) { + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(L, narr, static_cast((sizeof...(Args) / 2) - narr), std::forward(args)...); + } + + table create(int narr = 0, int nrec = 0) { + return create(base_t::lua_state(), narr, nrec); + } + + template + table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create(Name&& name, int narr = 0, int nrec = 0) { + table x = create(base_t::lua_state(), narr, nrec); + this->set(std::forward(name), x); + return x; + } + + template + table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + table x = create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + this->set(std::forward(name), x); + return x; + } + + template + table create_with(Args&&... args) { + return create_with(base_t::lua_state(), std::forward(args)...); + } + + template + table create_named(Name&& name, Args&&... args) { + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(std::forward(name), narr, sizeof...(Args) / 2 - narr, std::forward(args)...); + } + }; +} // sol + +#endif // SOL_TABLE_CORE_HPP diff --git a/3rdparty/sol2/sol/table_iterator.hpp b/3rdparty/sol2/sol/table_iterator.hpp new file mode 100644 index 00000000000..7d81a6515bb --- /dev/null +++ b/3rdparty/sol2/sol/table_iterator.hpp @@ -0,0 +1,120 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TABLE_ITERATOR_HPP +#define SOL_TABLE_ITERATOR_HPP + +#include "object.hpp" +#include + +namespace sol { + + template + class basic_table_iterator : public std::iterator> { + private: + typedef std::iterator> base_t; + public: + typedef object key_type; + typedef object mapped_type; + typedef base_t::value_type value_type; + typedef base_t::iterator_category iterator_category; + typedef base_t::difference_type difference_type; + typedef base_t::pointer pointer; + typedef base_t::reference reference; + typedef const value_type& const_reference; + + private: + std::pair kvp; + reference_type ref; + int tableidx = 0; + int keyidx = 0; + std::ptrdiff_t idx = 0; + + public: + + basic_table_iterator() : keyidx(-1), idx(-1) { + + } + + basic_table_iterator(reference_type x) : ref(std::move(x)) { + ref.push(); + tableidx = lua_gettop(ref.lua_state()); + stack::push(ref.lua_state(), nil); + this->operator++(); + if (idx == -1) { + return; + } + --idx; + } + + basic_table_iterator& operator++() { + if (idx == -1) + return *this; + + if (lua_next(ref.lua_state(), tableidx) == 0) { + idx = -1; + keyidx = -1; + return *this; + } + ++idx; + kvp.first = object(ref.lua_state(), -2); + kvp.second = object(ref.lua_state(), -1); + lua_pop(ref.lua_state(), 1); + // leave key on the stack + keyidx = lua_gettop(ref.lua_state()); + return *this; + } + + basic_table_iterator operator++(int) { + auto saved = *this; + this->operator++(); + return saved; + } + + reference operator*() { + return kvp; + } + + const_reference operator*() const { + return kvp; + } + + bool operator== (const basic_table_iterator& right) const { + return idx == right.idx; + } + + bool operator!= (const basic_table_iterator& right) const { + return idx != right.idx; + } + + ~basic_table_iterator() { + if (keyidx != -1) { + stack::remove(ref.lua_state(), keyidx, 1); + } + if (ref.valid()) { + stack::remove(ref.lua_state(), tableidx, 1); + } + } + }; + +} // sol + +#endif // SOL_TABLE_ITERATOR_HPP diff --git a/3rdparty/sol2/sol/thread.hpp b/3rdparty/sol2/sol/thread.hpp new file mode 100644 index 00000000000..d4834dee4f2 --- /dev/null +++ b/3rdparty/sol2/sol/thread.hpp @@ -0,0 +1,77 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_THREAD_HPP +#define SOL_THREAD_HPP + +#include "reference.hpp" +#include "stack.hpp" + +namespace sol { + class thread : public reference { + public: + thread() noexcept = default; + thread(const thread&) = default; + thread(thread&&) = default; + thread(const stack_reference& r) : thread(r.lua_state(), r.stack_index()) {}; + thread(stack_reference&& r) : thread(r.lua_state(), r.stack_index()) {}; + thread& operator=(const thread&) = default; + thread& operator=(thread&&) = default; + thread(lua_State* L, int index = -1) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::thread); +#endif // Safety + } + + state_view state() const { + return state_view(this->thread_state()); + } + + lua_State* thread_state() const { + auto pp = stack::push_pop(*this); + lua_State* lthread = lua_tothread(lua_state(), -1); + return lthread; + } + + thread_status status() const { + lua_State* lthread = thread_state(); + thread_status lstat = static_cast(lua_status(lthread)); + if (lstat != thread_status::ok && lua_gettop(lthread) == 0) { + // No thing on the thread's stack means its dead + return thread_status::dead; + } + return lstat; + } + + thread create() { + return create(lua_state()); + } + + static thread create(lua_State* L) { + lua_newthread(L); + thread result(L); + lua_pop(L, 1); + return result; + } + }; +} // sol + +#endif // SOL_THREAD_HPP diff --git a/3rdparty/sol2/sol/tie.hpp b/3rdparty/sol2/sol/tie.hpp new file mode 100644 index 00000000000..fc3ec155044 --- /dev/null +++ b/3rdparty/sol2/sol/tie.hpp @@ -0,0 +1,101 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TIE_HPP +#define SOL_TIE_HPP + +#include "traits.hpp" + +namespace sol { + + namespace detail { + template + struct is_speshul : std::false_type {}; + } + + template + struct tie_size : std::tuple_size {}; + + template + struct is_tieable : std::integral_constant::value > 0)> {}; + + template + struct tie_t : public std::tuple...> { + private: + typedef std::tuple...> base_t; + + template + void set(std::false_type, T&& target) { + std::get<0>(*this) = std::forward(target); + } + + template + void set(std::true_type, T&& target) { + typedef tie_size> value_size; + typedef tie_size> tie_size; + typedef std::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; + typedef std::make_index_sequence indices; + set_extra(detail::is_speshul>(), indices(), std::forward(target)); + } + + template + void set_extra(std::true_type, std::index_sequence, T&& target) { + using std::get; + (void)detail::swallow{ 0, + (get(*this) = get(types(), target), 0)... + , 0 }; + } + + template + void set_extra(std::false_type, std::index_sequence, T&& target) { + using std::get; + (void)detail::swallow{ 0, + (get(*this) = get(target), 0)... + , 0 }; + } + + public: + using base_t::base_t; + + template + tie_t& operator= (T&& value) { + typedef is_tieable> tieable; + set(tieable(), std::forward(value)); + return *this; + } + + }; + + template + struct tie_size< tie_t > : std::tuple_size< std::tuple > { }; + + namespace adl_barrier_detail { + template + inline tie_t...> tie(Tn&&... argn) { + return tie_t...>(std::forward(argn)...); + } + } + + using namespace adl_barrier_detail; + +} // sol + +#endif // SOL_TIE_HPP diff --git a/3rdparty/sol2/sol/traits.hpp b/3rdparty/sol2/sol/traits.hpp new file mode 100644 index 00000000000..1721b90e866 --- /dev/null +++ b/3rdparty/sol2/sol/traits.hpp @@ -0,0 +1,425 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TRAITS_HPP +#define SOL_TRAITS_HPP + +#include "tuple.hpp" +#include "bind_traits.hpp" +#include +#include +#include + +namespace sol { + template + using index_value = std::integral_constant; + + namespace meta { + template + struct identity { typedef T type; }; + + template + using identity_t = typename identity::type; + + template + struct is_tuple : std::false_type { }; + + template + struct is_tuple> : std::true_type { }; + + template + struct unwrapped { + typedef T type; + }; + + template + struct unwrapped> { + typedef T type; + }; + + template + using unwrapped_t = typename unwrapped::type; + + template + struct unwrap_unqualified : unwrapped> {}; + + template + using unwrap_unqualified_t = typename unwrap_unqualified::type; + + template + struct remove_member_pointer; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + using remove_member_pointer_t = remove_member_pointer; + + template class Templ, typename T> + struct is_specialization_of : std::false_type { }; + template class Templ> + struct is_specialization_of> : std::true_type { }; + + template + struct all_same : std::true_type { }; + + template + struct all_same : std::integral_constant ::value && all_same::value> { }; + + template + struct any_same : std::false_type { }; + + template + struct any_same : std::integral_constant ::value || any_same::value> { }; + + template + using invoke_t = typename T::type; + + template + using boolean = std::integral_constant; + + template + using neg = boolean; + + template + using condition = std::conditional_t; + + template + struct all : boolean {}; + + template + struct all : condition, boolean> {}; + + template + struct any : boolean {}; + + template + struct any : condition, any> {}; + + enum class enable_t { + _ + }; + + constexpr const auto enabler = enable_t::_; + + template + using disable_if_t = std::enable_if_t; + + template + using enable = std::enable_if_t::value, enable_t>; + + template + using disable = std::enable_if_t>::value, enable_t>; + + template + using disable_any = std::enable_if_t>::value, enable_t>; + + template + struct find_in_pack_v : boolean { }; + + template + struct find_in_pack_v : any, find_in_pack_v> { }; + + namespace meta_detail { + template + struct index_in_pack : std::integral_constant { }; + + template + struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> { }; + } + + template + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct index_in : meta_detail::index_in_pack<0, T, List> { }; + + template + struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct at_in_pack {}; + + template + using at_in_pack_t = typename at_in_pack::type; + + template + struct at_in_pack : std::conditional> {}; + + template + struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; + + namespace meta_detail { + template class Pred, typename... Ts> + struct count_for_pack : std::integral_constant {}; + template class Pred, typename T, typename... Ts> + struct count_for_pack : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, + std::integral_constant(Limit != 0 && Pred::value)>, + count_for_pack(Pred::value), Pred, Ts...> + > { }; + template class Pred, typename... Ts> + struct count_2_for_pack : std::integral_constant {}; + template class Pred, typename T, typename U, typename... Ts> + struct count_2_for_pack : std::conditional_t(Pred::value)>, + count_2_for_pack(Pred::value), Pred, Ts...> + > { }; + } // meta_detail + + template class Pred, typename... Ts> + struct count_for_pack : meta_detail::count_for_pack { }; + + template class Pred, typename List> + struct count_for; + + template class Pred, typename... Args> + struct count_for> : count_for_pack {}; + + template class Pred, typename... Ts> + struct count_for_to_pack : meta_detail::count_for_pack { }; + + template class Pred, typename... Ts> + struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; + + template + struct return_type { + typedef std::tuple type; + }; + + template + struct return_type { + typedef T type; + }; + + template<> + struct return_type<> { + typedef void type; + }; + + template + using return_type_t = typename return_type::type; + + namespace meta_detail { + template struct always_true : std::true_type {}; + struct is_invokable_tester { + template + always_true()(std::declval()...))> static test(int); + template + std::false_type static test(...); + }; + } // meta_detail + + template + struct is_invokable; + template + struct is_invokable : decltype(meta_detail::is_invokable_tester::test(0)) {}; + + namespace meta_detail { + + template>::value> + struct is_callable : std::is_function> {}; + + template + struct is_callable { + using yes = char; + using no = struct { char s[2]; }; + + struct F { void operator()(); }; + struct Derived : T, F {}; + template struct Check; + + template + static no test(Check*); + + template + static yes test(...); + + static const bool value = sizeof(test(0)) == sizeof(yes); + }; + + struct has_begin_end_impl { + template, + typename B = decltype(std::declval().begin()), + typename E = decltype(std::declval().end())> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_key_value_pair_impl { + template, + typename V = typename U::value_type, + typename F = decltype(std::declval().first), + typename S = decltype(std::declval().second)> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + template () < std::declval())> + std::true_type supports_op_less_test(const T&); + std::false_type supports_op_less_test(...); + template () == std::declval())> + std::true_type supports_op_equal_test(const T&); + std::false_type supports_op_equal_test(...); + template () <= std::declval())> + std::true_type supports_op_less_equal_test(const T&); + std::false_type supports_op_less_equal_test(...); + + } // meta_detail + + template + using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval())); + template + using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval())); + template + using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval())); + + template + struct is_callable : boolean::value> {}; + + template + struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test(0)) {}; + + template + struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; + + template + using is_string_constructible = any, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; + + template + using is_c_str = any< + std::is_same>, const char*>, + std::is_same>, char*>, + std::is_same, std::string> + >; + + template + struct is_move_only : all< + neg>, + neg>>, + std::is_move_constructible> + > {}; + + template + using is_not_move_only = neg>; + + namespace meta_detail { + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward_as_tuple(std::forward(x)); + } + + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward(x); + } + } // meta_detail + + template + decltype(auto) tuplefy(X&&... x) { + return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); + } + } // meta + namespace detail { + template + decltype(auto) forward_get(Tuple&& tuple) { + return std::forward>(std::get(tuple)); + } + + template + auto forward_tuple_impl(std::index_sequence, Tuple&& tuple) -> decltype(std::tuple(tuple))...>(forward_get(tuple)...)) { + return std::tuple(tuple))...>(std::move(std::get(tuple))...); + } + + template + auto forward_tuple(Tuple&& tuple) { + auto x = forward_tuple_impl(std::make_index_sequence>::value>(), std::forward(tuple)); + return x; + } + + template + auto unwrap(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + T& unwrap(std::reference_wrapper arg) { + return arg.get(); + } + + template + auto deref(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + inline T& deref(T* item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::shared_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::shared_ptr& item) { + return *item; + } + + template + inline T* ptr(T& val) { + return std::addressof(val); + } + + template + inline T* ptr(std::reference_wrapper val) { + return std::addressof(val.get()); + } + + template + inline T* ptr(T* val) { + return val; + } + } // detail +} // sol + +#endif // SOL_TRAITS_HPP diff --git a/3rdparty/sol2/sol/tuple.hpp b/3rdparty/sol2/sol/tuple.hpp new file mode 100644 index 00000000000..07a6d493de1 --- /dev/null +++ b/3rdparty/sol2/sol/tuple.hpp @@ -0,0 +1,80 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TUPLE_HPP +#define SOL_TUPLE_HPP + +#include +#include + +namespace sol { + namespace detail { + using swallow = std::initializer_list; + } // detail + + template + struct types { typedef std::make_index_sequence indices; static constexpr std::size_t size() { return sizeof...(Args); } }; + namespace meta { + namespace detail { + template + struct tuple_types_ { typedef types type; }; + + template + struct tuple_types_> { typedef types type; }; + } // detail + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + template + using tuple_types = typename detail::tuple_types_::type; + + template + struct pop_front_type; + + template + using pop_front_type_t = typename pop_front_type::type; + + template + struct pop_front_type> { typedef void front_type; typedef types type; }; + + template + struct pop_front_type> { typedef Arg front_type; typedef types type; }; + + template + using tuple_element = std::tuple_element>; + + template + using tuple_element_t = std::tuple_element_t>; + + template + using unqualified_tuple_element = unqualified>; + + template + using unqualified_tuple_element_t = unqualified_t>; + + } // meta +} // sol + +#endif // SOL_TUPLE_HPP diff --git a/3rdparty/sol2/sol/types.hpp b/3rdparty/sol2/sol/types.hpp new file mode 100644 index 00000000000..86ac4806532 --- /dev/null +++ b/3rdparty/sol2/sol/types.hpp @@ -0,0 +1,756 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TYPES_HPP +#define SOL_TYPES_HPP + +#include "optional.hpp" +#include "compatibility.hpp" +#include "traits.hpp" +#include "string_shim.hpp" +#include +#include + +namespace sol { + namespace detail { +#ifdef SOL_NO_EXCEPTIONS + template + int static_trampoline(lua_State* L) { + return f(L); + } + + template + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + return f(L, std::forward(args)...); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#else + template + int static_trampoline(lua_State* L) { + try { + return f(L); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } + catch (...) { + lua_pushstring(L, "caught (...) exception"); + } + return lua_error(L); + } + + template + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + try { + return f(L, std::forward(args)...); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } + catch (...) { + lua_pushstring(L, "caught (...) exception"); + } + return lua_error(L); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#endif // Exceptions vs. No Exceptions + + template + struct unique_usertype {}; + + template + struct implicit_wrapper { + T& item; + implicit_wrapper(T* item) : item(*item) {} + implicit_wrapper(T& item) : item(item) {} + operator T& () { + return item; + } + operator T* () { + return std::addressof(item); + } + }; + } // detail + + struct nil_t {}; + const nil_t nil{}; + inline bool operator==(nil_t, nil_t) { return true; } + inline bool operator!=(nil_t, nil_t) { return false; } + + struct metatable_key_t {}; + const metatable_key_t metatable_key = {}; + + struct no_metatable_t {}; + const no_metatable_t no_metatable = {}; + + typedef std::remove_pointer_t lua_r_CFunction; + + template + struct unique_usertype_traits { + typedef T type; + typedef T actual_type; + static const bool value = false; + + template + static bool is_null(U&&) { + return false; + } + + template + static auto get(U&& value) { + return std::addressof(detail::deref(value)); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::shared_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::unique_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct non_null {}; + + template + struct function_sig {}; + + struct upvalue_index { + int index; + upvalue_index(int idx) : index(lua_upvalueindex(idx)) {} + operator int() const { return index; } + }; + + struct raw_index { + int index; + raw_index(int i) : index(i) {} + operator int() const { return index; } + }; + + struct absolute_index { + int index; + absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {} + operator int() const { return index; } + }; + + struct lightuserdata_value { + void* value; + lightuserdata_value(void* data) : value(data) {} + operator void*() const { return value; } + }; + + struct userdata_value { + void* value; + userdata_value(void* data) : value(data) {} + operator void*() const { return value; } + }; + + template + struct light { + L* value; + + light(L& x) : value(std::addressof(x)) {} + light(L* x) : value(x) {} + light(void* x) : value(static_cast(x)) {} + operator L* () const { return value; } + operator L& () const { return *value; } + }; + + template + auto make_light(T& l) { + typedef meta::unwrapped_t>> L; + return light(l); + } + + template + struct user { + U value; + + user(U x) : value(std::move(x)) {} + operator U* () { return std::addressof(value); } + operator U& () { return value; } + operator const U& () const { return value; } + }; + + template + auto make_user(T&& u) { + typedef meta::unwrapped_t> U; + return user(std::forward(u)); + } + + template + struct metatable_registry_key { + T key; + + metatable_registry_key(T key) : key(std::forward(key)) {} + }; + + template + auto meta_registry_key(T&& key) { + typedef meta::unqualified_t K; + return metatable_registry_key(std::forward(key)); + } + + template + struct closure { + lua_CFunction c_function; + std::tuple upvalues; + closure(lua_CFunction f, Upvalues... upvalues) : c_function(f), upvalues(std::forward(upvalues)...) {} + }; + + template <> + struct closure<> { + lua_CFunction c_function; + int upvalues; + closure(lua_CFunction f, int upvalues = 0) : c_function(f), upvalues(upvalues) {} + }; + + typedef closure<> c_closure; + + template + closure make_closure(lua_CFunction f, Args&&... args) { + return closure(f, std::forward(args)...); + } + + template + struct function_arguments { + std::tuple arguments; + template , function_arguments>> = meta::enabler> + function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward(arg), std::forward(args)...) {} + }; + + template , typename... Args> + auto as_function(Args&&... args) { + return function_arguments...>(std::forward(args)...); + } + + template , typename... Args> + auto as_function_reference(Args&&... args) { + return function_arguments(std::forward(args)...); + } + + template + struct as_table_t { + T source; + template + as_table_t(Args&&... args) : source(std::forward(args)...) {} + + operator std::add_lvalue_reference_t () { + return source; + } + }; + + template + as_table_t as_table(T&& container) { + return as_table_t(std::forward(container)); + } + + struct this_state { + lua_State* L; + operator lua_State* () const { + return L; + } + lua_State* operator-> () const { + return L; + } + }; + + enum class call_syntax { + dot = 0, + colon = 1 + }; + + enum class call_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + handler = LUA_ERRERR, + gc = LUA_ERRGCMM + }; + + enum class thread_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + handler = LUA_ERRERR, + dead, + }; + + enum class load_status : int { + ok = LUA_OK, + syntax = LUA_ERRSYNTAX, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + file = LUA_ERRFILE, + }; + + enum class type : int { + none = LUA_TNONE, + nil = LUA_TNIL, + string = LUA_TSTRING, + number = LUA_TNUMBER, + thread = LUA_TTHREAD, + boolean = LUA_TBOOLEAN, + function = LUA_TFUNCTION, + userdata = LUA_TUSERDATA, + lightuserdata = LUA_TLIGHTUSERDATA, + table = LUA_TTABLE, + poly = none | nil | string | number | thread | + table | boolean | function | userdata | lightuserdata + }; + + enum class meta_function { + construct, + index, + new_index, + mode, + call, + metatable, + to_string, + length, + unary_minus, + addition, + subtraction, + multiplication, + division, + modulus, + power_of, + involution = power_of, + concatenation, + equal_to, + less_than, + less_than_or_equal_to, + garbage_collect, + call_function = call, + }; + + typedef meta_function meta_method; + + const std::array meta_variable_names = { { + "__index", + "__newindex", + } }; + + const std::array meta_function_names = { { + "new", + "__index", + "__newindex", + "__mode", + "__call", + "__metatable", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", + } }; + + inline const std::string& name_of(meta_function mf) { + return meta_function_names[static_cast(mf)]; + } + + inline type type_of(lua_State* L, int index) { + return static_cast(lua_type(L, index)); + } + + inline int type_panic(lua_State* L, int index, type expected, type actual) { + return luaL_error(L, "stack index %d, expected %s, received %s", index, + expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), + expected == type::poly ? "anything" : lua_typename(L, static_cast(actual)) + ); + } + + // Specify this function as the handler for lua::check if you know there's nothing wrong + inline int no_panic(lua_State*, int, type, type) noexcept { + return 0; + } + + inline void type_error(lua_State* L, int expected, int actual) { + luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); + } + + inline void type_error(lua_State* L, type expected, type actual) { + type_error(L, static_cast(expected), static_cast(actual)); + } + + inline void type_assert(lua_State* L, int index, type expected, type actual) { + if (expected != type::poly && expected != actual) { + type_panic(L, index, expected, actual); + } + } + + inline void type_assert(lua_State* L, int index, type expected) { + type actual = type_of(L, index); + type_assert(L, index, expected, actual); + } + + inline std::string type_name(lua_State* L, type t) { + return lua_typename(L, static_cast(t)); + } + + class reference; + class stack_reference; + template + struct proxy; + template + class usertype; + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + typedef table_core table; + typedef table_core global_table; + typedef stack_table_core stack_table; + typedef stack_table_core stack_global_table; + template + class basic_function; + template + class basic_protected_function; + using function = basic_function; + using protected_function = basic_protected_function; + using stack_function = basic_function; + using stack_protected_function = basic_protected_function; + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + struct variadic_args; + using object = basic_object; + using stack_object = basic_object; + using userdata = basic_userdata; + using stack_userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using stack_lightuserdata = basic_lightuserdata; + class coroutine; + class thread; + struct variadic_args; + struct this_state; + + namespace detail { + template + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template + struct lua_type_of> : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of::value>> : std::integral_constant {}; + + template + struct lua_type_of::value>> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template class V, typename... Args> + struct accumulate : std::integral_constant {}; + + template class V, typename T, typename... Args> + struct accumulate : accumulate::value, V, Args...> {}; + } // detail + + template + struct is_unique_usertype : std::integral_constant::value> {}; + + template + struct lua_type_of : detail::lua_type_of {}; + + template + struct lua_size : std::integral_constant { }; + + template + struct lua_size> : std::integral_constant::value + lua_size::value> { }; + + template + struct lua_size> : std::integral_constant::value> { }; + + template + struct is_lua_primitive : std::integral_constant>::value + || (lua_size::value > 1) + || std::is_base_of>::value + || std::is_base_of>::value + || meta::is_specialization_of>::value + || meta::is_specialization_of>::value + > { }; + + template + struct is_lua_reference : std::integral_constant>::value + || std::is_base_of>::value + || meta::is_specialization_of>::value + > { }; + + template + struct is_lua_primitive : std::true_type {}; + template + struct is_lua_primitive> : std::true_type { }; + template + struct is_lua_primitive> : std::true_type { }; + template + struct is_lua_primitive> : is_lua_primitive { }; + template + struct is_lua_primitive> : std::true_type {}; + template <> + struct is_lua_primitive : std::true_type {}; + template <> + struct is_lua_primitive : std::true_type {}; + template + struct is_lua_primitive> : is_lua_primitive {}; + + template + struct is_proxy_primitive : is_lua_primitive { }; + + template + struct is_transparent_argument : std::false_type {}; + + template <> + struct is_transparent_argument : std::true_type {}; + + template <> + struct is_transparent_argument : std::true_type {}; + + template + struct lua_bind_traits : meta::bind_traits { + private: + typedef meta::bind_traits base_t; + public: + static const std::size_t true_arity = base_t::arity; + static const std::size_t arity = base_t::arity - meta::count_for::value; + static const std::size_t true_free_arity = base_t::free_arity; + static const std::size_t free_arity = base_t::free_arity - meta::count_for::value; + }; + + template + struct is_table : std::false_type {}; + template + struct is_table> : std::true_type {}; + + template + struct is_function : std::false_type {}; + template + struct is_function> : std::true_type {}; + template + struct is_function> : std::true_type {}; + + template + struct is_lightuserdata : std::false_type {}; + template + struct is_lightuserdata> : std::true_type {}; + + template + struct is_userdata : std::false_type {}; + template + struct is_userdata> : std::true_type {}; + + template + inline type type_of() { + return lua_type_of>::value; + } +} // sol + +#endif // SOL_TYPES_HPP diff --git a/3rdparty/sol2/sol/userdata.hpp b/3rdparty/sol2/sol/userdata.hpp new file mode 100644 index 00000000000..6a4098f1a0a --- /dev/null +++ b/3rdparty/sol2/sol/userdata.hpp @@ -0,0 +1,82 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_USERDATA_HPP +#define SOL_USERDATA_HPP + +#include "reference.hpp" + +namespace sol { + template + class basic_userdata : public base_t { + public: + basic_userdata() noexcept = default; + template , basic_userdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_userdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::userdata); + } +#endif // Safety + } + basic_userdata(const basic_userdata&) = default; + basic_userdata(basic_userdata&&) = default; + basic_userdata& operator=(const basic_userdata&) = default; + basic_userdata& operator=(basic_userdata&&) = default; + basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {} + basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {} + basic_userdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::userdata); +#endif // Safety + } + }; + + template + class basic_lightuserdata : public base_t { + public: + basic_lightuserdata() noexcept = default; + template , basic_lightuserdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_lightuserdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } + basic_lightuserdata(const basic_lightuserdata&) = default; + basic_lightuserdata(basic_lightuserdata&&) = default; + basic_lightuserdata& operator=(const basic_lightuserdata&) = default; + basic_lightuserdata& operator=(basic_lightuserdata&&) = default; + basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::lightuserdata); +#endif // Safety + } + }; + +} // sol + +#endif // SOL_USERDATA_HPP diff --git a/3rdparty/sol2/sol/usertype.hpp b/3rdparty/sol2/sol/usertype.hpp new file mode 100644 index 00000000000..7fae5119c6d --- /dev/null +++ b/3rdparty/sol2/sol/usertype.hpp @@ -0,0 +1,97 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_USERTYPE_HPP +#define SOL_USERTYPE_HPP + +#include "stack.hpp" +#include "usertype_metatable.hpp" +#include "simple_usertype_metatable.hpp" +#include "container_usertype_metatable.hpp" +#include + +namespace sol { + + template + class usertype { + private: + std::unique_ptr metatableregister; + + template + usertype(usertype_detail::verified_tag, Args&&... args) : metatableregister(detail::make_unique_deleter, Args...>, detail::deleter>(std::forward(args)...)) {} + + template + usertype(usertype_detail::add_destructor_tag, Args&&... args) : usertype(usertype_detail::verified, std::forward(args)..., "__gc", default_destructor) {} + + template + usertype(usertype_detail::check_destructor_tag, Args&&... args) : usertype(meta::condition, meta::neg>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward(args)...) {} + + public: + + template + usertype(Args&&... args) : usertype(meta::condition, meta::neg>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward(args)...) {} + + template + usertype(constructors constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + usertype(constructor_wrapper constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter, detail::deleter>(L, std::forward(args)...)) {} + + usertype_detail::registrar* registrar_data() { + return metatableregister.get(); + } + + int push(lua_State* L) { + return metatableregister->push_um(L); + } + }; + + template + class simple_usertype : public usertype { + private: + typedef usertype base_t; + lua_State* state; + + public: + template + simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward(args)...), state(L) {} + + template + void set(N&& n, F&& f) { + auto meta = static_cast*>(base_t::registrar_data()); + meta->add(state, n, f); + } + }; + + namespace stack { + template + struct pusher> { + static int push(lua_State* L, usertype& user) { + return user.push(L); + } + }; + } // stack +} // sol + +#endif // SOL_USERTYPE_HPP diff --git a/3rdparty/sol2/sol/usertype_metatable.hpp b/3rdparty/sol2/sol/usertype_metatable.hpp new file mode 100644 index 00000000000..cd57f2679b9 --- /dev/null +++ b/3rdparty/sol2/sol/usertype_metatable.hpp @@ -0,0 +1,583 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_USERTYPE_METATABLE_HPP +#define SOL_USERTYPE_METATABLE_HPP + +#include "wrapper.hpp" +#include "call.hpp" +#include "stack.hpp" +#include "types.hpp" +#include "stack_reference.hpp" +#include "usertype_traits.hpp" +#include "inheritance.hpp" +#include "raii.hpp" +#include "deprecate.hpp" +#include +#include + +namespace sol { + namespace usertype_detail { + struct no_comp { + template + bool operator()(A&&, B&&) const { + return false; + } + }; + + typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); + typedef int(*member_search)(lua_State*, void*); + + struct find_call_pair { + member_search first; + member_search second; + + find_call_pair(member_search first, member_search second) : first(first), second(second) {} + }; + + inline bool is_indexer(string_detail::string_shim s) { + return s == name_of(meta_function::index) || s == name_of(meta_function::new_index); + } + + inline bool is_indexer(meta_function mf) { + return mf == meta_function::index || mf == meta_function::new_index; + } + + inline bool is_indexer(call_construction) { + return false; + } + + inline bool is_indexer(base_classes_tag) { + return false; + } + + inline auto make_shim(string_detail::string_shim s) { + return s; + } + + inline auto make_shim(call_construction) { + return string_detail::string_shim(name_of(meta_function::call_function)); + } + + inline auto make_shim(meta_function mf) { + return string_detail::string_shim(name_of(mf)); + } + + inline auto make_shim(base_classes_tag) { + return string_detail::string_shim(detail::base_class_cast_key()); + } + + template + inline std::string make_string(Arg&& arg) { + string_detail::string_shim s = make_shim(arg); + return std::string(s.c_str(), s.size()); + } + + template + inline luaL_Reg make_reg(N&& n, lua_CFunction f) { + luaL_Reg l{ make_shim(std::forward(n)).c_str(), f }; + return l; + } + + struct registrar { + virtual int push_um(lua_State* L) = 0; + virtual ~registrar() {} + }; + + template + inline int indexing_fail(lua_State* L) { + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + if (is_index) + return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + else + return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + } + + template + static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { + if (found) + return; + const char* metakey = &usertype_traits::metatable[0]; + const char* gcmetakey = &usertype_traits::gc_table[0]; + const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); + + luaL_getmetatable(L, metakey); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 1); + return; + } + + stack::get_field(L, basewalkkey); + if (type_of(L, -1) == type::nil) { + lua_pop(L, 2); + return; + } + lua_CFunction basewalkfunc = stack::pop(L); + lua_pop(L, 1); + + stack::get_field(L, gcmetakey); + int value = basewalkfunc(L); + if (value > -1) { + found = true; + ret = value; + } + } + + template + static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { + (void)L; + (void)found; + (void)ret; + (void)accessor; + (void)detail::swallow{ 0, (walk_single_base(L, found, ret, accessor), 0)... }; + } + + template + inline int operator_wrap(lua_State* L) { + auto maybel = stack::check_get(L, 1); + if (maybel) { + auto mayber = stack::check_get(L, 2); + if (mayber) { + auto& l = *maybel; + auto& r = *mayber; + if (std::is_same::value) { + return stack::push(L, detail::ptr(l) == detail::ptr(r)); + } + else { + Op op; + return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); + } + } + } + return stack::push(L, false); + } + + template = meta::enabler> + inline void make_reg_op(Regs& l, int& index, const char* name) { + l[index] = { name, &operator_wrap }; + ++index; + } + + template = meta::enabler> + inline void make_reg_op(Regs&, int&, const char*) { + // Do nothing if there's no support + } + + struct add_destructor_tag {}; + struct check_destructor_tag {}; + struct verified_tag {} const verified{}; + + template + struct is_constructor : std::false_type {}; + + template + struct is_constructor> : std::true_type {}; + + template + struct is_constructor> : std::true_type {}; + + template + struct is_constructor> : std::true_type {}; + + template <> + struct is_constructor : std::true_type {}; + + template + using has_constructor = meta::any>...>; + + template + struct is_destructor : std::false_type {}; + + template + struct is_destructor> : std::true_type {}; + + template + using has_destructor = meta::any>...>; + + } // usertype_detail + + template + struct clean_type { + typedef std::conditional_t>::value, T&, std::decay_t> type; + }; + + template + using clean_type_t = typename clean_type::type; + + template + struct usertype_metatable : usertype_detail::registrar {}; + + template + struct usertype_metatable, Tn...> : usertype_detail::registrar { + typedef std::make_index_sequence indices; + typedef std::index_sequence half_indices; + typedef std::array regs_t; + typedef std::tuple RawTuple; + typedef std::tuple ...> Tuple; + template + struct check_binding : is_variable_binding> {}; + typedef std::unordered_map mapping_t; + Tuple functions; + mapping_t mapping; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + lua_CFunction destructfunc; + lua_CFunction callconstructfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool mustindex; + bool secondarymeta; + bool hasequals; + bool hasless; + bool haslessequals; + + template >> = meta::enabler> + inline lua_CFunction make_func() { + return std::get(functions); + } + + template >> = meta::enabler> + inline lua_CFunction make_func() { + return call; + } + + static bool contains_variable() { + typedef meta::any...> has_variables; + return has_variables::value; + } + + bool contains_index() const { + bool idx = false; + (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get(functions))), 0) ... }; + return idx; + } + + int finish_regs(regs_t& l, int& index) { + if (!hasless) { + const char* name = name_of(meta_function::less_than).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less>(l, index, name); + } + if (!haslessequals) { + const char* name = name_of(meta_function::less_than_or_equal_to).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less_equal>(l, index, name); + } + if (!hasequals) { + const char* name = name_of(meta_function::equal_to).c_str(); + usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); + } + if (destructfunc != nullptr) { + l[index] = { name_of(meta_function::garbage_collect).c_str(), destructfunc }; + ++index; + } + return index; + } + + template + void make_regs(regs_t&, int&, call_construction, F&&) { + callconstructfunc = call; + secondarymeta = true; + } + + template + void make_regs(regs_t&, int&, base_classes_tag, bases) { + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::value = true), 0)... }; + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + + template , base_classes_tag, call_construction>::value>> + void make_regs(regs_t& l, int& index, N&& n, F&&) { + if (is_variable_binding>::value) { + return; + } + luaL_Reg reg = usertype_detail::make_reg(std::forward(n), make_func()); + // Returnable scope + // That would be a neat keyword for C++ + // returnable { ... }; + if (reg.name == name_of(meta_function::equal_to)) { + hasequals = true; + } + if (reg.name == name_of(meta_function::less_than)) { + hasless = true; + } + if (reg.name == name_of(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + if (reg.name == name_of(meta_function::garbage_collect)) { + destructfunc = reg.func; + return; + } + else if (reg.name == name_of(meta_function::index)) { + indexfunc = reg.func; + mustindex = true; + return; + } + else if (reg.name == name_of(meta_function::new_index)) { + newindexfunc = reg.func; + mustindex = true; + return; + } + l[index] = reg; + ++index; + } + + template > + usertype_metatable(Args&&... args) : functions(std::forward(args)...), + mapping(), + indexfunc(usertype_detail::indexing_fail), newindexfunc(usertype_detail::indexing_fail), + destructfunc(nullptr), callconstructfunc(nullptr), + indexbase(&core_indexing_call), newindexbase(&core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()), + hasequals(false), hasless(false), haslessequals(false) { + std::initializer_list ilist{ { + std::pair( + usertype_detail::make_string(std::get(functions)), + usertype_detail::find_call_pair(&usertype_metatable::real_find_call, + &usertype_metatable::real_find_call) + ) + }... }; + mapping.insert(ilist); + } + + template + static int real_find_call(lua_State* L, void* um) { + auto& f = *static_cast(um); + if (is_variable_binding(f.functions))>::value) { + return real_call_with(L, f); + } + return stack::push(L, c_closure(call, stack::push(L, light(f)))); + } + + template + static int core_indexing_call(lua_State* L) { + usertype_metatable& f = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + static const int keyidx = -2 + static_cast(is_index); + if (toplevel && stack::get(L, keyidx) != type::string) { + return is_index ? f.indexfunc(L) : f.newindexfunc(L); + } + std::string name = stack::get(L, keyidx); + auto memberit = f.mapping.find(name); + if (memberit != f.mapping.cend()) { + auto& member = is_index ? memberit->second.second : memberit->second.first; + return (member)(L, static_cast(&f)); + } + string_detail::string_shim accessor = name; + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) + f.indexbaseclasspropogation(L, found, ret, accessor); + else + f.newindexbaseclasspropogation(L, found, ret, accessor); + if (found) { + return ret; + } + return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; + } + + static int real_index_call(lua_State* L) { + return core_indexing_call(L); + } + + static int real_new_index_call(lua_State* L) { + return core_indexing_call(L); + } + + template + static int real_call(lua_State* L) { + usertype_metatable& f = stack::get>(L, upvalue_index(1)); + return real_call_with(L, f); + } + + template + static int real_call_with(lua_State* L, usertype_metatable& um) { + auto& f = std::get(um.functions); + return call_detail::call_wrapped(L, f); + } + + template + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + template + static int call_with(lua_State* L) { + return detail::static_trampoline<(&real_call_with)>(L); + } + + static int index_call(lua_State* L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State* L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + + virtual int push_um(lua_State* L) override { + return stack::push(L, std::move(*this)); + } + + ~usertype_metatable() override { + + } + }; + + namespace stack { + + template + struct pusher, Args...>> { + typedef usertype_metatable, Args...> umt_t; + typedef typename umt_t::regs_t regs_t; + + static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { + // ensure some sort of uniqueness + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable; + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table[0]; + // Make sure userdata's memory is properly in lua first, + // otherwise all the light userdata we make later will become invalid + stack::push>(L, metatable_key, uniquegcmetakey, std::move(umx)); + // Create the top level thing that will act as our deleter later on + stack_reference umt(L, -1); + stack::set_field(L, gcmetakey, umt); + umt.pop(); + + stack::get_field(L, gcmetakey); + return stack::pop>(L); + } + + static int push(lua_State* L, umt_t&& umx) { + + umt_t& um = make_cleanup(L, std::move(umx)); + regs_t value_table{ {} }; + int lastreg = 0; + (void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... }; + um.finish_regs(value_table, lastreg); + value_table[lastreg] = { nullptr, nullptr }; + regs_t ref_table = value_table; + regs_t unique_table = value_table; + bool hasdestructor = !value_table.empty() && name_of(meta_function::garbage_collect) == value_table[lastreg - 1].name; + if (hasdestructor) { + ref_table[lastreg - 1] = { nullptr, nullptr }; + unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct }; + } + + // Now use um + const bool& mustindex = um.mustindex; + for (std::size_t i = 0; i < 3; ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + luaL_Reg* metaregs = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable[0]; + metaregs = ref_table.data(); + break; + case 1: + metakey = &usertype_traits>::metatable[0]; + metaregs = unique_table.data(); + break; + case 2: + default: + metakey = &usertype_traits::metatable[0]; + metaregs = value_table.data(); + break; + } + luaL_newmetatable(L, metakey); + stack_reference t(L, -1); + stack::push(L, make_light(um)); + luaL_setfuncs(L, metaregs, 1); + + if (um.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); + } + if (um.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); + } + + stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um)), t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um)), t.stack_index()); + + if (mustindex) { + // Basic index pushing: specialize + // index and newindex to give variables and stuff + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), t.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), t.stack_index()); + } + else { + // If there's only functions, we can use the fast index version + stack::set_field(L, meta_function::index, t, t.stack_index()); + } + // metatable on the metatable + // for call constructor purposes and such + lua_createtable(L, 0, 1); + stack_reference metabehind(L, -1); + if (um.callconstructfunc != nullptr) { + stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); + } + if (um.secondarymeta) { + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); + } + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + // We want to just leave the table + // in the registry only, otherwise we return it + if (i < 2) { + t.pop(); + } + } + + return 1; + } + }; + + } // stack + +} // sol + +#endif // SOL_USERTYPE_METATABLE_HPP diff --git a/3rdparty/sol2/sol/usertype_traits.hpp b/3rdparty/sol2/sol/usertype_traits.hpp new file mode 100644 index 00000000000..2dd3d62cbaf --- /dev/null +++ b/3rdparty/sol2/sol/usertype_traits.hpp @@ -0,0 +1,55 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_USERTYPE_TRAITS_HPP +#define SOL_USERTYPE_TRAITS_HPP + +#include "demangle.hpp" + +namespace sol { + + template + struct usertype_traits { + static const std::string name; + static const std::string qualified_name; + static const std::string metatable; + static const std::string user_gc_metatable; + static const std::string gc_table; + }; + + template + const std::string usertype_traits::name = detail::short_demangle(); + + template + const std::string usertype_traits::qualified_name = detail::demangle(); + + template + const std::string usertype_traits::metatable = std::string("sol.").append(detail::demangle()); + + template + const std::string usertype_traits::user_gc_metatable = std::string("sol.").append(detail::demangle()).append(".user\xE2\x99\xBB"); + + template + const std::string usertype_traits::gc_table = std::string("sol.").append(detail::demangle().append(".\xE2\x99\xBB")); + +} + +#endif // SOL_USERTYPE_TRAITS_HPP diff --git a/3rdparty/sol2/sol/variadic_args.hpp b/3rdparty/sol2/sol/variadic_args.hpp new file mode 100644 index 00000000000..36fa3cda7e2 --- /dev/null +++ b/3rdparty/sol2/sol/variadic_args.hpp @@ -0,0 +1,236 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_VARIADIC_ARGS_HPP +#define SOL_VARIADIC_ARGS_HPP + +#include "stack.hpp" +#include "stack_proxy.hpp" +#include +#include + +namespace sol { + template + struct va_iterator : std::iterator, std::ptrdiff_t, std::conditional_t, std::conditional_t> { + typedef std::iterator, std::ptrdiff_t, std::conditional_t, std::conditional_t> base_t; + typedef typename base_t::reference reference; + typedef typename base_t::pointer pointer; + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::iterator_category iterator_category; + lua_State* L; + int index; + int stacktop; + stack_proxy sp; + + va_iterator() : L(nullptr), index((std::numeric_limits::max)()), stacktop((std::numeric_limits::max)()) {} + va_iterator(lua_State* L, int index, int stacktop) : L(L), index(index), stacktop(stacktop), sp(L, index) {} + + reference operator*() { + return stack_proxy(L, index); + } + + pointer operator->() { + sp = stack_proxy(L, index); + return &sp; + } + + va_iterator& operator++ () { + ++index; + return *this; + } + + va_iterator operator++ (int) { + auto r = *this; + this->operator ++(); + return r; + } + + va_iterator& operator-- () { + --index; + return *this; + } + + va_iterator operator-- (int) { + auto r = *this; + this->operator --(); + return r; + } + + va_iterator& operator+= (difference_type idx) { + index += static_cast(idx); + return *this; + } + + va_iterator& operator-= (difference_type idx) { + index -= static_cast(idx); + return *this; + } + + difference_type operator- (const va_iterator& r) const { + return index - r.index; + } + + va_iterator operator+ (difference_type idx) const { + va_iterator r = *this; + r += idx; + return r; + } + + reference operator[](difference_type idx) { + return stack_proxy(L, index + static_cast(idx)); + } + + bool operator==(const va_iterator& r) const { + if (stacktop == (std::numeric_limits::max)()) { + return r.index == r.stacktop; + } + else if (r.stacktop == (std::numeric_limits::max)()) { + return index == stacktop; + } + return index == r.index; + } + + bool operator != (const va_iterator& r) const { + return !(this->operator==(r)); + } + + bool operator < (const va_iterator& r) const { + return index < r.index; + } + + bool operator > (const va_iterator& r) const { + return index > r.index; + } + + bool operator <= (const va_iterator& r) const { + return index <= r.index; + } + + bool operator >= (const va_iterator& r) const { + return index >= r.index; + } + }; + + template + inline va_iterator operator+(typename va_iterator::difference_type n, const va_iterator& r) { + return r + n; + } + + struct variadic_args { + private: + lua_State* L; + int index; + int stacktop; + + public: + typedef stack_proxy reference_type; + typedef stack_proxy value_type; + typedef stack_proxy* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef va_iterator iterator; + typedef va_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + variadic_args() = default; + variadic_args(lua_State* L, int index = -1) : L(L), index(lua_absindex(L, index)), stacktop(lua_gettop(L)) {} + variadic_args(const variadic_args&) = default; + variadic_args& operator=(const variadic_args&) = default; + variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + } + variadic_args& operator=(variadic_args&& o) { + L = o.L; + index = o.index; + stacktop = o.stacktop; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + return *this; + } + + iterator begin() { return iterator(L, index, stacktop + 1); } + iterator end() { return iterator(L, stacktop + 1, stacktop + 1); } + const_iterator begin() const { return const_iterator(L, index, stacktop + 1); } + const_iterator end() const { return const_iterator(L, stacktop + 1, stacktop + 1); } + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + reverse_iterator rbegin() { return std::reverse_iterator(begin()); } + reverse_iterator rend() { return std::reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return std::reverse_iterator(begin()); } + const_reverse_iterator rend() const { return std::reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return std::reverse_iterator(cbegin()); } + const_reverse_iterator crend() const { return std::reverse_iterator(cend()); } + + int push() const { + int pushcount = 0; + for (int i = index; i <= stacktop; ++i) { + lua_pushvalue(L, i); + pushcount += 1; + } + return pushcount; + } + + template + decltype(auto) get(difference_type start = 0) const { + return stack::get(L, index + static_cast(start)); + } + + stack_proxy operator[](difference_type start) const { + return stack_proxy(L, index + static_cast(start)); + } + + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + int leftover_count() const { return stacktop - (index - 1); } + int top() const { return stacktop; } + }; + + namespace stack { + template <> + struct getter { + static variadic_args get(lua_State* L, int index, record& tracking) { + tracking.last = 0; + return variadic_args(L, index); + } + }; + + template <> + struct pusher { + static int push(lua_State*, const variadic_args& ref) { + return ref.push(); + } + }; + } // stack +} // sol + +#endif // SOL_VARIADIC_ARGS_HPP diff --git a/3rdparty/sol2/sol/wrapper.hpp b/3rdparty/sol2/sol/wrapper.hpp new file mode 100644 index 00000000000..7e38d39f3fe --- /dev/null +++ b/3rdparty/sol2/sol/wrapper.hpp @@ -0,0 +1,233 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_WRAPPER_HPP +#define SOL_WRAPPER_HPP + +#include "types.hpp" + +namespace sol { + + template + struct wrapper { + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) call(F& f, Args&&... args) { + return f(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward(args)...); + } + }; + }; + + template + struct wrapper>>::value>> { + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) invoke(Args&&... args) { + return fx(std::forward(args)...); + } + + template + static decltype(auto) call(F& fx, Args&&... args) { + return fx(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + }; + }; + + template + struct wrapper>::value>> { + typedef lua_bind_traits traits_type; + typedef typename traits_type::object_type object_type; + typedef typename traits_type::return_type return_type; + typedef typename traits_type::args_list args_list; + typedef types free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) invoke(object_type& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + template + static decltype(auto) call(Fx&& fx, object_type& mem) { + return (mem.*fx); + } + + template + static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { + (mem.*fx) = std::forward(arg); + } + + struct caller { + template + decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { + return call(std::forward(fx), mem, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + }; + }; + + template + struct member_function_wrapper { + typedef O object_type; + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + + template + static R invoke(O& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + template + static R call(Fx&& fx, O& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { + return call(std::forward(fx), mem, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(O& mem, Args&&... args) const { + return invoke(mem, std::forward(args)...); + } + }; + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + +} // sol + +#endif // SOL_WRAPPER_HPP diff --git a/3rdparty/sol2/test_containers.cpp b/3rdparty/sol2/test_containers.cpp new file mode 100644 index 00000000000..015fbd20db0 --- /dev/null +++ b/3rdparty/sol2/test_containers.cpp @@ -0,0 +1,310 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +std::vector test_table_return_one() { + return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; +} + +std::vector> test_table_return_two() { + return{ { "one", 1 },{ "two", 2 },{ "three", 3 } }; +} + +std::map test_table_return_three() { + return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } }; +} + +TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") { + sol::state lua; + std::vector v{ 1, 2, 3 }; + lua.set_function("f", [&]() -> std::vector& { + return v; + }); + lua.script("x = f()"); + sol::object x = lua["x"]; + sol::type xt = x.get_type(); + REQUIRE(xt == sol::type::userdata); + sol::table t = x; + bool matching; + matching = t[1] == 1; + REQUIRE(matching); + matching = t[2] == 2; + REQUIRE(matching); + matching = t[3] == 3; + REQUIRE(matching); +} + +TEST_CASE("containers/vector_roundtrip", "make sure vectors can be round-tripped") { + sol::state lua; + std::vector v{ 1, 2, 3 }; + lua.set_function("f", [&]() -> std::vector& { + return v; + }); + lua.script("x = f()"); + std::vector x = lua["x"]; + bool areequal = x == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/list_roundtrip", "make sure lists can be round-tripped") { + sol::state lua; + std::list v{ 1, 2, 3 }; + lua.set_function("f", [&]() -> std::list& { + return v; + }); + lua.script("x = f()"); + std::list x = lua["x"]; + bool areequal = x == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/map_roundtrip", "make sure maps can be round-tripped") { + sol::state lua; + std::map v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; + lua.set_function("f", [&]() -> std::map& { + return v; + }); + lua.script("x = f()"); + std::map x = lua["x"]; + bool areequal = x == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/unordered_map_roundtrip", "make sure unordered_maps can be round-tripped") { + sol::state lua; + std::unordered_map v{ { "a", 1 },{ "b", 2 },{ "c", 3 } }; + lua.set_function("f", [&]() -> std::unordered_map& { + return v; + }); + lua.script("x = f()"); + std::unordered_map x = lua["x"]; + bool areequal = x == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/unordered_set_roundtrip", "make sure unordered_sets can be round-tripped") { + sol::state lua; + std::unordered_set v{ 1, 2, 3 }; + lua.set_function("f", [&]() -> std::unordered_set& { + return v; + }); + lua.script("x = f()"); + std::unordered_set x = lua["x"]; + bool areequal = x == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/set_roundtrip", "make sure sets can be round-tripped") { + sol::state lua; + std::set v{ 1, 2, 3 }; + lua.set_function("f", [&]() -> std::set& { + return v; + }); + lua.script("x = f()"); + std::set x = lua["x"]; + bool areequal = x == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/custom-usertype", "make sure container usertype metatables can be overridden") { + typedef std::unordered_map bark; + + sol::state lua; + lua.open_libraries(); + lua.new_usertype("bark", + "something", [](const bark& b) { + INFO("It works: " << b.at(24)); + }, + "size", &bark::size, + "at", sol::resolve(&bark::at), + "clear", &bark::clear + ); + bark obj{ { 24, 50 } }; + lua.set("a", &obj); + REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)")); + REQUIRE_NOTHROW(lua.script("a:something()")); + lua.set("a", obj); + REQUIRE_NOTHROW(lua.script("assert(a:at(24) == 50)")); + REQUIRE_NOTHROW(lua.script("a:something()")); +} + +TEST_CASE("containers/const-serialization-kvp", "make sure const keys / values are respected") { + typedef std::map bark; + + sol::state lua; + lua.open_libraries(); + bark obj{ { 24, 50 } }; + lua.set("a", &obj); + REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)")); + REQUIRE_THROWS(lua.script("a[24] = 51")); + REQUIRE_NOTHROW(lua.script("assert(a[24] == 50)")); +} + +TEST_CASE("containers/basic-serialization", "make sure containers are turned into proper userdata and have basic hooks established") { + typedef std::vector woof; + sol::state lua; + lua.open_libraries(); + lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }); + REQUIRE_NOTHROW( + lua.script("for k = 1, #b do assert(k == b[k]) end"); + ); + woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; + lua.set("b", w); + REQUIRE_NOTHROW( + lua.script("for k = 1, #b do assert(k == b[k]) end"); + ); + lua.set("b", &w); + REQUIRE_NOTHROW( + lua.script("for k = 1, #b do assert(k == b[k]) end"); + ); + lua.set("b", std::ref(w)); + REQUIRE_NOTHROW( + lua.script("for k = 1, #b do assert(k == b[k]) end"); + ); +} + +#if 0 // glibc is a fuccboi +TEST_CASE("containers/const-serialization", "make sure containers are turned into proper userdata and the basic hooks respect const-ness") { + typedef std::vector woof; + sol::state lua; + lua.open_libraries(); + lua.set("b", woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }); + REQUIRE_NOTHROW( + lua.script("for k, v in pairs(b) do assert(k == v) end"); + ); + REQUIRE_THROWS(lua.script("b[1] = 20")); +} +#endif // Fuck you, glibc + +TEST_CASE("containers/table-serialization", "ensure types can be serialized as tables still") { + typedef std::vector woof; + sol::state lua; + lua.open_libraries(); + lua.set("b", sol::as_table(woof{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 })); + REQUIRE_NOTHROW( + lua.script("for k, v in ipairs(b) do assert(k == v) end"); + ); + woof w{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }; + lua.set("b", sol::as_table(w)); + REQUIRE_NOTHROW( + lua.script("for k, v in ipairs(b) do assert(k == v) end"); + ); + lua.set("b", sol::as_table(&w)); + REQUIRE_NOTHROW( + lua.script("for k, v in ipairs(b) do assert(k == v) end"); + ); + lua.set("b", sol::as_table(std::ref(w))); + REQUIRE_NOTHROW( + lua.script("for k, v in ipairs(b) do assert(k == v) end"); + ); +} + +TEST_CASE("containers/const-correctness", "usertype metatable names should reasonably ignore const attributes") { + struct Vec { + int x, y, z; + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("Vec", "x", &Vec::x, "y", &Vec::y, "z", &Vec::z); + + Vec vec; + vec.x = 1; + vec.y = 2; + vec.z = -3; + + std::vector foo; + foo.push_back(vec); + + std::vector bar; + bar.push_back(&vec); + + lua.script(R"( +func = function(vecs) + for i = 1, #vecs do + vec = vecs[i] + print(i, ":", vec.x, vec.y, vec.z) + end +end +)"); + + REQUIRE_NOTHROW({ + lua["func"](foo); + lua["func"](bar); + }); +} + +TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable from standard containers") { + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.set_function("test_one", test_table_return_one); + lua.set_function("test_two", test_table_return_two); + lua.set_function("test_three", test_table_return_three); + + REQUIRE_NOTHROW(lua.script("a = test_one()")); + REQUIRE_NOTHROW(lua.script("b = test_two()")); + REQUIRE_NOTHROW(lua.script("c = test_three()")); + + REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(b.one == 1, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')")); + REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')")); + REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')")); + + sol::table a = lua.get("a"); + sol::table b = lua.get("b"); + sol::table c = lua.get("c"); + + REQUIRE(a.size() == 10ULL); + REQUIRE(a.get(3) == 3); + REQUIRE(b.get("one") == 1); + REQUIRE(b.get("three") == 3); + REQUIRE(c.get("name") == "Rapptz"); + REQUIRE(c.get("project") == "sol"); +} + +TEST_CASE("containers/usertype-transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") { + class A { + public: + int a; + A(int b = 2) : a(b) {}; + + void func() { } + }; + + struct B { + + B() { + for (std::size_t i = 0; i < 20; ++i) { + a_list.emplace_back(static_cast(i)); + } + } + + std::vector a_list; + }; + + sol::state lua; + lua.new_usertype("B", + "a_list", &B::a_list + ); + + lua.script(R"( +b = B.new() +a_ref = b.a_list[2] +)"); + + B& b = lua["b"]; + A& a_ref = lua["a_ref"]; + REQUIRE(&b.a_list[1] == &a_ref); + REQUIRE(b.a_list[1].a == a_ref.a); +} diff --git a/3rdparty/sol2/test_coroutines.cpp b/3rdparty/sol2/test_coroutines.cpp new file mode 100644 index 00000000000..1581dc3d5a8 --- /dev/null +++ b/3rdparty/sol2/test_coroutines.cpp @@ -0,0 +1,64 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +TEST_CASE("threading/coroutines", "ensure calling a coroutine works") { + const auto& script = R"(counter = 20 + +function loop() + while counter ~= 30 + do + coroutine.yield(counter); + counter = counter + 1; + end + return counter +end +)"; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::coroutine); + lua.script(script); + sol::coroutine cr = lua["loop"]; + + int counter; + for (counter = 20; counter < 31 && cr; ++counter) { + int value = cr(); + if (counter != value) { + throw std::logic_error("fuck"); + } + } + counter -= 1; + REQUIRE(counter == 30); +} + +TEST_CASE("threading/new-thread-coroutines", "ensure calling a coroutine works when the work is put on a different thread") { + const auto& script = R"(counter = 20 + +function loop() + while counter ~= 30 + do + coroutine.yield(counter); + counter = counter + 1; + end + return counter +end +)"; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::coroutine); + lua.script(script); + sol::thread runner = sol::thread::create(lua.lua_state()); + sol::state_view runnerstate = runner.state(); + sol::coroutine cr = runnerstate["loop"]; + + int counter; + for (counter = 20; counter < 31 && cr; ++counter) { + int value = cr(); + if (counter != value) { + throw std::logic_error("fuck"); + } + } + counter -= 1; + REQUIRE(counter == 30); +} \ No newline at end of file diff --git a/3rdparty/sol2/test_customizations.cpp b/3rdparty/sol2/test_customizations.cpp new file mode 100644 index 00000000000..dc15a92027c --- /dev/null +++ b/3rdparty/sol2/test_customizations.cpp @@ -0,0 +1,86 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include +#include + +struct two_things { + int a; + bool b; +}; + +namespace sol { + + // First, the expected size + // Specialization of a struct + template <> + struct lua_size : std::integral_constant {}; + + // Now, specialize various stack structures + namespace stack { + + template <> + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + // Check first and second second index for being the proper types + bool success = stack::check(L, index, handler) + && stack::check(L, index + 1, handler); + tracking.use(2); + return success; + } + }; + + template <> + struct getter { + static two_things get(lua_State* L, int index, record& tracking) { + // Get the first element + int a = stack::get(L, index); + // Get the second element, + // in the +1 position from the first + bool b = stack::get(L, index + 1); + // we use 2 slots, each of the previous takes 1 + tracking.use(2); + return two_things{ a, b }; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, const two_things& things) { + int amount = stack::push(L, things.a); + amount += stack::push(L, things.b); + // Return 2 things + return amount; + } + }; + + } +} + +TEST_CASE("customization/split-struct", "using the newly documented customization points to handle different kinds of classes") { + sol::state lua; + + // Create a pass-through style of function + lua.script("function f ( a, b, c ) return a + c, b end"); + lua.set_function("g", [](int a, bool b, int c, double d) { + return std::make_tuple(a + c, b, d + 2.5); + }); + + // get the function out of Lua + sol::function f = lua["f"]; + sol::function g = lua["g"]; + + two_things thingsf = f(two_things{ 24, true }, 1); + two_things thingsg; + double d; + sol::tie( thingsg, d ) = g(two_things{ 25, false }, 2, 34.0); + REQUIRE(thingsf.a == 25); + REQUIRE(thingsf.b); + + REQUIRE(thingsg.a == 27); + REQUIRE_FALSE(thingsg.b); + REQUIRE(d == 36.5); +} diff --git a/3rdparty/sol2/test_functions.cpp b/3rdparty/sol2/test_functions.cpp new file mode 100644 index 00000000000..60a3c7020ef --- /dev/null +++ b/3rdparty/sol2/test_functions.cpp @@ -0,0 +1,949 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include +#include +#include "test_stack_guard.hpp" + +std::function makefn() { + auto fx = []() -> int { + return 0x1456789; + }; + return fx; +} + +void takefn(std::function purr) { + if (purr() != 0x1456789) + throw 0; +} + +struct A { + int a = 0xA; int bark() { return 1; } +}; + +std::tuple bark(int num_value, A* a) { + return std::tuple(num_value * 2, a->bark()); +} + +void test_free_func(std::function f) { + f(); +} + +void test_free_func2(std::function f, int arg1) { + int val = f(arg1); + if (val != arg1) + throw sol::error("failed function call!"); +} + +int overloaded(int x) { + INFO(x); + return 3; +} + +int overloaded(int x, int y) { + INFO(x << " " << y); + return 7; +} + +int overloaded(int x, int y, int z) { + INFO(x << " " << y << " " << z); + return 11; +} + +int non_overloaded(int x, int y, int z) { + INFO(x << " " << y << " " << z); + return 13; +} + +namespace sep { + int plop_xyz(int x, int y, std::string z) { + INFO(x << " " << y << " " << z); + return 11; + } +} + +int func_1(int) { + return 1; +} + +std::string func_1s(std::string a) { + return "string: " + a; +} + +int func_2(int, int) { + return 2; +} + +void func_3(int, int, int) { + +} + +int f1(int) { return 32; } +int f2(int, int) { return 1; } +struct fer { + double f3(int, int) { + return 2.5; + } +}; + +TEST_CASE("functions/tuple-returns", "Make sure tuple returns are ordered properly") { + sol::state lua; + lua.script("function f() return '3', 4 end"); + + std::tuple result = lua["f"](); + auto s = std::get<0>(result); + auto v = std::get<1>(result); + REQUIRE(s == "3"); + REQUIRE(v == 4); +} + +TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("non_overloaded", non_overloaded); + REQUIRE_NOTHROW(lua.script("x = non_overloaded(1, 2, 3)\nprint(x)")); + + /* + // Cannot reasonably support: clang++ refuses to try enough + // deductions to make this work + lua.set_function("overloaded", overloaded); + REQUIRE_NOTHROW(lua.script("print(overloaded(1))")); + + lua.set_function("overloaded", overloaded); + REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))")); + + lua.set_function("overloaded", overloaded); + REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))")); + */ + lua.set_function("overloaded", sol::resolve(overloaded)); + REQUIRE_NOTHROW(lua.script("print(overloaded(1))")); + + lua.set_function("overloaded", sol::resolve(overloaded)); + REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2))")); + + lua.set_function("overloaded", sol::resolve(overloaded)); + REQUIRE_NOTHROW(lua.script("print(overloaded(1, 2, 3))")); +} + +TEST_CASE("functions/return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua") { + const static std::tuple triple = std::make_tuple(10, 11, 12); + const static std::tuple paired = std::make_tuple(10, 10.f); + sol::state lua; + lua.set_function("f", [] { + return std::make_tuple(10, 11, 12); + }); + int a = 0; + lua.set_function("h", []() { + return std::make_tuple(10, 10.0f); + }); + lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); + auto tcpp = lua.get("f").call(); + auto tlua = lua.get("g").call(); + auto tcpp2 = lua.get("h").call(); + auto tluaget = lua.get("x", "y", "z"); + REQUIRE(tcpp == triple); + REQUIRE(tlua == triple); + REQUIRE(tluaget == triple); + REQUIRE(tcpp2 == paired); +} + +TEST_CASE("functions/deducing-return-order-and-multi-get", "Check if return order is in the same reading order specified in Lua, with regular deducing calls") { + const static std::tuple triple = std::make_tuple(10, 11, 12); + sol::state lua; + lua.set_function("f_string", []() { return "this is a string!"; }); + sol::function f_string = lua["f_string"]; + + // Make sure there are no overload collisions / compiler errors for automatic string conversions + std::string f_string_result = f_string(); + REQUIRE(f_string_result == "this is a string!"); + f_string_result = f_string(); + REQUIRE(f_string_result == "this is a string!"); + + lua.set_function("f", [] { + return std::make_tuple(10, 11, 12); + }); + lua.script("function g() return 10, 11, 12 end\nx,y,z = g()"); + std::tuple tcpp = lua.get("f")(); + std::tuple tlua = lua.get("g")(); + std::tuple tluaget = lua.get("x", "y", "z"); + INFO("cpp: " << std::get<0>(tcpp) << ',' << std::get<1>(tcpp) << ',' << std::get<2>(tcpp)); + INFO("lua: " << std::get<0>(tlua) << ',' << std::get<1>(tlua) << ',' << std::get<2>(tlua)); + INFO("lua xyz: " << lua.get("x") << ',' << lua.get("y") << ',' << lua.get("z")); + REQUIRE(tcpp == triple); + REQUIRE(tlua == triple); + REQUIRE(tluaget == triple); +} + +TEST_CASE("functions/optional-values", "check if optionals can be passed in to be nil or otherwise") { + struct thing { + int v; + }; + sol::state lua; + lua.script(R"( function f (a) + return a +end )"); + + sol::function lua_bark = lua["f"]; + + sol::optional testv = lua_bark(sol::optional(29)); + sol::optional testn = lua_bark(sol::nullopt); + REQUIRE((bool)testv); + REQUIRE_FALSE((bool)testn); + REQUIRE(testv.value() == 29); + sol::optional v = lua_bark(sol::optional(thing{ 29 })); + REQUIRE_NOTHROW(sol::nil_t n = lua_bark(sol::nullopt)); + REQUIRE(v->v == 29); +} + +TEST_CASE("functions/pair-and-tuple-and-proxy-tests", "Check if sol::reference and sol::proxy can be passed to functions as arguments") { + sol::state lua; + lua.new_usertype("A", + "bark", &A::bark); + lua.script(R"( function f (num_value, a) + return num_value * 2, a:bark() +end +function h (num_value, a, b) + return num_value * 2, a:bark(), b * 3 +end +nested = { variables = { no = { problem = 10 } } } )"); + lua.set_function("g", bark); + + sol::function cpp_bark = lua["g"]; + sol::function lua_bark = lua["f"]; + sol::function lua_bark2 = lua["h"]; + + sol::reference lua_variable_x = lua["nested"]["variables"]["no"]["problem"]; + A cpp_variable_y; + + static const std::tuple abdesired(20, 1); + static const std::pair cddesired = { 20, 1 }; + static const std::tuple abcdesired(20, 1, 3); + + std::tuple ab = cpp_bark(lua_variable_x, cpp_variable_y); + std::pair cd = lua_bark(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y); + + REQUIRE(ab == abdesired); + REQUIRE(cd == cddesired); + + ab = cpp_bark(std::make_pair(lua_variable_x, cpp_variable_y)); + cd = lua_bark(std::make_pair(lua["nested"]["variables"]["no"]["problem"], cpp_variable_y)); + + REQUIRE(ab == abdesired); + REQUIRE(cd == cddesired); + + std::tuple abc = lua_bark2(std::make_tuple(10, cpp_variable_y), sol::optional(1)); + REQUIRE(abc == abcdesired); +} + +TEST_CASE("functions/sol::function-to-std::function", "check if conversion to std::function works properly and calls with correct arguments") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("testFunc", test_free_func); + lua.set_function("testFunc2", test_free_func2); + lua.script( + "testFunc(function() print(\"hello std::function\") end)" + ); + REQUIRE_NOTHROW(lua.script( + "function m(a)\n" + " print(\"hello std::function with arg \", a)\n" + " return a\n" + "end\n" + "\n" + "testFunc2(m, 1)" + )); +} + +TEST_CASE("functions/returning-functions-from-C++-and-gettin-in-lua", "check to see if returning a functor and getting a functor from lua is possible") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("makefn", makefn); + lua.set_function("takefn", takefn); + lua.script("afx = makefn()\n" + "print(afx())\n" + "takefn(afx)\n"); +} + +TEST_CASE("functions/function_result-protected_function_result", "Function result should be the beefy return type for sol::function that allows for error checking and error handlers") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::debug); + static const char unhandlederrormessage[] = "true error message"; + static const char handlederrormessage[] = "doodle"; + static const std::string handlederrormessage_s = handlederrormessage; + + // Some function; just using a lambda to be cheap + auto doomfx = []() { + INFO("doomfx called"); + throw std::runtime_error(unhandlederrormessage); + }; + auto luadoomfx = [&lua]() { + INFO("luadoomfx called"); + // Does not bypass error function, will call it + luaL_error(lua.lua_state(), unhandlederrormessage); + }; + lua.set_function("doom", doomfx); + lua.set_function("luadoom", luadoomfx); + + auto cpphandlerfx = [](std::string x) { + INFO("c++ handler called with: " << x); + return handlederrormessage; + }; + lua.set_function("cpphandler", cpphandlerfx); + lua.script( + std::string("function luahandler ( message )") + + " print('lua handler called with: ' .. message)" + + " return '" + handlederrormessage + "'" + + "end" + ); + auto nontrampolinefx = [](lua_State*) -> int { throw "x"; }; + lua_CFunction c_nontrampolinefx = nontrampolinefx; + lua.set("nontrampoline", c_nontrampolinefx); + lua.set_function("bark", []() -> int {return 100; }); + + sol::function luahandler = lua["luahandler"]; + sol::function cpphandler = lua["cpphandler"]; + sol::protected_function doom(lua["doom"], luahandler); + sol::protected_function luadoom(lua["luadoom"]); + sol::protected_function nontrampoline = lua["nontrampoline"]; + sol::protected_function justfine = lua["bark"]; + sol::protected_function justfinewithhandler = lua["bark"]; + luadoom.error_handler = cpphandler; + nontrampoline.error_handler = cpphandler; + justfinewithhandler.error_handler = luahandler; + bool present = true; + { + sol::protected_function_result result = doom(); + REQUIRE_FALSE(result.valid()); + sol::optional operr = result; + sol::optional opvalue = result; + present = (bool)operr; + REQUIRE(present); + present = (bool)opvalue; + REQUIRE_FALSE(present); + sol::error err = result; + REQUIRE(err.what() == handlederrormessage_s); + } + { + sol::protected_function_result result = luadoom(); + REQUIRE_FALSE(result.valid()); + sol::optional operr = result; + sol::optional opvalue = result; + present = (bool)operr; + REQUIRE(present); + present = (bool)opvalue; + REQUIRE_FALSE(present); + sol::error err = result; + REQUIRE(err.what() == handlederrormessage_s); + } + { + sol::protected_function_result result = nontrampoline(); + REQUIRE_FALSE(result.valid()); + sol::optional operr = result; + sol::optional opvalue = result; + present = (bool)operr; + REQUIRE(present); + present = (bool)opvalue; + REQUIRE_FALSE(present); + sol::error err = result; + REQUIRE(err.what() == handlederrormessage_s); + } + { + sol::protected_function_result result = justfine(); + REQUIRE(result.valid()); + sol::optional operr = result; + sol::optional opvalue = result; + present = (bool)operr; + REQUIRE_FALSE(present); + present = (bool)opvalue; + REQUIRE(present); + int value = result; + REQUIRE(value == 100); + } + { + sol::protected_function_result result = justfinewithhandler(); + REQUIRE(result.valid()); + sol::optional operr = result; + sol::optional opvalue = result; + present = (bool)operr; + REQUIRE_FALSE(present); + present = (bool)opvalue; + REQUIRE(present); + int value = result; + REQUIRE(value == 100); + } +} + +TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction happens") { + static int created = 0; + static int destroyed = 0; + static void* last_call = nullptr; + static void* static_call = reinterpret_cast(0x01); + typedef void(*fptr)(); + struct x { + x() { ++created; } + x(const x&) { ++created; } + x(x&&) { ++created; } + x& operator=(const x&) { return *this; } + x& operator=(x&&) { return *this; } + void func() { last_call = static_cast(this); }; + ~x() { ++destroyed; } + }; + struct y { + y() { ++created; } + y(const x&) { ++created; } + y(x&&) { ++created; } + y& operator=(const x&) { return *this; } + y& operator=(x&&) { return *this; } + static void func() { last_call = static_call; }; + void operator()() { func(); } + operator fptr () { return func; } + ~y() { ++destroyed; } + }; + + // stateful functors/member functions should always copy unless specified + { + created = 0; + destroyed = 0; + last_call = nullptr; + { + sol::state lua; + x x1; + lua.set_function("x1copy", &x::func, x1); + lua.script("x1copy()"); + REQUIRE(created == 2); + REQUIRE(destroyed == 0); + REQUIRE_FALSE(last_call == &x1); + + lua.set_function("x1ref", &x::func, std::ref(x1)); + lua.script("x1ref()"); + REQUIRE(created == 2); + REQUIRE(destroyed == 0); + REQUIRE(last_call == &x1); + } + REQUIRE(created == 2); + REQUIRE(destroyed == 2); + } + + // things convertible to a static function should _never_ be forced to make copies + // therefore, pass through untouched + { + created = 0; + destroyed = 0; + last_call = nullptr; + { + sol::state lua; + y y1; + lua.set_function("y1copy", y1); + lua.script("y1copy()"); + REQUIRE(created == 1); + REQUIRE(destroyed == 0); + REQUIRE(last_call == static_call); + + last_call = nullptr; + lua.set_function("y1ref", std::ref(y1)); + lua.script("y1ref()"); + REQUIRE(created == 1); + REQUIRE(destroyed == 0); + REQUIRE(last_call == static_call); + } + REQUIRE(created == 1); + REQUIRE(destroyed == 1); + } +} + + +TEST_CASE("functions/all-kinds", "Register all kinds of functions, make sure they all compile and work") { + sol::state lua; + + struct test_1 { + int a = 0xA; + virtual int bark() { + return a; + } + + int bark_mem() { + return a; + } + + static std::tuple x_bark(int num_value, test_1* a) { + return std::tuple(num_value * 2, a->a); + } + }; + + struct test_2 { + int a = 0xC; + int bark() { + return 20; + } + }; + + struct inner { + const int z = 5653; + }; + + struct nested { + inner i; + }; + + auto a = []() { return 500; }; + auto b = [&]() { return 501; }; + auto c = [&]() { return 502; }; + auto d = []() { return 503; }; + + lua.new_usertype("test_1", + "bark", sol::c_call + ); + lua.new_usertype("test_2", + "bark", sol::c_call + ); + test_2 t2; + + lua.set_function("a", a); + lua.set_function("b", b); + lua.set_function("c", std::ref(c)); + lua.set_function("d", std::ref(d)); + lua.set_function("f", &test_1::bark); + lua.set_function("g", test_1::x_bark); + lua.set_function("h", sol::c_call); + lua.set_function("i", &test_2::bark, test_2()); + lua.set_function("j", &test_2::a, test_2()); + lua.set_function("k", &test_2::a); + lua.set_function("l", sol::c_call); + lua.set_function("m", &test_2::a, &t2); + lua.set_function("n", sol::c_call); + + lua.script(R"( +o1 = test_1.new() +o2 = test_2.new() +)"); + + lua.script(R"( +ob = o1:bark() + +A = a() +B = b() +C = c() +D = d() +F = f(o1) +G0, G1 = g(2, o1) +H = h(o1) +I = i(o1) +I = i(o1) +)"); + + + lua.script(R"( +J0 = j() +j(24) +J1 = j() + )"); + + lua.script(R"( +K0 = k(o2) +k(o2, 1024) +K1 = k(o2) + )"); + + lua.script(R"( +L0 = l(o1) +l(o1, 678) +L1 = l(o1) + )"); + + + lua.script(R"( +M0 = m() +m(256) +M1 = m() + )"); + + lua.script(R"( +N = n(1, 2, 3) + )"); + int ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N; + std::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) + = lua.get( + "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" + ); + + REQUIRE(ob == 0xA); + + REQUIRE(A == 500); + REQUIRE(B == 501); + REQUIRE(C == 502); + REQUIRE(D == 503); + + REQUIRE(F == 0xA); + REQUIRE(G0 == 4); + REQUIRE(G1 == 0xA); + REQUIRE(H == 0xA); + REQUIRE(I == 20); + + REQUIRE(J0 == 0xC); + REQUIRE(J1 == 24); + + REQUIRE(K0 == 0xC); + REQUIRE(K1 == 1024); + + REQUIRE(L0 == 0xA); + REQUIRE(L1 == 678); + + REQUIRE(M0 == 0xC); + REQUIRE(M1 == 256); + + REQUIRE(N == 13); + + sol::tie(ob, A, B, C, D, F, G0, G1, H, I, J0, J1, K0, K1, L0, L1, M0, M1, N) + = lua.get( + "ob", "A", "B", "C", "D", "F", "G0", "G1", "H", "I", "J0", "J1", "K0", "K1", "L0", "L1", "M0", "M1", "N" + ); + + REQUIRE(ob == 0xA); + + REQUIRE(A == 500); + REQUIRE(B == 501); + REQUIRE(C == 502); + REQUIRE(D == 503); + + REQUIRE(F == 0xA); + REQUIRE(G0 == 4); + REQUIRE(G1 == 0xA); + REQUIRE(H == 0xA); + REQUIRE(I == 20); + + REQUIRE(J0 == 0xC); + REQUIRE(J1 == 24); + + REQUIRE(K0 == 0xC); + REQUIRE(K1 == 1024); + + REQUIRE(L0 == 0xA); + REQUIRE(L1 == 678); + + REQUIRE(M0 == 0xC); + REQUIRE(M1 == 256); + + REQUIRE(N == 13); + + // Work that compiler, WORK IT! + lua.set("o", &test_1::bark); + lua.set("p", test_1::x_bark); + lua.set("q", sol::c_call); + lua.set("r", &test_2::a); + lua.set("s", sol::readonly(&test_2::a)); + lua.set_function("t", sol::readonly(&test_2::a), test_2()); + lua.set_function("u", &nested::i, nested()); + lua.set("v", &nested::i); + lua.set("nested", nested()); + lua.set("inner", inner()); + REQUIRE_THROWS(lua.script("s(o2, 2)")); + REQUIRE_THROWS(lua.script("t(2)")); + REQUIRE_THROWS(lua.script("u(inner)")); + REQUIRE_THROWS(lua.script("v(nested, inner)")); +} + +TEST_CASE("simple/call-with-parameters", "Lua function is called with a few parameters from C++") { + sol::state lua; + + REQUIRE_NOTHROW(lua.script("function my_add(i, j, k) return i + j + k end")); + auto f = lua.get("my_add"); + REQUIRE_NOTHROW(lua.script("function my_nothing(i, j, k) end")); + auto fvoid = lua.get("my_nothing"); + int a; + REQUIRE_NOTHROW(fvoid(1, 2, 3)); + REQUIRE_NOTHROW(a = f.call(1, 2, 3)); + REQUIRE(a == 6); + REQUIRE_THROWS(a = f(1, 2, "arf")); +} + +TEST_CASE("simple/call-c++-function", "C++ function is called from lua") { + sol::state lua; + + lua.set_function("plop_xyz", sep::plop_xyz); + lua.script("x = plop_xyz(2, 6, 'hello')"); + + REQUIRE(lua.get("x") == 11); +} + +TEST_CASE("simple/call-lambda", "A C++ lambda is exposed to lua and called") { + sol::state lua; + + int a = 0; + + lua.set_function("foo", [&a] { a = 1; }); + + lua.script("foo()"); + + REQUIRE(a == 1); +} + +TEST_CASE("advanced/get-and-call", "Checks for lambdas returning values after a get operation") { + const static std::string lol = "lol", str = "str"; + const static std::tuple heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); + sol::state lua; + + REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; })); + REQUIRE(lua.get("a").call() == 42); + + REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); + REQUIRE(lua.get("b").call() == 42u); + + REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); + REQUIRE(lua.get("c").call() == 3.14); + + REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); + REQUIRE(lua.get("d").call() == 6.28f); + + REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); + REQUIRE(lua.get("e").call() == lol); + + REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); + REQUIRE(lua.get("f").call()); + + REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); + REQUIRE(lua.get("g").call() == str); + + REQUIRE_NOTHROW(lua.set_function("h", [] {})); + REQUIRE_NOTHROW(lua.get("h").call()); + + REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); + REQUIRE(lua.get("i").call() == sol::nil); + REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); + REQUIRE((lua.get("j").call() == heh_tuple)); +} + +TEST_CASE("advanced/operator[]-call", "Checks for lambdas returning values using operator[]") { + const static std::string lol = "lol", str = "str"; + const static std::tuple heh_tuple = std::make_tuple(1, 6.28f, 3.14, std::string("heh")); + sol::state lua; + + REQUIRE_NOTHROW(lua.set_function("a", [] { return 42; })); + REQUIRE(lua["a"].call() == 42); + + REQUIRE_NOTHROW(lua.set_function("b", [] { return 42u; })); + REQUIRE(lua["b"].call() == 42u); + + REQUIRE_NOTHROW(lua.set_function("c", [] { return 3.14; })); + REQUIRE(lua["c"].call() == 3.14); + + REQUIRE_NOTHROW(lua.set_function("d", [] { return 6.28f; })); + REQUIRE(lua["d"].call() == 6.28f); + + REQUIRE_NOTHROW(lua.set_function("e", [] { return "lol"; })); + REQUIRE(lua["e"].call() == lol); + + REQUIRE_NOTHROW(lua.set_function("f", [] { return true; })); + REQUIRE(lua["f"].call()); + + REQUIRE_NOTHROW(lua.set_function("g", [] { return std::string("str"); })); + REQUIRE(lua["g"].call() == str); + + REQUIRE_NOTHROW(lua.set_function("h", [] {})); + REQUIRE_NOTHROW(lua["h"].call()); + + REQUIRE_NOTHROW(lua.set_function("i", [] { return sol::nil; })); + REQUIRE(lua["i"].call() == sol::nil); + REQUIRE_NOTHROW(lua.set_function("j", [] { return std::make_tuple(1, 6.28f, 3.14, std::string("heh")); })); + REQUIRE((lua["j"].call() == heh_tuple)); +} + +TEST_CASE("advanced/call-lambdas", "A C++ lambda is exposed to lua and called") { + sol::state lua; + + int x = 0; + lua.set_function("set_x", [&](int new_x) { + x = new_x; + return 0; + }); + + lua.script("set_x(9)"); + REQUIRE(x == 9); +} + +TEST_CASE("advanced/call-referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") { + sol::state lua; + + int x = 0; + auto objx = [&](int new_x) { + x = new_x; + return 0; + }; + lua.set_function("set_x", std::ref(objx)); + + int y = 0; + auto objy = [&](int new_y) { + y = new_y; + return std::tuple(0, 0); + }; + lua.set_function("set_y", &decltype(objy)::operator(), std::ref(objy)); + + lua.script("set_x(9)"); + lua.script("set_y(9)"); + REQUIRE(x == 9); + REQUIRE(y == 9); +} + +TEST_CASE("functions/tie", "make sure advanced syntax with 'tie' works") { + sol::state lua; + + lua.script(R"(function f () + return 1, 2, 3 +end)"); + sol::function f = lua["f"]; + + int a, b, c; + sol::tie(a, b, c) = f(); + REQUIRE(a == 1); + REQUIRE(b == 2); + REQUIRE(c == 3); +} + +TEST_CASE("functions/variadic_args", "Check to see we can receive multiple arguments through a variadic") { + struct structure { + int x; + bool b; + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.set_function("v", [](sol::this_state, sol::variadic_args va) -> structure { + int r = 0; + for (auto v : va) { + int value = v; + r += value; + } + return{ r, r > 200 }; + }); + + lua.script("x = v(25, 25)"); + lua.script("x2 = v(25, 25, 100, 50, 250, 150)"); + lua.script("x3 = v(1, 2, 3, 4, 5, 6)"); + + structure& lx = lua["x"]; + structure& lx2 = lua["x2"]; + structure& lx3 = lua["x3"]; + REQUIRE(lx.x == 50); + REQUIRE(lx2.x == 600); + REQUIRE(lx3.x == 21); + REQUIRE_FALSE(lx.b); + REQUIRE(lx2.b); + REQUIRE_FALSE(lx3.b); +} + +TEST_CASE("functions/required_and_variadic_args", "Check if a certain number of arguments can still be required even when using variadic_args") { + sol::state lua; + lua.set_function("v", + [](sol::this_state, sol::variadic_args, int, int) { + } + ); + REQUIRE_NOTHROW(lua.script("v(20, 25, 30)")); + REQUIRE_NOTHROW(lua.script("v(20, 25)")); +#ifndef SOL_LUAJIT + REQUIRE_THROWS(lua.script("v(20)")); +#endif // LuaJIT has problems with exceptions, as fucking usual +} + +TEST_CASE("functions/overloading", "Check if overloading works properly for regular set function syntax") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("func_1", func_1); + lua.set_function("func", sol::overload(func_2, func_3, func_1, func_1s)); + + const std::string string_bark = "string: bark"; + + REQUIRE_NOTHROW(lua.script( + "a = func(1)\n" + "b = func('bark')\n" + "c = func(1,2)\n" + "func(1,2,3)\n" + )); + + REQUIRE((lua["a"] == 1)); + REQUIRE((lua["b"] == string_bark)); + REQUIRE((lua["c"] == 2)); + + REQUIRE_THROWS(lua.script("func(1,2,'meow')")); +} + +TEST_CASE("overloading/c_call", "Make sure that overloading works with c_call functionality") { + sol::state lua; + lua.set("f", sol::c_call, sol::wrap, sol::wrap>); + lua.set("g", sol::c_call>); + lua.set("h", sol::c_call); + lua.set("obj", fer()); + + lua.script("r1 = f(1)"); + lua.script("r2 = f(1, 2)"); + lua.script("r3 = f(obj, 1, 2)"); + lua.script("r4 = g(1)"); + lua.script("r5 = h(1, 2)"); + + int r1 = lua["r1"]; + int r2 = lua["r2"]; + double r3 = lua["r3"]; + int r4 = lua["r4"]; + int r5 = lua["r5"]; + + REQUIRE(r1 == 32); + REQUIRE(r2 == 1); + REQUIRE(r3 == 2.5); + REQUIRE(r4 == 32); + REQUIRE(r5 == 1); +} + +TEST_CASE("functions/stack-protect", "make sure functions don't impede on the stack") { + //setup sol/lua + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::string); + + lua.script("function ErrorHandler(msg) print('Lua created error msg : ' .. msg) return msg end"); + lua.script("function stringtest(a) if a == nil then error('fuck') end print('Lua recieved content : ' .. a) return a end"); + + // test normal function + { + sol::stack_guard normalsg(lua); + std::string str = lua["stringtest"]("normal test"); + INFO("Back in C++, direct call result is : " << str); + } + + //test protected_function + sol::protected_function Stringtest(lua["stringtest"]); + Stringtest.error_handler = lua["ErrorHandler"]; + sol::stack_guard sg(lua); + { + sol::protected_function_result stringresult = Stringtest("protected test"); + REQUIRE(stringresult.valid()); + std::string s = stringresult; + INFO("Back in C++, protected result is : " << s); + } + REQUIRE(sg.check_stack()); + + //test optional + { + sol::stack_guard opsg(lua); + sol::optional opt_result = Stringtest("optional test"); + REQUIRE(opsg.check_stack()); + if (opt_result) + { + std::string s = opt_result.value(); + INFO("Back in C++, opt_result is : " << s); + } + else + { + INFO("opt_result failed"); + } + } + REQUIRE(sg.check_stack()); + + { + sol::protected_function_result errresult = Stringtest(sol::nil); + REQUIRE_FALSE(errresult.valid()); + sol::error err = errresult; + std::string msg = err.what(); + INFO("error :" << msg); + } + REQUIRE(sg.check_stack()); +} diff --git a/3rdparty/sol2/test_inheritance.cpp b/3rdparty/sol2/test_inheritance.cpp new file mode 100644 index 00000000000..5afb363b8e7 --- /dev/null +++ b/3rdparty/sol2/test_inheritance.cpp @@ -0,0 +1,247 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include + +TEST_CASE("inheritance/basic", "test that metatables are properly inherited") { + struct A { + int a = 5; + }; + + struct B { + int b() { + return 10; + } + }; + + struct C : B, A { + double c = 2.4; + }; + + struct D : C { + bool d() const { + return true; + } + }; + + sol::state lua; + lua.new_usertype("A", + "a", &A::a + ); + lua.new_usertype("B", + "b", &B::b + ); + lua.new_usertype("C", + "c", &C::c, + sol::base_classes, sol::bases() + ); + lua.new_usertype("D", + "d", &D::d, + sol::base_classes, sol::bases() + ); + + lua.script("obj = D.new()"); + lua.script("d = obj:d()"); + bool d = lua["d"]; + lua.script("c = obj.c"); + double c = lua["c"]; + lua.script("b = obj:b()"); + int b = lua["b"]; + lua.script("a = obj.a"); + int a = lua["a"]; + + REQUIRE(d); + REQUIRE(c == 2.4); + REQUIRE(b == 10); + REQUIRE(a == 5); +} + +TEST_CASE("inheritance/multi-base", "test that multiple bases all work and overloading for constructors works with them") { + class TestClass00 { + public: + int Thing() const { return 123; } + }; + + class TestClass01 : public TestClass00 { + public: + TestClass01() : a(1) {} + TestClass01(const TestClass00& other) : a(other.Thing()) {} + + int a; + }; + + class TestClass02 : public TestClass01 { + public: + TestClass02() : b(2) {} + TestClass02(const TestClass01& other) : b(other.a) {} + TestClass02(const TestClass00& other) : b(other.Thing()) {} + + int b; + }; + + class TestClass03 : public TestClass02 { + public: + TestClass03() : c(2) {} + TestClass03(const TestClass02& other) : c(other.b) {} + TestClass03(const TestClass01& other) : c(other.a) {} + TestClass03(const TestClass00& other) : c(other.Thing()) {} + + int c; + }; + + sol::state lua; + + sol::usertype s_TestUsertype00( + sol::call_constructor, sol::constructors>(), + "Thing", &TestClass00::Thing + ); + + lua.set_usertype("TestClass00", s_TestUsertype00); + + sol::usertype s_TestUsertype01( + sol::call_constructor, sol::constructors, sol::types>(), + sol::base_classes, sol::bases(), + "a", &TestClass01::a + ); + + lua.set_usertype("TestClass01", s_TestUsertype01); + + sol::usertype s_TestUsertype02( + sol::call_constructor, sol::constructors, sol::types, sol::types>(), + sol::base_classes, sol::bases(), + "b", &TestClass02::b + ); + + lua.set_usertype("TestClass02", s_TestUsertype02); + + sol::usertype s_TestUsertype03( + sol::call_constructor, sol::constructors, sol::types, sol::types, sol::types>(), + sol::base_classes, sol::bases(), + "c", &TestClass03::c + ); + + lua.set_usertype("TestClass03", s_TestUsertype03); + + lua.script(R"( +tc0 = TestClass00() +)"); + + lua.script(R"( +tc2 = TestClass02(tc0) +)"); + + lua.script(R"( +tc1 = TestClass01() +)"); + + lua.script(R"( +tc3 = TestClass03(tc1) +)"); + + TestClass00& tc0 = lua["tc0"]; + TestClass01& tc1 = lua["tc1"]; + TestClass02& tc2 = lua["tc2"]; + TestClass03& tc3 = lua["tc3"]; + REQUIRE(tc1.a == 1); + REQUIRE(tc2.a == 1); + REQUIRE(tc2.b == 123); + REQUIRE(tc3.a == 1); + REQUIRE(tc3.b == 2); + REQUIRE(tc3.c == 1); +} + +TEST_CASE("inheritance/simple-multi-base", "test that multiple bases all work and overloading for constructors works with them") { + class TestClass00 { + public: + int Thing() const { return 123; } + }; + + class TestClass01 : public TestClass00 { + public: + TestClass01() : a(1) {} + TestClass01(const TestClass00& other) : a(other.Thing()) {} + + int a; + }; + + class TestClass02 : public TestClass01 { + public: + TestClass02() : b(2) {} + TestClass02(const TestClass01& other) : b(other.a) {} + TestClass02(const TestClass00& other) : b(other.Thing()) {} + + int b; + }; + + class TestClass03 : public TestClass02 { + public: + TestClass03() : c(2) {} + TestClass03(const TestClass02& other) : c(other.b) {} + TestClass03(const TestClass01& other) : c(other.a) {} + TestClass03(const TestClass00& other) : c(other.Thing()) {} + + int c; + }; + + sol::state lua; + + sol::simple_usertype s_TestUsertype00( lua, + sol::call_constructor, sol::constructors>(), + "Thing", &TestClass00::Thing + ); + + lua.set_usertype("TestClass00", s_TestUsertype00); + + sol::simple_usertype s_TestUsertype01( lua, + sol::call_constructor, sol::constructors, sol::types>(), + sol::base_classes, sol::bases(), + "a", &TestClass01::a + ); + + lua.set_usertype("TestClass01", s_TestUsertype01); + + sol::simple_usertype s_TestUsertype02( lua, + sol::call_constructor, sol::constructors, sol::types, sol::types>(), + sol::base_classes, sol::bases(), + "b", &TestClass02::b + ); + + lua.set_usertype("TestClass02", s_TestUsertype02); + + sol::simple_usertype s_TestUsertype03( lua, + sol::call_constructor, sol::constructors, sol::types, sol::types, sol::types>(), + sol::base_classes, sol::bases(), + "c", &TestClass03::c + ); + + lua.set_usertype("TestClass03", s_TestUsertype03); + + lua.script(R"( +tc0 = TestClass00() +)"); + + lua.script(R"( +tc2 = TestClass02(tc0) +)"); + + lua.script(R"( +tc1 = TestClass01() +)"); + + lua.script(R"( +tc3 = TestClass03(tc1) +)"); + + TestClass00& tc0 = lua["tc0"]; + TestClass01& tc1 = lua["tc1"]; + TestClass02& tc2 = lua["tc2"]; + TestClass03& tc3 = lua["tc3"]; + REQUIRE(tc1.a == 1); + REQUIRE(tc2.a == 1); + REQUIRE(tc2.b == 123); + REQUIRE(tc3.a == 1); + REQUIRE(tc3.b == 2); + REQUIRE(tc3.c == 1); +} diff --git a/3rdparty/sol2/test_operators.cpp b/3rdparty/sol2/test_operators.cpp new file mode 100644 index 00000000000..b8e48e783ee --- /dev/null +++ b/3rdparty/sol2/test_operators.cpp @@ -0,0 +1,83 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +TEST_CASE("operators/default", "test that generic equality operators and all sorts of equality tests can be used") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + struct T {}; + struct U { + int a; + U(int x = 20) : a(x) {} + bool operator==(const U& r) { + return a == r.a; + } + }; + struct V { + int a; + V(int x = 20) : a(x) {} + bool operator==(const V& r) const { + return a == r.a; + } + }; + lua.new_usertype("T"); + lua.new_usertype("U"); + lua.new_usertype("V"); + + T t1; + T& t2 = t1; + T t3; + U u1; + U u2{ 30 }; + U u3; + U v1; + U v2{ 30 }; + U v3; + lua["t1"] = &t1; + lua["t2"] = &t2; + lua["t3"] = &t3; + lua["u1"] = &u1; + lua["u2"] = &u2; + lua["u3"] = &u3; + lua["v1"] = &v1; + lua["v2"] = &v2; + lua["v3"] = &v3; + + // Can only compare identity here + REQUIRE_NOTHROW({ + lua.script("assert(t1 == t1)"); + lua.script("assert(t2 == t2)"); + lua.script("assert(t3 == t3)"); + }); + REQUIRE_NOTHROW({ + lua.script("assert(t1 == t2)"); + lua.script("assert(not (t1 == t3))"); + lua.script("assert(not (t2 == t3))"); + }); + // Object should compare equal to themselves + // (and not invoke operator==; pointer test should be sufficient) + REQUIRE_NOTHROW({ + lua.script("assert(u1 == u1)"); + lua.script("assert(u2 == u2)"); + lua.script("assert(u3 == u3)"); + }); + REQUIRE_NOTHROW({ + lua.script("assert(not (u1 == u2))"); + lua.script("assert(u1 == u3)"); + lua.script("assert(not (u2 == u3))"); + }); + // Object should compare equal to themselves + // (and not invoke operator==; pointer test should be sufficient) + REQUIRE_NOTHROW({ + lua.script("assert(v1 == v1)"); + lua.script("assert(v2 == v2)"); + lua.script("assert(v3 == v3)"); + }); + REQUIRE_NOTHROW({ + lua.script("assert(not (v1 == v2))"); + lua.script("assert(v1 == v3)"); + lua.script("assert(not (v2 == v3))"); + }); +} \ No newline at end of file diff --git a/3rdparty/sol2/test_overflow.cpp b/3rdparty/sol2/test_overflow.cpp new file mode 100644 index 00000000000..68c11811a97 --- /dev/null +++ b/3rdparty/sol2/test_overflow.cpp @@ -0,0 +1,47 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + + +TEST_CASE("issues/stack-overflow", "make sure various operations repeated don't trigger stack overflow") { + sol::state lua; + lua.script("t = {};t[0]=20"); + lua.script("lua_function=function(i)return i;end"); + + sol::function f = lua["lua_function"]; + std::string teststring = "testtext"; + REQUIRE_NOTHROW( + for (int i = 0; i < 1000000; ++i) { + std::string result = f(teststring); + if (result != teststring) throw std::logic_error("RIP"); + } + ); + sol::table t = lua["t"]; + int expected = 20; + REQUIRE_NOTHROW( + for (int i = 0; i < 1000000; ++i) { + int result = t[0]; + t.size(); + if (result != expected) + throw std::logic_error("RIP"); + } + ); +} + + +TEST_CASE("issues/stack-overflow-2", "make sure basic iterators clean up properly when they're not iterated through (e.g., with empty())") { + sol::state lua; + sol::table t = lua.create_table_with(1, "wut"); + int MAX = 50000; + auto fx = [&]() { + int a = 50; + for (int i = 0; i < MAX; ++i) { + if (t.empty()) { + a += 4; + } + a += 2; + } + }; + REQUIRE_NOTHROW(fx()); +} diff --git a/3rdparty/sol2/test_simple_usertypes.cpp b/3rdparty/sol2/test_simple_usertypes.cpp new file mode 100644 index 00000000000..4683aa3b631 --- /dev/null +++ b/3rdparty/sol2/test_simple_usertypes.cpp @@ -0,0 +1,459 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include +#include +#include +#include + +TEST_CASE("usertype/simple-usertypes", "Ensure that simple usertypes properly work here") { + struct marker { + bool value = false; + }; + struct bark { + int var = 50; + marker mark; + + void fun() { + var = 51; + } + + int get() const { + return var; + } + + int set(int x) { + var = x; + return var; + } + + std::string special() const { + return mark.value ? "woof" : "pantpant"; + } + + const marker& the_marker() const { + return mark; + } + }; + + sol::state lua; + lua.new_simple_usertype("bark", + "fun", &bark::fun, + "get", &bark::get, + "var", sol::as_function( &bark::var ), + "the_marker", sol::as_function(&bark::the_marker), + "x", sol::overload(&bark::get), + "y", sol::overload(&bark::set), + "z", sol::overload(&bark::get, &bark::set) + ); + + lua.script("b = bark.new()"); + bark& b = lua["b"]; + + lua.script("b:fun()"); + int var = b.var; + REQUIRE(var == 51); + + lua.script("b:var(20)"); + lua.script("v = b:var()"); + int v = lua["v"]; + REQUIRE(v == 20); + REQUIRE(b.var == 20); + + lua.script("m = b:the_marker()"); + marker& m = lua["m"]; + REQUIRE_FALSE(b.mark.value); + REQUIRE_FALSE(m.value); + m.value = true; + REQUIRE(&b.mark == &m); + REQUIRE(b.mark.value); + + sol::table barktable = lua["bark"]; + barktable["special"] = &bark::special; + + lua.script("s = b:special()"); + std::string s = lua["s"]; + REQUIRE(s == "woof"); + + lua.script("b:y(24)"); + lua.script("x = b:x()"); + int x = lua["x"]; + REQUIRE(x == 24); + + lua.script("z = b:z(b:z() + 5)"); + int z = lua["z"]; + REQUIRE(z == 29); +} + +TEST_CASE("usertype/simple-usertypes-constructors", "Ensure that calls with specific arguments work") { + struct marker { + bool value = false; + }; + struct bark { + int var = 50; + marker mark; + + bark() {} + bark(int v) : var(v) {} + + void fun() { + var = 51; + } + + int get() const { + return var; + } + + int set(int x) { + var = x; + return var; + } + + std::string special() const { + return mark.value ? "woof" : "pantpant"; + } + + const marker& the_marker() const { + return mark; + } + }; + + sol::state lua; + lua.new_simple_usertype("bark", + sol::constructors, sol::types>(), + "fun", sol::protect( &bark::fun ), + "get", &bark::get, + "var", sol::as_function( &bark::var ), + "the_marker", &bark::the_marker, + "x", sol::overload(&bark::get), + "y", sol::overload(&bark::set), + "z", sol::overload(&bark::get, &bark::set) + ); + + lua.script("bx = bark.new(760)"); + bark& bx = lua["bx"]; + REQUIRE(bx.var == 760); + + lua.script("b = bark.new()"); + bark& b = lua["b"]; + + lua.script("b:fun()"); + int var = b.var; + REQUIRE(var == 51); + + lua.script("b:var(20)"); + lua.script("v = b:var()"); + int v = lua["v"]; + REQUIRE(v == 20); + + lua.script("m = b:the_marker()"); + marker& m = lua["m"]; + REQUIRE_FALSE(b.mark.value); + REQUIRE_FALSE(m.value); + m.value = true; + REQUIRE(&b.mark == &m); + REQUIRE(b.mark.value); + + sol::table barktable = lua["bark"]; + barktable["special"] = &bark::special; + + lua.script("s = b:special()"); + std::string s = lua["s"]; + REQUIRE(s == "woof"); + + lua.script("b:y(24)"); + lua.script("x = b:x()"); + int x = lua["x"]; + REQUIRE(x == 24); + + lua.script("z = b:z(b:z() + 5)"); + int z = lua["z"]; + REQUIRE(z == 29); +} + +TEST_CASE("usertype/simple-shared-ptr-regression", "simple usertype metatables should not screw over unique usertype metatables") { + static int created = 0; + static int destroyed = 0; + struct test { + test() { + ++created; + } + + ~test() { + ++destroyed; + } + }; + { + std::list> tests; + sol::state lua; + lua.open_libraries(); + + lua.new_simple_usertype("test", + "create", [&]() -> std::shared_ptr { + tests.push_back(std::make_shared()); + return tests.back(); + } + ); + REQUIRE(created == 0); + REQUIRE(destroyed == 0); + lua.script("x = test.create()"); + REQUIRE(created == 1); + REQUIRE(destroyed == 0); + REQUIRE_FALSE(tests.empty()); + std::shared_ptr& x = lua["x"]; + std::size_t xuse = x.use_count(); + std::size_t tuse = tests.back().use_count(); + REQUIRE(xuse == tuse); + } + REQUIRE(created == 1); + REQUIRE(destroyed == 1); +} + +TEST_CASE("usertype/simple-vars", "simple usertype vars can bind various values (no ref)") { + int muh_variable = 10; + int through_variable = 25; + + sol::state lua; + lua.open_libraries(); + + struct test {}; + lua.new_simple_usertype("test", + "straight", sol::var(2), + "global", sol::var(muh_variable), + "global2", sol::var(through_variable), + "global3", sol::var(std::ref(through_variable)) + ); + + through_variable = 20; + + lua.script(R"( +print(test.straight) +s = test.straight +print(test.global) +g = test.global +print(test.global2) +g2 = test.global2 +print(test.global3) +g3 = test.global3 +)"); + + int s = lua["s"]; + int g = lua["g"]; + int g2 = lua["g2"]; + int g3 = lua["g3"]; + REQUIRE(s == 2); + REQUIRE(g == 10); + REQUIRE(g2 == 25); + REQUIRE(g3 == 20); +} + +TEST_CASE("usertypes/simple-variable-control", "test to see if usertypes respond to inheritance and variable controls") { + class A { + public: + virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; + }; + + class B : public A { + public: + virtual void a() override { } + }; + + class sA { + public: + virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; + }; + + class sB : public sA { + public: + virtual void a() override { } + }; + + struct sV { + int a = 10; + int b = 20; + + int get_b() const { + return b + 2; + } + + void set_b(int value) { + b = value; + } + }; + + struct sW : sV {}; + + sol::state lua; + lua.open_libraries(); + + lua.new_usertype("A", "a", &A::a); + lua.new_usertype("B", sol::base_classes, sol::bases()); + lua.new_simple_usertype("sA", "a", &sA::a); + lua.new_simple_usertype("sB", sol::base_classes, sol::bases()); + lua.new_simple_usertype("sV", "a", &sV::a, "b", &sV::b, "pb", sol::property(&sV::get_b, &sV::set_b)); + lua.new_simple_usertype("sW", sol::base_classes, sol::bases()); + + B b; + lua.set("b", &b); + lua.script("b:a()"); + + sB sb; + lua.set("sb", &sb); + lua.script("sb:a()"); + + sV sv; + lua.set("sv", &sv); + lua.script("print(sv.b)assert(sv.b == 20)"); + + sW sw; + lua.set("sw", &sw); + lua.script("print(sw.a)assert(sw.a == 10)"); + lua.script("print(sw.b)assert(sw.b == 20)"); + lua.script("print(sw.pb)assert(sw.pb == 22)"); + lua.script("sw.a = 11"); + lua.script("sw.b = 21"); + lua.script("print(sw.a)assert(sw.a == 11)"); + lua.script("print(sw.b)assert(sw.b == 21)"); + lua.script("print(sw.pb)assert(sw.pb == 23)"); + lua.script("sw.pb = 25"); + lua.script("print(sw.b)assert(sw.b == 25)"); + lua.script("print(sw.pb)assert(sw.pb == 27)"); +} + +TEST_CASE("usertype/simple-factory-constructor-overload-usage", "simple usertypes should probably invoke types") { + class A { + public: + virtual void a() { throw std::runtime_error("entered base pure virtual implementation"); }; + }; + + class B : public A { + public: + int bvar = 24; + virtual void a() override { } + void f() {} + }; + + sol::state lua; + lua.open_libraries(); + sol::constructors, sol::types> c; + lua.new_simple_usertype("B", + sol::call_constructor, c, + "new", sol::factories([]() { return B(); }), + "new2", sol::initializers([](B& mem) { new(&mem)B(); }, [](B& mem, int v) { new(&mem)B(); mem.bvar = v; }), + "f", sol::as_function(&B::bvar), + "g", sol::overload([](B&) { return 2; }, [](B&, int v) { return v; }) + ); + + lua.script("b = B()"); + lua.script("b2 = B.new()"); + lua.script("b3 = B.new2()"); + lua.script("b4 = B.new2(11)"); + + lua.script("x = b:f()"); + lua.script("x2 = b2:f()"); + lua.script("x3 = b3:f()"); + lua.script("x4 = b4:f()"); + int x = lua["x"]; + int x2 = lua["x2"]; + int x3 = lua["x3"]; + int x4 = lua["x4"]; + REQUIRE(x == 24); + REQUIRE(x2 == 24); + REQUIRE(x3 == 24); + REQUIRE(x4 == 11); + + lua.script("y = b:g()"); + lua.script("y2 = b2:g(3)"); + lua.script("y3 = b3:g()"); + lua.script("y4 = b4:g(3)"); + int y = lua["y"]; + int y2 = lua["y2"]; + int y3 = lua["y3"]; + int y4 = lua["y4"]; + REQUIRE(y == 2); + REQUIRE(y2 == 3); + REQUIRE(y3 == 2); + REQUIRE(y4 == 3); +} + +TEST_CASE("usertype/simple-runtime-append", "allow extra functions to be appended at runtime directly to the metatable itself") { + class A { + }; + + class B : public A { + }; + + sol::state lua; + lua.new_simple_usertype("A"); + lua.new_simple_usertype("B", sol::base_classes, sol::bases()); + lua.set("b", std::make_unique()); + lua["A"]["method"] = []() { return 200; }; + lua["B"]["method2"] = [](B&) { return 100; }; + lua.script("x = b.method()"); + lua.script("y = b:method()"); + + int x = lua["x"]; + int y = lua["y"]; + REQUIRE(x == 200); + REQUIRE(y == 200); + + lua.script("z = b.method2(b)"); + lua.script("w = b:method2()"); + int z = lua["z"]; + int w = lua["w"]; + REQUIRE(z == 100); + REQUIRE(w == 100); +} + +TEST_CASE("usertype/simple-destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") { + sol::state lua; + + class CrashClass { + public: + CrashClass() { + } + + ~CrashClass() { + a = 10; // This will cause a crash. + } + + private: + int a; + }; + + lua.new_simple_usertype("CrashClass", + sol::call_constructor, sol::constructors>() + ); + + lua.script(R"( + function testCrash() + local x = CrashClass() + end + )"); + + for (int i = 0; i < 1000; ++i) { + lua["testCrash"](); + } +} + +TEST_CASE("usertype/simple-table-append", "Ensure that appending to the meta table also affects the internal function table for pointers as well") { + struct A { + int func() { + return 5000; + } + }; + + sol::state lua; + lua.open_libraries(); + + lua.new_simple_usertype("A"); + sol::table table = lua["A"]; + table["func"] = &A::func; + A a; + lua.set("a", &a); + REQUIRE_NOTHROW( + lua.script("assert(a:func() == 5000)") + ); +} diff --git a/3rdparty/sol2/test_stack_guard.hpp b/3rdparty/sol2/test_stack_guard.hpp new file mode 100644 index 00000000000..d77ffb8b682 --- /dev/null +++ b/3rdparty/sol2/test_stack_guard.hpp @@ -0,0 +1,11 @@ +#pragma once + +struct test_stack_guard { + lua_State* L; + int& begintop; + int& endtop; + test_stack_guard(lua_State* L, int& begintop, int& endtop) : L(L), begintop(begintop), endtop(endtop) { + begintop = lua_gettop(L); + } + ~test_stack_guard() { endtop = lua_gettop(L); } +}; diff --git a/3rdparty/sol2/test_strings.cpp b/3rdparty/sol2/test_strings.cpp new file mode 100644 index 00000000000..98396e204bd --- /dev/null +++ b/3rdparty/sol2/test_strings.cpp @@ -0,0 +1,122 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include + +struct test {}; +template +struct test_t {}; + +namespace muh_namespace { + struct ns_test {}; + + namespace { + struct ns_anon_test {}; + } +} + +// There isn't a single library roundtripping which codecvt works on. We'll do the nitty-gritty of it later... +TEST_CASE("stack/strings", "test that strings can be roundtripped") { + sol::state lua; + + static const char utf8str[] = "\xF0\x9F\x8D\x8C\x20\xE6\x99\xA5\x20\x46\x6F\x6F\x20\xC2\xA9\x20\x62\x61\x72\x20\xF0\x9D\x8C\x86\x20\x62\x61\x7A\x20\xE2\x98\x83\x20\x71\x75\x78"; + static const char16_t utf16str[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 }; + static const char32_t utf32str[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 }; +#ifdef _WIN32 + INFO("win32 widestr"); + static const wchar_t widestr[] = { 0xD83C, 0xDF4C, 0x20, 0x6665, 0x20, 0x46, 0x6F, 0x6F, 0x20, 0xA9, 0x20, 0x62, 0x61, 0x72, 0x20, 0xD834, 0xDF06, 0x20, 0x62, 0x61, 0x7A, 0x20, 0x2603, 0x20, 0x71, 0x75, 0x78, 0x00 }; +#else + INFO("non-windows widestr"); + static const wchar_t widestr[] = { 0x1F34C, 0x0020, 0x6665, 0x0020, 0x0046, 0x006F, 0x006F, 0x0020, 0x00A9, 0x0020, 0x0062, 0x0061, 0x0072, 0x0020, 0x1D306, 0x0020, 0x0062, 0x0061, 0x007A, 0x0020, 0x2603, 0x0020, 0x0071, 0x0075, 0x0078, 0x00 }; +#endif + static const std::string utf8str_s = utf8str; + static const std::u16string utf16str_s = utf16str; + static const std::u32string utf32str_s = utf32str; + static const std::wstring widestr_s = widestr; + +#ifdef SOL_CODECVT_SUPPORT + INFO("sizeof(wchar_t): " << sizeof(wchar_t)); + INFO("sizeof(char16_t): " << sizeof(char16_t)); + INFO("sizeof(char32_t): " << sizeof(char32_t)); + INFO("utf8str: " << utf8str); + INFO("utf8str_s: " << utf8str_s); + + lua["utf8"] = utf8str; + lua["utf16"] = utf16str; + lua["utf32"] = utf32str; + lua["wide"] = widestr; + + std::string utf8_to_utf8 = lua["utf8"]; + std::string utf16_to_utf8 = lua["utf16"]; + std::string utf32_to_utf8 = lua["utf32"]; + std::string wide_to_utf8 = lua["wide"]; + + REQUIRE(utf8_to_utf8 == utf8str_s); + REQUIRE(utf16_to_utf8 == utf8str_s); + REQUIRE(utf32_to_utf8 == utf8str_s); + REQUIRE(wide_to_utf8 == utf8str_s); + + std::wstring utf8_to_wide = lua["utf8"]; + std::wstring utf16_to_wide = lua["utf16"]; + std::wstring utf32_to_wide = lua["utf32"]; + std::wstring wide_to_wide = lua["wide"]; + + REQUIRE(utf8_to_wide == widestr_s); + REQUIRE(utf16_to_wide == widestr_s); + REQUIRE(utf32_to_wide == widestr_s); + REQUIRE(wide_to_wide == widestr_s); + + std::u16string utf8_to_utf16 = lua["utf8"]; + std::u16string utf16_to_utf16 = lua["utf16"]; + std::u16string utf32_to_utf16 = lua["utf32"]; + std::u16string wide_to_utf16 = lua["wide"]; + + REQUIRE(utf8_to_utf16 == utf16str_s); + REQUIRE(utf16_to_utf16 == utf16str_s); + REQUIRE(utf32_to_utf16 == utf16str_s); + REQUIRE(wide_to_utf16 == utf16str_s); + + std::u32string utf8_to_utf32 = lua["utf8"]; + std::u32string utf16_to_utf32 = lua["utf16"]; + std::u32string utf32_to_utf32 = lua["utf32"]; + std::u32string wide_to_utf32 = lua["wide"]; + + REQUIRE(utf8_to_utf32 == utf32str_s); + REQUIRE(utf16_to_utf32 == utf32str_s); + REQUIRE(utf32_to_utf32 == utf32str_s); + REQUIRE(wide_to_utf32 == utf32str_s); + + char32_t utf8_to_char32 = lua["utf8"]; + char32_t utf16_to_char32 = lua["utf16"]; + char32_t utf32_to_char32 = lua["utf32"]; + char32_t wide_to_char32 = lua["wide"]; + + REQUIRE(utf8_to_char32 == utf32str[0]); + REQUIRE(utf16_to_char32 == utf32str[0]); + REQUIRE(utf32_to_char32 == utf32str[0]); + REQUIRE(wide_to_char32 == utf32str[0]); +#endif // codecvt support +} + +TEST_CASE("detail/demangling", "test some basic demangling cases") { + std::string teststr = sol::detail::short_demangle(); + std::string nsteststr = sol::detail::short_demangle(); + std::string nsateststr = sol::detail::short_demangle(); + + REQUIRE(teststr == "test"); + REQUIRE(nsteststr == "ns_test"); + REQUIRE(nsateststr == "ns_anon_test"); +} + +TEST_CASE("object/string-pushers", "test some basic string pushers with in_place constructor") { + sol::state lua; + + sol::object ocs(lua, sol::in_place, "bark\0bark", 9); + sol::object os(lua, sol::in_place, std::string("bark\0bark", 9), 8); + bool test1 = os.as() == std::string("bark\0bar", 8); + bool test2 = ocs.as() == std::string("bark\0bark", 9); + REQUIRE(test1); + REQUIRE(test2); +} diff --git a/3rdparty/sol2/test_tables.cpp b/3rdparty/sol2/test_tables.cpp new file mode 100644 index 00000000000..cb8f291ee09 --- /dev/null +++ b/3rdparty/sol2/test_tables.cpp @@ -0,0 +1,548 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include +#include +#include +#include + +#include "test_stack_guard.hpp" + +std::string free_function() { + INFO("free_function()"); + return "test"; +} + +struct object { + std::string operator() () { + INFO("member_test()"); + return "test"; + } +}; + +int plop_xyz(int x, int y, std::string z) { + INFO(x << " " << y << " " << z); + return 11; +} + +TEST_CASE("tables/as-enums", "Making sure enums can be put in and gotten out as values") { + enum direction { + up, + down, + left, + right + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua["direction"] = lua.create_table_with( + "up", direction::up, + "down", direction::down, + "left", direction::left, + "right", direction::right + ); + + sol::object obj = lua["direction"]["up"]; + bool isdir = obj.is(); + REQUIRE(isdir); + auto dir = obj.as(); + REQUIRE(dir == direction::up); +} + +TEST_CASE("tables/as-enum-classes", "Making sure enums can be put in and gotten out as values") { + enum class direction { + up, + down, + left, + right + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua["direction"] = lua.create_table_with( + "up", direction::up, + "down", direction::down, + "left", direction::left, + "right", direction::right + ); + + sol::object obj = lua["direction"]["up"]; + bool isdir = obj.is(); + REQUIRE(isdir); + auto dir = obj.as(); + REQUIRE(dir == direction::up); +} + +TEST_CASE("tables/cleanup", "make sure tables leave the stack balanced") { + sol::state lua; + lua.open_libraries(); + + auto f = [] { return 5; }; + for (int i = 0; i < 30; i++) { + std::string name = std::string("init") + std::to_string(i); + int top = lua_gettop(lua); + lua[name] = f; + int aftertop = lua_gettop(lua); + REQUIRE(aftertop == top); + int val = lua[name](); + REQUIRE(val == 5); + } +} + +TEST_CASE("tables/nested-cleanup", "make sure tables leave the stack balanced") { + sol::state lua; + lua.open_libraries(); + + lua.script("A={}"); + auto f = [] { return 5; }; + for (int i = 0; i < 30; i++) { + std::string name = std::string("init") + std::to_string(i); + int top = lua_gettop(lua); + auto A = lua["A"]; + int beforetop = lua_gettop(lua); + REQUIRE(beforetop == top); + A[name] = f; + int aftertop = lua_gettop(lua); + REQUIRE(aftertop == top); + int val = A[name](); + REQUIRE(val == 5); + } +} + +TEST_CASE("tables/new_enum", "Making sure enums can be put in and gotten out as values") { + enum class direction { + up, + down, + left, + right + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_enum( "direction", + "up", direction::up, + "down", direction::down, + "left", direction::left, + "right", direction::right + ); + + direction d = lua["direction"]["left"]; + REQUIRE(d == direction::left); + REQUIRE_THROWS(lua.script("direction.left = 50")); + d = lua["direction"]["left"]; + REQUIRE(d == direction::left); +} + +TEST_CASE("tables/for-each", "Testing the use of for_each to get values from a lua table") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("arr = {\n" + "[0] = \"Hi\",\n" + "[1] = 123.45,\n" + "[2] = \"String value\",\n" + // Does nothing + //"[3] = nil,\n" + //"[nil] = 3,\n" + "[\"WOOF\"] = 123,\n" + "}"); + sol::table tbl = lua["arr"]; + std::size_t tablesize = 4; + std::size_t iterations = 0; + auto fx = [&iterations](sol::object key, sol::object value) { + ++iterations; + sol::type keytype = key.get_type(); + switch (keytype) { + case sol::type::number: + switch (key.as()) { + case 0: + REQUIRE((value.as() == "Hi")); + break; + case 1: + REQUIRE((value.as() == 123.45)); + break; + case 2: + REQUIRE((value.as() == "String value")); + break; + case 3: + REQUIRE((value.is())); + break; + } + break; + case sol::type::string: + if (key.as() == "WOOF") { + REQUIRE((value.as() == 123)); + } + break; + case sol::type::nil: + REQUIRE((value.as() == 3)); + break; + default: + break; + } + }; + auto fxpair = [&fx](std::pair kvp) { fx(kvp.first, kvp.second); }; + tbl.for_each(fx); + REQUIRE(iterations == tablesize); + + iterations = 0; + tbl.for_each(fxpair); + REQUIRE(iterations == tablesize); +} + +TEST_CASE("tables/for-each-empty", "empty tables should not crash") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("arr = {}"); + sol::table tbl = lua["arr"]; + REQUIRE(tbl.empty()); + std::size_t tablesize = 0; + std::size_t iterations = 0; + auto fx = [&iterations](sol::object key, sol::object value) { + ++iterations; + sol::type keytype = key.get_type(); + switch (keytype) { + case sol::type::number: + switch (key.as()) { + case 0: + REQUIRE((value.as() == "Hi")); + break; + case 1: + REQUIRE((value.as() == 123.45)); + break; + case 2: + REQUIRE((value.as() == "String value")); + break; + case 3: + REQUIRE((value.is())); + break; + } + break; + case sol::type::string: + if (key.as() == "WOOF") { + REQUIRE((value.as() == 123)); + } + break; + case sol::type::nil: + REQUIRE((value.as() == 3)); + break; + default: + break; + } + }; + auto fxpair = [&fx](std::pair kvp) { fx(kvp.first, kvp.second); }; + tbl.for_each(fx); + REQUIRE(iterations == tablesize); + + iterations = 0; + tbl.for_each(fxpair); + REQUIRE(iterations == tablesize); + + iterations = 0; + for (const auto& kvp : tbl) { + fxpair(kvp); + ++iterations; + } + REQUIRE(iterations == tablesize); +} + +TEST_CASE("tables/iterators", "Testing the use of iteratrs to get values from a lua table") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("arr = {\n" + "[0] = \"Hi\",\n" + "[1] = 123.45,\n" + "[2] = \"String value\",\n" + // Does nothing + //"[3] = nil,\n" + //"[nil] = 3,\n" + "[\"WOOF\"] = 123,\n" + "}"); + sol::table tbl = lua["arr"]; + std::size_t tablesize = 4; + std::size_t iterations = 0; + + int begintop = 0; + int endtop = 0; + { + test_stack_guard s(lua.lua_state(), begintop, endtop); + for (auto& kvp : tbl) { + [&iterations](sol::object key, sol::object value) { + ++iterations; + sol::type keytype = key.get_type(); + switch (keytype) { + case sol::type::number: + switch (key.as()) { + case 0: + REQUIRE((value.as() == "Hi")); + break; + case 1: + REQUIRE((value.as() == 123.45)); + break; + case 2: + REQUIRE((value.as() == "String value")); + break; + case 3: + REQUIRE((value.is())); + break; + } + break; + case sol::type::string: + if (key.as() == "WOOF") { + REQUIRE((value.as() == 123)); + } + break; + case sol::type::nil: + REQUIRE((value.as() == 3)); + break; + default: + break; + } + }(kvp.first, kvp.second); + } + } REQUIRE(begintop == endtop); + REQUIRE(iterations == tablesize); +} + +TEST_CASE("tables/variables", "Check if tables and variables work as intended") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::os); + lua.get("os").set("name", "windows"); + REQUIRE_NOTHROW(lua.script("assert(os.name == \"windows\")")); +} + +TEST_CASE("tables/create", "Check if creating a table is kosher") { + sol::state lua; + lua["testtable"] = sol::table::create(lua.lua_state(), 0, 0, "Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + sol::table testtable = testobj.as(); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/create-local", "Check if creating a table is kosher") { + sol::state lua; + lua["testtable"] = lua.create_table(0, 0, "Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + sol::table testtable = testobj.as(); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/create-local-named", "Check if creating a table is kosher") { + sol::state lua; + sol::table testtable = lua.create_table("testtable", 0, 0, "Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + REQUIRE((testobj == testtable)); + REQUIRE_FALSE((testobj != testtable)); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/create-with-local", "Check if creating a table is kosher") { + sol::state lua; + lua["testtable"] = lua.create_table_with("Woof", "Bark", 1, 2, 3, 4); + sol::object testobj = lua["testtable"]; + REQUIRE(testobj.is()); + sol::table testtable = testobj.as(); + REQUIRE((testtable["Woof"] == std::string("Bark"))); + REQUIRE((testtable[1] == 2)); + REQUIRE((testtable[3] == 4)); +} + +TEST_CASE("tables/functions-variables", "Check if tables and function calls work as intended") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::os); + auto run_script = [](sol::state& lua) -> void { + lua.script("assert(os.fun() == \"test\")"); + }; + + lua.get("os").set_function("fun", + []() { + INFO("stateless lambda()"); + return "test"; + } + ); + REQUIRE_NOTHROW(run_script(lua)); + + lua.get("os").set_function("fun", &free_function); + REQUIRE_NOTHROW(run_script(lua)); + + // l-value, canNOT optimise + // prefer value semantics unless wrapped with std::reference_wrapper + { + auto lval = object(); + lua.get("os").set_function("fun", &object::operator(), lval); + } + REQUIRE_NOTHROW(run_script(lua)); + + auto reflval = object(); + lua.get("os").set_function("fun", &object::operator(), std::ref(reflval)); + REQUIRE_NOTHROW(run_script(lua)); + + + // stateful lambda: non-convertible, cannot be optimised + int breakit = 50; + lua.get("os").set_function("fun", + [&breakit]() { + INFO("stateful lambda()"); + return "test"; + } + ); + REQUIRE_NOTHROW(run_script(lua)); + + // r-value, cannot optimise + lua.get("os").set_function("fun", &object::operator(), object()); + REQUIRE_NOTHROW(run_script(lua)); + + // r-value, cannot optimise + auto rval = object(); + lua.get("os").set_function("fun", &object::operator(), std::move(rval)); + REQUIRE_NOTHROW(run_script(lua)); +} + +TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works properly") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("foo = 20\nbar = \"hello world\""); + // basic retrieval + std::string bar = lua["bar"]; + int foo = lua["foo"]; + REQUIRE(bar == "hello world"); + REQUIRE(foo == 20); + // test operator= for stringification + // errors due to ambiguous operators + bar = lua["bar"]; + + // basic setting + lua["bar"] = 20.4; + lua["foo"] = "goodbye"; + + // doesn't modify the actual values obviously. + REQUIRE(bar == "hello world"); + REQUIRE(foo == 20); + + // function setting + lua["test"] = plop_xyz; + REQUIRE_NOTHROW(lua.script("assert(test(10, 11, \"hello\") == 11)")); + + // function retrieval + sol::function test = lua["test"]; + REQUIRE(test.call(10, 11, "hello") == 11); + + // setting a lambda + lua["lamb"] = [](int x) { + return x * 2; + }; + + REQUIRE_NOTHROW(lua.script("assert(lamb(220) == 440)")); + + // function retrieval of a lambda + sol::function lamb = lua["lamb"]; + REQUIRE(lamb.call(220) == 440); + + // test const table retrieval + auto assert1 = [](const sol::table& t) { + std::string a = t["foo"]; + double b = t["bar"]; + REQUIRE(a == "goodbye"); + REQUIRE(b == 20.4); + }; + + REQUIRE_NOTHROW(assert1(lua.globals())); +} + +TEST_CASE("tables/operator[]-valid", "Test if proxies on tables can lazily evaluate validity") { + sol::state lua; + bool isFullScreen = false; + auto fullscreennopers = lua["fullscreen"]["nopers"]; + auto fullscreen = lua["fullscreen"]; + REQUIRE_FALSE(fullscreennopers.valid()); + REQUIRE_FALSE(fullscreen.valid()); + + lua["fullscreen"] = true; + + REQUIRE_FALSE(fullscreennopers.valid()); + REQUIRE(fullscreen.valid()); + isFullScreen = lua["fullscreen"]; + REQUIRE(isFullScreen); + + lua["fullscreen"] = false; + REQUIRE_FALSE(fullscreennopers.valid()); + REQUIRE(fullscreen.valid()); + isFullScreen = lua["fullscreen"]; + REQUIRE_FALSE(isFullScreen); +} + +TEST_CASE("tables/operator[]-optional", "Test if proxies on tables can lazily evaluate validity") { + sol::state lua; + + sol::optional test1 = lua["no_exist_yet"]; + bool present = (bool)test1; + REQUIRE_FALSE(present); + + lua["no_exist_yet"] = 262; + sol::optional test2 = lua["no_exist_yet"]; + present = (bool)test2; + REQUIRE(present); + REQUIRE(test2.value() == 262); + + sol::optional nope = lua["nope"]["kek"]["hah"]; + auto nope2 = lua.get>(std::make_tuple("nope", "kek", "hah")); + present = (bool)nope; + REQUIRE_FALSE(present); + present = (bool)nope2; + REQUIRE_FALSE(present); + lua.create_named_table("nope", "kek", lua.create_table_with("hah", 1)); + sol::optional non_nope = lua["nope"]["kek"]["hah"].get>(); + sol::optional non_nope2 = lua.get>(std::make_tuple("nope", "kek", "hah")); + present = (bool)non_nope; + REQUIRE(present); + present = (bool)non_nope2; + REQUIRE(present); + REQUIRE(non_nope.value() == 1); + REQUIRE(non_nope2.value() == 1); + + INFO("Keys: nope, kek, hah"); + lua.set(std::make_tuple("nope", "kek", "hah"), 35); + sol::optional non_nope3 = lua["nope"]["kek"]["hah"].get>(); + sol::optional non_nope4 = lua.get>(std::make_tuple("nope", "kek", "hah")); + present = (bool)non_nope3; + REQUIRE(present); + present = (bool)non_nope4; + REQUIRE(present); + REQUIRE(non_nope3.value() == 35); + REQUIRE(non_nope4.value() == 35); +} + +TEST_CASE("tables/add", "Basic test to make sure the 'add' feature works") { + static const int sz = 120; + + sol::state lua; + sol::table t = lua.create_table(sz, 0); + + std::vector bigvec( sz ); + std::iota(bigvec.begin(), bigvec.end(), 1); + + for (std::size_t i = 0; i < bigvec.size(); ++i) { + t.add(bigvec[i]); + } + for (std::size_t i = 0; i < bigvec.size(); ++i) { + int val = t[i + 1]; + REQUIRE(val == bigvec[i]); + } +} diff --git a/3rdparty/sol2/test_usertypes.cpp b/3rdparty/sol2/test_usertypes.cpp new file mode 100644 index 00000000000..8d5d6c01b72 --- /dev/null +++ b/3rdparty/sol2/test_usertypes.cpp @@ -0,0 +1,1425 @@ +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include +#include +#include +#include + +struct vars { + vars() { + + } + + int boop = 0; + + ~vars() { + + } +}; + +struct fuser { + int x; + fuser() : x(0) {} + + fuser(int x) : x(x) {} + + int add(int y) { + return x + y; + } + + int add2(int y) { + return x + y + 2; + } +}; + +namespace crapola { + struct fuser { + int x; + fuser() : x(0) {} + fuser(int x) : x(x) {} + fuser(int x, int x2) : x(x * x2) {} + + int add(int y) { + return x + y; + } + int add2(int y) { + return x + y + 2; + } + }; +} // crapola + +class Base { +public: + Base(int a_num) : m_num(a_num) { } + + int get_num() { + return m_num; + } + +protected: + int m_num; +}; + +class Derived : public Base { +public: + Derived(int a_num) : Base(a_num) { } + + int get_num_10() { + return 10 * m_num; + } +}; + +class abstract_A { +public: + virtual void a() = 0; +}; + +class abstract_B : public abstract_A { +public: + virtual void a() override { + INFO("overridden a() in B : public A - BARK"); + } +}; + +struct Vec { + float x, y, z; + Vec(float x, float y, float z) : x{ x }, y{ y }, z{ z } {} + float length() { + return sqrtf(x*x + y*y + z*z); + } + Vec normalized() { + float invS = 1 / length(); + return{ x * invS, y * invS, z * invS }; + } +}; + +struct giver { + int a = 0; + + giver() { + + } + + void gief() { + a = 1; + } + + static void stuff() { + + } + + static void gief_stuff(giver& t, int a) { + t.a = a; + } + + ~giver() { + + } + +}; + +struct factory_test { +private: + factory_test() { a = true_a; } + ~factory_test() { a = 0; } +public: + static int num_saved; + static int num_killed; + + struct deleter { + void operator()(factory_test* f) { + f->~factory_test(); + } + }; + + static const int true_a; + int a; + + static std::unique_ptr make() { + return std::unique_ptr(new factory_test(), deleter()); + } + + static void save(factory_test& f) { + new(&f)factory_test(); + ++num_saved; + } + + static void kill(factory_test& f) { + f.~factory_test(); + ++num_killed; + } +}; + +int factory_test::num_saved = 0; +int factory_test::num_killed = 0; +const int factory_test::true_a = 156; + +bool something() { + return true; +} + +struct thing { + int v = 100; + + thing() {} + thing(int x) : v(x) {} +}; + +struct self_test { + int bark; + + self_test() : bark(100) { + + } + + void g(const std::string& str) { + std::cout << str << '\n'; + bark += 1; + } + + void f(const self_test& t) { + std::cout << "got test" << '\n'; + if (t.bark != bark) + throw sol::error("bark values are not the same for self_test f function"); + if (&t != this) + throw sol::error("call does not reference self for self_test f function"); + } +}; + +struct ext_getset { + + int bark = 24; + const int meow = 56; + + ext_getset() = default; + ext_getset(int v) : bark(v) {} + ext_getset(ext_getset&&) = default; + ext_getset(const ext_getset&) = delete; + ext_getset& operator=(ext_getset&&) = default; + ext_getset& operator=(const ext_getset&) = delete; + ~ext_getset() { + + } + + std::string x() { + return "bark bark bark"; + } + + int x2(std::string x) { + return static_cast(x.length()); + } + + void set(sol::variadic_args, sol::this_state, int x) { + bark = x; + } + + int get(sol::this_state, sol::variadic_args) { + return bark; + } + + static void s_set(int) { + + } + + static int s_get(int x) { + return x + 20; + } + +}; + +template +void des(T& e) { + e.~T(); +} + +TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") { + sol::state lua; + + sol::usertype lc{ "add", &fuser::add, "add2", &fuser::add2 }; + lua.set_usertype(lc); + + lua.script("a = fuser:new()\n" + "b = a:add(1)\n" + "c = a:add2(1)\n"); + + sol::object a = lua.get("a"); + sol::object b = lua.get("b"); + sol::object c = lua.get("c"); + REQUIRE((a.is())); + auto atype = a.get_type(); + auto btype = b.get_type(); + auto ctype = c.get_type(); + REQUIRE((atype == sol::type::userdata)); + REQUIRE((btype == sol::type::number)); + REQUIRE((ctype == sol::type::number)); + int bresult = b.as(); + int cresult = c.as(); + REQUIRE(bresult == 1); + REQUIRE(cresult == 3); +} + +TEST_CASE("usertype/usertype-constructors", "Show that we can create classes from usertype and use them with multiple constructors") { + + sol::state lua; + + sol::constructors, sol::types, sol::types> con; + sol::usertype lc(con, "add", &crapola::fuser::add, "add2", &crapola::fuser::add2); + lua.set_usertype(lc); + + lua.script( + "a = fuser.new(2)\n" + "u = a:add(1)\n" + "v = a:add2(1)\n" + "b = fuser:new()\n" + "w = b:add(1)\n" + "x = b:add2(1)\n" + "c = fuser.new(2, 3)\n" + "y = c:add(1)\n" + "z = c:add2(1)\n"); + sol::object a = lua.get("a"); + auto atype = a.get_type(); + REQUIRE((atype == sol::type::userdata)); + sol::object u = lua.get("u"); + sol::object v = lua.get("v"); + REQUIRE((u.as() == 3)); + REQUIRE((v.as() == 5)); + + sol::object b = lua.get("b"); + auto btype = b.get_type(); + REQUIRE((btype == sol::type::userdata)); + sol::object w = lua.get("w"); + sol::object x = lua.get("x"); + REQUIRE((w.as() == 1)); + REQUIRE((x.as() == 3)); + + sol::object c = lua.get("c"); + auto ctype = c.get_type(); + REQUIRE((ctype == sol::type::userdata)); + sol::object y = lua.get("y"); + sol::object z = lua.get("z"); + REQUIRE((y.as() == 7)); + REQUIRE((z.as() == 9)); +} + +TEST_CASE("usertype/usertype-utility", "Show internal management of classes registered through new_usertype") { + sol::state lua; + + lua.new_usertype("fuser", "add", &fuser::add, "add2", &fuser::add2); + + lua.script("a = fuser.new()\n" + "b = a:add(1)\n" + "c = a:add2(1)\n"); + + sol::object a = lua.get("a"); + sol::object b = lua.get("b"); + sol::object c = lua.get("c"); + REQUIRE((a.is())); + auto atype = a.get_type(); + auto btype = b.get_type(); + auto ctype = c.get_type(); + REQUIRE((atype == sol::type::userdata)); + REQUIRE((btype == sol::type::number)); + REQUIRE((ctype == sol::type::number)); + int bresult = b.as(); + int cresult = c.as(); + REQUIRE(bresult == 1); + REQUIRE(cresult == 3); +} + +TEST_CASE("usertype/usertype-utility-derived", "usertype classes must play nice when a derived class does not overload a publically visible base function") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::constructors> basector; + sol::usertype baseusertype(basector, "get_num", &Base::get_num); + + lua.set_usertype(baseusertype); + + lua.script("base = Base.new(5)"); + REQUIRE_NOTHROW(lua.script("print(base:get_num())")); + + sol::constructors> derivedctor; + sol::usertype derivedusertype(derivedctor, + "get_num_10", &Derived::get_num_10, + "get_num", &Derived::get_num + ); + + lua.set_usertype(derivedusertype); + + lua.script("derived = Derived.new(7)"); + lua.script("dgn = derived:get_num()\n" + "print(dgn)"); + lua.script("dgn10 = derived:get_num_10()\n" + "print(dgn10)"); + + REQUIRE((lua.get("dgn10") == 70)); + REQUIRE((lua.get("dgn") == 7)); +} + +TEST_CASE("usertype/self-referential usertype", "usertype classes must play nice when C++ object types are requested for C++ code") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("test", "g", &self_test::g, "f", &self_test::f); + + lua.script( + "local a = test.new()\n" + "a:g(\"woof\")\n" + "a:f(a)\n" + ); +} + +TEST_CASE("usertype/issue-number-twenty-five", "Using pointers and references from C++ classes in Lua") { + struct test { + int x = 0; + test& set() { + x = 10; + return *this; + } + + int get() { + return x; + } + + test* pget() { + return this; + } + + test create_get() { + return *this; + } + + int fun(int xa) { + return xa * 10; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("test", "set", &test::set, "get", &test::get, "pointer_get", &test::pget, "fun", &test::fun, "create_get", &test::create_get); + REQUIRE_NOTHROW(lua.script("x = test.new()")); + REQUIRE_NOTHROW(lua.script("assert(x:set():get() == 10)")); + REQUIRE_NOTHROW(lua.script("y = x:pointer_get()")); + REQUIRE_NOTHROW(lua.script("y:set():get()")); + REQUIRE_NOTHROW(lua.script("y:fun(10)")); + REQUIRE_NOTHROW(lua.script("x:fun(10)")); + REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == x:fun(10), '...')")); + REQUIRE_NOTHROW(lua.script("assert(y:fun(10) == 100, '...')")); + REQUIRE_NOTHROW(lua.script("assert(y:set():get() == y:set():get(), '...')")); + REQUIRE_NOTHROW(lua.script("assert(y:set():get() == 10, '...')")); +} + +TEST_CASE("usertype/issue-number-thirty-five", "using value types created from lua-called C++ code, fixing user-defined types with constructors") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + sol::constructors> ctor; + sol::usertype udata(ctor, "normalized", &Vec::normalized, "length", &Vec::length); + lua.set_usertype(udata); + + REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" + "print(v:length())")); + REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" + "print(v:normalized():length())")); +} + +TEST_CASE("usertype/lua-stored-usertype", "ensure usertype values can be stored without keeping usertype object alive") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + { + sol::constructors> ctor; + sol::usertype udata(ctor, + "normalized", &Vec::normalized, + "length", &Vec::length); + + lua.set_usertype(udata); + // usertype dies, but still usable in lua! + } + + REQUIRE_NOTHROW(lua.script("collectgarbage()\n" + "v = Vec.new(1, 2, 3)\n" + "print(v:length())")); + + REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" + "print(v:normalized():length())")); +} + +TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as member variables for usertype") { + sol::state lua; + lua.open_libraries(sol::lib::base); + sol::constructors> ctor; + sol::usertype udata(ctor, + "x", &Vec::x, + "y", &Vec::y, + "z", &Vec::z, + "normalized", &Vec::normalized, + "length", &Vec::length); + lua.set_usertype(udata); + + REQUIRE_NOTHROW(lua.script("v = Vec.new(1, 2, 3)\n" + "v2 = Vec.new(0, 1, 0)\n" + "print(v:length())\n" + )); + REQUIRE_NOTHROW(lua.script("v.x = 2\n" + "v2.y = 2\n" + "print(v.x, v.y, v.z)\n" + "print(v2.x, v2.y, v2.z)\n" + )); + REQUIRE_NOTHROW(lua.script("assert(v.x == 2)\n" + "assert(v2.x == 0)\n" + "assert(v2.y == 2)\n" + )); + REQUIRE_NOTHROW(lua.script("v.x = 3\n" + "local x = v.x\n" + "assert(x == 3)\n" + )); + + struct breaks { + sol::function f; + }; + + lua.open_libraries(sol::lib::base); + lua.set("b", breaks()); + lua.new_usertype("breaks", + "f", &breaks::f + ); + + breaks& b = lua["b"]; + REQUIRE_NOTHROW(lua.script("b.f = function () print('BARK!') end")); + REQUIRE_NOTHROW(lua.script("b.f()")); + REQUIRE_NOTHROW(b.f()); +} + +TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("giver", + "gief_stuff", giver::gief_stuff, + "gief", &giver::gief, + "__tostring", [](const giver& t) { + return std::to_string(t.a) + ": giving value"; + } + ).get("giver") + .set_function("stuff", giver::stuff); + + REQUIRE_NOTHROW(lua.script("giver.stuff()")); + REQUIRE_NOTHROW(lua.script("t = giver.new()\n" + "print(tostring(t))\n" + "t:gief()\n" + "t:gief_stuff(20)\n")); + giver& g = lua.get("t"); + REQUIRE(g.a == 20); +} + +TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique and shared pointers ('unique usertypes')") { + const int64_t unique_value = 0x7125679355635963; + auto uniqueint = std::make_unique(unique_value); + auto sharedint = std::make_shared(unique_value); + long preusecount = sharedint.use_count(); + { sol::state lua; + lua.open_libraries(sol::lib::base); + lua.set("uniqueint", std::move(uniqueint)); + lua.set("sharedint", sharedint); + std::unique_ptr& uniqueintref = lua["uniqueint"]; + std::shared_ptr& sharedintref = lua["sharedint"]; + int64_t* rawuniqueintref = lua["uniqueint"]; + int64_t* rawsharedintref = lua["sharedint"]; + int siusecount = sharedintref.use_count(); + REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref)); + REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr)); + REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get())); + REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref)); + REQUIRE(siusecount == sharedint.use_count()); + std::shared_ptr moreref = sharedint; + REQUIRE(unique_value == *moreref.get()); + REQUIRE(moreref.use_count() == sharedint.use_count()); + REQUIRE(moreref.use_count() == sharedintref.use_count()); + } + REQUIRE(preusecount == sharedint.use_count()); +} + +TEST_CASE("regressions/one", "issue number 48") { + sol::state lua; + lua.new_usertype("vars", + "boop", &vars::boop); + REQUIRE_NOTHROW(lua.script("beep = vars.new()\n" + "beep.boop = 1")); + // test for segfault + auto my_var = lua.get("beep"); + REQUIRE(my_var.boop == 1); + auto* ptr = &my_var; + REQUIRE(ptr->boop == 1); +} + +TEST_CASE("usertype/get-set-references", "properly get and set with std::ref semantics. Note that to get, we must not use Unqualified on the type...") { + sol::state lua; + + lua.new_usertype("vars", + "boop", &vars::boop); + vars var{}; + vars rvar{}; + lua.set("beep", var); + lua.set("rbeep", std::ref(rvar)); + auto& my_var = lua.get("beep"); + auto& ref_var = lua.get>("rbeep"); + vars& proxy_my_var = lua["beep"]; + std::reference_wrapper proxy_ref_var = lua["rbeep"]; + var.boop = 2; + rvar.boop = 5; + + // Was return as a value: var must be diferent from "beep" + REQUIRE_FALSE(std::addressof(var) == std::addressof(my_var)); + REQUIRE_FALSE(std::addressof(proxy_my_var) == std::addressof(var)); + REQUIRE((my_var.boop == 0)); + REQUIRE(var.boop != my_var.boop); + + REQUIRE(std::addressof(ref_var) == std::addressof(rvar)); + REQUIRE(std::addressof(proxy_ref_var.get()) == std::addressof(rvar)); + REQUIRE(rvar.boop == 5); + REQUIRE(rvar.boop == ref_var.boop); +} + +TEST_CASE("usertype/destructor-tests", "Show that proper copies / destruction happens") { + static int created = 0; + static int destroyed = 0; + static void* last_call = nullptr; + struct x { + x() { ++created; } + x(const x&) { ++created; } + x(x&&) { ++created; } + x& operator=(const x&) { return *this; } + x& operator=(x&&) { return *this; } + ~x() { ++destroyed; } + }; + { + sol::state lua; + lua.new_usertype("x"); + x x1; + x x2; + lua.set("x1copy", x1, "x2copy", x2, "x1ref", std::ref(x1)); + x& x1copyref = lua["x1copy"]; + x& x2copyref = lua["x2copy"]; + x& x1ref = lua["x1ref"]; + REQUIRE(created == 4); + REQUIRE(destroyed == 0); + REQUIRE(std::addressof(x1) == std::addressof(x1ref)); + REQUIRE(std::addressof(x1copyref) != std::addressof(x1)); + REQUIRE(std::addressof(x2copyref) != std::addressof(x2)); + } + REQUIRE(created == 4); + REQUIRE(destroyed == 4); +} + +TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") { + int numsaved = factory_test::num_saved; + int numkilled = factory_test::num_killed; + { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("factory_test", + "new", sol::initializers(factory_test::save), + "__gc", sol::destructor(factory_test::kill), + "a", &factory_test::a + ); + + std::unique_ptr f = factory_test::make(); + lua.set("true_a", factory_test::true_a, "f", f.get()); + REQUIRE_NOTHROW(lua.script("assert(f.a == true_a)")); + + REQUIRE_NOTHROW(lua.script( + "local fresh_f = factory_test:new()\n" + "assert(fresh_f.a == true_a)\n")); + } + int expectednumsaved = numsaved + 1; + int expectednumkilled = numkilled + 1; + REQUIRE(expectednumsaved == factory_test::num_saved); + REQUIRE(expectednumkilled == factory_test::num_killed); +} + +TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") { + struct A { int x = 201; }; + struct B { + int foo(const A* a) { return a->x; }; + }; + + sol::state lua; + lua.new_usertype("B", + "foo", &B::foo + ); + lua.set("a", A()); + lua.set("b", B()); + lua.script("x = b:foo(a)"); + int x = lua["x"]; + REQUIRE(x == 201); +} + +TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") { + struct woof { + int var; + + int func(int x) { + return var + x; + } + + double func2(int x, int y) { + return var + x + y + 0.5; + } + + std::string func2s(int x, std::string y) { + return y + " " + std::to_string(x); + } + }; + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("woof", + "var", &woof::var, + "func", sol::overload(&woof::func, &woof::func2, &woof::func2s) + ); + + const std::string bark_58 = "bark 58"; + + REQUIRE_NOTHROW(lua.script( + "r = woof:new()\n" + "a = r:func(1)\n" + "b = r:func(1, 2)\n" + "c = r:func(58, 'bark')\n" + )); + REQUIRE((lua["a"] == 1)); + REQUIRE((lua["b"] == 3.5)); + REQUIRE((lua["c"] == bark_58)); + + REQUIRE_THROWS(lua.script("r:func(1,2,'meow')")); +} + +TEST_CASE("usertype/overloading_values", "ensure overloads handle properly") { + struct overloading_test { + int print(int i) { INFO("Integer print: " << i); return 500 + i; } + int print() { INFO("No param print."); return 500; } + }; + + sol::state lua; + lua.new_usertype("overloading_test", sol::constructors<>(), + "print", sol::overload(static_cast(&overloading_test::print), static_cast(&overloading_test::print)), + "print2", sol::overload(static_cast(&overloading_test::print), static_cast(&overloading_test::print)) + ); + lua.set("test", overloading_test()); + + sol::function f0_0 = lua.load("return test:print()"); + sol::function f0_1 = lua.load("return test:print2()"); + sol::function f1_0 = lua.load("return test:print(24)"); + sol::function f1_1 = lua.load("return test:print2(24)"); + int res = f0_0(); + int res2 = f0_1(); + int res3 = f1_0(); + int res4 = f1_1(); + + REQUIRE(res == 500); + REQUIRE(res2 == 500); + + REQUIRE(res3 == 524); + REQUIRE(res4 == 524); +} + +TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles properly and errors out at runtime") { + struct bark { + int var = 50; + }; + struct woof { + bark b; + }; + + struct nested { + const int f = 25; + }; + + struct outer { + nested n; + }; + + sol::state lua; + lua.new_usertype("woof", + "b", &woof::b); + lua.new_usertype("bark", + "var", &bark::var); + lua.new_usertype("outer", + "n", &outer::n); + lua.set("w", woof()); + lua.set("n", nested()); + lua.set("o", outer()); + lua.set("f", sol::c_call); + lua.script(R"( + x = w.b + x.var = 20 + val = w.b.var == x.var + v = f(n); + )"); + + woof& w = lua["w"]; + bark& x = lua["x"]; + nested& n = lua["n"]; + int v = lua["v"]; + bool val = lua["val"]; + // enforce reference semantics + REQUIRE(std::addressof(w.b) == std::addressof(x)); + REQUIRE(n.f == 25); + REQUIRE(v == 25); + REQUIRE(val); + + REQUIRE_THROWS(lua.script("f(n, 50)")); + REQUIRE_THROWS(lua.script("o.n = 25")); +} + +TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions can be called on userdata and from their originating (meta)tables") { + struct bark { + int var = 50; + + void func() {} + + static void oh_boy() {} + + static int oh_boy(std::string name) { + return static_cast(name.length()); + } + + int operator()(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("bark", + "var", &bark::var, + "var2", sol::readonly(&bark::var), + "something", something, + "something2", [](int x, int y) { return x + y; }, + "func", &bark::func, + "oh_boy", sol::overload(sol::resolve(&bark::oh_boy), sol::resolve(&bark::oh_boy)), + sol::meta_function::call_function, &bark::operator() + ); + + REQUIRE_NOTHROW(lua.script("assert(bark.oh_boy('woo') == 3)")); + REQUIRE_NOTHROW(lua.script("bark.oh_boy()")); + + bark b; + lua.set("b", &b); + + sol::table b_table = lua["b"]; + sol::function member_func = b_table["func"]; + sol::function s = b_table["something"]; + sol::function s2 = b_table["something2"]; + + sol::table b_metatable = b_table[sol::metatable_key]; + bool isvalidmt = b_metatable.valid(); + REQUIRE(isvalidmt); + sol::function b_call = b_metatable["__call"]; + sol::function b_as_function = lua["b"]; + + int x = b_as_function(1); + int y = b_call(b, 1); + bool z = s(); + int w = s2(2, 3); + REQUIRE(x == 1); + REQUIRE(y == 1); + REQUIRE(z); + REQUIRE(w == 5); + + lua.script(R"( +lx = b(1) +ly = getmetatable(b).__call(b, 1) +lz = b.something() +lz2 = bark.something() +lw = b.something2(2, 3) +lw2 = bark.something2(2, 3) + )"); + + int lx = lua["lx"]; + int ly = lua["ly"]; + bool lz = lua["lz"]; + int lw = lua["lw"]; + bool lz2 = lua["lz2"]; + int lw2 = lua["lw2"]; + REQUIRE(lx == 1); + REQUIRE(ly == 1); + REQUIRE(lz); + REQUIRE(lz2); + REQUIRE(lw == 5); + REQUIRE(lw2 == 5); + REQUIRE(lx == ly); + REQUIRE(lz == lz2); + REQUIRE(lw == lw2); + + REQUIRE_THROWS(lua.script("b.var2 = 2")); +} + +TEST_CASE("usertype/properties", "Check if member properties/variables work") { + struct bark { + int var = 50; + int var2 = 25; + + int get_var2() const { + return var2; + } + + int get_var3() { + return var2; + } + + void set_var2(int x) { + var2 = x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("bark", + "var", &bark::var, + "var2", sol::readonly(&bark::var2), + "a", sol::property(&bark::get_var2, &bark::set_var2), + "b", sol::property(&bark::get_var2), + "c", sol::property(&bark::get_var3), + "d", sol::property(&bark::set_var2) + ); + + bark b; + lua.set("b", &b); + + lua.script("b.a = 59"); + lua.script("var2_0 = b.a"); + lua.script("var2_1 = b.b"); + lua.script("b.d = 1568"); + lua.script("var2_2 = b.c"); + + int var2_0 = lua["var2_0"]; + int var2_1 = lua["var2_1"]; + int var2_2 = lua["var2_2"]; + REQUIRE(var2_0 == 59); + REQUIRE(var2_1 == 59); + REQUIRE(var2_2 == 1568); + + REQUIRE_THROWS(lua.script("b.var2 = 24")); + REQUIRE_THROWS(lua.script("r = b.d")); + REQUIRE_THROWS(lua.script("r = b.d")); + REQUIRE_THROWS(lua.script("b.b = 25")); + REQUIRE_THROWS(lua.script("b.c = 11")); +} + +TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") { + class Test { + public: + void sayHello() { std::cout << "Hey\n"; } + }; + + sol::state lua; + lua.new_usertype("Test", "sayHello", &Test::sayHello); + static const std::string code = R"( + local t = Test.new() + t:sayHello() --Works fine + t.sayHello() --Uh oh. + )"; + REQUIRE_THROWS(lua.script(code)); +} + +TEST_CASE("usertype/call_constructor", "make sure lua types can be constructed with function call constructors") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("thing", + "v", &thing::v + , sol::call_constructor, sol::constructors, sol::types>() + ); + + lua.script(R"( +t = thing(256) +)"); + + thing& y = lua["t"]; + INFO(y.v); + REQUIRE(y.v == 256); +} + +TEST_CASE("usertype/call_constructor_2", "prevent metatable regression") { + class class01 { + public: + int x = 57; + class01() {} + }; + + class class02 { + public: + int x = 50; + class02() {} + class02(const class01& other) : x(other.x) {} + }; + + sol::state lua; + + lua.new_usertype("class01", + sol::call_constructor, sol::constructors, sol::types>() + ); + + lua.new_usertype("class02", + sol::call_constructor, sol::constructors, sol::types, sol::types>() + ); + + REQUIRE_NOTHROW(lua.script(R"( +x = class01() +y = class02(x) +)")); + class02& y = lua["y"]; + REQUIRE(y.x == 57); +} + +TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("thing", + "v", &thing::v + , sol::call_constructor, sol::constructors<>() + ); + + REQUIRE_THROWS(lua.script("t = thing(256)")); +} + + +TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + SECTION("order1") + { + lua.new_usertype("thing", + "v", &thing::v + , sol::call_constructor, sol::no_constructor + ); + REQUIRE_THROWS(lua.script("t = thing.new()")); + } + + SECTION("order2") + { + lua.new_usertype("thing" + , sol::call_constructor, sol::no_constructor + , "v", &thing::v + ); + REQUIRE_THROWS(lua.script("t = thing.new()")); + } + + REQUIRE_THROWS(lua.script("t = thing.new()")); +} + +TEST_CASE("usertype/coverage", "try all the things") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("ext_getset", + sol::call_constructor, sol::constructors, sol::types>(), + sol::meta_function::garbage_collect, sol::destructor(des), + "x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) { + return m.meow + 50 + y + x.length(); + }), + "bark", &ext_getset::bark, + "meow", &ext_getset::meow, + "readonlybark", sol::readonly(&ext_getset::bark), + "set", &ext_getset::set, + "get", &ext_getset::get, + "sset", &ext_getset::s_set, + "sget", &ext_getset::s_get, + "propbark", sol::property(&ext_getset::set, &ext_getset::get), + "readonlypropbark", sol::property(&ext_getset::get), + "writeonlypropbark", sol::property(&ext_getset::set) + ); + + INFO("usertype created"); + + lua.script(R"( +e = ext_getset() +w = e:x(e:x(), e:x(e:x())) +print(w) +)"); + + int w = lua["w"]; + REQUIRE(w == (56 + 50 + 14 + 14)); + + INFO("REQUIRE(w) successful"); + + lua.script(R"( +e:set(500) +e.sset(24) +x = e:get() +y = e.sget(20) +)"); + + int x = lua["x"]; + int y = lua["y"]; + REQUIRE(x == 500); + REQUIRE(y == 40); + + INFO("REQUIRE(x, y) successful"); + + lua.script(R"( +e.bark = 5001 +a = e:get() +print(e.bark) +print(a) + +e.propbark = 9700 +b = e:get() +print(e.propbark) +print(b) +)"); + int a = lua["a"]; + int b = lua["b"]; + + REQUIRE(a == 5001); + REQUIRE(b == 9700); + + INFO("REQUIRE(a, b) successful"); + + lua.script(R"( +c = e.readonlybark +d = e.meow +print(e.readonlybark) +print(c) +print(e.meow) +print(d) +)"); + + int c = lua["c"]; + int d = lua["d"]; + REQUIRE(c == 9700); + REQUIRE(d == 56); + + INFO("REQUIRE(c, d) successful"); + + lua.script(R"( +e.writeonlypropbark = 500 +z = e.readonlypropbark +print(e.readonlybark) +print(e.bark) +)"); + + int z = lua["z"]; + REQUIRE(z == 500); + + INFO("REQUIRE(z) successful"); + + REQUIRE_THROWS(lua.script("e.readonlybark = 24")); + INFO("REQUIRE_THROWS 1 successful"); + REQUIRE_THROWS(lua.script("e.readonlypropbark = 500")); + INFO("REQUIRE_THROWS 2 successful"); + REQUIRE_THROWS(lua.script("y = e.writeonlypropbark")); + INFO("REQUIRE_THROWS 3 successful"); + +} + +TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") { + struct NoCopy { + int get() const { return _you_can_copy_me; } + void set(int val) { _you_can_copy_me = val; } + + int _you_can_copy_me; + std::mutex _haha_you_cant_copy_me; + }; + + sol::state lua; + lua.new_usertype("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set)); + + REQUIRE_NOTHROW( + lua.script(R"__( +nocopy = NoCopy.new() +nocopy.val = 5 + )__") + ); +} + +TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") { + struct protect_me { + int gen(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("protect_me", + "gen", sol::protect( &protect_me::gen ) + ); + + REQUIRE_NOTHROW( + lua.script(R"__( +pm = protect_me.new() +value = pcall(pm.gen,pm) +)__"); + ); + bool value = lua["value"]; + REQUIRE_FALSE(value); +} + +TEST_CASE("usertype/shared-ptr-regression", "usertype metatables should not screw over unique usertype metatables") { + static int created = 0; + static int destroyed = 0; + struct test { + test() { + ++created; + } + + ~test() { + ++destroyed; + } + }; + { + std::list> tests; + sol::state lua; + lua.open_libraries(); + + lua.new_usertype("test", + "create", [&]() -> std::shared_ptr { + tests.push_back(std::make_shared()); + return tests.back(); + } + ); + REQUIRE(created == 0); + REQUIRE(destroyed == 0); + lua.script("x = test.create()"); + REQUIRE(created == 1); + REQUIRE(destroyed == 0); + REQUIRE_FALSE(tests.empty()); + std::shared_ptr& x = lua["x"]; + std::size_t xuse = x.use_count(); + std::size_t tuse = tests.back().use_count(); + REQUIRE(xuse == tuse); + } + REQUIRE(created == 1); + REQUIRE(destroyed == 1); +} + +TEST_CASE("usertype/double-deleter-guards", "usertype metatables internally must not rely on internal ") { + struct c_a { int x; }; + struct c_b { int y; }; + REQUIRE_NOTHROW( { + sol::state lua; + lua.new_usertype("c_a", "x", &c_a::x); + lua.new_usertype("c_b", "y", &c_b::y); + lua = sol::state(); + lua.new_usertype("c_a", "x", &c_a::x); + lua.new_usertype("c_b", "y", &c_b::y); + lua = sol::state(); + }); +} + +TEST_CASE("usertype/vars", "usertype vars can bind various class items") { + static int muh_variable = 25; + static int through_variable = 10; + + sol::state lua; + lua.open_libraries(); + struct test {}; + lua.new_usertype("test", + "straight", sol::var(2), + "global", sol::var(muh_variable), + "ref_global", sol::var(std::ref(muh_variable)), + "global2", sol::var(through_variable), + "ref_global2", sol::var(std::ref(through_variable)) + ); + + int prets = lua["test"]["straight"]; + int pretg = lua["test"]["global"]; + int pretrg = lua["test"]["ref_global"]; + int pretg2 = lua["test"]["global2"]; + int pretrg2 = lua["test"]["ref_global2"]; + + REQUIRE(prets == 2); + REQUIRE(pretg == 25); + REQUIRE(pretrg == 25); + REQUIRE(pretg2 == 10); + REQUIRE(pretrg2 == 10); + + lua.script(R"( +print(test.straight) +test.straight = 50 +print(test.straight) +)"); + int s = lua["test"]["straight"]; + REQUIRE(s == 50); + + lua.script(R"( +t = test.new() +print(t.global) +t.global = 50 +print(t.global) +)"); + int mv = lua["test"]["global"]; + REQUIRE(mv == 50); + REQUIRE(muh_variable == 25); + + + lua.script(R"( +print(t.ref_global) +t.ref_global = 50 +print(t.ref_global) +)"); + int rmv = lua["test"]["ref_global"]; + REQUIRE(rmv == 50); + REQUIRE(muh_variable == 50); + + REQUIRE(through_variable == 10); + lua.script(R"( +print(test.global2) +test.global2 = 35 +print(test.global2) +)"); + int tv = lua["test"]["global2"]; + REQUIRE(through_variable == 10); + REQUIRE(tv == 35); + + lua.script(R"( +print(test.ref_global2) +test.ref_global2 = 35 +print(test.ref_global2) +)"); + int rtv = lua["test"]["ref_global2"]; + REQUIRE(rtv == 35); + REQUIRE(through_variable == 35); +} + +TEST_CASE("usertypes/var-and-property", "make sure const vars are readonly and properties can handle lambdas") { + const static int arf = 20; + + struct test { + int value = 10; + }; + + sol::state lua; + lua.open_libraries(); + + lua.new_usertype("test", + "prop", sol::property( + [](test& t) { + return t.value; + }, + [](test& t, int x) { + t.value = x; + } + ), + "global", sol::var(std::ref(arf)) + ); + + lua.script(R"( +t = test.new() +print(t.prop) +t.prop = 50 +print(t.prop) + )"); + + test& t = lua["t"]; + REQUIRE(t.value == 50); + + + REQUIRE_THROWS( + lua.script(R"( +t = test.new() +print(t.global) +t.global = 20 +print(t.global) + )")); +} + +TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") { + class Entity { + public: + std::string GetName() { + return "Charmander"; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io); + + lua.new_usertype("Entity", + "new", sol::no_constructor, + "get_name", &Entity::GetName + ); + + lua.script(R"( + function my_func(entity) + print("INSIDE LUA") + print(entity:get_name()) + end +)"); + + sol::function my_func = lua["my_func"]; + REQUIRE_NOTHROW({ + auto ent = std::make_shared(); + my_func(ent); + Entity ent2; + my_func(ent2); + my_func(std::make_shared()); + }); +} + +TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") { + sol::state lua; + lua.new_usertype("A", "a", &abstract_A::a); + lua.new_usertype("B", sol::base_classes, sol::bases()); + lua.script(R"(local b = B.new() +b:a() +)"); +} + +TEST_CASE("usertype/as_function", "Ensure that variables can be turned into functions by as_function") { + class B { + public: + int bvar = 24; + }; + + sol::state lua; + lua.open_libraries(); + lua.new_usertype("B", "b", &B::bvar, "f", sol::as_function(&B::bvar)); + + B b; + lua.set("b", &b); + lua.script("x = b:f()"); + lua.script("y = b.b"); + int x = lua["x"]; + int y = lua["y"]; + REQUIRE(x == 24); + REQUIRE(y == 24); +} + +TEST_CASE("usertype/destruction-test", "make sure usertypes are properly destructed and don't double-delete memory or segfault") { + sol::state lua; + + class CrashClass { + public: + CrashClass() { + } + + ~CrashClass() { + a = 10; // This will cause a crash. + } + + private: + int a; + }; + + lua.new_usertype("CrashClass", + sol::call_constructor, sol::constructors>() + ); + + lua.script(R"( + function testCrash() + local x = CrashClass() + end + )"); + + for (int i = 0; i < 1000; ++i) { + lua["testCrash"](); + } +} diff --git a/3rdparty/sol2/tests.cpp b/3rdparty/sol2/tests.cpp new file mode 100644 index 00000000000..9aeaf255a34 --- /dev/null +++ b/3rdparty/sol2/tests.cpp @@ -0,0 +1,680 @@ +#define CATCH_CONFIG_MAIN +#define SOL_CHECK_ARGUMENTS + +#include +#include + +#include +#include +#include +#include +#include + +#include "test_stack_guard.hpp" + +bool func_opt_ret_bool(sol::optional i) { + if (i) + { + INFO(i.value()); + } + else + { + INFO("optional isn't set"); + } + return true; +} + +TEST_CASE("table/traversal", "ensure that we can chain requests and tunnel down into a value if we desire") { + + sol::state lua; + int begintop = 0, endtop = 0; + + sol::function scriptload = lua.load("t1 = {t2 = {t3 = 24}};"); + scriptload(); + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + int traversex24 = lua.traverse_get("t1", "t2", "t3"); + REQUIRE(traversex24 == 24); + } REQUIRE(begintop == endtop); + + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + int x24 = lua["t1"]["t2"]["t3"]; + REQUIRE(x24 == 24); + } REQUIRE(begintop == endtop); + + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + lua["t1"]["t2"]["t3"] = 64; + int traversex64 = lua.traverse_get("t1", "t2", "t3"); + REQUIRE(traversex64 == 64); + } REQUIRE(begintop == endtop); + + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + int x64 = lua["t1"]["t2"]["t3"]; + REQUIRE(x64 == 64); + } REQUIRE(begintop == endtop); + + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + lua.traverse_set("t1", "t2", "t3", 13); + int traversex13 = lua.traverse_get("t1", "t2", "t3"); + REQUIRE(traversex13 == 13); + } REQUIRE(begintop == endtop); + + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + int x13 = lua["t1"]["t2"]["t3"]; + REQUIRE(x13 == 13); + } REQUIRE(begintop == endtop); +} + +TEST_CASE("simple/set", "Check if the set works properly.") { + sol::state lua; + int begintop = 0, endtop = 0; + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + lua.set("a", 9); + } REQUIRE(begintop == endtop); + REQUIRE_NOTHROW(lua.script("if a ~= 9 then error('wrong value') end")); + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + lua.set("d", "hello"); + } REQUIRE(begintop == endtop); + REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); + + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + lua.set("e", std::string("hello"), "f", true); + } REQUIRE(begintop == endtop); + REQUIRE_NOTHROW(lua.script("if d ~= 'hello' then error('expected \\'hello\\', got '.. tostring(d)) end")); + REQUIRE_NOTHROW(lua.script("if f ~= true then error('wrong value') end")); +} + +TEST_CASE("simple/get", "Tests if the get function works properly.") { + sol::state lua; + int begintop = 0, endtop = 0; + + lua.script("a = 9"); + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + auto a = lua.get("a"); + REQUIRE(a == 9.0); + } REQUIRE(begintop == endtop); + + lua.script("b = nil"); + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + REQUIRE_NOTHROW(lua.get("b")); + } REQUIRE(begintop == endtop); + + lua.script("d = 'hello'"); + lua.script("e = true"); + { + test_stack_guard g(lua.lua_state(), begintop, endtop); + std::string d; + bool e; + std::tie(d, e) = lua.get("d", "e"); + REQUIRE(d == "hello"); + REQUIRE(e == true); + } REQUIRE(begintop == endtop); +} + +TEST_CASE("simple/set-get-global-integer", "Tests if the get function works properly with global integers") { + sol::state lua; + lua[1] = 25.4; + lua.script("b = 1"); + double a = lua.get(1); + double b = lua.get("b"); + REQUIRE(a == 25.4); + REQUIRE(b == 1); +} + +TEST_CASE("simple/get_or", "check if table.get_or works correctly") { + sol::state lua; + + auto bob_table = lua.create_table("bob"); + bob_table.set("is_set", 42); + + int is_set = bob_table.get_or("is_set", 3); + int is_not_set = bob_table.get_or("is_not_set", 22); + + REQUIRE(is_set == 42); + REQUIRE(is_not_set == 22); + + lua["joe"] = 55.6; + double bark = lua.get_or("joe", 60); + REQUIRE(bark == 55.6); +} + +TEST_CASE("simple/proxy_get_or", "check if proxy.get_or works correctly") { + sol::state lua; + + auto bob_table = lua.create_table("bob"); + bob_table.set("is_set", 42); + + int is_set = bob_table["is_set"].get_or(3); + int is_not_set = bob_table["is_not_set"].get_or(22); + + REQUIRE(is_set == 42); + REQUIRE(is_not_set == 22); + + lua["joe"] = 55.6; + double bark = lua["joe"].get_or(60); + REQUIRE(bark == 55.6); +} + +TEST_CASE("simple/addition", "check if addition works and can be gotten through lua.get and lua.set") { + sol::state lua; + + lua.set("b", 0.2); + lua.script("c = 9 + b"); + auto c = lua.get("c"); + + REQUIRE(c == 9.2); +} + +TEST_CASE("simple/if", "check if if statements work through lua") { + sol::state lua; + + std::string program = "if true then f = 0.1 else f = 'test' end"; + lua.script(program); + auto f = lua.get("f"); + + REQUIRE(f == 0.1); + REQUIRE((f == lua["f"])); +} + +TEST_CASE("negative/basic_errors", "Check if error handling works correctly") { + sol::state lua; + + REQUIRE_THROWS(lua.script("nil[5]")); +} + +TEST_CASE("libraries", "Check if we can open libraries") { + sol::state lua; + REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base, sol::lib::os)); +} + +TEST_CASE("libraries2", "Check if we can open ALL the libraries") { + sol::state lua; + REQUIRE_NOTHROW(lua.open_libraries(sol::lib::base, + sol::lib::bit32, + sol::lib::coroutine, + sol::lib::debug, + sol::lib::ffi, + sol::lib::jit, + sol::lib::math, + sol::lib::os, + sol::lib::package, + sol::lib::string, + sol::lib::table)); +} + +TEST_CASE("interop/null-to-nil-and-back", "nil should be the given type when a pointer from C++ is returned as nullptr, and nil should result in nullptr in connected C++ code") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("lol", []() -> int* { + return nullptr; + }); + lua.set_function("rofl", [](int* x) { + INFO(x); + }); + REQUIRE_NOTHROW(lua.script("x = lol()\n" + "rofl(x)\n" + "assert(x == nil)")); +} + +TEST_CASE("utilities/this_state", "Ensure this_state argument can be gotten anywhere in the function.") { + struct bark { + int with_state(sol::this_state l, int a, int b) { + lua_State* L = l; + int c = lua_gettop(L); + return a + b + (c - c); + } + + static int with_state_2(int a, sol::this_state l, int b) { + INFO("inside with_state_2"); + lua_State* L = l; + INFO("L is" << (void*)L); + int c = lua_gettop(L); + return a * b + (c - c); + } + }; + + sol::state lua; + INFO("created lua state"); + lua.open_libraries(sol::lib::base); + lua.new_usertype("bark", + "with_state", &bark::with_state + ); + + INFO("setting b and with_state_2"); + bark b; + lua.set("b", &b); + lua.set("with_state_2", bark::with_state_2); + INFO("finished setting"); + INFO("getting fx"); + sol::function fx = lua["with_state_2"]; + INFO("calling fx"); + int a = fx(25, 25); + INFO("finished setting fx"); + INFO("calling a script"); + lua.script("a = with_state_2(25, 25)"); + INFO("calling c script"); + lua.script("c = b:with_state(25, 25)"); + INFO("getting a"); + int la = lua["a"]; + INFO("getting b"); + int lc = lua["c"]; + + REQUIRE(lc == 50); + REQUIRE(a == 625); + REQUIRE(la == 625); +} + +TEST_CASE("object/conversions", "make sure all basic reference types can be made into objects") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + struct d {}; + + lua.script("function f () print('bark') end"); + lua["d"] = d{}; + lua["l"] = static_cast(nullptr); + + sol::table t = lua.create_table(); + sol::thread th = sol::thread::create(lua); + sol::function f = lua["f"]; + sol::protected_function pf = lua["f"]; + sol::userdata ud = lua["d"]; + sol::lightuserdata lud = lua["l"]; + + sol::object ot(t); + sol::object ot2 = ot; + sol::object oth(th); + sol::object of(f); + sol::object opf(pf); + sol::object od(ud); + sol::object ol(lud); + + auto oni = sol::make_object(lua, 50); + auto ond = sol::make_object(lua, 50.0); + + std::string somestring = "look at this text isn't it nice"; + auto osl = sol::make_object(lua, "Bark bark bark"); + auto os = sol::make_object(lua, somestring); + + auto omn = sol::make_object(lua, sol::nil); + + REQUIRE(ot.get_type() == sol::type::table); + REQUIRE(ot2.get_type() == sol::type::table); + REQUIRE(oth.get_type() == sol::type::thread); + REQUIRE(of.get_type() == sol::type::function); + REQUIRE(opf.get_type() == sol::type::function); + REQUIRE(od.get_type() == sol::type::userdata); + REQUIRE(ol.get_type() == sol::type::lightuserdata); + REQUIRE(oni.get_type() == sol::type::number); + REQUIRE(ond.get_type() == sol::type::number); + REQUIRE(osl.get_type() == sol::type::string); + REQUIRE(os.get_type() == sol::type::string); + REQUIRE(omn.get_type() == sol::type::nil); +} + +TEST_CASE("state/require_file", "opening files as 'requires'") { + static const char FILE_NAME[] = "./tmp_thingy.lua"; + + std::fstream file(FILE_NAME, std::ios::out); + + sol::state lua; + lua.open_libraries(sol::lib::base); + + SECTION("with usertypes") + { + struct foo { + foo(int bar) : bar(bar) {} + + const int bar; + }; + + lua.new_usertype("foo", + sol::constructors>{}, + "bar", &foo::bar + ); + + file << "return { modfunc = function () return foo.new(221) end }" << std::endl; + file.close(); + + const sol::table thingy1 = lua.require_file("thingy", FILE_NAME); + + CHECK(thingy1.valid()); + + const foo foo_v = thingy1["modfunc"](); + + int val1 = foo_v.bar; + + CHECK(val1 == 221); + } + + SECTION("simple") + { + file << "return { modfunc = function () return 221 end }" << std::endl; + file.close(); + + const sol::table thingy1 = lua.require_file("thingy", FILE_NAME); + const sol::table thingy2 = lua.require_file("thingy", FILE_NAME); + + CHECK(thingy1.valid()); + CHECK(thingy2.valid()); + + int val1 = thingy1["modfunc"](); + int val2 = thingy2["modfunc"](); + + CHECK(val1 == 221); + CHECK(val2 == 221); + // must have loaded the same table + CHECK(thingy1 == thingy2); + } + + std::remove(FILE_NAME); +} + +TEST_CASE("state/require_script", "opening strings as 'requires' clauses") { + std::string code = "return { modfunc = function () return 221 end }"; + + sol::state lua; + sol::table thingy1 = lua.require_script("thingy", code); + sol::table thingy2 = lua.require_script("thingy", code); + + int val1 = thingy1["modfunc"](); + int val2 = thingy2["modfunc"](); + REQUIRE(val1 == 221); + REQUIRE(val2 == 221); + // must have loaded the same table + REQUIRE(thingy1 == thingy2); +} + +TEST_CASE("state/require", "opening using a file") { + struct open { + static int open_func(lua_State* L) { + sol::state_view lua = L; + return sol::stack::push(L, lua.create_table_with("modfunc", sol::as_function([]() { return 221; }))); + } + }; + + sol::state lua; + sol::table thingy1 = lua.require("thingy", open::open_func); + sol::table thingy2 = lua.require("thingy", open::open_func); + + int val1 = thingy1["modfunc"](); + int val2 = thingy2["modfunc"](); + REQUIRE(val1 == 221); + REQUIRE(val2 == 221); + // THIS IS ONLY REQUIRED IN LUA 5.3, FOR SOME REASON + // must have loaded the same table + // REQUIRE(thingy1 == thingy2); +} + +TEST_CASE("state/multi-require", "make sure that requires transfers across hand-rolled script implementation and standard requiref") { + struct open { + static int open_func(lua_State* L) { + sol::state_view lua = L; + return sol::stack::push(L, lua.create_table_with("modfunc", sol::as_function([]() { return 221; }))); + } + }; + + std::string code = "return { modfunc = function () return 221 end }"; + sol::state lua; + sol::table thingy1 = lua.require("thingy", open::open_func); + sol::table thingy2 = lua.require("thingy", open::open_func); + sol::table thingy3 = lua.require_script("thingy", code); + + int val1 = thingy1["modfunc"](); + int val2 = thingy2["modfunc"](); + int val3 = thingy3["modfunc"](); + REQUIRE(val1 == 221); + REQUIRE(val2 == 221); + REQUIRE(val3 == 221); + // must have loaded the same table + // Lua is not obliged to give a shit. Thanks, Lua + //REQUIRE(thingy1 == thingy2); + // But we care, thankfully + //REQUIRE(thingy1 == thingy3); + REQUIRE(thingy2 == thingy3); +} + +TEST_CASE("feature/indexing-overrides", "make sure index functions can be overridden on types") { + struct PropertySet { + sol::object get_property_lua(const char* name, sol::this_state s) + { + auto& var = props[name]; + return sol::make_object(s, var); + } + + void set_property_lua(const char* name, sol::stack_object object) + { + props[name] = object.as(); + } + + std::unordered_map props; + }; + + struct DynamicObject { + PropertySet& get_dynamic_props() { + return dynamic_props; + } + + PropertySet dynamic_props; + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("PropertySet" + , sol::meta_function::new_index, &PropertySet::set_property_lua + , sol::meta_function::index, &PropertySet::get_property_lua + ); + lua.new_usertype("DynamicObject" + , "props", sol::property(&DynamicObject::get_dynamic_props) + ); + + lua.script(R"__( +obj = DynamicObject:new() +obj.props.name = 'test name' +print('name = ' .. obj.props.name) +)__"); + + std::string name = lua["obj"]["props"]["name"]; + REQUIRE(name == "test name"); +} + +TEST_CASE("features/indexing-numbers", "make sure indexing functions can be override on usertypes") { + class vector { + public: + double data[3]; + + vector() : data{ 0,0,0 } {} + + double& operator[](int i) + { + return data[i]; + } + + + static double my_index(vector& v, int i) + { + return v[i]; + } + + static void my_new_index(vector& v, int i, double x) + { + v[i] = x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("vector", sol::constructors>(), + sol::meta_function::index, &vector::my_index, + sol::meta_function::new_index, &vector::my_new_index); + lua.script("v = vector.new()\n" + "print(v[1])\n" + "v[2] = 3\n" + "print(v[2])\n" + ); + + vector& v = lua["v"]; + REQUIRE(v[0] == 0.0); + REQUIRE(v[1] == 0.0); + REQUIRE(v[2] == 3.0); +} + +TEST_CASE("features/multiple-inheritance", "Ensure that multiple inheritance works as advertised") { + struct base1 { + int a1 = 250; + }; + + struct base2 { + int a2 = 500; + }; + + struct simple : base1 { + + }; + + struct complex : base1, base2 { + + }; + + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("base1", + "a1", &base1::a1 + ); + lua.new_usertype("base2", + "a2", &base2::a2 + ); + lua.new_usertype("simple", + "a1", &simple::a1, + sol::base_classes, sol::bases() + ); + lua.new_usertype("complex", + "a1", &complex::a1, + "a2", &complex::a2, + sol::base_classes, sol::bases() + ); + lua.script("c = complex.new()\n" + "s = simple.new()\n" + "b1 = base1.new()\n" + "b2 = base1.new()\n" + ); + + base1* sb1 = lua["s"]; + REQUIRE(sb1 != nullptr); + REQUIRE(sb1->a1 == 250); + + base1* cb1 = lua["c"]; + base2* cb2 = lua["c"]; + + REQUIRE(cb1 != nullptr); + REQUIRE(cb2 != nullptr); + REQUIRE(cb1->a1 == 250); + REQUIRE(cb2->a2 == 500); +} + + +TEST_CASE("regressions/std::ref", "Ensure that std::reference_wrapper<> isn't considered as a function by using unwrap_unqualified_t trait") { + struct base1 { + int a1 = 250; + }; + + sol::state lua; + base1 v; + lua["vp"] = &v; + lua["vr"] = std::ref(v); + + base1* vp = lua["vp"]; + base1& vr = lua["vr"]; + REQUIRE(vp != nullptr); + REQUIRE(vp == &v); + + REQUIRE(vp->a1 == 250); + REQUIRE(vr.a1 == 250); + + v.a1 = 568; + + REQUIRE(vp->a1 == 568); + REQUIRE(vr.a1 == 568); +} + +TEST_CASE("optional/left-out-args", "Make sure arguments can be left out of optional without tanking miserably") { + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // sol::optional needs an argument no matter what? + lua.set_function("func_opt_ret_bool", func_opt_ret_bool); + REQUIRE_NOTHROW( + lua.script(R"( + func_opt_ret_bool(42) + func_opt_ret_bool() + print('ok') + )"); + ); +} + +TEST_CASE("pusher/constness", "Make sure more types can handle being const and junk") { + struct Foo { + Foo(const sol::function& f) : _f(f) {} + const sol::function& _f; + + const sol::function& f() const { return _f; } + }; + + sol::state lua; + + lua.new_usertype("Foo", + sol::call_constructor, sol::no_constructor, + "f", &Foo::f + ); + + lua["func"] = []() { return 20; }; + sol::function f = lua["func"]; + lua["foo"] = Foo(f); + Foo& foo = lua["foo"]; + int x = foo.f()(); + REQUIRE(x == 20); +} + +TEST_CASE("proxy/proper-pushing", "allow proxies to reference other proxies and be serialized as the proxy itself and not a function or something") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::io); + + class T {}; + lua.new_usertype("T"); + + T t; + lua["t1"] = &t; + lua["t2"] = lua["t1"]; + lua.script("b = t1 == t2"); + bool b = lua["b"]; + REQUIRE(b); +} + +TEST_CASE("compilation/const-regression", "make sure constness in tables is respected all the way down") { + struct State { + public: + State() { + this->state_.registry()["state"] = this; + } + + sol::state state_; + }; + + State state; + State* s = state.state_.registry()["state"]; + REQUIRE(s == &state); +}