234 template<
typename To>
238 if (holds_alternative<To>(lhs) and holds_alternative<To>(rhs)) {
239 r.set(get<To>(lhs), get<To>(rhs));
241 }
else if (holds_alternative<To>(lhs) and promotable_to<To>(rhs)) {
242 r.set(get<To>(lhs),
static_cast<To
>(rhs));
244 }
else if (promotable_to<To>(lhs) and holds_alternative<To>(rhs)) {
245 r.set(
static_cast<To
>(lhs), get<To>(rhs));
251 constexpr ~datum() noexcept
256 constexpr datum(datum
const& other) noexcept : _tag(other._tag), _value(other._value)
258 if (other.is_pointer()) {
263 constexpr datum(datum&& other) noexcept : _tag(
other._tag), _value(
other._value)
265 other._tag = tag_type::monostate;
266 other._value._long_long = 0;
269 constexpr datum() noexcept : _tag(tag_type::monostate), _value(0) {}
270 constexpr explicit datum(std::monostate) noexcept : _tag(tag_type::monostate), _value(0) {}
271 constexpr explicit datum(nullptr_t) noexcept : _tag(tag_type::null), _value(0) {}
272 constexpr explicit datum(continue_type) noexcept : _tag(tag_type::flow_continue), _value(0) {}
273 constexpr explicit datum(break_type) noexcept : _tag(tag_type::flow_break), _value(0) {}
274 constexpr explicit datum(
bool value) noexcept : _tag(tag_type::boolean), _value(value) {}
275 constexpr explicit datum(std::floating_point
auto value) noexcept :
276 _tag(tag_type::floating_point), _value(narrow_cast<double>(value))
280 constexpr explicit datum(numeric_integral
auto value) noexcept :
281 _tag(tag_type::integral), _value(narrow_cast<long long>(value))
285 constexpr explicit datum(decimal value) noexcept : _tag(tag_type::decimal), _value(value) {}
286 constexpr explicit datum(std::chrono::year_month_day value) noexcept : _tag(tag_type::year_month_day), _value(value) {}
288 explicit datum(std::string_view value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
289 explicit datum(
char const *value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
290 explicit datum(vector_type value) noexcept : _tag(tag_type::vector), _value(
new vector_type{
std::move(value)}) {}
291 explicit datum(map_type value) noexcept : _tag(tag_type::map), _value(
new map_type{
std::move(value)}) {}
292 explicit datum(bstring value) noexcept : _tag(tag_type::bstring), _value(
new bstring{
std::move(value)}) {}
294 template<
typename... Args>
295 [[nodiscard]]
static datum
make_vector(Args
const&...args)
noexcept
297 return datum{vector_type{datum{args}...}};
300 template<
typename Key,
typename Value,
typename... Args>
301 static void populate_map(map_type& r, Key
const& key, Value
const& value, Args
const&...args)
noexcept
304 if constexpr (
sizeof...(Args) > 0) {
305 populate_map(r, args...);
309 template<
typename... Args>
310 [[nodiscard]]
static datum make_map(Args
const&...args)
noexcept
312 static_assert(
sizeof...(Args) % 2 == 0,
"Expect key value pairs for the arguments of make_map()");
315 if constexpr (
sizeof...(Args) > 0) {
316 populate_map(r, args...);
321 [[nodiscard]]
static datum make_break() noexcept
323 return datum{break_type{}};
326 [[nodiscard]]
static datum make_continue() noexcept
328 return datum{continue_type{}};
331 constexpr datum& operator=(datum
const& other)
noexcept
333 hi_return_on_self_assignment(other);
337 _value =
other._value;
338 if (
other.is_pointer()) {
344 constexpr datum& operator=(datum&& other)
noexcept
351 constexpr datum& operator=(std::floating_point
auto value)
noexcept(
sizeof(value) <= 4)
354 _tag = tag_type::floating_point;
355 _value =
static_cast<double>(value);
359 constexpr datum& operator=(numeric_integral
auto value)
noexcept(
sizeof(value) <= 4)
362 _tag = tag_type::integral;
363 _value =
static_cast<long long>(value);
367 constexpr datum& operator=(decimal value)
370 _tag = tag_type::decimal;
374 constexpr datum& operator=(
bool value)
noexcept
377 _tag = tag_type::boolean;
382 constexpr datum& operator=(std::chrono::year_month_day value)
noexcept
385 _tag = tag_type::year_month_day;
390 constexpr datum& operator=(std::monostate)
noexcept
393 _tag = tag_type::monostate;
398 constexpr datum& operator=(nullptr_t)
noexcept
401 _tag = tag_type::null;
409 _tag = tag_type::string;
414 datum& operator=(
char const *value)
noexcept
417 _tag = tag_type::string;
422 datum& operator=(std::string_view value)
noexcept
425 _tag = tag_type::string;
430 datum& operator=(vector_type value)
noexcept
433 _tag = tag_type::vector;
434 _value =
new vector_type{
std::move(value)};
438 datum& operator=(map_type value)
noexcept
441 _tag = tag_type::map;
446 datum& operator=(bstring value)
noexcept
449 _tag = tag_type::bstring;
454 constexpr explicit operator bool() const noexcept
457 case tag_type::floating_point:
458 return to_bool(get<double>(*
this));
459 case tag_type::decimal:
460 return to_bool(get<decimal>(*
this));
461 case tag_type::boolean:
462 return get<bool>(*
this);
463 case tag_type::integral:
464 return to_bool(get<long long>(*
this));
465 case tag_type::year_month_day:
467 case tag_type::string:
468 return not get<std::string>(*this).empty();
469 case tag_type::vector:
470 return not get<vector_type>(*this).empty();
472 return not get<map_type>(*this).empty();
473 case tag_type::bstring:
474 return not get<bstring>(*this).empty();
480 [[nodiscard]]
constexpr bool empty()
const
483 case tag_type::string:
484 return get<std::string>(*this).empty();
485 case tag_type::vector:
486 return get<vector_type>(*this).empty();
488 return get<map_type>(*this).empty();
489 case tag_type::bstring:
490 return get<bstring>(*this).empty();
492 throw std::domain_error(std::format(
"Type {} can not be checked for empty", *
this));
496 template<std::
floating_po
int T>
497 constexpr explicit operator T()
const
500 case tag_type::floating_point:
501 return static_cast<T
>(get<double>(*
this));
502 case tag_type::integral:
503 return static_cast<T
>(get<long long>(*
this));
504 case tag_type::decimal:
505 return static_cast<T
>(get<decimal>(*
this));
506 case tag_type::boolean:
507 return static_cast<T
>(get<bool>(*
this));
509 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
513 constexpr explicit operator decimal()
const
516 case tag_type::floating_point:
517 return decimal(get<double>(*
this));
518 case tag_type::integral:
519 return decimal(get<long long>(*
this));
520 case tag_type::decimal:
521 return get<decimal>(*
this);
522 case tag_type::boolean:
523 return decimal(get<bool>(*
this));
525 throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
529 template<numeric_
integral T>
530 constexpr explicit operator T()
const
532 if (
auto f = get_if<double>(*
this)) {
539 return narrow_cast<T>(r);
541 }
else if (
auto i = get_if<long long>(*
this)) {
545 return narrow_cast<T>(*i);
547 }
else if (
auto d = get_if<decimal>(*
this)) {
548 hilet r =
static_cast<long long>(*d);
552 return narrow_cast<T>(r);
554 }
else if (
auto b = get_if<bool>(*
this)) {
555 return narrow_cast<T>(*b);
558 throw std::domain_error(std::format(
"Can't convert {} to an integral", repr(*
this)));
562 constexpr explicit operator std::chrono::year_month_day()
const
564 if (
auto ymd = get_if<std::chrono::year_month_day>(*
this)) {
567 throw std::domain_error(std::format(
"Can't convert {} to an std::chrono::year_month_day", repr(*
this)));
574 case tag_type::monostate:
576 case tag_type::floating_point:
578 case tag_type::decimal:
580 case tag_type::integral:
582 case tag_type::boolean:
583 return _value._bool ?
"true" :
"false";
584 case tag_type::year_month_day:
585 return std::format(
"{:%Y-%m-%d}", _value._year_month_day);
588 case tag_type::flow_break:
590 case tag_type::flow_continue:
592 case tag_type::string:
593 return *_value._string;
594 case tag_type::vector:
597 for (
hilet& item : *_value._vector) {
607 for (
hilet& item : *_value._map) {
608 r += repr(item.first);
610 r += repr(item.second);
616 case tag_type::bstring:
617 return base64::encode(*_value._bstring);
623 explicit operator std::string_view()
const
625 if (
auto s = get_if<std::string>(*
this)) {
626 return std::string_view{*s};
628 throw std::domain_error(std::format(
"Can't convert {} to an std::string_view", repr(*
this)));
632 explicit operator vector_type()
const
634 if (
auto v = get_if<vector_type>(*
this)) {
637 throw std::domain_error(std::format(
"Can't convert {} to an vector", repr(*
this)));
641 explicit operator map_type()
const
643 if (
auto m = get_if<map_type>(*
this)) {
650 explicit operator bstring()
const
653 if (_tag != tag_type::bstring) {
654 throw std::domain_error(std::format(
"Can't convert {} to an bstring", repr(*
this)));
656 return get<bstring>(*
this);
659 [[nodiscard]]
constexpr char const *type_name() const noexcept
662 case tag_type::floating_point:
664 case tag_type::decimal:
666 case tag_type::integral:
668 case tag_type::boolean:
670 case tag_type::year_month_day:
672 case tag_type::string:
674 case tag_type::vector:
678 case tag_type::bstring:
689 return _tag == tag_type::monostate;
695 [[nodiscard]]
constexpr bool is_break() const noexcept
697 return _tag == tag_type::flow_break;
705 return _tag == tag_type::flow_continue;
711 case tag_type::floating_point:
713 case tag_type::decimal:
715 case tag_type::integral:
717 case tag_type::boolean:
719 case tag_type::year_month_day:
722 r |= narrow_cast<uint32_t>(
static_cast<int>(_value._year_month_day.year())) << 16;
723 r |= narrow_cast<uint32_t>(
static_cast<unsigned>(_value._year_month_day.month())) << 8;
724 r |= narrow_cast<uint32_t>(
static_cast<unsigned>(_value._year_month_day.day()));
727 case tag_type::string:
729 case tag_type::vector:
732 for (
hilet& v : *_value._vector) {
733 r = hash_mix(r, v.hash());
740 for (
hilet& kv : *_value._map) {
741 r = hash_mix(r, kv.first.hash(), kv.second.hash());
745 case tag_type::bstring:
754 if (
hilet *s = get_if<std::string>(*
this)) {
756 }
else if (
hilet *v = get_if<vector_type>(*
this)) {
758 }
else if (
hilet *m = get_if<map_type>(*
this)) {
760 }
else if (
hilet *b = get_if<bstring>(*
this)) {
767 [[nodiscard]]
constexpr friend std::size_t size(datum
const& rhs)
772 [[nodiscard]]
constexpr datum
const& back()
const
774 if (
hilet *v = get_if<vector_type>(*
this)) {
784 [[nodiscard]]
constexpr datum& back()
786 if (
auto *v = get_if<vector_type>(*
this)) {
796 [[nodiscard]]
constexpr datum
const& front()
const
798 if (
hilet *v = get_if<vector_type>(*
this)) {
804 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
808 [[nodiscard]]
constexpr datum& front()
810 if (
auto *v = get_if<vector_type>(*
this)) {
816 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
820 [[nodiscard]]
constexpr auto cbegin()
const
822 if (
hilet *v = get_if<vector_type>(*
this)) {
825 throw std::domain_error(std::format(
"Can not evaluate {}.cbegin()", repr(*
this)));
829 [[nodiscard]]
constexpr auto begin()
const
831 if (
hilet *v = get_if<vector_type>(*
this)) {
834 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
838 [[nodiscard]]
constexpr auto begin()
840 if (
hilet *v = get_if<vector_type>(*
this)) {
843 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
847 [[nodiscard]]
constexpr auto cend()
const
849 if (
hilet *v = get_if<vector_type>(*
this)) {
856 [[nodiscard]]
constexpr auto end()
const
858 if (
hilet *v = get_if<vector_type>(*
this)) {
865 [[nodiscard]]
constexpr auto end()
867 if (
hilet *v = get_if<vector_type>(*
this)) {
878 if (
hilet *
m = get_if<map_type>(*
this)) {
882 r.push_back(kv.first);
894 if (
hilet *
m = get_if<map_type>(*
this)) {
898 r.push_back(kv.second);
902 throw std::domain_error(std::format(
"Can not evaluate {}.values()", repr(*
this)));
910 if (
hilet *
m = get_if<map_type>(*
this)) {
919 throw std::domain_error(std::format(
"Can not evaluate {}.items()", repr(*
this)));
923 constexpr void push_back(
datum const& rhs)
925 if (
auto *v = get_if<vector_type>(*
this)) {
926 return v->push_back(rhs);
928 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
932 constexpr void push_back(datum&& rhs)
934 if (
auto *v = get_if<vector_type>(*
this)) {
937 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
941 template<
typename Arg>
942 constexpr void push_back(Arg&& arg)
944 push_back(datum{std::forward<Arg>(arg)});
947 constexpr void pop_back()
949 if (
auto *v = get_if<vector_type>(*
this)) {
953 return v->pop_back();
955 throw std::domain_error(std::format(
"Can not evaluate {}.pop_back()", repr(*
this)));
959 [[nodiscard]]
constexpr bool contains(datum
const& rhs)
const
961 if (
auto *m = get_if<map_type>(*
this)) {
962 return m->contains(rhs);
964 throw std::domain_error(std::format(
"Can not evaluate {}.contains({})", repr(*
this), repr(rhs)));
968 template<
typename Arg>
969 [[nodiscard]]
constexpr bool contains(Arg
const& arg)
const
971 return contains(datum{arg});
977 find(path.cbegin(), path.cend(), r);
984 const_cast<datum *
>(
this)->
find(path.cbegin(), path.cend(), tmp);
1000 return to_bool(remove(path.cbegin(), path.cend()));
1011 return find_one(path.cbegin(), path.cend(),
false);
1022 return find_one(path.cbegin(), path.cend(),
true);
1033 return const_cast<datum *
>(
this)->find_one(path.cbegin(), path.cend(),
false);
1036 [[nodiscard]]
datum const& operator[](
datum const& rhs)
const
1038 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1039 hilet& v = get<vector_type>(*
this);
1041 auto index = get<long long>(rhs);
1043 index = ssize(v) + index;
1045 if (index < 0 or index >= ssize(v)) {
1051 }
else if (holds_alternative<map_type>(*
this)) {
1052 hilet&
m = get<map_type>(*
this);
1054 if (it ==
m.end()) {
1061 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1065 [[nodiscard]]
constexpr datum& operator[](datum
const& rhs)
1067 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1068 auto& v = get<vector_type>(*
this);
1070 auto index = get<long long>(rhs);
1072 index = ssize(v) + index;
1074 if (index < 0 or index >= ssize(v)) {
1080 }
else if (holds_alternative<map_type>(*
this)) {
1081 auto&
m = get<map_type>(*
this);
1085 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1089 [[nodiscard]]
constexpr datum
const& operator[](
auto const& rhs)
const
1091 return (*
this)[datum{rhs}];
1094 [[nodiscard]]
constexpr datum& operator[](
auto const& rhs)
1096 return (*
this)[datum{rhs}];
1099 [[nodiscard]]
constexpr datum& operator++()
1101 if (holds_alternative<long long>(*
this)) {
1102 ++_value._long_long;
1109 [[nodiscard]]
constexpr datum& operator--()
1111 if (holds_alternative<long long>(*
this)) {
1112 --_value._long_long;
1119 [[nodiscard]]
constexpr datum operator++(
int)
1121 if (holds_alternative<long long>(*
this)) {
1123 _value._long_long++;
1129 [[nodiscard]]
constexpr datum operator--(
int)
1131 if (holds_alternative<long long>(*
this)) {
1133 _value._long_long--;
1140 constexpr datum& operator+=(
auto const& rhs)
1142 if (holds_alternative<vector_type>(*
this)) {
1146 return (*
this) = (*this) + rhs;
1150#define X(op, inner_op) \
1151 constexpr datum& operator op(auto const& rhs) \
1153 return (*this) = (*this)inner_op rhs; \
1167 [[nodiscard]]
friend constexpr bool operator==(datum
const& lhs, datum
const& rhs)
noexcept
1169 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1170 return doubles.lhs() == doubles.rhs();
1172 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1173 return decimals.lhs() == decimals.rhs();
1175 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1176 return long_longs.lhs() == long_longs.rhs();
1178 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1179 return bools.lhs() == bools.rhs();
1181 }
else if (
hilet ymds = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1182 return ymds.lhs() == ymds.rhs();
1184 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1185 return strings.lhs() == strings.rhs();
1187 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1188 return vectors.lhs() == vectors.rhs();
1190 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1191 return maps.lhs() == maps.rhs();
1194 return lhs._tag == rhs._tag;
1226 [[nodiscard]]
friend constexpr std::partial_ordering operator<=>(datum
const& lhs, datum
const& rhs)
noexcept
1228 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1229 return doubles.lhs() <=> doubles.rhs();
1231 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1232 return decimals.lhs() <=> decimals.rhs();
1234 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1235 return long_longs.lhs() <=> long_longs.rhs();
1237 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1238 return bools.lhs() <=> bools.rhs();
1240 }
else if (
hilet year_month_days = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1241 return year_month_days.lhs() <=> year_month_days.rhs();
1243 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1244 return strings.lhs() <=> strings.rhs();
1246 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1247 return vectors.lhs() <=> vectors.rhs();
1249 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1250 return maps.lhs() <=> maps.rhs();
1252 }
else if (
hilet bstrings = promote_if<bstring>(lhs, rhs)) {
1253 return bstrings.lhs() <=> bstrings.rhs();
1256 return lhs._tag <=> rhs._tag;
1270 [[nodiscard]]
friend constexpr datum operator-(datum
const& rhs)
1272 if (
hilet rhs_double = get_if<double>(rhs)) {
1273 return datum{-*rhs_double};
1275 }
else if (
hilet rhs_decimal = get_if<decimal>(rhs)) {
1276 return datum{-*rhs_decimal};
1278 }
else if (
hilet rhs_long_long = get_if<long long>(rhs)) {
1279 return datum{-*rhs_long_long};
1295 [[nodiscard]]
friend constexpr datum operator~(datum
const& rhs)
1297 if (
hilet rhs_long_long = get_if<long long>(rhs)) {
1298 return datum{~*rhs_long_long};
1319 [[nodiscard]]
friend constexpr datum operator+(datum
const& lhs, datum
const& rhs)
1321 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1322 return datum{doubles.lhs() + doubles.rhs()};
1324 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1325 return datum{decimals.lhs() + decimals.rhs()};
1327 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1328 return datum{long_longs.lhs() + long_longs.rhs()};
1330 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1331 return datum{strings.lhs() + strings.rhs()};
1333 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1334 auto r = vectors.lhs();
1335 r.insert(r.end(), vectors.rhs().begin(), vectors.rhs().end());
1339 throw std::domain_error(std::format(
"Can not evaluate {} '+' {}", repr(lhs), repr(rhs)));
1354 [[nodiscard]]
friend constexpr datum operator-(datum
const& lhs, datum
const& rhs)
1356 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1357 return datum{doubles.lhs() - doubles.rhs()};
1359 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1360 return datum{decimals.lhs() - decimals.rhs()};
1362 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1363 return datum{long_longs.lhs() - long_longs.rhs()};
1366 throw std::domain_error(std::format(
"Can not evaluate {} '-' {}", repr(lhs), repr(rhs)));
1381 [[nodiscard]]
friend constexpr datum operator*(datum
const& lhs, datum
const& rhs)
1383 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1384 return datum{doubles.lhs() * doubles.rhs()};
1386 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1387 return datum{decimals.lhs() * decimals.rhs()};
1389 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1390 return datum{long_longs.lhs() * long_longs.rhs()};
1393 throw std::domain_error(std::format(
"Can not evaluate {} '*' {}", repr(lhs), repr(rhs)));
1408 [[nodiscard]]
friend constexpr datum operator/(datum
const& lhs, datum
const& rhs)
1410 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1411 if (doubles.rhs() == 0) {
1412 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1414 return datum{doubles.lhs() / doubles.rhs()};
1416 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1417 if (decimals.rhs() == 0) {
1418 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1420 return datum{decimals.lhs() / decimals.rhs()};
1422 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1423 if (long_longs.rhs() == 0) {
1424 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1426 return datum{long_longs.lhs() / long_longs.rhs()};
1429 throw std::domain_error(std::format(
"Can not evaluate {} '/' {}", repr(lhs), repr(rhs)));
1444 [[nodiscard]]
friend constexpr datum operator%(datum
const& lhs, datum
const& rhs)
1446 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1447 if (long_longs.rhs() == 0) {
1448 throw std::domain_error(std::format(
"Divide by zero {} '%' {}", repr(lhs), repr(rhs)));
1450 return datum{long_longs.lhs() % long_longs.rhs()};
1453 throw std::domain_error(std::format(
"Can not evaluate {} '%' {}", repr(lhs), repr(rhs)));
1467 [[nodiscard]]
friend constexpr datum
pow(datum
const& lhs, datum
const& rhs)
1469 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1470 return datum{
pow(doubles.lhs(), doubles.rhs())};
1472 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1473 return datum{
pow(long_longs.lhs(), long_longs.rhs())};
1476 throw std::domain_error(std::format(
"Can not evaluate pow({}, {})", repr(lhs), repr(rhs)));
1490 [[nodiscard]]
friend constexpr datum operator&(datum
const& lhs, datum
const& rhs)
1492 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1493 return datum{long_longs.lhs() & long_longs.rhs()};
1495 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1496 return datum{bools.lhs() and bools.rhs()};
1499 throw std::domain_error(std::format(
"Can not evaluate {} '&' {}", repr(lhs), repr(rhs)));
1513 [[nodiscard]]
friend constexpr datum operator|(datum
const& lhs, datum
const& rhs)
1515 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1516 return datum{long_longs.lhs() | long_longs.rhs()};
1518 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1519 return datum{bools.lhs() or bools.rhs()};
1522 throw std::domain_error(std::format(
"Can not evaluate {} '|' {}", repr(lhs), repr(rhs)));
1536 [[nodiscard]]
friend constexpr datum operator^(datum
const& lhs, datum
const& rhs)
1538 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1539 return datum{long_longs.lhs() ^ long_longs.rhs()};
1541 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1542 return datum{bools.lhs() != bools.rhs()};
1545 throw std::domain_error(std::format(
"Can not evaluate {} '^' {}", repr(lhs), repr(rhs)));
1561 [[nodiscard]]
friend constexpr datum operator<<(datum
const& lhs, datum
const& rhs)
1563 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1564 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1565 throw std::domain_error(std::format(
"Invalid shift count {} '<<' {}", repr(lhs), repr(rhs)));
1567 return datum{long_longs.lhs() << long_longs.rhs()};
1570 throw std::domain_error(std::format(
"Can not evaluate {} '<<' {}", repr(lhs), repr(rhs)));
1585 [[nodiscard]]
friend constexpr datum operator>>(datum
const& lhs, datum
const& rhs)
1587 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1588 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1589 throw std::domain_error(std::format(
"Invalid shift count {} '>>' {}", repr(lhs), repr(rhs)));
1591 return datum{long_longs.lhs() >> long_longs.rhs()};
1594 throw std::domain_error(std::format(
"Can not evaluate {} '>>' {}", repr(lhs), repr(rhs)));
1604 [[nodiscard]] friend constexpr auto operator op(datum const& lhs, auto const& rhs) \
1606 return lhs op datum{rhs}; \
1608 [[nodiscard]] friend constexpr auto operator op(auto const& lhs, datum const& rhs) \
1610 return datum{lhs} op rhs; \
1627 [[nodiscard]]
friend std::string repr(datum
const& rhs)
noexcept
1630 case tag_type::monostate:
1632 case tag_type::floating_point:
1633 return std::format(
"{:.1f}", rhs._value._double);
1634 case tag_type::decimal:
1636 case tag_type::integral:
1637 return std::format(
"{}", rhs._value._long_long);
1638 case tag_type::boolean:
1639 return rhs._value._bool ?
"true" :
"false";
1640 case tag_type::year_month_day:
1641 return std::format(
"{:%Y-%m-%d}", rhs._value._year_month_day);
1642 case tag_type::null:
1644 case tag_type::flow_break:
1646 case tag_type::flow_continue:
1648 case tag_type::string:
1649 return std::format(
"\"{}\"", *rhs._value._string);
1650 case tag_type::vector:
1653 for (
hilet& item : *rhs._value._vector) {
1663 for (
hilet& item : *rhs._value._map) {
1664 r += repr(item.first);
1666 r += repr(item.second);
1672 case tag_type::bstring:
1673 return base64::encode(*rhs._value._bstring);
1692 template<
typename T>
1695 if constexpr (std::is_same_v<T, double>) {
1696 return rhs._tag == tag_type::floating_point;
1697 }
else if constexpr (std::is_same_v<T, decimal>) {
1698 return rhs._tag == tag_type::decimal;
1699 }
else if constexpr (std::is_same_v<T, long long>) {
1700 return rhs._tag == tag_type::integral;
1701 }
else if constexpr (std::is_same_v<T, bool>) {
1702 return rhs._tag == tag_type::boolean;
1703 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1704 return rhs._tag == tag_type::year_month_day;
1705 }
else if constexpr (std::is_same_v<T, nullptr_t>) {
1706 return rhs._tag == tag_type::null;
1707 }
else if constexpr (std::is_same_v<T, std::monostate>) {
1708 return rhs._tag == tag_type::monostate;
1709 }
else if constexpr (std::is_same_v<T, break_type>) {
1710 return rhs._tag == tag_type::flow_break;
1711 }
else if constexpr (std::is_same_v<T, continue_type>) {
1712 return rhs._tag == tag_type::flow_continue;
1713 }
else if constexpr (std::is_same_v<T, std::string>) {
1714 return rhs._tag == tag_type::string;
1715 }
else if constexpr (std::is_same_v<T, vector_type>) {
1716 return rhs._tag == tag_type::vector;
1717 }
else if constexpr (std::is_same_v<T, map_type>) {
1718 return rhs._tag == tag_type::map;
1719 }
else if constexpr (std::is_same_v<T, bstring>) {
1720 return rhs._tag == tag_type::bstring;
1737 template<
typename To>
1740 if constexpr (std::is_same_v<To, double>) {
1741 return holds_alternative<double>(rhs) or holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or
1742 holds_alternative<bool>(rhs);
1743 }
else if constexpr (std::is_same_v<To, decimal>) {
1744 return holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1745 }
else if constexpr (std::is_same_v<To, long long>) {
1746 return holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1748 return holds_alternative<To>(rhs);
1760 template<
typename T>
1761 [[nodiscard]]
friend constexpr T
const&
get(
datum const& rhs)
noexcept
1763 hi_axiom(holds_alternative<T>(rhs));
1764 if constexpr (std::is_same_v<T, double>) {
1765 return rhs._value._double;
1766 }
else if constexpr (std::is_same_v<T, decimal>) {
1767 return rhs._value._decimal;
1768 }
else if constexpr (std::is_same_v<T, long long>) {
1769 return rhs._value._long_long;
1770 }
else if constexpr (std::is_same_v<T, bool>) {
1771 return rhs._value._bool;
1772 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1773 return rhs._value._year_month_day;
1774 }
else if constexpr (std::is_same_v<T, std::string>) {
1775 return *rhs._value._string;
1776 }
else if constexpr (std::is_same_v<T, vector_type>) {
1777 return *rhs._value._vector;
1778 }
else if constexpr (std::is_same_v<T, map_type>) {
1779 return *rhs._value._map;
1780 }
else if constexpr (std::is_same_v<T, bstring>) {
1781 return *rhs._value._bstring;
1795 template<
typename T>
1796 [[nodiscard]]
friend constexpr T&
get(
datum& rhs)
noexcept
1798 hi_axiom(holds_alternative<T>(rhs));
1799 if constexpr (std::is_same_v<T, double>) {
1800 return rhs._value._double;
1801 }
else if constexpr (std::is_same_v<T, decimal>) {
1802 return rhs._value._decimal;
1803 }
else if constexpr (std::is_same_v<T, long long>) {
1804 return rhs._value._long_long;
1805 }
else if constexpr (std::is_same_v<T, bool>) {
1806 return rhs._value._bool;
1807 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1808 return rhs._value._year_month_day;
1809 }
else if constexpr (std::is_same_v<T, std::string>) {
1810 return *rhs._value._string;
1811 }
else if constexpr (std::is_same_v<T, vector_type>) {
1812 return *rhs._value._vector;
1813 }
else if constexpr (std::is_same_v<T, map_type>) {
1814 return *rhs._value._map;
1815 }
else if constexpr (std::is_same_v<T, bstring>) {
1816 return *rhs._value._bstring;
1830 template<
typename T>
1833 if (holds_alternative<T>(rhs)) {
1834 return &get<T>(rhs);
1848 template<
typename T>
1849 [[nodiscard]]
friend constexpr T
const *
get_if(
datum const& rhs)
noexcept
1851 if (holds_alternative<T>(rhs)) {
1852 return &get<T>(rhs);
1867 template<
typename T>
1870 if (
auto *value = rhs.find_one(path)) {
1871 if (holds_alternative<T>(*value)) {
1872 return &get<T>(*value);
1890 template<
typename T>
1893 if (
auto *value =
const_cast<datum&
>(rhs).find_one(path)) {
1894 if (holds_alternative<T>(*value)) {
1895 return &get<T>(*value);
1905 enum class tag_type :
signed char {
1924 tag_type _tag = tag_type::monostate;
1927 long long _long_long;
1930 std::chrono::year_month_day _year_month_day;
1932 vector_type *_vector;
1936 constexpr value_type(numeric_integral
auto value) noexcept : _long_long(narrow_cast<long long>(value)) {}
1937 constexpr value_type(std::floating_point
auto value) noexcept : _double(narrow_cast<double>(value)) {}
1938 constexpr value_type(decimal value) noexcept : _decimal(value) {}
1939 constexpr value_type(
bool value) noexcept : _bool(value) {}
1940 constexpr value_type(std::chrono::year_month_day value) noexcept : _year_month_day(value) {}
1941 constexpr value_type(
std::string *value) noexcept : _string(value) {}
1942 constexpr value_type(vector_type *value) noexcept : _vector(value) {}
1943 constexpr value_type(map_type *value) noexcept : _map(value) {}
1944 constexpr value_type(bstring *value) noexcept : _bstring(value) {}
1949 [[nodiscard]]
constexpr bool is_scalar() const noexcept
1951 return to_underlying(_tag) >= 0;
1954 [[nodiscard]]
constexpr bool is_pointer() const noexcept
1956 return to_underlying(_tag) < 0;
1959 hi_no_inline
void copy_pointer(datum
const& other)
noexcept
1962 switch (
other._tag) {
1963 case tag_type::string:
1966 case tag_type::vector:
1967 _value._vector =
new vector_type{*
other._value._vector};
1970 _value._map =
new map_type{*
other._value._map};
1972 case tag_type::bstring:
1973 _value._bstring =
new bstring{*
other._value._bstring};
1980 hi_no_inline
void _delete_pointer() noexcept
1984 case tag_type::string:
1985 delete _value._string;
1987 case tag_type::vector:
1988 delete _value._vector;
1993 case tag_type::bstring:
1994 delete _value._bstring;
2001 constexpr void delete_pointer() noexcept
2008 void find_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *>& r)
noexcept
2010 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2011 for (
auto& item : *vector) {
2012 item.find(it + 1, it_end, r);
2015 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2016 for (
auto& item : *map) {
2017 item.second.find(it + 1, it_end, r);
2022 void find_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *>& r)
noexcept
2024 this->
find(it + 1, it_end, r);
2026 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2027 for (
auto& item : *vector) {
2028 item.find(it, it_end, r);
2031 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2032 for (
auto& item : *map) {
2033 item.second.find(it, it_end, r);
2039 jsonpath_indices
const& indices,
2040 jsonpath::const_iterator it,
2041 jsonpath::const_iterator it_end,
2044 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2045 for (
hilet index : indices.filter(ssize(*vector))) {
2046 (*vector)[index].find(it + 1, it_end, r);
2052 jsonpath_names
const& names,
2053 jsonpath::const_iterator it,
2054 jsonpath::const_iterator it_end,
2057 if (
auto map = get_if<datum::map_type>(*
this)) {
2058 for (
hilet& name : names) {
2059 hilet name_ = datum{name};
2060 auto jt = map->find(name_);
2061 if (jt != map->cend()) {
2062 jt->second.find(it + 1, it_end, r);
2069 jsonpath_slice
const& slice,
2070 jsonpath::const_iterator it,
2071 jsonpath::const_iterator it_end,
2074 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2075 hilet first = slice.begin(vector->size());
2076 hilet last = slice.end(vector->size());
2078 for (
auto index = first; index != last; index += slice.step) {
2079 if (index >= 0 and index < vector->size()) {
2080 (*this)[index].find(it + 1, it_end, r);
2091 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2092 find(it + 1, it_end, r);
2094 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2095 find(it + 1, it_end, r);
2097 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2098 find_wildcard(it, it_end, r);
2100 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2101 find_descend(it, it_end, r);
2103 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2104 find_indices(*indices, it, it_end, r);
2106 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2107 find_names(*names, it, it_end, r);
2109 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2110 find_slice(*slice, it, it_end, r);
2117 [[nodiscard]]
int remove_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2121 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2122 auto jt = vector->begin();
2123 while (jt != vector->end()) {
2124 hilet match = jt->remove(it + 1, it_end);
2128 jt = vector->erase(jt);
2133 return vector->empty() ? 2 : r;
2135 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2136 auto jt = map->begin();
2137 while (jt != map->end()) {
2138 hilet match = jt->second.remove(it + 1, it_end);
2142 jt = map->erase(jt);
2147 return map->empty() ? 2 : r;
2154 [[nodiscard]]
int remove_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2166 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2167 auto jt = vector->begin();
2168 while (jt != vector->end()) {
2169 hilet match = jt->remove(it, it_end);
2173 jt = vector->erase(jt);
2178 return vector->empty() ? 2 : r;
2180 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2181 auto jt = map->begin();
2182 while (jt != map->end()) {
2183 hilet match = jt->second.remove(it, it_end);
2187 jt = map->erase(jt);
2192 return map->empty() ? 2 : r;
2200 remove_indices(jsonpath_indices
const& indices, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2202 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2206 for (
hilet index : indices.filter(ssize(*vector))) {
2207 hilet match = (*vector)[index - offset].remove(it + 1, it_end);
2210 vector->erase(vector->begin() + (index - offset));
2215 return vector->empty() ? 2 : r;
2223 remove_names(jsonpath_names
const& names, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2225 if (
auto map = get_if<datum::map_type>(*
this)) {
2228 for (
hilet& name : names) {
2229 hilet name_ = datum{name};
2230 auto jt = map->find(name_);
2231 if (jt != map->cend()) {
2232 hilet match = jt->second.remove(it + 1, it_end);
2240 return map->empty() ? 2 : r;
2248 remove_slice(jsonpath_slice
const& slice, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2250 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2253 hilet first = slice.begin(vector->size());
2254 hilet last = slice.end(vector->size());
2257 for (
auto index = first; index != last; index += slice.step) {
2258 if (index >= 0 and index < vector->size()) {
2259 hilet match = (*this)[index - offset].remove(it + 1, it_end);
2263 vector->erase(vector->begin() + (index - offset));
2269 return vector->empty() ? 2 : r;
2276 [[nodiscard]]
int remove(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2282 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2283 return remove(it + 1, it_end);
2285 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2286 return remove(it + 1, it_end);
2288 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2289 return remove_wildcard(it, it_end);
2291 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2292 return remove_descend(it, it_end);
2294 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2295 return remove_indices(*indices, it, it_end);
2297 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2298 return remove_names(*names, it, it_end);
2300 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2301 return remove_slice(*slice, it, it_end);
2308 [[nodiscard]] datum *
2309 find_one_name(datum
const& name, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2311 hi_axiom(holds_alternative<std::string>(name));
2313 if (
auto *map = get_if<map_type>(*
this)) {
2314 auto i = map->find(name);
2315 if (i != map->end()) {
2316 return i->second.find_one(it + 1, it_end, create);
2318 }
else if (create) {
2319 (*map)[name] = datum{std::monostate{}};
2320 return find_one_name(name, it, it_end, create);
2326 }
else if (holds_alternative<std::monostate>(*
this) and create) {
2327 *
this = datum::make_map(name, std::monostate{});
2328 return find_one_name(name, it, it_end, create);
2335 [[nodiscard]] datum *
2336 find_one_index(
std::size_t index, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2338 if (
auto *vector = get_if<vector_type>(*
this)) {
2339 if (index < vector->size()) {
2340 return (*vector)[index].find_one(it + 1, it_end, create);
2341 }
else if (index == vector->size() and create) {
2342 vector->push_back(datum{std::monostate{}});
2343 return find_one_index(index, it, it_end, create);
2348 }
else if (holds_alternative<std::monostate>(*
this) and index == 0 and create) {
2349 *
this = datum::make_vector(std::monostate{});
2350 return find_one_index(index, it, it_end, create);
2357 [[nodiscard]] datum *find_one(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2362 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2363 return find_one(it + 1, it_end, create);
2365 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2366 return find_one(it + 1, it_end, create);
2368 }
else if (
hilet *indices = std::get_if<jsonpath_indices>(&*it)) {
2370 return find_one_index(indices->front(), it, it_end, create);
2372 }
else if (
hilet *names = std::get_if<jsonpath_names>(&*it)) {
2374 return find_one_name(datum{names->front()}, it, it_end,
create);