From c9980bfc28b29a339d341ff1b72321c0a3de8fec Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 4 Feb 2018 19:23:24 -0500 Subject: [PATCH] Add push function, update single --- single/sol/sol.hpp | 1118 +++++++++++++++++++++++------------- single/sol/sol_forward.hpp | 21 +- sol/proxy.hpp | 8 + 3 files changed, 736 insertions(+), 411 deletions(-) diff --git a/single/sol/sol.hpp b/single/sol/sol.hpp index f8618b5c..dd5e8228 100644 --- a/single/sol/sol.hpp +++ b/single/sol/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 2018-01-31 02:05:24.489928 UTC -// This header was generated with sol v2.19.0 (revision 49d99d1) +// Generated 2018-02-05 00:23:04.380676 UTC +// This header was generated with sol v2.19.0 (revision 8f6f12d) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -78,19 +78,6 @@ #endif // compiler-specific checks #endif // C++17 only -#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 #if defined(_DEBUG) && !defined(NDEBUG) @@ -195,6 +182,10 @@ #endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH #endif // Boost has unordered_map with Compatible Key and CompatibleHash +#ifndef SOL_STACK_STRING_OPTIMIZATION_SIZE +#define SOL_STACK_STRING_OPTIMIZATION_SIZE 1024 +#endif // Optimized conversion routines using a KB or so off the stack + // end of sol/feature_test.hpp namespace sol { @@ -973,15 +964,163 @@ namespace meta { // end of sol/bind_traits.hpp +// beginning of sol/string_view.hpp + +#ifdef SOL_CXX17_FEATURES +#include +#endif // C++17 features +#include +#ifdef SOL_USE_BOOST +#include +#endif + +namespace sol { +#ifdef SOL_CXX17_FEATURES + template > + using basic_string_view = std::basic_string_view; + typedef std::string_view string_view; + typedef std::wstring_view wstring_view; + typedef std::u16string_view u16string_view; + typedef std::u32string_view u32string_view; + typedef std::hash string_view_hash; +#else + template > + struct basic_string_view { + std::size_t s; + const Char* p; + + basic_string_view(const std::string& r) + : basic_string_view(r.data(), r.size()) { + } + basic_string_view(const Char* ptr) + : basic_string_view(ptr, Traits::length(ptr)) { + } + basic_string_view(const Char* ptr, std::size_t sz) + : s(sz), p(ptr) { + } + + static int compare(const Char* lhs_p, std::size_t lhs_sz, const Char* rhs_p, std::size_t rhs_sz) { + int result = Traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); + if (result != 0) + return result; + if (lhs_sz < rhs_sz) + return -1; + if (lhs_sz > rhs_sz) + return 1; + return 0; + } + + const Char* begin() const { + return p; + } + + const Char* end() const { + return p + s; + } + + const Char* cbegin() const { + return p; + } + + const Char* cend() const { + return p + s; + } + + const Char* data() const { + return p; + } + + std::size_t size() const { + return s; + } + + std::size_t length() const { + return size(); + } + + operator std::basic_string() const { + return std::basic_string(data(), size()); + } + + bool operator==(const basic_string_view& r) const { + return compare(p, s, r.data(), r.size()) == 0; + } + + bool operator==(const Char* r) const { + return compare(r, Traits::length(r), p, s) == 0; + } + + bool operator==(const std::basic_string& r) const { + return compare(r.data(), r.size(), p, s) == 0; + } + + bool operator!=(const basic_string_view& r) const { + return !(*this == r); + } + + bool operator!=(const char* r) const { + return !(*this == r); + } + + bool operator!=(const std::basic_string& r) const { + return !(*this == r); + } + }; + + template > + struct basic_string_view_hash { + typedef basic_string_view argument_type; + typedef std::size_t result_type; + + template + result_type operator()(const std::basic_string& r) const { + return (*this)(argument_type(r.c_str(), r.size())); + } + + result_type operator()(const argument_type& r) const { +#ifdef SOL_USE_BOOST + return boost::hash_range(r.begin(), r.end()); +#else + // Modified, from libstdc++ + // An implementation attempt at Fowler No Voll, 1a. + // Supposedly, used in MSVC, + // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? + // But, well. Can't win them all, right? + // This should normally only apply when NOT using boost, + // so this should almost never be tapped into... + std::size_t hash = 0; + const unsigned char* cptr = reinterpret_cast(r.data()); + for (std::size_t sz = r.size(); sz != 0; --sz) { + hash ^= static_cast(*cptr++); + hash *= static_cast(1099511628211ULL); + } + return hash; +#endif + } + }; +} // namespace sol + +namespace std { + template + struct hash< ::sol::basic_string_view > : ::sol::basic_string_view_hash {}; +} // namespace std + +namespace sol { + using string_view = basic_string_view; + using wstring_view = basic_string_view; + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + using string_view_hash = std::hash; +#endif // C++17 Support +} // namespace sol + +// end of sol/string_view.hpp + #include #include #include -#include #include #include -#ifdef SOL_CXX17_FEATURES -#include -#endif namespace sol { template @@ -1499,6 +1638,13 @@ namespace sol { template struct is_matched_lookup : meta_detail::is_matched_lookup_impl::value> {}; + template + using is_string_like = any< + is_specialization_of>, + is_specialization_of>, + meta::all>, meta::any_same>>, char, char16_t, char32_t, wchar_t>> + >; + template using is_string_constructible = any< meta::all>, std::is_same>>, char>>, @@ -4159,154 +4305,6 @@ namespace sol { // end of sol/forward_detail.hpp -// beginning of sol/string_view.hpp - -#ifdef SOL_CXX17_FEATURES -#endif // C++17 features -#ifdef SOL_USE_BOOST -#include -#endif - -namespace sol { -#ifdef SOL_CXX17_FEATURES - typedef std::string_view string_view; - typedef std::wstring_view wstring_view; - typedef std::u16string_view u16string_view; - typedef std::u32string_view u32string_view; - typedef std::hash string_view_hash; -#else - template > - struct basic_string_view { - std::size_t s; - const Char* p; - - basic_string_view(const std::string& r) - : basic_string_view(r.data(), r.size()) { - } - basic_string_view(const Char* ptr) - : basic_string_view(ptr, Traits::length(ptr)) { - } - basic_string_view(const Char* ptr, std::size_t sz) - : s(sz), p(ptr) { - } - - static int compare(const Char* lhs_p, std::size_t lhs_sz, const Char* rhs_p, std::size_t rhs_sz) { - int result = Traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); - if (result != 0) - return result; - if (lhs_sz < rhs_sz) - return -1; - if (lhs_sz > rhs_sz) - return 1; - return 0; - } - - const Char* begin() const { - return p; - } - - const Char* end() const { - return p + s; - } - - const Char* cbegin() const { - return p; - } - - const Char* cend() const { - return p + s; - } - - const Char* data() const { - return p; - } - - std::size_t size() const { - return s; - } - - std::size_t length() const { - return size(); - } - - operator std::basic_string() const { - return std::basic_string(data(), size()); - } - - bool operator==(const basic_string_view& r) const { - return compare(p, s, r.data(), r.size()) == 0; - } - - bool operator==(const Char* r) const { - return compare(r, Traits::length(r), p, s) == 0; - } - - bool operator==(const std::basic_string& r) const { - return compare(r.data(), r.size(), p, s) == 0; - } - - bool operator!=(const basic_string_view& r) const { - return !(*this == r); - } - - bool operator!=(const char* r) const { - return !(*this == r); - } - - bool operator!=(const std::basic_string& r) const { - return !(*this == r); - } - }; - - template > - struct basic_string_view_hash { - typedef basic_string_view argument_type; - typedef std::size_t result_type; - - template - result_type operator()(const std::basic_string& r) const { - return (*this)(argument_type(r.c_str(), r.size())); - } - - result_type operator()(const argument_type& r) const { -#ifdef SOL_USE_BOOST - return boost::hash_range(r.begin(), r.end()); -#else - // Modified, from libstdc++ - // An implementation attempt at Fowler No Voll, 1a. - // Supposedly, used in MSVC, - // GCC (libstdc++) uses MurmurHash of some sort for 64-bit though...? - // But, well. Can't win them all, right? - // This should normally only apply when NOT using boost, - // so this should almost never be tapped into... - std::size_t hash = 0; - const unsigned char* cptr = reinterpret_cast(r.data()); - for (std::size_t sz = r.size(); sz != 0; --sz) { - hash ^= static_cast(*cptr++); - hash *= static_cast(1099511628211ULL); - } - return hash; -#endif - } - }; -} // namespace sol - -namespace std { - template - struct hash< ::sol::basic_string_view > : ::sol::basic_string_view_hash {}; -} // namespace std - -namespace sol { - using string_view = basic_string_view; - using wstring_view = basic_string_view; - using u16string_view = basic_string_view; - using u32string_view = basic_string_view; - using string_view_hash = std::hash; -#endif // C++17 Support -} // namespace sol - -// end of sol/string_view.hpp - // beginning of sol/raii.hpp namespace sol { @@ -5264,35 +5262,17 @@ namespace sol { 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 {}; - - 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> : std::false_type {}; template - struct is_container>::value && !is_initializer_list>::value>> : std::true_type {}; + struct is_container>::value + && !is_initializer_list>::value + && !meta::is_string_like>::value + >> : std::true_type {}; template struct is_container>::value && !meta::any_same>, char, wchar_t, char16_t, char32_t>::value>> : std::true_type {}; @@ -5308,17 +5288,11 @@ 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 {}; template struct lua_type_of : std::integral_constant {}; @@ -5482,18 +5456,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 {}; - - template <> - struct lua_type_of : std::integral_constant {}; - - template <> - struct lua_type_of : std::integral_constant {}; - #ifdef SOL_CXX17_FEATURES template struct lua_type_of> : std::integral_constant {}; @@ -8257,9 +8219,313 @@ namespace sol { // end of sol/overload.hpp -#ifdef SOL_CODECVT_SUPPORT -#include -#endif // codecvt header support +// beginning of sol/unicode.hpp + +#pragma once + +#include + +namespace sol { + // Everything here was lifted pretty much straight out of + // ogonek, because fuck figuring it out= + namespace unicode { + enum error_code { + ok = 0, + invalid_code_point, + invalid_code_unit, + invalid_leading_surrogate, + invalid_trailing_surrogate, + sequence_too_short, + overlong_sequence, + }; + + inline const string_view& to_string(error_code ec) { + static const string_view arr[4] = { + "ok", + "invalid code points", + "invalid code unit", + "overlong sequence" + }; + return arr[static_cast(ec)]; + } + + template + struct decoded_result { + error_code error; + char32_t codepoint; + It next; + }; + + template + struct encoded_result { + error_code error; + std::size_t code_units_size; + std::array code_units; + }; + + struct unicode_detail { + // codepoint related + static constexpr char32_t last_code_point = 0x10FFFF; + + static constexpr char32_t first_lead_surrogate = 0xD800; + static constexpr char32_t last_lead_surrogate = 0xDBFF; + + static constexpr char32_t first_trail_surrogate = 0xDC00; + static constexpr char32_t last_trail_surrogate = 0xDFFF; + + static constexpr char32_t first_surrogate = first_lead_surrogate; + static constexpr char32_t last_surrogate = last_trail_surrogate; + + static constexpr bool is_lead_surrogate(char32_t u) { + return u >= first_lead_surrogate && u <= last_lead_surrogate; + } + static constexpr bool is_trail_surrogate(char32_t u) { + return u >= first_trail_surrogate && u <= last_trail_surrogate; + } + static constexpr bool is_surrogate(char32_t u) { + return u >= first_surrogate && u <= last_surrogate; + } + + // utf8 related + static constexpr auto last_1byte_value = 0x7Fu; + static constexpr auto last_2byte_value = 0x7FFu; + static constexpr auto last_3byte_value = 0xFFFFu; + + static constexpr auto start_2byte_mask = 0x80u; + static constexpr auto start_3byte_mask = 0xE0u; + static constexpr auto start_4byte_mask = 0xF0u; + + static constexpr auto continuation_mask = 0xC0u; + static constexpr auto continuation_signature = 0x80u; + + static constexpr int sequence_length(unsigned char b) { + return (b & start_2byte_mask) == 0 ? 1 + : (b & start_3byte_mask) != start_3byte_mask ? 2 + : (b & start_4byte_mask) != start_4byte_mask ? 3 + : 4; + } + + static constexpr char32_t decode(unsigned char b0, unsigned char b1) { + return ((b0 & 0x1F) << 6) | (b1 & 0x3F); + } + static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2) { + return ((b0 & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F); + } + static constexpr char32_t decode(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3) { + return ((b0 & 0x07) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F); + } + + // utf16 related + static constexpr char32_t last_bmp_value = 0xFFFF; + static constexpr char32_t normalizing_value = 0x10000; + static constexpr int lead_surrogate_bitmask = 0xFFC00; + static constexpr int trail_surrogate_bitmask = 0x3FF; + static constexpr int lead_shifted_bits = 10; + + static char32_t combine_surrogates(char16_t lead, char16_t trail) { + auto hi = lead - first_lead_surrogate; + auto lo = trail - first_trail_surrogate; + return normalizing_value + ((hi << lead_shifted_bits) | lo); + } + }; + + inline encoded_result code_point_to_utf8(char32_t codepoint) { + encoded_result er; + er.error = error_code::ok; + if (codepoint <= unicode_detail::last_1byte_value) { + er.code_units_size = 1; + er.code_units = std::array{ static_cast(codepoint) }; + } + else if (codepoint <= unicode_detail::last_2byte_value) { + er.code_units_size = 2; + er.code_units = std::array{ + static_cast(0xC0 | ((codepoint & 0x7C0) >> 6)), + static_cast(0x80 | (codepoint & 0x3F)), + }; + } + else if (codepoint <= unicode_detail::last_3byte_value) { + er.code_units_size = 3; + er.code_units = std::array{ + static_cast(0xE0 | ((codepoint & 0xF000) >> 12)), + static_cast(0x80 | ((codepoint & 0xFC0) >> 6)), + static_cast(0x80 | (codepoint & 0x3F)), + }; + } + else { + er.code_units_size = 4; + er.code_units = std::array{ + static_cast(0xF0 | ((codepoint & 0x1C0000) >> 18)), + static_cast(0x80 | ((codepoint & 0x3F000) >> 12)), + static_cast(0x80 | ((codepoint & 0xFC0) >> 6)), + static_cast(0x80 | (codepoint & 0x3F)), + }; + } + return er; + } + + inline encoded_result code_point_to_utf16(char32_t codepoint) { + encoded_result er; + + if (codepoint <= unicode_detail::last_bmp_value) { + er.code_units_size = 1; + er.code_units = std::array{ static_cast(codepoint) }; + er.error = error_code::ok; + } + else { + auto normal = codepoint - unicode_detail::normalizing_value; + auto lead = unicode_detail::first_lead_surrogate + ((normal & unicode_detail::lead_surrogate_bitmask) >> unicode_detail::lead_shifted_bits); + auto trail = unicode_detail::first_trail_surrogate + (normal & unicode_detail::trail_surrogate_bitmask); + er.code_units = std::array{ + static_cast(lead), + static_cast(trail) + }; + er.code_units_size = 2; + er.error = error_code::ok; + } + return er; + } + + inline encoded_result code_point_to_utf32(char32_t codepoint) { + encoded_result er; + er.code_units_size = 1; + er.code_units[0] = codepoint; + er.error = error_code::ok; + return er; + } + + template + inline decoded_result utf8_to_code_point(It it, It last) { + decoded_result dr; + if (it == last) { + dr.next = it; + dr.error = error_code::sequence_too_short; + return dr; + } + + unsigned char b0 = *it; + std::size_t length = unicode_detail::sequence_length(b0); + + if (length == 1) { + dr.codepoint = static_cast(b0); + dr.error = error_code::ok; + ++it; + dr.next = it; + return dr; + } + + auto is_invalid = [](unsigned char b) { return b == 0xC0 || b == 0xC1 || b > 0xF4; }; + auto is_continuation = [](unsigned char b) { + return (b & unicode_detail::continuation_mask) == unicode_detail::continuation_signature; + }; + + if (is_invalid(b0) || is_continuation(b0)) { + dr.error = error_code::invalid_code_unit; + dr.next = it; + return dr; + } + + ++it; + std::array b; + b[0] = b0; + for (std::size_t i = 1; i < length; ++i) { + b[i] = *it; + if (!is_continuation(b[i])) { + dr.error = error_code::invalid_code_unit; + dr.next = it; + return dr; + } + ++it; + } + + char32_t decoded; + switch (length) { + case 2: + decoded = unicode_detail::decode(b[0], b[1]); + break; + case 3: + decoded = unicode_detail::decode(b[0], b[1], b[2]); + break; + default: + decoded = unicode_detail::decode(b[0], b[1], b[2], b[3]); + break; + } + + auto is_overlong = [](char32_t u, std::size_t bytes) { + return u <= unicode_detail::last_1byte_value + || (u <= unicode_detail::last_2byte_value && bytes > 2) + || (u <= unicode_detail::last_3byte_value && bytes > 3); + }; + if (is_overlong(decoded, length)) { + dr.error = error_code::overlong_sequence; + return dr; + } + if (unicode_detail::is_surrogate(decoded) || decoded > unicode_detail::last_code_point) { + dr.error = error_code::invalid_code_point; + return dr; + } + + // then everything is fine + dr.codepoint = decoded; + dr.error = error_code::ok; + dr.next = it; + return dr; + } + + template + inline decoded_result utf16_to_code_point(It it, It last) { + decoded_result dr; + if (it == last) { + dr.next = it; + dr.error = error_code::sequence_too_short; + return dr; + } + + char16_t lead = static_cast(*it); + + if (!unicode_detail::is_surrogate(lead)) { + ++it; + dr.codepoint = static_cast(lead); + dr.next = it; + dr.error = error_code::ok; + return dr; + } + if (!unicode_detail::is_lead_surrogate(lead)) { + dr.error = error_code::invalid_leading_surrogate; + dr.next = it; + return dr; + } + + ++it; + auto trail = *it; + if (!unicode_detail::is_trail_surrogate(trail)) { + dr.error = error_code::invalid_trailing_surrogate; + dr.next = it; + return dr; + } + + dr.codepoint = unicode_detail::combine_surrogates(lead, trail); + dr.next = ++it; + dr.error = error_code::ok; + return dr; + } + + template + inline decoded_result utf32_to_code_point(It it, It last) { + decoded_result dr; + if (it == last) { + dr.next = it; + dr.error = error_code::sequence_too_short; + return dr; + } + dr.codepoint = static_cast(*it); + dr.next = ++it; + dr.error = error_code::ok; + return dr; + } + } +} +// end of sol/unicode.hpp + #ifdef SOL_CXX17_FEATURES #endif // C++17 @@ -8664,111 +8930,137 @@ namespace stack { } }; - template <> - struct getter { + template + struct getter> { static string_view get(lua_State* L, int index, record& tracking) { tracking.use(1); size_t sz; const char* str = lua_tolstring(L, index, &sz); - return string_view(str, sz); + return basic_string_view(str, sz); } }; -#ifdef SOL_CODECVT_SUPPORT - template <> - struct getter { - static std::wstring get(lua_State* L, int index, record& tracking) { + template + struct getter> { + typedef std::basic_string S; + static S get(lua_State* L, int index, record& tracking) { + typedef std::conditional_t Ch; + typedef typename std::allocator_traits::template rebind_alloc ChAl; + typedef std::char_traits ChTraits; + getter> g; + (void)g; + return g.template get_into(L, index, tracking); + } + }; + + template + struct getter> { + template + static S get_into(lua_State* L, int index, record& tracking) { + typedef typename S::value_type Ch; tracking.use(1); size_t len; - auto str = lua_tolstring(L, index, &len); + auto utf8p = lua_tolstring(L, index, &len); if (len < 1) - return std::wstring(); - if (sizeof(wchar_t) == 2) { - thread_local std::wstring_convert> convert; - std::wstring r = convert.from_bytes(str, str + len); -#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ < 7 - // Thanks, MinGW and libstdc++, for introducing this absolutely asinine bug - // https://sourceforge.net/p/mingw-w64/bugs/538/ - // http://chat.stackoverflow.com/transcript/message/32271369#32271369 - for (auto& c : r) { - uint8_t* b = reinterpret_cast(&c); - std::swap(b[0], b[1]); - } -#endif - return r; + return S(); + std::size_t needed_size = 0; + const char* strb = utf8p; + const char* stre = utf8p + len; + for (const char* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf8_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf16(dr.codepoint); + needed_size += er.code_units_size; + strtarget = dr.next; + } + S r(needed_size, static_cast(0)); + r.resize(needed_size); + Ch* target = &r[0]; + for (const char* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf8_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf16(dr.codepoint); + std::memcpy(target, er.code_units.data(), er.code_units_size * sizeof(Ch)); + strtarget = dr.next; + target += er.code_units_size; } - thread_local std::wstring_convert> convert; - std::wstring r = convert.from_bytes(str, str + len); return r; } + + static std::basic_string get(lua_State* L, int index, record& tracking) { + return get_into>(L, index, tracking); + } }; - template <> - struct getter { - static std::u16string get(lua_State* L, int index, record& tracking) { + template + struct getter> { + template + static S get_into(lua_State* L, int index, record& tracking) { + typedef typename S::value_type Ch; tracking.use(1); size_t len; - auto str = lua_tolstring(L, index, &len); + auto utf8p = lua_tolstring(L, index, &len); if (len < 1) - return std::u16string(); -#ifdef _MSC_VER - thread_local std::wstring_convert, int16_t> convert; - auto intd = convert.from_bytes(str, str + len); - std::u16string r(intd.size(), '\0'); - std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); -#else - thread_local std::wstring_convert, char16_t> convert; - std::u16string r = convert.from_bytes(str, str + len); -#endif // VC++ is a shit + return S(); + std::size_t needed_size = 0; + const char* strb = utf8p; + const char* stre = utf8p + len; + for (const char* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf8_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf32(dr.codepoint); + needed_size += er.code_units_size; + strtarget = dr.next; + } + S r(needed_size, static_cast(0)); + r.resize(needed_size); + Ch* target = &r[0]; + for (const char* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf8_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf32(dr.codepoint); + std::memcpy(target, er.code_units.data(), er.code_units_size * sizeof(Ch)); + strtarget = dr.next; + target += er.code_units_size; + } return r; } - }; - template <> - struct getter { - static std::u32string get(lua_State* L, int index, record& tracking) { - tracking.use(1); - size_t len; - auto str = lua_tolstring(L, index, &len); - if (len < 1) - return std::u32string(); -#ifdef _MSC_VER - thread_local std::wstring_convert, int32_t> convert; - auto intd = convert.from_bytes(str, str + len); - std::u32string r(intd.size(), '\0'); - std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); -#else - thread_local std::wstring_convert, char32_t> convert; - std::u32string r = convert.from_bytes(str, str + len); -#endif // VC++ is a shit - return r; - } - }; - - template <> - struct getter { - static wchar_t get(lua_State* L, int index, record& tracking) { - auto str = getter{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : wchar_t(0); + static std::basic_string get(lua_State* L, int index, record& tracking) { + return get_into>(L, index, tracking); } }; template <> struct getter { static char16_t get(lua_State* L, int index, record& tracking) { - auto str = getter{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : char16_t(0); + string_view utf8 = stack::get(L, index, tracking); + const char* strb = utf8.data(); + const char* stre = utf8.data() + utf8.size(); + auto dr = unicode::utf8_to_code_point(strb, stre); + auto er = unicode::code_point_to_utf16(dr.codepoint); + return er.code_units[0]; } }; template <> struct getter { static char32_t get(lua_State* L, int index, record& tracking) { - auto str = getter{}.get(L, index, tracking); - return str.size() > 0 ? str[0] : char32_t(0); + string_view utf8 = stack::get(L, index, tracking); + const char* strb = utf8.data(); + const char* stre = utf8.data() + utf8.size(); + auto dr = unicode::utf8_to_code_point(strb, stre); + auto er = unicode::code_point_to_utf32(dr.codepoint); + return er.code_units[0]; + } + }; + + template <> + struct getter { + static wchar_t get(lua_State* L, int index, record& tracking) { + typedef std::conditional_t Ch; + getter g; + (void)g; + auto c = g.get(L, index, tracking); + return static_cast(c); } }; -#endif // codecvt header support template <> struct getter { @@ -9183,8 +9475,6 @@ namespace stack { // beginning of sol/stack_push.hpp #include -#ifdef SOL_CODECVT_SUPPORT -#endif // codecvt support #ifdef SOL_CXX17_FEATURES #endif // C++17 @@ -9533,6 +9823,7 @@ namespace stack { return 1; } }; + #ifdef SOL_NOEXCEPT_FUNCTION_TYPE template <> struct pusher> { @@ -9735,26 +10026,26 @@ namespace stack { } }; - template <> - struct pusher { - static int push(lua_State* L, const std::string& str) { + template + struct pusher> { + static int push(lua_State* L, const std::basic_string& str) { lua_pushlstring(L, str.c_str(), str.size()); return 1; } - static int push(lua_State* L, const std::string& str, std::size_t sz) { + static int push(lua_State* L, const std::basic_string& str, std::size_t sz) { lua_pushlstring(L, str.c_str(), sz); return 1; } }; - template <> - struct pusher { - static int push(lua_State* L, const string_view& sv) { + template + struct pusher> { + static int push(lua_State* L, const basic_string_view& sv) { return stack::push(L, sv.data(), sv.length()); } - static int push(lua_State* L, const string_view& sv, std::size_t n) { + static int push(lua_State* L, const basic_string_view& sv, std::size_t n) { return stack::push(L, sv.data(), n); } }; @@ -9792,7 +10083,6 @@ namespace stack { } }; -#ifdef SOL_CODECVT_SUPPORT template <> struct pusher { static int push(lua_State* L, const wchar_t* wstr) { @@ -9805,13 +10095,13 @@ namespace stack { static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { if (sizeof(wchar_t) == 2) { - thread_local std::wstring_convert> convert; - std::string u8str = convert.to_bytes(strb, stre); - return stack::push(L, u8str); + const char16_t* sb = reinterpret_cast(strb); + const char16_t* se = reinterpret_cast(stre); + return stack::push(L, sb, se); } - thread_local std::wstring_convert> convert; - std::string u8str = convert.to_bytes(strb, stre); - return stack::push(L, u8str); + const char32_t* sb = reinterpret_cast(strb); + const char32_t* se = reinterpret_cast(stre); + return stack::push(L, sb, se); } }; @@ -9838,6 +10128,20 @@ namespace stack { template <> struct pusher { + static int convert_into(lua_State* L, char* start, std::size_t, const char16_t* strb, const char16_t* stre) { + char* target = start; + for (const char16_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf16_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf8(dr.codepoint); + const char* utf8data = er.code_units.data(); + std::memcpy(target, utf8data, er.code_units_size); + target += er.code_units_size; + strtarget = dr.next; + } + + return stack::push(L, start, target); + } + static int push(lua_State* L, const char16_t* u16str) { return push(L, u16str, std::char_traits::length(u16str)); } @@ -9847,14 +10151,30 @@ namespace stack { } static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { -#ifdef _MSC_VER - thread_local std::wstring_convert, int16_t> convert; - std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); -#else - thread_local std::wstring_convert, char16_t> convert; - std::string u8str = convert.to_bytes(strb, stre); -#endif // VC++ is a shit - return stack::push(L, u8str); + // TODO: use new unicode methods + // TODO: use new unicode methods + char sbo[SOL_STACK_STRING_OPTIMIZATION_SIZE]; + // if our max string space is small enough, use SBO + // right off the bat + std::size_t max_possible_code_units = (stre - strb) * 4; + if (max_possible_code_units <= SOL_STACK_STRING_OPTIMIZATION_SIZE) { + return convert_into(L, sbo, max_possible_code_units, strb, stre); + } + // otherwise, we must manually count/check size + std::size_t needed_size = 0; + for (const char16_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf16_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf8(dr.codepoint); + needed_size += er.code_units_size; + strtarget = dr.next; + } + if (needed_size < SOL_STACK_STRING_OPTIMIZATION_SIZE) { + return convert_into(L, sbo, needed_size, strb, stre); + } + std::string u8str("", 0); + u8str.resize(needed_size); + char* target = &u8str[0]; + return convert_into(L, target, needed_size, strb, stre); } }; @@ -9881,6 +10201,19 @@ namespace stack { template <> struct pusher { + static int convert_into(lua_State* L, char* start, std::size_t, const char32_t* strb, const char32_t* stre) { + char* target = start; + for (const char32_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf32_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf8(dr.codepoint); + const char* data = er.code_units.data(); + std::memcpy(target, data, er.code_units_size); + target += er.code_units_size; + strtarget = dr.next; + } + return stack::push(L, start, target); + } + static int push(lua_State* L, const char32_t* u32str) { return push(L, u32str, u32str + std::char_traits::length(u32str)); } @@ -9890,14 +10223,29 @@ namespace stack { } static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { -#ifdef _MSC_VER - thread_local std::wstring_convert, int32_t> convert; - std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); -#else - thread_local std::wstring_convert, char32_t> convert; - std::string u8str = convert.to_bytes(strb, stre); -#endif // VC++ is a shit - return stack::push(L, u8str); + // TODO: use new unicode methods + char sbo[SOL_STACK_STRING_OPTIMIZATION_SIZE]; + // if our max string space is small enough, use SBO + // right off the bat + std::size_t max_possible_code_units = (stre - strb) * 4; + if (max_possible_code_units <= SOL_STACK_STRING_OPTIMIZATION_SIZE) { + return convert_into(L, sbo, max_possible_code_units, strb, stre); + } + // otherwise, we must manually count/check size + std::size_t needed_size = 0; + for (const char32_t* strtarget = strb; strtarget < stre;) { + auto dr = unicode::utf32_to_code_point(strtarget, stre); + auto er = unicode::code_point_to_utf8(dr.codepoint); + needed_size += er.code_units_size; + strtarget = dr.next; + } + if (needed_size < SOL_STACK_STRING_OPTIMIZATION_SIZE) { + return convert_into(L, sbo, needed_size, strb, stre); + } + std::string u8str("", 0); + u8str.resize(needed_size); + char* target = &u8str[0]; + return convert_into(L, target, needed_size, strb, stre); } }; @@ -9959,7 +10307,7 @@ namespace stack { struct pusher { static int push(lua_State* L, wchar_t c) { const wchar_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); + return stack::push(L, &str[0], 1); } }; @@ -9967,7 +10315,7 @@ namespace stack { struct pusher { static int push(lua_State* L, char16_t c) { const char16_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); + return stack::push(L, &str[0], 1); } }; @@ -9975,77 +10323,43 @@ namespace stack { struct pusher { static int push(lua_State* L, char32_t c) { const char32_t str[2] = { c, '\0' }; - return stack::push(L, str, 1); + return stack::push(L, &str[0], 1); } }; - template <> - struct pusher { - static int push(lua_State* L, const std::wstring& wstr) { - return push(L, wstr.data(), wstr.size()); + template + struct pusher> { + static int push(lua_State* L, const std::basic_string& wstr) { + return push(L, wstr, wstr.size()); } - static int push(lua_State* L, const std::wstring& wstr, std::size_t sz) { + static int push(lua_State* L, const std::basic_string& wstr, std::size_t sz) { return stack::push(L, wstr.data(), wstr.data() + sz); } }; - template <> - struct pusher { - static int push(lua_State* L, const std::u16string& u16str) { + template + struct pusher> { + static int push(lua_State* L, const std::basic_string& u16str) { return push(L, u16str, u16str.size()); } - static int push(lua_State* L, const std::u16string& u16str, std::size_t sz) { + static int push(lua_State* L, const std::basic_string& u16str, std::size_t sz) { return stack::push(L, u16str.data(), u16str.data() + sz); } }; - template <> - struct pusher { - static int push(lua_State* L, const std::u32string& u32str) { + template + struct pusher> { + static int push(lua_State* L, const std::basic_string& u32str) { return push(L, u32str, u32str.size()); } - static int push(lua_State* L, const std::u32string& u32str, std::size_t sz) { + static int push(lua_State* L, const std::basic_string& u32str, std::size_t sz) { return stack::push(L, u32str.data(), u32str.data() + sz); } }; - template <> - struct pusher { - static int push(lua_State* L, const wstring_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - - static int push(lua_State* L, const wstring_view& sv, std::size_t n) { - return stack::push(L, sv.data(), n); - } - }; - - template <> - struct pusher { - static int push(lua_State* L, const u16string_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - - static int push(lua_State* L, const u16string_view& sv, std::size_t n) { - return stack::push(L, sv.data(), n); - } - }; - - template <> - struct pusher { - static int push(lua_State* L, const u32string_view& sv) { - return stack::push(L, sv.data(), sv.length()); - } - - static int push(lua_State* L, const u32string_view& sv, std::size_t n) { - return stack::push(L, sv.data(), n); - } - }; -#endif // codecvt Header Support - template struct pusher> { template @@ -10489,8 +10803,6 @@ namespace stack { // end of sol/stack_probe.hpp -#include - namespace sol { namespace detail { using typical_chunk_name_t = char[32]; @@ -10960,10 +11272,6 @@ namespace sol { namespace sol { struct stack_proxy : public stack_proxy_base { - private: - lua_State* L; - int index; - public: stack_proxy() : stack_proxy_base() { @@ -14159,6 +14467,10 @@ namespace sol { return set(std::move(other)); } + int push() const noexcept { + return get().push(L); + } + template decltype(auto) get() const { return tuple_get(std::make_index_sequence>::value>()); @@ -14191,7 +14503,11 @@ namespace sol { template decltype(auto) call(Args&&... args) { +#ifdef SOL_SAFE_FUNCTION + return get().template call(std::forward(args)...); +#else return get().template call(std::forward(args)...); +#endif // Safe function usage } template @@ -15358,7 +15674,8 @@ namespace sol { } static error_result get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) { - if (key < 1) { + key += deferred_traits::index_adjustment(L, self); + if (key < 0) { return stack::push(L, lua_nil); } auto it = deferred_traits::begin(L, self); @@ -15366,7 +15683,7 @@ namespace sol { if (it == e) { return stack::push(L, lua_nil); } - while (key > 1) { + while (key > 0) { --key; ++it; if (it == e) { @@ -15378,10 +15695,10 @@ namespace sol { static error_result get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) { std::ptrdiff_t len = static_cast(size_start(L, self)); - if (key < 1 || key > len) { + key += deferred_traits::index_adjustment(L, self); + if (key < 0 || key >= len) { return stack::push(L, lua_nil); } - --key; auto it = std::next(deferred_traits::begin(L, self), key); return get_associative(is_associative(), L, it); } @@ -15432,14 +15749,15 @@ namespace sol { static error_result set_category(std::input_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); + key += deferred_traits::index_adjustment(L, self); auto e = deferred_traits::end(L, self); auto it = deferred_traits::begin(L, self); auto backit = it; - for (; key > 1 && it != e; --key, ++it) { + for (; key > 0 && it != e; --key, ++it) { backit = it; } if (it == e) { - if (key == 1) { + if (key == 0) { return add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after::value ? backit : it); } return error_result("out of bounds (too big) for set on '%s'", detail::demangle().c_str()); @@ -15449,10 +15767,10 @@ namespace sol { static error_result set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { decltype(auto) key = okey.as(); - if (key < 1) { + if (key <= 0) { return error_result("sol: out of bounds (too small) for set on '%s'", detail::demangle().c_str()); } - --key; + key += deferred_traits::index_adjustment(L, self); std::ptrdiff_t len = static_cast(size_start(L, self)); if (key == len) { return add_copyable(is_copyable(), L, self, std::move(value)); @@ -15670,7 +15988,7 @@ namespace sol { static error_result insert_lookup(std::false_type, lua_State* L, T& self, stack_object where, stack_object value) { auto it = deferred_traits::begin(L, self); auto key = where.as(); - --key; + key += deferred_traits::index_adjustment(L, self); std::advance(it, key); self.insert(it, value.as()); return {}; @@ -15680,7 +15998,7 @@ namespace sol { auto key = where.as(); auto backit = self.before_begin(); { - --key; + key += deferred_traits::index_adjustment(L, self); auto e = deferred_traits::end(L, self); for (auto it = deferred_traits::begin(L, self); key > 0; ++backit, ++it, --key) { if (backit == e) { @@ -15714,7 +16032,7 @@ namespace sol { static error_result erase_integral(std::true_type, lua_State* L, T& self, K& key) { auto it = deferred_traits::begin(L, self); - --key; + key += deferred_traits::index_adjustment(L, self); std::advance(it, key); self.erase(it); @@ -15747,7 +16065,7 @@ namespace sol { static error_result erase_after_has(std::true_type, lua_State* L, T& self, K& key) { auto backit = self.before_begin(); { - --key; + key += deferred_traits::index_adjustment(L, self); auto e = deferred_traits::end(L, self); for (auto it = deferred_traits::begin(L, self); key > 0; ++backit, ++it, --key) { if (backit == e) { @@ -15964,6 +16282,10 @@ namespace sol { return stack::push(L, empty_start(L, self)); } + static std::ptrdiff_t index_adjustment(lua_State*, T&) { + return static_cast(-1); + } + static int pairs(lua_State* L) { typedef meta::any>> is_assoc; return pairs_associative(is_assoc(), L); @@ -16057,10 +16379,10 @@ namespace sol { static int get(lua_State* L) { T& self = get_src(L); std::ptrdiff_t idx = stack::get(L, 2); - if (idx > static_cast(std::extent::value) || idx < 1) { + idx += deferred_traits::index_adjustment(L, self); + if (idx >= static_cast(std::extent::value) || idx < 0) { return stack::push(L, lua_nil); } - --idx; return stack::push_reference(L, detail::deref(self[idx])); } @@ -16071,13 +16393,13 @@ namespace sol { static int set(lua_State* L) { T& self = get_src(L); std::ptrdiff_t idx = stack::get(L, 2); - if (idx > static_cast(std::extent::value)) { + idx += deferred_traits::index_adjustment(L, self); + if (idx >= static_cast(std::extent::value)) { return luaL_error(L, "sol: index out of bounds (too big) for set on '%s'", detail::demangle().c_str()); } - if (idx < 1) { + if (idx < 0) { return luaL_error(L, "sol: index out of bounds (too small) for set on '%s'", detail::demangle().c_str()); } - --idx; self[idx] = stack::get(L, 3); return 0; } @@ -16110,6 +16432,10 @@ namespace sol { return pairs(L); } + static std::ptrdiff_t index_adjustment(lua_State*, T&) { + return -1; + } + static iterator begin(lua_State*, T& self) { return std::addressof(self[0]); } @@ -19851,13 +20177,13 @@ namespace sol { } template - state_view& new_enum(const std::string& name, Args&&... args) { + state_view& new_enum(const string_view& name, Args&&... args) { global.new_enum(name, std::forward(args)...); return *this; } template - state_view& new_enum(const std::string& name, std::initializer_list> items) { + state_view& new_enum(const string_view& name, std::initializer_list> items) { global.new_enum(name, std::move(items)); return *this; } diff --git a/single/sol/sol_forward.hpp b/single/sol/sol_forward.hpp index 54fed737..773c2373 100644 --- a/single/sol/sol_forward.hpp +++ b/single/sol/sol_forward.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 2018-01-31 02:05:24.772464 UTC -// This header was generated with sol v2.19.0 (revision 49d99d1) +// Generated 2018-02-05 00:23:04.726719 UTC +// This header was generated with sol v2.19.0 (revision 8f6f12d) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP @@ -45,19 +45,6 @@ #endif // compiler-specific checks #endif // C++17 only -#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 #if defined(_DEBUG) && !defined(NDEBUG) @@ -162,6 +149,10 @@ #endif // SOL_UNORDERED_MAP_COMPATIBLE_HASH #endif // Boost has unordered_map with Compatible Key and CompatibleHash +#ifndef SOL_STACK_STRING_OPTIMIZATION_SIZE +#define SOL_STACK_STRING_OPTIMIZATION_SIZE 1024 +#endif // Optimized conversion routines using a KB or so off the stack + // end of sol/feature_test.hpp namespace sol { diff --git a/sol/proxy.hpp b/sol/proxy.hpp index 7e0f55c7..5ef8fa3f 100644 --- a/sol/proxy.hpp +++ b/sol/proxy.hpp @@ -94,6 +94,10 @@ namespace sol { return set(std::move(other)); } + int push() const noexcept { + return get().push(L); + } + template decltype(auto) get() const { return tuple_get(std::make_index_sequence>::value>()); @@ -126,7 +130,11 @@ namespace sol { template decltype(auto) call(Args&&... args) { +#ifdef SOL_SAFE_FUNCTION + return get().template call(std::forward(args)...); +#else return get().template call(std::forward(args)...); +#endif // Safe function usage } template