chore: meoJson update to v4.3.4 (#12460)

* chore: meoJson update to v4.3.2

* chore: meoJson update to v4.3.4
This commit is contained in:
status102
2025-04-28 14:31:12 +08:00
committed by GitHub
parent 91b53a4b73
commit dd82fa0075
17 changed files with 1668 additions and 547 deletions

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <initializer_list>
@@ -37,37 +39,86 @@ public:
// explicit basic_array(const basic_value<string_t>& val);
// explicit basic_array(basic_value<string_t>&& val);
template <typename collection_t,
std::enable_if_t<_utils::is_collection<collection_t> &&
std::is_constructible_v<value_type, _utils::range_value_t<collection_t>>,
bool> = true>
template <
typename collection_t,
std::enable_if_t<
_utils::is_collection<collection_t>
&& std::is_constructible_v<value_type, _utils::range_value_t<collection_t>>,
bool> = true>
basic_array(collection_t arr)
: _array_data(std::make_move_iterator(arr.begin()), std::make_move_iterator(arr.end()))
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& value) : basic_array(value.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& value) : basic_array(ext::jsonization<jsonization_t>().to_json(value))
{}
{
}
template <
typename fixed_array_t,
std::enable_if_t<_utils::is_fixed_array<fixed_array_t>, bool> = true>
basic_array(const fixed_array_t& arr)
: _array_data(arr.begin(), arr.end())
{
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& value)
: basic_array(value.to_json())
{
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_array(const jsonization_t& value)
: basic_array(ext::jsonization<jsonization_t>().to_json(value))
{
}
template <typename... elem_ts>
basic_array(const std::tuple<elem_ts...>& tup)
{
foreach_tuple(tup, std::make_index_sequence<std::tuple_size_v<std::tuple<elem_ts...>>>());
}
template <typename first_t, typename second_t>
basic_array(std::pair<first_t, second_t> pair)
: _array_data({ std::move(pair.first), std::move(pair.second) })
{
}
~basic_array() noexcept = default;
bool empty() const noexcept { return _array_data.empty(); }
size_t size() const noexcept { return _array_data.size(); }
bool contains(size_t pos) const { return pos < _array_data.size(); }
bool exists(size_t pos) const { return contains(pos); }
const basic_value<string_t>& at(size_t pos) const;
string_t dumps(std::optional<size_t> indent = std::nullopt) const { return indent ? format(*indent) : to_string(); }
string_t dumps(std::optional<size_t> indent = std::nullopt) const
{
return indent ? format(*indent) : to_string();
}
string_t to_string() const;
string_t format(size_t indent = 4) const { return format(indent, 0); }
template <typename value_t>
bool all() const;
template <typename value_t, template <typename...> typename collection_t = std::vector>
collection_t<value_t> as_collection() const;
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array>
fixed_array_t<value_t, Size> as_fixed_array() const;
template <typename... elem_ts>
std::tuple<elem_ts...> as_tuple() const;
template <typename first_t, typename second_t>
std::pair<first_t, second_t> as_pair() const;
// Usage: get(key_1, key_2, ..., default_value);
template <typename... key_then_default_value_t>
@@ -112,23 +163,54 @@ public:
basic_array<string_t>& operator=(const basic_array<string_t>&) = default;
basic_array<string_t>& operator=(basic_array<string_t>&&) noexcept = default;
template <typename value_t, std::enable_if_t<std::is_convertible_v<value_t, basic_array<string_t>>, bool> = true>
template <
typename value_t,
std::enable_if_t<std::is_convertible_v<value_t, basic_array<string_t>>, bool> = true>
basic_array<string_t>& operator=(value_t rhs)
{
return *this = basic_array<string_t>(std::move(rhs));
}
bool operator==(const basic_array<string_t>& rhs) const;
bool operator!=(const basic_array<string_t>& rhs) const { return !(*this == rhs); }
template <typename value_t, template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
template <
typename value_t,
template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
explicit operator collection_t<value_t>() const
{
return as_collection<value_t, collection_t>();
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> = true>
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array,
std::enable_if_t<_utils::is_fixed_array<fixed_array_t<value_t, Size>>, bool> = true>
explicit operator fixed_array_t<value_t, Size>() const
{
return as_fixed_array<value_t, Size, fixed_array_t>();
}
template <typename... elem_ts>
explicit operator std::tuple<elem_ts...>() const
{
return as_tuple<elem_ts...>();
}
template <typename elem1_t, typename elem2_t>
explicit operator std::pair<elem1_t, elem2_t>() const
{
return as_pair<elem1_t, elem2_t>();
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> =
true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
@@ -137,8 +219,12 @@ public:
}
return dst;
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
@@ -150,13 +236,25 @@ public:
private:
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
auto get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
auto
get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
template <typename value_t, typename... rest_keys_t>
auto get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const;
template <typename value_t>
auto get_helper(const value_t& default_value, size_t pos) const;
template <typename tuple_t>
tuple_t as_tuple_templ() const;
template <size_t index, typename tuple_t>
void set_tuple(tuple_t& tup) const;
template <typename Tuple, std::size_t... Is>
void foreach_tuple(const Tuple& t, std::index_sequence<Is...>)
{
(_array_data.emplace_back(std::get<Is>(t)), ...);
}
string_t format(size_t indent, size_t indent_times) const;
private:
@@ -164,15 +262,20 @@ private:
};
template <typename string_t>
inline basic_array<string_t>::basic_array(std::initializer_list<value_type> init_list) : _array_data(init_list)
{}
inline basic_array<string_t>::basic_array(std::initializer_list<value_type> init_list)
: _array_data(init_list)
{
}
template <typename string_t>
inline basic_array<string_t>::basic_array(typename raw_array::size_type size) : _array_data(size)
{}
inline basic_array<string_t>::basic_array(typename raw_array::size_type size)
: _array_data(size)
{
}
// template <typename string_t>
// inline basic_array<string_t>::basic_array(const basic_value<string_t>& val) : basic_array<string_t>(val.as_array())
// inline basic_array<string_t>::basic_array(const basic_value<string_t>& val) :
// basic_array<string_t>(val.as_array())
//{}
//
// template <typename string_t>
@@ -202,8 +305,9 @@ template <typename string_t>
template <typename... args_t>
inline decltype(auto) basic_array<string_t>::emplace_back(args_t&&... args)
{
static_assert(std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_array::value_type");
static_assert(
std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_array::value_type");
return _array_data.emplace_back(std::forward<args_t>(args)...);
}
@@ -266,18 +370,18 @@ inline bool basic_array<string_t>::all() const
namespace _as_collection_helper
{
template <typename T>
class has_emplace_back
{
template <typename U>
static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type());
template <typename T>
class has_emplace_back
{
template <typename U>
static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type());
template <typename U>
static std::false_type test(...);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
}
template <typename string_t>
@@ -298,31 +402,94 @@ inline collection_t<value_t> basic_array<string_t>::as_collection() const
return result;
}
template <typename string_t>
template <typename value_t, size_t Size, template <typename, size_t> typename fixed_array_t>
inline fixed_array_t<value_t, Size> basic_array<string_t>::as_fixed_array() const
{
if (size() != Size) {
throw exception("Wrong array size");
}
fixed_array_t<value_t, Size> result;
for (size_t i = 0; i < Size; ++i) {
result.at(i) = _array_data.at(i).template as<value_t>();
}
return result;
}
template <typename string_t>
template <size_t index, typename tuple_t>
inline void basic_array<string_t>::set_tuple(tuple_t& tup) const
{
using elem_t = std::tuple_element_t<index, tuple_t>;
if constexpr (index > 0) {
set_tuple<index - 1>(tup);
}
std::get<index>(tup) = static_cast<elem_t>(at(index));
}
template <typename string_t>
template <typename tuple_t>
inline tuple_t basic_array<string_t>::as_tuple_templ() const
{
constexpr size_t tuple_size = std::tuple_size_v<tuple_t>;
if (size() != tuple_size) {
throw exception("Wrong array size");
}
tuple_t result;
set_tuple<tuple_size - 1>(result);
return result;
}
template <typename string_t>
template <typename... elem_ts>
inline std::tuple<elem_ts...> basic_array<string_t>::as_tuple() const
{
return as_tuple_templ<std::tuple<elem_ts...>>();
}
template <typename string_t>
template <typename first_t, typename second_t>
inline std::pair<first_t, second_t> basic_array<string_t>::as_pair() const
{
return as_tuple_templ<std::pair<first_t, second_t>>();
}
template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_array<string_t>::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<sizeof...(keys_then_default_value) - 1> {});
return get(
std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
}
template <typename string_t>
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
inline auto basic_array<string_t>::get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
inline auto basic_array<string_t>::get(
std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
{
constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1;
return get_helper(std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
return get_helper(
std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
}
template <typename string_t>
template <typename value_t, typename... rest_keys_t>
inline auto basic_array<string_t>::get_helper(const value_t& default_value, size_t pos, rest_keys_t&&... rest) const
inline auto basic_array<string_t>::get_helper(
const value_t& default_value,
size_t pos,
rest_keys_t&&... rest) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(pos)) {
@@ -341,9 +508,9 @@ template <typename string_t>
template <typename value_t>
inline auto basic_array<string_t>::get_helper(const value_t& default_value, size_t pos) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(pos)) {
@@ -382,7 +549,8 @@ inline std::optional<value_t> basic_array<string_t>::find(size_t pos) const
return std::nullopt;
}
const auto& val = _array_data.at(pos);
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>()) : std::nullopt;
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>())
: std::nullopt;
}
template <typename string_t>
@@ -434,25 +602,29 @@ inline typename basic_array<string_t>::reverse_iterator basic_array<string_t>::r
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::rbegin() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::rbegin() const noexcept
{
return _array_data.rbegin();
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::rend() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::rend() const noexcept
{
return _array_data.rend();
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::crbegin() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::crbegin() const noexcept
{
return _array_data.crbegin();
}
template <typename string_t>
inline typename basic_array<string_t>::const_reverse_iterator basic_array<string_t>::crend() const noexcept
inline typename basic_array<string_t>::const_reverse_iterator
basic_array<string_t>::crend() const noexcept
{
return _array_data.crend();
}
@@ -470,7 +642,8 @@ inline const basic_value<string_t>& basic_array<string_t>::operator[](size_t pos
}
template <typename string_t>
inline basic_array<string_t> basic_array<string_t>::operator+(const basic_array<string_t>& rhs) const&
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());
@@ -481,8 +654,10 @@ template <typename string_t>
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()),
std::make_move_iterator(rhs.end()));
temp._array_data.insert(
_array_data.end(),
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
return temp;
}
@@ -496,7 +671,10 @@ inline basic_array<string_t> basic_array<string_t>::operator+(const basic_array<
template <typename string_t>
inline basic_array<string_t> basic_array<string_t>::operator+(basic_array<string_t>&& rhs) &&
{
_array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
_array_data.insert(
_array_data.end(),
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
return std::move(*this);
}
@@ -510,7 +688,10 @@ inline basic_array<string_t>& basic_array<string_t>::operator+=(const basic_arra
template <typename string_t>
inline basic_array<string_t>& basic_array<string_t>::operator+=(basic_array<string_t>&& rhs)
{
_array_data.insert(_array_data.end(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
_array_data.insert(
_array_data.end(),
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
return *this;
}
@@ -520,11 +701,14 @@ inline bool basic_array<string_t>::operator==(const basic_array<string_t>& rhs)
return _array_data == rhs._array_data;
}
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>>>
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();

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <exception>
@@ -9,7 +11,11 @@ class exception : public std::exception
{
public:
exception() = default;
exception(const std::string& msg) : _what(msg) {}
exception(const std::string& msg)
: _what(msg)
{
}
exception(const exception&) = default;
exception& operator=(const exception&) = default;
@@ -18,7 +24,10 @@ public:
virtual ~exception() noexcept override = default;
virtual const char* what() const noexcept override { return _what.empty() ? "Unknown exception" : _what.c_str(); }
virtual const char* what() const noexcept override
{
return _what.empty() ? "Unknown exception" : _what.c_str();
}
protected:
std::string _what;

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <initializer_list>
@@ -36,31 +38,54 @@ public:
// explicit basic_object(const basic_value<string_t>& val);
// explicit basic_object(basic_value<string_t>&& val);
template <typename map_t, std::enable_if_t<_utils::is_map<map_t> &&
std::is_constructible_v<value_type, _utils::range_value_t<map_t>>,
bool> = true>
basic_object(map_t map) : _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end()))
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& value) : basic_object(value.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& value) : basic_object(ext::jsonization<jsonization_t>().to_json(value))
{}
template <
typename map_t,
std::enable_if_t<
_utils::is_map<map_t>
&& std::is_constructible_v<value_type, _utils::range_value_t<map_t>>,
bool> = true>
basic_object(map_t map)
: _object_data(std::make_move_iterator(map.begin()), std::make_move_iterator(map.end()))
{
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& value)
: basic_object(value.to_json())
{
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_object(const jsonization_t& value)
: basic_object(ext::jsonization<jsonization_t>().to_json(value))
{
}
~basic_object() = default;
bool empty() const noexcept { return _object_data.empty(); }
size_t size() const noexcept { return _object_data.size(); }
bool contains(const string_t& key) const;
bool exists(const string_t& key) const { return contains(key); }
const basic_value<string_t>& at(const string_t& key) const;
string_t dumps(std::optional<size_t> indent = std::nullopt) const { return indent ? format(*indent) : to_string(); }
string_t dumps(std::optional<size_t> indent = std::nullopt) const
{
return indent ? format(*indent) : to_string();
}
string_t to_string() const;
string_t format(size_t indent = 4) const { return format(indent, 0); }
template <typename value_t>
bool all() const;
template <typename value_t, template <typename...> typename map_t = std::map>
@@ -102,23 +127,32 @@ public:
basic_object<string_t>& operator=(const basic_object<string_t>&) = default;
basic_object<string_t>& operator=(basic_object<string_t>&&) = default;
template <typename value_t, std::enable_if_t<std::is_convertible_v<value_t, basic_object<string_t>>, bool> = true>
template <
typename value_t,
std::enable_if_t<std::is_convertible_v<value_t, basic_object<string_t>>, bool> = true>
basic_object<string_t>& operator=(value_t rhs)
{
return *this = basic_object<string_t>(std::move(rhs));
}
bool operator==(const basic_object<string_t>& rhs) const;
bool operator!=(const basic_object<string_t>& rhs) const { return !(*this == rhs); }
template <typename value_t, template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
template <
typename value_t,
template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
explicit operator map_t<string_t, value_t>() const
{
return as_map<value_t, map_t>();
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> = true>
template <
typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> =
true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
@@ -127,8 +161,12 @@ public:
}
return dst;
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
@@ -140,8 +178,9 @@ public:
private:
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
auto get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
auto
get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
template <typename value_t, typename... rest_keys_t>
auto get_helper(const value_t& default_value, const string_t& key, rest_keys_t&&... rest) const;
template <typename value_t>
@@ -155,8 +194,11 @@ private:
template <typename string_t>
inline basic_object<string_t>::basic_object(std::initializer_list<value_type> init_list)
: _object_data(std::make_move_iterator(init_list.begin()), std::make_move_iterator(init_list.end()))
{}
: _object_data(
std::make_move_iterator(init_list.begin()),
std::make_move_iterator(init_list.end()))
{
}
// template <typename string_t>
// inline basic_object<string_t>::basic_object(const basic_value<string_t>& val) :
@@ -202,9 +244,10 @@ template <typename string_t>
template <typename... args_t>
inline decltype(auto) basic_object<string_t>::emplace(args_t&&... args)
{
static_assert(std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_object::value_type");
return _object_data.emplace(std::forward<args_t>(args)...);
static_assert(
std::is_constructible_v<value_type, args_t...>,
"Parameter can't be used to construct a raw_object::value_type");
return _object_data.insert_or_assign(std::forward<args_t>(args)...);
}
template <typename string_t>
@@ -220,7 +263,8 @@ inline string_t basic_object<string_t>::to_string() const
string_t str { '{' };
for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) {
const auto& [key, val] = *iter;
str += char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':' } + val.to_string();
str +=
char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':' } + val.to_string();
if (++iter != _object_data.cend()) {
str += ',';
}
@@ -238,8 +282,8 @@ inline string_t basic_object<string_t>::format(size_t indent, size_t indent_time
string_t str { '{', '\n' };
for (auto iter = _object_data.cbegin(); iter != _object_data.cend();) {
const auto& [key, val] = *iter;
str += body_indent + char_t('"') + _utils::unescape_string(key) + string_t { '\"', ':', ' ' } +
val.format(indent, indent_times + 1);
str += body_indent + char_t('"') + _utils::unescape_string(key)
+ string_t { '\"', ':', ' ' } + val.format(indent, indent_times + 1);
if (++iter != _object_data.cend()) {
str += ',';
}
@@ -276,28 +320,33 @@ template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_object<string_t>::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<sizeof...(keys_then_default_value) - 1> {});
return get(
std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
}
template <typename string_t>
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
inline auto basic_object<string_t>::get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
inline auto basic_object<string_t>::get(
std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
{
constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1;
return get_helper(std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
return get_helper(
std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
}
template <typename string_t>
template <typename value_t, typename... rest_keys_t>
inline auto basic_object<string_t>::get_helper(const value_t& default_value, const string_t& key,
rest_keys_t&&... rest) const
inline auto basic_object<string_t>::get_helper(
const value_t& default_value,
const string_t& key,
rest_keys_t&&... rest) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(key)) {
@@ -314,11 +363,12 @@ inline auto basic_object<string_t>::get_helper(const value_t& default_value, con
template <typename string_t>
template <typename value_t>
inline auto basic_object<string_t>::get_helper(const value_t& default_value, const string_t& key) const
inline auto
basic_object<string_t>::get_helper(const value_t& default_value, const string_t& key) const
{
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t> ||
std::is_same_v<basic_array<string_t>, value_t> ||
std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_json = std::is_same_v<basic_value<string_t>, value_t>
|| std::is_same_v<basic_array<string_t>, value_t>
|| std::is_same_v<basic_object<string_t>, value_t>;
constexpr bool is_string = std::is_constructible_v<string_t, value_t> && !is_json;
if (!contains(key)) {
@@ -358,7 +408,8 @@ inline std::optional<value_t> basic_object<string_t>::find(const string_t& key)
return std::nullopt;
}
const auto& val = iter->second;
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>()) : std::nullopt;
return val.template is<value_t>() ? std::optional<value_t>(val.template as<value_t>())
: std::nullopt;
}
template <typename string_t>
@@ -374,7 +425,8 @@ inline typename basic_object<string_t>::iterator basic_object<string_t>::end() n
}
template <typename string_t>
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::begin() const noexcept
inline typename basic_object<string_t>::const_iterator
basic_object<string_t>::begin() const noexcept
{
return _object_data.begin();
}
@@ -386,7 +438,8 @@ inline typename basic_object<string_t>::const_iterator basic_object<string_t>::e
}
template <typename string_t>
inline typename basic_object<string_t>::const_iterator basic_object<string_t>::cbegin() const noexcept
inline typename basic_object<string_t>::const_iterator
basic_object<string_t>::cbegin() const noexcept
{
return _object_data.cbegin();
}
@@ -410,7 +463,8 @@ inline basic_value<string_t>& basic_object<string_t>::operator[](string_t&& key)
}
template <typename string_t>
inline basic_object<string_t> basic_object<string_t>::operator|(const basic_object<string_t>& rhs) const&
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());
@@ -422,12 +476,15 @@ inline basic_object<string_t> basic_object<string_t>::operator|(basic_object<str
{
basic_object<string_t> temp = *this;
// temp._object_data.merge(std::move(rhs._object_data));
temp._object_data.insert(std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
temp._object_data.insert(
std::make_move_iterator(rhs.begin()),
std::make_move_iterator(rhs.end()));
return temp;
}
template <typename string_t>
inline basic_object<string_t> basic_object<string_t>::operator|(const basic_object<string_t>& rhs) &&
inline basic_object<string_t>
basic_object<string_t>::operator|(const basic_object<string_t>& rhs) &&
{
_object_data.insert(rhs.begin(), rhs.end());
return std::move(*this);
@@ -461,11 +518,14 @@ inline bool basic_object<string_t>::operator==(const basic_object<string_t>& rhs
return _object_data == rhs._object_data;
}
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>>>
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();

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <type_traits>
@@ -9,96 +11,101 @@ namespace json
{
namespace _serialization_helper
{
template <typename in_t, typename serializer_t>
class is_serializable
{
template <typename U>
static auto test(int) -> decltype(std::declval<serializer_t>()(std::declval<U>()), std::true_type());
template <typename in_t, typename serializer_t>
class is_serializable
{
template <typename U>
static auto test(int)
-> decltype(std::declval<serializer_t>()(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<in_t>(0))::value;
};
public:
static constexpr bool value = decltype(test<in_t>(0))::value;
};
struct empty_serializer
{
// sample:
// json::value operator()(const type_1&) const { return ...; }
// json::value operator()(const type_2&) const { return ...; }
// json::value operator()(const type_3&) const { return ...; }
};
struct empty_serializer
{
// sample:
// json::value operator()(const type_1&) const { return ...; }
// json::value operator()(const type_2&) const { return ...; }
// json::value operator()(const type_3&) const { return ...; }
};
template <typename T>
void unable_to_serialize()
{
static_assert(!sizeof(T), "Unable to serialize T. "
template <typename T>
void unable_to_serialize()
{
static_assert(
!sizeof(T),
"Unable to serialize T. "
#ifdef _MSC_VER
"See T below: " __FUNCSIG__
"See T below: " __FUNCSIG__
#else
// "See T below: " __PRETTY_FUNCTION__
// "See T below: " __PRETTY_FUNCTION__
#endif
);
}
);
}
}
namespace _serialization_helper
{
template <typename out_t, typename deserializer_t, typename string_t = default_string_t>
class is_deserializable
{
template <typename U>
static auto test(int)
-> decltype(std::declval<deserializer_t>()(std::declval<basic_value<string_t>>(), std::declval<U&>()),
std::true_type());
template <typename out_t, typename deserializer_t, typename string_t = default_string_t>
class is_deserializable
{
template <typename U>
static auto test(int)
-> decltype(std::declval<deserializer_t>()(std::declval<basic_value<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<out_t>(0))::value;
};
public:
static constexpr bool value = decltype(test<out_t>(0))::value;
};
struct empty_deserializer
{
// sample:
// bool operator()(const json::value&, type_1&) const { return ...; }
// bool operator()(const json::value&, type_2&) const { return ...; }
// bool operator()(const json::value&, type_3&) const { return ...; }
};
struct empty_deserializer
{
// sample:
// bool operator()(const json::value&, type_1&) const { return ...; }
// bool operator()(const json::value&, type_2&) const { return ...; }
// bool operator()(const json::value&, type_3&) const { return ...; }
};
template <typename T>
void unable_to_deserialize()
{
static_assert(!sizeof(T), "Unable to deserialize T. "
template <typename T>
void unable_to_deserialize()
{
static_assert(
!sizeof(T),
"Unable to deserialize T. "
#ifdef _MSC_VER
"See T below: " __FUNCSIG__
"See T below: " __FUNCSIG__
#else
// "See T below: " __PRETTY_FUNCTION__
// "See T below: " __PRETTY_FUNCTION__
#endif
);
}
);
}
}
template <typename in_t, typename serializer_t = _serialization_helper::empty_serializer,
typename string_t = default_string_t>
template <
typename in_t,
typename serializer_t = _serialization_helper::empty_serializer,
typename string_t = default_string_t>
basic_value<string_t> serialize(in_t&& in, const serializer_t& serializer = {})
{
if constexpr (_serialization_helper::is_serializable<in_t, serializer_t>::value) {
return serializer(std::forward<in_t>(in));
}
else if constexpr (std::is_constructible_v<basic_value<string_t>, in_t>) {
return basic_value<string_t>(std::forward<in_t>(in));
}
else if constexpr (_utils::is_collection<std::decay_t<in_t>>) {
else if constexpr (
_utils::is_collection<std::decay_t<in_t>> || _utils::is_fixed_array<std::decay_t<in_t>>) {
basic_array<string_t> arr;
for (auto&& elem : in) {
using elem_t = decltype(elem);
auto j_elem = serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
auto j_elem =
serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
arr.emplace_back(std::move(j_elem));
}
return arr;
@@ -109,27 +116,32 @@ basic_value<string_t> serialize(in_t&& in, const serializer_t& serializer = {})
using key_t = decltype(key);
using elem_t = decltype(elem);
auto j_elem = serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
auto j_elem =
serialize<elem_t, serializer_t, string_t>(std::forward<elem_t>(elem), serializer);
obj.emplace(std::forward<key_t>(key), std::move(j_elem));
}
return obj;
}
else if constexpr (std::is_constructible_v<basic_value<string_t>, in_t>) {
return basic_value<string_t>(std::forward<in_t>(in));
}
else {
_serialization_helper::unable_to_serialize<in_t>();
}
}
template <typename out_t, typename deserializer_t = _serialization_helper::empty_deserializer,
typename string_t = default_string_t>
bool deserialize(const basic_value<string_t>& in, out_t& out, const deserializer_t& deserializer = {})
template <
typename out_t,
typename deserializer_t = _serialization_helper::empty_deserializer,
typename string_t = default_string_t>
bool deserialize(
const basic_value<string_t>& in,
out_t& out,
const deserializer_t& deserializer = {})
{
if constexpr (_serialization_helper::is_deserializable<out_t, deserializer_t>::value) {
return deserializer(in, out);
}
else if constexpr (std::is_constructible_v<out_t, basic_value<string_t>>) {
out = out_t(in);
return true;
}
else if constexpr (_utils::is_collection<std::decay_t<out_t>>) {
if (!in.is_array()) {
return false;
@@ -149,20 +161,45 @@ bool deserialize(const basic_value<string_t>& in, out_t& out, const deserializer
}
return true;
}
else if constexpr (_utils::is_map<std::decay_t<out_t>>) {
if (!in.is_object()) {
else if constexpr (_utils::is_fixed_array<std::decay_t<out_t>>) {
if (!in.is_array()) {
return false;
}
for (auto&& [key, j_elem] : in.as_object()) {
auto&& in_as_arr = in.as_array();
constexpr size_t out_size = _utils::fixed_array_size<out_t>;
if (in_as_arr.size() != out_size) {
return false;
}
for (size_t i = 0; i < out_size; ++i) {
auto&& j_elem = in_as_arr.at(i);
using elem_t = typename out_t::value_type;
elem_t elem {};
if (!deserialize<elem_t, deserializer_t, string_t>(j_elem, elem, deserializer)) {
return false;
}
out.emplace(std::move(elem));
out.at(i) = std::move(elem);
}
return true;
}
else if constexpr (_utils::is_map<std::decay_t<out_t>>) {
if (!in.is_object()) {
return false;
}
for (auto&& [key, j_elem] : in.as_object()) {
using elem_t = typename out_t::mapped_type;
elem_t elem {};
if (!deserialize<elem_t, deserializer_t, string_t>(j_elem, elem, deserializer)) {
return false;
}
out.emplace(std::forward<decltype(key)>(key), std::move(elem));
}
return true;
}
else if constexpr (std::is_constructible_v<out_t, basic_value<string_t>>) {
out = out_t(in);
return true;
}
else {
_serialization_helper::unable_to_deserialize<out_t>();
}

View File

@@ -1,5 +1,7 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include "array.hpp"
#include "object.hpp"
#include "value.hpp"
#include "value.hpp"

View File

@@ -1,7 +1,14 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <iomanip>
#include <limits>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include <variant>
namespace json
{
@@ -61,12 +68,38 @@ constexpr bool is_container<T, std::void_t<typename T::value_type, range_value_t
template <typename T, typename = void>
constexpr bool is_map = false;
template <typename T>
constexpr bool is_map<T, std::void_t<typename T::key_type, typename T::mapped_type>> = is_container<T>;
constexpr bool is_map<T, std::void_t<typename T::key_type, typename T::mapped_type>> =
is_container<T>;
template <typename T, typename = void>
constexpr bool is_fixed_array = false;
template <template <typename, size_t> typename arr_t, typename value_t, size_t size>
constexpr bool is_fixed_array<arr_t<value_t, size>> = true;
template <typename T, typename = std::enable_if_t<is_fixed_array<T>>>
constexpr size_t fixed_array_size = 0;
template <template <typename, size_t> typename arr_t, typename value_t, size_t size>
constexpr size_t fixed_array_size<arr_t<value_t, size>> = size;
template <typename T, typename = void>
constexpr bool is_collection = false;
template <typename T>
constexpr bool is_collection<T> = is_container<T> && !is_map<T>;
constexpr bool is_collection<T> = is_container<T> && !is_map<T> && !is_fixed_array<T>;
template <typename T>
constexpr bool is_variant = false;
template <typename... args_t>
constexpr bool is_variant<std::variant<args_t...>> = true;
template <typename T>
constexpr bool is_tuple = false;
template <typename... args_t>
constexpr bool is_tuple<std::tuple<args_t...>> = true;
template <typename T>
constexpr bool is_pair = false;
template <typename... args_t>
constexpr bool is_pair<std::pair<args_t...>> = true;
template <typename T>
class has_to_json_in_member
@@ -85,7 +118,8 @@ template <typename T>
class has_to_json_in_templ_spec
{
template <typename U>
static auto test(int) -> decltype(std::declval<ext::jsonization<U>>().to_json(std::declval<U>()), std::true_type());
static auto test(int)
-> decltype(std::declval<ext::jsonization<U>>().to_json(std::declval<U>()), std::true_type());
template <typename U>
static std::false_type test(...);
@@ -113,8 +147,7 @@ class has_check_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<U>>().check_json(std::declval<json::basic_value<string_t>>()),
std::true_type());
-> decltype(std::declval<ext::jsonization<U>>().check_json(std::declval<json::basic_value<string_t>>()), std::true_type());
template <typename U>
static std::false_type test(...);
@@ -142,9 +175,7 @@ class has_from_json_in_templ_spec
{
template <typename U>
static auto test(int)
-> decltype(std::declval<ext::jsonization<U>>().from_json(std::declval<json::basic_value<string_t>>(),
std::declval<U&>()),
std::true_type());
-> decltype(std::declval<ext::jsonization<U>>().from_json(std::declval<json::basic_value<string_t>>(), std::declval<U&>()), std::true_type());
template <typename U>
static std::false_type test(...);
@@ -154,7 +185,7 @@ public:
};
template <typename string_t>
static constexpr string_t unescape_string(const string_t& str)
inline constexpr string_t unescape_string(const string_t& str)
{
using char_t = typename string_t::value_type;
@@ -202,26 +233,41 @@ static constexpr string_t unescape_string(const string_t& str)
}
template <typename string_t>
static constexpr string_t true_string()
inline constexpr string_t true_string()
{
return { 't', 'r', 'u', 'e' };
}
template <typename string_t>
static constexpr string_t false_string()
inline constexpr string_t false_string()
{
return { 'f', 'a', 'l', 's', 'e' };
}
template <typename string_t>
static constexpr string_t null_string()
inline constexpr string_t null_string()
{
return { 'n', 'u', 'l', 'l' };
}
template <typename string_t, typename any_t>
string_t to_basic_string(any_t&& arg)
inline string_t to_basic_string(any_t&& arg)
{
#ifdef MEOJSON_KEEP_FLOATING_PRECISION
using real_type = std::remove_reference_t<any_t>;
if constexpr (std::is_floating_point_v<real_type>) {
if constexpr (std::is_same_v<string_t, std::string>) {
std::ostringstream oss;
oss << std::setprecision(std::numeric_limits<real_type>::max_digits10) << arg;
return oss.str();
}
else if constexpr (std::is_same_v<string_t, std::wstring>) {
std::wostringstream oss;
oss << std::setprecision(std::numeric_limits<real_type>::max_digits10) << arg;
return oss.str();
}
}
#endif
if constexpr (std::is_same_v<string_t, std::string>) {
return std::to_string(std::forward<any_t>(arg));
}
@@ -232,4 +278,54 @@ string_t to_basic_string(any_t&& arg)
static_assert(!sizeof(any_t), "Unsupported type");
}
}
template <std::size_t id, typename string_t, typename variant_t>
inline bool _serialize_variant_impl(basic_value<string_t>& val, variant_t&& var)
{
if (var.index() != id) {
return false;
}
val = basic_value<string_t>(std::get<id>(std::forward<variant_t>(var)));
return true;
}
template <typename string_t, typename variant_t, std::size_t... ids>
inline basic_value<string_t> serialize_variant(variant_t&& var, std::index_sequence<ids...>)
{
basic_value<string_t> val;
(_serialize_variant_impl<ids>(val, std::forward<variant_t>(var)) || ...);
return val;
}
template <std::size_t id, typename string_t, typename variant_t>
inline bool _deserialize_variant_impl(const basic_value<string_t>& val, variant_t& var)
{
using alt_t = std::variant_alternative_t<id, variant_t>;
if (!val.template is<alt_t>()) {
return false;
}
var = val.template as<alt_t>();
return true;
}
template <typename string_t, typename variant_t, std::size_t... ids>
inline variant_t deserialize_variant(const basic_value<string_t>& val, std::index_sequence<ids...>)
{
variant_t var;
(_deserialize_variant_impl<ids>(val, var) || ...);
return var;
}
template <typename string_t, typename variant_t, std::size_t... ids>
inline bool detect_variant(const basic_value<string_t>& val, std::index_sequence<ids...>)
{
return (val.template is<std::variant_alternative_t<ids, variant_t>>() || ...);
}
template <typename string_t, typename tuple_t, std::size_t... ids>
inline bool detect_tuple(const basic_value<string_t>& val, std::index_sequence<ids...>)
{
return val.is_array() && val.as_array().size() == std::tuple_size_v<tuple_t>
&& (val.at(ids).template is<std::tuple_element_t<ids, tuple_t>>() || ...);
}
} // namespace json::_utils

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cstddef>
@@ -7,6 +9,8 @@
#include <ostream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <variant>
#include "exception.hpp"
@@ -64,30 +68,87 @@ public:
template <typename... args_t>
basic_value(value_type type, args_t&&... args);
template <typename collection_t,
std::enable_if_t<_utils::is_collection<collection_t> &&
std::is_constructible_v<typename basic_array<string_t>::value_type,
_utils::range_value_t<collection_t>>,
bool> = true>
basic_value(collection_t&& collection) : basic_value(basic_array<string_t>(std::forward<collection_t>(collection)))
{}
template <typename map_t, std::enable_if_t<_utils::is_map<map_t> &&
std::is_constructible_v<typename basic_object<string_t>::value_type,
_utils::range_value_t<map_t>>,
bool> = true>
basic_value(map_t&& map) : basic_value(basic_object<string_t>(std::forward<map_t>(map)))
{}
template <
typename collection_t,
std::enable_if_t<
_utils::is_collection<collection_t>
&& std::is_constructible_v<
typename basic_array<string_t>::value_type,
_utils::range_value_t<collection_t>>,
bool> = true>
basic_value(collection_t&& collection)
: basic_value(basic_array<string_t>(std::forward<collection_t>(collection)))
{
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& value) : basic_value(value.to_json())
{}
template <typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& value) : basic_value(ext::jsonization<jsonization_t>().to_json(value))
{}
template <
typename fixed_array_t,
std::enable_if_t<_utils::is_fixed_array<fixed_array_t>, bool> = true>
basic_value(const fixed_array_t& arr)
: basic_value(basic_array<string_t>(arr))
{
}
template <typename value_t, std::enable_if_t<!std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
template <
typename map_t,
std::enable_if_t<
_utils::is_map<map_t>
&& std::is_constructible_v<
typename basic_object<string_t>::value_type,
_utils::range_value_t<map_t>>,
bool> = true>
basic_value(map_t&& map)
: basic_value(basic_object<string_t>(std::forward<map_t>(map)))
{
}
template <typename enum_t, std::enable_if_t<std::is_enum_v<enum_t>, bool> = true>
basic_value(enum_t e)
: basic_value(static_cast<std::underlying_type_t<enum_t>>(e))
{
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_member<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& value)
: basic_value(value.to_json())
{
}
template <
typename jsonization_t,
std::enable_if_t<_utils::has_to_json_in_templ_spec<jsonization_t>::value, bool> = true>
basic_value(const jsonization_t& value)
: basic_value(ext::jsonization<jsonization_t>().to_json(value))
{
}
template <typename... elem_ts>
basic_value(std::tuple<elem_ts...>&& tup)
: basic_value(basic_array<string_t>(std::forward<std::tuple<elem_ts...>>(tup)))
{
}
template <typename elem1_t, typename elem2_t>
basic_value(std::pair<elem1_t, elem2_t>&& pair)
: basic_value(basic_array<string_t>(std::pair<elem1_t, elem2_t>(pair)))
{
}
template <
typename variant_t,
std::enable_if_t<_utils::is_variant<std::decay_t<variant_t>>, bool> = true>
basic_value(variant_t&& var)
: basic_value(_utils::serialize_variant<string_t>(
std::forward<variant_t>(var),
std::make_index_sequence<std::variant_size_v<std::decay_t<variant_t>>>()))
{
}
template <
typename value_t,
std::enable_if_t<!std::is_convertible_v<value_t, basic_value<string_t>>, 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.
@@ -99,13 +160,21 @@ public:
~basic_value();
bool valid() const noexcept { return _type != value_type::invalid; }
bool empty() const noexcept { return is_null(); }
bool is_null() const noexcept { return _type == value_type::null; }
bool is_number() const noexcept { return _type == value_type::number; }
bool is_boolean() const noexcept { return _type == value_type::boolean; }
bool is_string() const noexcept { return _type == value_type::string; }
bool is_array() const noexcept { return _type == value_type::array; }
bool is_object() const noexcept { return _type == value_type::object; }
template <typename value_t>
bool is() const noexcept;
@@ -114,9 +183,13 @@ public:
bool contains(const string_t& key) const;
bool contains(size_t pos) const;
bool exists(const string_t& key) const { return contains(key); }
bool exists(size_t pos) const { return contains(pos); }
value_type type() const noexcept { return _type; }
const basic_value<string_t>& at(size_t pos) const;
const basic_value<string_t>& at(const string_t& key) const;
@@ -148,6 +221,11 @@ public:
template <typename value_t, template <typename...> typename collection_t = std::vector>
collection_t<value_t> as_collection() const;
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array>
fixed_array_t<value_t, Size> as_fixed_array() const;
template <typename value_t, template <typename...> typename map_t = std::map>
map_t<string_t, value_t> as_map() const;
@@ -162,20 +240,29 @@ public:
void clear() noexcept;
string_t dumps(std::optional<size_t> indent = std::nullopt) const { return indent ? format(*indent) : to_string(); }
string_t dumps(std::optional<size_t> indent = std::nullopt) const
{
return indent ? format(*indent) : to_string();
}
// return raw string
string_t to_string() const;
string_t format(size_t indent = 4) const { return format(indent, 0); }
basic_value<string_t>& operator=(const basic_value<string_t>& rhs);
basic_value<string_t>& operator=(basic_value<string_t>&&) noexcept;
template <typename value_t, std::enable_if_t<std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
template <
typename value_t,
std::enable_if_t<std::is_convertible_v<value_t, basic_value<string_t>>, bool> = true>
basic_value<string_t>& operator=(value_t rhs)
{
return *this = basic_value<string_t>(std::move(rhs));
}
bool operator==(const basic_value<string_t>& rhs) const;
bool operator!=(const basic_value<string_t>& rhs) const { return !(*this == rhs); }
const basic_value<string_t>& operator[](size_t pos) const;
@@ -200,34 +287,63 @@ public:
basic_value<string_t>& operator+=(basic_array<string_t>&& rhs);
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(); }
explicit operator unsigned long long() const { return as_unsigned_long_long(); }
explicit operator float() const { return as_float(); }
explicit operator double() const { return as_double(); }
explicit operator long double() const { return as_long_double(); }
explicit operator string_t() const { return as_string(); }
explicit operator basic_array<string_t>() const { return as_array(); }
explicit operator basic_object<string_t>() const { return as_object(); }
template <typename value_t, template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
template <
typename value_t,
template <typename...> typename collection_t = std::vector,
std::enable_if_t<_utils::is_collection<collection_t<value_t>>, bool> = true>
explicit operator collection_t<value_t>() const
{
return as_collection<value_t, collection_t>();
}
template <typename value_t, template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
template <
typename value_t,
size_t Size,
template <typename, size_t> typename fixed_array_t = std::array,
std::enable_if_t<_utils::is_fixed_array<fixed_array_t<value_t, Size>>, bool> = true>
explicit operator fixed_array_t<value_t, Size>() const
{
return as_fixed_array<value_t, Size, fixed_array_t>();
}
template <
typename value_t,
template <typename...> typename map_t = std::map,
std::enable_if_t<_utils::is_map<map_t<string_t, value_t>>, bool> = true>
explicit operator map_t<string_t, value_t>() const
{
return as_map<value_t, map_t>();
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> = true>
template <
typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_member<jsonization_t, string_t>::value, bool> =
true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
@@ -236,8 +352,12 @@ public:
}
return dst;
}
template <typename jsonization_t,
std::enable_if_t<_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value, bool> = true>
template <
typename jsonization_t,
std::enable_if_t<
_utils::has_from_json_in_templ_spec<jsonization_t, string_t>::value,
bool> = true>
explicit operator jsonization_t() const
{
jsonization_t dst {};
@@ -247,6 +367,32 @@ public:
return dst;
}
template <typename enum_t, std::enable_if_t<std::is_enum_v<enum_t>, bool> = true>
explicit operator enum_t() const
{
return static_cast<enum_t>(static_cast<std::underlying_type_t<enum_t>>(*this));
}
template <typename... elem_ts>
explicit operator std::tuple<elem_ts...>() const
{
return as_array().template as_tuple<elem_ts...>();
}
template <typename elem1_t, typename elem2_t>
explicit operator std::pair<elem1_t, elem2_t>() const
{
return as_array().template as_pair<elem1_t, elem2_t>();
}
template <typename... args_t>
explicit operator std::variant<args_t...>() const
{
return _utils::deserialize_variant<string_t, std::variant<args_t...>>(
*this,
std::make_index_sequence<std::variant_size_v<std::variant<args_t...>>>());
}
private:
friend class basic_array<string_t>;
friend class basic_object<string_t>;
@@ -256,8 +402,9 @@ private:
static var_t deep_copy(const var_t& src);
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
auto get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
auto
get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const;
template <typename value_t, typename first_key_t, typename... rest_keys_t>
auto get_helper(const value_t& default_value, first_key_t&& first, rest_keys_t&&... rest) const;
@@ -276,89 +423,125 @@ inline basic_value<string_t>::basic_value() = default;
template <typename string_t>
inline basic_value<string_t>::basic_value(const basic_value<string_t>& rhs)
: _type(rhs._type), _raw_data(deep_copy(rhs._raw_data))
{}
: _type(rhs._type)
, _raw_data(deep_copy(rhs._raw_data))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(basic_value<string_t>&& rhs) noexcept = default;
template <typename string_t>
inline basic_value<string_t>::basic_value(bool b)
: _type(value_type::boolean),
_raw_data(string_t(b ? _utils::true_string<string_t>() : _utils::false_string<string_t>()))
{}
: _type(value_type::boolean)
, _raw_data(string_t(b ? _utils::true_string<string_t>() : _utils::false_string<string_t>()))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(int num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(unsigned num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(long num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(unsigned long num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(long long num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(unsigned long long num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(float num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(double num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(long double num)
: _type(value_type::number), _raw_data(_utils::to_basic_string<string_t>(num))
{}
: _type(value_type::number)
, _raw_data(_utils::to_basic_string<string_t>(num))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(const char_t* str) : _type(value_type::string), _raw_data(string_t(str))
{}
inline basic_value<string_t>::basic_value(const char_t* str)
: _type(value_type::string)
, _raw_data(string_t(str))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(string_t str) : _type(value_type::string), _raw_data(std::move(str))
{}
inline basic_value<string_t>::basic_value(string_t str)
: _type(value_type::string)
, _raw_data(std::move(str))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(std::nullptr_t) : _type(value_type::null)
{}
inline basic_value<string_t>::basic_value(std::nullptr_t)
: _type(value_type::null)
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(basic_array<string_t> arr)
: _type(value_type::array), _raw_data(std::make_unique<basic_array<string_t>>(std::move(arr)))
{}
: _type(value_type::array)
, _raw_data(std::make_unique<basic_array<string_t>>(std::move(arr)))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(basic_object<string_t> obj)
: _type(value_type::object), _raw_data(std::make_unique<basic_object<string_t>>(std::move(obj)))
{}
: _type(value_type::object)
, _raw_data(std::make_unique<basic_object<string_t>>(std::move(obj)))
{
}
template <typename string_t>
inline basic_value<string_t>::basic_value(std::initializer_list<typename basic_object<string_t>::value_type> init_list)
: _type(value_type::object), _raw_data(std::make_unique<basic_object<string_t>>(init_list))
{}
inline basic_value<string_t>::basic_value(
std::initializer_list<typename basic_object<string_t>::value_type> init_list)
: _type(value_type::object)
, _raw_data(std::make_unique<basic_object<string_t>>(init_list))
{
}
// for Pimpl
template <typename string_t>
@@ -380,7 +563,7 @@ inline bool basic_value<string_t>::is() const noexcept
else if constexpr (std::is_same_v<bool, value_t>) {
return is_boolean();
}
else if constexpr (std::is_arithmetic_v<value_t>) {
else if constexpr (std::is_arithmetic_v<value_t> || std::is_enum_v<value_t>) {
return is_number();
}
else if constexpr (std::is_constructible_v<string_t, value_t>) {
@@ -392,12 +575,31 @@ inline bool basic_value<string_t>::is() const noexcept
else if constexpr (_utils::is_collection<value_t>) {
return is_array() && all<typename value_t::value_type>();
}
else if constexpr (_utils::is_fixed_array<value_t>) {
return is_array() && all<typename value_t::value_type>()
&& as_array().size() == _utils::fixed_array_size<value_t>;
}
else if constexpr (std::is_same_v<basic_object<string_t>, value_t>) {
return is_object();
}
else if constexpr (_utils::is_map<value_t>) {
return is_object() && std::is_constructible_v<string_t, typename value_t::key_type> &&
all<typename value_t::mapped_type>();
return is_object() && std::is_constructible_v<string_t, typename value_t::key_type>
&& all<typename value_t::mapped_type>();
}
else if constexpr (_utils::is_variant<value_t>) {
return _utils::detect_variant<string_t, value_t>(
*this,
std::make_index_sequence<std::variant_size_v<value_t>>());
}
else if constexpr (_utils::is_pair<value_t>) {
return is_array() && as_array().size() == 2
&& at(0).template is<typename value_t::first_type>()
&& at(1).template is<typename value_t::second_type>();
}
else if constexpr (_utils::is_tuple<value_t>) {
return _utils::detect_tuple<string_t, value_t>(
*this,
std::make_index_sequence<std::tuple_size_v<value_t>>());
}
else {
static_assert(!sizeof(value_t), "Unsupported type");
@@ -444,33 +646,42 @@ template <typename string_t>
template <typename... key_then_default_value_t>
inline auto basic_value<string_t>::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<sizeof...(keys_then_default_value) - 1> {});
return get(
std::forward_as_tuple(keys_then_default_value...),
std::make_index_sequence<sizeof...(keys_then_default_value) - 1> {});
}
template <typename string_t>
template <typename... key_then_default_value_t, size_t... keys_indexes_t>
inline auto basic_value<string_t>::get(std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
inline auto basic_value<string_t>::get(
std::tuple<key_then_default_value_t...> keys_then_default_value,
std::index_sequence<keys_indexes_t...>) const
{
constexpr unsigned long default_value_index = sizeof...(key_then_default_value_t) - 1;
return get_helper(std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
return get_helper(
std::get<default_value_index>(keys_then_default_value),
std::get<keys_indexes_t>(keys_then_default_value)...);
}
template <typename string_t>
template <typename value_t, typename first_key_t, typename... rest_keys_t>
inline auto basic_value<string_t>::get_helper(const value_t& default_value, first_key_t&& first,
rest_keys_t&&... rest) const
inline auto basic_value<string_t>::get_helper(
const value_t& default_value,
first_key_t&& first,
rest_keys_t&&... rest) const
{
if constexpr (std::is_constructible_v<string_t, first_key_t>) {
return is_object() ? as_object().get_helper(default_value, std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
return is_object() ? as_object().get_helper(
default_value,
std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
: default_value;
}
else if constexpr (std::is_integral_v<std::decay_t<first_key_t>>) {
return is_array() ? as_array().get_helper(default_value, std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
return is_array() ? as_array().get_helper(
default_value,
std::forward<first_key_t>(first),
std::forward<rest_keys_t>(rest)...)
: default_value;
}
else {
@@ -480,16 +691,22 @@ inline auto basic_value<string_t>::get_helper(const value_t& default_value, firs
template <typename string_t>
template <typename value_t, typename unique_key_t>
inline auto basic_value<string_t>::get_helper(const value_t& default_value, unique_key_t&& first) const
inline auto
basic_value<string_t>::get_helper(const value_t& default_value, unique_key_t&& first) const
{
if constexpr (std::is_constructible_v<string_t, unique_key_t>) {
return is_object() ? as_object().get_helper(default_value, std::forward<unique_key_t>(first)) : default_value;
return is_object()
? as_object().get_helper(default_value, std::forward<unique_key_t>(first))
: default_value;
}
else if constexpr (std::is_integral_v<std::decay_t<unique_key_t>>) {
return is_array() ? as_array().get_helper(default_value, std::forward<unique_key_t>(first)) : default_value;
return is_array() ? as_array().get_helper(default_value, std::forward<unique_key_t>(first))
: default_value;
}
else {
static_assert(!sizeof(unique_key_t), "Parameter must be integral or string_t constructible");
static_assert(
!sizeof(unique_key_t),
"Parameter must be integral or string_t constructible");
}
}
@@ -722,10 +939,14 @@ template <typename string_t>
template <typename... args_t>
inline decltype(auto) basic_value<string_t>::emplace(args_t&&... args)
{
constexpr bool is_array_args = std::is_constructible_v<typename basic_array<string_t>::value_type, args_t...>;
constexpr bool is_object_args = std::is_constructible_v<typename basic_object<string_t>::value_type, args_t...>;
constexpr bool is_array_args =
std::is_constructible_v<typename basic_array<string_t>::value_type, args_t...>;
constexpr bool is_object_args =
std::is_constructible_v<typename basic_object<string_t>::value_type, args_t...>;
static_assert(is_array_args || is_object_args, "Args can not constructure a array or object value");
static_assert(
is_array_args || is_object_args,
"Args can not constructure a array or object value");
if constexpr (is_array_args) {
return as_array().emplace_back(std::forward<args_t>(args)...);
@@ -801,6 +1022,13 @@ inline collection_t<value_t> basic_value<string_t>::as_collection() const
return as_array().template as_collection<value_t, collection_t>();
}
template <typename string_t>
template <typename value_t, size_t Size, template <typename, size_t> typename fixed_array_t>
inline fixed_array_t<value_t, Size> basic_value<string_t>::as_fixed_array() const
{
return as_array().template as_fixed_array<value_t, Size>();
}
template <typename string_t>
template <typename value_t, template <typename...> typename map_t>
inline map_t<string_t, value_t> basic_value<string_t>::as_map() const
@@ -818,12 +1046,15 @@ inline basic_value<string_t>& basic_value<string_t>::operator=(const basic_value
}
template <typename string_t>
inline basic_value<string_t>& basic_value<string_t>::operator=(basic_value<string_t>&& rhs) noexcept = default;
inline basic_value<string_t>&
basic_value<string_t>::operator=(basic_value<string_t>&& rhs) noexcept = default;
template <typename string_t>
inline bool basic_value<string_t>::operator==(const basic_value<string_t>& rhs) const
{
if (_type != rhs._type) return false;
if (_type != rhs._type) {
return false;
}
switch (_type) {
case value_type::null:
@@ -878,7 +1109,8 @@ inline basic_value<string_t>& basic_value<string_t>::operator[](string_t&& key)
}
template <typename string_t>
inline basic_value<string_t> basic_value<string_t>::operator|(const basic_object<string_t>& rhs) const&
inline basic_value<string_t>
basic_value<string_t>::operator|(const basic_object<string_t>& rhs) const&
{
return as_object() | rhs;
}
@@ -916,7 +1148,8 @@ inline basic_value<string_t>& basic_value<string_t>::operator|=(basic_object<str
}
template <typename string_t>
inline basic_value<string_t> basic_value<string_t>::operator+(const basic_array<string_t>& rhs) const&
inline basic_value<string_t>
basic_value<string_t>::operator+(const basic_array<string_t>& rhs) const&
{
return as_array() + rhs;
}
@@ -956,9 +1189,12 @@ inline basic_value<string_t>& basic_value<string_t>::operator+=(basic_array<stri
template <typename string_t>
template <typename... args_t>
inline basic_value<string_t>::basic_value(value_type type, args_t&&... args)
: _type(type), _raw_data(std::forward<args_t>(args)...)
: _type(type)
, _raw_data(std::forward<args_t>(args)...)
{
static_assert(std::is_constructible_v<var_t, args_t...>, "Parameter can't be used to construct a var_t");
static_assert(
std::is_constructible_v<var_t, args_t...>,
"Parameter can't be used to construct a var_t");
}
template <typename string_t>
@@ -981,11 +1217,14 @@ inline typename basic_value<string_t>::var_t basic_value<string_t>::deep_copy(co
return dst;
}
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 =
std::enable_if_t<std::is_same_v<std_ostream_t, ostream_t> || std::is_base_of_v<std_ostream_t, ostream_t>>>
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 = 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();

View File

@@ -1,6 +1,10 @@
#pragma once
// IWYU pragma: begin_exports
#include "common/serialization.hpp"
#include "common/types.hpp"
#include "parser/parser.hpp"
#include "reflection/jsonization.hpp"
// IWYU pragma: end_exports

View File

@@ -1,4 +1,8 @@
#pragma once
// IWYU pragma: begin_exports
#include "common/types.hpp"
#include "parser5/parser5.hpp"
#include "parser5/parser5.hpp"
// IWYU pragma: end_exports

View File

@@ -1,13 +1,17 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
#include <bit>
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;
@@ -15,25 +19,37 @@ inline constexpr bool is_little_endian()
}
#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);
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);
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);
@@ -45,14 +61,17 @@ 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);
@@ -63,16 +82,19 @@ 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;
@@ -86,14 +108,17 @@ 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);
@@ -102,10 +127,12 @@ inline int countr_one(uint64_t x)
// no constexpr endian awareness before C++20
inline bool is_little_endian()
{
union {
union
{
uint32_t u32;
uint8_t u8;
} u = { 0x01020304 };
return u.u8 == 4;
}
} // namespace json::_bitops

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cstdint>
@@ -28,11 +30,13 @@ struct packed_bytes
};
}
#ifndef MEOJSON_DISABLE_PACKED_BYTES
#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
#endif
namespace json::_packed_bytes
{
@@ -66,14 +70,19 @@ struct packed_bytes_trait_uint64
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 (_bitops::is_little_endian())
if (_bitops::is_little_endian()) {
return _bitops::countr_zero(x) / 8;
else
}
else {
return _bitops::countl_zero(x) / 8;
}
}
};
@@ -108,16 +117,22 @@ struct packed_bytes_trait_uint32
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 (_bitops::is_little_endian())
if (_bitops::is_little_endian()) {
return _bitops::countr_zero(x) / 8;
else
}
else {
return _bitops::countl_zero(x) / 8;
}
}
};
template <>
struct packed_bytes<8>
{
@@ -133,9 +148,14 @@ struct packed_bytes<4>
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>>>>;
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>>>>;
} // namespace json::_packed_bytes

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
// current NEON implementation doesn't outperform 64-bit scalar implementation
@@ -17,7 +19,10 @@ struct packed_bytes_trait_neon
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)
{
@@ -26,19 +31,31 @@ struct packed_bytes_trait_neon
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)
{
#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);
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
}

View File

@@ -1,4 +1,7 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include "packed_bytes.hpp"
#include <emmintrin.h>
@@ -35,9 +38,15 @@ struct packed_bytes_trait_sse
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 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)
{
@@ -97,14 +106,20 @@ struct packed_bytes_trait_avx2
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 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)
{

View File

@@ -1,5 +1,8 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <cctype>
#include <fstream>
#include <optional>
#include <ostream>
@@ -15,8 +18,10 @@ namespace json
// * parser declare *
// ****************************
template <typename string_t = default_string_t, typename parsing_t = void,
typename accel_traits = _packed_bytes::packed_bytes_trait_max>
template <
typename string_t = default_string_t,
typename parsing_t = void,
typename accel_traits = _packed_bytes::packed_bytes_trait_max>
class parser
{
public:
@@ -28,7 +33,12 @@ public:
static std::optional<basic_value<string_t>> parse(const parsing_t& content);
private:
parser(parsing_iter_t cbegin, parsing_iter_t cend) noexcept : _cur(cbegin), _end(cend) { ; }
parser(parsing_iter_t cbegin, parsing_iter_t cend) noexcept
: _cur(cbegin)
, _end(cend)
{
;
}
std::optional<basic_value<string_t>> parse();
basic_value<string_t> parse_value();
@@ -47,6 +57,7 @@ private:
bool skip_string_literal_with_accel();
bool skip_whitespace() noexcept;
bool skip_digit();
bool skip_unicode_escape(uint16_t& pair_high, string_t& result);
private:
parsing_iter_t _cur;
@@ -63,8 +74,10 @@ auto parse(const parsing_t& content);
template <typename char_t>
auto parse(char_t* content);
template <typename istream_t,
typename = std::enable_if_t<std::is_base_of_v<std::basic_istream<typename istream_t::char_type>, istream_t>>>
template <
typename istream_t,
typename = std::enable_if_t<
std::is_base_of_v<std::basic_istream<typename istream_t::char_type>, istream_t>>>
auto parse(istream_t& istream, bool check_bom);
template <typename ifstream_t = std::ifstream, typename path_t = void>
@@ -72,17 +85,17 @@ auto open(const path_t& path, bool check_bom = false);
namespace literals
{
value operator""_json(const char* str, size_t len);
wvalue operator""_json(const wchar_t* str, size_t len);
value operator""_json(const char* str, size_t len);
wvalue operator""_json(const wchar_t* str, size_t len);
value operator""_jvalue(const char* str, size_t len);
wvalue operator""_jvalue(const wchar_t* str, size_t len);
value operator""_jvalue(const char* str, size_t len);
wvalue operator""_jvalue(const wchar_t* str, size_t len);
array operator""_jarray(const char* str, size_t len);
warray operator""_jarray(const wchar_t* str, size_t len);
array operator""_jarray(const char* str, size_t len);
warray operator""_jarray(const wchar_t* str, size_t len);
object operator""_jobject(const char* str, size_t len);
wobject operator""_jobject(const wchar_t* str, size_t len);
object operator""_jobject(const char* str, size_t len);
wobject operator""_jobject(const wchar_t* str, size_t len);
}
template <typename string_t = default_string_t>
@@ -93,7 +106,8 @@ const basic_value<string_t> invalid_value();
// *************************
template <typename string_t, typename parsing_t, typename accel_traits>
inline std::optional<basic_value<string_t>> parser<string_t, parsing_t, accel_traits>::parse(const parsing_t& content)
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, accel_traits>(content.cbegin(), content.cend()).parse();
}
@@ -252,7 +266,9 @@ inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_st
if (!string_opt) {
return invalid_value<string_t>();
}
return basic_value<string_t>(basic_value<string_t>::value_type::string, std::move(string_opt).value());
return basic_value<string_t>(
basic_value<string_t>::value_type::string,
std::move(string_opt).value());
}
template <typename string_t, typename parsing_t, typename accel_traits>
@@ -350,7 +366,10 @@ inline basic_value<string_t> parser<string_t, parsing_t, accel_traits>::parse_ob
return invalid_value<string_t>();
}
result.emplace(std::move(*key_opt), std::move(val));
auto emplaced = result.emplace(std::move(*key_opt), std::move(val)).second;
if (!emplaced) {
return invalid_value<string_t>();
}
if (*_cur == ',') {
++_cur;
@@ -382,6 +401,7 @@ inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_
string_t result;
auto no_escape_beg = _cur;
uint16_t pair_high = 0;
while (_cur != _end) {
if constexpr (sizeof(*_cur) == 1 && accel_traits::available) {
@@ -399,6 +419,9 @@ inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_
if (_cur == _end) {
return std::nullopt;
}
if (pair_high && *_cur != 'u') {
return std::nullopt;
}
switch (*_cur) {
case '"':
result.push_back('"');
@@ -424,9 +447,11 @@ inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_
case 't':
result.push_back('\t');
break;
// case 'u':
// result.push_back('\u');
// break;
case 'u':
if (!skip_unicode_escape(pair_high, result)) {
return std::nullopt;
}
break;
default:
// Illegal backslash escape
return std::nullopt;
@@ -435,10 +460,16 @@ inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_
break;
}
case '"': {
if (pair_high) {
return std::nullopt;
}
result += string_t(no_escape_beg, _cur++);
return result;
}
default:
if (pair_high) {
return std::nullopt;
}
++_cur;
break;
}
@@ -446,6 +477,103 @@ inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_
return std::nullopt;
}
template <typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<string_t, parsing_t, accel_traits>::skip_unicode_escape(
uint16_t& pair_high,
string_t& result)
{
uint16_t cp = 0;
for (int i = 0; i < 4; ++i) {
if (++_cur == _end) {
return false;
}
if (!std::isxdigit(static_cast<unsigned char>(*_cur))) {
return false;
}
cp <<= 4;
if ('0' <= *_cur && *_cur <= '9') {
cp |= *_cur - '0';
}
else if ('a' <= *_cur && *_cur <= 'f') {
cp |= *_cur - 'a' + 10;
}
else if ('A' <= *_cur && *_cur <= 'F') {
cp |= *_cur - 'A' + 10;
}
else {
return false;
}
}
uint32_t ext_cp = cp;
uint16_t hi_cp = 0, lo_cp = 0;
if (0xD800 <= cp && cp <= 0xDBFF) {
if (pair_high) {
return false;
}
pair_high = cp;
return true;
}
if (0xDC00 <= cp && cp <= 0xDFFF) {
if (!pair_high) {
return false;
}
ext_cp = (((pair_high - 0xD800) << 10) | (cp - 0xDC00)) + 0x10000;
hi_cp = pair_high;
lo_cp = cp;
pair_high = 0;
}
if constexpr (std::is_same_v<typename string_t::value_type, char>) {
// utf8
if (ext_cp <= 0x7F) {
result.push_back(static_cast<char>(ext_cp));
}
else if (ext_cp <= 0x7FF) {
result.push_back(static_cast<char>(((ext_cp >> 6) & 0b00011111) | 0b11000000u));
result.push_back(static_cast<char>((ext_cp & 0b00111111) | 0b10000000u));
}
else if (ext_cp <= 0xFFFF) {
result.push_back(static_cast<char>(((ext_cp >> 12) & 0b00001111) | 0b11100000u));
result.push_back(static_cast<char>(((ext_cp >> 6) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>((ext_cp & 0b00111111) | 0b10000000u));
}
else {
result.push_back(static_cast<char>(((ext_cp >> 18) & 0b00000111) | 0b11110000u));
result.push_back(static_cast<char>(((ext_cp >> 12) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>(((ext_cp >> 6) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>((ext_cp & 0b00111111) | 0b10000000u));
}
}
else if constexpr (std::is_same_v<typename string_t::value_type, wchar_t>) {
if constexpr (sizeof(wchar_t) == 4) {
result.push_back(static_cast<wchar_t>(ext_cp));
}
else if constexpr (sizeof(wchar_t) == 2) {
if (ext_cp <= 0xFFFF) {
result.push_back(static_cast<wchar_t>(ext_cp));
}
else {
result.push_back(static_cast<wchar_t>(hi_cp));
result.push_back(static_cast<wchar_t>(lo_cp));
}
}
else {
static_assert(!sizeof(typename string_t::value_type), "Unsupported wchar");
}
}
else {
static_assert(!sizeof(typename string_t::value_type), "Unsupported type");
}
return true;
}
template <typename string_t, typename parsing_t, typename accel_traits>
inline bool parser<string_t, parsing_t, accel_traits>::skip_string_literal_with_accel()
{
@@ -456,8 +584,10 @@ inline bool parser<string_t, parsing_t, accel_traits>::skip_string_literal_with_
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>('\\')));
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;
@@ -551,8 +681,8 @@ auto parse(istream_t& ifs, bool check_bom)
static constexpr uchar Bom_1 = 0xBB;
static constexpr uchar Bom_2 = 0xBF;
if (str.size() >= 3 && static_cast<uchar>(str.at(0)) == Bom_0 && static_cast<uchar>(str.at(1)) == Bom_1 &&
static_cast<uchar>(str.at(2)) == Bom_2) {
if (str.size() >= 3 && static_cast<uchar>(str.at(0)) == Bom_0
&& static_cast<uchar>(str.at(1)) == Bom_1 && static_cast<uchar>(str.at(2)) == Bom_2) {
str.assign(str.begin() + 3, str.end());
}
}
@@ -578,50 +708,56 @@ auto open(const path_t& filepath, bool check_bom)
namespace literals
{
inline value operator""_json(const char* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline wvalue operator""_json(const wchar_t* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline value operator""_json(const char* str, size_t len)
{
return operator""_jvalue(str, len);
}
inline value operator""_jvalue(const char* str, size_t len)
{
return parse(std::string_view(str, len)).value_or(value());
}
inline wvalue operator""_jvalue(const wchar_t* str, size_t len)
{
return parse(std::wstring_view(str, len)).value_or(wvalue());
}
inline wvalue operator""_json(const wchar_t* str, size_t len)
{
return operator""_jvalue(str, 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();
}
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();
}
inline value operator""_jvalue(const char* str, size_t len)
{
return parse(std::string_view(str, len)).value_or(value());
}
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();
}
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();
}
inline wvalue operator""_jvalue(const wchar_t* str, size_t len)
{
return parse(std::wstring_view(str, len)).value_or(wvalue());
}
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();
}
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();
}
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();
}
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();
}
} // namespace literals
template <typename string_t>
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());
return basic_value<string_t>(
basic_value<string_t>::value_type::invalid,
typename basic_value<string_t>::var_t());
}
} // namespace json

View File

@@ -1,10 +1,11 @@
// IWYU pragma: private, include <meojson/json5.hpp>
#pragma once
#include <algorithm>
#include <cctype>
#include <cmath>
#include <iomanip>
#include <regex>
#include <sstream>
#include <stack>
#include <vector>
@@ -31,6 +32,7 @@ public:
{
public:
exception() = default;
exception(const std::string& type, const std::string& msg, const std::string& detail)
{
std::stringstream ss;
@@ -38,6 +40,7 @@ public:
ss << detail << std::endl;
_what = ss.str();
}
exception(const exception&) = default;
exception& operator=(const exception&) = default;
exception(exception&&) = default;
@@ -50,8 +53,12 @@ public:
{
public:
InvalidChar(u8char ch = 0, const std::string& detail = "")
: exception("Invalid Char", "Unexpected token \'" + StringFromCharCode(ch) + "\'", detail)
{}
: exception(
"Invalid Char",
"Unexpected token \'" + StringFromCharCode(ch) + "\'",
detail)
{
}
};
class InvalidIdentifier : public exception
@@ -59,14 +66,17 @@ public:
public:
InvalidIdentifier(const std::string& msg = "", const std::string& detail = "")
: exception("Invalid Identifier", msg, detail)
{}
{
}
};
class InvalidEOF : public exception
{
public:
InvalidEOF(const std::string& msg = "", const std::string& detail = "") : exception("Invalid EOF", msg, detail)
{}
InvalidEOF(const std::string& msg = "", const std::string& detail = "")
: exception("Invalid EOF", msg, detail)
{
}
};
public:
@@ -175,7 +185,13 @@ public:
static std::optional<value> parse(const string_t& content, std::string* error = nullptr);
private:
parser5(string_iter_t cbegin, string_iter_t cend) noexcept : _cur(cbegin), _end(cend), _line_begin_cur(cbegin) {}
parser5(string_iter_t cbegin, string_iter_t cend) noexcept
: _cur(cbegin)
, _end(cend)
, _line_begin_cur(cbegin)
{
}
std::optional<value> parse();
private:
@@ -272,62 +288,68 @@ inline bool parser5<string_t>::unicode::isSpaceSeparator(u8char ch)
template <typename string_t>
inline bool parser5<string_t>::unicode::isIdStartChar(u8char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '$') || (ch == '_') ||
findInRange(json::unicode::id_start, toUnicode(ch));
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch == '$') || (ch == '_')
|| findInRange(json::unicode::id_start, toUnicode(ch));
}
template <typename string_t>
inline bool parser5<string_t>::unicode::isIdContinueChar(u8char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '$') ||
(ch == '_') || findInRange(json::unicode::id_continue, toUnicode(ch));
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')
|| (ch == '$') || (ch == '_') || findInRange(json::unicode::id_continue, toUnicode(ch));
}
template <typename string_t>
inline bool parser5<string_t>::unicode::isDigit(u8char ch)
{
auto str = StringFromCharCode(ch);
return std::regex_search(str, std::regex(R"([0-9])"));
return (ch >= '0' && ch <= '9');
}
template <typename string_t>
inline bool parser5<string_t>::unicode::isHexDigit(u8char ch)
{
auto str = StringFromCharCode(ch);
return std::regex_search(str, std::regex(R"([0-9A-Fa-f])"));
return (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') || (ch >= '0' && ch <= '9');
}
template <typename string_t>
inline uint64_t parser5<string_t>::unicode::toUnicode(u8char ch)
{
std::stack<uint8_t> coded;
if (ch == 0) {
return ch;
}
std::stack<uint8_t> coded;
while (ch > 0) {
coded.push(ch & 0xff);
ch = ch >> 8;
ch >>= 8;
}
u8char charcode = 0;
uint8_t t = coded.top();
coded.pop();
if (t < 128) {
return t;
}
uint8_t high_bit_mask = (1 << 6) - 1;
uint8_t high_bit_mask = 0b00111111;
uint8_t high_bit_shift = 0;
int total_bits = 0;
const int other_bits = 6;
while ((t & 0xC0) == 0xC0) {
t <<= 1;
t &= 0xff;
total_bits += 6;
total_bits += other_bits;
high_bit_mask >>= 1;
high_bit_shift++;
charcode <<= other_bits;
charcode |= coded.top() & ((1 << other_bits) - 1);
coded.pop();
if (!coded.empty()) {
charcode <<= other_bits;
charcode |= coded.top() & ((1 << other_bits) - 1);
coded.pop();
}
}
charcode |= static_cast<uint64_t>((t >> high_bit_shift) & high_bit_mask) << total_bits;
return charcode;
}
@@ -346,7 +368,8 @@ inline bool parser5<string_t>::unicode::findInRange(const array_t& range, u8char
return false;
}
// set 中保存的是类似于 { start1, end1, start2, end2, ... } 的形式, 区间可表示为[start, end)
// 判断lb是否位于start的位置, 如果是, 则表示codePoint在某个区间的内部, 如果不是, 则表示codePoint在两个区间中间
// 判断lb是否位于start的位置, 如果是, 则表示codePoint在某个区间的内部, 如果不是,
// 则表示codePoint在两个区间中间
return std::distance(begin, lb) % 2 == 0;
}
@@ -519,11 +542,13 @@ inline typename parser5<string_t>::u8char parser5<string_t>::unicodeEscape()
/* utf-8 reader */
template <typename string_t>
inline typename parser5<string_t>::u8char parser5<string_t>::peek(const string_iter_t& begin, const string_iter_t& end,
size_t* plen)
inline typename parser5<string_t>::u8char
parser5<string_t>::peek(const string_iter_t& begin, const string_iter_t& end, size_t* plen)
{
if (begin == end) {
if (plen) *plen = 0;
if (plen) {
*plen = 0;
}
return 0;
}
uint8_t head = *begin;
@@ -549,10 +574,12 @@ inline typename parser5<string_t>::u8char parser5<string_t>::peek(const std::str
{
return peek(str.cbegin(), str.cend());
}
inline constexpr size_t operator"" _sz(unsigned long long size)
{
return size;
}
template <typename string_t>
inline typename parser5<string_t>::u8char parser5<string_t>::read()
{
@@ -581,11 +608,15 @@ inline typename parser5<string_t>::u8char parser5<string_t>::read()
template <typename string_t>
inline std::string parser5<string_t>::StringFromCharCode(typename parser5<string_t>::u8char code)
{
if (code == 0) return "";
if (code == 0) {
return "";
}
std::string str;
for (auto i = 0; i < 8; ++i) {
auto ch = (0xff & code);
if (ch) str.insert(0, 1, static_cast<char>(ch));
if (ch) {
str.insert(0, 1, static_cast<char>(ch));
}
code >>= 8;
}
return str;
@@ -700,7 +731,8 @@ inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_m
}
template <typename string_t>
inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_multiLineCommentAsterisk()
inline std::optional<typename parser5<string_t>::Token>
parser5<string_t>::lex_multiLineCommentAsterisk()
{
switch (_current_char) {
case '*':
@@ -808,7 +840,8 @@ inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_v
}
template <typename string_t>
inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_identifierNameStartEscape()
inline std::optional<typename parser5<string_t>::Token>
parser5<string_t>::lex_identifierNameStartEscape()
{
if (_current_char != 'u') {
throw InvalidChar(_current_char, exceptionDetailInfo());
@@ -855,7 +888,8 @@ inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_i
}
template <typename string_t>
inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_identifierNameEscape()
inline std::optional<typename parser5<string_t>::Token>
parser5<string_t>::lex_identifierNameEscape()
{
if (_current_char != 'u') {
throw InvalidChar(_current_char, exceptionDetailInfo());
@@ -1047,7 +1081,8 @@ inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_d
}
template <typename string_t>
inline std::optional<typename parser5<string_t>::Token> parser5<string_t>::lex_decimalExponentInteger()
inline std::optional<typename parser5<string_t>::Token>
parser5<string_t>::lex_decimalExponentInteger()
{
if (unicode::isDigit(_current_char)) {
_buffer += StringFromCharCode(read());
@@ -1386,7 +1421,8 @@ inline void parser5<string_t>::parse_afterArrayValue()
template <typename string_t>
inline void parser5<string_t>::parse_end()
{}
{
}
template <typename string_t>
inline void parser5<string_t>::parseStates(ParseState state)
@@ -1417,6 +1453,7 @@ inline void parser5<string_t>::parseStates(ParseState state)
break;
}
}
/* stack operation */
template <typename string_t>
inline void parser5<string_t>::push()

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json5.hpp>
// This is a generated file. Do not edit.
#pragma once
#include <array>

View File

@@ -1,3 +1,5 @@
// IWYU pragma: private, include <meojson/json.hpp>
#pragma once
#include <string>
@@ -8,9 +10,12 @@
namespace json::_jsonization_helper
{
struct next_is_optional_t
{};
{
};
struct va_arg_end
{};
{
};
struct dumper
{
@@ -21,19 +26,25 @@ struct dumper
result.emplace(key, var);
return result;
}
template <typename... rest_t>
json::value _to_json(const char*, next_is_optional_t, rest_t&&... rest) const
{
return _to_json(std::forward<rest_t>(rest)...);
}
json::value _to_json(va_arg_end) const { return {}; }
};
struct checker
{
template <typename var_t, typename... rest_t>
bool _check_json(const json::value& in, std::string& error_key, const char* key, const var_t&,
rest_t&&... rest) const
bool _check_json(
const json::value& in,
std::string& error_key,
const char* key,
const var_t&,
rest_t&&... rest) const
{
auto opt = in.find(key);
if (!opt || !opt->is<var_t>()) {
@@ -42,9 +53,16 @@ struct checker
}
return _check_json(in, error_key, std::forward<rest_t>(rest)...);
}
template <typename var_t, typename... rest_t>
bool _check_json(const json::value& in, std::string& error_key, const char*, next_is_optional_t, const char* key,
const var_t&, rest_t&&... rest) const
bool _check_json(
const json::value& in,
std::string& error_key,
const char*,
next_is_optional_t,
const char* key,
const var_t&,
rest_t&&... rest) const
{
auto opt = in.find(key);
if (opt) {
@@ -56,13 +74,19 @@ struct checker
return _check_json(in, error_key, std::forward<rest_t>(rest)...);
}
bool _check_json(const json::value&, std::string&, va_arg_end) const { return true; }
};
struct loader
{
template <typename var_t, typename... rest_t>
bool _from_json(const json::value& in, std::string& error_key, const char* key, var_t& var, rest_t&&... rest) const
bool _from_json(
const json::value& in,
std::string& error_key,
const char* key,
var_t& var,
rest_t&&... rest) const
{
auto opt = in.find(key);
if (!opt || !opt->is<var_t>()) {
@@ -73,9 +97,16 @@ struct loader
return _from_json(in, error_key, std::forward<rest_t>(rest)...);
}
template <typename var_t, typename... rest_t>
bool _from_json(const json::value& in, std::string& error_key, const char*, next_is_optional_t, const char* key,
var_t& var, rest_t&&... rest) const
bool _from_json(
const json::value& in,
std::string& error_key,
const char*,
next_is_optional_t,
const char* key,
var_t& var,
rest_t&&... rest) const
{
auto opt = in.find(key);
if (opt) {
@@ -88,6 +119,7 @@ struct loader
return _from_json(in, error_key, std::forward<rest_t>(rest)...);
}
bool _from_json(const json::value&, std::string&, va_arg_end) const { return true; }
};
} // namespace json::_jsonization_helper
@@ -111,122 +143,322 @@ namespace json::_private_macro
#define _MEOJSON_FOR_EACH_0(pred, ...)
#define _MEOJSON_FOR_EACH_1(pred, x, ...) pred(x)
#define _MEOJSON_FOR_EACH_2(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_1(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_3(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_2(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_4(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_3(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_5(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_4(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_6(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_5(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_7(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_6(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_8(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_7(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_9(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_8(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_10(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_9(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_11(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_10(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_12(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_11(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_13(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_12(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_14(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_13(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_15(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_14(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_16(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_15(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_17(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_16(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_18(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_17(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_19(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_18(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_20(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_19(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_21(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_20(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_22(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_21(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_23(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_22(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_24(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_23(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_25(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_24(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_26(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_25(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_27(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_26(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_28(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_27(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_29(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_28(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_30(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_29(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_31(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_30(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_32(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_31(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_33(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_32(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_34(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_33(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_35(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_34(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_36(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_35(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_37(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_36(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_38(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_37(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_39(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_38(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_40(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_39(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_41(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_40(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_42(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_41(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_43(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_42(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_44(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_43(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_45(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_44(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_46(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_45(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_47(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_46(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_48(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_47(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_49(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_48(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_50(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_49(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_51(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_50(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_52(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_51(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_53(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_52(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_54(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_53(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_55(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_54(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_56(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_55(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_57(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_56(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_58(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_57(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_59(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_58(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_60(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_59(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_61(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_60(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_62(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_61(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_63(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_62(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_64(pred, x, ...) pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_63(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_2(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_1(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_3(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_2(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_4(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_3(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_5(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_4(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_6(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_5(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_7(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_6(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_8(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_7(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_9(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_8(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_10(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_9(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_11(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_10(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_12(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_11(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_13(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_12(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_14(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_13(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_15(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_14(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_16(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_15(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_17(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_16(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_18(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_17(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_19(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_18(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_20(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_19(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_21(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_20(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_22(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_21(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_23(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_22(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_24(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_23(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_25(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_24(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_26(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_25(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_27(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_26(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_28(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_27(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_29(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_28(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_30(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_29(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_31(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_30(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_32(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_31(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_33(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_32(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_34(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_33(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_35(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_34(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_36(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_35(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_37(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_36(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_38(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_37(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_39(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_38(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_40(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_39(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_41(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_40(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_42(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_41(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_43(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_42(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_44(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_43(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_45(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_44(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_46(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_45(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_47(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_46(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_48(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_47(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_49(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_48(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_50(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_49(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_51(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_50(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_52(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_51(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_53(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_52(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_54(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_53(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_55(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_54(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_56(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_55(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_57(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_56(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_58(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_57(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_59(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_58(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_60(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_59(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_61(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_60(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_62(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_61(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_63(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_62(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_64(pred, x, ...) \
pred(x) _MEOJSON_EXPAND(_MEOJSON_FOR_EACH_63(pred, __VA_ARGS__))
#define _MEOJSON_ARG_COUNT(...) \
_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT1(0, ##__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \
30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, \
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define _MEOJSON_ARG_COUNT1(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, \
_38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, \
_56, _57, _58, _59, _60, _61, _62, _63, _64, N, ...) \
#define _MEOJSON_ARG_COUNT(...) \
_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT1( \
0, \
##__VA_ARGS__, \
64, \
63, \
62, \
61, \
60, \
59, \
58, \
57, \
56, \
55, \
54, \
53, \
52, \
51, \
50, \
49, \
48, \
47, \
46, \
45, \
44, \
43, \
42, \
41, \
40, \
39, \
38, \
37, \
36, \
35, \
34, \
33, \
32, \
31, \
30, \
29, \
28, \
27, \
26, \
25, \
24, \
23, \
22, \
21, \
20, \
19, \
18, \
17, \
16, \
15, \
14, \
13, \
12, \
11, \
10, \
9, \
8, \
7, \
6, \
5, \
4, \
3, \
2, \
1, \
0))
#define _MEOJSON_ARG_COUNT1( \
_0, \
_1, \
_2, \
_3, \
_4, \
_5, \
_6, \
_7, \
_8, \
_9, \
_10, \
_11, \
_12, \
_13, \
_14, \
_15, \
_16, \
_17, \
_18, \
_19, \
_20, \
_21, \
_22, \
_23, \
_24, \
_25, \
_26, \
_27, \
_28, \
_29, \
_30, \
_31, \
_32, \
_33, \
_34, \
_35, \
_36, \
_37, \
_38, \
_39, \
_40, \
_41, \
_42, \
_43, \
_44, \
_45, \
_46, \
_47, \
_48, \
_49, \
_50, \
_51, \
_52, \
_53, \
_54, \
_55, \
_56, \
_57, \
_58, \
_59, \
_60, \
_61, \
_62, \
_63, \
_64, \
N, \
...) \
N
#define _MEOJSON_FOR_EACH_(N, pred, ...) _MEOJSON_EXPAND(_MEOJSON_CONCATENATE(_MEOJSON_FOR_EACH_, N)(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH_(N, pred, ...) \
_MEOJSON_EXPAND(_MEOJSON_CONCATENATE(_MEOJSON_FOR_EACH_, N)(pred, __VA_ARGS__))
#define _MEOJSON_FOR_EACH(pred, ...) \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH_(_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT(__VA_ARGS__)), pred, __VA_ARGS__))
_MEOJSON_EXPAND( \
_MEOJSON_FOR_EACH_(_MEOJSON_EXPAND(_MEOJSON_ARG_COUNT(__VA_ARGS__)), pred, __VA_ARGS__))
#define _MEOJSON_VARNAME(x) _MEOJSON_CONCATENATE(_meojson_jsonization_, x)
#define _MEOJSON_KEY_VALUE(x) _MEOJSON_STRINGIZE(x), x,
} // namespace json::_private_macro
#define MEO_TOJSON(...) \
json::value to_json() const \
{ \
return json::_jsonization_helper::dumper()._to_json(_MEOJSON_EXPAND( \
_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) json::_jsonization_helper::va_arg_end {}); \
#define MEO_TOJSON(...) \
json::value to_json() const \
{ \
return json::_jsonization_helper::dumper()._to_json( \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
}
#define MEO_CHECKJSON(...) \
bool check_json(const json::value& _MEOJSON_VARNAME(in)) const \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return check_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool check_json(const json::value& _MEOJSON_VARNAME(in), std::string& _MEOJSON_VARNAME(error_key)) const \
{ \
return json::_jsonization_helper::checker()._check_json( \
_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
#define MEO_CHECKJSON(...) \
bool check_json(const json::value& _MEOJSON_VARNAME(in)) const \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return check_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool check_json( \
const json::value& _MEOJSON_VARNAME(in), \
std::string& _MEOJSON_VARNAME(error_key)) const \
{ \
return json::_jsonization_helper::checker()._check_json( \
_MEOJSON_VARNAME(in), \
_MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
}
#define MEO_FROMJSON(...) \
bool from_json(const json::value& _MEOJSON_VARNAME(in)) \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return from_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool from_json(const json::value& _MEOJSON_VARNAME(in), std::string& _MEOJSON_VARNAME(error_key)) \
{ \
return json::_jsonization_helper::loader()._from_json( \
_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
#define MEO_FROMJSON(...) \
bool from_json(const json::value& _MEOJSON_VARNAME(in)) \
{ \
std::string _MEOJSON_VARNAME(error_key); \
return from_json(_MEOJSON_VARNAME(in), _MEOJSON_VARNAME(error_key)); \
} \
bool from_json( \
const json::value& _MEOJSON_VARNAME(in), \
std::string& _MEOJSON_VARNAME(error_key)) \
{ \
return json::_jsonization_helper::loader()._from_json( \
_MEOJSON_VARNAME(in), \
_MEOJSON_VARNAME(error_key), \
_MEOJSON_EXPAND(_MEOJSON_FOR_EACH(_MEOJSON_KEY_VALUE, __VA_ARGS__)) \
json::_jsonization_helper::va_arg_end {}); \
}
#define MEO_JSONIZATION(...) \