225 template<
typename To>
233 r.set(
get<To>(lhs),
static_cast<To>(rhs));
236 r.set(
static_cast<To>(lhs),
get<To>(rhs));
249 if (
other.is_pointer()) {
256 other._tag = tag_type::monostate;
257 other._value._long_long = 0;
260 constexpr datum()
noexcept : _tag(tag_type::monostate), _value(0) {}
261 constexpr explicit datum(std::monostate)
noexcept : _tag(tag_type::monostate), _value(0) {}
262 constexpr explicit datum(nullptr_t)
noexcept : _tag(tag_type::null), _value(0) {}
263 constexpr explicit datum(continue_type)
noexcept : _tag(tag_type::flow_continue), _value(0) {}
264 constexpr explicit datum(break_type)
noexcept : _tag(tag_type::flow_break), _value(0) {}
265 constexpr explicit datum(
bool value)
noexcept : _tag(tag_type::boolean), _value(value) {}
266 constexpr explicit datum(std::floating_point
auto value)
noexcept :
271 constexpr explicit datum(numeric_integral
auto value)
noexcept :
276 constexpr explicit datum(decimal value)
noexcept : _tag(tag_type::decimal), _value(value) {}
277 constexpr explicit datum(std::chrono::year_month_day value)
noexcept : _tag(tag_type::year_month_day), _value(value) {}
279 explicit datum(std::string_view value)
noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
280 explicit datum(
char const *value)
noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
281 explicit datum(vector_type value)
noexcept : _tag(tag_type::vector), _value(
new vector_type{
std::move(value)}) {}
282 explicit datum(map_type value)
noexcept : _tag(tag_type::map), _value(
new map_type{
std::move(value)}) {}
283 explicit datum(bstring value)
noexcept : _tag(tag_type::bstring), _value(
new bstring{
std::move(value)}) {}
285 template<
typename...
Args>
286 [[
nodiscard]]
static datum make_vector(
Args const&...args)
noexcept
288 return datum{vector_type{datum{args}...}};
291 template<
typename Key,
typename Value,
typename...
Args>
292 static void populate_map(map_type& r, Key
const& key,
Value const& value,
Args const&...args)
noexcept
295 if constexpr (
sizeof...(Args) > 0) {
296 populate_map(r, args...);
300 template<
typename...
Args>
301 [[
nodiscard]]
static datum make_map(
Args const&...args)
noexcept
303 static_assert(
sizeof...(Args) % 2 == 0,
"Expect key value pairs for the arguments of make_map()");
306 if constexpr (
sizeof...(Args) > 0) {
307 populate_map(r, args...);
314 return datum{break_type{}};
319 return datum{continue_type{}};
322 constexpr datum& operator=(datum
const&
other)
noexcept
324 hi_return_on_self_assignment(
other);
328 _value =
other._value;
329 if (
other.is_pointer()) {
335 constexpr datum& operator=(datum&&
other)
noexcept
342 constexpr datum& operator=(std::floating_point
auto value)
noexcept(
sizeof(value) <= 4)
345 _tag = tag_type::floating_point;
346 _value =
static_cast<double>(value);
350 constexpr datum& operator=(numeric_integral
auto value)
noexcept(
sizeof(value) <= 4)
353 _tag = tag_type::integral;
354 _value =
static_cast<long long>(value);
358 constexpr datum& operator=(decimal value)
361 _tag = tag_type::decimal;
365 constexpr datum& operator=(
bool value)
noexcept
368 _tag = tag_type::boolean;
373 constexpr datum& operator=(std::chrono::year_month_day value)
noexcept
376 _tag = tag_type::year_month_day;
381 constexpr datum& operator=(std::monostate)
noexcept
384 _tag = tag_type::monostate;
389 constexpr datum& operator=(nullptr_t)
noexcept
392 _tag = tag_type::null;
400 _tag = tag_type::string;
405 datum& operator=(
char const *value)
noexcept
408 _tag = tag_type::string;
413 datum& operator=(std::string_view value)
noexcept
416 _tag = tag_type::string;
421 datum& operator=(vector_type value)
noexcept
424 _tag = tag_type::vector;
425 _value =
new vector_type{
std::move(value)};
429 datum& operator=(map_type value)
noexcept
432 _tag = tag_type::map;
437 datum& operator=(bstring value)
noexcept
440 _tag = tag_type::bstring;
448 case tag_type::floating_point:
450 case tag_type::decimal:
452 case tag_type::boolean:
454 case tag_type::integral:
456 case tag_type::year_month_day:
458 case tag_type::string:
460 case tag_type::vector:
464 case tag_type::bstring:
471 [[
nodiscard]]
constexpr bool empty()
const
474 case tag_type::string:
476 case tag_type::vector:
480 case tag_type::bstring:
483 throw std::domain_error(std::format(
"Type {} can not be checked for empty", *
this));
487 template<std::
floating_po
int T>
488 constexpr explicit operator T()
const
491 case tag_type::floating_point:
493 case tag_type::integral:
495 case tag_type::decimal:
497 case tag_type::boolean:
500 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
504 constexpr explicit operator decimal()
const
507 case tag_type::floating_point:
509 case tag_type::integral:
511 case tag_type::decimal:
513 case tag_type::boolean:
516 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
520 template<numeric_
integral T>
521 constexpr explicit operator T()
const
539 hilet r =
static_cast<long long>(*d);
553 constexpr explicit operator std::chrono::year_month_day()
const
558 throw std::domain_error(std::format(
"Can't convert {} to an std::chrono::year_month_day",
repr(*
this)));
565 case tag_type::monostate:
567 case tag_type::floating_point:
568 return hi::to_string(_value._double);
569 case tag_type::decimal:
571 case tag_type::integral:
573 case tag_type::boolean:
574 return _value._bool ?
"true" :
"false";
575 case tag_type::year_month_day:
576 return std::format(
"{:%Y-%m-%d}", _value._year_month_day);
579 case tag_type::flow_break:
581 case tag_type::flow_continue:
583 case tag_type::string:
584 return *_value._string;
585 case tag_type::vector:
588 for (hilet& item : *_value._vector) {
598 for (hilet& item : *_value._map) {
599 r +=
repr(item.first);
601 r +=
repr(item.second);
607 case tag_type::bstring:
608 return base64::encode(*_value._bstring);
614 explicit operator std::string_view()
const
617 return std::string_view{*s};
623 explicit operator vector_type()
const
632 explicit operator map_type()
const
641 explicit operator bstring()
const
644 if (_tag != tag_type::bstring) {
653 case tag_type::floating_point:
655 case tag_type::decimal:
657 case tag_type::integral:
659 case tag_type::boolean:
661 case tag_type::year_month_day:
663 case tag_type::string:
665 case tag_type::vector:
669 case tag_type::bstring:
680 return _tag == tag_type::monostate;
688 return _tag == tag_type::flow_break;
696 return _tag == tag_type::flow_continue;
702 case tag_type::floating_point:
704 case tag_type::decimal:
706 case tag_type::integral:
708 case tag_type::boolean:
710 case tag_type::year_month_day:
718 case tag_type::string:
720 case tag_type::vector:
723 for (hilet& v : *_value._vector) {
724 r = hash_mix(r, v.hash());
731 for (hilet&
kv : *_value._map) {
732 r = hash_mix(r,
kv.first.hash(),
kv.second.hash());
736 case tag_type::bstring:
763 [[
nodiscard]]
constexpr datum
const& back()
const
787 [[
nodiscard]]
constexpr datum
const& front()
const
811 [[
nodiscard]]
constexpr auto cbegin()
const
820 [[
nodiscard]]
constexpr auto begin()
const
838 [[
nodiscard]]
constexpr auto cend()
const
872 for (hilet&
kv : *m) {
873 r.push_back(
kv.first);
888 for (hilet&
kv : *m) {
889 r.push_back(
kv.second);
905 for (hilet& item : *m) {
906 r.push_back(make_vector(item.first, item.second));
914 constexpr void push_back(
datum const& rhs)
917 return v->push_back(rhs);
923 constexpr void push_back(datum&& rhs)
932 template<
typename Arg>
933 constexpr void push_back(
Arg&&
arg)
935 push_back(datum{std::forward<Arg>(
arg)});
938 constexpr void pop_back()
944 return v->pop_back();
950 [[
nodiscard]]
constexpr bool contains(datum
const& rhs)
const
953 return m->contains(rhs);
959 template<
typename Arg>
962 return contains(datum{
arg});
968 find(path.cbegin(), path.cend(), r);
975 const_cast<datum *
>(
this)->find(path.cbegin(), path.cend(),
tmp);
991 return to_bool(
remove(path.cbegin(), path.cend()));
1001 hi_axiom(path.is_singular());
1002 return find_one(path.cbegin(), path.cend(),
false);
1012 hi_axiom(path.is_singular());
1013 return find_one(path.cbegin(), path.cend(),
true);
1023 hi_axiom(path.is_singular());
1024 return const_cast<datum *
>(
this)->
find_one(path.cbegin(), path.cend(),
false);
1034 index =
ssize(v) + index;
1044 hilet
it = m.find(rhs);
1045 if (
it == m.end()) {
1056 [[
nodiscard]]
constexpr datum& operator[](datum
const& rhs)
1063 index =
ssize(v) + index;
1080 [[
nodiscard]]
constexpr datum
const& operator[](
auto const& rhs)
const
1082 return (*
this)[datum{rhs}];
1085 [[
nodiscard]]
constexpr datum& operator[](
auto const& rhs)
1087 return (*
this)[datum{rhs}];
1090 [[
nodiscard]]
constexpr datum& operator++()
1093 ++_value._long_long;
1100 [[
nodiscard]]
constexpr datum& operator--()
1103 --_value._long_long;
1110 [[
nodiscard]]
constexpr datum operator++(
int)
1114 _value._long_long++;
1120 [[
nodiscard]]
constexpr datum operator--(
int)
1124 _value._long_long--;
1131 constexpr datum& operator+=(
auto const& rhs)
1137 return (*
this) = (*this) + rhs;
1141#define X(op, inner_op) \
1142 constexpr datum& operator op(auto const& rhs) \
1144 return (*this) = (*this)inner_op rhs; \
1158 [[
nodiscard]]
friend constexpr bool operator==(datum
const& lhs, datum
const& rhs)
noexcept
1185 return lhs._tag == rhs._tag;
1217 [[
nodiscard]]
friend constexpr std::partial_ordering operator<=>(datum
const& lhs, datum
const& rhs)
noexcept
1247 return lhs._tag <=> rhs._tag;
1261 [[
nodiscard]]
friend constexpr datum operator-(datum
const& rhs)
1286 [[
nodiscard]]
friend constexpr datum operator~(datum
const& rhs)
1310 [[
nodiscard]]
friend constexpr datum operator+(datum
const& lhs, datum
const& rhs)
1345 [[
nodiscard]]
friend constexpr datum operator-(datum
const& lhs, datum
const& rhs)
1372 [[
nodiscard]]
friend constexpr datum operator*(datum
const& lhs, datum
const& rhs)
1399 [[
nodiscard]]
friend constexpr datum operator/(datum
const& lhs, datum
const& rhs)
1435 [[
nodiscard]]
friend constexpr datum operator%(datum
const& lhs, datum
const& rhs)
1458 [[
nodiscard]]
friend constexpr datum
pow(datum
const& lhs, datum
const& rhs)
1481 [[
nodiscard]]
friend constexpr datum operator&(datum
const& lhs, datum
const& rhs)
1504 [[
nodiscard]]
friend constexpr datum operator|(datum
const& lhs, datum
const& rhs)
1527 [[
nodiscard]]
friend constexpr datum operator^(datum
const& lhs, datum
const& rhs)
1552 [[
nodiscard]]
friend constexpr datum operator<<(datum
const& lhs, datum
const& rhs)
1576 [[
nodiscard]]
friend constexpr datum operator>>(datum
const& lhs, datum
const& rhs)
1595 [[nodiscard]] friend constexpr auto operator op(datum const& lhs, auto const& rhs) \
1597 return lhs op datum{rhs}; \
1599 [[nodiscard]] friend constexpr auto operator op(auto const& lhs, datum const& rhs) \
1601 return datum{lhs} op rhs; \
1621 case tag_type::monostate:
1623 case tag_type::floating_point:
1624 return std::format(
"{:.1f}", rhs._value._double);
1625 case tag_type::decimal:
1627 case tag_type::integral:
1628 return std::format(
"{}", rhs._value._long_long);
1629 case tag_type::boolean:
1630 return rhs._value._bool ?
"true" :
"false";
1631 case tag_type::year_month_day:
1632 return std::format(
"{:%Y-%m-%d}", rhs._value._year_month_day);
1633 case tag_type::null:
1635 case tag_type::flow_break:
1637 case tag_type::flow_continue:
1639 case tag_type::string:
1640 return std::format(
"\"{}\"", *rhs._value._string);
1641 case tag_type::vector:
1644 for (hilet& item : *rhs._value._vector) {
1654 for (hilet& item : *rhs._value._map) {
1655 r +=
repr(item.first);
1657 r +=
repr(item.second);
1663 case tag_type::bstring:
1664 return base64::encode(*rhs._value._bstring);
1683 template<
typename T>
1686 if constexpr (std::is_same_v<T, double>) {
1687 return rhs._tag == tag_type::floating_point;
1688 }
else if constexpr (std::is_same_v<T, decimal>) {
1689 return rhs._tag == tag_type::decimal;
1690 }
else if constexpr (std::is_same_v<T, long long>) {
1691 return rhs._tag == tag_type::integral;
1692 }
else if constexpr (std::is_same_v<T, bool>) {
1693 return rhs._tag == tag_type::boolean;
1694 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1695 return rhs._tag == tag_type::year_month_day;
1696 }
else if constexpr (std::is_same_v<T, nullptr_t>) {
1697 return rhs._tag == tag_type::null;
1698 }
else if constexpr (std::is_same_v<T, std::monostate>) {
1699 return rhs._tag == tag_type::monostate;
1700 }
else if constexpr (std::is_same_v<T, break_type>) {
1701 return rhs._tag == tag_type::flow_break;
1702 }
else if constexpr (std::is_same_v<T, continue_type>) {
1703 return rhs._tag == tag_type::flow_continue;
1704 }
else if constexpr (std::is_same_v<T, std::string>) {
1705 return rhs._tag == tag_type::string;
1706 }
else if constexpr (std::is_same_v<T, vector_type>) {
1707 return rhs._tag == tag_type::vector;
1708 }
else if constexpr (std::is_same_v<T, map_type>) {
1709 return rhs._tag == tag_type::map;
1710 }
else if constexpr (std::is_same_v<T, bstring>) {
1711 return rhs._tag == tag_type::bstring;
1713 hi_static_no_default();
1728 template<
typename To>
1731 if constexpr (std::is_same_v<To, double>) {
1734 }
else if constexpr (std::is_same_v<To, decimal>) {
1736 }
else if constexpr (std::is_same_v<To, long long>) {
1751 template<
typename T>
1755 if constexpr (std::is_same_v<T, double>) {
1756 return rhs._value._double;
1757 }
else if constexpr (std::is_same_v<T, decimal>) {
1758 return rhs._value._decimal;
1759 }
else if constexpr (std::is_same_v<T, long long>) {
1760 return rhs._value._long_long;
1761 }
else if constexpr (std::is_same_v<T, bool>) {
1762 return rhs._value._bool;
1763 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1764 return rhs._value._year_month_day;
1765 }
else if constexpr (std::is_same_v<T, std::string>) {
1766 return *rhs._value._string;
1767 }
else if constexpr (std::is_same_v<T, vector_type>) {
1768 return *rhs._value._vector;
1769 }
else if constexpr (std::is_same_v<T, map_type>) {
1770 return *rhs._value._map;
1771 }
else if constexpr (std::is_same_v<T, bstring>) {
1772 return *rhs._value._bstring;
1774 hi_static_no_default();
1786 template<
typename T>
1790 if constexpr (std::is_same_v<T, double>) {
1791 return rhs._value._double;
1792 }
else if constexpr (std::is_same_v<T, decimal>) {
1793 return rhs._value._decimal;
1794 }
else if constexpr (std::is_same_v<T, long long>) {
1795 return rhs._value._long_long;
1796 }
else if constexpr (std::is_same_v<T, bool>) {
1797 return rhs._value._bool;
1798 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1799 return rhs._value._year_month_day;
1800 }
else if constexpr (std::is_same_v<T, std::string>) {
1801 return *rhs._value._string;
1802 }
else if constexpr (std::is_same_v<T, vector_type>) {
1803 return *rhs._value._vector;
1804 }
else if constexpr (std::is_same_v<T, map_type>) {
1805 return *rhs._value._map;
1806 }
else if constexpr (std::is_same_v<T, bstring>) {
1807 return *rhs._value._bstring;
1809 hi_static_no_default();
1821 template<
typename T>
1839 template<
typename T>
1858 template<
typename T>
1861 if (
auto *value = rhs.find_one(path)) {
1881 template<
typename T>
1896 enum class tag_type :
signed char {
1915 tag_type _tag = tag_type::monostate;
1918 long long _long_long;
1921 std::chrono::year_month_day _year_month_day;
1923 vector_type *_vector;
1929 constexpr value_type(decimal value)
noexcept : _decimal(value) {}
1930 constexpr value_type(
bool value)
noexcept : _bool(value) {}
1931 constexpr value_type(std::chrono::year_month_day value)
noexcept : _year_month_day(value) {}
1933 constexpr value_type(vector_type *value)
noexcept : _vector(value) {}
1934 constexpr value_type(map_type *value)
noexcept : _map(value) {}
1935 constexpr value_type(bstring *value)
noexcept : _bstring(value) {}
1942 return std::to_underlying(_tag) >= 0;
1947 return std::to_underlying(_tag) < 0;
1950 hi_no_inline
void copy_pointer(datum
const&
other)
noexcept
1952 hi_axiom(
other.is_pointer());
1953 switch (
other._tag) {
1954 case tag_type::string:
1957 case tag_type::vector:
1958 _value._vector =
new vector_type{*
other._value._vector};
1961 _value._map =
new map_type{*
other._value._map};
1963 case tag_type::bstring:
1964 _value._bstring =
new bstring{*
other._value._bstring};
1971 hi_no_inline
void _delete_pointer()
noexcept
1973 hi_axiom(is_pointer());
1975 case tag_type::string:
1976 delete _value._string;
1978 case tag_type::vector:
1979 delete _value._vector;
1984 case tag_type::bstring:
1985 delete _value._bstring;
1992 constexpr void delete_pointer()
noexcept
2002 for (
auto& item : *vector) {
2007 for (
auto& item : *map) {
2008 item.second.find(
it + 1,
it_end, r);
2018 for (
auto& item : *vector) {
2023 for (
auto& item : *map) {
2030 jsonpath::indices
const& indices,
2031 jsonpath::const_iterator
it,
2032 jsonpath::const_iterator
it_end,
2036 for (hilet index : indices.filter(
ssize(*vector))) {
2037 (*vector)[index].find(
it + 1,
it_end, r);
2043 jsonpath::names
const& names,
2044 jsonpath::const_iterator
it,
2045 jsonpath::const_iterator
it_end,
2049 for (hilet& name : names) {
2050 hilet
name_ = datum{name};
2052 if (
jt != map->cend()) {
2060 jsonpath::slice
const& slice,
2061 jsonpath::const_iterator
it,
2062 jsonpath::const_iterator
it_end,
2066 hilet first = slice.begin(vector->size());
2067 hilet last = slice.end(vector->size());
2069 for (
auto index = first; index != last; index += slice.step) {
2071 (*this)[index].find(
it + 1,
it_end, r);
2082 }
else if (std::holds_alternative<jsonpath::root>(*
it)) {
2085 }
else if (std::holds_alternative<jsonpath::current>(*
it)) {
2088 }
else if (std::holds_alternative<jsonpath::wildcard>(*
it)) {
2091 }
else if (std::holds_alternative<jsonpath::descend>(*
it)) {
2094 }
else if (
auto indices = std::get_if<jsonpath::indices>(&*
it)) {
2095 find_indices(*indices,
it,
it_end, r);
2097 }
else if (
auto names = std::get_if<jsonpath::names>(&*
it)) {
2100 }
else if (
auto slice = std::get_if<jsonpath::slice>(&*
it)) {
2108 [[
nodiscard]]
int remove_wildcard(jsonpath::const_iterator
it, jsonpath::const_iterator
it_end)
noexcept
2113 auto jt = vector->begin();
2114 while (
jt != vector->end()) {
2119 jt = vector->erase(
jt);
2124 return vector->empty() ? 2 : r;
2127 auto jt = map->begin();
2128 while (
jt != map->end()) {
2133 jt = map->erase(
jt);
2138 return map->empty() ? 2 : r;
2145 [[
nodiscard]]
int remove_descend(jsonpath::const_iterator
it, jsonpath::const_iterator
it_end)
noexcept
2158 auto jt = vector->begin();
2159 while (
jt != vector->end()) {
2164 jt = vector->erase(
jt);
2169 return vector->empty() ? 2 : r;
2172 auto jt = map->begin();
2173 while (
jt != map->end()) {
2178 jt = map->erase(
jt);
2183 return map->empty() ? 2 : r;
2191 remove_indices(jsonpath::indices
const& indices, jsonpath::const_iterator
it, jsonpath::const_iterator
it_end)
noexcept
2197 for (hilet index : indices.filter(
ssize(*vector))) {
2198 hilet
match = (*vector)[index - offset].remove(
it + 1,
it_end);
2201 vector->erase(vector->begin() + (index - offset));
2206 return vector->empty() ? 2 : r;
2214 remove_names(jsonpath::names
const& names, jsonpath::const_iterator
it, jsonpath::const_iterator
it_end)
noexcept
2219 for (hilet& name : names) {
2220 hilet
name_ = datum{name};
2222 if (
jt != map->cend()) {
2231 return map->empty() ? 2 : r;
2239 remove_slice(jsonpath::slice
const& slice, jsonpath::const_iterator
it, jsonpath::const_iterator
it_end)
noexcept
2244 hilet first = slice.begin(vector->size());
2245 hilet last = slice.end(vector->size());
2248 for (
auto index = first; index != last; index += slice.step) {
2250 hilet
match = (*this)[index - offset].remove(
it + 1,
it_end);
2254 vector->erase(vector->begin() + (index - offset));
2260 return vector->empty() ? 2 : r;
2273 }
else if (std::holds_alternative<jsonpath::root>(*
it)) {
2276 }
else if (std::holds_alternative<jsonpath::current>(*
it)) {
2279 }
else if (std::holds_alternative<jsonpath::wildcard>(*
it)) {
2280 return remove_wildcard(
it,
it_end);
2282 }
else if (std::holds_alternative<jsonpath::descend>(*
it)) {
2285 }
else if (
auto indices = std::get_if<jsonpath::indices>(&*
it)) {
2286 return remove_indices(*indices,
it,
it_end);
2288 }
else if (
auto names = std::get_if<jsonpath::names>(&*
it)) {
2289 return remove_names(*names,
it,
it_end);
2291 }
else if (
auto slice = std::get_if<jsonpath::slice>(&*
it)) {
2292 return remove_slice(*slice,
it,
it_end);
2300 find_one_name(datum
const& name, jsonpath::const_iterator
it, jsonpath::const_iterator
it_end,
bool create)
noexcept
2305 auto i = map->find(name);
2306 if (i != map->end()) {
2310 (*map)[name] = datum{std::monostate{}};
2318 *
this = datum::make_map(name, std::monostate{});
2332 }
else if (index == vector->size()
and create) {
2333 vector->push_back(datum{std::monostate{}});
2340 *
this = datum::make_vector(std::monostate{});
2353 }
else if (std::holds_alternative<jsonpath::root>(*
it)) {
2356 }
else if (std::holds_alternative<jsonpath::current>(*
it)) {
2359 }
else if (hilet *indices = std::get_if<jsonpath::indices>(&*
it)) {
2360 hi_axiom(indices->size() == 1);
2363 }
else if (hilet *names = std::get_if<jsonpath::names>(&*
it)) {
2364 hi_axiom(names->size() == 1);