From 07416c7a468402b704154c63c20b91f5d48a729b Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 18 Jul 2017 21:08:05 +0000 Subject: [PATCH 1/4] Bump versions to latest releases --- scripts/update_dependencies.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/update_dependencies.sh b/scripts/update_dependencies.sh index 2f7953c6f..bb9fc1a00 100755 --- a/scripts/update_dependencies.sh +++ b/scripts/update_dependencies.sh @@ -10,13 +10,13 @@ set -o nounset # http://git.661346.n2.nabble.com/subtree-merges-lose-prefix-after-rebase-td7332850.html OSMIUM_REPO="https://github.com/osmcode/libosmium.git" -OSMIUM_TAG=v2.11.0 +OSMIUM_TAG=v2.11.3 VARIANT_REPO="https://github.com/mapbox/variant.git" -VARIANT_TAG=v1.1.0 +VARIANT_TAG=v1.1.3 SOL_REPO="https://github.com/ThePhD/sol2.git" -SOL_TAG=v2.15.8 +SOL_TAG=v2.17.5 RAPIDJSON_REPO="https://github.com/miloyip/rapidjson.git" RAPIDJSON_TAG=v1.1.0 From b91c2f0299722e64a6945808d64c3397c35811d0 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 18 Jul 2017 21:08:32 +0000 Subject: [PATCH 2/4] Squashed 'third_party/libosmium/' changes from c1f34c455..9fd2348c6 9fd2348c6 Release v2.11.3 ed708286e Fix namespace. 835df8a7f Fix multipolygon assembler. 0979ab529 Fix areas assembler algorithm. 801f84c62 Bugfix: Invalid use of iterators. f85653820 Read OPL file correctly even if trailing newline in file missing. a31571c0f Release v2.11.2 a3903b368 Use minimum size of 64 bytes for buffers. b86bafefe Release v2.11.1 32ebf736c Updated change log. 632ea5198 Bugfix: Call get_creator_function() in main thread. ddc79eee7 Add test for not correctly handled unsupported_file_format_error. 86197a14f Bugfix: Terminate called on full buffer. 4340be8ad Fix the Filter::count() method. git-subtree-dir: third_party/libosmium git-subtree-split: 9fd2348c6956b6e1b930b50850e99eb31207ed50 --- CHANGELOG.md | 34 +++++++++++++++++-- CMakeLists.txt | 2 +- include/osmium/area/assembler.hpp | 24 +++++++------ include/osmium/builder/builder.hpp | 18 +++++++++- include/osmium/builder/osm_object_builder.hpp | 20 ++++++----- include/osmium/io/detail/opl_input_format.hpp | 5 +++ include/osmium/io/reader.hpp | 8 +++-- include/osmium/memory/buffer.hpp | 15 ++++++-- include/osmium/tags/filter.hpp | 2 +- include/osmium/version.hpp | 4 +-- test/CMakeLists.txt | 3 +- test/t/io/data-nonl.opl | 1 + test/t/io/data.opl | 1 + test/t/io/test_opl_parser.cpp | 22 ++++++++++++ test/t/io/test_reader_fileformat.cpp | 10 ++++++ test/t/memory/test_buffer_basics.cpp | 19 +++++++++-- 16 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 test/t/io/data-nonl.opl create mode 100644 test/t/io/data.opl create mode 100644 test/t/io/test_reader_fileformat.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index d12bb76cf..cc1fdcc8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,36 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [unreleased] - -### Added +### Fixed -### Changed +## [2.11.3] - 2017-05-03 ### Fixed +- Two bugs in area assembler affecting very complex multipolygons and + multipolygons with overlapping or nearly overlapping lines. +- Invalid use of iterators leading to undefined behaviour in area assembler + code. +- Read OPL file correctly even if trailing newline in file is missing. + + +## [2.11.2] - 2017-04-10 + +### Fixed + +- Use minimum size of 64 bytes for buffers. This fixes an infinite loop + when buffer size is zero. + + +## [2.11.1] - 2017-03-07 + +### Fixed + +- Terminate called on full non-auto-growing buffer. (Issue #189.) +- When file formats were used that were not compiled into the binary, it + terminated instead of throwing. (Issue #197.) +- The `Filter::count()` method didn't compile at all. + ## [2.11.0] - 2017-01-14 @@ -525,7 +549,11 @@ This project adheres to [Semantic Versioning](http://semver.org/). Doxygen (up to version 1.8.8). This version contains a workaround to fix this. -[unreleased]: https://github.com/osmcode/libosmium/compare/v2.10.3...HEAD +[unreleased]: https://github.com/osmcode/libosmium/compare/v2.11.3...HEAD +[2.11.3]: https://github.com/osmcode/libosmium/compare/v2.11.2...v2.11.3 +[2.11.2]: https://github.com/osmcode/libosmium/compare/v2.11.1...v2.11.2 +[2.11.1]: https://github.com/osmcode/libosmium/compare/v2.11.0...v2.11.1 +[2.11.0]: https://github.com/osmcode/libosmium/compare/v2.10.3...v2.11.0 [2.10.3]: https://github.com/osmcode/libosmium/compare/v2.10.2...v2.10.3 [2.10.2]: https://github.com/osmcode/libosmium/compare/v2.10.1...v2.10.2 [2.10.1]: https://github.com/osmcode/libosmium/compare/v2.10.0...v2.10.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 21478ec8d..e536c3469 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ project(libosmium) set(LIBOSMIUM_VERSION_MAJOR 2) set(LIBOSMIUM_VERSION_MINOR 11) -set(LIBOSMIUM_VERSION_PATCH 0) +set(LIBOSMIUM_VERSION_PATCH 3) set(LIBOSMIUM_VERSION "${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}") diff --git a/include/osmium/area/assembler.hpp b/include/osmium/area/assembler.hpp index 3509b57bc..78a9d09d7 100644 --- a/include/osmium/area/assembler.hpp +++ b/include/osmium/area/assembler.hpp @@ -474,17 +474,17 @@ namespace osmium { class rings_stack_element { - int32_t m_y; + double m_y; detail::ProtoRing* m_ring_ptr; public: - rings_stack_element(int32_t y, detail::ProtoRing* ring_ptr) : + rings_stack_element(double y, detail::ProtoRing* ring_ptr) : m_y(y), m_ring_ptr(ring_ptr) { } - int32_t y() const noexcept { + double y() const noexcept { return m_y; } @@ -504,7 +504,7 @@ namespace osmium { return m_y < rhs.m_y; } - }; // class ring_stack_element + }; // class rings_stack_element using rings_stack = std::vector; @@ -592,7 +592,7 @@ namespace osmium { if (debug()) { std::cerr << " Segment belongs to outer ring\n"; } - const int32_t y = int32_t(ay + (by - ay) * (lx - ax) / (bx - ax)); + const double y = ay + (by - ay) * (lx - ax) / double(bx - ax); outer_rings.emplace_back(y, segment->ring()); } } @@ -859,8 +859,8 @@ namespace osmium { } void merge_two_rings(open_ring_its_type& open_ring_its, const location_to_ring_map& m1, const location_to_ring_map& m2) { - auto& r1 = *m1.ring_it; - auto& r2 = *m2.ring_it; + std::list::iterator r1 = *m1.ring_it; + std::list::iterator r2 = *m2.ring_it; if (r1->get_node_ref_stop().location() == r2->get_node_ref_start().location()) { r1->join_forward(*r2); @@ -876,11 +876,11 @@ namespace osmium { assert(false); } + open_ring_its.erase(std::find(open_ring_its.begin(), open_ring_its.end(), r2)); m_rings.erase(r2); - open_ring_its.remove(r2); if (r1->closed()) { - open_ring_its.remove(r1); + open_ring_its.erase(std::find(open_ring_its.begin(), open_ring_its.end(), r1)); } } @@ -988,6 +988,7 @@ namespace osmium { } loc_done.insert(c.stop_location); find_candidates(candidates, loc_done, xrings, c); + loc_done.erase(c.stop_location); if (debug()) { std::cerr << " ...back\n"; } @@ -1085,12 +1086,13 @@ namespace osmium { // Join all (open) rings in the candidate to get one closed ring. assert(chosen_cand->rings.size() > 1); const auto& first_ring = chosen_cand->rings.front().first; - for (auto it = chosen_cand->rings.begin() + 1; it != chosen_cand->rings.end(); ++it) { + const detail::ProtoRing& remaining_ring = first_ring.ring(); + for (auto it = std::next(chosen_cand->rings.begin()); it != chosen_cand->rings.end(); ++it) { merge_two_rings(open_ring_its, first_ring, it->first); } if (debug()) { - std::cerr << " Merged to " << first_ring.ring() << "\n"; + std::cerr << " Merged to " << remaining_ring << "\n"; } return true; diff --git a/include/osmium/builder/builder.hpp b/include/osmium/builder/builder.hpp index 107f4a9d0..d4358843b 100644 --- a/include/osmium/builder/builder.hpp +++ b/include/osmium/builder/builder.hpp @@ -167,6 +167,20 @@ namespace osmium { return length; } + /** + * Append data to buffer and append an additional \0. + * + * @param data Pointer to data. + * @param length Length of data in bytes. + * @returns The number of bytes appended (length + 1). + */ + osmium::memory::item_size_type append_with_zero(const char* data, const osmium::memory::item_size_type length) { + unsigned char* target = reserve_space(length + 1); + std::copy_n(reinterpret_cast(data), length, target); + target[length] = '\0'; + return length + 1; + } + /** * Append \0-terminated string to buffer. * @@ -180,9 +194,11 @@ namespace osmium { /** * Append '\0' to the buffer. * + * @deprecated Use append_with_zero() instead. + * * @returns The number of bytes appended (always 1). */ - osmium::memory::item_size_type append_zero() { + OSMIUM_DEPRECATED osmium::memory::item_size_type append_zero() { *reserve_space(1) = '\0'; return 1; } diff --git a/include/osmium/builder/osm_object_builder.hpp b/include/osmium/builder/osm_object_builder.hpp index 1dd5f972f..d4483b192 100644 --- a/include/osmium/builder/osm_object_builder.hpp +++ b/include/osmium/builder/osm_object_builder.hpp @@ -99,7 +99,8 @@ namespace osmium { if (std::strlen(value) > osmium::max_osm_string_length) { throw std::length_error("OSM tag value is too long"); } - add_size(append(key) + append(value)); + add_size(append(key)); + add_size(append(value)); } /** @@ -117,8 +118,8 @@ namespace osmium { if (value_length > osmium::max_osm_string_length) { throw std::length_error("OSM tag value is too long"); } - add_size(append(key, osmium::memory::item_size_type(key_length)) + append_zero() + - append(value, osmium::memory::item_size_type(value_length)) + append_zero()); + add_size(append_with_zero(key, osmium::memory::item_size_type(key_length))); + add_size(append_with_zero(value, osmium::memory::item_size_type(value_length))); } /** @@ -134,8 +135,8 @@ namespace osmium { if (value.size() > osmium::max_osm_string_length) { throw std::length_error("OSM tag value is too long"); } - add_size(append(key.data(), osmium::memory::item_size_type(key.size()) + 1) + - append(value.data(), osmium::memory::item_size_type(value.size()) + 1)); + add_size(append(key.data(), osmium::memory::item_size_type(key.size()) + 1)); + add_size(append(value.data(), osmium::memory::item_size_type(value.size()) + 1)); } /** @@ -144,7 +145,8 @@ namespace osmium { * @param tag Tag. */ void add_tag(const osmium::Tag& tag) { - add_size(append(tag.key()) + append(tag.value())); + add_size(append(tag.key())); + add_size(append(tag.value())); } /** @@ -226,7 +228,7 @@ namespace osmium { throw std::length_error("OSM relation member role is too long"); } member.set_role_size(osmium::string_size_type(length) + 1); - add_size(append(role, osmium::memory::item_size_type(length)) + append_zero()); + add_size(append_with_zero(role, osmium::memory::item_size_type(length))); add_padding(true); } @@ -310,7 +312,7 @@ namespace osmium { throw std::length_error("OSM user name is too long"); } comment.set_user_size(osmium::string_size_type(length) + 1); - add_size(append(user, osmium::memory::item_size_type(length)) + append_zero()); + add_size(append_with_zero(user, osmium::memory::item_size_type(length))); } void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) { @@ -322,7 +324,7 @@ namespace osmium { throw std::length_error("OSM changeset comment is too long"); } comment.set_text_size(osmium::string_size_type(length) + 1); - add_size(append(text, osmium::memory::item_size_type(length)) + append_zero()); + add_size(append_with_zero(text, osmium::memory::item_size_type(length))); add_padding(true); } diff --git a/include/osmium/io/detail/opl_input_format.hpp b/include/osmium/io/detail/opl_input_format.hpp index 135f1a5e0..62598f706 100644 --- a/include/osmium/io/detail/opl_input_format.hpp +++ b/include/osmium/io/detail/opl_input_format.hpp @@ -123,6 +123,11 @@ namespace osmium { rest = input.substr(ppos); } + if (!rest.empty()) { + m_data = rest.data(); + parse_line(); + } + if (m_buffer.committed() > 0) { send_to_output_queue(std::move(m_buffer)); } diff --git a/include/osmium/io/reader.hpp b/include/osmium/io/reader.hpp index c39eaaa62..825cb41ce 100644 --- a/include/osmium/io/reader.hpp +++ b/include/osmium/io/reader.hpp @@ -92,6 +92,8 @@ namespace osmium { osmium::io::File m_file; + detail::ParserFactory::create_parser_type m_creator; + enum class status { okay = 0, // normal reading error = 1, // some error occurred while reading @@ -128,13 +130,12 @@ namespace osmium { } // This function will run in a separate thread. - static void parser_thread(const osmium::io::File& file, + static void parser_thread(const detail::ParserFactory::create_parser_type& creator, detail::future_string_queue_type& input_queue, detail::future_buffer_queue_type& osmdata_queue, std::promise&& header_promise, osmium::io::detail::reader_options options) { std::promise promise = std::move(header_promise); - const auto creator = detail::ParserFactory::instance().get_creator_function(file); const auto parser = creator(input_queue, osmdata_queue, promise, options); parser->parse(); } @@ -236,6 +237,7 @@ namespace osmium { template explicit Reader(const osmium::io::File& file, TArgs&&... args) : m_file(file.check()), + m_creator(detail::ParserFactory::instance().get_creator_function(m_file)), m_status(status::okay), m_childpid(0), m_input_queue(detail::get_input_queue_size(), "raw_input"), @@ -256,7 +258,7 @@ namespace osmium { std::promise header_promise; m_header_future = header_promise.get_future(); - m_thread = osmium::thread::thread_handler{parser_thread, std::ref(m_file), std::ref(m_input_queue), std::ref(m_osmdata_queue), std::move(header_promise), m_options}; + m_thread = osmium::thread::thread_handler{parser_thread, std::ref(m_creator), std::ref(m_input_queue), std::ref(m_osmdata_queue), std::move(header_promise), m_options}; } template diff --git a/include/osmium/memory/buffer.hpp b/include/osmium/memory/buffer.hpp index 370d01e0b..1b75b4fa5 100644 --- a/include/osmium/memory/buffer.hpp +++ b/include/osmium/memory/buffer.hpp @@ -119,6 +119,15 @@ namespace osmium { auto_grow m_auto_grow{auto_grow::no}; std::function m_full; + static size_t calculate_capacity(size_t capacity) noexcept { + // The majority of all Nodes will fit into this size. + constexpr static const size_t min_capacity = 64; + if (capacity < min_capacity) { + return min_capacity; + } + return capacity; + } + public: /** @@ -198,13 +207,13 @@ namespace osmium { * of the alignment. */ explicit Buffer(size_t capacity, auto_grow auto_grow = auto_grow::yes) : - m_memory(new unsigned char[capacity]), + m_memory(new unsigned char[calculate_capacity(capacity)]), m_data(m_memory.get()), - m_capacity(capacity), + m_capacity(calculate_capacity(capacity)), m_written(0), m_committed(0), m_auto_grow(auto_grow) { - if (capacity % align_bytes != 0) { + if (m_capacity % align_bytes != 0) { throw std::invalid_argument("buffer capacity needs to be multiple of alignment"); } } diff --git a/include/osmium/tags/filter.hpp b/include/osmium/tags/filter.hpp index 22abb1430..797565db8 100644 --- a/include/osmium/tags/filter.hpp +++ b/include/osmium/tags/filter.hpp @@ -140,7 +140,7 @@ namespace osmium { * Return the number of rules in this filter. */ size_t count() const { - return m_rules.count(); + return m_rules.size(); } /** diff --git a/include/osmium/version.hpp b/include/osmium/version.hpp index d32641a55..a36a4d900 100644 --- a/include/osmium/version.hpp +++ b/include/osmium/version.hpp @@ -35,8 +35,8 @@ DEALINGS IN THE SOFTWARE. #define LIBOSMIUM_VERSION_MAJOR 2 #define LIBOSMIUM_VERSION_MINOR 11 -#define LIBOSMIUM_VERSION_PATCH 0 +#define LIBOSMIUM_VERSION_PATCH 3 -#define LIBOSMIUM_VERSION_STRING "2.11.0" +#define LIBOSMIUM_VERSION_STRING "2.11.3" #endif // OSMIUM_VERSION_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index db0e93485..68f8887c4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -167,9 +167,10 @@ add_unit_test(io test_compression_factory) add_unit_test(io test_bzip2 ENABLE_IF ${BZIP2_FOUND} LIBS ${BZIP2_LIBRARIES}) add_unit_test(io test_file_formats) add_unit_test(io test_reader LIBS "${OSMIUM_XML_LIBRARIES};${OSMIUM_PBF_LIBRARIES}") +add_unit_test(io test_reader_fileformat ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT}) add_unit_test(io test_reader_with_mock_decompression ENABLE_IF ${Threads_FOUND} LIBS ${OSMIUM_XML_LIBRARIES}) add_unit_test(io test_reader_with_mock_parser ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT}) -add_unit_test(io test_opl_parser) +add_unit_test(io test_opl_parser ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT}) add_unit_test(io test_output_utils) add_unit_test(io test_output_iterator ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT}) add_unit_test(io test_string_table) diff --git a/test/t/io/data-nonl.opl b/test/t/io/data-nonl.opl new file mode 100644 index 000000000..db2354439 --- /dev/null +++ b/test/t/io/data-nonl.opl @@ -0,0 +1 @@ +n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02 \ No newline at end of file diff --git a/test/t/io/data.opl b/test/t/io/data.opl new file mode 100644 index 000000000..2c7e2a35f --- /dev/null +++ b/test/t/io/data.opl @@ -0,0 +1 @@ +n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02 diff --git a/test/t/io/test_opl_parser.cpp b/test/t/io/test_opl_parser.cpp index 9ad6eeb75..dad223865 100644 --- a/test/t/io/test_opl_parser.cpp +++ b/test/t/io/test_opl_parser.cpp @@ -3,8 +3,10 @@ #include #include "catch.hpp" +#include "utils.hpp" #include +#include #include namespace oid = osmium::io::detail; @@ -1073,3 +1075,23 @@ TEST_CASE("Parse line with external interface") { } +TEST_CASE("Parse OPL using Reader") { + osmium::io::File file{with_data_dir("t/io/data.opl")}; + osmium::io::Reader reader{file}; + + const auto buffer = reader.read(); + REQUIRE(buffer); + const auto& node = buffer.get(0); + REQUIRE(node.id() == 1); +} + +TEST_CASE("Parse OPL with missing newline using Reader") { + osmium::io::File file{with_data_dir("t/io/data-nonl.opl")}; + osmium::io::Reader reader{file}; + + const auto buffer = reader.read(); + REQUIRE(buffer); + const auto& node = buffer.get(0); + REQUIRE(node.id() == 1); +} + diff --git a/test/t/io/test_reader_fileformat.cpp b/test/t/io/test_reader_fileformat.cpp new file mode 100644 index 000000000..a64932e70 --- /dev/null +++ b/test/t/io/test_reader_fileformat.cpp @@ -0,0 +1,10 @@ + +#include "catch.hpp" +#include "utils.hpp" + +#include + +TEST_CASE("Reader throws on unsupported file format") { + REQUIRE_THROWS_AS(osmium::io::Reader{with_data_dir("t/io/data.osm")}, osmium::unsupported_file_format_error); +} + diff --git a/test/t/memory/test_buffer_basics.cpp b/test/t/memory/test_buffer_basics.cpp index ffe725168..d9d174b0f 100644 --- a/test/t/memory/test_buffer_basics.cpp +++ b/test/t/memory/test_buffer_basics.cpp @@ -6,8 +6,8 @@ TEST_CASE("Buffer basics") { osmium::memory::Buffer invalid_buffer1; osmium::memory::Buffer invalid_buffer2; - osmium::memory::Buffer empty_buffer1(1024); - osmium::memory::Buffer empty_buffer2(2048); + osmium::memory::Buffer empty_buffer1{1024}; + osmium::memory::Buffer empty_buffer2{2048}; REQUIRE(!invalid_buffer1); REQUIRE(!invalid_buffer2); @@ -32,3 +32,18 @@ TEST_CASE("Buffer basics") { } +TEST_CASE("Buffer with zero size") { + osmium::memory::Buffer buffer{0}; + REQUIRE(buffer.capacity() == 64); +} + +TEST_CASE("Buffer with less than minimum size") { + osmium::memory::Buffer buffer{63}; + REQUIRE(buffer.capacity() == 64); +} + +TEST_CASE("Buffer with minimum size") { + osmium::memory::Buffer buffer{64}; + REQUIRE(buffer.capacity() == 64); +} + From 9418f5613a420db7a59e3cb9c982736218cc64e0 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Tue, 18 Jul 2017 21:11:03 +0000 Subject: [PATCH 3/4] Update sol2 to v2.17.5 --- third_party/sol2/sol2/sol.hpp | 4618 ++++++++++++++++++++++++--------- 1 file changed, 3332 insertions(+), 1286 deletions(-) diff --git a/third_party/sol2/sol2/sol.hpp b/third_party/sol2/sol2/sol.hpp index ff868d73c..335c7852b 100644 --- a/third_party/sol2/sol2/sol.hpp +++ b/third_party/sol2/sol2/sol.hpp @@ -1,6 +1,6 @@ // The MIT License (MIT) -// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors +// Copyright (c) 2013-2017 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 @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2017-02-19 09:59:38.638408 UTC -// This header was generated with sol v2.15.8 (revision 0c8ec82) +// Generated 2017-07-09 23:05:15.984374 UTC +// This header was generated with sol v2.18.0 (revision 2d65f6c) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -47,11 +47,175 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wshadow" #pragma GCC diagnostic ignored "-Wconversion" +#if __GNUC__ > 6 +#pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif #elif defined _MSC_VER #pragma warning( push ) #pragma warning( disable : 4324 ) // structure was padded due to alignment specifier +#pragma warning( disable : 4503 ) // decorated name horse shit +#pragma warning( disable : 4702 ) // unreachable code #endif // g++ +// beginning of sol/forward.hpp + +// beginning of sol/feature_test.hpp + +#if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && (defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (_MSVC_LANG > 201402)) +#ifndef SOL_CXX17_FEATURES +#define SOL_CXX17_FEATURES 1 +#endif // C++17 features macro +#endif // C++17 features check + +#if defined(__cpp_noexcept_function_type) +#ifndef SOL_NOEXCEPT_FUNCTION_TYPE +#define SOL_NOEXCEPT_FUNCTION_TYPE 1 +#endif // noexcept is part of a function's type +#endif + +#if defined(_WIN32) || defined(_MSC_VER) +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // sol codecvt support +#elif defined(__GNUC__) +#if __GNUC__ >= 5 +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // codecvt support +#endif // g++ 5.x.x (MinGW too) +#else +#endif // Windows/VC++ vs. g++ vs Others + +#ifdef _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/feature_test.hpp + +namespace sol { + + class reference; + class stack_reference; + template + struct proxy; + template + class usertype; + template + class simple_usertype; + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = 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 + struct basic_environment; + using environment = basic_environment; + using stack_environment = basic_environment; + template + class basic_function; + template + class basic_protected_function; + using protected_function = basic_protected_function; + using stack_protected_function = basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; +#ifdef SOL_SAFE_FUNCTIONS + using function = protected_function; + using stack_function = stack_protected_function; +#else + using function = unsafe_function; + using stack_function = stack_unsafe_function; +#endif + 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 variadic_results; + struct this_state; + struct this_environment; + template + struct light; + template + struct user; + template + struct as_args_t; + +} // sol + +// end of sol/forward.hpp + // beginning of sol/state.hpp // beginning of sol/state_view.hpp @@ -190,12 +354,13 @@ namespace sol { template using void_tuple_element_t = typename void_tuple_element::type; - template + template struct basic_traits { private: typedef std::conditional_t::value, int, T>& first_type; public: + static const bool is_noexcept = it_is_noexcept; 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); @@ -215,123 +380,238 @@ namespace sol { }; template::value> - struct fx_traits : basic_traits {}; + struct fx_traits : basic_traits {}; // Free Functions template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args..., ...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args..., ...); }; // Member Functions /* C-Style Variadics */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...); }; /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile; }; /* Member Function Qualifiers */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) && ; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) && ; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) noexcept; + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile & noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile && noexcept; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile && noexcept; + }; + +#endif // noexcept is part of a function's type + template struct fx_traits : fx_traits::function_type, false> {}; @@ -345,6 +625,7 @@ namespace sol { typedef R Arg; typedef T object_type; using signature_type = R(T::*); + static const bool is_noexcept = false; static const bool is_member_function = false; static const std::size_t arity = 1; static const std::size_t free_arity = 2; @@ -359,6 +640,7 @@ namespace sol { template using arg_at = void_tuple_element_t; }; + } // meta_detail template @@ -381,6 +663,10 @@ namespace sol { #include #include #include +#include +#ifdef SOL_CXX17_FEATURES +#include +#endif namespace sol { template @@ -629,6 +915,42 @@ namespace sol { static std::false_type test(...); }; + struct has_key_type_impl { + template, + typename V = typename U::key_type> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_mapped_type_impl { + template, + typename V = typename U::mapped_type> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_value_type_impl { + template, + typename V = typename U::value_type> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_iterator_impl { + template, + typename V = typename U::iterator> + 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, @@ -668,8 +990,37 @@ namespace sol { template struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; + template + struct has_key_type : decltype(meta_detail::has_key_type_impl::test(0)) {}; + + template + struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test(0)) {}; + + template + struct has_iterator : decltype(meta_detail::has_iterator_impl::test(0)) {}; + + template + struct has_value_type : decltype(meta_detail::has_value_type_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>>; + struct is_associative : meta::all, has_mapped_type> {}; + + template + using is_string_constructible = any< + std::is_same, const char*> + , std::is_same, char> + , std::is_same, std::string> + , std::is_same, std::initializer_list> +#ifdef SOL_CXX17_FEATURES + , std::is_same, std::string_view> +#endif + >; + + template + struct is_pair : std::false_type {}; + + template + struct is_pair> : std::true_type {}; template using is_c_str = any< @@ -704,7 +1055,19 @@ namespace sol { decltype(auto) tuplefy(X&&... x) { return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); } + + template + struct iterator_tag { + using type = std::input_iterator_tag; + }; + + template + struct iterator_tag> { + using type = typename T::iterator_category; + }; + } // meta + namespace detail { template decltype(auto) forward_get(Tuple&& tuple) { @@ -781,7 +1144,9 @@ namespace sol { // end of sol/traits.hpp -// beginning of sol/object.hpp +// beginning of sol/function.hpp + +// beginning of sol/unsafe_function.hpp // beginning of sol/reference.hpp @@ -797,22 +1162,12 @@ namespace sol { #include #include #include +#ifdef SOL_USING_CXX_LUAJIT +#include +#endif // C++ LuaJIT ... whatever that means #else #include -#endif // C++-compiler Lua - -#if defined(_WIN32) || defined(_MSC_VER) -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // sol codecvt support -#elif defined(__GNUC__) -#if __GNUC__ >= 5 -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // codecvt support -#endif // g++ 5.x.x (MinGW too) -#else -#endif // Windows/VC++ vs. g++ vs Others +#endif // C++ Mangling for Lua #ifdef LUAJIT_VERSION #ifndef SOL_LUAJIT @@ -831,68 +1186,38 @@ namespace sol { #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 +#if defined(__cplusplus) && !defined(SOL_USING_CXX_LUA) extern "C" { #endif +// beginning of sol/compatibility/5.2.0.h + +#ifndef SOL_5_2_0_H +#define SOL_5_2_0_H + +#if SOL_LUA_VERSION < 503 + +inline int lua_isinteger(lua_State* L, int idx) { + if (lua_type(L, idx) != LUA_TNUMBER) + return 0; + // This is a very slipshod way to do the testing + // but lua_totingerx doesn't play ball nicely + // on older versions... + lua_Number n = lua_tonumber(L, idx); + lua_Integer i = lua_tointeger(L, idx); + if (i != n) + return 0; + // it's DEFINITELY an integer + return 1; +} + +#endif // SOL_LUA_VERSION == 502 +#endif // SOL_5_2_0_H +// end of sol/compatibility/5.2.0.h + // beginning of sol/compatibility/5.1.0.h #ifndef SOL_5_1_0_H @@ -921,7 +1246,7 @@ extern "C" { /* LuaJIT does not have the updated error codes for thread status/function returns */ #ifndef LUA_ERRGCMM -#define LUA_ERRGCMM (LUA_ERRERR + 1) +#define LUA_ERRGCMM (LUA_ERRERR + 2) #endif // LUA_ERRGCMM /* LuaJIT does not support continuation contexts / return error codes? */ @@ -1086,21 +1411,25 @@ inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const c #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); +#if !defined(SOL_LUAJIT_VERSION) || SOL_LUAJIT_VERSION < 20100 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_Integer lua_tointegerx(lua_State *L, int i, int *isnum); 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); +const lua_Number *lua_version(lua_State *L); void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); void luaL_setmetatable(lua_State *L, const char *tname); +void *luaL_testudata(lua_State *L, int i, const char *tname); +#define luaL_newlib(L, l) \ + (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) +#endif // LuaJIT-2.1.0-beta3 added these compatibility functions + +int lua_absindex(lua_State *L, int i); +void lua_rawgetp(lua_State *L, int i, const void *p); +void lua_rawsetp(lua_State *L, int i, const void *p); +void lua_getuservalue(lua_State *L, int i); +void lua_setuservalue(lua_State *L, int i); 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); @@ -1115,32 +1444,7 @@ int luaL_fileresult(lua_State *L, int stat, const char *fname); #ifndef SOL_5_X_X_INL #define SOL_5_X_X_INL -// beginning of sol/compatibility/5.2.0.h - -#ifndef SOL_5_2_0_H -#define SOL_5_2_0_H - -#if SOL_LUA_VERSION < 503 - -inline int lua_isinteger(lua_State* L, int idx) { - if (lua_type(L, idx) != LUA_TNUMBER) - return 0; - // This is a very slipshod way to do the testing - // but lua_totingerx doesn't play ball nicely - // on older versions... - lua_Number n = lua_tonumber(L, idx); - lua_Integer i = lua_tointeger(L, idx); - if (i != n) - return 0; - // it's DEFINITELY an integer - return 1; -} - -#endif // SOL_LUA_VERSION == 502 -#endif // SOL_5_2_0_H -// end of sol/compatibility/5.2.0.h - -#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 +#if SOL_LUA_VERSION < 502 #include @@ -1152,6 +1456,7 @@ inline int lua_absindex(lua_State *L, int i) { return i; } +#if !defined(SOL_LUAJIT_VERSION) || SOL_LUAJIT_VERSION < 20100 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"); @@ -1159,6 +1464,69 @@ inline void lua_copy(lua_State *L, int from, int to) { lua_replace(L, abs_to); } +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 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 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; +} + +/* +** 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 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; +} +#endif + inline void lua_rawgetp(lua_State *L, int i, const void *p) { int abs_i = lua_absindex(L, i); lua_pushlightuserdata(L, (void*)p); @@ -1173,30 +1541,6 @@ inline void lua_rawsetp(lua_State *L, int i, const void *p) { 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); @@ -1246,28 +1590,6 @@ inline void lua_setuservalue(lua_State *L, int i) { 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"); @@ -1383,14 +1705,6 @@ inline void luaL_traceback(lua_State *L, lua_State *L1, } #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)) @@ -1420,7 +1734,7 @@ inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { } else { char buf[1024]; -#if defined(__GLIBC__) || defined(_POSIX_VERSION) +#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) strerror_r(en, buf, 1024); #else strerror_s(buf, 1024, en); @@ -1663,14 +1977,6 @@ 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 */ @@ -1812,7 +2118,7 @@ inline void luaL_pushresult(luaL_Buffer_52 *B) { #endif // SOL_5_X_X_INL // end of sol/compatibility/5.x.x.inl -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(SOL_USING_CXX_LUA) } #endif @@ -1822,28 +2128,51 @@ inline void luaL_pushresult(luaL_Buffer_52 *B) { // beginning of sol/in_place.hpp +#include + namespace sol { +#ifdef SOL_CXX17_FEATURES + using in_place_t = std::in_place_t; + constexpr std::in_place_t in_place{}; + constexpr std::in_place_t in_place_of{}; + + template using in_place_type_t = std::in_place_type_t; + template + constexpr std::in_place_type_t in_place_type{}; + + template using in_place_index_t = std::in_place_index_t; + template + constexpr in_place_index_t in_place_index{}; +#else namespace detail { - struct in_place_of {}; + struct in_place_of_tag {}; 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()); } + struct in_place_tag { constexpr in_place_tag() = default; }; + + constexpr inline in_place_tag in_place (detail::in_place_of_tag) { return in_place_tag(); } template - constexpr inline in_place_tag in_place(detail::in_place_of_t) { return in_place_tag(in_place_tag::init()); } + constexpr inline in_place_tag in_place (detail::in_place_of_t) { return in_place_tag(); } template - constexpr inline in_place_tag in_place(detail::in_place_of_i) { return in_place_tag(in_place_tag::init()); } + constexpr inline in_place_tag in_place (detail::in_place_of_i) { return in_place_tag(); } - using in_place_t = in_place_tag(&)(detail::in_place_of); + constexpr inline in_place_tag in_place_of(detail::in_place_of_tag) { return in_place_tag(); } + template + constexpr inline in_place_tag in_place_type (detail::in_place_of_t) { return in_place_tag(); } + template + constexpr inline in_place_tag in_place_index (detail::in_place_of_i) { return in_place_tag(); } + + using in_place_t = in_place_tag(&)(detail::in_place_of_tag); 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); +#endif } // sol @@ -2576,15 +2905,12 @@ namespace sol { } constexpr T& value() const { - return ref ? - *ref #ifdef SOL_NO_EXCEPTIONS - // we can't abort here - // because there's no constexpr abort - : *(T*)nullptr; + return *ref; #else - : throw bad_optional_access("bad optional access"); -#endif + return ref ? *ref + : (throw bad_optional_access("bad optional access"), *ref); +#endif // Exceptions } explicit constexpr operator bool() const noexcept { @@ -2941,14 +3267,26 @@ namespace sol { const nullopt_t nullopt = boost::none; #endif // Boost vs. Better optional + namespace meta { + template + struct is_optional : std::false_type {}; + template + struct is_optional> : std::true_type {}; + } // meta } // sol // end of sol/optional.hpp // beginning of sol/string_shim.hpp +#ifdef SOL_CXX17_FEATURES +#endif // C++17 features + namespace sol { namespace string_detail { +#ifdef SOL_CXX17_FEATURES + typedef std::string_view string_shim; +#else struct string_shim { std::size_t s; const char* p; @@ -3004,27 +3342,42 @@ namespace sol { return !(*this == r); } }; +#endif // C++17 } } // end of sol/string_shim.hpp #include +#ifdef SOL_CXX17_FEATURES +#include +#endif // C++17 namespace sol { namespace detail { +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + typedef int(*lua_CFunction_noexcept) (lua_State *L) noexcept; +#endif // noexcept function type for lua_CFunction + #ifdef SOL_NO_EXCEPTIONS template - int static_trampoline(lua_State* L) { + int static_trampoline(lua_State* L) noexcept { return f(L); } +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + template + int static_trampoline_noexcept(lua_State* L) noexcept { + return f(L); + } +#endif + template - int trampoline(lua_State* L, Fx&& f, Args&&... args) { + int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept { return f(L, std::forward(args)...); } - inline int c_trampoline(lua_State* L, lua_CFunction f) { + inline int c_trampoline(lua_State* L, lua_CFunction f) noexcept { return trampoline(L, f); } #else @@ -3047,8 +3400,29 @@ namespace sol { return lua_error(L); } +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE +#if 0 + template + int static_trampoline(lua_State* L) noexcept { +#else + template + int static_trampoline_noexcept(lua_State* L) noexcept { +#endif // impossible + return f(L); + } + +#else + template + int static_trampoline_noexcept(lua_State* L) noexcept { + return f(L); + } +#endif // noexcept lua_CFunction type + template int trampoline(lua_State* L, Fx&& f, Args&&... args) { + if (meta::bind_traits>::is_noexcept) { + return f(L, std::forward(args)...); + } try { return f(L, std::forward(args)...); } @@ -3071,6 +3445,21 @@ namespace sol { } #endif // Exceptions vs. No Exceptions + template + inline int typed_static_trampoline_raw(std::true_type, lua_State* L) { + return static_trampoline_noexcept(L); + } + + template + inline int typed_static_trampoline_raw(std::false_type, lua_State* L) { + return static_trampoline(L); + } + + template + inline int typed_static_trampoline(lua_State* L) { + return typed_static_trampoline_raw(std::integral_constant::is_noexcept>(), L); + } + template struct unique_usertype {}; @@ -3086,6 +3475,9 @@ namespace sol { return std::addressof(item); } }; + + struct unchecked_t {}; + const unchecked_t unchecked = unchecked_t{}; } // detail struct lua_nil_t {}; @@ -3097,8 +3489,11 @@ namespace sol { const nil_t nil{}; #endif - struct metatable_key_t {}; - const metatable_key_t metatable_key = {}; + struct metatable_t {}; + const metatable_t metatable_key = {}; + + struct env_t {}; + const env_t env_key = {}; struct no_metatable_t {}; const no_metatable_t no_metatable = {}; @@ -3160,26 +3555,46 @@ namespace sol { struct upvalue_index { int index; - upvalue_index(int idx) : index(lua_upvalueindex(idx)) {} - operator int() const { return 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; } + 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; } + absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) { + + } + + operator int() const { + return index; + } }; struct ref_index { int index; - ref_index(int idx) : index(idx) {} - operator int() const { return index; } + ref_index(int idx) : index(idx) { + + } + + operator int() const { + return index; + } }; struct lightuserdata_value { @@ -3289,11 +3704,28 @@ namespace sol { } }; + template + struct nested { + T source; + + template + nested(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)); } + template + nested as_nested(T&& container) { + return as_nested(std::forward(container)); + } + struct this_state { lua_State* L; operator lua_State* () const { @@ -3304,6 +3736,19 @@ namespace sol { } }; + struct new_table { + int sequence_hint = 0; + int map_hint = 0; + + new_table() = default; + new_table(const new_table&) = default; + new_table(new_table&&) = default; + new_table& operator=(const new_table&) = default; + new_table& operator=(new_table&&) = default; + + new_table(int sequence_hint, int map_hint = 0) : sequence_hint(sequence_hint), map_hint(map_hint) {} + }; + enum class call_syntax { dot = 0, colon = 1 @@ -3315,7 +3760,9 @@ namespace sol { runtime = LUA_ERRRUN, memory = LUA_ERRMEM, handler = LUA_ERRERR, - gc = LUA_ERRGCMM + gc = LUA_ERRGCMM, + syntax = LUA_ERRSYNTAX, + file = LUA_ERRFILE, }; enum class thread_status : int { @@ -3354,6 +3801,61 @@ namespace sol { table | boolean | function | userdata | lightuserdata }; + inline const std::string& to_string(call_status c) { + static const std::array names{{ + "ok", + "yielded", + "runtime", + "memory", + "handler", + "gc", + "syntax", + "file", + }}; + switch (c) { + case call_status::ok: + return names[0]; + case call_status::yielded: + return names[1]; + case call_status::runtime: + return names[2]; + case call_status::memory: + return names[3]; + case call_status::handler: + return names[4]; + case call_status::gc: + return names[5]; + case call_status::syntax: + return names[6]; + case call_status::file: + return names[7]; + } + return names[0]; + } + + inline const std::string& to_string(load_status c) { + static const std::array names{ { + "ok", + "memory", + "gc", + "syntax", + "file", + } }; + switch (c) { + case load_status::ok: + return names[0]; + case load_status::memory: + return names[1]; + case load_status::gc: + return names[2]; + case load_status::syntax: + return names[3]; + case load_status::file: + return names[4]; + } + return names[0]; + } + enum class meta_function { construct, index, @@ -3390,54 +3892,52 @@ namespace sol { typedef meta_function meta_method; - const std::array meta_variable_names = { { - "__index", - "__newindex", - } }; + inline const std::array& meta_function_names() { + static const std::array names = { { + "new", + "__index", + "__newindex", + "__mode", + "__call", + "__mt", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", - const std::array meta_function_names = { { - "new", - "__index", - "__newindex", - "__mode", - "__call", - "__mt", - "__tostring", - "__len", - "__unm", - "__add", - "__sub", - "__mul", - "__div", - "__mod", - "__pow", - "__concat", - "__eq", - "__lt", - "__le", - "__gc", - - "__idiv", - "__shl", - "__shr", - "__bnot", - "__band", - "__bor", - "__bxor", + "__idiv", + "__shl", + "__shr", + "__bnot", + "__band", + "__bor", + "__bxor", - "__pairs", - "__next" - } }; + "__pairs", + "__next" + } }; + return names; + } - inline const std::string& name_of(meta_function mf) { - return meta_function_names[static_cast(mf)]; + inline const std::string& to_string(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) { + inline int type_panic(lua_State* L, int index, type expected, type actual) noexcept(false) { 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)) @@ -3449,15 +3949,15 @@ namespace sol { return 0; } - inline void type_error(lua_State* L, int expected, int actual) { + inline void type_error(lua_State* L, int expected, int actual) noexcept(false) { luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); } - inline void type_error(lua_State* L, type expected, type actual) { + inline void type_error(lua_State* L, type expected, type actual) noexcept(false) { type_error(L, static_cast(expected), static_cast(actual)); } - inline void type_assert(lua_State* L, int index, type expected, type actual) { + inline void type_assert(lua_State* L, int index, type expected, type actual) noexcept(false) { if (expected != type::poly && expected != actual) { type_panic(L, index, expected, actual); } @@ -3472,52 +3972,6 @@ namespace sol { 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; - using unsafe_function = basic_function; - using safe_function = basic_protected_function; - using stack_unsafe_function = basic_function; - using stack_safe_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 {}; @@ -3567,9 +4021,6 @@ namespace sol { template <> struct lua_type_of : std::integral_constant {}; - template <> - struct lua_type_of : std::integral_constant {}; - template <> struct lua_type_of : std::integral_constant {}; @@ -3588,6 +4039,21 @@ namespace sol { 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 {}; @@ -3654,6 +4120,9 @@ namespace sol { template <> struct lua_type_of : std::integral_constant {}; + template <> + struct lua_type_of : std::integral_constant {}; + template <> struct lua_type_of : std::integral_constant {}; @@ -3666,14 +4135,61 @@ namespace sol { template struct lua_type_of::value>> : std::integral_constant {}; + template <> + struct lua_type_of : std::integral_constant {}; + +#ifdef SOL_CXX17_FEATURES + 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 {}; +#else + template <> + struct lua_type_of : std::integral_constant {}; +#endif // C++ 17 (or not) features + template struct is_container : std::false_type {}; - template - struct is_container>::value>> : std::true_type {}; + template <> + struct is_container : std::false_type {}; template <> - struct lua_type_of : std::integral_constant {}; + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + +#ifdef SOL_CXX17_FEATURES + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + +#endif // C++ 17 + + template + struct is_container>::value>> : std::true_type {}; template class V, typename... Args> struct accumulate : std::integral_constant {}; @@ -3686,10 +4202,14 @@ namespace sol { struct is_unique_usertype : std::integral_constant::value> {}; template - struct lua_type_of : detail::lua_type_of {}; + struct lua_type_of : detail::lua_type_of { + typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; + }; template - struct lua_size : std::integral_constant { }; + struct lua_size : std::integral_constant { + typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; + }; template struct lua_size> : std::integral_constant::value + lua_size::value> { }; @@ -3697,10 +4217,24 @@ namespace sol { template struct lua_size> : std::integral_constant::value> { }; + namespace detail { + template + struct void_ { typedef void type; }; + template + struct has_internal_marker_impl : std::false_type {}; + template + struct has_internal_marker_impl::type> : std::true_type {}; + + template + struct has_internal_marker : has_internal_marker_impl {}; + } + template struct is_lua_primitive : std::integral_constant>::value - || (lua_size::value > 1) + || ((type::userdata == lua_type_of>::value) + && detail::has_internal_marker>>::value + && !detail::has_internal_marker>>::value) || std::is_base_of>::value || std::is_base_of>::value || meta::is_specialization_of>::value @@ -3740,6 +4274,9 @@ namespace sol { template <> struct is_transparent_argument : std::true_type {}; + template <> + struct is_transparent_argument : std::true_type {}; + template <> struct is_transparent_argument : std::true_type {}; @@ -3780,6 +4317,9 @@ namespace sol { template struct is_userdata> : std::true_type {}; + template + struct is_environment : std::integral_constant::value || is_table::value> {}; + template struct is_container : detail::is_container{}; @@ -3787,6 +4327,14 @@ namespace sol { inline type type_of() { return lua_type_of>::value; } + + namespace detail { + template + struct lua_type_of, std::enable_if_t<::sol::is_container::value>> : std::integral_constant {}; + + template + struct lua_type_of, std::enable_if_t::value>> : lua_type_of {}; + } // detail } // sol // end of sol/types.hpp @@ -3862,12 +4410,59 @@ namespace sol { inline bool operator!= (const stack_reference& l, const stack_reference& r) { return !operator==(l, r); } + + inline bool operator==(const stack_reference& lhs, const lua_nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const lua_nil_t&, const stack_reference& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const stack_reference& lhs, const lua_nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const lua_nil_t&, const stack_reference& rhs) { + return rhs.valid(); + } } // sol // end of sol/stack_reference.hpp namespace sol { namespace stack { + inline void remove(lua_State* L, int rawindex, int count) { + if (count < 1) + return; + int top = lua_gettop(L); + if (rawindex == -count || top == rawindex) { + // 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 + int index = lua_absindex(L, rawindex); + if (index < 0) { + index = lua_gettop(L) + (index + 1); + } + int last = index + count; + for (int i = index; i < last; ++i) { + lua_remove(L, index); + } + } + + struct push_popper_at { + lua_State* L; + int index; + int count; + push_popper_at(lua_State* luastate, int index = -1, int count = 1) : L(luastate), index(index), count(count) { } + ~push_popper_at() { remove(L, index, count); } + }; + template struct push_popper_n { lua_State* L; @@ -3894,6 +4489,12 @@ namespace sol { push_popper push_pop(T&& x) { return push_popper(std::forward(x)); } + template + push_popper_at push_pop_at(T&& x) { + int c = x.push(); + lua_State* L = x.lua_state(); + return push_popper_at(L, lua_absindex(L, -c), c); + } template push_popper_n pop_n(lua_State* L, int x) { return push_popper_n(L, x); @@ -3902,6 +4503,7 @@ namespace sol { namespace detail { struct global_tag { } const global_{}; + struct no_safety_tag {} const no_safety{}; } // detail class reference { @@ -4030,6 +4632,22 @@ namespace sol { inline bool operator!= (const reference& l, const reference& r) { return !operator==(l, r); } + + inline bool operator==(const reference& lhs, const lua_nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const lua_nil_t&, const reference& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const reference& lhs, const lua_nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const lua_nil_t&, const reference& rhs) { + return rhs.valid(); + } } // sol // end of sol/reference.hpp @@ -4038,81 +4656,6 @@ namespace sol { // 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()) {} - template >>, meta::neg>> = meta::enabler> - basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} - basic_userdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::userdata); -#endif // Safety - } - basic_userdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::userdata); -#endif // Safety - } - }; - - template - 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()) {} - template >>, meta::neg>> = meta::enabler> - basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} - basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - type_assert(L, index, type::lightuserdata); -#endif // Safety - } - basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - type_assert(L, -1, type::lightuserdata); -#endif // Safety - } - }; - -} // sol - -// end of sol/userdata.hpp - // beginning of sol/tie.hpp namespace sol { @@ -4239,25 +4782,26 @@ namespace sol { 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(); - } + using unique_destructor = void(*)(void*); 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)); + unique_destructor& dx = *static_cast(static_cast(pointerpointer + 1)); (dx)(memory); return 0; } + template + inline void usertype_unique_alloc_destroy(void* memory) { + T** pointerpointer = static_cast(memory); + unique_destructor* dx = static_cast(static_cast(pointerpointer + 1)); + Real* target = static_cast(static_cast(dx + 1)); + std::allocator alloc; + alloc.destroy(target); + } + template inline int user_alloc_destroy(lua_State* L) { void* rawdata = lua_touserdata(L, 1); @@ -4349,6 +4893,7 @@ namespace sol { }; template using strip_t = typename strip::type; + const bool default_check_arguments = #ifdef SOL_CHECK_ARGUMENTS true; @@ -4359,6 +4904,17 @@ namespace sol { inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { return getter>{}.get(L, index, tracking); } + + template + inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) { + typedef meta::all< + std::is_lvalue_reference, + meta::neg>, + meta::neg>>, + meta::neg>> + > use_reference_tag; + return pusher>>{}.push(L, std::forward(arg), std::forward(args)...); + } } // stack_detail inline bool maybe_indexable(lua_State* L, int index = -1) { @@ -4379,13 +4935,12 @@ namespace sol { 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)...); + return stack_detail::push_reference(L, std::forward(t), std::forward(args)...); + } + + template + inline int push_reference(lua_State* L, Arg&& arg, Args&&... args) { + return stack_detail::push_reference(L, std::forward(arg), std::forward(args)...); } inline int multi_push(lua_State*) { @@ -4614,6 +5169,7 @@ namespace sol { // beginning of sol/demangle.hpp #include +#include namespace sol { namespace detail { @@ -4875,7 +5431,8 @@ namespace sol { // end of sol/inheritance.hpp -#include +#ifdef SOL_CXX17_FEATURES +#endif // C++17 namespace sol { namespace stack { @@ -4984,6 +5541,15 @@ namespace sol { } }; + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + template struct checker { template @@ -5046,6 +5612,14 @@ namespace sol { } }; + template + struct checker, type::userdata, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::check(L, index, std::forward(handler), tracking); + } + }; + template struct checker, type::userdata, C> : checker, type::lightuserdata, C> {}; @@ -5074,7 +5648,7 @@ namespace sol { return false; } // Do advanced check for call-style userdata? - static const auto& callkey = name_of(meta_function::call); + static const auto& callkey = to_string(meta_function::call); if (lua_getmetatable(L, index) == 0) { // No metatable, no __call key possible handler(L, index, type::function, t); @@ -5107,7 +5681,73 @@ namespace sol { return true; } if (t != type::userdata) { - handler(L, index, type::function, t); + handler(L, index, type::table, t); + return false; + } + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (lua_getmetatable(L, index) == 0) { + return true; + } + type t = type_of(L, -1); + if (t == type::table || t == type::none || t == type::nil) { + lua_pop(L, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L, 1); + handler(L, index, expected, t); + return false; + } + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (lua_getmetatable(L, index) == 0) { + return true; + } + type t = type_of(L, -1); + if (t == type::table || t == type::none || t == type::nil) { + lua_pop(L, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L, 1); + handler(L, index, type::table, t); + return false; + } + return true; + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (lua_getmetatable(L, index) == 0) { + return true; + } + type t = type_of(L, -1); + if (t == type::table || t == type::none || t == type::nil) { + lua_pop(L, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L, 1); + handler(L, index, type::table, t); return false; } return true; @@ -5179,11 +5819,34 @@ namespace sol { } }; - template - struct checker::value>> { + template + struct checker::value>> { + typedef typename unique_usertype_traits::type T; 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); + const type indextype = type_of(L, index); + tracking.use(1); + if (indextype != type::userdata) { + handler(L, index, type::userdata, indextype); + return false; + } + if (lua_getmetatable(L, index) == 0) { + return true; + } + int metatableindex = lua_gettop(L); + if (stack_detail::check_metatable>(L, metatableindex)) { + void* memory = lua_touserdata(L, index); + T** pointerpointer = static_cast(memory); + detail::unique_destructor& pdx = *static_cast(static_cast(pointerpointer + 1)); + bool success = &detail::usertype_unique_alloc_destroy == pdx; + if (!success) { + handler(L, index, type::userdata, indextype); + } + return success; + } + lua_pop(L, 1); + handler(L, index, type::userdata, indextype); + return false; } }; @@ -5227,6 +5890,40 @@ namespace sol { return stack::check(L, index, no_panic, tracking); } }; + +#ifdef SOL_CXX17_FEATURES + template + struct checker, type::poly, C> { + typedef std::variant V; + typedef std::variant_size V_size; + typedef std::integral_constant V_is_empty; + + template + static bool is_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { + if (V_is_empty::value && lua_isnone(L, index)) { + return true; + } + tracking.use(1); + handler(L, index, type::poly, type_of(L, index)); + return false; + } + + template + static bool is_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { + typedef std::variant_alternative_t T; + if (stack::check(L, index, no_panic, tracking)) { + return true; + } + return is_one(std::integral_constant(), L, index, std::forward(handler), tracking); + } + + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return is_one(std::integral_constant(), L, index, std::forward(handler), tracking); + } + }; +#endif // C++17 + } // stack } // sol @@ -5258,8 +5955,9 @@ namespace sol { #ifdef SOL_CODECVT_SUPPORT #include -#include -#endif +#endif // codecvt header support +#ifdef SOL_CXX17_FEATURES +#endif // C++17 namespace sol { namespace stack { @@ -5305,53 +6003,55 @@ namespace sol { template struct getter, std::enable_if_t>::value>> { - static T get(lua_State* L, int index, record& tracking) { + static T get(lua_State* L, int relindex, record& tracking) { typedef typename T::value_type V; + return get(types(), L, relindex, tracking); + } + + template + static T get(types, lua_State* L, int relindex, record& tracking) { tracking.use(1); - index = lua_absindex(L, index); + int index = lua_absindex(L, relindex); 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)) { + bool isnil = false; for (int vi = 0; vi < lua_size::value; ++vi) { type t = static_cast(lua_geti(L, index, i + vi)); - if (t == type::lua_nil) { + isnil = t == type::lua_nil; + if (isnil) { if (i == 0) { - continue; - } - else { - lua_pop(L, (vi + 1)); - return arr; + break; } + lua_pop(L, (vi + 1)); + return arr; } } + if (isnil) + continue; 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)) { + bool isnil = false; 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::lua_nil) { + isnil = t == type::lua_nil; + if (isnil) { if (i == 0) { - continue; - } - else { - lua_pop(L, (vi + 1)); - return arr; + break; } + lua_pop(L, (vi + 1)); + return arr; } } + if (isnil) + continue; arr.push_back(stack::get(L, -1)); } #endif @@ -5365,10 +6065,15 @@ namespace sol { typedef typename T::value_type P; typedef typename P::first_type K; typedef typename P::second_type V; + return get(types(), L, index, tracking); + } + + template + static T get(types, lua_State* L, int relindex, record& tracking) { tracking.use(1); T associative; - index = lua_absindex(L, index); + int index = lua_absindex(L, relindex); lua_pushnil(L); while (lua_next(L, index) != 0) { decltype(auto) key = stack::check_get(L, -2); @@ -5383,6 +6088,40 @@ namespace sol { } }; + template + struct getter, std::enable_if_t::value>> { + static T get(lua_State* L, int index, record& tracking) { + getter g; + // VC++ has a bad warning here: shut it up + (void)g; + return g.get(L, index, tracking); + } + }; + + template + struct getter, std::enable_if_t, meta::neg>>>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type V; + getter> g; + // VC++ has a bad warning here: shut it up + (void)g; + return g.get(types>(), L, index, tracking); + } + }; + + template + struct getter, std::enable_if_t, meta::has_key_value_pair>>::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; + getter> g; + // VC++ has a bad warning here: shut it up + (void)g; + return g.get(types>(), L, index, tracking); + } + }; + template struct getter::value || std::is_base_of::value>> { static T get(lua_State* L, int index, record& tracking) { @@ -5453,17 +6192,7 @@ namespace sol { 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); + return std::string(str, len); } }; @@ -5471,10 +6200,11 @@ namespace sol { struct getter { static const char* get(lua_State* L, int index, record& tracking) { tracking.use(1); - return lua_tostring(L, index); + size_t sz; + return lua_tolstring(L, index, &sz); } }; - + template<> struct getter { static char get(lua_State* L, int index, record& tracking) { @@ -5497,12 +6227,12 @@ namespace sol { if (sizeof(wchar_t) == 2) { static std::wstring_convert> convert; std::wstring r = convert.from_bytes(str, str + len); -#ifdef __MINGW32__ +#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ < 7 // 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); + uint8_t* b = reinterpret_cast(&c); std::swap(b[0], b[1]); } #endif @@ -5586,8 +6316,9 @@ namespace sol { 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) + const auto& mfnames = meta_function_names(); + for (std::size_t i = 0; i < mfnames.size(); ++i) + if (mfnames[i] == name) return static_cast(i); return meta_function::construct; } @@ -5682,7 +6413,7 @@ namespace sol { T* obj = static_cast(udata); return obj; } - + static T& get(lua_State* L, int index, record& tracking) { return *get_no_lua_nil(L, index, tracking); } @@ -5696,35 +6427,50 @@ namespace sol { tracking.use(1); return nullptr; } - return getter>::get_no_lua_nil(L, index, tracking); + getter> g; + // Avoid VC++ warning + (void)g; + return g.get_no_lua_nil(L, index, tracking); } }; template struct getter> { static T* get(lua_State* L, int index, record& tracking) { - return getter>::get_no_lua_nil(L, index, tracking); + getter> g; + // Avoid VC++ warning + (void)g; + return g.get_no_lua_nil(L, index, tracking); } }; template struct getter { static T& get(lua_State* L, int index, record& tracking) { - return getter>::get(L, index, tracking); + getter> g; + // Avoid VC++ warning + (void)g; + return g.get(L, index, tracking); } }; template struct getter> { static T& get(lua_State* L, int index, record& tracking) { - return getter{}.get(L, index, tracking); + getter g; + // Avoid VC++ warning + (void)g; + return g.get(L, index, tracking); } }; template struct getter { static T* get(lua_State* L, int index, record& tracking) { - return getter>::get(L, index, tracking); + getter> g; + // Avoid VC++ warning + (void)g; + return g.get(L, index, tracking); } }; @@ -5736,31 +6482,31 @@ namespace sol { 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)); + detail::unique_destructor* fx = static_cast(static_cast(pref + 1)); Real* mem = static_cast(static_cast(fx + 1)); return *mem; } }; - template - struct getter> { - typedef std::tuple(nullptr, 0))...> R; - - template - static R apply(std::index_sequence<>, lua_State*, int, record&, TArgs&&... args) { + template + struct getter> { + typedef std::tuple(nullptr, 0))...> R; + + template + static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) { // Fuck you too, VC++ - return R{std::forward(args)...}; + return R{ std::forward(args)... }; } - - template - static R apply(std::index_sequence, lua_State* L, int index, record& tracking, TArgs&&... args) { + + template + static R apply(std::index_sequence, lua_State* L, int index, record& tracking, Args&&... 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)); + 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); + return apply(std::make_index_sequence(), L, index, tracking); } }; @@ -5771,6 +6517,64 @@ namespace sol { } }; +#ifdef SOL_CXX17_FEATURES + template<> + struct getter { + static std::string_view get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz; + const char* str = lua_tolstring(L, index, &sz); + return std::string_view(str, sz); + } + }; + + template + struct getter> { + typedef std::variant V; + typedef std::variant_size V_size; + typedef std::integral_constant V_is_empty; + + static V get_empty(std::true_type, lua_State* L, int index, record& tracking) { + return V(); + } + + static V get_empty(std::false_type, lua_State* L, int index, record& tracking) { + typedef std::variant_alternative_t<0, V> T; + // This should never be reached... + // please check your code and understand what you did to bring yourself here + std::abort(); + return V(std::in_place_index<0>, stack::get(L, index)); + } + + static V get_one(std::integral_constant, lua_State* L, int index, record& tracking) { + return get_empty(V_is_empty(), L, index, tracking); + } + + template + static V get_one(std::integral_constant, lua_State* L, int index, record& tracking) { + typedef std::variant_alternative_t T; + if (stack::check(L, index, no_panic, tracking)) { + return V(std::in_place_index, stack::get(L, index)); + } + return get_one(std::integral_constant(), L, index, tracking); + } + + static V get(lua_State* L, int index, record& tracking) { + return get_one(std::integral_constant(), L, index, tracking); + } + }; +#else + 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); + } + }; +#endif // C++17-wave + } // stack } // sol @@ -5859,6 +6663,48 @@ namespace sol { return check_get(L, index, no_panic, tracking); } }; + +#ifdef SOL_CXX17_FEATURES + template + struct check_getter> { + typedef std::variant V; + typedef std::variant_size V_size; + typedef std::integral_constant V_is_empty; + + template + static optional get_empty(std::true_type, lua_State* L, int index, Handler&& handler, record& tracking) { + return nullopt; + } + + template + static optional get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record& tracking) { + typedef std::variant_alternative_t<0, V> T; + // This should never be reached... + // please check your code and understand what you did to bring yourself here + handler(L, index, type::poly, type_of(L, index)); + return nullopt; + } + + template + static optional get_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { + return get_empty(V_is_empty(), L, index, std::forward(handler), tracking); + } + + template + static optional get_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { + typedef std::variant_alternative_t T; + if (stack::check(L, index, no_panic, tracking)) { + return V(std::in_place_index, stack::get(L, index)); + } + return get_one(std::integral_constant(), L, index, std::forward(handler), tracking); + } + + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + return get_one(std::integral_constant(), L, index, std::forward(handler), tracking); + } + }; +#endif // C++17 } // stack } // sol @@ -5976,9 +6822,32 @@ namespace sol { #ifdef SOL_CODECVT_SUPPORT #endif +#ifdef SOL_CXX17_FEATURES +#endif // C++17 namespace sol { namespace stack { + inline int push_environment_of(lua_State* L, int index = -1) { +#if SOL_LUA_VERSION < 502 + // Use lua_setfenv + lua_getfenv(L, index); + return 1; +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + if (lua_getupvalue(L, index, 1) == nullptr) { + push(L, lua_nil); + return 1; + } +#endif + return 1; + } + + template + int push_environment_of(const T& target) { + target.push(); + return push_environment_of(target.lua_state(), -1) + 1; + } + template struct pusher> { template @@ -6068,8 +6937,9 @@ namespace sol { template >> = meta::enabler> static int push(lua_State* L, Arg&& arg) { - if (unique_usertype_traits::is_null(arg)) + if (unique_usertype_traits::is_null(arg)) { return stack::push(L, lua_nil); + } return push_deep(L, std::forward(arg)); } @@ -6080,10 +6950,10 @@ namespace sol { 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)); + P** pref = static_cast(lua_newuserdata(L, sizeof(P*) + sizeof(detail::unique_destructor) + sizeof(Real))); + detail::unique_destructor* fx = static_cast(static_cast(pref + 1)); Real* mem = static_cast(static_cast(fx + 1)); - *fx = detail::special_destruct; + *fx = detail::usertype_unique_alloc_destroy; detail::default_construct::construct(mem, std::forward(args)...); *pref = unique_usertype_traits::get(*mem); if (luaL_newmetatable(L, &usertype_traits>::metatable()[0]) == 1) { @@ -6215,8 +7085,8 @@ namespace sol { }; template<> - struct pusher { - static int push(lua_State* L, metatable_key_t) { + struct pusher { + static int push(lua_State* L, metatable_t) { lua_pushlstring(L, "__mt", 4); return 1; } @@ -6237,6 +7107,23 @@ namespace sol { return 1; } }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + template<> + struct pusher> { + static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; +#endif // noexcept function type template<> struct pusher { @@ -6305,7 +7192,7 @@ namespace sol { return 1; } - template , no_metatable_t, metatable_key_t>> = meta::enabler> + template , no_metatable_t, metatable_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)...); @@ -6318,7 +7205,7 @@ namespace sol { } template - static int push(lua_State* L, metatable_key_t, Key&& key, Args&&... args) { + static int push(lua_State* L, metatable_t, Key&& key, Args&&... args) { const auto name = &key[0]; return push_with(L, name, std::forward(args)...); } @@ -6412,7 +7299,7 @@ namespace sol { template<> struct pusher { static int push(lua_State* L, meta_function m) { - const std::string& str = name_of(m); + const std::string& str = to_string(m); lua_pushlstring(L, str.c_str(), str.size()); return 1; } @@ -6610,7 +7497,7 @@ namespace sol { if (t == nullopt) { return stack::push(L, nullopt); } - return stack::push(L, t.value()); + return stack::push(L, static_cast::value, O&, O&&>>(t.value())); } }; @@ -6634,6 +7521,71 @@ namespace sol { return 0; } }; + + template<> + struct pusher { + static int push(lua_State* L, const new_table& nt) { + lua_createtable(L, nt.sequence_hint, nt.map_hint); + return 1; + } + }; + +#ifdef SOL_CXX17_FEATURES + template <> + struct pusher { + static int push(lua_State* L, const std::string_view& sv) { + return stack::push(L, sv.data(), sv.length()); + } + }; +#ifdef SOL_CODECVT_SUPPORT + template <> + struct pusher { + static int push(lua_State* L, const std::wstring_view& sv) { + return stack::push(L, sv.data(), sv.length()); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, const std::u16string_view& sv) { + return stack::push(L, sv.data(), sv.length()); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, const std::u32string_view& sv) { + return stack::push(L, sv.data(), sv.length()); + } + }; +#endif // codecvt header support + + namespace stack_detail { + + struct push_function { + lua_State* L; + + push_function(lua_State* L) : L(L) {} + + template + int operator()(T&& value) const { + return stack::push(L, std::forward(value)); + } + }; + + } // stack_detail + + template + struct pusher> { + static int push(lua_State* L, const std::variant& v) { + return std::visit(stack_detail::push_function(L), v); + } + + static int push(lua_State* L, std::variant&& v) { + return std::visit(stack_detail::push_function(L), std::move(v)); + } + }; +#endif } // stack } // sol @@ -6685,13 +7637,28 @@ namespace sol { }; template - struct field_getter { - void get(lua_State* L, metatable_key_t, int tableindex = -1) { + struct field_getter { + void get(lua_State* L, metatable_t, int tableindex = -1) { if (lua_getmetatable(L, tableindex) == 0) push(L, lua_nil); } }; + template + struct field_getter { + void get(lua_State* L, env_t, int tableindex = -1) { +#if SOL_LUA_VERSION < 502 + // Use lua_setfenv + lua_getfenv(L, tableindex); +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + if (lua_getupvalue(L, tableindex, 1) == nullptr) { + push(L, lua_nil); + } +#endif + } + }; + template struct field_getter::value>> { template @@ -6710,7 +7677,7 @@ namespace sol { #if SOL_LUA_VERSION >= 503 template - struct field_getter::value>> { + struct field_getter::value && !std::is_same::value>> { template void get(lua_State* L, Key&& key, int tableindex = -1) { lua_geti(L, tableindex, static_cast(key)); @@ -6728,7 +7695,7 @@ namespace sol { #endif // Lua 5.3.x template - struct field_getter::value>> { + struct field_getter::value && !std::is_same::value>> { template void get(lua_State* L, Key&& key, int tableindex = -1) { lua_rawgeti(L, tableindex, static_cast(key)); @@ -6799,9 +7766,9 @@ namespace sol { }; template - struct field_setter { + struct field_setter { template - void set(lua_State* L, metatable_key_t, Value&& value, int tableindex = -2) { + void set(lua_State* L, metatable_t, Value&& value, int tableindex = -2) { push(L, std::forward(value)); lua_setmetatable(L, tableindex); } @@ -6827,7 +7794,7 @@ namespace sol { #if SOL_LUA_VERSION >= 503 template - struct field_setter::value>> { + struct field_setter::value && !std::is_same::value>> { template void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { push(L, std::forward(value)); @@ -6837,7 +7804,7 @@ namespace sol { #endif // Lua 5.3.x template - struct field_setter::value>> { + struct field_setter::value && !std::is_same::value>> { template void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { push(L, std::forward(value)); @@ -6983,7 +7950,7 @@ namespace sol { } template - inline std::pair get_as_upvalues(lua_State* L, int index = 1) { + inline std::pair get_as_upvalues(lua_State* L, int index = 2) { const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); typedef std::array data_t; data_t voiddata{ {} }; @@ -7032,28 +7999,6 @@ namespace sol { 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, index); - } - } - 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; @@ -7155,48 +8100,15 @@ namespace sol { // end of sol/stack.hpp -// beginning of sol/as_args.hpp - -namespace sol { - template - struct to_args_t { - T src; - }; - - template - auto as_args(Source&& source) { - return to_args_t{ std::forward(source) }; - } - - namespace stack { - template - struct pusher> { - int push(lua_State* L, const to_args_t& e) { - int p = 0; - for (const auto& i : e.src) { - p += stack::push(L, i); - } - return p; - } - }; - } -} // sol - -// end of sol/as_args.hpp - -// beginning of sol/variadic_args.hpp - -// beginning of sol/stack_proxy.hpp - -// beginning of sol/function.hpp - // beginning of sol/function_result.hpp // beginning of sol/proxy_base.hpp namespace sol { + struct proxy_base_tag {}; + template - struct proxy_base { + struct proxy_base : proxy_base_tag { operator std::string() const { const Super& super = *static_cast(static_cast(this)); return super.template get(); @@ -7289,7 +8201,7 @@ namespace sol { template struct wrapper { - typedef lua_bind_traits traits_type; + 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; @@ -7308,8 +8220,8 @@ namespace sol { }; template - struct wrapper>>::value>> { - typedef lua_bind_traits traits_type; + 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; @@ -7342,16 +8254,21 @@ namespace sol { template struct wrapper>::value>> { - typedef lua_bind_traits traits_type; + 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) invoke(object_type& mem) { + return mem.*fx; + } + + template + static decltype(auto) invoke(object_type& mem, Arg&& arg, Args&&...) { + return mem.*fx = std::forward(arg); } template @@ -7489,15 +8406,94 @@ namespace sol { }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE //noexcept has become a part of a function's type + + 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 { + + }; + +#endif // noexcept is part of a function's type + } // sol // end of sol/wrapper.hpp namespace sol { namespace function_detail { - template + template inline int call(lua_State* L) { - Fx& fx = stack::get>(L, upvalue_index(1)); + Fx& fx = stack::get>(L, upvalue_index(start)); return fx(L); } } // function_detail @@ -7592,11 +8588,29 @@ namespace sol { return property_detail::property(std::true_type(), std::forward(f)); } + template + inline decltype(auto) writeonly_property(F&& f) { + return property_detail::property(std::false_type(), std::forward(f)); + } + + template + struct readonly_wrapper { + T v; + + readonly_wrapper(T v) : v(std::move(v)) {} + + operator T& () { + return v; + } + operator const T& () const { + return v; + } + }; + // Allow someone to make a member variable readonly (const) template inline auto readonly(R T::* v) { - typedef const R C; - return static_cast(v); + return readonly_wrapper>(v); } template @@ -7616,11 +8630,25 @@ namespace sol { return var_wrapper(std::forward(v)); } + namespace meta { + template + struct is_member_object : std::is_member_object_pointer {}; + + template + struct is_member_object> : std::true_type {}; + } + } // sol // end of sol/property.hpp namespace sol { + namespace function_detail { + inline int no_construction_error(lua_State* L) { + return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); + } + } + namespace call_detail { template @@ -7634,7 +8662,7 @@ namespace sol { } template - struct void_call; + struct void_call : void_call> {}; template struct void_call> { @@ -7662,7 +8690,7 @@ namespace sol { 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 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 @@ -7686,7 +8714,7 @@ namespace sol { template inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + 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 @@ -7701,7 +8729,7 @@ namespace sol { template inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { - typedef lua_bind_traits> traits; + 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 @@ -7826,6 +8854,14 @@ namespace sol { return f(L); } }; +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, detail::lua_CFunction_noexcept f) { + return f(L); + } + }; +#endif // noexcept function types template struct agnostic_lua_call_wrapper { @@ -7837,7 +8873,7 @@ namespace sol { 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)"); + return function_detail::no_construction_error(L); } }; @@ -7849,6 +8885,13 @@ namespace sol { } }; + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, C> { + static int call(lua_State* L, std::reference_wrapper f) { + return agnostic_lua_call_wrapper{}.call(L, f.get()); + } + }; + template struct lua_call_wrapper : agnostic_lua_call_wrapper {}; @@ -7922,7 +8965,7 @@ namespace sol { 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)...); + return call_assign(std::is_copy_assignable>(), L, std::forward(args)...); } template @@ -7932,12 +8975,12 @@ namespace sol { template static int call(lua_State* L, V&& f) { - return call_const(std::is_const(), L, f); + return call_const(std::is_const(), L, std::forward(f)); } template static int call(lua_State* L, V&& f, object_type& o) { - return call_const(std::is_const(), L, f, o); + return call_const(std::is_const(), L, std::forward(f), o); } }; @@ -7948,9 +8991,10 @@ namespace sol { typedef typename wrap::object_type object_type; template - static int call(lua_State* L, V&& f, object_type& o) { + static int call(lua_State* L, V&& v, object_type& o) { typedef typename wrap::returns_list returns_list; typedef typename wrap::caller caller; + F f(std::forward(v)); return stack::call_into_lua(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); } @@ -7974,6 +9018,28 @@ namespace sol { } }; + template + struct lua_call_wrapper, false, is_variable, checked, boost, C> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, V&&) { + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + + template + static int call(lua_State* L, V&&, object_type&) { + return luaL_error(L, "sol: cannot write to a sol::readonly variable"); + } + }; + + template + struct lua_call_wrapper, true, is_variable, checked, boost, C> : lua_call_wrapper { + + }; + template struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { typedef constructor_list F; @@ -8102,12 +9168,21 @@ namespace sol { struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { typedef std::conditional_t P; typedef meta::unqualified_t

U; + typedef wrapper wrap; typedef lua_bind_traits traits_type; + typedef meta::unqualified_t> object_type; template - static int self_call(lua_State* L, F&& f) { - typedef wrapper wrap; - typedef meta::unqualified_t> object_type; + static int self_call(std::true_type, lua_State* L, F&& f) { + // The type being void means we don't have any arguments, so it might be a free functions? + typedef typename traits_type::free_args_list args_list; + 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); + } + + template + static int self_call(std::false_type, lua_State* L, F&& f) { typedef meta::pop_front_type_t args_list; typedef T Ta; #ifdef SOL_SAFE_USERTYPE @@ -8129,7 +9204,7 @@ namespace sol { 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)...); + return self_call(meta::any, meta::boolean>::value != type::userdata>>(), L, pick(meta::boolean(), f), std::forward(args)...); } template @@ -8175,9 +9250,9 @@ namespace sol { return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward(fx), std::forward(args)...); } - template + template inline int call_user(lua_State* L) { - auto& fx = stack::get>(L, upvalue_index(1)); + auto& fx = stack::get>(L, upvalue_index(start)); return call_wrapped(L, fx); } @@ -8195,6 +9270,9 @@ namespace sol { template struct is_var_bind> : std::true_type {}; + + template + struct is_var_bind> : is_var_bind {}; } // call_detail template @@ -8267,7 +9345,7 @@ namespace sol { } template - int call_wrapper_entry(lua_State* L) { + int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits::is_noexcept) { return call_wrapper_function(std::is_member_function_pointer>(), L); } @@ -8280,15 +9358,30 @@ namespace sol { } }; + template + inline int c_call_raw(std::true_type, lua_State* L) { + return fx(L); + } + + template + inline int c_call_raw(std::false_type, lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, function_detail::call_wrapper_entry); +#else + return detail::typed_static_trampoline), (&function_detail::call_wrapper_entry)>(L); +#endif // fuck you clang :c + } + } // 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 + typedef meta::unqualified_t Fu; + return function_detail::c_call_raw(std::integral_constant::value +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + || std::is_same::value +#endif + >(), L); } template @@ -8321,16 +9414,16 @@ namespace sol { template struct upvalue_free_function { typedef std::remove_pointer_t> function_type; - typedef lua_bind_traits traits_type; + typedef meta::bind_traits traits_type; - static int real_call(lua_State* L) { + static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { 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); + return detail::typed_static_trampoline(L); } int operator()(lua_State* L) { @@ -8343,13 +9436,13 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { + static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { // 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 memberdata = stack::stack_detail::get_as_upvalues(L); auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); function_type& memfx = memberdata.first; auto& item = *objdata.first; @@ -8357,7 +9450,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); + return detail::typed_static_trampoline(L); } int operator()(lua_State* L) { @@ -8370,13 +9463,13 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { + static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { // 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 memberdata = stack::stack_detail::get_as_upvalues(L); auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); auto& mem = *objdata.first; function_type& var = memberdata.first; @@ -8391,7 +9484,39 @@ namespace sol { } static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); + return detail::typed_static_trampoline(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) noexcept(traits_type::is_noexcept) { + // 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); + 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); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::typed_static_trampoline(L); } int operator()(lua_State* L) { @@ -8404,16 +9529,16 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) { + static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { // Layout: // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto memberdata = stack::stack_detail::get_as_upvalues(L); 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); + return detail::typed_static_trampoline(L); } int operator()(lua_State* L) { @@ -8424,12 +9549,11 @@ namespace sol { 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) { + static int real_call(lua_State* L) noexcept(false) { // Layout: // idx 1...n: verbatim data of member variable pointer - auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto memberdata = stack::stack_detail::get_as_upvalues(L); function_type& var = memberdata.first; switch (lua_gettop(L)) { case 1: @@ -8442,7 +9566,34 @@ namespace sol { } static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); + return detail::typed_static_trampoline(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) noexcept(false) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + 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::typed_static_trampoline(L); } int operator()(lua_State* L) { @@ -8460,11 +9611,11 @@ namespace sol { namespace function_detail { template struct functor_function { - typedef meta::unwrapped_t> Function; - Function fx; + typedef std::decay_t> function_type; + function_type fx; template - functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} + functor_function(function_type f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} int call(lua_State* L) { return call_detail::call_wrapped(L, fx); @@ -8766,7 +9917,9 @@ namespace sol { 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); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + 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)); } @@ -8785,7 +9938,9 @@ namespace sol { template static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, fx); stack::push(L, c_closure(freefunc, upvalues)); } @@ -8793,7 +9948,9 @@ namespace sol { 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); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, fx); stack::push(L, c_closure(freefunc, upvalues)); } @@ -8811,14 +9968,16 @@ namespace sol { 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); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + 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)...); + select_member_variable(meta::is_member_object>(), L, std::forward(fx), std::forward(args)...); } template >> = meta::enabler> @@ -8830,7 +9989,9 @@ namespace sol { template static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; - int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, fx); stack::push(L, c_closure(freefunc, upvalues)); } @@ -8838,7 +9999,9 @@ namespace sol { 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); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, fx); stack::push(L, c_closure(freefunc, upvalues)); } @@ -8852,7 +10015,9 @@ namespace sol { 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); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::stack_detail::push_as_upvalues(L, target); stack::push(L, c_closure(freefunc, upvalues)); } @@ -8860,17 +10025,30 @@ namespace sol { stack::push(L, f); } - template +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + static void select_function(std::true_type, lua_State* L, detail::lua_CFunction_noexcept f) { + stack::push(L, f); + } +#endif // noexcept function type + + template >, std::is_base_of>>> = meta::enabler> static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + select_function(std::is_function>>(), L, std::forward(fx), std::forward(args)...); + } + + template >, std::is_base_of>>> = meta::enabler> + static void select(lua_State* L, Fx&& fx) { + stack::push(L, std::forward(fx)); } template static void set_fx(lua_State* L, Args&&... args) { - lua_CFunction freefunc = function_detail::call>; + lua_CFunction freefunc = function_detail::call, 2>; - stack::push>(L, std::forward(args)...); - stack::push(L, c_closure(freefunc, 1)); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push>(L, std::forward(args)...); + stack::push(L, c_closure(freefunc, upvalues)); } template @@ -8899,7 +10077,11 @@ namespace sol { template struct pusher> { - static int push(lua_State* L, std::function fx) { + static int push(lua_State* L, const std::function& fx) { + return pusher>{}.push(L, fx); + } + + static int push(lua_State* L, std::function&& fx) { return pusher>{}.push(L, std::move(fx)); } }; @@ -8913,7 +10095,15 @@ namespace sol { }; template - struct pusher, meta::neg>, meta::neg>>>::value>> { + struct pusher, + meta::neg>, + meta::neg>> +#ifdef SOL_NOEXCEPT_FUNCTION_TYPE + , meta::neg>, + meta::neg>> +#endif // noexcept function types + >::value>> { template static int push(lua_State* L, F&& f) { return pusher>{}.push(L, std::forward(f)); @@ -8938,15 +10128,19 @@ namespace sol { 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)); + lua_CFunction cf = call_detail::call_user, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push>>(L, std::move(pw.value)); + return stack::push(L, c_closure(cf, upvalues)); } 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)); + lua_CFunction cf = call_detail::call_user, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push>>(L, pw.value); + return stack::push(L, c_closure(cf, upvalues)); } }; @@ -9017,6 +10211,18 @@ namespace sol { } }; + template <> + struct pusher { + static int push(lua_State* L, no_construction) { + lua_CFunction cf = &function_detail::no_construction_error; + return stack::push(L, cf); + } + + static int push(lua_State* L, no_construction c, function_detail::call_indicator) { + return push(L, c); + } + }; + template struct pusher>> { static int push(lua_State* L, detail::tagged>) { @@ -9029,9 +10235,11 @@ namespace sol { 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)); + lua_CFunction cf = call_detail::call_user, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push>>(L, std::forward(c)); + return stack::push(L, c_closure(cf, upvalues)); } }; @@ -9046,9 +10254,11 @@ namespace sol { 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)); + lua_CFunction cf = call_detail::call_user, 2>; + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push>(L, std::move(c)); + return stack::push(L, c_closure(cf, upvalues)); } }; @@ -9139,51 +10349,9 @@ namespace sol { 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::lua_nil) { - return nullptr; - } - return get_std_func(return_types(), args_lists(), L, index); - } - }; - } // stack } // sol -// end of sol/function.hpp +// end of sol/unsafe_function.hpp // beginning of sol/protected_function.hpp @@ -9199,11 +10367,11 @@ namespace sol { call_status err; template - decltype(auto) tagged_get(types>) const { + decltype(auto) tagged_get(types>) const { if (!valid()) { - return sol::optional(nullopt); + return optional(nullopt); } - return stack::get>(L, index); + return stack::get>(L, index); } template @@ -9424,7 +10592,7 @@ namespace sol { 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(const proxy_base& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} template >>, meta::neg>> = meta::enabler> basic_protected_function(lua_State* L, T&& r, reference eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {} basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { @@ -9461,6 +10629,411 @@ namespace sol { // end of sol/protected_function.hpp +namespace sol { + + 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::lua_nil) { + return nullptr; + } + return get_std_func(return_types(), args_lists(), L, index); + } + }; + } // stack + +} // sol + +// end of sol/function.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&& k) : tbl(table), key(std::forward(k)) {} + + 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; + optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + 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 { + auto pp = 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; + } + + type get_type() const { + type t = type::none; + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); + if (p) { + t = type_of(tbl.lua_state(), -1); + } + lua_pop(tbl.lua_state(), p.levels); + return t; + } + }; + + template + inline bool operator==(T&& left, const proxy& right) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator==(const proxy& right, T&& left) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator!=(T&& left, const proxy& right) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator!=(const proxy& right, T&& left) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator==(lua_nil_t, const proxy& right) { + return !right.valid(); + } + + template + inline bool operator==(const proxy& right, lua_nil_t) { + return !right.valid(); + } + + template + inline bool operator!=(lua_nil_t, const proxy& right) { + return right.valid(); + } + + template + inline bool operator!=(const proxy& right, lua_nil_t) { + return right.valid(); + } + + namespace stack { + template + struct pusher> { + static int push(lua_State* L, const proxy& p) { + sol::reference r = p; + return r.push(L); + } + }; + } // stack +} // sol + +// end of sol/proxy.hpp + +// beginning of sol/usertype.hpp + +// beginning of sol/usertype_metatable.hpp + +// beginning of sol/deprecate.hpp + +#ifndef SOL_DEPRECATED + #ifdef _MSC_VER + #define SOL_DEPRECATED __declspec(deprecated) + #elif __GNUC__ + #define SOL_DEPRECATED __attribute__((deprecated)) + #else + #define SOL_DEPRECATED [[deprecated]] + #endif // compilers +#endif // SOL_DEPRECATED + +namespace sol { + namespace detail { + template + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; + } // detail +} // sol + +// end of sol/deprecate.hpp + +// beginning of sol/object.hpp + +// beginning of sol/object_base.hpp + +namespace sol { + + template + class basic_object_base : 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 { + int r = base_t::registry_index(); + if (r == LUA_REFNIL) + return meta::any_same, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; + if (r == LUA_NOREF) + return false; + auto pp = stack::push_pop(*this); + return stack::check(base_t::lua_state(), -1, no_panic); + } + + public: + basic_object_base() noexcept = default; + basic_object_base(const basic_object_base&) = default; + basic_object_base(basic_object_base&&) = default; + basic_object_base& operator=(const basic_object_base&) = default; + basic_object_base& operator=(basic_object_base&&) = default; + template , basic_object_base>>> = meta::enabler> + basic_object_base(T&& arg, Args&&... args) : base_t(std::forward(arg), std::forward(args)...) { } + + template + decltype(auto) as() const { + return as_stack(std::is_same()); + } + + template + bool is() const { + return is_stack(std::is_same()); + } + }; +} // sol + +// end of sol/object_base.hpp + +// beginning of sol/userdata.hpp + +namespace sol { + template + class basic_userdata : public basic_table { + typedef basic_table 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()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} + basic_userdata(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_userdata(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, index, type_panic); +#endif // Safety + } + }; + + template + class basic_lightuserdata : public basic_object_base { + typedef basic_object_base 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_lightuserdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } + basic_lightuserdata(const basic_lightuserdata&) = default; + basic_lightuserdata(basic_lightuserdata&&) = default; + basic_lightuserdata& operator=(const basic_lightuserdata&) = default; + basic_lightuserdata& operator=(basic_lightuserdata&&) = default; + basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} + basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, index, type_panic); +#endif // Safety + } + }; + +} // sol + +// end of sol/userdata.hpp + +// beginning of sol/as_args.hpp + +namespace sol { + template + struct as_args_t { + T src; + }; + + template + auto as_args(Source&& source) { + return as_args_t{ std::forward(source) }; + } + + namespace stack { + template + struct pusher> { + int push(lua_State* L, const as_args_t& e) { + int p = 0; + for (const auto& i : e.src) { + p += stack::push(L, i); + } + return p; + } + }; + } // stack +} // sol + +// end of sol/as_args.hpp + +// beginning of sol/variadic_args.hpp + +// beginning of sol/stack_proxy.hpp + namespace sol { struct stack_proxy : public proxy_base { private: @@ -9476,6 +11049,10 @@ namespace sol { return stack::get(L, stack_index()); } + type get_type() const noexcept { + return type_of(lua_state(), stack_index()); + } + int push() const { return push(L); } @@ -9562,7 +11139,6 @@ namespace sol { // end of sol/stack_proxy.hpp #include -#include namespace sol { template @@ -9579,17 +11155,27 @@ namespace sol { stack_proxy sp; va_iterator() : L(nullptr), index((std::numeric_limits::max)()), stacktop((std::numeric_limits::max)()) {} + va_iterator(const va_iterator& r) : L(r.L), index(r.index), stacktop(r.stacktop) {} va_iterator(lua_State* luastate, int idx, int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {} reference operator*() { return stack_proxy(L, index); } + reference operator*() const { + return stack_proxy(L, index); + } + pointer operator->() { sp = stack_proxy(L, index); return &sp; } + pointer operator->() const { + const_cast(sp) = stack_proxy(L, index); + return &sp; + } + va_iterator& operator++ () { ++index; return *this; @@ -9632,7 +11218,7 @@ namespace sol { return r; } - reference operator[](difference_type idx) { + reference operator[](difference_type idx) const { return stack_proxy(L, index + static_cast(idx)); } @@ -9691,6 +11277,7 @@ namespace sol { variadic_args() = default; variadic_args(lua_State* luastate, int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {} + variadic_args(lua_State* luastate, int stackindex, int lastindex) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lastindex) {} variadic_args(const variadic_args&) = default; variadic_args& operator=(const variadic_args&) = default; variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { @@ -9749,6 +11336,10 @@ namespace sol { return stack::get(L, index + static_cast(start)); } + type get_type(difference_type start = 0) const noexcept { + return type_of(L, index + static_cast(start)); + } + stack_proxy operator[](difference_type start) const { return stack_proxy(L, index + static_cast(start)); } @@ -9756,6 +11347,7 @@ namespace sol { lua_State* lua_state() const { return L; }; int stack_index() const { return index; }; int leftover_count() const { return stacktop - (index - 1); } + std::size_t size() const { return static_cast(leftover_count()); } int top() const { return stacktop; } }; @@ -9801,30 +11393,10 @@ namespace sol { return r; } - template - class basic_object : public base_t { + template + class basic_object : public basic_object_base { 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); - } + typedef basic_object_base base_t; template basic_object(std::integral_constant, lua_State* L, int index = -1) noexcept : base_t(L, index) { @@ -9835,7 +11407,7 @@ namespace sol { public: basic_object() noexcept = default; - template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> + template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> basic_object(T&& r) : base_t(std::forward(r)) {} basic_object(lua_nil_t r) : base_t(r) {} basic_object(const basic_object&) = default; @@ -9849,29 +11421,19 @@ namespace sol { basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} basic_object(lua_State* L, ref_index index) noexcept : base_t(L, index) {} template - 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)...)) {} + 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)...) {} + basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept + : basic_object(L, in_place_type, std::forward(arg), std::forward(args)...) {} basic_object& operator=(const basic_object&) = default; basic_object& operator=(basic_object&&) = default; - basic_object& operator=(const base_t& b) { base_t::operator=(b); return *this; } - basic_object& operator=(base_t&& b) { base_t::operator=(std::move(b)); return *this; } + basic_object& operator=(const base_type& b) { base_t::operator=(b); return *this; } + basic_object& operator=(base_type&& b) { base_t::operator=(std::move(b)); return *this; } template 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; } - - 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 @@ -9883,208 +11445,137 @@ namespace sol { object make_object(lua_State* L, Args&&... args) { return make_reference(L, std::forward(args)...); } - - inline bool operator==(const object& lhs, const lua_nil_t&) { - return !lhs.valid(); - } - - inline bool operator==(const lua_nil_t&, const object& rhs) { - return !rhs.valid(); - } - - inline bool operator!=(const object& lhs, const lua_nil_t&) { - return lhs.valid(); - } - - inline bool operator!=(const lua_nil_t&, const object& rhs) { - return rhs.valid(); - } } // sol // end of sol/object.hpp -namespace sol { - template - 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&& k) : tbl(table), key(std::forward(k)) {} - - 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 { - auto pp = 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) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator==(const proxy& right, T&& left) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator!=(T&& left, const proxy& right) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator!=(const proxy& right, T&& left) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator==(lua_nil_t, const proxy& right) { - return !right.valid(); - } - - template - inline bool operator==(const proxy& right, lua_nil_t) { - return !right.valid(); - } - - template - inline bool operator!=(lua_nil_t, const proxy& right) { - return right.valid(); - } - - template - inline bool operator!=(const proxy& right, lua_nil_t) { - return right.valid(); - } - - namespace stack { - template - struct pusher> { - static int push(lua_State* L, const proxy& p) { - sol::reference r = p; - return r.push(L); - } - }; - } // stack -} // sol - -// end of sol/proxy.hpp - -// beginning of sol/usertype.hpp - -// beginning of sol/usertype_metatable.hpp - -// beginning of sol/deprecate.hpp - -#ifndef SOL_DEPRECATED - #ifdef _MSC_VER - #define SOL_DEPRECATED __declspec(deprecated) - #elif __GNUC__ - #define SOL_DEPRECATED __attribute__((deprecated)) - #else - #define SOL_DEPRECATED [[deprecated]] - #endif // compilers -#endif // SOL_DEPRECATED - -namespace sol { - namespace detail { - template - struct SOL_DEPRECATED deprecate_type { - using type = T; - }; - } // detail -} // sol - -// end of sol/deprecate.hpp - #include #include namespace sol { namespace usertype_detail { + const int metatable_index = 2; + const int metatable_core_index = 3; + const int filler_index = 4; + const int magic_index = 5; + + const int simple_metatable_index = 2; + const int index_function_index = 3; + const int newindex_function_index = 4; + + typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); + typedef int(*member_search)(lua_State*, void*, int); + + struct call_information { + member_search index; + member_search new_index; + int runtime_target; + + call_information(member_search index, member_search newindex) : call_information(index, newindex, -1) {} + call_information(member_search index, member_search newindex, int runtimetarget) : index(index), new_index(newindex), runtime_target(runtimetarget) {} + }; + + typedef std::unordered_map mapping_t; + + 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; + object index; + object newindex; + base_walk indexbaseclasspropogation; + base_walk newindexbaseclasspropogation; + + simple_map(const char* mkey, base_walk index, base_walk newindex, object i, object ni, variable_map&& vars, function_map&& funcs) + : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), + index(std::move(i)), newindex(std::move(ni)), + indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} + }; + } + + struct usertype_metatable_core { + usertype_detail::mapping_t mapping; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + std::vector runtime; + bool mustindex; + + usertype_metatable_core(lua_CFunction ifx, lua_CFunction nifx) : + mapping(), indexfunc(ifx), + newindexfunc(nifx), runtime(), mustindex(false) + { + + } + + usertype_metatable_core(const usertype_metatable_core&) = default; + usertype_metatable_core(usertype_metatable_core&&) = default; + usertype_metatable_core& operator=(const usertype_metatable_core&) = default; + usertype_metatable_core& operator=(usertype_metatable_core&&) = default; + + }; + + namespace usertype_detail { + const lua_Integer toplevel_magic = static_cast(0xCCC2CCC1); + + struct add_destructor_tag {}; + struct check_destructor_tag {}; + struct verified_tag {} const verified{}; + + template + struct is_non_factory_constructor : std::false_type {}; + + template + struct is_non_factory_constructor> : std::true_type {}; + + template + struct is_non_factory_constructor> : std::true_type {}; + + template <> + struct is_non_factory_constructor : std::true_type {}; + + template + struct is_constructor : is_non_factory_constructor {}; + + 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>...>; + struct no_comp { template bool operator()(A&&, B&&) const { @@ -10092,30 +11583,32 @@ namespace sol { } }; - 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 int is_indexer(string_detail::string_shim s) { + if (s == to_string(meta_function::index)) { + return 1; + } + else if (s == to_string(meta_function::new_index)) { + return 2; + } + return 0; } - inline bool is_indexer(meta_function mf) { - return mf == meta_function::index || mf == meta_function::new_index; + inline int is_indexer(meta_function mf) { + if (mf == meta_function::index) { + return 1; + } + else if (mf == meta_function::new_index) { + return 2; + } + return 0; } - inline bool is_indexer(call_construction) { - return false; + inline int is_indexer(call_construction) { + return 0; } - inline bool is_indexer(base_classes_tag) { - return false; + inline int is_indexer(base_classes_tag) { + return 0; } inline auto make_shim(string_detail::string_shim s) { @@ -10123,11 +11616,11 @@ namespace sol { } inline auto make_shim(call_construction) { - return string_detail::string_shim(name_of(meta_function::call_function)); + return string_detail::string_shim(to_string(meta_function::call_function)); } inline auto make_shim(meta_function mf) { - return string_detail::string_shim(name_of(mf)); + return string_detail::string_shim(to_string(mf)); } inline auto make_shim(base_classes_tag) { @@ -10137,28 +11630,153 @@ namespace sol { template inline std::string make_string(Arg&& arg) { string_detail::string_shim s = make_shim(arg); - return std::string(s.c_str(), s.size()); + return std::string(s.data(), s.size()); } template inline luaL_Reg make_reg(N&& n, lua_CFunction f) { - luaL_Reg l{ make_shim(std::forward(n)).c_str(), f }; + luaL_Reg l{ make_shim(std::forward(n)).data(), f }; return l; } struct registrar { + registrar() = default; + registrar(const registrar&) = default; + registrar(registrar&&) = default; + registrar& operator=(const registrar&) = default; + registrar& operator=(registrar&&) = default; virtual int push_um(lua_State* L) = 0; virtual ~registrar() {} }; - template + inline bool is_toplevel(lua_State* L, int index = magic_index) { + int isnum = 0; + lua_Integer magic = lua_tointegerx(L, upvalue_index(index), &isnum); + return isnum != 0 && magic == toplevel_magic; + } + + inline int runtime_object_call(lua_State* L, void*, int runtimetarget) { + usertype_metatable_core& umc = stack::get>(L, upvalue_index(metatable_core_index)); + std::vector& runtime = umc.runtime; + object& runtimeobj = runtime[runtimetarget]; + return stack::push(L, runtimeobj); + } + + 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()); + if (is_index) { +#if 0//def SOL_SAFE_USERTYPE + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); +#else + if (is_toplevel(L)) { + if (lua_getmetatable(L, 1) == 1) { + int metatarget = lua_gettop(L); + stack::get_field(L, stack_reference(L, raw_index(2)), metatarget); + return 1; + } + } + // With runtime extensibility, we can't hard-error things. They have to return nil, like regular table types, unfortunately... + return stack::push(L, lua_nil); +#endif + } + else { + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); + } + } + + int runtime_new_index(lua_State* L, void*, int runtimetarget); + + template + inline int metatable_newindex(lua_State* L) { + if (is_toplevel(L)) { + auto non_indexable = [&L]() { + if (is_simple) { + simple_map& sm = stack::get>(L, upvalue_index(simple_metatable_index)); + function_map& functions = sm.functions; + optional maybeaccessor = stack::get>(L, 2); + if (!maybeaccessor) { + return; + } + std::string& accessor = maybeaccessor.value(); + auto preexistingit = functions.find(accessor); + if (preexistingit == functions.cend()) { + functions.emplace_hint(preexistingit, std::move(accessor), sol::object(L, 3)); + } + else { + preexistingit->second = sol::object(L, 3); + } + return; + } + usertype_metatable_core& umc = stack::get>(L, upvalue_index(metatable_core_index)); + bool mustindex = umc.mustindex; + if (!mustindex) + return; + optional maybeaccessor = stack::get>(L, 2); + if (!maybeaccessor) { + return; + } + std::string& accessor = maybeaccessor.value(); + mapping_t& mapping = umc.mapping; + std::vector& runtime = umc.runtime; + int target = static_cast(runtime.size()); + auto preexistingit = mapping.find(accessor); + if (preexistingit == mapping.cend()) { + runtime.emplace_back(L, 3); + mapping.emplace_hint(mapping.cend(), accessor, call_information(&runtime_object_call, &runtime_new_index, target)); + } + else { + target = preexistingit->second.runtime_target; + runtime[target] = sol::object(L, 3); + preexistingit->second = call_information(&runtime_object_call, &runtime_new_index, target); + } + }; + non_indexable(); + for (std::size_t i = 0; i < 4; lua_settop(L, 3), ++i) { + const char* metakey = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable()[0]; + luaL_getmetatable(L, metakey); + break; + case 1: + metakey = &usertype_traits>::metatable()[0]; + luaL_getmetatable(L, metakey); + break; + case 2: + metakey = &usertype_traits::metatable()[0]; + luaL_getmetatable(L, metakey); + break; + case 3: + default: + metakey = &usertype_traits::user_metatable()[0]; + { + luaL_getmetatable(L, metakey); + lua_getmetatable(L, -1); + } + break; + } + int tableindex = lua_gettop(L); + if (type_of(L, tableindex) == type::lua_nil) { + continue; + } + stack::set_field(L, stack_reference(L, raw_index(2)), stack_reference(L, raw_index(3)), tableindex); + } + lua_settop(L, 0); + return 0; + } + return indexing_fail(L); + } + + inline int runtime_new_index(lua_State* L, void*, int runtimetarget) { + usertype_metatable_core& umc = stack::get>(L, upvalue_index(metatable_core_index)); + std::vector& runtime = umc.runtime; + object& runtimeobj = runtime[runtimetarget]; + runtimeobj = object(L, 3); + return 0; } template @@ -10230,41 +11848,6 @@ namespace sol { 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_non_factory_constructor : std::false_type {}; - - template - struct is_non_factory_constructor> : std::true_type {}; - - template - struct is_non_factory_constructor> : std::true_type {}; - - template <> - struct is_non_factory_constructor : std::true_type {}; - - template - struct is_constructor : is_non_factory_constructor {}; - - 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 @@ -10279,7 +11862,7 @@ namespace sol { struct usertype_metatable : usertype_detail::registrar {}; template - struct usertype_metatable, Tn...> : usertype_detail::registrar { + struct usertype_metatable, Tn...> : usertype_metatable_core, usertype_detail::registrar { typedef std::make_index_sequence indices; typedef std::index_sequence half_indices; typedef std::array regs_t; @@ -10287,11 +11870,7 @@ namespace sol { 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; @@ -10300,20 +11879,20 @@ namespace sol { 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() { + lua_CFunction make_func() const { return std::get(functions); } template >> = meta::enabler> - inline lua_CFunction make_func() { - return call; + lua_CFunction make_func() const { + const auto& name = std::get(functions); + return (usertype_detail::make_shim(name) == "__newindex") ? &call : &call; } static bool contains_variable() { @@ -10323,25 +11902,25 @@ namespace sol { bool contains_index() const { bool idx = false; - (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get(functions))), 0) ... }; + (void)detail::swallow{ 0, ((idx |= (usertype_detail::is_indexer(std::get(functions)) != 0)), 0) ... }; return idx; } int finish_regs(regs_t& l, int& index) { if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); + const char* name = to_string(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(); + const char* name = to_string(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(); + const char* name = to_string(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 }; + l[index] = { to_string(meta_function::garbage_collect).c_str(), destructfunc }; ++index; } return index; @@ -10355,6 +11934,7 @@ namespace sol { template void make_regs(regs_t&, int&, base_classes_tag, bases) { + static_assert(!meta::any_same::value, "base classes cannot list the original class as part of the bases"); if (sizeof...(Bases) < 1) { return; } @@ -10378,25 +11958,25 @@ namespace sol { // Returnable scope // That would be a neat keyword for C++ // returnable { ... }; - if (reg.name == name_of(meta_function::equal_to)) { + if (reg.name == to_string(meta_function::equal_to)) { hasequals = true; } - if (reg.name == name_of(meta_function::less_than)) { + if (reg.name == to_string(meta_function::less_than)) { hasless = true; } - if (reg.name == name_of(meta_function::less_than_or_equal_to)) { + if (reg.name == to_string(meta_function::less_than_or_equal_to)) { haslessequals = true; } - if (reg.name == name_of(meta_function::garbage_collect)) { + if (reg.name == to_string(meta_function::garbage_collect)) { destructfunc = reg.func; return; } - else if (reg.name == name_of(meta_function::index)) { + else if (reg.name == to_string(meta_function::index)) { indexfunc = reg.func; mustindex = true; return; } - else if (reg.name == name_of(meta_function::new_index)) { + else if (reg.name == to_string(meta_function::new_index)) { newindexfunc = reg.func; mustindex = true; return; @@ -10406,37 +11986,58 @@ namespace sol { } template > - usertype_metatable(Args&&... args) : functions(std::forward(args)...), - mapping(), - indexfunc(usertype_detail::indexing_fail), newindexfunc(usertype_detail::indexing_fail), + usertype_metatable(Args&&... args) : usertype_metatable_core(&usertype_detail::indexing_fail, &usertype_detail::metatable_newindex), usertype_detail::registrar(), + functions(std::forward(args)...), 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()), + 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) + std::initializer_list ilist{ { + std::pair( usertype_detail::make_string(std::get(functions)), + usertype_detail::call_information(&usertype_metatable::real_find_call, + &usertype_metatable::real_find_call) ) }... }; - mapping.insert(ilist); + this->mapping.insert(ilist); + for (const auto& n : meta_function_names()) { + this->mapping.erase(n); + } + this->mustindex = contains_variable() || contains_index(); } + usertype_metatable(const usertype_metatable&) = default; + usertype_metatable(usertype_metatable&&) = default; + usertype_metatable& operator=(const usertype_metatable&) = default; + usertype_metatable& operator=(usertype_metatable&&) = default; + template - static int real_find_call(lua_State* L, void* um) { + static int real_find_call(lua_State* L, void* um, int) { 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)))); + // set up upvalues + // for a chained call + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push(L, light(f)); + auto cfunc = &call; + return stack::push(L, c_closure(cfunc, upvalues)); + } + + template + static int real_meta_call(lua_State* L, void* um, int) { + auto& f = *static_cast(um); + return is_index ? f.indexfunc(L) : f.newindexfunc(L); } template static int core_indexing_call(lua_State* L) { - usertype_metatable& f = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + usertype_metatable& f = toplevel + ? stack::get>(L, upvalue_index(usertype_detail::metatable_index)) + : 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); @@ -10444,8 +12045,9 @@ namespace sol { 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)); + const usertype_detail::call_information& ci = memberit->second; + const usertype_detail::member_search& member = is_index ? ci.index: ci.new_index; + return (member)(L, static_cast(&f), ci.runtime_target); } string_detail::string_shim accessor = name; int ret = 0; @@ -10471,7 +12073,7 @@ namespace sol { template static int real_call(lua_State* L) { - usertype_metatable& f = stack::get>(L, upvalue_index(1)); + usertype_metatable& f = stack::get>(L, upvalue_index(usertype_detail::metatable_index)); return real_call_with(L, f); } @@ -10489,20 +12091,20 @@ namespace sol { template static int call(lua_State* L) { - return detail::static_trampoline<(&real_call)>(L); + return detail::typed_static_trampoline), (&real_call)>(L); } template static int call_with(lua_State* L) { - return detail::static_trampoline<(&real_call_with)>(L); + return detail::typed_static_trampoline), (&real_call_with)>(L); } static int index_call(lua_State* L) { - return detail::static_trampoline<(&real_index_call)>(L); + return detail::typed_static_trampoline(L); } static int new_index_call(lua_State* L) { - return detail::static_trampoline<(&real_new_index_call)>(L); + return detail::typed_static_trampoline(L); } virtual int push_um(lua_State* L) override { @@ -10551,6 +12153,7 @@ namespace sol { static int push(lua_State* L, umt_t&& umx) { umt_t& um = make_cleanup(L, std::move(umx)); + usertype_metatable_core& umc = um; 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)... }; @@ -10558,14 +12161,14 @@ namespace sol { 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; + bool hasdestructor = !value_table.empty() && to_string(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 }; } + unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct }; // Now use um - const bool& mustindex = um.mustindex; + const bool& mustindex = umc.mustindex; for (std::size_t i = 0; i < 3; ++i) { // Pointer types, AKA "references" from C++ const char* metakey = nullptr; @@ -10587,8 +12190,10 @@ namespace sol { } luaL_newmetatable(L, metakey); stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, metaregs, 1); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push(L, make_light(um)); + luaL_setfuncs(L, metaregs, upvalues); if (um.baseclasscheck != nullptr) { stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); @@ -10597,14 +12202,14 @@ namespace sol { 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()); + stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, nullptr, make_light(um), make_light(umc)), t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, nullptr, make_light(um), make_light(umc)), 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()); + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), t.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), t.stack_index()); } else { // If there's only functions, we can use the fast index version @@ -10615,11 +12220,11 @@ namespace sol { lua_createtable(L, 0, 3); stack_reference metabehind(L, -1); if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); + stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), 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, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); } stack::set_field(L, metatable_key, metabehind, t.stack_index()); metabehind.pop(); @@ -10631,18 +12236,20 @@ namespace sol { // Now for the shim-table that actually gets assigned to the name luaL_newmetatable(L, &usertype_traits::user_metatable()[0]); stack_reference t(L, -1); - stack::push(L, make_light(um)); - luaL_setfuncs(L, value_table.data(), 1); + int upvalues = 0; + upvalues += stack::push(L, nullptr); + upvalues += stack::push(L, make_light(um)); + luaL_setfuncs(L, value_table.data(), upvalues); { lua_createtable(L, 0, 3); stack_reference metabehind(L, -1); if (um.callconstructfunc != nullptr) { - stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index()); - } - if (um.secondarymeta) { - stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index()); - stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index()); + stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, nullptr, make_light(um), make_light(umc)), metabehind.stack_index()); } + + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, nullptr, make_light(um), make_light(umc), nullptr, usertype_detail::toplevel_magic), metabehind.stack_index()); + stack::set_field(L, metatable_key, metabehind, t.stack_index()); metabehind.pop(); } @@ -10662,94 +12269,42 @@ namespace sol { namespace sol { namespace usertype_detail { - const lua_Integer toplevel_magic = static_cast(0x00000001); - - 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); + inline int call_indexing_object(lua_State* L, object& f) { + int before = lua_gettop(L); + f.push(); + for (int i = 1; i <= before; ++i) { + lua_pushvalue(L, i); } - - 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) { - int isnum = 0; - lua_Integer magic = lua_tointegerx(L, lua_upvalueindex(4), &isnum); - if (isnum != 0 && magic == toplevel_magic) { - for (std::size_t i = 0; i < 3; lua_pop(L, 1), ++i) { - // Pointer types, AKA "references" from C++ - const char* metakey = nullptr; - switch (i) { - case 0: - metakey = &usertype_traits::metatable()[0]; - break; - case 1: - metakey = &usertype_traits>::metatable()[0]; - break; - case 2: - default: - metakey = &usertype_traits::metatable()[0]; - break; - } - luaL_getmetatable(L, metakey); - int tableindex = lua_gettop(L); - if (type_of(L, tableindex) == type::lua_nil) { - continue; - } - stack::set_field(L, stack_reference(L, 2), stack_reference(L, 3), tableindex); - } - lua_settop(L, 0); - return 0; - } - return indexing_fail(L); + lua_callk(L, before, LUA_MULTRET, 0, nullptr); + int after = lua_gettop(L); + return after - before; } - inline int simple_indexing_fail(lua_State* L) { - return stack::push(L, sol::lua_nil); - } - - template + template inline int simple_core_indexing_call(lua_State* L) { - simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + simple_map& sm = toplevel + ? stack::get>(L, upvalue_index(simple_metatable_index)) + : 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); + if (has_indexing) { + object& indexingfunc = is_index + ? sm.index + : sm.newindex; + return call_indexing_object(L, indexingfunc); + } + else { + return is_index + ? indexing_fail(L) + : metatable_newindex(L); + } } } string_detail::string_shim accessor = stack::get(L, keyidx); - std::string accessorkey = accessor.c_str(); + std::string accessorkey = accessor.data(); auto vit = variables.find(accessorkey); if (vit != variables.cend()) { auto& varwrap = *(vit->second); @@ -10760,10 +12315,25 @@ namespace sol { } auto fit = functions.find(accessorkey); if (fit != functions.cend()) { - auto& func = (fit->second); - return stack::push(L, func); + sol::object& func = fit->second; + if (is_index) { + return stack::push(L, func); + } + else { + if (has_indexing && !is_toplevel(L)) { + object& indexingfunc = is_index + ? sm.index + : sm.newindex; + return call_indexing_object(L, indexingfunc); + } + else { + return is_index + ? indexing_fail(L) + : metatable_newindex(L); + } + } } - // Check table storage first for a method that works + /* Check table storage first for a method that works luaL_getmetatable(L, sm.metakey); if (type_of(L, -1) != type::lua_nil) { stack::get_field(L, accessor.c_str(), lua_gettop(L)); @@ -10775,7 +12345,8 @@ namespace sol { lua_pop(L, 1); } lua_pop(L, 1); - + */ + int ret = 0; bool found = false; // Otherwise, we need to do propagating calls through the bases @@ -10789,26 +12360,47 @@ namespace sol { return ret; } if (toplevel) { - lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); - return indexingfunc(L); + if (has_indexing && !is_toplevel(L)) { + object& indexingfunc = is_index + ? sm.index + : sm.newindex; + return call_indexing_object(L, indexingfunc); + } + else { + return is_index + ? indexing_fail(L) + : metatable_newindex(L); + } } return -1; } + template inline int simple_real_index_call(lua_State* L) { - return simple_core_indexing_call(L); + return simple_core_indexing_call(L); } + template inline int simple_real_new_index_call(lua_State* L) { - return simple_core_indexing_call(L); + return simple_core_indexing_call(L); } + template inline int simple_index_call(lua_State* L) { - return detail::static_trampoline<(&simple_real_index_call)>(L); +#if defined(__clang__) + return detail::trampoline(L, &simple_real_index_call); +#else + return detail::typed_static_trampoline), (&simple_real_index_call)>(L); +#endif } + template inline int simple_new_index_call(lua_State* L) { - return detail::static_trampoline<(&simple_real_new_index_call)>(L); +#if defined(__clang__) + return detail::trampoline(L, &simple_real_new_index_call); +#else + return detail::typed_static_trampoline), (&simple_real_new_index_call)>(L); +#endif } } @@ -10820,8 +12412,8 @@ namespace sol { usertype_detail::function_map registrations; usertype_detail::variable_map varmap; object callconstructfunc; - lua_CFunction indexfunc; - lua_CFunction newindexfunc; + object indexfunc; + object newindexfunc; lua_CFunction indexbase; lua_CFunction newindexbase; usertype_detail::base_walk indexbaseclasspropogation; @@ -10834,6 +12426,15 @@ namespace sol { template void insert(N&& n, object&& o) { std::string key = usertype_detail::make_string(std::forward(n)); + int is_indexer = static_cast(usertype_detail::is_indexer(n)); + if (is_indexer == 1) { + indexfunc = o; + mustindex = true; + } + else if (is_indexer == 2) { + newindexfunc = o; + mustindex = true; + } auto hint = registrations.find(key); if (hint == registrations.cend()) { registrations.emplace_hint(hint, std::move(key), std::move(o)); @@ -10900,7 +12501,7 @@ namespace sol { template void add(lua_State* L, N&& n, constructor_wrapper c) { - object o(L, in_place>>, std::move(c)); + object o(L, in_place_type>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -10910,7 +12511,7 @@ namespace sol { template void add(lua_State* L, N&& n, constructor_list c) { - object o(L, in_place>>, std::move(c)); + object o(L, in_place_type>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -10920,7 +12521,7 @@ namespace sol { template void add(lua_State* L, N&& n, destructor_wrapper c) { - object o(L, in_place>>, std::move(c)); + object o(L, in_place_type>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -10930,7 +12531,7 @@ namespace sol { template void add(lua_State* L, N&& n, destructor_wrapper c) { - object o(L, in_place>>, std::move(c)); + object o(L, in_place_type>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -10941,6 +12542,7 @@ namespace sol { 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. Please file a bug report."); + static_assert(!meta::any_same::value, "base classes cannot list the original class as part of the bases"); if (sizeof...(Bases) < 1) { return; } @@ -10959,8 +12561,8 @@ namespace sol { template simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) : callconstructfunc(lua_nil), - indexfunc(&usertype_detail::simple_indexing_fail), newindexfunc(&usertype_detail::simple_metatable_newindex), - indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), + indexfunc(lua_nil), newindexfunc(lua_nil), + 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(false), secondarymeta(false) { @@ -10998,6 +12600,11 @@ namespace sol { 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) {} + simple_usertype_metatable(const simple_usertype_metatable&) = default; + simple_usertype_metatable(simple_usertype_metatable&&) = default; + simple_usertype_metatable& operator=(const simple_usertype_metatable&) = default; + simple_usertype_metatable& operator=(simple_usertype_metatable&&) = default; + virtual int push_um(lua_State* L) override { return stack::push(L, std::move(*this)); } @@ -11024,6 +12631,7 @@ namespace sol { 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.indexfunc), std::move(umx.newindexfunc), std::move(umx.varmap), std::move(umx.registrations) ); stack_reference stackvarmap(L, -1); @@ -11036,34 +12644,38 @@ namespace sol { } static int push(lua_State* L, umt_t&& umx) { + bool hasindex = umx.indexfunc.valid(); + bool hasnewindex = umx.newindexfunc.valid(); auto& varmap = make_cleanup(L, umx); + auto sic = hasindex ? &usertype_detail::simple_index_call : &usertype_detail::simple_index_call; + auto snic = hasnewindex ? &usertype_detail::simple_new_index_call : &usertype_detail::simple_new_index_call; bool hasequals = false; bool hasless = false; bool haslessequals = false; auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { - if (first == name_of(meta_function::equal_to)) { + if (first == to_string(meta_function::equal_to)) { hasequals = true; } - else if (first == name_of(meta_function::less_than)) { + else if (first == to_string(meta_function::less_than)) { hasless = true; } - else if (first == name_of(meta_function::less_than_or_equal_to)) { + else if (first == to_string(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 == to_string(meta_function::index)) { + umx.indexfunc = second; } - else if (first == name_of(meta_function::new_index)) { - umx.newindexfunc = second.template as(); + else if (first == to_string(meta_function::new_index)) { + umx.newindexfunc = second; } switch (i) { case 0: - if (first == name_of(meta_function::garbage_collect)) { + if (first == to_string(meta_function::garbage_collect)) { return; } break; case 1: - if (first == name_of(meta_function::garbage_collect)) { + if (first == to_string(meta_function::garbage_collect)) { stack::set_field(L, first, detail::unique_destruct, t.stack_index()); return; } @@ -11075,7 +12687,6 @@ namespace sol { stack::set_field(L, first, second, t.stack_index()); }; for (std::size_t i = 0; i < 3; ++i) { - // Pointer types, AKA "references" from C++ const char* metakey = nullptr; switch (i) { case 0: @@ -11099,15 +12710,15 @@ namespace sol { luaL_Reg opregs[4]{}; int opregsindex = 0; if (!hasless) { - const char* name = name_of(meta_function::less_than).c_str(); + const char* name = to_string(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(); + const char* name = to_string(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(); + const char* name = to_string(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(); @@ -11128,16 +12739,14 @@ namespace sol { if (umx.mustindex) { // use indexing function stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc + make_closure(sic, + nullptr, + make_light(varmap) ), 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 + make_closure(snic, + nullptr, + make_light(varmap) ), t.stack_index()); } else { @@ -11153,16 +12762,14 @@ namespace sol { } if (umx.secondarymeta) { stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, - make_light(varmap), - umx.indexfunc, - umx.newindexfunc + make_closure(sic, + nullptr, + make_light(varmap) ), 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 + make_closure(snic, + nullptr, + make_light(varmap) ), metabehind.stack_index()); } stack::set_field(L, metatable_key, metabehind, t.stack_index()); @@ -11187,17 +12794,19 @@ namespace sol { } // use indexing function stack::set_field(L, meta_function::index, - make_closure(&usertype_detail::simple_index_call, + make_closure(sic, + nullptr, make_light(varmap), - umx.indexfunc, - umx.newindexfunc, + nullptr, + nullptr, usertype_detail::toplevel_magic ), metabehind.stack_index()); stack::set_field(L, meta_function::new_index, - make_closure(&usertype_detail::simple_new_index_call, + make_closure(snic, + nullptr, make_light(varmap), - umx.indexfunc, - umx.newindexfunc, + nullptr, + nullptr, usertype_detail::toplevel_magic ), metabehind.stack_index()); stack::set_field(L, metatable_key, metabehind, t.stack_index()); @@ -11226,7 +12835,7 @@ namespace sol { typedef std::array one; typedef std::array two; - template static one test(decltype(&C::find)); + template static one test(decltype(std::declval().find(std::declval>()))*); template static two test(...); public: @@ -11300,13 +12909,21 @@ namespace sol { template struct container_usertype_metatable { - typedef meta::has_key_value_pair> is_associative; + typedef meta::is_associative>> is_associative; typedef meta::unqualified_t T; typedef typename T::iterator I; typedef std::conditional_t> KV; typedef typename KV::first_type K; typedef typename KV::second_type V; typedef std::remove_reference_t())> IR; + typedef typename meta::iterator_tag::type tag_t; + typedef std::conditional_t::value, + V, + std::conditional_t()) + > + > push_type; struct iter { T& source; @@ -11324,7 +12941,26 @@ namespace sol { return *p.value(); #else return stack::get(L, 1); -#endif +#endif // Safe getting with error + } + + static int delegate_call(lua_State* L) { + static std::unordered_map calls{ + { "add", &real_add_call }, + { "insert", &real_insert_call }, + { "clear", &real_clear_call }, + { "find", &real_find_call }, + { "get", &real_get_call } + }; + auto maybename = stack::check_get(L, 2); + if (maybename) { + auto& name = *maybename; + auto it = calls.find(name); + if (it != calls.cend()) { + return stack::push(L, it->second); + } + } + return stack::push(L, lua_nil); } static int real_index_call_associative(std::true_type, lua_State* L) { @@ -11335,25 +12971,10 @@ namespace sol { auto it = detail::find(src, *k); if (it != end(src)) { auto& v = *it; - return stack::push_reference(L, v.second); + return stack::stack_detail::push_reference(L, v.second); } } - else { - auto maybename = stack::check_get(L, 2); - if (maybename) { - auto& name = *maybename; - if (name == "add") { - return stack::push(L, &add_call); - } - else if (name == "insert") { - return stack::push(L, &insert_call); - } - else if (name == "clear") { - return stack::push(L, &clear_call); - } - } - } - return stack::push(L, lua_nil); + return delegate_call(L); } static int real_index_call_associative(std::false_type, lua_State* L) { @@ -11363,39 +12984,24 @@ namespace sol { using std::begin; auto it = begin(src); K k = *maybek; -#ifdef SOL_SAFE_USERTYPE if (k > src.size() || k < 1) { return stack::push(L, lua_nil); } -#else -#endif // Safety --k; std::advance(it, k); - return stack::push_reference(L, *it); + return stack::stack_detail::push_reference(L, *it); } - else { - auto maybename = stack::check_get(L, 2); - if (maybename) { - auto& name = *maybename; - if (name == "add") { - return stack::push(L, &add_call); - } - else if (name == "insert") { - return stack::push(L, &insert_call); - } - else if (name == "clear") { - return stack::push(L, &clear_call); - } - } - } - - return stack::push(L, lua_nil); + return delegate_call(L); } static int real_index_call(lua_State* L) { return real_index_call_associative(is_associative(), L); } + static int real_get_call(lua_State* L) { + return real_index_call_associative(is_associative(), L); + } + static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) { return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); } @@ -11404,48 +13010,91 @@ namespace sol { return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); } - static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { + static int real_new_index_call_fixed(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) }); - } +#ifdef SOL_CHECK_ARGUMENTS + auto maybek = stack::check_get(L, 2); + if (!maybek) { + return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); + } + K& k = *maybek; +#else + K k = stack::get(L, 2); +#endif + 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_const(std::true_type, std::false_type, lua_State* L) { + static int real_new_index_call_fixed(std::false_type, lua_State* L) { auto& src = get_src(L); -#ifdef SOL_SAFE_USERTYPE +#ifdef SOL_CHECK_ARGUMENTS auto maybek = stack::check_get(L, 2); if (!maybek) { - return stack::push(L, lua_nil); + return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); } - K k = *maybek; + K& k = *maybek; +#else + K k = stack::get(L, 2); +#endif + using std::end; + auto it = detail::find(src, k); + if (it != end(src)) { + auto& v = *it; + v.second = stack::get(L, 3); + } + else { + return luaL_error(L, "sol: cannot insert key of type %s to into %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); + } + return 0; + } + + static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { + return real_new_index_call_fixed(std::integral_constant::value>(), L); + } + + static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) { + auto& src = get_src(L); +#ifdef SOL_CHECK_ARGUMENTS + auto maybek = stack::check_get(L, 2); + if (!maybek) { + return luaL_error(L, "sol: improper index of type %s to a %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); + } + K& k = *maybek; #else K k = stack::get(L, 2); #endif using std::begin; auto it = begin(src); +#ifdef SOL_CHECK_ARGUMENTS + if (k < 1) { + return luaL_error(L, "sol: out of bounds index to a %s", detail::demangle().c_str()); + } +#endif + --k; if (k == src.size()) { - real_add_call_push(std::integral_constant::value>(), L, src, 1); + real_add_call_push(std::integral_constant::value && std::is_copy_constructible::value>(), L, src, 1); return 0; } - --k; +#ifdef SOL_CHECK_ARGUMENTS + if (k > src.size()) { + return luaL_error(L, "sol: out of bounds index to a %s", detail::demangle().c_str()); + } +#endif std::advance(it, k); *it = stack::get(L, 3); return 0; } static int real_new_index_call(lua_State* L) { - return real_new_index_call_const(meta::neg, std::is_const>>(), is_associative(), L); + return real_new_index_call_const(meta::neg, std::is_const, meta::neg>>>(), meta::all>(), L); } static int real_pairs_next_call_assoc(std::true_type, lua_State* L) { @@ -11456,7 +13105,9 @@ namespace sol { if (it == end(source)) { return 0; } - int p = stack::multi_push_reference(L, it->first, it->second); + int p; + p = stack::push_reference(L, it->first); + p += stack::stack_detail::push_reference(L, it->second); std::advance(it, 1); return p; } @@ -11479,7 +13130,9 @@ namespace sol { if (it == end(source)) { return 0; } - int p = stack::multi_push_reference(L, k + 1, *it); + int p; + p = stack::push_reference(L, k + 1); + p += stack::stack_detail::push_reference(L, *it); std::advance(it, 1); return p; } @@ -11523,7 +13176,7 @@ namespace sol { } static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) { - return real_add_call_insert(std::integral_constant::value>(), L, src, boost); + return real_add_call_insert(std::integral_constant::value && std::is_copy_constructible::value>(), L, src, boost); } static int real_add_call_associative(std::true_type, lua_State* L) { @@ -11532,7 +13185,7 @@ namespace sol { static int real_add_call_associative(std::false_type, lua_State* L) { auto& src = get_src(L); - return real_add_call_push(std::integral_constant::value>(), L, src); + return real_add_call_push(std::integral_constant::value && std::is_copy_constructible::value>(), L, src); } static int real_add_call_capable(std::true_type, lua_State* L) { @@ -11545,7 +13198,7 @@ namespace sol { } static int real_add_call(lua_State* L) { - return real_add_call_capable(std::integral_constant::value || detail::has_insert::value>(), L); + return real_add_call_capable(std::integral_constant::value || detail::has_insert::value) && std::is_copy_constructible::value>(), L); } static int real_insert_call_capable(std::false_type, std::false_type, lua_State*L) { @@ -11569,7 +13222,7 @@ namespace sol { } static int real_insert_call(lua_State*L) { - return real_insert_call_capable(std::integral_constant::value>(), is_associative(), L); + return real_insert_call_capable(std::integral_constant::value && std::is_copy_assignable::value>(), is_associative(), L); } static int real_clear_call_capable(std::false_type, lua_State* L) { @@ -11587,36 +13240,74 @@ namespace sol { return real_clear_call_capable(std::integral_constant::value>(), L); } + static int real_find_call_capable(std::false_type, std::false_type, lua_State*L) { + static const std::string& s = detail::demangle(); + return luaL_error(L, "sol: cannot call find on type %s", s.c_str()); + } + + static int real_find_call_capable(std::false_type, std::true_type, lua_State*L) { + return real_index_call(L); + } + + static int real_find_call_capable(std::true_type, std::false_type, lua_State* L) { + auto k = stack::check_get(L, 2); + if (k) { + auto& src = get_src(L); + auto it = src.find(*k); + if (it != src.end()) { + auto& v = *it; + return stack::stack_detail::push_reference(L, v); + } + } + return stack::push(L, lua_nil); + } + + static int real_find_call_capable(std::true_type, std::true_type, lua_State* L) { + return real_index_call(L); + } + + static int real_find_call(lua_State*L) { + return real_find_call_capable(std::integral_constant::value>(), is_associative(), L); + } + static int add_call(lua_State*L) { - return detail::static_trampoline<(&real_add_call)>(L); + return detail::typed_static_trampoline(L); } static int insert_call(lua_State*L) { - return detail::static_trampoline<(&real_insert_call)>(L); + return detail::typed_static_trampoline(L); } static int clear_call(lua_State*L) { - return detail::static_trampoline<(&real_clear_call)>(L); + return detail::typed_static_trampoline(L); + } + + static int find_call(lua_State*L) { + return detail::typed_static_trampoline(L); } static int length_call(lua_State*L) { - return detail::static_trampoline<(&real_length_call)>(L); + return detail::typed_static_trampoline(L); } static int pairs_next_call(lua_State*L) { - return detail::static_trampoline<(&real_pairs_next_call)>(L); + return detail::typed_static_trampoline(L); } static int pairs_call(lua_State*L) { - return detail::static_trampoline<(&real_pairs_call)>(L); + return detail::typed_static_trampoline(L); + } + + static int get_call(lua_State*L) { + return detail::typed_static_trampoline(L); } static int index_call(lua_State*L) { - return detail::static_trampoline<(&real_index_call)>(L); + return detail::typed_static_trampoline(L); } static int new_index_call(lua_State*L) { - return detail::static_trampoline<(&real_new_index_call)>(L); + return detail::typed_static_trampoline(L); } }; @@ -11625,15 +13316,17 @@ namespace sol { template inline auto container_metatable() { typedef container_usertype_metatable> meta_cumt; - std::array reg = { { + std::array reg = { { { "__index", &meta_cumt::index_call }, { "__newindex", &meta_cumt::new_index_call }, { "__pairs", &meta_cumt::pairs_call }, { "__ipairs", &meta_cumt::pairs_call }, { "__len", &meta_cumt::length_call }, + { "get", &meta_cumt::get_call }, { "clear", &meta_cumt::clear_call }, { "insert", &meta_cumt::insert_call }, { "add", &meta_cumt::add_call }, + { "find", &meta_cumt::find_call }, std::is_pointer::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy }, { nullptr, nullptr } } }; @@ -11739,7 +13432,9 @@ namespace sol { } int push(lua_State* L) { - return metatableregister->push_um(L); + int r = metatableregister->push_um(L); + metatableregister = nullptr; + return r; } }; @@ -11756,7 +13451,7 @@ namespace sol { template void set(N&& n, F&& f) { auto meta = static_cast*>(base_t::registrar_data()); - meta->add(state, n, f); + meta->add(state, std::forward(n), std::forward(f)); } }; @@ -11878,8 +13573,11 @@ namespace sol { } } - template - class basic_table_core : public base_t { + const new_table create = new_table{}; + + template + class basic_table_core : public basic_object_base { + typedef basic_object_base base_t; friend class state; friend class state_view; @@ -11916,15 +13614,15 @@ namespace sol { -> 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))... + traverse_get_optional(meta::is_optional>(), detail::forward_get<0>(keys)), + traverse_get_optional(meta::is_optional>(), detail::forward_get<1>(keys)), + traverse_get_optional(meta::is_optional>(), 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)); + return traverse_get_optional(meta::is_optional>(), detail::forward_get(keys)); } template @@ -11992,41 +13690,52 @@ namespace sol { traverse_set_deep(std::forward(keys)...); } - basic_table_core(lua_State* L, detail::global_tag t) noexcept : reference(L, t) { } - + basic_table_core(lua_State* L, detail::global_tag t) noexcept : base_t(L, t) { } + + protected: + basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) {} + basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) {} + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward(r)) {} + public: - typedef basic_table_iterator iterator; + 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() noexcept = default; basic_table_core(const basic_table_core&) = default; basic_table_core(basic_table_core&&) = default; basic_table_core& operator=(const basic_table_core&) = default; basic_table_core& operator=(basic_table_core&&) = default; basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {} basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {} - template >>, meta::neg>> = meta::enabler> + template >>, meta::neg, ref_index>>> = meta::enabler> basic_table_core(lua_State* L, T&& r) : basic_table_core(L, sol::ref_index(r.registry_index())) {} - basic_table_core(lua_State* L, int index = -1) : base_t(L, index) { + basic_table_core(lua_State* L, new_table nt) : base_t(L, (lua_createtable(L, nt.sequence_hint, nt.map_hint), -1)) { + if (!std::is_base_of::value) { + lua_pop(L, 1); + } + } + basic_table_core(lua_State* L, int index = -1) : basic_table_core(detail::no_safety, L, index) { #ifdef SOL_CHECK_ARGUMENTS stack::check(L, index, type_panic); #endif // Safety } - basic_table_core(lua_State* L, ref_index index) : base_t(L, index) { + basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) { #ifdef SOL_CHECK_ARGUMENTS auto pp = stack::push_pop(*this); stack::check(L, -1, type_panic); #endif // Safety } + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, 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 + } iterator begin() const { return iterator(*this); @@ -12054,7 +13763,7 @@ namespace sol { template decltype(auto) get_or(Key&& key, T&& otherwise) const { typedef decltype(get("")) U; - sol::optional option = get>(std::forward(key)); + optional option = get>(std::forward(key)); if (option) { return static_cast(option.value()); } @@ -12063,7 +13772,7 @@ namespace sol { template decltype(auto) get_or(Key&& key, D&& otherwise) const { - sol::optional option = get>(std::forward(key)); + optional option = get>(std::forward(key)); if (option) { return static_cast(option.value()); } @@ -12073,7 +13782,7 @@ namespace sol { 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)...); + return traverse_get_optional(meta::is_optional>(), std::forward(keys)...); } template @@ -12316,10 +14025,185 @@ namespace sol { namespace sol { typedef table_core table; + + namespace stack { + template <> + struct getter { + static table get(lua_State* L, int index = -1) { + if (lua_getmetatable(L, index) == 0) { + return table(L, ref_index(LUA_REFNIL)); + } + return table(L, -1); + } + }; + } // stack } // sol // end of sol/table.hpp +// beginning of sol/environment.hpp + +namespace sol { + + template + struct basic_environment : basic_table { + private: + typedef basic_table base_t; + + public: + basic_environment() noexcept = default; + basic_environment(const basic_environment&) = default; + basic_environment(basic_environment&&) = default; + basic_environment& operator=(const basic_environment&) = default; + basic_environment& operator=(basic_environment&&) = default; + basic_environment(const stack_reference& r) : basic_environment(r.lua_state(), r.stack_index()) {} + basic_environment(stack_reference&& r) : basic_environment(r.lua_state(), r.stack_index()) {} + + basic_environment(lua_State* L, new_table nt) : base_t(L, std::move(nt)) {} + basic_environment(lua_State* L, new_table t, const reference& fallback) : basic_environment(L, std::move(t)) { + sol::stack_table mt(L, sol::new_table(0, 1)); + mt.set(sol::meta_function::index, fallback); + this->set(metatable_key, mt); + mt.pop(); + } + + basic_environment(env_t, const stack_reference& extraction_target) : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(this->lua_state(), -1, type_panic); +#endif // Safety + lua_pop(this->lua_state(), 2); + } + basic_environment(env_t, const reference& extraction_target) : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(this->lua_state(), -1, type_panic); +#endif // Safety + lua_pop(this->lua_state(), 2); + } + basic_environment(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_environment(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, -1, type_panic); +#endif // Safety + } + template , basic_environment>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_environment>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + + template + void set_on(const T& target) const { + lua_State* L = target.lua_state(); + auto pp = stack::push_pop(target); +#if SOL_LUA_VERSION < 502 + // Use lua_setfenv + this->push(); + lua_setfenv(L, -2); +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + this->push(); + const char* name = lua_setupvalue(L, -2, 1); + if (name == nullptr) { + this->pop(); + } +#endif + } + }; + + template + void set_environment(const basic_environment& env, const T& target) { + env.set_on(target); + } + + template + basic_environment get_environment(const T& target) { + lua_State* L = target.lua_state(); + auto pp = stack::pop_n(L, stack::push_environment_of(target)); + return basic_environment(L, -1); + } + + struct this_environment { + optional env; + + this_environment() : env(nullopt) {} + this_environment(sol::environment e) : env(std::move(e)) {} + this_environment(const this_environment&) = default; + this_environment(this_environment&&) = default; + this_environment& operator=(const this_environment&) = default; + this_environment& operator=(this_environment&&) = default; + + explicit operator bool() const { + return static_cast(env); + } + + operator optional& () { + return env; + } + + operator const optional& () const { + return env; + } + + operator environment& () { + return env.value(); + } + + operator const environment& () const { + return env.value(); + } + }; + + namespace stack { + template <> + struct getter { + static environment get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return get_environment(stack_reference(L, raw_index(index))); + } + }; + + template <> + struct getter { + static this_environment get(lua_State* L, int, record& tracking) { + tracking.use(0); + lua_Debug info; + // Level 0 means current function (this C function, which may or may not be useful for us?) + // Level 1 means next call frame up the stack. (Can be nothing if function called directly from C++ with lua_p/call) + int pre_stack_size = lua_gettop(L); + if (lua_getstack(L, 1, &info) != 1) { + if (lua_getstack(L, 0, &info) != 1) { + lua_settop(L, pre_stack_size); + return this_environment(); + } + } + if (lua_getinfo(L, "f", &info) == 0) { + lua_settop(L, pre_stack_size); + return this_environment(); + } + + sol::stack_reference f(L, -1); + sol::environment env(sol::env_key, f); + if (!env.valid()) { + lua_settop(L, pre_stack_size); + return this_environment(); + } + return this_environment(std::move(env)); + } + }; + } // stack +} // sol + +// end of sol/environment.hpp + // beginning of sol/load_result.hpp namespace sol { @@ -12332,11 +14216,11 @@ namespace sol { load_status err; template - decltype(auto) tagged_get(types>) const { + decltype(auto) tagged_get(types>) const { if (!valid()) { - return sol::optional(nullopt); + return optional(nullopt); } - return stack::get>(L, index); + return stack::get>(L, index); } template @@ -12349,20 +14233,20 @@ namespace sol { return stack::get(L, index); } - sol::optional tagged_get(types>) const { + optional tagged_get(types>) const { if (valid()) { return nullopt; } - return sol::error(detail::direct_error, stack::get(L, index)); + return error(detail::direct_error, stack::get(L, index)); } - sol::error tagged_get(types) const { + 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)); + return error(detail::direct_error, stack::get(L, index)); } public: @@ -12458,6 +14342,29 @@ namespace sol { return kb; } + inline protected_function_result simple_on_error(lua_State*, sol::protected_function_result result) { + return result; + } + + inline protected_function_result default_on_error( lua_State* L, protected_function_result pfr ) { + type t = type_of(L, pfr.stack_index()); + std::string err = to_string(pfr.status()) + " error"; + if (t == type::string) { + err += " "; + err += stack::get(L, pfr.stack_index()); + } +#ifdef SOL_NO_EXCEPTIONS + if (t != type::nil) { + lua_pop(L, 1); + } + stack::push(L, err); + lua_error(L); +#else + throw error(detail::direct_error, err); +#endif + return pfr; + } + class state_view { private: lua_State* L; @@ -12639,16 +14546,94 @@ namespace sol { return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); } + template + protected_function_result do_string(const std::string& code, const basic_environment& env) { + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); + set_environment(env, pf); + return pf(); + } + + template + protected_function_result do_file(const std::string& filename, const basic_environment& env) { + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); + set_environment(env, pf); + return pf(); + } + protected_function_result do_string(const std::string& code) { - sol::protected_function pf = load(code); + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); return pf(); } protected_function_result do_file(const std::string& filename) { - sol::protected_function pf = load_file(filename); + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); return pf(); } + protected_function_result script(const std::string& code, const environment& env) { + return script(code, env, sol::default_on_error); + } + + protected_function_result script_file(const std::string& filename, const environment& env) { + return script_file(filename, env, sol::default_on_error); + } + + template >> = meta::enabler> + protected_function_result script(const std::string& code, Fx&& on_error) { + protected_function_result pfr = do_string(code); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template >> = meta::enabler> + protected_function_result script_file(const std::string& filename, Fx&& on_error) { + protected_function_result pfr = do_file(filename); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template + protected_function_result script(const std::string& code, const basic_environment& env, Fx&& on_error) { + protected_function_result pfr = do_string(code, env); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template + protected_function_result script_file(const std::string& filename, const basic_environment& env, Fx&& on_error) { + protected_function_result pfr = do_file(filename, env); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + function_result script(const std::string& code) { int index = lua_gettop(L); stack::script(L, code); @@ -12905,9 +14890,10 @@ namespace sol { const char* message = lua_tostring(L, -1); if (message) { std::string err = message; - lua_pop(L, 1); + lua_settop(L, 0); throw error(err); } + lua_settop(L, 0); throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic")); #endif } @@ -12918,13 +14904,13 @@ namespace sol { optional maybetopmsg = stack::check_get(L, 1); if (maybetopmsg) { const string_detail::string_shim& topmsg = maybetopmsg.value(); - msg.assign(topmsg.c_str(), topmsg.size()); + msg.assign(topmsg.data(), topmsg.size()); } luaL_traceback(L, L, msg.c_str(), 1); optional maybetraceback = stack::check_get(L, -1); if (maybetraceback) { const string_detail::string_shim& traceback = maybetraceback.value(); - msg.assign(traceback.c_str(), traceback.size()); + msg.assign(traceback.data(), traceback.size()); } return stack::push(L, msg); } @@ -12936,6 +14922,7 @@ namespace sol { state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), state_view(unique_base::get()) { set_panic(panic); + sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler)); stack::luajit_exception_handler(unique_base::get()); } @@ -13210,6 +15197,61 @@ namespace sol { // end of sol/coroutine.hpp +// beginning of sol/variadic_results.hpp + +// beginning of sol/as_returns.hpp + +namespace sol { + template + struct as_returns_t { + T src; + }; + + template + auto as_returns(Source&& source) { + return as_returns_t>{ std::forward(source) }; + } + + namespace stack { + template + struct pusher> { + int push(lua_State* L, const as_returns_t& e) { + auto& src = detail::unwrap(e.src); + int p = 0; + for (const auto& i : src) { + p += stack::push(L, i); + } + return p; + } + }; + } // stack +} // sol + +// end of sol/as_returns.hpp + +namespace sol { + + struct variadic_results : public std::vector { + using std::vector::vector; + }; + + namespace stack { + template <> + struct pusher { + int push(lua_State* L, const variadic_results& e) { + int p = 0; + for (const auto& i : e) { + p += stack::push(L, i); + } + return p; + } + }; + } // stack + +} // sol + +// end of sol/variadic_results.hpp + #ifdef __GNUC__ #pragma GCC diagnostic pop #elif defined _MSC_VER @@ -13218,7 +15260,11 @@ namespace sol { #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); } }} +#if DO_CHECK +#define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } } +#else +#define check(expr) { CA_ASSUME(expr); } +#endif #endif #endif // Unreal Engine 4 Bullshit From 04acd2141b47b4eee1b0ba87beec05425ae8cf68 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 20 Jul 2017 22:01:54 +0000 Subject: [PATCH 4/4] Use sol 2.17.5 instead --- third_party/sol2/sol2/sol.hpp | 2362 +++++++++++---------------------- 1 file changed, 791 insertions(+), 1571 deletions(-) diff --git a/third_party/sol2/sol2/sol.hpp b/third_party/sol2/sol2/sol.hpp index 335c7852b..a349ea9d1 100644 --- a/third_party/sol2/sol2/sol.hpp +++ b/third_party/sol2/sol2/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2017-07-09 23:05:15.984374 UTC -// This header was generated with sol v2.18.0 (revision 2d65f6c) +// Generated 2017-06-13 20:34:08.313723 UTC +// This header was generated with sol v2.17.5 (revision 51a03b2) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -53,169 +53,8 @@ #elif defined _MSC_VER #pragma warning( push ) #pragma warning( disable : 4324 ) // structure was padded due to alignment specifier -#pragma warning( disable : 4503 ) // decorated name horse shit -#pragma warning( disable : 4702 ) // unreachable code #endif // g++ -// beginning of sol/forward.hpp - -// beginning of sol/feature_test.hpp - -#if (defined(__cplusplus) && __cplusplus == 201703L) || (defined(_MSC_VER) && _MSC_VER > 1900 && (defined(_HAS_CXX17) && _HAS_CXX17 == 1) || (_MSVC_LANG > 201402)) -#ifndef SOL_CXX17_FEATURES -#define SOL_CXX17_FEATURES 1 -#endif // C++17 features macro -#endif // C++17 features check - -#if defined(__cpp_noexcept_function_type) -#ifndef SOL_NOEXCEPT_FUNCTION_TYPE -#define SOL_NOEXCEPT_FUNCTION_TYPE 1 -#endif // noexcept is part of a function's type -#endif - -#if defined(_WIN32) || defined(_MSC_VER) -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // sol codecvt support -#elif defined(__GNUC__) -#if __GNUC__ >= 5 -#ifndef SOL_CODECVT_SUPPORT -#define SOL_CODECVT_SUPPORT 1 -#endif // codecvt support -#endif // g++ 5.x.x (MinGW too) -#else -#endif // Windows/VC++ vs. g++ vs Others - -#ifdef _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/feature_test.hpp - -namespace sol { - - class reference; - class stack_reference; - template - struct proxy; - template - class usertype; - template - class simple_usertype; - template - class basic_table_core; - template - using table_core = basic_table_core; - template - using stack_table_core = basic_table_core; - template - using basic_table = 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 - struct basic_environment; - using environment = basic_environment; - using stack_environment = basic_environment; - template - class basic_function; - template - class basic_protected_function; - using protected_function = basic_protected_function; - using stack_protected_function = basic_protected_function; - using unsafe_function = basic_function; - using safe_function = basic_protected_function; - using stack_unsafe_function = basic_function; - using stack_safe_function = basic_protected_function; -#ifdef SOL_SAFE_FUNCTIONS - using function = protected_function; - using stack_function = stack_protected_function; -#else - using function = unsafe_function; - using stack_function = stack_unsafe_function; -#endif - 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 variadic_results; - struct this_state; - struct this_environment; - template - struct light; - template - struct user; - template - struct as_args_t; - -} // sol - -// end of sol/forward.hpp - // beginning of sol/state.hpp // beginning of sol/state_view.hpp @@ -354,13 +193,12 @@ namespace sol { template using void_tuple_element_t = typename void_tuple_element::type; - template + template struct basic_traits { private: typedef std::conditional_t::value, int, T>& first_type; public: - static const bool is_noexcept = it_is_noexcept; 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); @@ -380,238 +218,123 @@ namespace sol { }; template::value> - struct fx_traits : basic_traits {}; + struct fx_traits : basic_traits {}; // Free Functions template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args..., ...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(*function_pointer_type)(Args..., ...); }; // Member Functions /* C-Style Variadics */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...); }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...); }; /* Const Volatile */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile; }; /* Member Function Qualifiers */ template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) && ; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) && ; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args...) const volatile &&; }; template - struct fx_traits : basic_traits { + struct fx_traits : basic_traits { typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; }; -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args...) noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args...) noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args..., ...) noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(*function_pointer_type)(Args..., ...) noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) noexcept; - }; - - /* Const Volatile */ - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) & noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) & noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const & noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const & noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile & noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile & noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) && noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) && noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const && noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const && noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args...) const volatile && noexcept; - }; - - template - struct fx_traits : basic_traits { - typedef R(T::* function_pointer_type)(Args..., ...) const volatile && noexcept; - }; - -#endif // noexcept is part of a function's type - template struct fx_traits : fx_traits::function_type, false> {}; @@ -625,7 +348,6 @@ namespace sol { typedef R Arg; typedef T object_type; using signature_type = R(T::*); - static const bool is_noexcept = false; static const bool is_member_function = false; static const std::size_t arity = 1; static const std::size_t free_arity = 2; @@ -640,7 +362,6 @@ namespace sol { template using arg_at = void_tuple_element_t; }; - } // meta_detail template @@ -664,9 +385,6 @@ namespace sol { #include #include #include -#ifdef SOL_CXX17_FEATURES -#include -#endif namespace sol { template @@ -915,42 +633,6 @@ namespace sol { static std::false_type test(...); }; - struct has_key_type_impl { - template, - typename V = typename U::key_type> - static std::true_type test(int); - - template - static std::false_type test(...); - }; - - struct has_mapped_type_impl { - template, - typename V = typename U::mapped_type> - static std::true_type test(int); - - template - static std::false_type test(...); - }; - - struct has_value_type_impl { - template, - typename V = typename U::value_type> - static std::true_type test(int); - - template - static std::false_type test(...); - }; - - struct has_iterator_impl { - template, - typename V = typename U::iterator> - 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, @@ -990,31 +672,8 @@ namespace sol { template struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; - template - struct has_key_type : decltype(meta_detail::has_key_type_impl::test(0)) {}; - - template - struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test(0)) {}; - - template - struct has_iterator : decltype(meta_detail::has_iterator_impl::test(0)) {}; - - template - struct has_value_type : decltype(meta_detail::has_value_type_impl::test(0)) {}; - template - struct is_associative : meta::all, has_mapped_type> {}; - - template - using is_string_constructible = any< - std::is_same, const char*> - , std::is_same, char> - , std::is_same, std::string> - , std::is_same, std::initializer_list> -#ifdef SOL_CXX17_FEATURES - , std::is_same, std::string_view> -#endif - >; + using is_string_constructible = any, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; template struct is_pair : std::false_type {}; @@ -1144,9 +803,7 @@ namespace sol { // end of sol/traits.hpp -// beginning of sol/function.hpp - -// beginning of sol/unsafe_function.hpp +// beginning of sol/object.hpp // beginning of sol/reference.hpp @@ -1162,13 +819,23 @@ namespace sol { #include #include #include -#ifdef SOL_USING_CXX_LUAJIT -#include -#endif // C++ LuaJIT ... whatever that means #else #include #endif // C++ Mangling for Lua +#if defined(_WIN32) || defined(_MSC_VER) +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // sol codecvt support +#elif defined(__GNUC__) +#if __GNUC__ >= 5 +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // codecvt support +#endif // g++ 5.x.x (MinGW too) +#else +#endif // Windows/VC++ vs. g++ vs Others + #ifdef LUAJIT_VERSION #ifndef SOL_LUAJIT #define SOL_LUAJIT @@ -1186,6 +853,61 @@ namespace sol { #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 @@ -1411,25 +1133,28 @@ inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const c #define lua_pushglobaltable(L) \ lua_pushvalue(L, LUA_GLOBALSINDEX) -void luaL_checkversion(lua_State *L); - -#if !defined(SOL_LUAJIT_VERSION) || SOL_LUAJIT_VERSION < 20100 -void lua_copy(lua_State *L, int from, int to); -lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); -lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); -const lua_Number *lua_version(lua_State *L); -void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); -void luaL_setmetatable(lua_State *L, const char *tname); -void *luaL_testudata(lua_State *L, int i, const char *tname); +#ifndef SOL_LUAJIT #define luaL_newlib(L, l) \ (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) -#endif // LuaJIT-2.1.0-beta3 added these compatibility functions +#else +#if SOL_LUAJIT_VERSION < 20100 +#define luaL_newlib(L, l) \ + (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) +#endif // LuaJIT-2.1.0-beta3 added this in itself +#endif // LuaJIT Compatibility + +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); @@ -1456,7 +1181,6 @@ inline int lua_absindex(lua_State *L, int i) { return i; } -#if !defined(SOL_LUAJIT_VERSION) || SOL_LUAJIT_VERSION < 20100 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"); @@ -1464,69 +1188,6 @@ inline void lua_copy(lua_State *L, int from, int to) { lua_replace(L, abs_to); } -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 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 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; -} - -/* -** 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 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; -} -#endif - inline void lua_rawgetp(lua_State *L, int i, const void *p) { int abs_i = lua_absindex(L, i); lua_pushlightuserdata(L, (void*)p); @@ -1541,6 +1202,30 @@ inline void lua_rawsetp(lua_State *L, int i, const void *p) { 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); @@ -1590,6 +1275,28 @@ inline void lua_setuservalue(lua_State *L, int i) { 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"); @@ -1705,6 +1412,14 @@ inline void luaL_traceback(lua_State *L, lua_State *L1, } #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)) @@ -1734,7 +1449,7 @@ inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { } else { char buf[1024]; -#if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) +#if defined(__GLIBC__) || defined(_POSIX_VERSION) strerror_r(en, buf, 1024); #else strerror_s(buf, 1024, en); @@ -1977,6 +1692,14 @@ 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 */ @@ -2128,51 +1851,28 @@ inline void luaL_pushresult(luaL_Buffer_52 *B) { // beginning of sol/in_place.hpp -#include - namespace sol { -#ifdef SOL_CXX17_FEATURES - using in_place_t = std::in_place_t; - constexpr std::in_place_t in_place{}; - constexpr std::in_place_t in_place_of{}; - - template using in_place_type_t = std::in_place_type_t; - template - constexpr std::in_place_type_t in_place_type{}; - - template using in_place_index_t = std::in_place_index_t; - template - constexpr in_place_index_t in_place_index{}; -#else namespace detail { - struct in_place_of_tag {}; + struct in_place_of {}; template struct in_place_of_i {}; template struct in_place_of_t {}; } // detail - struct in_place_tag { constexpr in_place_tag() = default; }; - - constexpr inline in_place_tag in_place (detail::in_place_of_tag) { return in_place_tag(); } + 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(); } + 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(); } + constexpr inline in_place_tag in_place(detail::in_place_of_i) { return in_place_tag(in_place_tag::init()); } - constexpr inline in_place_tag in_place_of(detail::in_place_of_tag) { return in_place_tag(); } - template - constexpr inline in_place_tag in_place_type (detail::in_place_of_t) { return in_place_tag(); } - template - constexpr inline in_place_tag in_place_index (detail::in_place_of_i) { return in_place_tag(); } - - using in_place_t = in_place_tag(&)(detail::in_place_of_tag); + 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); -#endif } // sol @@ -3279,14 +2979,8 @@ namespace sol { // beginning of sol/string_shim.hpp -#ifdef SOL_CXX17_FEATURES -#endif // C++17 features - namespace sol { namespace string_detail { -#ifdef SOL_CXX17_FEATURES - typedef std::string_view string_shim; -#else struct string_shim { std::size_t s; const char* p; @@ -3342,42 +3036,27 @@ namespace sol { return !(*this == r); } }; -#endif // C++17 } } // end of sol/string_shim.hpp #include -#ifdef SOL_CXX17_FEATURES -#include -#endif // C++17 namespace sol { namespace detail { -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - typedef int(*lua_CFunction_noexcept) (lua_State *L) noexcept; -#endif // noexcept function type for lua_CFunction - #ifdef SOL_NO_EXCEPTIONS template - int static_trampoline(lua_State* L) noexcept { + int static_trampoline(lua_State* L) { return f(L); } -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - template - int static_trampoline_noexcept(lua_State* L) noexcept { - return f(L); - } -#endif - template - int trampoline(lua_State* L, Fx&& f, Args&&... args) noexcept { + 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) noexcept { + inline int c_trampoline(lua_State* L, lua_CFunction f) { return trampoline(L, f); } #else @@ -3394,35 +3073,15 @@ namespace sol { } #if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) catch (...) { + std::exception_ptr eptr = std::current_exception(); lua_pushstring(L, "caught (...) exception"); } #endif return lua_error(L); } -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE -#if 0 - template - int static_trampoline(lua_State* L) noexcept { -#else - template - int static_trampoline_noexcept(lua_State* L) noexcept { -#endif // impossible - return f(L); - } - -#else - template - int static_trampoline_noexcept(lua_State* L) noexcept { - return f(L); - } -#endif // noexcept lua_CFunction type - template int trampoline(lua_State* L, Fx&& f, Args&&... args) { - if (meta::bind_traits>::is_noexcept) { - return f(L, std::forward(args)...); - } try { return f(L, std::forward(args)...); } @@ -3445,21 +3104,6 @@ namespace sol { } #endif // Exceptions vs. No Exceptions - template - inline int typed_static_trampoline_raw(std::true_type, lua_State* L) { - return static_trampoline_noexcept(L); - } - - template - inline int typed_static_trampoline_raw(std::false_type, lua_State* L) { - return static_trampoline(L); - } - - template - inline int typed_static_trampoline(lua_State* L) { - return typed_static_trampoline_raw(std::integral_constant::is_noexcept>(), L); - } - template struct unique_usertype {}; @@ -3721,11 +3365,6 @@ namespace sol { return as_table_t(std::forward(container)); } - template - nested as_nested(T&& container) { - return as_nested(std::forward(container)); - } - struct this_state { lua_State* L; operator lua_State* () const { @@ -3972,6 +3611,64 @@ namespace sol { 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; + template + using basic_table = 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 + struct basic_environment; + using environment = basic_environment; + using stack_environment = basic_environment; + template + class basic_function; + template + class basic_protected_function; + using protected_function = basic_protected_function; + using stack_protected_function = basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; +#ifdef SOL_SAFE_FUNCTIONS + using function = protected_function; + using stack_function = stack_protected_function; +#else + using function = unsafe_function; + using stack_function = stack_unsafe_function; +#endif + 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; + struct this_environment; + namespace detail { template struct lua_type_of : std::integral_constant {}; @@ -4021,6 +3718,9 @@ namespace sol { template <> struct lua_type_of : std::integral_constant {}; + template <> + struct lua_type_of : std::integral_constant {}; + template <> struct lua_type_of : std::integral_constant {}; @@ -4135,29 +3835,6 @@ namespace sol { template struct lua_type_of::value>> : std::integral_constant {}; - template <> - struct lua_type_of : std::integral_constant {}; - -#ifdef SOL_CXX17_FEATURES - 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 {}; -#else - template <> - struct lua_type_of : std::integral_constant {}; -#endif // C++ 17 (or not) features - template struct is_container : std::false_type {}; @@ -4173,24 +3850,12 @@ namespace sol { template <> struct is_container : std::false_type {}; -#ifdef SOL_CXX17_FEATURES - template <> - struct is_container : std::false_type {}; - - template <> - struct is_container : std::false_type {}; - - template <> - struct is_container : std::false_type {}; - - template <> - struct is_container : std::false_type {}; - -#endif // C++ 17 - template struct is_container>::value>> : std::true_type {}; + template <> + struct lua_type_of : std::integral_constant {}; + template class V, typename... Args> struct accumulate : std::integral_constant {}; @@ -4782,26 +4447,25 @@ namespace sol { template struct as_value_tag {}; - using unique_destructor = void(*)(void*); + 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); - unique_destructor& dx = *static_cast(static_cast(pointerpointer + 1)); + special_destruct_func& dx = *static_cast(static_cast(pointerpointer + 1)); (dx)(memory); return 0; } - template - inline void usertype_unique_alloc_destroy(void* memory) { - T** pointerpointer = static_cast(memory); - unique_destructor* dx = static_cast(static_cast(pointerpointer + 1)); - Real* target = static_cast(static_cast(dx + 1)); - std::allocator alloc; - alloc.destroy(target); - } - template inline int user_alloc_destroy(lua_State* L) { void* rawdata = lua_touserdata(L, 1); @@ -5431,8 +5095,7 @@ namespace sol { // end of sol/inheritance.hpp -#ifdef SOL_CXX17_FEATURES -#endif // C++17 +#include namespace sol { namespace stack { @@ -5834,16 +5497,8 @@ namespace sol { return true; } int metatableindex = lua_gettop(L); - if (stack_detail::check_metatable>(L, metatableindex)) { - void* memory = lua_touserdata(L, index); - T** pointerpointer = static_cast(memory); - detail::unique_destructor& pdx = *static_cast(static_cast(pointerpointer + 1)); - bool success = &detail::usertype_unique_alloc_destroy == pdx; - if (!success) { - handler(L, index, type::userdata, indextype); - } - return success; - } + if (stack_detail::check_metatable>(L, metatableindex)) + return true; lua_pop(L, 1); handler(L, index, type::userdata, indextype); return false; @@ -5890,40 +5545,6 @@ namespace sol { return stack::check(L, index, no_panic, tracking); } }; - -#ifdef SOL_CXX17_FEATURES - template - struct checker, type::poly, C> { - typedef std::variant V; - typedef std::variant_size V_size; - typedef std::integral_constant V_is_empty; - - template - static bool is_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { - if (V_is_empty::value && lua_isnone(L, index)) { - return true; - } - tracking.use(1); - handler(L, index, type::poly, type_of(L, index)); - return false; - } - - template - static bool is_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { - typedef std::variant_alternative_t T; - if (stack::check(L, index, no_panic, tracking)) { - return true; - } - return is_one(std::integral_constant(), L, index, std::forward(handler), tracking); - } - - template - static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return is_one(std::integral_constant(), L, index, std::forward(handler), tracking); - } - }; -#endif // C++17 - } // stack } // sol @@ -5955,9 +5576,7 @@ namespace sol { #ifdef SOL_CODECVT_SUPPORT #include -#endif // codecvt header support -#ifdef SOL_CXX17_FEATURES -#endif // C++17 +#endif namespace sol { namespace stack { @@ -6067,7 +5686,7 @@ namespace sol { typedef typename P::second_type V; return get(types(), L, index, tracking); } - + template static T get(types, lua_State* L, int relindex, record& tracking) { tracking.use(1); @@ -6097,7 +5716,7 @@ namespace sol { return g.get(L, index, tracking); } }; - + template struct getter, std::enable_if_t, meta::neg>>>::value>> { static T get(lua_State* L, int index, record& tracking) { @@ -6192,7 +5811,17 @@ namespace sol { tracking.use(1); std::size_t len; auto str = lua_tolstring(L, index, &len); - return std::string(str, 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); } }; @@ -6200,11 +5829,10 @@ namespace sol { struct getter { static const char* get(lua_State* L, int index, record& tracking) { tracking.use(1); - size_t sz; - return lua_tolstring(L, index, &sz); + return lua_tostring(L, index); } }; - + template<> struct getter { static char get(lua_State* L, int index, record& tracking) { @@ -6232,7 +5860,7 @@ namespace sol { // 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); + uint8_t* b = reinterpret_cast(&c); std::swap(b[0], b[1]); } #endif @@ -6413,7 +6041,7 @@ namespace sol { T* obj = static_cast(udata); return obj; } - + static T& get(lua_State* L, int index, record& tracking) { return *get_no_lua_nil(L, index, tracking); } @@ -6482,31 +6110,31 @@ namespace sol { static Real& get(lua_State* L, int index, record& tracking) { tracking.use(1); P** pref = static_cast(lua_touserdata(L, index)); - detail::unique_destructor* fx = static_cast(static_cast(pref + 1)); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); Real* mem = static_cast(static_cast(fx + 1)); return *mem; } }; - template - struct getter> { - typedef std::tuple(nullptr, 0))...> R; - - template - static R apply(std::index_sequence<>, lua_State*, int, record&, Args&&... args) { + 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)... }; + return R{std::forward(args)...}; } - - template - static R apply(std::index_sequence, lua_State* L, int index, record& tracking, Args&&... 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)); + 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); + return apply(std::make_index_sequence(), L, index, tracking); } }; @@ -6516,65 +6144,6 @@ namespace sol { return std::pair(L, index)), decltype(stack::get(L, index))>{stack::get(L, index, tracking), stack::get(L, index + tracking.used, tracking)}; } }; - -#ifdef SOL_CXX17_FEATURES - template<> - struct getter { - static std::string_view get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t sz; - const char* str = lua_tolstring(L, index, &sz); - return std::string_view(str, sz); - } - }; - - template - struct getter> { - typedef std::variant V; - typedef std::variant_size V_size; - typedef std::integral_constant V_is_empty; - - static V get_empty(std::true_type, lua_State* L, int index, record& tracking) { - return V(); - } - - static V get_empty(std::false_type, lua_State* L, int index, record& tracking) { - typedef std::variant_alternative_t<0, V> T; - // This should never be reached... - // please check your code and understand what you did to bring yourself here - std::abort(); - return V(std::in_place_index<0>, stack::get(L, index)); - } - - static V get_one(std::integral_constant, lua_State* L, int index, record& tracking) { - return get_empty(V_is_empty(), L, index, tracking); - } - - template - static V get_one(std::integral_constant, lua_State* L, int index, record& tracking) { - typedef std::variant_alternative_t T; - if (stack::check(L, index, no_panic, tracking)) { - return V(std::in_place_index, stack::get(L, index)); - } - return get_one(std::integral_constant(), L, index, tracking); - } - - static V get(lua_State* L, int index, record& tracking) { - return get_one(std::integral_constant(), L, index, tracking); - } - }; -#else - 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); - } - }; -#endif // C++17-wave - } // stack } // sol @@ -6663,48 +6232,6 @@ namespace sol { return check_get(L, index, no_panic, tracking); } }; - -#ifdef SOL_CXX17_FEATURES - template - struct check_getter> { - typedef std::variant V; - typedef std::variant_size V_size; - typedef std::integral_constant V_is_empty; - - template - static optional get_empty(std::true_type, lua_State* L, int index, Handler&& handler, record& tracking) { - return nullopt; - } - - template - static optional get_empty(std::false_type, lua_State* L, int index, Handler&& handler, record& tracking) { - typedef std::variant_alternative_t<0, V> T; - // This should never be reached... - // please check your code and understand what you did to bring yourself here - handler(L, index, type::poly, type_of(L, index)); - return nullopt; - } - - template - static optional get_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { - return get_empty(V_is_empty(), L, index, std::forward(handler), tracking); - } - - template - static optional get_one(std::integral_constant, lua_State* L, int index, Handler&& handler, record& tracking) { - typedef std::variant_alternative_t T; - if (stack::check(L, index, no_panic, tracking)) { - return V(std::in_place_index, stack::get(L, index)); - } - return get_one(std::integral_constant(), L, index, std::forward(handler), tracking); - } - - template - static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { - return get_one(std::integral_constant(), L, index, std::forward(handler), tracking); - } - }; -#endif // C++17 } // stack } // sol @@ -6822,8 +6349,6 @@ namespace sol { #ifdef SOL_CODECVT_SUPPORT #endif -#ifdef SOL_CXX17_FEATURES -#endif // C++17 namespace sol { namespace stack { @@ -6937,9 +6462,6 @@ namespace sol { template >> = meta::enabler> static int push(lua_State* L, Arg&& arg) { - if (unique_usertype_traits::is_null(arg)) { - return stack::push(L, lua_nil); - } return push_deep(L, std::forward(arg)); } @@ -6950,10 +6472,10 @@ namespace sol { template static int push_deep(lua_State* L, Args&&... args) { - P** pref = static_cast(lua_newuserdata(L, sizeof(P*) + sizeof(detail::unique_destructor) + sizeof(Real))); - detail::unique_destructor* fx = static_cast(static_cast(pref + 1)); + 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::usertype_unique_alloc_destroy; + *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) { @@ -7107,23 +6629,6 @@ namespace sol { return 1; } }; -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - template<> - struct pusher> { - static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { - lua_pushcclosure(L, func, n); - return 1; - } - }; - - template<> - struct pusher { - static int push(lua_State* L, detail::lua_CFunction_noexcept func, int n = 0) { - lua_pushcclosure(L, func, n); - return 1; - } - }; -#endif // noexcept function type template<> struct pusher { @@ -7497,7 +7002,7 @@ namespace sol { if (t == nullopt) { return stack::push(L, nullopt); } - return stack::push(L, static_cast::value, O&, O&&>>(t.value())); + return stack::push(L, t.value()); } }; @@ -7529,63 +7034,6 @@ namespace sol { return 1; } }; - -#ifdef SOL_CXX17_FEATURES - template <> - struct pusher { - static int push(lua_State* L, const std::string_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - }; -#ifdef SOL_CODECVT_SUPPORT - template <> - struct pusher { - static int push(lua_State* L, const std::wstring_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - }; - - template <> - struct pusher { - static int push(lua_State* L, const std::u16string_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - }; - - template <> - struct pusher { - static int push(lua_State* L, const std::u32string_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - }; -#endif // codecvt header support - - namespace stack_detail { - - struct push_function { - lua_State* L; - - push_function(lua_State* L) : L(L) {} - - template - int operator()(T&& value) const { - return stack::push(L, std::forward(value)); - } - }; - - } // stack_detail - - template - struct pusher> { - static int push(lua_State* L, const std::variant& v) { - return std::visit(stack_detail::push_function(L), v); - } - - static int push(lua_State* L, std::variant&& v) { - return std::visit(stack_detail::push_function(L), std::move(v)); - } - }; -#endif } // stack } // sol @@ -8100,6 +7548,175 @@ namespace sol { // end of sol/stack.hpp +// beginning of sol/object_base.hpp + +namespace sol { + + template + class basic_object_base : 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 { + int r = base_t::registry_index(); + if (r == LUA_REFNIL) + return meta::any_same, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; + if (r == LUA_NOREF) + return false; + auto pp = stack::push_pop(*this); + return stack::check(base_t::lua_state(), -1, no_panic); + } + + public: + basic_object_base() noexcept = default; + basic_object_base(const basic_object_base&) = default; + basic_object_base(basic_object_base&&) = default; + basic_object_base& operator=(const basic_object_base&) = default; + basic_object_base& operator=(basic_object_base&&) = default; + template , basic_object_base>>> = meta::enabler> + basic_object_base(T&& arg, Args&&... args) : base_t(std::forward(arg), std::forward(args)...) { } + + template + decltype(auto) as() const { + return as_stack(std::is_same()); + } + + template + bool is() const { + return is_stack(std::is_same()); + } + }; +} // sol + +// end of sol/object_base.hpp + +// beginning of sol/userdata.hpp + +namespace sol { + template + class basic_userdata : public basic_table { + typedef basic_table 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()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} + basic_userdata(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_userdata(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, index, type_panic); +#endif // Safety + } + }; + + template + class basic_lightuserdata : public basic_object_base { + typedef basic_object_base 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_lightuserdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } + basic_lightuserdata(const basic_lightuserdata&) = default; + basic_lightuserdata(basic_lightuserdata&&) = default; + basic_lightuserdata& operator=(const basic_lightuserdata&) = default; + basic_lightuserdata& operator=(basic_lightuserdata&&) = default; + basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} + basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, index, type_panic); +#endif // Safety + } + }; + +} // sol + +// end of sol/userdata.hpp + +// beginning of sol/as_args.hpp + +namespace sol { + template + struct to_args_t { + T src; + }; + + template + auto as_args(Source&& source) { + return to_args_t{ std::forward(source) }; + } + + namespace stack { + template + struct pusher> { + int push(lua_State* L, const to_args_t& e) { + int p = 0; + for (const auto& i : e.src) { + p += stack::push(L, i); + } + return p; + } + }; + } +} // sol + +// end of sol/as_args.hpp + +// beginning of sol/variadic_args.hpp + +// beginning of sol/stack_proxy.hpp + +// beginning of sol/function.hpp + // beginning of sol/function_result.hpp // beginning of sol/proxy_base.hpp @@ -8201,7 +7818,7 @@ namespace sol { template struct wrapper { - typedef lua_bind_traits> traits_type; + 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; @@ -8220,8 +7837,8 @@ namespace sol { }; template - struct wrapper>>::value>> { - typedef lua_bind_traits>> traits_type; + 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; @@ -8254,7 +7871,7 @@ namespace sol { template struct wrapper>::value>> { - typedef lua_bind_traits> traits_type; + 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; @@ -8406,85 +8023,6 @@ namespace sol { }; -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE //noexcept has become a part of a function's type - - 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 { - - }; - -#endif // noexcept is part of a function's type - } // sol // end of sol/wrapper.hpp @@ -8854,14 +8392,6 @@ namespace sol { return f(L); } }; -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - template - struct agnostic_lua_call_wrapper { - static int call(lua_State* L, detail::lua_CFunction_noexcept f) { - return f(L); - } - }; -#endif // noexcept function types template struct agnostic_lua_call_wrapper { @@ -9345,7 +8875,7 @@ namespace sol { } template - int call_wrapper_entry(lua_State* L) noexcept(meta::bind_traits::is_noexcept) { + int call_wrapper_entry(lua_State* L) { return call_wrapper_function(std::is_member_function_pointer>(), L); } @@ -9358,30 +8888,15 @@ namespace sol { } }; - template - inline int c_call_raw(std::true_type, lua_State* L) { - return fx(L); - } - - template - inline int c_call_raw(std::false_type, lua_State* L) { -#ifdef __clang__ - return detail::trampoline(L, function_detail::call_wrapper_entry); -#else - return detail::typed_static_trampoline), (&function_detail::call_wrapper_entry)>(L); -#endif // fuck you clang :c - } - } // function_detail template inline int c_call(lua_State* L) { - typedef meta::unqualified_t Fu; - return function_detail::c_call_raw(std::integral_constant::value -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - || std::is_same::value -#endif - >(), 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 @@ -9414,16 +8929,16 @@ namespace sol { template struct upvalue_free_function { typedef std::remove_pointer_t> function_type; - typedef meta::bind_traits traits_type; + typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { + 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::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9436,7 +8951,7 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { + 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 @@ -9450,7 +8965,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9463,7 +8978,7 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { + 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 @@ -9484,7 +8999,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9497,7 +9012,7 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { + 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 @@ -9516,7 +9031,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9529,7 +9044,7 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) noexcept(traits_type::is_noexcept) { + 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); @@ -9538,7 +9053,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9549,8 +9064,9 @@ namespace sol { 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) noexcept(false) { + 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); @@ -9566,7 +9082,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9579,7 +9095,7 @@ namespace sol { typedef std::remove_pointer_t> function_type; typedef lua_bind_traits traits_type; - static int real_call(lua_State* L) noexcept(false) { + 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); @@ -9593,7 +9109,7 @@ namespace sol { } static int call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_call)>(L); } int operator()(lua_State* L) { @@ -9611,11 +9127,11 @@ namespace sol { namespace function_detail { template struct functor_function { - typedef std::decay_t> function_type; - function_type fx; + typedef meta::unwrapped_t> Function; + Function fx; template - functor_function(function_type f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} + 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); @@ -10025,15 +9541,9 @@ namespace sol { stack::push(L, f); } -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - static void select_function(std::true_type, lua_State* L, detail::lua_CFunction_noexcept f) { - stack::push(L, f); - } -#endif // noexcept function type - template >, std::is_base_of>>> = meta::enabler> static void select(lua_State* L, Fx&& fx, Args&&... args) { - select_function(std::is_function>>(), L, std::forward(fx), std::forward(args)...); + select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); } template >, std::is_base_of>>> = meta::enabler> @@ -10095,15 +9605,7 @@ namespace sol { }; template - struct pusher, - meta::neg>, - meta::neg>> -#ifdef SOL_NOEXCEPT_FUNCTION_TYPE - , meta::neg>, - meta::neg>> -#endif // noexcept function types - >::value>> { + struct pusher, meta::neg>, meta::neg>>>::value>> { template static int push(lua_State* L, F&& f) { return pusher>{}.push(L, std::forward(f)); @@ -10349,9 +9851,51 @@ namespace sol { 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::lua_nil) { + return nullptr; + } + return get_std_func(return_types(), args_lists(), L, index); + } + }; + } // stack } // sol -// end of sol/unsafe_function.hpp +// end of sol/function.hpp // beginning of sol/protected_function.hpp @@ -10629,411 +10173,6 @@ namespace sol { // end of sol/protected_function.hpp -namespace sol { - - 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::lua_nil) { - return nullptr; - } - return get_std_func(return_types(), args_lists(), L, index); - } - }; - } // stack - -} // sol - -// end of sol/function.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&& k) : tbl(table), key(std::forward(k)) {} - - 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; - optional option = get>(); - if (option) { - return static_cast(option.value()); - } - return static_cast(std::forward(otherwise)); - } - - template - decltype(auto) get_or(D&& otherwise) const { - 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 { - auto pp = 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; - } - - type get_type() const { - type t = type::none; - auto pp = stack::push_pop(tbl); - auto p = stack::probe_get_field, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); - if (p) { - t = type_of(tbl.lua_state(), -1); - } - lua_pop(tbl.lua_state(), p.levels); - return t; - } - }; - - template - inline bool operator==(T&& left, const proxy& right) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator==(const proxy& right, T&& left) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator!=(T&& left, const proxy& right) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator!=(const proxy& right, T&& left) { - typedef decltype(stack::get(nullptr, 0)) U; - return right.template get>() == left; - } - - template - inline bool operator==(lua_nil_t, const proxy& right) { - return !right.valid(); - } - - template - inline bool operator==(const proxy& right, lua_nil_t) { - return !right.valid(); - } - - template - inline bool operator!=(lua_nil_t, const proxy& right) { - return right.valid(); - } - - template - inline bool operator!=(const proxy& right, lua_nil_t) { - return right.valid(); - } - - namespace stack { - template - struct pusher> { - static int push(lua_State* L, const proxy& p) { - sol::reference r = p; - return r.push(L); - } - }; - } // stack -} // sol - -// end of sol/proxy.hpp - -// beginning of sol/usertype.hpp - -// beginning of sol/usertype_metatable.hpp - -// beginning of sol/deprecate.hpp - -#ifndef SOL_DEPRECATED - #ifdef _MSC_VER - #define SOL_DEPRECATED __declspec(deprecated) - #elif __GNUC__ - #define SOL_DEPRECATED __attribute__((deprecated)) - #else - #define SOL_DEPRECATED [[deprecated]] - #endif // compilers -#endif // SOL_DEPRECATED - -namespace sol { - namespace detail { - template - struct SOL_DEPRECATED deprecate_type { - using type = T; - }; - } // detail -} // sol - -// end of sol/deprecate.hpp - -// beginning of sol/object.hpp - -// beginning of sol/object_base.hpp - -namespace sol { - - template - class basic_object_base : 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 { - int r = base_t::registry_index(); - if (r == LUA_REFNIL) - return meta::any_same, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; - if (r == LUA_NOREF) - return false; - auto pp = stack::push_pop(*this); - return stack::check(base_t::lua_state(), -1, no_panic); - } - - public: - basic_object_base() noexcept = default; - basic_object_base(const basic_object_base&) = default; - basic_object_base(basic_object_base&&) = default; - basic_object_base& operator=(const basic_object_base&) = default; - basic_object_base& operator=(basic_object_base&&) = default; - template , basic_object_base>>> = meta::enabler> - basic_object_base(T&& arg, Args&&... args) : base_t(std::forward(arg), std::forward(args)...) { } - - template - decltype(auto) as() const { - return as_stack(std::is_same()); - } - - template - bool is() const { - return is_stack(std::is_same()); - } - }; -} // sol - -// end of sol/object_base.hpp - -// beginning of sol/userdata.hpp - -namespace sol { - template - class basic_userdata : public basic_table { - typedef basic_table 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()) {} - template >>, meta::neg, ref_index>>> = meta::enabler> - basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} - basic_userdata(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check(L, index, type_panic); -#endif // Safety - } - basic_userdata(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check(L, index, type_panic); -#endif // Safety - } - }; - - template - class basic_lightuserdata : public basic_object_base { - typedef basic_object_base 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_lightuserdata>::value) { - auto pp = stack::push_pop(*this); - type_assert(base_t::lua_state(), -1, type::lightuserdata); - } -#endif // Safety - } - basic_lightuserdata(const basic_lightuserdata&) = default; - basic_lightuserdata(basic_lightuserdata&&) = default; - basic_lightuserdata& operator=(const basic_lightuserdata&) = default; - basic_lightuserdata& operator=(basic_lightuserdata&&) = default; - basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} - basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} - template >>, meta::neg, ref_index>>> = meta::enabler> - basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} - basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - stack::check(L, index, type_panic); -#endif // Safety - } - basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { -#ifdef SOL_CHECK_ARGUMENTS - auto pp = stack::push_pop(*this); - stack::check(L, index, type_panic); -#endif // Safety - } - }; - -} // sol - -// end of sol/userdata.hpp - -// beginning of sol/as_args.hpp - -namespace sol { - template - struct as_args_t { - T src; - }; - - template - auto as_args(Source&& source) { - return as_args_t{ std::forward(source) }; - } - - namespace stack { - template - struct pusher> { - int push(lua_State* L, const as_args_t& e) { - int p = 0; - for (const auto& i : e.src) { - p += stack::push(L, i); - } - return p; - } - }; - } // stack -} // sol - -// end of sol/as_args.hpp - -// beginning of sol/variadic_args.hpp - -// beginning of sol/stack_proxy.hpp - namespace sol { struct stack_proxy : public proxy_base { private: @@ -11049,10 +10188,6 @@ namespace sol { return stack::get(L, stack_index()); } - type get_type() const noexcept { - return type_of(lua_state(), stack_index()); - } - int push() const { return push(L); } @@ -11155,27 +10290,17 @@ namespace sol { stack_proxy sp; va_iterator() : L(nullptr), index((std::numeric_limits::max)()), stacktop((std::numeric_limits::max)()) {} - va_iterator(const va_iterator& r) : L(r.L), index(r.index), stacktop(r.stacktop) {} va_iterator(lua_State* luastate, int idx, int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {} reference operator*() { return stack_proxy(L, index); } - reference operator*() const { - return stack_proxy(L, index); - } - pointer operator->() { sp = stack_proxy(L, index); return &sp; } - pointer operator->() const { - const_cast(sp) = stack_proxy(L, index); - return &sp; - } - va_iterator& operator++ () { ++index; return *this; @@ -11218,7 +10343,7 @@ namespace sol { return r; } - reference operator[](difference_type idx) const { + reference operator[](difference_type idx) { return stack_proxy(L, index + static_cast(idx)); } @@ -11277,7 +10402,6 @@ namespace sol { variadic_args() = default; variadic_args(lua_State* luastate, int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {} - variadic_args(lua_State* luastate, int stackindex, int lastindex) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lastindex) {} variadic_args(const variadic_args&) = default; variadic_args& operator=(const variadic_args&) = default; variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { @@ -11336,10 +10460,6 @@ namespace sol { return stack::get(L, index + static_cast(start)); } - type get_type(difference_type start = 0) const noexcept { - return type_of(L, index + static_cast(start)); - } - stack_proxy operator[](difference_type start) const { return stack_proxy(L, index + static_cast(start)); } @@ -11347,7 +10467,6 @@ namespace sol { lua_State* lua_state() const { return L; }; int stack_index() const { return index; }; int leftover_count() const { return stacktop - (index - 1); } - std::size_t size() const { return static_cast(leftover_count()); } int top() const { return stacktop; } }; @@ -11421,11 +10540,9 @@ namespace sol { basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} basic_object(lua_State* L, ref_index index) noexcept : base_t(L, index) {} template - 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)...)) {} + 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_type, std::forward(arg), std::forward(args)...) {} + basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place, std::forward(arg), std::forward(args)...) {} basic_object& operator=(const basic_object&) = default; basic_object& operator=(basic_object&&) = default; basic_object& operator=(const base_type& b) { base_t::operator=(b); return *this; } @@ -11449,6 +10566,183 @@ namespace 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&& k) : tbl(table), key(std::forward(k)) {} + + 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; + optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + 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 { + auto pp = 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) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator==(const proxy& right, T&& left) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator!=(T&& left, const proxy& right) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator!=(const proxy& right, T&& left) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator==(lua_nil_t, const proxy& right) { + return !right.valid(); + } + + template + inline bool operator==(const proxy& right, lua_nil_t) { + return !right.valid(); + } + + template + inline bool operator!=(lua_nil_t, const proxy& right) { + return right.valid(); + } + + template + inline bool operator!=(const proxy& right, lua_nil_t) { + return right.valid(); + } + + namespace stack { + template + struct pusher> { + static int push(lua_State* L, const proxy& p) { + sol::reference r = p; + return r.push(L); + } + }; + } // stack +} // sol + +// end of sol/proxy.hpp + +// beginning of sol/usertype.hpp + +// beginning of sol/usertype_metatable.hpp + +// beginning of sol/deprecate.hpp + +#ifndef SOL_DEPRECATED + #ifdef _MSC_VER + #define SOL_DEPRECATED __declspec(deprecated) + #elif __GNUC__ + #define SOL_DEPRECATED __attribute__((deprecated)) + #else + #define SOL_DEPRECATED [[deprecated]] + #endif // compilers +#endif // SOL_DEPRECATED + +namespace sol { + namespace detail { + template + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; + } // detail +} // sol + +// end of sol/deprecate.hpp + #include #include @@ -11630,12 +10924,12 @@ namespace sol { template inline std::string make_string(Arg&& arg) { string_detail::string_shim s = make_shim(arg); - return std::string(s.data(), s.size()); + 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)).data(), f }; + luaL_Reg l{ make_shim(std::forward(n)).c_str(), f }; return l; } @@ -11668,7 +10962,7 @@ namespace sol { #if 0//def SOL_SAFE_USERTYPE auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); - return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); + 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 if (is_toplevel(L)) { if (lua_getmetatable(L, 1) == 1) { @@ -11684,7 +10978,7 @@ namespace sol { else { auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); - return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data()); + 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()); } } @@ -12091,20 +11385,20 @@ namespace sol { template static int call(lua_State* L) { - return detail::typed_static_trampoline), (&real_call)>(L); + return detail::static_trampoline<(&real_call)>(L); } template static int call_with(lua_State* L) { - return detail::typed_static_trampoline), (&real_call_with)>(L); + return detail::static_trampoline<(&real_call_with)>(L); } static int index_call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_index_call)>(L); } static int new_index_call(lua_State* L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_new_index_call)>(L); } virtual int push_um(lua_State* L) override { @@ -12164,8 +11458,8 @@ namespace sol { bool hasdestructor = !value_table.empty() && to_string(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 }; } - unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct }; // Now use um const bool& mustindex = umc.mustindex; @@ -12304,7 +11598,7 @@ namespace sol { } } string_detail::string_shim accessor = stack::get(L, keyidx); - std::string accessorkey = accessor.data(); + std::string accessorkey = accessor.c_str(); auto vit = variables.find(accessorkey); if (vit != variables.cend()) { auto& varwrap = *(vit->second); @@ -12390,7 +11684,7 @@ namespace sol { #if defined(__clang__) return detail::trampoline(L, &simple_real_index_call); #else - return detail::typed_static_trampoline), (&simple_real_index_call)>(L); + return detail::static_trampoline<(&simple_real_index_call)>(L); #endif } @@ -12399,7 +11693,7 @@ namespace sol { #if defined(__clang__) return detail::trampoline(L, &simple_real_new_index_call); #else - return detail::typed_static_trampoline), (&simple_real_new_index_call)>(L); + return detail::static_trampoline<(&simple_real_new_index_call)>(L); #endif } } @@ -12501,7 +11795,7 @@ namespace sol { template void add(lua_State* L, N&& n, constructor_wrapper c) { - object o(L, in_place_type>>, std::move(c)); + object o(L, in_place>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -12511,7 +11805,7 @@ namespace sol { template void add(lua_State* L, N&& n, constructor_list c) { - object o(L, in_place_type>>, std::move(c)); + object o(L, in_place>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -12521,7 +11815,7 @@ namespace sol { template void add(lua_State* L, N&& n, destructor_wrapper c) { - object o(L, in_place_type>>, std::move(c)); + object o(L, in_place>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -12531,7 +11825,7 @@ namespace sol { template void add(lua_State* L, N&& n, destructor_wrapper c) { - object o(L, in_place_type>>, std::move(c)); + object o(L, in_place>>, std::move(c)); if (std::is_same, call_construction>::value) { callconstructfunc = std::move(o); return; @@ -12909,7 +12203,7 @@ namespace sol { template struct container_usertype_metatable { - typedef meta::is_associative>> is_associative; + typedef meta::has_key_value_pair> is_associative; typedef meta::unqualified_t T; typedef typename T::iterator I; typedef std::conditional_t> KV; @@ -12944,25 +12238,6 @@ namespace sol { #endif // Safe getting with error } - static int delegate_call(lua_State* L) { - static std::unordered_map calls{ - { "add", &real_add_call }, - { "insert", &real_insert_call }, - { "clear", &real_clear_call }, - { "find", &real_find_call }, - { "get", &real_get_call } - }; - auto maybename = stack::check_get(L, 2); - if (maybename) { - auto& name = *maybename; - auto it = calls.find(name); - if (it != calls.cend()) { - return stack::push(L, it->second); - } - } - return stack::push(L, lua_nil); - } - static int real_index_call_associative(std::true_type, lua_State* L) { auto k = stack::check_get(L, 2); if (k) { @@ -12974,7 +12249,25 @@ namespace sol { return stack::stack_detail::push_reference(L, v.second); } } - return delegate_call(L); + else { + auto maybename = stack::check_get(L, 2); + if (maybename) { + auto& name = *maybename; + if (name == "add") { + return stack::push(L, &add_call); + } + else if (name == "insert") { + return stack::push(L, &insert_call); + } + else if (name == "clear") { + return stack::push(L, &clear_call); + } + else if (name == "find") { + return stack::push(L, &find_call); + } + } + } + return stack::push(L, lua_nil); } static int real_index_call_associative(std::false_type, lua_State* L) { @@ -12991,17 +12284,32 @@ namespace sol { std::advance(it, k); return stack::stack_detail::push_reference(L, *it); } - return delegate_call(L); + else { + auto maybename = stack::check_get(L, 2); + if (maybename) { + auto& name = *maybename; + if (name == "add") { + return stack::push(L, &add_call); + } + else if (name == "insert") { + return stack::push(L, &insert_call); + } + else if (name == "clear") { + return stack::push(L, &clear_call); + } + else if (name == "find") { + return stack::push(L, &find_call); + } + } + } + + return stack::push(L, lua_nil); } static int real_index_call(lua_State* L) { return real_index_call_associative(is_associative(), L); } - static int real_get_call(lua_State* L) { - return real_index_call_associative(is_associative(), L); - } - static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) { return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); } @@ -13010,12 +12318,12 @@ namespace sol { return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); } - static int real_new_index_call_fixed(std::true_type, lua_State* L) { + static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { auto& src = get_src(L); #ifdef SOL_CHECK_ARGUMENTS auto maybek = stack::check_get(L, 2); if (!maybek) { - return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); + return luaL_error(L, "sol: improper key of type %s to a %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); } K& k = *maybek; #else @@ -13033,33 +12341,6 @@ namespace sol { return 0; } - static int real_new_index_call_fixed(std::false_type, lua_State* L) { - auto& src = get_src(L); -#ifdef SOL_CHECK_ARGUMENTS - auto maybek = stack::check_get(L, 2); - if (!maybek) { - return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); - } - K& k = *maybek; -#else - K k = stack::get(L, 2); -#endif - using std::end; - auto it = detail::find(src, k); - if (it != end(src)) { - auto& v = *it; - v.second = stack::get(L, 3); - } - else { - return luaL_error(L, "sol: cannot insert key of type %s to into %s", lua_typename(L, static_cast(type_of(L, 2))), detail::demangle().c_str()); - } - return 0; - } - - static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { - return real_new_index_call_fixed(std::integral_constant::value>(), L); - } - static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) { auto& src = get_src(L); #ifdef SOL_CHECK_ARGUMENTS @@ -13094,7 +12375,7 @@ namespace sol { } static int real_new_index_call(lua_State* L) { - return real_new_index_call_const(meta::neg, std::is_const, meta::neg>>>(), meta::all>(), L); + return real_new_index_call_const(meta::neg, std::is_const, meta::neg>>>(), is_associative(), L); } static int real_pairs_next_call_assoc(std::true_type, lua_State* L) { @@ -13271,43 +12552,39 @@ namespace sol { } static int add_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_add_call)>(L); } static int insert_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_insert_call)>(L); } static int clear_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_clear_call)>(L); } static int find_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_find_call)>(L); } static int length_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_length_call)>(L); } static int pairs_next_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_pairs_next_call)>(L); } static int pairs_call(lua_State*L) { - return detail::typed_static_trampoline(L); - } - - static int get_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_pairs_call)>(L); } static int index_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_index_call)>(L); } static int new_index_call(lua_State*L) { - return detail::typed_static_trampoline(L); + return detail::static_trampoline<(&real_new_index_call)>(L); } }; @@ -13316,13 +12593,12 @@ namespace sol { template inline auto container_metatable() { typedef container_usertype_metatable> meta_cumt; - std::array reg = { { + std::array reg = { { { "__index", &meta_cumt::index_call }, { "__newindex", &meta_cumt::new_index_call }, { "__pairs", &meta_cumt::pairs_call }, { "__ipairs", &meta_cumt::pairs_call }, { "__len", &meta_cumt::length_call }, - { "get", &meta_cumt::get_call }, { "clear", &meta_cumt::clear_call }, { "insert", &meta_cumt::insert_call }, { "add", &meta_cumt::add_call }, @@ -13451,7 +12727,7 @@ namespace sol { template void set(N&& n, F&& f) { auto meta = static_cast*>(base_t::registrar_data()); - meta->add(state, std::forward(n), std::forward(f)); + meta->add(state, n, f); } }; @@ -14904,13 +14180,13 @@ namespace sol { optional maybetopmsg = stack::check_get(L, 1); if (maybetopmsg) { const string_detail::string_shim& topmsg = maybetopmsg.value(); - msg.assign(topmsg.data(), topmsg.size()); + msg.assign(topmsg.c_str(), topmsg.size()); } luaL_traceback(L, L, msg.c_str(), 1); optional maybetraceback = stack::check_get(L, -1); if (maybetraceback) { const string_detail::string_shim& traceback = maybetraceback.value(); - msg.assign(traceback.data(), traceback.size()); + msg.assign(traceback.c_str(), traceback.size()); } return stack::push(L, msg); } @@ -14922,7 +14198,6 @@ namespace sol { state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), state_view(unique_base::get()) { set_panic(panic); - sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler)); stack::luajit_exception_handler(unique_base::get()); } @@ -15197,61 +14472,6 @@ namespace sol { // end of sol/coroutine.hpp -// beginning of sol/variadic_results.hpp - -// beginning of sol/as_returns.hpp - -namespace sol { - template - struct as_returns_t { - T src; - }; - - template - auto as_returns(Source&& source) { - return as_returns_t>{ std::forward(source) }; - } - - namespace stack { - template - struct pusher> { - int push(lua_State* L, const as_returns_t& e) { - auto& src = detail::unwrap(e.src); - int p = 0; - for (const auto& i : src) { - p += stack::push(L, i); - } - return p; - } - }; - } // stack -} // sol - -// end of sol/as_returns.hpp - -namespace sol { - - struct variadic_results : public std::vector { - using std::vector::vector; - }; - - namespace stack { - template <> - struct pusher { - int push(lua_State* L, const variadic_results& e) { - int p = 0; - for (const auto& i : e) { - p += stack::push(L, i); - } - return p; - } - }; - } // stack - -} // sol - -// end of sol/variadic_results.hpp - #ifdef __GNUC__ #pragma GCC diagnostic pop #elif defined _MSC_VER