From 5ec31e869b2381177381271544fee346ebda2ddc Mon Sep 17 00:00:00 2001 From: MistEO Date: Mon, 4 Dec 2023 17:06:18 +0800 Subject: [PATCH] chore: update meojson --- 3rdparty/include/meojson/bitops.hpp | 166 ++++++++++-------- 3rdparty/include/meojson/json.hpp | 47 ++++- 3rdparty/include/meojson/packed_bytes.hpp | 104 ++++++----- 3rdparty/include/meojson/packed_bytes_arm.hpp | 37 ++-- 3rdparty/include/meojson/packed_bytes_x86.hpp | 56 +++--- 5 files changed, 248 insertions(+), 162 deletions(-) diff --git a/3rdparty/include/meojson/bitops.hpp b/3rdparty/include/meojson/bitops.hpp index ec6137fd6..e1db493af 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); } +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; - } +// 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 81ff96d5b..afa714117 100644 --- a/3rdparty/include/meojson/json.hpp +++ b/3rdparty/include/meojson/json.hpp @@ -194,6 +194,8 @@ class basic_value 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> @@ -313,6 +315,8 @@ class basic_array { return format(indent, 0); } + template + bool all() const; template typename vector_t = std::vector> vector_t to_vector() const; @@ -425,6 +429,8 @@ class basic_object { return format(indent, 0); } + template + bool all() const; template typename map_t = std::map> map_t to_map() const; @@ -488,7 +494,7 @@ class basic_object // **************************** template + typename accel_traits = _packed_bytes::packed_bytes_trait_max> class parser { public: @@ -1152,6 +1158,21 @@ inline string_t basic_value::format(size_t indent, size_t indent_times } } +template +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 @@ -1432,6 +1453,18 @@ inline string_t basic_array::format(size_t indent, size_t indent_times 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 @@ -1772,6 +1805,18 @@ inline string_t basic_object::format(size_t indent, size_t indent_time 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 diff --git a/3rdparty/include/meojson/packed_bytes.hpp b/3rdparty/include/meojson/packed_bytes.hpp index c4717776c..76bd43bec 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>; - __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 value_type less(value_type x, uint8_t n) + { + return (((x)-UINT64_C(0x0101010101010101) * (n)) & ~(x)&UINT64_C(0x8080808080808080)); } - __packed_bytes_strong_inline static bool is_all_zero(value_type v) + __packed_bytes_strong_inline static value_type is_zero_memberwise(value_type v) { - return v == UINT64_C(0); + return (((v)-UINT64_C(0x0101010101010101)) & ~(v)&UINT64_C(0x8080808080808080)); } - __packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) { + __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> { +struct packed_bytes<8> +{ using traits = std::enable_if_t; }; 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 86fc07fb8..05e59f32a 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 afa6951d8..ff1eb467e 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