mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
feat: update meojson to v3.1.1 (#6956)
This commit is contained in:
88
3rdparty/include/meojson/bitops.hpp
vendored
Normal file
88
3rdparty/include/meojson/bitops.hpp
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
#include <bit>
|
||||
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;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include <cstdint>
|
||||
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);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#endif // __AVX2__
|
||||
#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;
|
||||
}
|
||||
}
|
||||
#endif // C++20
|
||||
355
3rdparty/include/meojson/json.hpp
vendored
355
3rdparty/include/meojson/json.hpp
vendored
@@ -5,11 +5,15 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "packed_bytes.hpp"
|
||||
|
||||
#define MEOJSON_INLINE inline
|
||||
|
||||
namespace json
|
||||
@@ -131,7 +135,7 @@ public:
|
||||
|
||||
bool as_boolean() const;
|
||||
int as_integer() const;
|
||||
// unsigned as_unsigned() const;
|
||||
unsigned as_unsigned() const;
|
||||
long as_long() const;
|
||||
unsigned long as_unsigned_long() const;
|
||||
long long as_long_long() const;
|
||||
@@ -182,16 +186,16 @@ public:
|
||||
basic_value<string_t>& operator[](const string_t& key);
|
||||
basic_value<string_t>& operator[](string_t&& key);
|
||||
|
||||
basic_value<string_t> operator|(const basic_object<string_t>& rhs) &;
|
||||
basic_value<string_t> operator|(basic_object<string_t>&& rhs) &;
|
||||
basic_value<string_t> operator|(const basic_object<string_t>& rhs) const&;
|
||||
basic_value<string_t> operator|(basic_object<string_t>&& rhs) const&;
|
||||
basic_value<string_t> operator|(const basic_object<string_t>& rhs) &&;
|
||||
basic_value<string_t> operator|(basic_object<string_t>&& rhs) &&;
|
||||
|
||||
basic_value<string_t>& operator|=(const basic_object<string_t>& rhs);
|
||||
basic_value<string_t>& operator|=(basic_object<string_t>&& rhs);
|
||||
|
||||
basic_value<string_t> operator+(const basic_array<string_t>& rhs) &;
|
||||
basic_value<string_t> operator+(basic_array<string_t>&& rhs) &;
|
||||
basic_value<string_t> operator+(const basic_array<string_t>& rhs) const&;
|
||||
basic_value<string_t> operator+(basic_array<string_t>&& rhs) const&;
|
||||
basic_value<string_t> operator+(const basic_array<string_t>& rhs) &&;
|
||||
basic_value<string_t> operator+(basic_array<string_t>&& rhs) &&;
|
||||
|
||||
@@ -200,6 +204,7 @@ public:
|
||||
|
||||
explicit operator bool() const { return as_boolean(); }
|
||||
explicit operator int() const { return as_integer(); }
|
||||
explicit operator unsigned() const { return as_unsigned(); }
|
||||
explicit operator long() const { return as_long(); }
|
||||
explicit operator unsigned long() const { return as_unsigned_long(); }
|
||||
explicit operator long long() const { return as_long_long(); }
|
||||
@@ -263,8 +268,12 @@ public:
|
||||
|
||||
explicit basic_array(const basic_value<string_t>& val);
|
||||
explicit basic_array(basic_value<string_t>&& val);
|
||||
template <typename array_t>
|
||||
basic_array(array_t arr);
|
||||
template <typename array_t, typename _ = std::enable_if_t<
|
||||
std::is_constructible_v<value_type, typename std::decay_t<array_t>::value_type>>>
|
||||
basic_array(array_t arr)
|
||||
{
|
||||
_array_data.assign(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end()));
|
||||
}
|
||||
|
||||
~basic_array() noexcept = default;
|
||||
|
||||
@@ -297,6 +306,7 @@ public:
|
||||
|
||||
void clear() noexcept;
|
||||
bool erase(size_t pos);
|
||||
bool erase(iterator iter);
|
||||
|
||||
iterator begin() noexcept;
|
||||
iterator end() noexcept;
|
||||
@@ -315,8 +325,8 @@ public:
|
||||
const basic_value<string_t>& operator[](size_t pos) const;
|
||||
basic_value<string_t>& operator[](size_t pos);
|
||||
|
||||
basic_array<string_t> operator+(const basic_array<string_t>& rhs) &;
|
||||
basic_array<string_t> operator+(basic_array<string_t>&& rhs) &;
|
||||
basic_array<string_t> operator+(const basic_array<string_t>& rhs) const&;
|
||||
basic_array<string_t> operator+(basic_array<string_t>&& rhs) const&;
|
||||
basic_array<string_t> operator+(const basic_array<string_t>& rhs) &&;
|
||||
basic_array<string_t> operator+(basic_array<string_t>&& rhs) &&;
|
||||
|
||||
@@ -356,6 +366,8 @@ class basic_object
|
||||
|
||||
public:
|
||||
using raw_object = std::map<string_t, basic_value<string_t>>;
|
||||
using key_type = typename raw_object::key_type;
|
||||
using mapped_type = typename raw_object::mapped_type;
|
||||
using value_type = typename raw_object::value_type;
|
||||
using iterator = typename raw_object::iterator;
|
||||
using const_iterator = typename raw_object::const_iterator;
|
||||
@@ -370,8 +382,12 @@ public:
|
||||
basic_object(std::initializer_list<value_type> init_list);
|
||||
explicit basic_object(const basic_value<string_t>& val);
|
||||
explicit basic_object(basic_value<string_t>&& val);
|
||||
template <typename map_t>
|
||||
basic_object(map_t map);
|
||||
template <typename map_t, typename _ = std::enable_if_t<
|
||||
std::is_constructible_v<value_type, typename std::decay_t<map_t>::value_type>>>
|
||||
basic_object(map_t map)
|
||||
{
|
||||
_object_data.insert(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end()));
|
||||
}
|
||||
|
||||
~basic_object() = default;
|
||||
|
||||
@@ -404,6 +420,7 @@ public:
|
||||
|
||||
void clear() noexcept;
|
||||
bool erase(const string_t& key);
|
||||
bool erase(iterator iter);
|
||||
|
||||
iterator begin() noexcept;
|
||||
iterator end() noexcept;
|
||||
@@ -415,8 +432,8 @@ public:
|
||||
basic_value<string_t>& operator[](const string_t& key);
|
||||
basic_value<string_t>& operator[](string_t&& key);
|
||||
|
||||
basic_object<string_t> operator|(const basic_object<string_t>& rhs) &;
|
||||
basic_object<string_t> operator|(basic_object<string_t>&& rhs) &;
|
||||
basic_object<string_t> operator|(const basic_object<string_t>& rhs) const&;
|
||||
basic_object<string_t> operator|(basic_object<string_t>&& rhs) const&;
|
||||
basic_object<string_t> operator|(const basic_object<string_t>& rhs) &&;
|
||||
basic_object<string_t> operator|(basic_object<string_t>&& rhs) &&;
|
||||
|
||||
@@ -448,7 +465,8 @@ private:
|
||||
// * parser declare *
|
||||
// ****************************
|
||||
|
||||
template <typename string_t = default_string_t, typename parsing_t = void>
|
||||
template <typename string_t = default_string_t, typename parsing_t = void,
|
||||
typename accel_traits = packed_bytes_trait_max>
|
||||
class parser
|
||||
{
|
||||
public:
|
||||
@@ -476,6 +494,7 @@ private:
|
||||
// parse and return a string_t
|
||||
std::optional<string_t> parse_stdstring();
|
||||
|
||||
void skip_string_literal();
|
||||
bool skip_whitespace() noexcept;
|
||||
bool skip_digit();
|
||||
|
||||
@@ -520,13 +539,6 @@ auto parse(istream_t& istream, bool check_bom);
|
||||
template <typename ifstream_t = std::ifstream, typename path_t = void>
|
||||
auto open(const path_t& path, bool check_bom = false);
|
||||
|
||||
template <typename ostream_t, typename string_t>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_value<string_t>& val);
|
||||
template <typename ostream_t, typename string_t>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_array<string_t>& arr);
|
||||
template <typename ostream_t, typename string_t>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_object<string_t>& obj);
|
||||
|
||||
namespace literals
|
||||
{
|
||||
value operator""_json(const char* str, size_t len);
|
||||
@@ -553,6 +565,9 @@ namespace literals
|
||||
template <typename string_t = default_string_t>
|
||||
const basic_value<string_t> invalid_value();
|
||||
|
||||
template <bool loose, typename any_t, typename string_t = default_string_t>
|
||||
basic_value<string_t> serialize(any_t&& arg);
|
||||
|
||||
// ******************************
|
||||
// * basic_value impl *
|
||||
// ******************************
|
||||
@@ -893,6 +908,13 @@ MEOJSON_INLINE int basic_value<string_t>::as_integer() const
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE unsigned basic_value<string_t>::as_unsigned() const
|
||||
{
|
||||
// I don't know why there is no std::stou.
|
||||
return static_cast<unsigned>(as_unsigned_long());
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE long basic_value<string_t>::as_long() const
|
||||
{
|
||||
@@ -1193,13 +1215,13 @@ MEOJSON_INLINE basic_value<string_t>& basic_value<string_t>::operator[](string_t
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator|(const basic_object<string_t>& rhs) &
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator|(const basic_object<string_t>& rhs) const&
|
||||
{
|
||||
return as_object() | rhs;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator|(basic_object<string_t>&& rhs) &
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator|(basic_object<string_t>&& rhs) const&
|
||||
{
|
||||
return as_object() | std::move(rhs);
|
||||
}
|
||||
@@ -1231,13 +1253,13 @@ MEOJSON_INLINE basic_value<string_t>& basic_value<string_t>::operator|=(basic_ob
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator+(const basic_array<string_t>& rhs) &
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator+(const basic_array<string_t>& rhs) const&
|
||||
{
|
||||
return as_array() + rhs;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator+(basic_array<string_t>&& rhs) &
|
||||
MEOJSON_INLINE basic_value<string_t> basic_value<string_t>::operator+(basic_array<string_t>&& rhs) const&
|
||||
{
|
||||
return as_array() + std::move(rhs);
|
||||
}
|
||||
@@ -1338,15 +1360,6 @@ MEOJSON_INLINE basic_array<string_t>::basic_array(basic_value<string_t>&& val)
|
||||
;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename array_t>
|
||||
MEOJSON_INLINE basic_array<string_t>::basic_array(array_t arr)
|
||||
{
|
||||
static_assert(std::is_constructible_v<value_type, typename array_t::value_type>,
|
||||
"array_t can not construct a json array");
|
||||
_array_data.assign(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end()));
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE void basic_array<string_t>::clear() noexcept
|
||||
{
|
||||
@@ -1356,7 +1369,13 @@ MEOJSON_INLINE void basic_array<string_t>::clear() noexcept
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE bool basic_array<string_t>::erase(size_t pos)
|
||||
{
|
||||
return _array_data.erase(pos) != _array_data.end();
|
||||
return erase(_array_data.begin() + pos);
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE bool basic_array<string_t>::erase(iterator iter)
|
||||
{
|
||||
return _array_data.erase(iter) != _array_data.end();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
@@ -1570,7 +1589,7 @@ MEOJSON_INLINE const basic_value<string_t>& basic_array<string_t>::operator[](si
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_array<string_t> basic_array<string_t>::operator+(const basic_array<string_t>& rhs) &
|
||||
MEOJSON_INLINE basic_array<string_t> basic_array<string_t>::operator+(const basic_array<string_t>& rhs) const&
|
||||
{
|
||||
basic_array<string_t> temp = *this;
|
||||
temp._array_data.insert(_array_data.end(), rhs.begin(), rhs.end());
|
||||
@@ -1578,7 +1597,7 @@ MEOJSON_INLINE basic_array<string_t> basic_array<string_t>::operator+(const basi
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_array<string_t> basic_array<string_t>::operator+(basic_array<string_t>&& rhs) &
|
||||
MEOJSON_INLINE basic_array<string_t> basic_array<string_t>::operator+(basic_array<string_t>&& rhs) const&
|
||||
{
|
||||
basic_array<string_t> temp = *this;
|
||||
temp._array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()),
|
||||
@@ -1682,6 +1701,12 @@ MEOJSON_INLINE bool basic_object<string_t>::erase(const string_t& key)
|
||||
return _object_data.erase(key) > 0 ? true : false;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE bool basic_object<string_t>::erase(iterator iter)
|
||||
{
|
||||
return _object_data.erase(iter) != _object_data.end();
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename... args_t>
|
||||
MEOJSON_INLINE decltype(auto) basic_object<string_t>::emplace(args_t&&... args)
|
||||
@@ -1855,7 +1880,7 @@ MEOJSON_INLINE basic_value<string_t>& basic_object<string_t>::operator[](string_
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_object<string_t> basic_object<string_t>::operator|(const basic_object<string_t>& rhs) &
|
||||
MEOJSON_INLINE basic_object<string_t> basic_object<string_t>::operator|(const basic_object<string_t>& rhs) const&
|
||||
{
|
||||
basic_object<string_t> temp = *this;
|
||||
temp._object_data.insert(rhs.begin(), rhs.end());
|
||||
@@ -1863,7 +1888,7 @@ MEOJSON_INLINE basic_object<string_t> basic_object<string_t>::operator|(const ba
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE basic_object<string_t> basic_object<string_t>::operator|(basic_object<string_t>&& rhs) &
|
||||
MEOJSON_INLINE basic_object<string_t> basic_object<string_t>::operator|(basic_object<string_t>&& rhs) const&
|
||||
{
|
||||
basic_object<string_t> temp = *this;
|
||||
// temp._object_data.merge(std::move(rhs._object_data));
|
||||
@@ -1906,27 +1931,19 @@ MEOJSON_INLINE bool basic_object<string_t>::operator==(const basic_object<string
|
||||
return _object_data == rhs._object_data;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
template <typename map_t>
|
||||
basic_object<string_t>::basic_object(map_t map)
|
||||
{
|
||||
static_assert(std::is_constructible_v<value_type, typename map_t::value_type>,
|
||||
"map_t can not construct a json object");
|
||||
_object_data.insert(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end()));
|
||||
}
|
||||
|
||||
// *************************
|
||||
// * parser impl *
|
||||
// *************************
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE std::optional<basic_value<string_t>> parser<string_t, parsing_t>::parse(const parsing_t& content)
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE std::optional<basic_value<string_t>> parser<string_t, parsing_t, accel_traits>::parse(
|
||||
const parsing_t& content)
|
||||
{
|
||||
return parser<string_t, parsing_t>(content.cbegin(), content.cend()).parse();
|
||||
return parser<string_t, parsing_t, accel_traits>(content.cbegin(), content.cend()).parse();
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE std::optional<basic_value<string_t>> parser<string_t, parsing_t>::parse()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE std::optional<basic_value<string_t>> parser<string_t, parsing_t, accel_traits>::parse()
|
||||
{
|
||||
if (!skip_whitespace()) {
|
||||
return std::nullopt;
|
||||
@@ -1957,8 +1974,8 @@ MEOJSON_INLINE std::optional<basic_value<string_t>> parser<string_t, parsing_t>:
|
||||
return result_value;
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_value()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_value()
|
||||
{
|
||||
switch (*_cur) {
|
||||
case 'n':
|
||||
@@ -1989,8 +2006,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_value()
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_null()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_null()
|
||||
{
|
||||
for (const auto& ch : null_string<string_t>()) {
|
||||
if (*_cur == ch) {
|
||||
@@ -2004,8 +2021,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_null()
|
||||
return basic_value<string_t>();
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_boolean()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_boolean()
|
||||
{
|
||||
switch (*_cur) {
|
||||
case 't':
|
||||
@@ -2033,8 +2050,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_boolean(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_number()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_number()
|
||||
{
|
||||
const auto first = _cur;
|
||||
if (*_cur == '-') {
|
||||
@@ -2072,8 +2089,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_number()
|
||||
return basic_value<string_t>(basic_value<string_t>::value_type::number, string_t(first, _cur));
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_string()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_string()
|
||||
{
|
||||
auto string_opt = parse_stdstring();
|
||||
if (!string_opt) {
|
||||
@@ -2082,8 +2099,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_string()
|
||||
return basic_value<string_t>(basic_value<string_t>::value_type::string, std::move(string_opt).value());
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_array()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_array()
|
||||
{
|
||||
if (*_cur == '[') {
|
||||
++_cur;
|
||||
@@ -2133,8 +2150,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_array()
|
||||
return basic_array<string_t>(std::move(result));
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_object()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_object()
|
||||
{
|
||||
if (*_cur == '{') {
|
||||
++_cur;
|
||||
@@ -2197,8 +2214,8 @@ MEOJSON_INLINE basic_value<string_t> parser<string_t, parsing_t>::parse_object()
|
||||
return basic_object<string_t>(std::move(result));
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE std::optional<string_t> parser<string_t, parsing_t>::parse_stdstring()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_stdstring()
|
||||
{
|
||||
if (*_cur == '"') {
|
||||
++_cur;
|
||||
@@ -2211,6 +2228,11 @@ MEOJSON_INLINE std::optional<string_t> parser<string_t, parsing_t>::parse_stdstr
|
||||
auto no_escape_beg = _cur;
|
||||
|
||||
while (_cur != _end) {
|
||||
if constexpr (sizeof(*_cur) == 1) {
|
||||
if constexpr (accel_traits::available) {
|
||||
skip_string_literal();
|
||||
}
|
||||
}
|
||||
switch (*_cur) {
|
||||
case '\t':
|
||||
case '\r':
|
||||
@@ -2246,9 +2268,9 @@ MEOJSON_INLINE std::optional<string_t> parser<string_t, parsing_t>::parse_stdstr
|
||||
case 't':
|
||||
result.push_back('\t');
|
||||
break;
|
||||
// case 'u':
|
||||
// result.push_back('\u');
|
||||
// break;
|
||||
// case 'u':
|
||||
// result.push_back('\u');
|
||||
// break;
|
||||
default:
|
||||
// Illegal backslash escape
|
||||
return std::nullopt;
|
||||
@@ -2268,8 +2290,30 @@ MEOJSON_INLINE std::optional<string_t> parser<string_t, parsing_t>::parse_stdstr
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE bool parser<string_t, parsing_t>::skip_whitespace() noexcept
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE void parser<string_t, parsing_t, accel_traits>::skip_string_literal()
|
||||
{
|
||||
if constexpr (sizeof(*_cur) != 1) {
|
||||
return;
|
||||
}
|
||||
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<uint8_t>('"')));
|
||||
result = accel_traits::bitwise_or(result, accel_traits::equal(pack, static_cast<uint8_t>('\\')));
|
||||
if (accel_traits::is_all_zero(result)) {
|
||||
_cur += accel_traits::step;
|
||||
}
|
||||
else {
|
||||
auto index = accel_traits::first_nonzero_byte(result);
|
||||
_cur += index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE bool parser<string_t, parsing_t, accel_traits>::skip_whitespace() noexcept
|
||||
{
|
||||
while (_cur != _end) {
|
||||
switch (*_cur) {
|
||||
@@ -2288,8 +2332,8 @@ MEOJSON_INLINE bool parser<string_t, parsing_t>::skip_whitespace() noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename string_t, typename parsing_t>
|
||||
MEOJSON_INLINE bool parser<string_t, parsing_t>::skip_digit()
|
||||
template <typename string_t, typename parsing_t, typename accel_traits>
|
||||
MEOJSON_INLINE bool parser<string_t, parsing_t, accel_traits>::skip_digit()
|
||||
{
|
||||
// At least one digit
|
||||
if (_cur != _end && std::isdigit(*_cur)) {
|
||||
@@ -2366,6 +2410,37 @@ MEOJSON_INLINE auto open(const path_t& filepath, bool check_bom)
|
||||
return opt;
|
||||
}
|
||||
|
||||
template <typename ostream_t, typename string_t,
|
||||
typename std_ostream_t =
|
||||
std::basic_ostream<typename string_t::value_type, std::char_traits<typename string_t::value_type>>,
|
||||
typename enable_t = typename std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> ||
|
||||
std::is_base_of_v<std_ostream_t, ostream_t>>>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_value<string_t>& val)
|
||||
{
|
||||
out << val.format();
|
||||
return out;
|
||||
}
|
||||
template <typename ostream_t, typename string_t,
|
||||
typename std_ostream_t =
|
||||
std::basic_ostream<typename string_t::value_type, std::char_traits<typename string_t::value_type>>,
|
||||
typename enable_t =
|
||||
std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_array<string_t>& arr)
|
||||
{
|
||||
out << arr.format();
|
||||
return out;
|
||||
}
|
||||
template <typename ostream_t, typename string_t,
|
||||
typename std_ostream_t =
|
||||
std::basic_ostream<typename string_t::value_type, std::char_traits<typename string_t::value_type>>,
|
||||
typename enable_t =
|
||||
std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
|
||||
ostream_t& operator<<(ostream_t& out, const basic_object<string_t>& obj)
|
||||
{
|
||||
out << obj.format();
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace literals
|
||||
{
|
||||
MEOJSON_INLINE value operator""_json(const char* str, size_t len)
|
||||
@@ -2445,33 +2520,119 @@ namespace literals
|
||||
}
|
||||
} // namespace literals
|
||||
|
||||
template <typename ostream_t, typename string_t>
|
||||
MEOJSON_INLINE ostream_t& operator<<(ostream_t& out, const basic_value<string_t>& val)
|
||||
{
|
||||
out << val.format();
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename ostream_t, typename string_t>
|
||||
MEOJSON_INLINE ostream_t& operator<<(ostream_t& out, const basic_array<string_t>& arr)
|
||||
{
|
||||
out << arr.format();
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename ostream_t, typename string_t>
|
||||
MEOJSON_INLINE ostream_t& operator<<(ostream_t& out, const basic_object<string_t>& obj)
|
||||
{
|
||||
out << obj.format();
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE const basic_value<string_t> invalid_value()
|
||||
{
|
||||
return basic_value<string_t>(basic_value<string_t>::value_type::invalid, typename basic_value<string_t>::var_t());
|
||||
}
|
||||
|
||||
namespace _serialization_helper
|
||||
{
|
||||
template <typename T>
|
||||
class has_output_operator
|
||||
{
|
||||
template <typename U>
|
||||
static auto test(int) -> decltype(std::declval<std::ostream&>() << std::declval<U>(), std::true_type());
|
||||
|
||||
template <typename U>
|
||||
static std::false_type test(...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
template <typename...>
|
||||
using void_t = void;
|
||||
|
||||
template <typename T, typename = void>
|
||||
constexpr bool is_container = false;
|
||||
template <typename T>
|
||||
constexpr bool is_container<
|
||||
T, void_t<typename T::value_type, decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> =
|
||||
true;
|
||||
|
||||
// something like a map
|
||||
template <typename T, typename = void>
|
||||
constexpr bool is_associative_container = false;
|
||||
template <typename T>
|
||||
constexpr bool is_associative_container<T, void_t<typename T::key_type, typename T::mapped_type>> = is_container<T>;
|
||||
|
||||
// something like a vector
|
||||
template <typename T, typename = void>
|
||||
constexpr bool is_sequence_container = false;
|
||||
template <typename T>
|
||||
constexpr bool is_sequence_container<T> = is_container<T> && !is_associative_container<T>;
|
||||
|
||||
template <typename input_t, typename string_t>
|
||||
MEOJSON_INLINE string_t to_stream_string(input_t&& arg)
|
||||
{
|
||||
if constexpr (has_output_operator<input_t>::value) {
|
||||
using char_t = typename string_t::value_type;
|
||||
using stringstream_t = std::basic_stringstream<char_t, std::char_traits<char_t>, std::allocator<char_t>>;
|
||||
|
||||
stringstream_t ss;
|
||||
ss << std::forward<input_t>(arg);
|
||||
return std::move(ss).str();
|
||||
}
|
||||
else {
|
||||
static_assert(!sizeof(input_t), "Unable to convert type to string, there is no operator <<.");
|
||||
}
|
||||
}
|
||||
|
||||
template <bool loose, typename input_t, typename string_t>
|
||||
MEOJSON_INLINE string_t to_string(input_t&& arg)
|
||||
{
|
||||
if constexpr (std::is_constructible_v<string_t, input_t>) {
|
||||
return arg;
|
||||
}
|
||||
else if constexpr (loose) {
|
||||
return to_stream_string<input_t, string_t>(std::forward<input_t>(arg));
|
||||
}
|
||||
else {
|
||||
static_assert(!sizeof(input_t), "Unable to convert type to string.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <bool loose, typename any_t, typename string_t>
|
||||
MEOJSON_INLINE basic_value<string_t> serialize(any_t&& arg)
|
||||
{
|
||||
using namespace _serialization_helper;
|
||||
|
||||
if constexpr (std::is_constructible_v<basic_value<string_t>, any_t>) {
|
||||
return arg;
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<basic_array<string_t>, any_t>) {
|
||||
return basic_array<string_t>(std::forward<any_t>(arg));
|
||||
}
|
||||
else if constexpr (std::is_constructible_v<basic_object<string_t>, any_t>) {
|
||||
return basic_object<string_t>(std::forward<any_t>(arg));
|
||||
}
|
||||
else if constexpr (is_sequence_container<std::decay_t<any_t>>) {
|
||||
basic_value<string_t> result;
|
||||
for (auto&& val : arg) {
|
||||
using value_t = decltype(val);
|
||||
|
||||
result.emplace(serialize<loose, value_t, string_t>(std::forward<value_t>(val)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if constexpr (is_associative_container<std::decay_t<any_t>>) {
|
||||
basic_value<string_t> result;
|
||||
for (auto&& [key, val] : arg) {
|
||||
using key_t = decltype(key);
|
||||
using value_t = decltype(val);
|
||||
|
||||
result.emplace(to_string<loose, key_t, string_t>(std::forward<key_t>(key)),
|
||||
serialize<loose, value_t, string_t>(std::forward<value_t>(val)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return to_string<loose, any_t, string_t>(std::forward<any_t>(arg));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename string_t>
|
||||
MEOJSON_INLINE static constexpr string_t unescape_string(const string_t& str)
|
||||
{
|
||||
|
||||
126
3rdparty/include/meojson/packed_bytes.hpp
vendored
Normal file
126
3rdparty/include/meojson/packed_bytes.hpp
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include "bitops.hpp"
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#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 {
|
||||
static constexpr bool available = false;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
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"
|
||||
#elif defined(__ARM_NEON) || defined(_M_ARM) || defined(_M_ARM64)
|
||||
#include "packed_bytes_arm.hpp"
|
||||
#endif
|
||||
|
||||
struct packed_bytes_trait_uint64 {
|
||||
static constexpr bool available = sizeof(void*) >= 8;
|
||||
static constexpr auto step = 8;
|
||||
using value_type = std::enable_if_t<sizeof(void*) >= 8, uint64_t>;
|
||||
|
||||
__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)
|
||||
{
|
||||
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 size_t first_nonzero_byte(value_type x) {
|
||||
if (json::__bitops::is_little_endian())
|
||||
return json::__bitops::countr_zero(x) / 8;
|
||||
else
|
||||
return json::__bitops::countl_zero(x) / 8;
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
value_type result;
|
||||
memcpy((void*)&result, ptr, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
__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 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) {
|
||||
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 size_t first_nonzero_byte(value_type x) {
|
||||
if (json::__bitops::is_little_endian())
|
||||
return json::__bitops::countr_zero(x) / 8;
|
||||
else
|
||||
return json::__bitops::countl_zero(x) / 8;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct packed_bytes<8> {
|
||||
using traits = std::enable_if_t<packed_bytes_trait_uint64::available, packed_bytes_trait_uint64>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<4> {
|
||||
using traits = packed_bytes_trait_uint32;
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
using packed_bytes_trait = typename packed_bytes<N>::traits;
|
||||
|
||||
using packed_bytes_trait_max = std::conditional_t<packed_bytes_trait<32>::available, packed_bytes_trait<32>,
|
||||
std::conditional_t<packed_bytes_trait<16>::available, packed_bytes_trait<16>,
|
||||
std::conditional_t<packed_bytes_trait<8>::available, packed_bytes_trait<8>,
|
||||
packed_bytes_trait<4>
|
||||
>>>;
|
||||
|
||||
63
3rdparty/include/meojson/packed_bytes_arm.hpp
vendored
Normal file
63
3rdparty/include/meojson/packed_bytes_arm.hpp
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
// current NEON implementation doesn't outperform 64-bit scalar implementation
|
||||
#ifdef MEOJSON_ENABLE_NEON
|
||||
#include "packed_bytes.hpp"
|
||||
#include <arm_neon.h>
|
||||
|
||||
#if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
|
||||
#define __packed_bytes_trait_arm64
|
||||
#endif
|
||||
|
||||
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 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, 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 bool is_all_zero(value_type x) {
|
||||
#ifdef __packed_bytes_trait_arm64
|
||||
return vmaxvq_u8(x) == 0;
|
||||
#else
|
||||
auto fold64 = vorr_u64(vget_high_u64(vreinterpretq_u8_u64(x), 0), vget_low_u64(vreinterpretq_u8_u64(x), 1));
|
||||
auto fold32 = vget_lane_u32(vreinterpret_u64_u32(fold64), 0) | vget_lane_u32(vreinterpret_u64_u32(fold64), 1);
|
||||
return fold32 == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
__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;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<16> {
|
||||
using traits = packed_bytes_trait_neon;
|
||||
};
|
||||
|
||||
#endif
|
||||
123
3rdparty/include/meojson/packed_bytes_x86.hpp
vendored
Normal file
123
3rdparty/include/meojson/packed_bytes_x86.hpp
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
#include "packed_bytes.hpp"
|
||||
|
||||
#include <emmintrin.h>
|
||||
#if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER)
|
||||
// MSVC enables all SSE4.1 intrinsics by default
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
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) {
|
||||
return _mm_loadu_si128(reinterpret_cast<const __m128i*>(ptr));
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n) {
|
||||
auto bcast = _mm_set1_epi8(static_cast<char>(n));
|
||||
auto all1 = _mm_set1_epi8(-1);
|
||||
auto max_with_n = _mm_max_epu8(x, bcast);
|
||||
auto is_greater_or_equal = _mm_cmpeq_epi8(max_with_n, x);
|
||||
auto is_less = _mm_andnot_si128(is_greater_or_equal, all1);
|
||||
return is_less;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n) {
|
||||
return _mm_cmpeq_epi8(x, _mm_set1_epi8(static_cast<char>(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 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) {
|
||||
#if defined(__SSE4_1__) || defined(__AVX2__) || defined(_MSC_VER)
|
||||
// SSE4.1 path
|
||||
return !!_mm_testz_si128(x, x);
|
||||
#else
|
||||
// SSE2 path
|
||||
auto cmp = _mm_cmpeq_epi8(x, _mm_set1_epi8(0));
|
||||
auto mask = (uint16_t)_mm_movemask_epi8(cmp);
|
||||
return mask == UINT16_C(0xFFFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
__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);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<16> {
|
||||
using traits = packed_bytes_trait_sse;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __AVX2__
|
||||
#include <immintrin.h>
|
||||
|
||||
struct packed_bytes_trait_avx2
|
||||
{
|
||||
static constexpr bool available = true;
|
||||
static constexpr auto step = 32;
|
||||
using value_type = __m256i;
|
||||
|
||||
__packed_bytes_strong_inline static value_type load_unaligned(const void* ptr)
|
||||
{
|
||||
return _mm256_loadu_si256(reinterpret_cast<const __m256i*>(ptr));
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type less(value_type x, uint8_t n)
|
||||
{
|
||||
auto bcast = _mm256_set1_epi8(static_cast<char>(n));
|
||||
auto all1 = _mm256_set1_epi8(-1);
|
||||
auto max_with_n = _mm256_max_epu8(x, bcast);
|
||||
auto is_greater_or_equal = _mm256_cmpeq_epi8(max_with_n, x);
|
||||
auto is_less = _mm256_andnot_si256(is_greater_or_equal, all1);
|
||||
return is_less;
|
||||
}
|
||||
|
||||
__packed_bytes_strong_inline static value_type equal(value_type x, uint8_t n)
|
||||
{
|
||||
return _mm256_cmpeq_epi8(x, _mm256_set1_epi8(static_cast<char>(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 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 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);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct packed_bytes<32> {
|
||||
using traits = packed_bytes_trait_avx2;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user