diff --git a/3rdparty/include/meojson/bitops.hpp b/3rdparty/include/meojson/bitops.hpp index ec6137fd64..e1db493afd 100644 --- a/3rdparty/include/meojson/bitops.hpp +++ b/3rdparty/include/meojson/bitops.hpp @@ -2,87 +2,111 @@ #if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) #include -namespace json::__bitops { - using std::countl_one; - using std::countr_one; - using std::countl_zero; - using std::countr_zero; - inline constexpr bool is_little_endian() { - return std::endian::native == std::endian::little; - } +namespace json::_bitops +{ +using std::countl_one; +using std::countl_zero; +using std::countr_one; +using std::countr_zero; +inline constexpr bool is_little_endian() +{ + return std::endian::native == std::endian::little; +} } #else #include -namespace json::__bitops { +namespace json::_bitops +{ #if defined(__GNUC__) || defined(__clang__) - inline constexpr int countl_zero(uint32_t x) { - if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) - return x == 0 ? 32 : __builtin_clz(x); - if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) - return x == 0 ? 32 : __builtin_clzl(x); - return x == 0 ? 32 : __builtin_clzll(x); - } - inline constexpr int countr_zero(uint32_t x) { - if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) - return x == 0 ? 32 : __builtin_ctz(x); - if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) - return x == 0 ? 32 : __builtin_ctzl(x); - return x == 0 ? 32 : __builtin_ctzll(x); - } - inline constexpr int countl_zero(uint64_t x) { - return x == 0 ? 64 : __builtin_clzll(x); - } - inline constexpr int countr_zero(uint64_t x) { - return x == 0 ? 64 : __builtin_ctzll(x); - } +inline constexpr int countl_zero(uint32_t x) +{ + if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) return x == 0 ? 32 : __builtin_clz(x); + if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) return x == 0 ? 32 : __builtin_clzl(x); + return x == 0 ? 32 : __builtin_clzll(x); +} +inline constexpr int countr_zero(uint32_t x) +{ + if constexpr (sizeof(uint32_t) == sizeof(unsigned int)) return x == 0 ? 32 : __builtin_ctz(x); + if constexpr (sizeof(uint32_t) == sizeof(unsigned long)) return x == 0 ? 32 : __builtin_ctzl(x); + return x == 0 ? 32 : __builtin_ctzll(x); +} +inline constexpr int countl_zero(uint64_t x) +{ + return x == 0 ? 64 : __builtin_clzll(x); +} +inline constexpr int countr_zero(uint64_t x) +{ + return x == 0 ? 64 : __builtin_ctzll(x); +} #elif defined(_MSC_VER) #ifdef __AVX2__ - // lzcnt intrinsics is not constexpr - inline int countl_zero(uint32_t x) { - return __lzcnt(x); - } - inline int countr_zero(uint32_t x) { - return _tzcnt_u32(x); - } - inline int countl_zero(uint64_t x) { - return (int)__lzcnt64(x); - } - inline int countr_zero(uint64_t x) { - return (int)_tzcnt_u64(x); - } +// lzcnt intrinsics is not constexpr +inline int countl_zero(uint32_t x) +{ + return __lzcnt(x); +} +inline int countr_zero(uint32_t x) +{ + return _tzcnt_u32(x); +} +inline int countl_zero(uint64_t x) +{ + return (int)__lzcnt64(x); +} +inline int countr_zero(uint64_t x) +{ + return (int)_tzcnt_u64(x); +} #else - inline constexpr int countl_zero(uint32_t x) { - unsigned long index = 0; - return _BitScanReverse(&index, x) ? 31 - index : 32; - } - inline constexpr int countr_zero(uint32_t x) { - unsigned long index = 0; - return _BitScanForward(&index, x) ? index : 32; - } - inline constexpr int countl_zero(uint64_t x) { - unsigned long index = 0; - return _BitScanReverse64(&index, x) ? 63 - index : 64; - } - inline constexpr int countr_zero(uint64_t x) { - unsigned long index = 0; - return _BitScanForward64(&index, x) ? index : 64; - } +inline constexpr int countl_zero(uint32_t x) +{ + unsigned long index = 0; + return _BitScanReverse(&index, x) ? 31 - index : 32; +} +inline constexpr int countr_zero(uint32_t x) +{ + unsigned long index = 0; + return _BitScanForward(&index, x) ? index : 32; +} +inline constexpr int countl_zero(uint64_t x) +{ + unsigned long index = 0; + return _BitScanReverse64(&index, x) ? 63 - index : 64; +} +inline constexpr int countr_zero(uint64_t x) +{ + unsigned long index = 0; + return _BitScanForward64(&index, x) ? index : 64; +} #endif // __AVX2__ -#else // compiler +#else // compiler #error "bring your own bit counting implementation" #endif - inline int countl_one(uint32_t x) { return countl_zero(~x); } - inline int countr_one(uint32_t x) { return countr_zero(~x); } - inline int countl_one(uint64_t x) { return countl_zero(~x); } - inline int countr_one(uint64_t x) { return countr_zero(~x); } - - // no constexpr endian awareness before C++20 - inline bool is_little_endian() { - union { - uint32_t u32; - uint8_t u8; - } u = { 0x01020304 }; - return u.u8 == 4; - } +inline int countl_one(uint32_t x) +{ + return countl_zero(~x); } +inline int countr_one(uint32_t x) +{ + return countr_zero(~x); +} +inline int countl_one(uint64_t x) +{ + return countl_zero(~x); +} +inline int countr_one(uint64_t x) +{ + return countr_zero(~x); +} + +// no constexpr endian awareness before C++20 +inline bool is_little_endian() +{ + union { + uint32_t u32; + uint8_t u8; + } u = { 0x01020304 }; + return u.u8 == 4; +} +} // namespace json::_bitops #endif // C++20 diff --git a/3rdparty/include/meojson/json.hpp b/3rdparty/include/meojson/json.hpp index 41546ae4eb..4790ae2bab 100644 --- a/3rdparty/include/meojson/json.hpp +++ b/3rdparty/include/meojson/json.hpp @@ -14,8 +14,6 @@ #include "packed_bytes.hpp" -#define MEOJSON_INLINE inline - namespace json { template @@ -35,13 +33,17 @@ using wvalue = basic_value; using warray = basic_array; using wobject = basic_object; -using u16value = basic_value; -using u16array = basic_array; -using u16object = basic_object; - -using u32value = basic_value; -using u32array = basic_array; -using u32object = basic_object; +namespace utils +{ + template + using iterator_t = decltype(std::declval().begin()); + template + using remove_cvref_t = std::remove_cv_t>; + template + using iter_value_t = typename std::iterator_traits>::value_type; + template + using range_value_t = iter_value_t>; +} // ********************************* // * basic_value declare * @@ -90,16 +92,33 @@ public: basic_value(basic_array arr); basic_value(basic_object obj); - basic_value(std::initializer_list>> init_list); + basic_value(std::initializer_list::value_type> init_list); // Constructed from raw data template basic_value(value_type type, args_t&&... args); - // Prohibit conversion of other types to basic_value - template + template ::value_type, + utils::range_value_t>, + bool> = true> + basic_value(collection_t&& collection) : basic_value(basic_array(std::forward(collection))) + {} + template ::value_type, + utils::range_value_t>, + bool> = true> + basic_value(map_t&& map) : basic_value(basic_object(std::forward(map))) + {} + + template >, bool> = true> basic_value(value_t) = delete; + // I don't know if you want to convert char to string or number, so I delete these constructors. + basic_value(char) = delete; + basic_value(wchar_t) = delete; + basic_value(char16_t) = delete; + basic_value(char32_t) = delete; + ~basic_value(); bool valid() const noexcept { return _type != value_type::invalid; } @@ -175,6 +194,13 @@ public: return format(indent, 0); } + template + bool all() const; + template typename vector_t = std::vector> + vector_t to_vector() const; + template typename map_t = std::map> + map_t to_map() const; + basic_value& operator=(const basic_value& rhs); basic_value& operator=(basic_value&&) noexcept; @@ -261,19 +287,17 @@ public: basic_array() = default; basic_array(const basic_array& rhs) = default; basic_array(basic_array&& rhs) noexcept = default; - basic_array(const raw_array& arr); - basic_array(raw_array&& arr) noexcept; - basic_array(std::initializer_list init_list); + basic_array(std::initializer_list init_list); basic_array(typename raw_array::size_type size); explicit basic_array(const basic_value& val); explicit basic_array(basic_value&& val); - template ::value_type>>> - basic_array(array_t arr) - { - _array_data.assign(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end())); - } + + template >>> + basic_array(collection_t arr) + : _array_data(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end())) + {} ~basic_array() noexcept = default; @@ -291,6 +315,10 @@ public: { return format(indent, 0); } + template + bool all() const; + template typename vector_t = std::vector> + vector_t to_vector() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -377,17 +405,13 @@ public: basic_object() = default; basic_object(const basic_object& rhs) = default; basic_object(basic_object&& rhs) noexcept = default; - basic_object(const raw_object& raw_obj); - basic_object(raw_object&& raw_obj); basic_object(std::initializer_list init_list); explicit basic_object(const basic_value& val); explicit basic_object(basic_value&& val); - template ::value_type>>> - basic_object(map_t map) - { - _object_data.insert(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end())); - } + template >>> + basic_object(map_t map) : _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end())) + {} ~basic_object() = default; @@ -405,6 +429,10 @@ public: { return format(indent, 0); } + template + bool all() const; + template typename map_t = std::map> + map_t to_map() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -466,7 +494,7 @@ private: // **************************** template + typename accel_traits = _packed_bytes::packed_bytes_trait_max> class parser { public: @@ -494,7 +522,7 @@ private: // parse and return a string_t std::optional parse_stdstring(); - void skip_string_literal(); + bool skip_string_literal_with_accel(); bool skip_whitespace() noexcept; bool skip_digit(); @@ -532,6 +560,10 @@ protected: template auto parse(const parsing_t& content); + +template +auto parse(char_t* content); + template , istream_t>>> auto parse(istream_t& istream, bool check_bom); @@ -543,30 +575,28 @@ namespace literals { value operator""_json(const char* str, size_t len); wvalue operator""_json(const wchar_t* str, size_t len); - u16value operator""_json(const char16_t* str, size_t len); - u32value operator""_json(const char32_t* str, size_t len); value operator""_jvalue(const char* str, size_t len); wvalue operator""_jvalue(const wchar_t* str, size_t len); - u16value operator""_jvalue(const char16_t* str, size_t len); - u32value operator""_jvalue(const char32_t* str, size_t len); array operator""_jarray(const char* str, size_t len); warray operator""_jarray(const wchar_t* str, size_t len); - u16array operator""_jarray(const char16_t* str, size_t len); - u32array operator""_jarray(const char32_t* str, size_t len); object operator""_jobject(const char* str, size_t len); wobject operator""_jobject(const wchar_t* str, size_t len); - u16object operator""_jobject(const char16_t* str, size_t len); - u32object operator""_jobject(const char32_t* str, size_t len); } template const basic_value invalid_value(); -template -basic_value serialize(any_t&& arg); +namespace _serialization_helper +{ + template + struct string_converter; +} +template > +basic_value serialize(any_t&& arg, string_converter_t&& string_converter = {}); // ****************************** // * basic_value impl * @@ -590,131 +620,114 @@ static constexpr string_t null_string() return { 'n', 'u', 'l', 'l' }; } +template +string_t to_basic_string(any_t&& arg) +{ + if constexpr (std::is_same_v) { + return std::to_string(std::forward(arg)); + } + else if constexpr (std::is_same_v) { + return std::to_wstring(std::forward(arg)); + } + else { + static_assert(!sizeof(any_t), "Unsupported type"); + } +} + template static constexpr string_t unescape_string(const string_t& str); template -MEOJSON_INLINE basic_value::basic_value() = default; +inline basic_value::basic_value() = default; template -MEOJSON_INLINE basic_value::basic_value(const basic_value& rhs) +inline basic_value::basic_value(const basic_value& rhs) : _type(rhs._type), _raw_data(deep_copy(rhs._raw_data)) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value(basic_value&& rhs) noexcept = default; +inline basic_value::basic_value(basic_value&& rhs) noexcept = default; template -MEOJSON_INLINE basic_value::basic_value(bool b) +inline basic_value::basic_value(bool b) : _type(value_type::boolean), _raw_data(string_t(b ? true_string() : false_string())) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value(int num) : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(int num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(unsigned num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(unsigned num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(long num) : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(unsigned long num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(unsigned long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(long long num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(long long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(unsigned long long num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(unsigned long long num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(float num) : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(float num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(double num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(double num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(long double num) - : _type(value_type::number), _raw_data(std::to_string(num)) -{ - ; -} +inline basic_value::basic_value(long double num) + : _type(value_type::number), _raw_data(to_basic_string(num)) +{} template -MEOJSON_INLINE basic_value::basic_value(const char_t* str) - : _type(value_type::string), _raw_data(string_t(str)) -{ - ; -} +inline basic_value::basic_value(const char_t* str) : _type(value_type::string), _raw_data(string_t(str)) +{} template -MEOJSON_INLINE basic_value::basic_value(string_t str) : _type(value_type::string), _raw_data(std::move(str)) -{ - ; -} +inline basic_value::basic_value(string_t str) : _type(value_type::string), _raw_data(std::move(str)) +{} template -MEOJSON_INLINE basic_value::basic_value(basic_array arr) +inline basic_value::basic_value(basic_array arr) : _type(value_type::array), _raw_data(std::make_unique>(std::move(arr))) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value(basic_object obj) +inline basic_value::basic_value(basic_object obj) : _type(value_type::object), _raw_data(std::make_unique>(std::move(obj))) -{ - ; -} +{} template -MEOJSON_INLINE basic_value::basic_value( - std::initializer_list>> init_list) +inline basic_value::basic_value(std::initializer_list::value_type> init_list) : _type(value_type::object), _raw_data(std::make_unique>(init_list)) -{ - ; -} +{} // for Pimpl template -MEOJSON_INLINE basic_value::~basic_value() = default; +inline basic_value::~basic_value() = default; template template -MEOJSON_INLINE bool basic_value::is() const noexcept +inline bool basic_value::is() const noexcept { if constexpr (std::is_same_v, value_t>) { return true; @@ -740,44 +753,44 @@ MEOJSON_INLINE bool basic_value::is() const noexcept } template -MEOJSON_INLINE bool basic_value::contains(const string_t& key) const +inline bool basic_value::contains(const string_t& key) const { return is_object() && as_object().contains(key); } template -MEOJSON_INLINE bool basic_value::contains(size_t pos) const +inline bool basic_value::contains(size_t pos) const { return is_array() && as_array().contains(pos); } template -MEOJSON_INLINE const basic_value& basic_value::at(size_t pos) const +inline const basic_value& basic_value::at(size_t pos) const { return as_array().at(pos); } template -MEOJSON_INLINE const basic_value& basic_value::at(const string_t& key) const +inline const basic_value& basic_value::at(const string_t& key) const { return as_object().at(key); } template -MEOJSON_INLINE bool basic_value::erase(size_t pos) +inline bool basic_value::erase(size_t pos) { return as_array().erase(pos); } template -MEOJSON_INLINE bool basic_value::erase(const string_t& key) +inline bool basic_value::erase(const string_t& key) { return as_object().erase(key); } template template -MEOJSON_INLINE auto basic_value::get(key_then_default_value_t&&... keys_then_default_value) const +inline auto basic_value::get(key_then_default_value_t&&... keys_then_default_value) const { return get(std::forward_as_tuple(keys_then_default_value...), std::make_index_sequence {}); @@ -785,8 +798,8 @@ MEOJSON_INLINE auto basic_value::get(key_then_default_value_t&&... key template template -MEOJSON_INLINE auto basic_value::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_value::get(std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; return get_helper(std::get(keys_then_default_value), @@ -795,8 +808,8 @@ MEOJSON_INLINE auto basic_value::get(std::tuple template -MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_value, first_key_t&& first, - rest_keys_t&&... rest) const +inline auto basic_value::get_helper(const value_t& default_value, first_key_t&& first, + rest_keys_t&&... rest) const { if constexpr (std::is_constructible_v) { return is_object() ? as_object().get_helper(default_value, std::forward(first), @@ -815,7 +828,7 @@ MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_val template template -MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_value, unique_key_t&& first) const +inline auto basic_value::get_helper(const value_t& default_value, unique_key_t&& first) const { if constexpr (std::is_constructible_v) { return is_object() ? as_object().get_helper(default_value, std::forward(first)) : default_value; @@ -830,7 +843,7 @@ MEOJSON_INLINE auto basic_value::get_helper(const value_t& default_val template template -MEOJSON_INLINE auto basic_array::get(key_then_default_value_t&&... keys_then_default_value) const +inline auto basic_array::get(key_then_default_value_t&&... keys_then_default_value) const { return get(std::forward_as_tuple(keys_then_default_value...), std::make_index_sequence {}); @@ -838,8 +851,8 @@ MEOJSON_INLINE auto basic_array::get(key_then_default_value_t&&... key template template -MEOJSON_INLINE auto basic_array::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_array::get(std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; return get_helper(std::get(keys_then_default_value), @@ -848,7 +861,7 @@ MEOJSON_INLINE auto basic_array::get(std::tuple template -MEOJSON_INLINE auto basic_object::get(key_then_default_value_t&&... keys_then_default_value) const +inline auto basic_object::get(key_then_default_value_t&&... keys_then_default_value) const { return get(std::forward_as_tuple(keys_then_default_value...), std::make_index_sequence {}); @@ -856,8 +869,8 @@ MEOJSON_INLINE auto basic_object::get(key_then_default_value_t&&... ke template template -MEOJSON_INLINE auto basic_object::get(std::tuple keys_then_default_value, - std::index_sequence) const +inline auto basic_object::get(std::tuple keys_then_default_value, + std::index_sequence) const { constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1; return get_helper(std::get(keys_then_default_value), @@ -866,20 +879,20 @@ MEOJSON_INLINE auto basic_object::get(std::tuple template -MEOJSON_INLINE std::optional basic_value::find(size_t pos) const +inline std::optional basic_value::find(size_t pos) const { return is_array() ? as_array().template find(pos) : std::nullopt; } template template -MEOJSON_INLINE std::optional basic_value::find(const string_t& key) const +inline std::optional basic_value::find(const string_t& key) const { return is_object() ? as_object().template find(key) : std::nullopt; } template -MEOJSON_INLINE bool basic_value::as_boolean() const +inline bool basic_value::as_boolean() const { if (is_boolean()) { if (const string_t& b_str = as_basic_type_str(); b_str == true_string()) { @@ -898,7 +911,7 @@ MEOJSON_INLINE bool basic_value::as_boolean() const } template -MEOJSON_INLINE int basic_value::as_integer() const +inline int basic_value::as_integer() const { if (is_number()) { return std::stoi(as_basic_type_str()); @@ -909,14 +922,14 @@ MEOJSON_INLINE int basic_value::as_integer() const } template -MEOJSON_INLINE unsigned basic_value::as_unsigned() const +inline unsigned basic_value::as_unsigned() const { // I don't know why there is no std::stou. return static_cast(as_unsigned_long()); } template -MEOJSON_INLINE long basic_value::as_long() const +inline long basic_value::as_long() const { if (is_number()) { return std::stol(as_basic_type_str()); @@ -927,7 +940,7 @@ MEOJSON_INLINE long basic_value::as_long() const } template -MEOJSON_INLINE unsigned long basic_value::as_unsigned_long() const +inline unsigned long basic_value::as_unsigned_long() const { if (is_number()) { return std::stoul(as_basic_type_str()); @@ -938,7 +951,7 @@ MEOJSON_INLINE unsigned long basic_value::as_unsigned_long() const } template -MEOJSON_INLINE long long basic_value::as_long_long() const +inline long long basic_value::as_long_long() const { if (is_number()) { return std::stoll(as_basic_type_str()); @@ -949,7 +962,7 @@ MEOJSON_INLINE long long basic_value::as_long_long() const } template -MEOJSON_INLINE unsigned long long basic_value::as_unsigned_long_long() const +inline unsigned long long basic_value::as_unsigned_long_long() const { if (is_number()) { return std::stoull(as_basic_type_str()); @@ -960,7 +973,7 @@ MEOJSON_INLINE unsigned long long basic_value::as_unsigned_long_long() } template -MEOJSON_INLINE float basic_value::as_float() const +inline float basic_value::as_float() const { if (is_number()) { return std::stof(as_basic_type_str()); @@ -971,7 +984,7 @@ MEOJSON_INLINE float basic_value::as_float() const } template -MEOJSON_INLINE double basic_value::as_double() const +inline double basic_value::as_double() const { if (is_number()) { return std::stod(as_basic_type_str()); @@ -982,7 +995,7 @@ MEOJSON_INLINE double basic_value::as_double() const } template -MEOJSON_INLINE long double basic_value::as_long_double() const +inline long double basic_value::as_long_double() const { if (is_number()) { return std::stold(as_basic_type_str()); @@ -993,7 +1006,7 @@ MEOJSON_INLINE long double basic_value::as_long_double() const } template -MEOJSON_INLINE string_t basic_value::as_string() const +inline string_t basic_value::as_string() const { if (is_string()) { return as_basic_type_str(); @@ -1004,7 +1017,7 @@ MEOJSON_INLINE string_t basic_value::as_string() const } template -MEOJSON_INLINE const basic_array& basic_value::as_array() const +inline const basic_array& basic_value::as_array() const { if (is_array()) { return *std::get(_raw_data); @@ -1014,7 +1027,7 @@ MEOJSON_INLINE const basic_array& basic_value::as_array() co } template -MEOJSON_INLINE const basic_object& basic_value::as_object() const +inline const basic_object& basic_value::as_object() const { if (is_object()) { return *std::get(_raw_data); @@ -1024,7 +1037,7 @@ MEOJSON_INLINE const basic_object& basic_value::as_object() } template -MEOJSON_INLINE basic_array& basic_value::as_array() +inline basic_array& basic_value::as_array() { if (empty()) { *this = basic_array(); @@ -1038,7 +1051,7 @@ MEOJSON_INLINE basic_array& basic_value::as_array() } template -MEOJSON_INLINE basic_object& basic_value::as_object() +inline basic_object& basic_value::as_object() { if (empty()) { *this = basic_object(); @@ -1053,26 +1066,26 @@ MEOJSON_INLINE basic_object& basic_value::as_object() template template -MEOJSON_INLINE value_t basic_value::as() const +inline value_t basic_value::as() const { return static_cast(*this); } template -MEOJSON_INLINE const string_t& basic_value::as_basic_type_str() const +inline const string_t& basic_value::as_basic_type_str() const { return std::get(_raw_data); } template -MEOJSON_INLINE string_t& basic_value::as_basic_type_str() +inline string_t& basic_value::as_basic_type_str() { return std::get(_raw_data); } template template -MEOJSON_INLINE decltype(auto) basic_value::emplace(args_t&&... args) +inline decltype(auto) basic_value::emplace(args_t&&... args) { constexpr bool is_array_args = std::is_constructible_v::value_type, args_t...>; constexpr bool is_object_args = std::is_constructible_v::value_type, args_t...>; @@ -1089,26 +1102,26 @@ MEOJSON_INLINE decltype(auto) basic_value::emplace(args_t&&... args) template template -MEOJSON_INLINE decltype(auto) basic_value::array_emplace(args_t&&... args) +inline decltype(auto) basic_value::array_emplace(args_t&&... args) { return emplace(std::forward(args)...); } template template -MEOJSON_INLINE decltype(auto) basic_value::object_emplace(args_t&&... args) +inline decltype(auto) basic_value::object_emplace(args_t&&... args) { return emplace(std::forward(args)...); } template -MEOJSON_INLINE void basic_value::clear() noexcept +inline void basic_value::clear() noexcept { *this = basic_value(); } template -MEOJSON_INLINE string_t basic_value::to_string() const +inline string_t basic_value::to_string() const { switch (_type) { case value_type::null: @@ -1128,7 +1141,7 @@ MEOJSON_INLINE string_t basic_value::to_string() const } template -MEOJSON_INLINE string_t basic_value::format(size_t indent, size_t indent_times) const +inline string_t basic_value::format(size_t indent, size_t indent_times) const { switch (_type) { case value_type::null: @@ -1146,7 +1159,36 @@ MEOJSON_INLINE string_t basic_value::format(size_t indent, size_t inde } template -MEOJSON_INLINE basic_value& basic_value::operator=(const basic_value& rhs) +template +inline bool basic_value::all() const +{ + if (is_array()) { + return as_array().template all(); + } + else if (is_object()) { + return as_object().template all(); + } + else { + return false; + } +} + +template +template typename vector_t> +inline vector_t basic_value::to_vector() const +{ + return as_array().template to_vector(); +} + +template +template typename map_t> +inline map_t basic_value::to_map() const +{ + return as_object().template to_map(); +} + +template +inline basic_value& basic_value::operator=(const basic_value& rhs) { _type = rhs._type; _raw_data = deep_copy(rhs._raw_data); @@ -1155,10 +1197,10 @@ MEOJSON_INLINE basic_value& basic_value::operator=(const bas } template -MEOJSON_INLINE basic_value& basic_value::operator=(basic_value&& rhs) noexcept = default; +inline basic_value& basic_value::operator=(basic_value&& rhs) noexcept = default; template -MEOJSON_INLINE bool basic_value::operator==(const basic_value& rhs) const +inline bool basic_value::operator==(const basic_value& rhs) const { if (_type != rhs._type) return false; @@ -1179,7 +1221,7 @@ MEOJSON_INLINE bool basic_value::operator==(const basic_value -MEOJSON_INLINE const basic_value& basic_value::operator[](size_t pos) const +inline const basic_value& basic_value::operator[](size_t pos) const { // basic_array not support to create by operator[] @@ -1187,7 +1229,7 @@ MEOJSON_INLINE const basic_value& basic_value::operator[](si } template -MEOJSON_INLINE basic_value& basic_value::operator[](size_t pos) +inline basic_value& basic_value::operator[](size_t pos) { // basic_array not support to create by operator[] @@ -1195,7 +1237,7 @@ MEOJSON_INLINE basic_value& basic_value::operator[](size_t p } template -MEOJSON_INLINE basic_value& basic_value::operator[](const string_t& key) +inline basic_value& basic_value::operator[](const string_t& key) { if (empty()) { *this = basic_object(); @@ -1205,7 +1247,7 @@ MEOJSON_INLINE basic_value& basic_value::operator[](const st } template -MEOJSON_INLINE basic_value& basic_value::operator[](string_t&& key) +inline basic_value& basic_value::operator[](string_t&& key) { if (empty()) { *this = basic_object(); @@ -1215,76 +1257,76 @@ MEOJSON_INLINE basic_value& basic_value::operator[](string_t } template -MEOJSON_INLINE basic_value basic_value::operator|(const basic_object& rhs) const& +inline basic_value basic_value::operator|(const basic_object& rhs) const& { return as_object() | rhs; } template -MEOJSON_INLINE basic_value basic_value::operator|(basic_object&& rhs) const& +inline basic_value basic_value::operator|(basic_object&& rhs) const& { return as_object() | std::move(rhs); } template -MEOJSON_INLINE basic_value basic_value::operator|(const basic_object& rhs) && +inline basic_value basic_value::operator|(const basic_object& rhs) && { return std::move(as_object()) | rhs; } template -MEOJSON_INLINE basic_value basic_value::operator|(basic_object&& rhs) && +inline basic_value basic_value::operator|(basic_object&& rhs) && { return std::move(as_object()) | std::move(rhs); } template -MEOJSON_INLINE basic_value& basic_value::operator|=(const basic_object& rhs) +inline basic_value& basic_value::operator|=(const basic_object& rhs) { as_object() |= rhs; return *this; } template -MEOJSON_INLINE basic_value& basic_value::operator|=(basic_object&& rhs) +inline basic_value& basic_value::operator|=(basic_object&& rhs) { as_object() |= std::move(rhs); return *this; } template -MEOJSON_INLINE basic_value basic_value::operator+(const basic_array& rhs) const& +inline basic_value basic_value::operator+(const basic_array& rhs) const& { return as_array() + rhs; } template -MEOJSON_INLINE basic_value basic_value::operator+(basic_array&& rhs) const& +inline basic_value basic_value::operator+(basic_array&& rhs) const& { return as_array() + std::move(rhs); } template -MEOJSON_INLINE basic_value basic_value::operator+(const basic_array& rhs) && +inline basic_value basic_value::operator+(const basic_array& rhs) && { return std::move(as_array()) + rhs; } template -MEOJSON_INLINE basic_value basic_value::operator+(basic_array&& rhs) && +inline basic_value basic_value::operator+(basic_array&& rhs) && { return std::move(as_array()) + std::move(rhs); } template -MEOJSON_INLINE basic_value& basic_value::operator+=(const basic_array& rhs) +inline basic_value& basic_value::operator+=(const basic_array& rhs) { as_array() += rhs; return *this; } template -MEOJSON_INLINE basic_value& basic_value::operator+=(basic_array&& rhs) +inline basic_value& basic_value::operator+=(basic_array&& rhs) { as_array() += std::move(rhs); return *this; @@ -1292,14 +1334,14 @@ MEOJSON_INLINE basic_value& basic_value::operator+=(basic_ar template template -basic_value::basic_value(value_type type, args_t&&... args) +inline basic_value::basic_value(value_type type, args_t&&... args) : _type(type), _raw_data(std::forward(args)...) { static_assert(std::is_constructible_v, "Parameter can't be used to construct a var_t"); } template -MEOJSON_INLINE typename basic_value::var_t basic_value::deep_copy(const var_t& src) +inline typename basic_value::var_t basic_value::deep_copy(const var_t& src) { var_t dst; if (const auto string_ptr = std::get_if(&src)) { @@ -1323,64 +1365,43 @@ MEOJSON_INLINE typename basic_value::var_t basic_value::deep // ****************************** template -MEOJSON_INLINE basic_array::basic_array(const raw_array& arr) : _array_data(arr) -{ - ; -} +inline basic_array::basic_array(std::initializer_list init_list) : _array_data(init_list) +{} template -MEOJSON_INLINE basic_array::basic_array(raw_array&& arr) noexcept : _array_data(std::move(arr)) -{ - ; -} +inline basic_array::basic_array(typename raw_array::size_type size) : _array_data(size) +{} template -MEOJSON_INLINE basic_array::basic_array(std::initializer_list init_list) : _array_data(init_list) -{ - ; -} +inline basic_array::basic_array(const basic_value& val) : basic_array(val.as_array()) +{} template -MEOJSON_INLINE basic_array::basic_array(typename raw_array::size_type size) : _array_data(size) -{ - ; -} - -template -MEOJSON_INLINE basic_array::basic_array(const basic_value& val) - : basic_array(val.as_array()) -{ - ; -} - -template -MEOJSON_INLINE basic_array::basic_array(basic_value&& val) +inline basic_array::basic_array(basic_value&& val) : basic_array(std::move(val.as_array())) -{ - ; -} +{} template -MEOJSON_INLINE void basic_array::clear() noexcept +inline void basic_array::clear() noexcept { _array_data.clear(); } template -MEOJSON_INLINE bool basic_array::erase(size_t pos) +inline bool basic_array::erase(size_t pos) { return erase(_array_data.begin() + pos); } template -MEOJSON_INLINE bool basic_array::erase(iterator iter) +inline bool basic_array::erase(iterator iter) { return _array_data.erase(iter) != _array_data.end(); } template template -MEOJSON_INLINE decltype(auto) basic_array::emplace_back(args_t&&... args) +inline decltype(auto) basic_array::emplace_back(args_t&&... args) { static_assert(std::is_constructible_v, "Parameter can't be used to construct a raw_array::value_type"); @@ -1389,19 +1410,19 @@ MEOJSON_INLINE decltype(auto) basic_array::emplace_back(args_t&&... ar template template -MEOJSON_INLINE decltype(auto) basic_array::push_back(args_t&&... args) +inline decltype(auto) basic_array::push_back(args_t&&... args) { return emplace_back(std::forward(args)...); } template -MEOJSON_INLINE const basic_value& basic_array::at(size_t pos) const +inline const basic_value& basic_array::at(size_t pos) const { return _array_data.at(pos); } template -MEOJSON_INLINE string_t basic_array::to_string() const +inline string_t basic_array::to_string() const { string_t str { '[' }; for (auto iter = _array_data.cbegin(); iter != _array_data.cend();) { @@ -1415,7 +1436,7 @@ MEOJSON_INLINE string_t basic_array::to_string() const } template -MEOJSON_INLINE string_t basic_array::format(size_t indent, size_t indent_times) const +inline string_t basic_array::format(size_t indent, size_t indent_times) const { const string_t tail_indent(indent * indent_times, ' '); const string_t body_indent(indent * (indent_times + 1), ' '); @@ -1432,10 +1453,56 @@ MEOJSON_INLINE string_t basic_array::format(size_t indent, size_t inde return str; } +template +template +inline bool basic_array::all() const +{ + for (const auto& elem : _array_data) { + if (!elem.template is()) { + return false; + } + } + return true; +} + +namespace _to_vector_helper +{ + template + class has_emplace_back + { + template + static auto test(int) -> decltype(std::declval().emplace_back(), std::true_type()); + + template + static std::false_type test(...); + + public: + static constexpr bool value = decltype(test(0))::value; + }; +} + +template +template typename vector_t> +inline vector_t basic_array::to_vector() const +{ + + vector_t result; + if constexpr (_to_vector_helper::has_emplace_back>::value) { + for (const auto& elem : _array_data) { + result.emplace_back(elem.template as()); + } + } + else { + for (const auto& elem : _array_data) { + result.emplace(elem.template as()); + } + } + return result; +} + template template -MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_value, size_t pos, - rest_keys_t&&... rest) const +inline auto basic_array::get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1456,7 +1523,7 @@ MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_val template template -MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_value, size_t pos) const +inline auto basic_array::get_helper(const value_t& default_value, size_t pos) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1493,7 +1560,7 @@ MEOJSON_INLINE auto basic_array::get_helper(const value_t& default_val template template -MEOJSON_INLINE std::optional basic_array::find(size_t pos) const +inline std::optional basic_array::find(size_t pos) const { static_assert(std::is_constructible_v>, "Type can NOT be constructed by basic_value"); @@ -1505,91 +1572,91 @@ MEOJSON_INLINE std::optional basic_array::find(size_t pos) co } template -MEOJSON_INLINE typename basic_array::iterator basic_array::begin() noexcept +inline typename basic_array::iterator basic_array::begin() noexcept { return _array_data.begin(); } template -MEOJSON_INLINE typename basic_array::iterator basic_array::end() noexcept +inline typename basic_array::iterator basic_array::end() noexcept { return _array_data.end(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::begin() const noexcept +inline typename basic_array::const_iterator basic_array::begin() const noexcept { return _array_data.begin(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::end() const noexcept +inline typename basic_array::const_iterator basic_array::end() const noexcept { return _array_data.end(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::cbegin() const noexcept +inline typename basic_array::const_iterator basic_array::cbegin() const noexcept { return _array_data.cbegin(); } template -MEOJSON_INLINE typename basic_array::const_iterator basic_array::cend() const noexcept +inline typename basic_array::const_iterator basic_array::cend() const noexcept { return _array_data.cend(); } template -MEOJSON_INLINE typename basic_array::reverse_iterator basic_array::rbegin() noexcept +inline typename basic_array::reverse_iterator basic_array::rbegin() noexcept { return _array_data.rbegin(); } template -MEOJSON_INLINE typename basic_array::reverse_iterator basic_array::rend() noexcept +inline typename basic_array::reverse_iterator basic_array::rend() noexcept { return _array_data.rend(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::rbegin() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::rbegin() const noexcept { return _array_data.rbegin(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::rend() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::rend() const noexcept { return _array_data.rend(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::crbegin() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::crbegin() const noexcept { return _array_data.crbegin(); } template -MEOJSON_INLINE typename basic_array::const_reverse_iterator basic_array::crend() const noexcept +inline typename basic_array::const_reverse_iterator basic_array::crend() const noexcept { return _array_data.crend(); } template -MEOJSON_INLINE basic_value& basic_array::operator[](size_t pos) +inline basic_value& basic_array::operator[](size_t pos) { return _array_data[pos]; } template -MEOJSON_INLINE const basic_value& basic_array::operator[](size_t pos) const +inline const basic_value& basic_array::operator[](size_t pos) const { return _array_data[pos]; } template -MEOJSON_INLINE basic_array basic_array::operator+(const basic_array& rhs) const& +inline basic_array basic_array::operator+(const basic_array& rhs) const& { basic_array temp = *this; temp._array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); @@ -1597,7 +1664,7 @@ MEOJSON_INLINE basic_array basic_array::operator+(const basi } template -MEOJSON_INLINE basic_array basic_array::operator+(basic_array&& rhs) const& +inline basic_array basic_array::operator+(basic_array&& rhs) const& { basic_array temp = *this; temp._array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), @@ -1606,35 +1673,35 @@ MEOJSON_INLINE basic_array basic_array::operator+(basic_arra } template -MEOJSON_INLINE basic_array basic_array::operator+(const basic_array& rhs) && +inline basic_array basic_array::operator+(const basic_array& rhs) && { _array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); return std::move(*this); } template -MEOJSON_INLINE basic_array basic_array::operator+(basic_array&& rhs) && +inline basic_array basic_array::operator+(basic_array&& rhs) && { _array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); return std::move(*this); } template -MEOJSON_INLINE basic_array& basic_array::operator+=(const basic_array& rhs) +inline basic_array& basic_array::operator+=(const basic_array& rhs) { _array_data.insert(_array_data.end(), rhs.begin(), rhs.end()); return *this; } template -MEOJSON_INLINE basic_array& basic_array::operator+=(basic_array&& rhs) +inline basic_array& basic_array::operator+=(basic_array&& rhs) { _array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); return *this; } template -MEOJSON_INLINE bool basic_array::operator==(const basic_array& rhs) const +inline bool basic_array::operator==(const basic_array& rhs) const { return _array_data == rhs._array_data; } @@ -1644,72 +1711,52 @@ MEOJSON_INLINE bool basic_array::operator==(const basic_array -MEOJSON_INLINE basic_object::basic_object(const raw_object& raw_obj) : _object_data(raw_obj) -{ - ; -} +inline basic_object::basic_object(std::initializer_list init_list) + : _object_data(std::make_move_iterator(init_list.begin()), std::make_move_iterator(init_list.end())) +{} template -MEOJSON_INLINE basic_object::basic_object(raw_object&& raw_obj) : _object_data(std::move(raw_obj)) -{ - ; -} +inline basic_object::basic_object(const basic_value& val) : basic_object(val.as_object()) +{} template -MEOJSON_INLINE basic_object::basic_object(std::initializer_list init_list) -{ - for (const auto& [key, val] : init_list) { - emplace(key, val); - } -} - -template -MEOJSON_INLINE basic_object::basic_object(const basic_value& val) - : basic_object(val.as_object()) -{ - ; -} - -template -MEOJSON_INLINE basic_object::basic_object(basic_value&& val) +inline basic_object::basic_object(basic_value&& val) : basic_object(std::move(val.as_object())) -{ - ; -} +{} template -MEOJSON_INLINE bool basic_object::contains(const string_t& key) const +inline bool basic_object::contains(const string_t& key) const { return _object_data.find(key) != _object_data.cend(); } template -MEOJSON_INLINE const basic_value& basic_object::at(const string_t& key) const +inline const basic_value& basic_object::at(const string_t& key) const { return _object_data.at(key); } template -MEOJSON_INLINE void basic_object::clear() noexcept +inline void basic_object::clear() noexcept { _object_data.clear(); } template -MEOJSON_INLINE bool basic_object::erase(const string_t& key) +inline bool basic_object::erase(const string_t& key) { return _object_data.erase(key) > 0 ? true : false; } template -MEOJSON_INLINE bool basic_object::erase(iterator iter) +inline bool basic_object::erase(iterator iter) { return _object_data.erase(iter) != _object_data.end(); } template template -MEOJSON_INLINE decltype(auto) basic_object::emplace(args_t&&... args) +inline decltype(auto) basic_object::emplace(args_t&&... args) { static_assert(std::is_constructible_v, "Parameter can't be used to construct a raw_object::value_type"); @@ -1718,13 +1765,13 @@ MEOJSON_INLINE decltype(auto) basic_object::emplace(args_t&&... args) template template -MEOJSON_INLINE decltype(auto) basic_object::insert(args_t&&... args) +inline decltype(auto) basic_object::insert(args_t&&... args) { return emplace(std::forward(args)...); } template -MEOJSON_INLINE string_t basic_object::to_string() const +inline string_t basic_object::to_string() const { string_t str { '{' }; for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) { @@ -1739,7 +1786,7 @@ MEOJSON_INLINE string_t basic_object::to_string() const } template -MEOJSON_INLINE string_t basic_object::format(size_t indent, size_t indent_times) const +inline string_t basic_object::format(size_t indent, size_t indent_times) const { const string_t tail_indent(indent * indent_times, ' '); const string_t body_indent(indent * (indent_times + 1), ' '); @@ -1758,10 +1805,33 @@ MEOJSON_INLINE string_t basic_object::format(size_t indent, size_t ind return str; } +template +template +inline bool basic_object::all() const +{ + for (const auto& [_, val] : _object_data) { + if (!val.template is()) { + return false; + } + } + return true; +} + +template +template typename map_t> +inline map_t basic_object::to_map() const +{ + map_t result; + for (const auto& [key, val] : _object_data) { + result.emplace(key, val.template as()); + } + return result; +} + template template -MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_value, const string_t& key, - rest_keys_t&&... rest) const +inline auto basic_object::get_helper(const value_t& default_value, const string_t& key, + rest_keys_t&&... rest) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1782,7 +1852,7 @@ MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_va template template -MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_value, const string_t& key) const +inline auto basic_object::get_helper(const value_t& default_value, const string_t& key) const { constexpr bool is_json = std::is_same_v, value_t> || std::is_same_v, value_t> || @@ -1819,7 +1889,7 @@ MEOJSON_INLINE auto basic_object::get_helper(const value_t& default_va template template -MEOJSON_INLINE std::optional basic_object::find(const string_t& key) const +inline std::optional basic_object::find(const string_t& key) const { static_assert(std::is_constructible_v>, "value_t can NOT be constructed by basic_value"); @@ -1832,55 +1902,55 @@ MEOJSON_INLINE std::optional basic_object::find(const string_ } template -MEOJSON_INLINE typename basic_object::iterator basic_object::begin() noexcept +inline typename basic_object::iterator basic_object::begin() noexcept { return _object_data.begin(); } template -MEOJSON_INLINE typename basic_object::iterator basic_object::end() noexcept +inline typename basic_object::iterator basic_object::end() noexcept { return _object_data.end(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::begin() const noexcept +inline typename basic_object::const_iterator basic_object::begin() const noexcept { return _object_data.begin(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::end() const noexcept +inline typename basic_object::const_iterator basic_object::end() const noexcept { return _object_data.end(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::cbegin() const noexcept +inline typename basic_object::const_iterator basic_object::cbegin() const noexcept { return _object_data.cbegin(); } template -MEOJSON_INLINE typename basic_object::const_iterator basic_object::cend() const noexcept +inline typename basic_object::const_iterator basic_object::cend() const noexcept { return _object_data.cend(); } template -MEOJSON_INLINE basic_value& basic_object::operator[](const string_t& key) +inline basic_value& basic_object::operator[](const string_t& key) { return _object_data[key]; } template -MEOJSON_INLINE basic_value& basic_object::operator[](string_t&& key) +inline basic_value& basic_object::operator[](string_t&& key) { return _object_data[std::move(key)]; } template -MEOJSON_INLINE basic_object basic_object::operator|(const basic_object& rhs) const& +inline basic_object basic_object::operator|(const basic_object& rhs) const& { basic_object temp = *this; temp._object_data.insert(rhs.begin(), rhs.end()); @@ -1888,7 +1958,7 @@ MEOJSON_INLINE basic_object basic_object::operator|(const ba } template -MEOJSON_INLINE basic_object basic_object::operator|(basic_object&& rhs) const& +inline basic_object basic_object::operator|(basic_object&& rhs) const& { basic_object temp = *this; // temp._object_data.merge(std::move(rhs._object_data)); @@ -1897,14 +1967,14 @@ MEOJSON_INLINE basic_object basic_object::operator|(basic_ob } template -MEOJSON_INLINE basic_object basic_object::operator|(const basic_object& rhs) && +inline basic_object basic_object::operator|(const basic_object& rhs) && { _object_data.insert(rhs.begin(), rhs.end()); return std::move(*this); } template -MEOJSON_INLINE basic_object basic_object::operator|(basic_object&& rhs) && +inline basic_object basic_object::operator|(basic_object&& rhs) && { //_object_data.merge(std::move(rhs._object_data)); _object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); @@ -1912,21 +1982,21 @@ MEOJSON_INLINE basic_object basic_object::operator|(basic_ob } template -MEOJSON_INLINE basic_object& basic_object::operator|=(const basic_object& rhs) +inline basic_object& basic_object::operator|=(const basic_object& rhs) { _object_data.insert(rhs.begin(), rhs.end()); return *this; } template -MEOJSON_INLINE basic_object& basic_object::operator|=(basic_object&& rhs) +inline basic_object& basic_object::operator|=(basic_object&& rhs) { _object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end())); return *this; } template -MEOJSON_INLINE bool basic_object::operator==(const basic_object& rhs) const +inline bool basic_object::operator==(const basic_object& rhs) const { return _object_data == rhs._object_data; } @@ -1936,14 +2006,13 @@ MEOJSON_INLINE bool basic_object::operator==(const basic_object -MEOJSON_INLINE std::optional> parser::parse( - const parsing_t& content) +inline std::optional> parser::parse(const parsing_t& content) { return parser(content.cbegin(), content.cend()).parse(); } template -MEOJSON_INLINE std::optional> parser::parse() +inline std::optional> parser::parse() { if (!skip_whitespace()) { return std::nullopt; @@ -1975,7 +2044,7 @@ MEOJSON_INLINE std::optional> parser -MEOJSON_INLINE basic_value parser::parse_value() +inline basic_value parser::parse_value() { switch (*_cur) { case 'n': @@ -2007,10 +2076,10 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_null() +inline basic_value parser::parse_null() { for (const auto& ch : null_string()) { - if (*_cur == ch) { + if (_cur != _end && *_cur == ch) { ++_cur; } else { @@ -2022,12 +2091,12 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_boolean() +inline basic_value parser::parse_boolean() { switch (*_cur) { case 't': for (const auto& ch : true_string()) { - if (*_cur == ch) { + if (_cur != _end && *_cur == ch) { ++_cur; } else { @@ -2037,7 +2106,7 @@ MEOJSON_INLINE basic_value parser:: return true; case 'f': for (const auto& ch : false_string()) { - if (*_cur == ch) { + if (_cur != _end && *_cur == ch) { ++_cur; } else { @@ -2051,7 +2120,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_number() +inline basic_value parser::parse_number() { const auto first = _cur; if (*_cur == '-') { @@ -2090,7 +2159,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_string() +inline basic_value parser::parse_string() { auto string_opt = parse_stdstring(); if (!string_opt) { @@ -2100,7 +2169,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_array() +inline basic_value parser::parse_array() { if (*_cur == '[') { ++_cur; @@ -2151,7 +2220,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE basic_value parser::parse_object() +inline basic_value parser::parse_object() { if (*_cur == '{') { ++_cur; @@ -2215,7 +2284,7 @@ MEOJSON_INLINE basic_value parser:: } template -MEOJSON_INLINE std::optional parser::parse_stdstring() +inline std::optional parser::parse_stdstring() { if (*_cur == '"') { ++_cur; @@ -2228,9 +2297,9 @@ MEOJSON_INLINE std::optional parser auto no_escape_beg = _cur; while (_cur != _end) { - if constexpr (sizeof(*_cur) == 1) { - if constexpr (accel_traits::available) { - skip_string_literal(); + if constexpr (sizeof(*_cur) == 1 && accel_traits::available) { + if (!skip_string_literal_with_accel()) { + return std::nullopt; } } switch (*_cur) { @@ -2291,16 +2360,18 @@ MEOJSON_INLINE std::optional parser } template -MEOJSON_INLINE void parser::skip_string_literal() +inline bool parser::skip_string_literal_with_accel() { if constexpr (sizeof(*_cur) != 1) { - return; + return false; } + while (_end - _cur >= accel_traits::step) { auto pack = accel_traits::load_unaligned(&(*_cur)); auto result = accel_traits::less(pack, 32); result = accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast('"'))); result = accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast('\\'))); + if (accel_traits::is_all_zero(result)) { _cur += accel_traits::step; } @@ -2310,10 +2381,12 @@ MEOJSON_INLINE void parser::skip_string_liter break; } } + + return _cur != _end; } template -MEOJSON_INLINE bool parser::skip_whitespace() noexcept +inline bool parser::skip_whitespace() noexcept { while (_cur != _end) { switch (*_cur) { @@ -2333,7 +2406,7 @@ MEOJSON_INLINE bool parser::skip_whitespace() } template -MEOJSON_INLINE bool parser::skip_digit() +inline bool parser::skip_digit() { // At least one digit if (_cur != _end && std::isdigit(*_cur)) { @@ -2360,14 +2433,20 @@ MEOJSON_INLINE bool parser::skip_digit() // ************************* template -MEOJSON_INLINE auto parse(const parsing_t& content) +auto parse(const parsing_t& content) { using string_t = std::basic_string; return parser::parse(content); } +template +auto parse(char_t* content) +{ + return parse(std::basic_string_view> { content }); +} + template -MEOJSON_INLINE auto parse(istream_t& ifs, bool check_bom) +auto parse(istream_t& ifs, bool check_bom) { using string_t = std::basic_string; @@ -2394,7 +2473,7 @@ MEOJSON_INLINE auto parse(istream_t& ifs, bool check_bom) } template -MEOJSON_INLINE auto open(const path_t& filepath, bool check_bom) +auto open(const path_t& filepath, bool check_bom) { using char_t = typename ifstream_t::char_type; using string_t = std::basic_string; @@ -2443,96 +2522,62 @@ ostream_t& operator<<(ostream_t& out, const basic_object& obj) namespace literals { - MEOJSON_INLINE value operator""_json(const char* str, size_t len) + inline value operator""_json(const char* str, size_t len) { return operator""_jvalue(str, len); } - MEOJSON_INLINE wvalue operator""_json(const wchar_t* str, size_t len) - { - return operator""_jvalue(str, len); - } - MEOJSON_INLINE u16value operator""_json(const char16_t* str, size_t len) - { - return operator""_jvalue(str, len); - } - MEOJSON_INLINE u32value operator""_json(const char32_t* str, size_t len) + inline wvalue operator""_json(const wchar_t* str, size_t len) { return operator""_jvalue(str, len); } - MEOJSON_INLINE value operator""_jvalue(const char* str, size_t len) + inline value operator""_jvalue(const char* str, size_t len) { return parse(std::string_view(str, len)).value_or(value()); } - MEOJSON_INLINE wvalue operator""_jvalue(const wchar_t* str, size_t len) + inline wvalue operator""_jvalue(const wchar_t* str, size_t len) { return parse(std::wstring_view(str, len)).value_or(wvalue()); } - MEOJSON_INLINE u16value operator""_jvalue(const char16_t* str, size_t len) - { - return parse(std::u16string_view(str, len)).value_or(u16value()); - } - MEOJSON_INLINE u32value operator""_jvalue(const char32_t* str, size_t len) - { - return parse(std::u32string_view(str, len)).value_or(u32value()); - } - MEOJSON_INLINE array operator""_jarray(const char* str, size_t len) + inline array operator""_jarray(const char* str, size_t len) { auto val = parse(std::string_view(str, len)).value_or(value()); return val.is_array() ? val.as_array() : array(); } - MEOJSON_INLINE warray operator""_jarray(const wchar_t* str, size_t len) + inline warray operator""_jarray(const wchar_t* str, size_t len) { auto val = parse(std::wstring_view(str, len)).value_or(wvalue()); return val.is_array() ? val.as_array() : warray(); } - MEOJSON_INLINE u16array operator""_jarray(const char16_t* str, size_t len) - { - auto val = parse(std::u16string_view(str, len)).value_or(u16value()); - return val.is_array() ? val.as_array() : u16array(); - } - MEOJSON_INLINE u32array operator""_jarray(const char32_t* str, size_t len) - { - auto val = parse(std::u32string_view(str, len)).value_or(u32value()); - return val.is_array() ? val.as_array() : u32array(); - } - MEOJSON_INLINE object operator""_jobject(const char* str, size_t len) + inline object operator""_jobject(const char* str, size_t len) { auto val = parse(std::string_view(str, len)).value_or(value()); return val.is_object() ? val.as_object() : object(); } - MEOJSON_INLINE wobject operator""_jobject(const wchar_t* str, size_t len) + inline wobject operator""_jobject(const wchar_t* str, size_t len) { auto val = parse(std::wstring_view(str, len)).value_or(wvalue()); return val.is_object() ? val.as_object() : wobject(); } - MEOJSON_INLINE u16object operator""_jobject(const char16_t* str, size_t len) - { - auto val = parse(std::u16string_view(str, len)).value_or(u16value()); - return val.is_object() ? val.as_object() : u16object(); - } - MEOJSON_INLINE u32object operator""_jobject(const char32_t* str, size_t len) - { - auto val = parse(std::u32string_view(str, len)).value_or(u32value()); - return val.is_object() ? val.as_object() : u32object(); - } } // namespace literals template -MEOJSON_INLINE const basic_value invalid_value() +const basic_value invalid_value() { return basic_value(basic_value::value_type::invalid, typename basic_value::var_t()); } namespace _serialization_helper { - template + template class has_output_operator { + using ostringstream_t = std::basic_ostringstream, std::allocator>; + template - static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); + static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); template static std::false_type test(...); @@ -2541,66 +2586,74 @@ namespace _serialization_helper static constexpr bool value = decltype(test(0))::value; }; - template - using void_t = void; - template constexpr bool is_container = false; template - constexpr bool is_container< - T, void_t().begin()), decltype(std::declval().end())>> = - true; + constexpr bool is_container>> = + std::is_same_v>; - // something like a map template - constexpr bool is_associative_container = false; + constexpr bool is_map = false; template - constexpr bool is_associative_container> = is_container; + constexpr bool is_map> = is_container; - // something like a vector template - constexpr bool is_sequence_container = false; + constexpr bool is_collection = false; template - constexpr bool is_sequence_container = is_container && !is_associative_container; + constexpr bool is_collection = is_container && !is_map; - template - MEOJSON_INLINE string_t to_stream_string(input_t&& arg) + template + struct string_converter { - if constexpr (has_output_operator::value) { - using char_t = typename string_t::value_type; - using stringstream_t = std::basic_stringstream, std::allocator>; + using char_t = typename string_t::value_type; + using ostringstream_t = std::basic_ostringstream, std::allocator>; - stringstream_t ss; - ss << std::forward(arg); - return std::move(ss).str(); - } - else { - static_assert(!sizeof(input_t), "Unable to convert type to string, there is no operator <<."); - } - } + template + static constexpr bool is_convertible = + std::is_constructible_v || (loose && has_output_operator::value); - template - MEOJSON_INLINE string_t to_string(input_t&& arg) + template + string_t operator()(input_t&& arg) const + { + if constexpr (std::is_constructible_v) { + return string_t(std::forward(arg)); + } + else if constexpr (!loose) { + static_assert(!sizeof(input_t), "Unable to convert type to string."); + } + else if constexpr (has_output_operator::value) { + ostringstream_t os; + os << std::forward(arg); + return std::move(os).str(); + } + else { + return serialize(std::forward(arg), *this).dumps(); + } + } + }; + + template + void unable_to_serialize() { - if constexpr (std::is_constructible_v) { - return arg; - } - else if constexpr (loose) { - return to_stream_string(std::forward(arg)); - } - else { - static_assert(!sizeof(input_t), "Unable to convert type to string."); - } - } -} + static_assert(!sizeof(T), "Unable to serialize T. " + "You can define the conversion of T to json, or overload operator<< for it. " +#ifdef _MSC_VER + "See T below: " __FUNCSIG__ +#else + //"See T below: " __PRETTY_FUNCTION__ -template -MEOJSON_INLINE basic_value serialize(any_t&& arg) +#endif + ); + } +} // namespace _serialization_helper + +template +basic_value serialize(any_t&& arg, string_converter_t&& string_converter) { using namespace _serialization_helper; if constexpr (std::is_constructible_v, any_t>) { - return arg; + return basic_value(std::forward(arg)); } else if constexpr (std::is_constructible_v, any_t>) { return basic_array(std::forward(arg)); @@ -2608,33 +2661,38 @@ MEOJSON_INLINE basic_value serialize(any_t&& arg) else if constexpr (std::is_constructible_v, any_t>) { return basic_object(std::forward(arg)); } - else if constexpr (is_sequence_container>) { + else if constexpr (std::decay_t::template is_convertible) { + return string_converter(std::forward(arg)); + } + else if constexpr (is_collection>) { basic_value result; for (auto&& val : arg) { using value_t = decltype(val); - result.emplace(serialize(std::forward(val))); + result.emplace(serialize(std::forward(val), + std::forward(string_converter))); } return result; } - else if constexpr (is_associative_container>) { + else if constexpr (is_map>) { basic_value result; for (auto&& [key, val] : arg) { using key_t = decltype(key); using value_t = decltype(val); - result.emplace(to_string(std::forward(key)), - serialize(std::forward(val))); + result.emplace(string_converter(std::forward(key)), + serialize(std::forward(val), + std::forward(string_converter))); } return result; } else { - return to_string(std::forward(arg)); + unable_to_serialize(); } } template -MEOJSON_INLINE static constexpr string_t unescape_string(const string_t& str) +static constexpr string_t unescape_string(const string_t& str) { using char_t = typename string_t::value_type; diff --git a/3rdparty/include/meojson/packed_bytes.hpp b/3rdparty/include/meojson/packed_bytes.hpp index c4717776ce..e0f68559a4 100644 --- a/3rdparty/include/meojson/packed_bytes.hpp +++ b/3rdparty/include/meojson/packed_bytes.hpp @@ -1,25 +1,32 @@ #pragma once + #include #include #include + #include "bitops.hpp" #if defined(__GNUC__) || defined(__clang__) -#define __packed_bytes_strong_inline __attribute__((always_inline)) +#define __packed_bytes_strong_inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define __packed_bytes_strong_inline __forceinline #else #define __packed_bytes_strong_inline inline #endif -struct packed_bytes_trait_none { +namespace json::_packed_bytes +{ +struct packed_bytes_trait_none +{ static constexpr bool available = false; }; template -struct packed_bytes { +struct packed_bytes +{ using traits = packed_bytes_trait_none; }; +} #if defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP) #include "packed_bytes_x86.hpp" @@ -27,100 +34,109 @@ struct packed_bytes { #include "packed_bytes_arm.hpp" #endif -struct packed_bytes_trait_uint64 { +namespace json::_packed_bytes +{ +struct packed_bytes_trait_uint64 +{ static constexpr bool available = sizeof(void*) >= 8; static constexpr auto step = 8; - using value_type = std::enable_if_t= 8, uint64_t>; + using value_type = uint64_t; - __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { + __packed_bytes_strong_inline static value_type load_unaligned(const void* ptr) + { value_type result; memcpy((void*)&result, ptr, 8); return result; } - __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { - return (((x) - UINT64_C(0x0101010101010101) * (n)) & ~(x) & UINT64_C(0x8080808080808080)); - } - - __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) { - return (((v) - UINT64_C(0x0101010101010101)) & ~(v) & UINT64_C(0x8080808080808080)); - } - - __packed_bytes_strong_inline static bool is_all_zero(value_type v) + __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { - return v == UINT64_C(0); + return (((x)-UINT64_C(0x0101010101010101) * (n)) & ~(x)&UINT64_C(0x8080808080808080)); } - __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { + __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) + { + return (((v)-UINT64_C(0x0101010101010101)) & ~(v)&UINT64_C(0x8080808080808080)); + } + + __packed_bytes_strong_inline static bool is_all_zero(value_type v) { return v == UINT64_C(0); } + + __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) + { return is_zero_memberwise((x) ^ (UINT64_C(0x0101010101010101) * (n))); } - __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { - return a | b; - } + __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return a | b; } - __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { - if (json::__bitops::is_little_endian()) - return json::__bitops::countr_zero(x) / 8; + __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) + { + if (_bitops::is_little_endian()) + return _bitops::countr_zero(x) / 8; else - return json::__bitops::countl_zero(x) / 8; + return _bitops::countl_zero(x) / 8; } }; -struct packed_bytes_trait_uint32 { +struct packed_bytes_trait_uint32 +{ static constexpr bool available = true; static constexpr auto step = 4; using value_type = uint32_t; - __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { + __packed_bytes_strong_inline static value_type load_unaligned(const void* ptr) + { value_type result; memcpy((void*)&result, ptr, 4); return result; } - __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { + __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) + { return (((x) - ~UINT32_C(0) / 255 * (n)) & ~(x) & ~UINT32_C(0) / 255 * 128); } - __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) { - return (((v) - UINT32_C(0x01010101)) & ~(v) & UINT32_C(0x80808080));; + __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) + { + return (((v)-UINT32_C(0x01010101)) & ~(v)&UINT32_C(0x80808080)); + ; } - __packed_bytes_strong_inline static bool is_all_zero(value_type v) { - return v == UINT32_C(0); - } + __packed_bytes_strong_inline static bool is_all_zero(value_type v) { return v == UINT32_C(0); } - __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { + __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) + { return is_zero_memberwise((x) ^ (~UINT32_C(0) / 255 * (n))); } - __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { - return a | b; - } + __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return a | b; } - __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { - if (json::__bitops::is_little_endian()) - return json::__bitops::countr_zero(x) / 8; + __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) + { + if (_bitops::is_little_endian()) + return _bitops::countr_zero(x) / 8; else - return json::__bitops::countl_zero(x) / 8; + return _bitops::countl_zero(x) / 8; } }; template <> -struct packed_bytes<8> { - using traits = std::enable_if_t; +struct packed_bytes<8> +{ + using traits = packed_bytes_trait_uint64; }; template <> -struct packed_bytes<4> { +struct packed_bytes<4> +{ using traits = packed_bytes_trait_uint32; }; template using packed_bytes_trait = typename packed_bytes::traits; -using packed_bytes_trait_max = std::conditional_t::available, packed_bytes_trait<32>, - std::conditional_t::available, packed_bytes_trait<16>, - std::conditional_t::available, packed_bytes_trait<8>, - packed_bytes_trait<4> - >>>; +using packed_bytes_trait_max = + std::conditional_t::available, packed_bytes_trait<32>, + std::conditional_t::available, packed_bytes_trait<16>, + std::conditional_t::available, packed_bytes_trait<8>, + packed_bytes_trait<4>>>>; +} // namespace json::_packed_bytes diff --git a/3rdparty/include/meojson/packed_bytes_arm.hpp b/3rdparty/include/meojson/packed_bytes_arm.hpp index 86fc07fb8c..05e59f32ae 100644 --- a/3rdparty/include/meojson/packed_bytes_arm.hpp +++ b/3rdparty/include/meojson/packed_bytes_arm.hpp @@ -9,34 +9,31 @@ #define __packed_bytes_trait_arm64 #endif -struct packed_bytes_trait_neon { +namespace json::_packed_bytes +{ +struct packed_bytes_trait_neon +{ static constexpr bool available = true; static constexpr auto step = 16; using value_type = uint8x16_t; - __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { - return vld1q_u8((uint8_t*)ptr); - } + __packed_bytes_strong_inline static value_type load_unaligned(const void* ptr) { return vld1q_u8((uint8_t*)ptr); } - __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { + __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) + { auto bcast = vdupq_n_u8(n); auto is_less = vcltq_u8(x, bcast); return is_less; } - __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { - return vceqq_u8(x, vdupq_n_u8(n)); - } + __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { return vceqq_u8(x, vdupq_n_u8(n)); } - __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { - return vceqq_u8(x, y); - } + __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { return vceqq_u8(x, y); } - __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { - return vorrq_u8(a, b); - } + __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return vorrq_u8(a, b); } - __packed_bytes_strong_inline static bool is_all_zero(value_type x) { + __packed_bytes_strong_inline static bool is_all_zero(value_type x) + { #ifdef __packed_bytes_trait_arm64 return vmaxvq_u8(x) == 0; #else @@ -46,18 +43,20 @@ struct packed_bytes_trait_neon { #endif } - __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { + __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) + { // https://community.arm.com/arm-community-blogs/b/infrastructure-solutions-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon auto cmp = equal(x, 0); auto res = vshrn_n_u16(cmp, 4); auto mask64 = vget_lane_u64(vreinterpret_u64_u8(res), 0); - return json::__bitops::countr_one(mask64) >> 2; + return _bitops::countr_one(mask64) >> 2; } }; template <> -struct packed_bytes<16> { +struct packed_bytes<16> +{ using traits = packed_bytes_trait_neon; }; - +} #endif diff --git a/3rdparty/include/meojson/packed_bytes_x86.hpp b/3rdparty/include/meojson/packed_bytes_x86.hpp index afa6951d86..ff1eb467e4 100644 --- a/3rdparty/include/meojson/packed_bytes_x86.hpp +++ b/3rdparty/include/meojson/packed_bytes_x86.hpp @@ -2,21 +2,26 @@ #include "packed_bytes.hpp" #include -#if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER) +#if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER) // MSVC enables all SSE4.1 intrinsics by default #include #endif -struct packed_bytes_trait_sse { +namespace json::_packed_bytes +{ +struct packed_bytes_trait_sse +{ static constexpr bool available = true; static constexpr auto step = 16; using value_type = __m128i; - __packed_bytes_strong_inline static value_type load_unaligned(const void *ptr) { + __packed_bytes_strong_inline static value_type load_unaligned(const void* ptr) + { return _mm_loadu_si128(reinterpret_cast(ptr)); } - __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) { + __packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) + { auto bcast = _mm_set1_epi8(static_cast(n)); auto all1 = _mm_set1_epi8(-1); auto max_with_n = _mm_max_epu8(x, bcast); @@ -25,19 +30,17 @@ struct packed_bytes_trait_sse { return is_less; } - __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { + __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) + { return _mm_cmpeq_epi8(x, _mm_set1_epi8(static_cast(n))); } - __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { - return _mm_cmpeq_epi8(x, y); - } + __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { return _mm_cmpeq_epi8(x, y); } - __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { - return _mm_or_si128(a, b); - } + __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return _mm_or_si128(a, b); } - __packed_bytes_strong_inline static bool is_all_zero(value_type x) { + __packed_bytes_strong_inline static bool is_all_zero(value_type x) + { #if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER) // SSE4.1 path return !!_mm_testz_si128(x, x); @@ -49,22 +52,25 @@ struct packed_bytes_trait_sse { #endif } - __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { + __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) + { auto cmp = _mm_cmpeq_epi8(x, _mm_set1_epi8(0)); auto mask = (uint16_t)_mm_movemask_epi8(cmp); - return json::__bitops::countr_one((uint32_t)mask); + return _bitops::countr_one((uint32_t)mask); } }; template <> -struct packed_bytes<16> { +struct packed_bytes<16> +{ using traits = packed_bytes_trait_sse; }; - - +} #ifdef __AVX2__ #include +namespace json::_packed_bytes +{ struct packed_bytes_trait_avx2 { static constexpr bool available = true; @@ -91,33 +97,29 @@ struct packed_bytes_trait_avx2 return _mm256_cmpeq_epi8(x, _mm256_set1_epi8(static_cast(n))); } - __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) - { - return _mm256_cmpeq_epi8(x, y); - } + __packed_bytes_strong_inline static value_type equal(value_type x, value_type y) { return _mm256_cmpeq_epi8(x, y); } __packed_bytes_strong_inline static value_type bitwise_or(value_type a, value_type b) { return _mm256_or_si256(a, b); } - __packed_bytes_strong_inline static bool is_all_zero(value_type x) - { - return (bool)_mm256_testz_si256(x, x); - } + __packed_bytes_strong_inline static bool is_all_zero(value_type x) { return (bool)_mm256_testz_si256(x, x); } __packed_bytes_strong_inline static size_t first_nonzero_byte(value_type x) { auto cmp = _mm256_cmpeq_epi8(x, _mm256_set1_epi8(0)); auto mask = (uint32_t)_mm256_movemask_epi8(cmp); // AVX512 alternative: _mm_cmpeq_epi8_mask - return json::__bitops::countr_one(mask); + return _bitops::countr_one(mask); } }; template <> -struct packed_bytes<32> { +struct packed_bytes<32> +{ using traits = packed_bytes_trait_avx2; }; +} #endif