218 constexpr ~datum() noexcept
223 constexpr datum(
datum const &other) noexcept : _tag(other._tag), _value(other._value)
225 if (other.is_pointer()) {
230 constexpr datum(datum &&other) noexcept : _tag(other._tag), _value(other._value)
232 other._tag = tag_type::monostate;
233 other._value._long_long = 0;
236 constexpr datum() noexcept : _tag(tag_type::monostate), _value(0) {}
237 constexpr explicit datum(std::monostate) noexcept : _tag(tag_type::monostate), _value(0) {}
238 constexpr explicit datum(nullptr_t) noexcept : _tag(tag_type::null), _value(0) {}
239 constexpr explicit datum(continue_type) noexcept : _tag(tag_type::flow_continue), _value(0) {}
240 constexpr explicit datum(break_type) noexcept : _tag(tag_type::flow_break), _value(0) {}
241 constexpr explicit datum(
bool value) noexcept : _tag(tag_type::boolean), _value(value) {}
242 constexpr explicit datum(std::floating_point
auto value) noexcept :
243 _tag(tag_type::floating_point), _value(
static_cast<double>(value))
247 constexpr explicit datum(numeric_integral
auto value) noexcept :
248 _tag(tag_type::integral), _value(
static_cast<long long>(value))
252 constexpr explicit datum(decimal value) noexcept : _tag(tag_type::decimal), _value(value) {}
253 constexpr explicit datum(std::chrono::year_month_day value) noexcept : _tag(tag_type::year_month_day), _value(value) {}
255 explicit datum(std::string_view value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
256 explicit datum(
char const *value) noexcept : _tag(tag_type::string), _value(
new std::string{value}) {}
257 explicit datum(vector_type value) noexcept : _tag(tag_type::vector), _value(
new vector_type{
std::move(value)}) {}
258 explicit datum(map_type value) noexcept : _tag(tag_type::map), _value(
new map_type{
std::move(value)}) {}
259 explicit datum(URL value) noexcept : _tag(tag_type::url), _value(
new URL{
std::move(value)}) {}
260 explicit datum(bstring value) noexcept : _tag(tag_type::bstring), _value(
new bstring{
std::move(value)}) {}
262 template<
typename... Args>
263 [[nodiscard]]
static datum make_vector(Args
const &...args)
noexcept
265 return datum{vector_type{datum{args}...}};
268 template<
typename Key,
typename Value,
typename... Args>
269 [[nodiscard]]
static void populate_map(map_type &r, Key
const &key, Value
const &value, Args
const &...args)
noexcept
272 if constexpr (
sizeof...(Args) > 0) {
273 populate_map(r, args...);
277 template<
typename... Args>
278 [[nodiscard]]
static datum make_map(Args
const &...args)
noexcept
280 static_assert(
sizeof...(Args) % 2 == 0,
"Expect key value pairs for the arguments of make_map()");
283 if constexpr (
sizeof...(Args) > 0) {
284 populate_map(r, args...);
289 [[nodiscard]]
static datum make_break() noexcept
291 return datum{break_type{}};
294 [[nodiscard]]
static datum make_continue() noexcept
296 return datum{continue_type{}};
299 constexpr datum &operator=(datum
const &other)
noexcept
301 hi_return_on_self_assignment(other);
305 _value = other._value;
306 if (other.is_pointer()) {
312 constexpr datum &operator=(datum &&other)
noexcept
319 constexpr datum &operator=(std::floating_point
auto value)
noexcept(
sizeof(value) <= 4)
322 _tag = tag_type::floating_point;
323 _value =
static_cast<double>(value);
327 constexpr datum &operator=(numeric_integral
auto value)
noexcept(
sizeof(value) <= 4)
330 _tag = tag_type::integral;
331 _value =
static_cast<long long>(value);
335 constexpr datum &operator=(decimal value)
338 _tag = tag_type::decimal;
342 constexpr datum &operator=(
bool value)
noexcept
345 _tag = tag_type::boolean;
350 constexpr datum &operator=(std::chrono::year_month_day value)
noexcept
353 _tag = tag_type::year_month_day;
358 constexpr datum &operator=(std::monostate)
noexcept
361 _tag = tag_type::monostate;
366 constexpr datum &operator=(nullptr_t)
noexcept
369 _tag = tag_type::null;
377 _tag = tag_type::string;
382 datum &operator=(
char const *value)
noexcept
385 _tag = tag_type::string;
390 datum &operator=(std::string_view value)
noexcept
393 _tag = tag_type::string;
398 datum &operator=(vector_type value)
noexcept
401 _tag = tag_type::vector;
402 _value =
new vector_type{
std::move(value)};
406 datum &operator=(map_type value)
noexcept
409 _tag = tag_type::map;
414 datum &operator=(URL value)
noexcept
417 _tag = tag_type::url;
422 datum &operator=(bstring value)
noexcept
425 _tag = tag_type::bstring;
430 constexpr explicit operator bool() const noexcept
433 case tag_type::floating_point:
return static_cast<bool>(get<double>(*
this));
434 case tag_type::decimal:
return static_cast<bool>(get<decimal>(*
this));
435 case tag_type::boolean:
return get<bool>(*
this);
436 case tag_type::integral:
return static_cast<bool>(get<long long>(*
this));
437 case tag_type::year_month_day:
return true;
438 case tag_type::string:
return not get<std::string>(*this).empty();
439 case tag_type::vector:
return not get<vector_type>(*this).empty();
440 case tag_type::map:
return not get<map_type>(*this).empty();
441 case tag_type::url:
return not get<URL>(*this).empty();
442 case tag_type::bstring:
return not get<bstring>(*this).empty();
443 default:
return false;
447 [[nodiscard]]
constexpr bool empty()
const
450 case tag_type::string:
return get<std::string>(*this).empty();
451 case tag_type::vector:
return get<vector_type>(*this).empty();
452 case tag_type::map:
return get<map_type>(*this).empty();
453 case tag_type::url:
return get<URL>(*this).empty();
454 case tag_type::bstring:
return get<bstring>(*this).empty();
455 default:
throw std::domain_error(std::format(
"Type {} can not be checked for empty", *
this));
459 template<std::
floating_po
int T>
460 constexpr explicit operator T()
const
463 case tag_type::floating_point:
return static_cast<T
>(get<double>(*
this));
464 case tag_type::integral:
return static_cast<T
>(get<long long>(*
this));
465 case tag_type::decimal:
return static_cast<T
>(get<decimal>(*
this));
466 case tag_type::boolean:
return static_cast<T
>(get<bool>(*
this));
467 default:
throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
471 constexpr explicit operator decimal()
const
474 case tag_type::floating_point:
return decimal(get<double>(*
this));
475 case tag_type::integral:
return decimal(get<long long>(*
this));
476 case tag_type::decimal:
return get<decimal>(*
this);
477 case tag_type::boolean:
return decimal(get<bool>(*
this));
478 default:
throw std::domain_error(std::format(
"Can't convert {} to floating point", *
this));
482 template<numeric_
integral T>
483 constexpr explicit operator T()
const
485 if (
auto f = get_if<double>(*
this)) {
491 return static_cast<T
>(r);
493 }
else if (
auto i = get_if<long long>(*
this)) {
497 return static_cast<T
>(*i);
499 }
else if (
auto d = get_if<decimal>(*
this)) {
500 auto r =
static_cast<long long>(*d);
504 return static_cast<T
>(r);
506 }
else if (
auto b = get_if<bool>(*
this)) {
507 return static_cast<T
>(*b);
510 throw std::domain_error(std::format(
"Can't convert {} to an integral", repr(*
this)));
514 constexpr explicit operator std::chrono::year_month_day()
const
516 if (
auto ymd = get_if<std::chrono::year_month_day>(*
this)) {
519 throw std::domain_error(std::format(
"Can't convert {} to an std::chrono::year_month_day", repr(*
this)));
526 case tag_type::monostate:
return "undefined";
527 case tag_type::floating_point:
return hi::to_string(_value._double);
528 case tag_type::decimal:
return to_string(_value._decimal);
529 case tag_type::integral:
return to_string(_value._long_long);
530 case tag_type::boolean:
return _value._bool ?
"true" :
"false";
531 case tag_type::year_month_day:
return std::format(
"{:%Y-%m-%d}", _value._year_month_day);
532 case tag_type::null:
return "null";
533 case tag_type::flow_break:
return "break";
534 case tag_type::flow_continue:
return "continue";
535 case tag_type::string:
return *_value._string;
536 case tag_type::url:
return to_string(*_value._url);
537 case tag_type::vector: {
539 for (
hilet &item : *_value._vector) {
546 case tag_type::map: {
548 for (
hilet &item : *_value._map) {
549 r += repr(item.first);
551 r += repr(item.second);
557 case tag_type::bstring:
return base64::encode(*_value._bstring);
558 default: hi_no_default();
562 explicit operator std::string_view()
const
564 if (
auto s = get_if<std::string>(*
this)) {
565 return std::string_view{*s};
566 }
else if (
auto u = get_if<URL>(*
this)) {
569 throw std::domain_error(std::format(
"Can't convert {} to an std::string_view", repr(*
this)));
573 explicit operator vector_type()
const
575 if (
auto v = get_if<vector_type>(*
this)) {
578 throw std::domain_error(std::format(
"Can't convert {} to an vector", repr(*
this)));
582 explicit operator map_type()
const
584 if (
auto m = get_if<map_type>(*
this)) {
591 explicit operator URL()
const
593 if (
auto u = get_if<URL>(*
this)) {
595 }
else if (
auto s = get_if<std::string>(*
this)) {
602 explicit operator bstring()
const
605 if (_tag != tag_type::bstring) {
606 throw std::domain_error(std::format(
"Can't convert {} to an bstring", repr(*
this)));
608 return get<bstring>(*
this);
611 [[nodiscard]]
constexpr char const *type_name() const noexcept
614 case tag_type::floating_point:
return "float";
615 case tag_type::decimal:
return "decimal";
616 case tag_type::integral:
return "int";
617 case tag_type::boolean:
return "bool";
618 case tag_type::year_month_day:
return "date";
619 case tag_type::string:
return "string";
620 case tag_type::url:
return "url";
621 case tag_type::vector:
return "vector";
622 case tag_type::map:
return "map";
623 case tag_type::bstring:
return "bytes";
624 default: hi_no_default();
632 return _tag == tag_type::monostate;
638 [[nodiscard]]
constexpr bool is_break() const noexcept
640 return _tag == tag_type::flow_break;
648 return _tag == tag_type::flow_continue;
651 [[nodiscard]]
constexpr std::size_t hash() const noexcept
658 case tag_type::year_month_day: {
660 r |=
static_cast<uint32_t
>(
static_cast<int>(_value._year_month_day.year())) << 16;
661 r |=
static_cast<uint32_t
>(
static_cast<unsigned>(_value._year_month_day.month())) << 8;
662 r |=
static_cast<uint32_t
>(
static_cast<unsigned>(_value._year_month_day.day()));
666 case tag_type::vector: {
668 for (
hilet &v : *_value._vector) {
669 r = hash_mix(r, v.hash());
673 case tag_type::map: {
675 for (
hilet &kv : *_value._map) {
676 r = hash_mix(r, kv.first.hash(), kv.second.hash());
682 default: hi_no_default();
688 if (
hilet *s = get_if<std::string>(*
this)) {
690 }
else if (
hilet *v = get_if<vector_type>(*
this)) {
692 }
else if (
hilet *m = get_if<map_type>(*
this)) {
694 }
else if (
hilet *b = get_if<bstring>(*
this)) {
701 [[nodiscard]]
constexpr friend std::size_t size(datum
const &rhs)
706 [[nodiscard]]
constexpr datum
const &back()
const
708 if (
hilet *v = get_if<vector_type>(*
this)) {
718 [[nodiscard]]
constexpr datum &back()
720 if (
auto *v = get_if<vector_type>(*
this)) {
730 [[nodiscard]]
constexpr datum
const &front()
const
732 if (
hilet *v = get_if<vector_type>(*
this)) {
738 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
742 [[nodiscard]]
constexpr datum &front()
744 if (
auto *v = get_if<vector_type>(*
this)) {
750 throw std::domain_error(std::format(
"Can not evaluate {}.front()", repr(*
this)));
754 [[nodiscard]]
constexpr auto cbegin()
const
756 if (
hilet *v = get_if<vector_type>(*
this)) {
759 throw std::domain_error(std::format(
"Can not evaluate {}.cbegin()", repr(*
this)));
763 [[nodiscard]]
constexpr auto begin()
const
765 if (
hilet *v = get_if<vector_type>(*
this)) {
768 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
772 [[nodiscard]]
constexpr auto begin()
774 if (
hilet *v = get_if<vector_type>(*
this)) {
777 throw std::domain_error(std::format(
"Can not evaluate {}.begin()", repr(*
this)));
781 [[nodiscard]]
constexpr auto cend()
const
783 if (
hilet *v = get_if<vector_type>(*
this)) {
790 [[nodiscard]]
constexpr auto end()
const
792 if (
hilet *v = get_if<vector_type>(*
this)) {
799 [[nodiscard]]
constexpr auto end()
801 if (
hilet *v = get_if<vector_type>(*
this)) {
812 if (
hilet *m = get_if<map_type>(*
this)) {
815 for (
hilet &kv : *m) {
816 r.push_back(kv.first);
828 if (
hilet *m = get_if<map_type>(*
this)) {
831 for (
hilet &kv : *m) {
832 r.push_back(kv.second);
836 throw std::domain_error(std::format(
"Can not evaluate {}.values()", repr(*
this)));
844 if (
hilet *m = get_if<map_type>(*
this)) {
848 for (
hilet &item : *m) {
849 r.push_back(make_vector(item.first, item.second));
853 throw std::domain_error(std::format(
"Can not evaluate {}.items()", repr(*
this)));
857 constexpr void push_back(
datum const &rhs)
859 if (
auto *v = get_if<vector_type>(*
this)) {
860 return v->push_back(rhs);
862 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
866 constexpr void push_back(datum &&rhs)
868 if (
auto *v = get_if<vector_type>(*
this)) {
871 throw std::domain_error(std::format(
"Can not evaluate {}.push_back({})", repr(*
this), repr(rhs)));
875 template<
typename Arg>
876 constexpr void push_back(Arg &&arg)
878 push_back(datum{std::forward<Arg>(arg)});
881 constexpr void pop_back()
883 if (
auto *v = get_if<vector_type>(*
this)) {
887 return v->pop_back();
889 throw std::domain_error(std::format(
"Can not evaluate {}.pop_back()", repr(*
this)));
893 [[nodiscard]]
constexpr bool contains(datum
const &rhs)
const
895 if (
auto *m = get_if<map_type>(*
this)) {
896 return m->contains(rhs);
898 throw std::domain_error(std::format(
"Can not evaluate {}.contains({})", repr(*
this), repr(rhs)));
902 template<
typename Arg>
903 [[nodiscard]]
constexpr bool contains(Arg
const &arg)
const
905 return contains(datum{arg});
911 find(path.cbegin(), path.cend(), r);
918 const_cast<datum *
>(
this)->
find(path.cbegin(), path.cend(), tmp);
934 return static_cast<bool>(remove(path.cbegin(), path.cend()));
944 hi_axiom(path.is_singular());
945 return find_one(path.cbegin(), path.cend(),
false);
955 hi_axiom(path.is_singular());
956 return find_one(path.cbegin(), path.cend(),
true);
966 hi_axiom(path.is_singular());
967 return const_cast<datum *
>(
this)->find_one(path.cbegin(), path.cend(),
false);
970 [[nodiscard]]
constexpr datum const &operator[](
datum const &rhs)
const
972 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
973 hilet &v = get<vector_type>(*
this);
975 auto index = get<long long>(rhs);
977 index = ssize(v) + index;
979 if (index < 0 or index >= ssize(v)) {
985 }
else if (holds_alternative<map_type>(*
this)) {
986 hilet &m = get<map_type>(*
this);
987 hilet it = m.find(rhs);
995 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
999 [[nodiscard]]
constexpr datum &operator[](datum
const &rhs)
1001 if (holds_alternative<vector_type>(*
this) and holds_alternative<long long>(rhs)) {
1002 auto &v = get<vector_type>(*
this);
1004 auto index = get<long long>(rhs);
1006 index = ssize(v) + index;
1008 if (index < 0 or index >= ssize(v)) {
1014 }
else if (holds_alternative<map_type>(*
this)) {
1015 auto &m = get<map_type>(*
this);
1019 throw std::domain_error(std::format(
"Can not evaluate {}[{}]", repr(*
this), repr(rhs)));
1023 [[nodiscard]]
constexpr datum
const &operator[](
auto const &rhs)
const
1025 return (*
this)[datum{rhs}];
1028 [[nodiscard]]
constexpr datum &operator[](
auto const &rhs)
1030 return (*
this)[datum{rhs}];
1033 [[nodiscard]]
constexpr datum &operator++()
1035 if (holds_alternative<long long>(*
this)) {
1036 ++_value._long_long;
1043 [[nodiscard]]
constexpr datum &operator--()
1045 if (holds_alternative<long long>(*
this)) {
1046 --_value._long_long;
1053 [[nodiscard]]
constexpr datum operator++(
int)
1055 if (holds_alternative<long long>(*
this)) {
1057 _value._long_long++;
1063 [[nodiscard]]
constexpr datum operator--(
int)
1065 if (holds_alternative<long long>(*
this)) {
1067 _value._long_long--;
1074 constexpr datum &operator+=(
auto const &rhs)
1076 if (holds_alternative<vector_type>(*
this)) {
1080 return (*
this) = (*this) + rhs;
1084#define X(op, inner_op) \
1085 constexpr datum &operator op(auto const &rhs) \
1087 return (*this) = (*this)inner_op rhs; \
1101 [[nodiscard]]
friend constexpr bool operator==(datum
const &lhs, datum
const &rhs)
noexcept
1103 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1104 return doubles.lhs() == doubles.rhs();
1106 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1107 return decimals.lhs() == decimals.rhs();
1109 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1110 return long_longs.lhs() == long_longs.rhs();
1112 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1113 return bools.lhs() == bools.rhs();
1115 }
else if (
hilet ymds = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1116 return ymds.lhs() == ymds.rhs();
1118 }
else if (
hilet urls = promote_if<URL>(lhs, rhs)) {
1119 return urls.lhs() == urls.rhs();
1121 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1122 return strings.lhs() == strings.rhs();
1124 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1125 return vectors.lhs() == vectors.rhs();
1127 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1128 return maps.lhs() == maps.rhs();
1131 return lhs._tag == rhs._tag;
1165 [[nodiscard]]
friend constexpr std::partial_ordering operator<=>(datum
const &lhs, datum
const &rhs)
noexcept
1167 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1168 return doubles.lhs() <=> doubles.rhs();
1170 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1171 return decimals.lhs() <=> decimals.rhs();
1173 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1174 return long_longs.lhs() <=> long_longs.rhs();
1176 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1177 return bools.lhs() <=> bools.rhs();
1179 }
else if (
hilet year_month_days = promote_if<std::chrono::year_month_day>(lhs, rhs)) {
1180 return year_month_days.lhs() <=> year_month_days.rhs();
1182 }
else if (
hilet urls = promote_if<URL>(lhs, rhs)) {
1183 return urls.lhs() <=> urls.rhs();
1185 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1186 return strings.lhs() <=> strings.rhs();
1188 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1189 return vectors.lhs() <=> vectors.rhs();
1191 }
else if (
hilet maps = promote_if<map_type>(lhs, rhs)) {
1192 return maps.lhs() <=> maps.rhs();
1194 }
else if (
hilet bstrings = promote_if<bstring>(lhs, rhs)) {
1195 return bstrings.lhs() <=> bstrings.rhs();
1198 return lhs._tag <=> rhs._tag;
1212 [[nodiscard]]
friend constexpr datum operator-(datum
const &rhs)
1214 if (
hilet rhs_double = get_if<double>(rhs)) {
1215 return datum{-*rhs_double};
1217 }
else if (
hilet rhs_decimal = get_if<decimal>(rhs)) {
1218 return datum{-*rhs_decimal};
1220 }
else if (
hilet rhs_long_long = get_if<long long>(rhs)) {
1221 return datum{-*rhs_long_long};
1237 [[nodiscard]]
friend constexpr datum operator~(datum
const &rhs)
1239 if (
hilet rhs_long_long = get_if<long long>(rhs)) {
1240 return datum{~*rhs_long_long};
1261 [[nodiscard]]
friend constexpr datum operator+(datum
const &lhs, datum
const &rhs)
1263 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1264 return datum{doubles.lhs() + doubles.rhs()};
1266 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1267 return datum{decimals.lhs() + decimals.rhs()};
1269 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1270 return datum{long_longs.lhs() + long_longs.rhs()};
1272 }
else if (
hilet strings = promote_if<std::string>(lhs, rhs)) {
1273 return datum{strings.lhs() + strings.rhs()};
1275 }
else if (
hilet vectors = promote_if<vector_type>(lhs, rhs)) {
1276 auto r = vectors.lhs();
1277 r.insert(r.end(), vectors.rhs().begin(), vectors.rhs().end());
1281 throw std::domain_error(std::format(
"Can not evaluate {} '+' {}", repr(lhs), repr(rhs)));
1296 [[nodiscard]]
friend constexpr datum operator-(datum
const &lhs, datum
const &rhs)
1298 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1299 return datum{doubles.lhs() - doubles.rhs()};
1301 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1302 return datum{decimals.lhs() - decimals.rhs()};
1304 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1305 return datum{long_longs.lhs() - long_longs.rhs()};
1308 throw std::domain_error(std::format(
"Can not evaluate {} '-' {}", repr(lhs), repr(rhs)));
1323 [[nodiscard]]
friend constexpr datum operator*(datum
const &lhs, datum
const &rhs)
1325 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1326 return datum{doubles.lhs() * doubles.rhs()};
1328 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1329 return datum{decimals.lhs() * decimals.rhs()};
1331 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1332 return datum{long_longs.lhs() * long_longs.rhs()};
1335 throw std::domain_error(std::format(
"Can not evaluate {} '*' {}", repr(lhs), repr(rhs)));
1352 [[nodiscard]]
friend constexpr datum operator/(datum
const &lhs, datum
const &rhs)
1354 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1355 if (doubles.rhs() == 0) {
1356 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1358 return datum{doubles.lhs() / doubles.rhs()};
1360 }
else if (
hilet decimals = promote_if<decimal>(lhs, rhs)) {
1361 if (decimals.rhs() == 0) {
1362 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1364 return datum{decimals.lhs() / decimals.rhs()};
1366 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1367 if (long_longs.rhs() == 0) {
1368 throw std::domain_error(std::format(
"Divide by zero {} '/' {}", repr(lhs), repr(rhs)));
1370 return datum{long_longs.lhs() / long_longs.rhs()};
1372 }
else if (
hilet urls = promote_if<URL>(lhs, rhs)) {
1373 return datum{urls.lhs() / urls.rhs()};
1376 throw std::domain_error(std::format(
"Can not evaluate {} '/' {}", repr(lhs), repr(rhs)));
1391 [[nodiscard]]
friend constexpr datum operator%(datum
const &lhs, datum
const &rhs)
1393 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1394 if (long_longs.rhs() == 0) {
1395 throw std::domain_error(std::format(
"Divide by zero {} '%' {}", repr(lhs), repr(rhs)));
1397 return datum{long_longs.lhs() % long_longs.rhs()};
1400 throw std::domain_error(std::format(
"Can not evaluate {} '%' {}", repr(lhs), repr(rhs)));
1414 [[nodiscard]]
friend constexpr datum
pow(datum
const &lhs, datum
const &rhs)
1416 if (
hilet doubles = promote_if<double>(lhs, rhs)) {
1417 return datum{
pow(doubles.lhs(), doubles.rhs())};
1419 }
else if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1420 return datum{
pow(long_longs.lhs(), long_longs.rhs())};
1423 throw std::domain_error(std::format(
"Can not evaluate pow({}, {})", repr(lhs), repr(rhs)));
1437 [[nodiscard]]
friend constexpr datum operator&(datum
const &lhs, datum
const &rhs)
1439 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1440 return datum{long_longs.lhs() & long_longs.rhs()};
1442 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1443 return datum{bools.lhs() and bools.rhs()};
1446 throw std::domain_error(std::format(
"Can not evaluate {} '&' {}", repr(lhs), repr(rhs)));
1460 [[nodiscard]]
friend constexpr datum
operator|(datum
const &lhs, datum
const &rhs)
1462 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1463 return datum{long_longs.lhs() | long_longs.rhs()};
1465 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1466 return datum{bools.lhs() or bools.rhs()};
1469 throw std::domain_error(std::format(
"Can not evaluate {} '|' {}", repr(lhs), repr(rhs)));
1483 [[nodiscard]]
friend constexpr datum operator^(datum
const &lhs, datum
const &rhs)
1485 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1486 return datum{long_longs.lhs() ^ long_longs.rhs()};
1488 }
else if (
hilet bools = promote_if<bool>(lhs, rhs)) {
1489 return datum{bools.lhs() != bools.rhs()};
1492 throw std::domain_error(std::format(
"Can not evaluate {} '^' {}", repr(lhs), repr(rhs)));
1508 [[nodiscard]]
friend constexpr datum operator<<(datum
const &lhs, datum
const &rhs)
1510 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1511 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1512 throw std::domain_error(std::format(
"Invalid shift count {} '<<' {}", repr(lhs), repr(rhs)));
1514 return datum{long_longs.lhs() << long_longs.rhs()};
1517 throw std::domain_error(std::format(
"Can not evaluate {} '<<' {}", repr(lhs), repr(rhs)));
1532 [[nodiscard]]
friend constexpr datum operator>>(datum
const &lhs, datum
const &rhs)
1534 if (
hilet long_longs = promote_if<long long>(lhs, rhs)) {
1535 if (long_longs.rhs() < 0 or long_longs.rhs() > (
sizeof(
long long) * CHAR_BIT - 1)) {
1536 throw std::domain_error(std::format(
"Invalid shift count {} '>>' {}", repr(lhs), repr(rhs)));
1538 return datum{long_longs.lhs() >> long_longs.rhs()};
1541 throw std::domain_error(std::format(
"Can not evaluate {} '>>' {}", repr(lhs), repr(rhs)));
1551 [[nodiscard]] friend constexpr auto operator op(datum const &lhs, auto const &rhs) noexcept(noexcept(lhs op datum{rhs})) \
1553 return lhs op datum{rhs}; \
1555 [[nodiscard]] friend constexpr auto operator op(auto const &lhs, datum const &rhs) noexcept(noexcept(datum{lhs} op rhs)) \
1557 return datum{lhs} op rhs; \
1574 [[nodiscard]]
friend std::string repr(datum
const &rhs)
noexcept
1577 case tag_type::monostate:
return "undefined";
1578 case tag_type::floating_point:
return std::format(
"{:.1f}", rhs._value._double);
1579 case tag_type::decimal:
return to_string(rhs._value._decimal);
1580 case tag_type::integral:
return std::format(
"{}", rhs._value._long_long);
1581 case tag_type::boolean:
return rhs._value._bool ?
"true" :
"false";
1582 case tag_type::year_month_day:
return std::format(
"{:%Y-%m-%d}", rhs._value._year_month_day);
1583 case tag_type::null:
return "null";
1584 case tag_type::flow_break:
return "break";
1585 case tag_type::flow_continue:
return "continue";
1586 case tag_type::string:
return std::format(
"\"{}\"", *rhs._value._string);
1587 case tag_type::url:
return to_string(*rhs._value._url);
1588 case tag_type::vector: {
1590 for (
hilet &item : *rhs._value._vector) {
1597 case tag_type::map: {
1599 for (
hilet &item : *rhs._value._map) {
1600 r += repr(item.first);
1602 r += repr(item.second);
1608 case tag_type::bstring:
return base64::encode(*rhs._value._bstring);
1609 default: hi_no_default();
1626 template<
typename T>
1629 if constexpr (std::is_same_v<T, double>) {
1630 return rhs._tag == tag_type::floating_point;
1631 }
else if constexpr (std::is_same_v<T, decimal>) {
1632 return rhs._tag == tag_type::decimal;
1633 }
else if constexpr (std::is_same_v<T, long long>) {
1634 return rhs._tag == tag_type::integral;
1635 }
else if constexpr (std::is_same_v<T, bool>) {
1636 return rhs._tag == tag_type::boolean;
1637 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1638 return rhs._tag == tag_type::year_month_day;
1639 }
else if constexpr (std::is_same_v<T, nullptr_t>) {
1640 return rhs._tag == tag_type::null;
1641 }
else if constexpr (std::is_same_v<T, std::monostate>) {
1642 return rhs._tag == tag_type::monostate;
1643 }
else if constexpr (std::is_same_v<T, break_type>) {
1644 return rhs._tag == tag_type::flow_break;
1645 }
else if constexpr (std::is_same_v<T, continue_type>) {
1646 return rhs._tag == tag_type::flow_continue;
1647 }
else if constexpr (std::is_same_v<T, std::string>) {
1648 return rhs._tag == tag_type::string;
1649 }
else if constexpr (std::is_same_v<T, vector_type>) {
1650 return rhs._tag == tag_type::vector;
1651 }
else if constexpr (std::is_same_v<T, map_type>) {
1652 return rhs._tag == tag_type::map;
1653 }
else if constexpr (std::is_same_v<T, URL>) {
1654 return rhs._tag == tag_type::url;
1655 }
else if constexpr (std::is_same_v<T, bstring>) {
1656 return rhs._tag == tag_type::bstring;
1658 hi_static_no_default();
1675 template<
typename To>
1678 if constexpr (std::is_same_v<To, double>) {
1679 return holds_alternative<double>(rhs) or holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or
1680 holds_alternative<bool>(rhs);
1681 }
else if constexpr (std::is_same_v<To, decimal>) {
1682 return holds_alternative<decimal>(rhs) or holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1683 }
else if constexpr (std::is_same_v<To, long long>) {
1684 return holds_alternative<long long>(rhs) or holds_alternative<bool>(rhs);
1685 }
else if constexpr (std::is_same_v<To, std::string>) {
1686 return holds_alternative<URL>(rhs) or holds_alternative<std::string>(rhs);
1687 }
else if constexpr (std::is_same_v<To, URL>) {
1688 return holds_alternative<URL>(rhs) or holds_alternative<std::string>(rhs);
1690 return holds_alternative<To>(rhs);
1702 template<
typename T>
1703 [[nodiscard]]
friend constexpr T
const &
get(
datum const &rhs)
noexcept
1705 hi_axiom(holds_alternative<T>(rhs));
1706 if constexpr (std::is_same_v<T, double>) {
1707 return rhs._value._double;
1708 }
else if constexpr (std::is_same_v<T, decimal>) {
1709 return rhs._value._decimal;
1710 }
else if constexpr (std::is_same_v<T, long long>) {
1711 return rhs._value._long_long;
1712 }
else if constexpr (std::is_same_v<T, bool>) {
1713 return rhs._value._bool;
1714 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1715 return rhs._value._year_month_day;
1716 }
else if constexpr (std::is_same_v<T, std::string>) {
1717 return *rhs._value._string;
1718 }
else if constexpr (std::is_same_v<T, vector_type>) {
1719 return *rhs._value._vector;
1720 }
else if constexpr (std::is_same_v<T, map_type>) {
1721 return *rhs._value._map;
1722 }
else if constexpr (std::is_same_v<T, URL>) {
1723 return *rhs._value._url;
1724 }
else if constexpr (std::is_same_v<T, bstring>) {
1725 return *rhs._value._bstring;
1727 hi_static_no_default();
1739 template<
typename T>
1740 [[nodiscard]]
friend constexpr T &
get(
datum &rhs)
noexcept
1742 hi_axiom(holds_alternative<T>(rhs));
1743 if constexpr (std::is_same_v<T, double>) {
1744 return rhs._value._double;
1745 }
else if constexpr (std::is_same_v<T, decimal>) {
1746 return rhs._value._decimal;
1747 }
else if constexpr (std::is_same_v<T, long long>) {
1748 return rhs._value._long_long;
1749 }
else if constexpr (std::is_same_v<T, bool>) {
1750 return rhs._value._bool;
1751 }
else if constexpr (std::is_same_v<T, std::chrono::year_month_day>) {
1752 return rhs._value._year_month_day;
1753 }
else if constexpr (std::is_same_v<T, std::string>) {
1754 return *rhs._value._string;
1755 }
else if constexpr (std::is_same_v<T, vector_type>) {
1756 return *rhs._value._vector;
1757 }
else if constexpr (std::is_same_v<T, map_type>) {
1758 return *rhs._value._map;
1759 }
else if constexpr (std::is_same_v<T, URL>) {
1760 return *rhs._value._url;
1761 }
else if constexpr (std::is_same_v<T, bstring>) {
1762 return *rhs._value._bstring;
1764 hi_static_no_default();
1776 template<
typename T>
1779 if (holds_alternative<T>(rhs)) {
1780 return &get<T>(rhs);
1794 template<
typename T>
1795 [[nodiscard]]
friend constexpr T
const *
get_if(
datum const &rhs)
noexcept
1797 if (holds_alternative<T>(rhs)) {
1798 return &get<T>(rhs);
1813 template<
typename T>
1816 if (
auto *value = rhs.find_one(path)) {
1817 if (holds_alternative<T>(*value)) {
1818 return &get<T>(*value);
1836 template<
typename T>
1839 if (
auto *value =
const_cast<datum &
>(rhs).find_one(path)) {
1840 if (holds_alternative<T>(*value)) {
1841 return &get<T>(*value);
1856 template<
typename To>
1860 if (holds_alternative<To>(lhs) and holds_alternative<To>(rhs)) {
1861 r.set(get<To>(lhs), get<To>(rhs));
1863 }
else if (holds_alternative<To>(lhs) and promotable_to<To>(rhs)) {
1864 r.set(get<To>(lhs),
static_cast<To
>(rhs));
1866 }
else if (promotable_to<To>(lhs) and holds_alternative<To>(rhs)) {
1867 r.set(
static_cast<To
>(lhs), get<To>(rhs));
1874 enum class tag_type :
signed char {
1894 tag_type _tag = tag_type::monostate;
1897 long long _long_long;
1900 std::chrono::year_month_day _year_month_day;
1902 vector_type *_vector;
1907 constexpr value_type(numeric_integral
auto value) noexcept : _long_long(
static_cast<long long>(value)) {}
1908 constexpr value_type(std::floating_point
auto value) noexcept : _double(
static_cast<double>(value)) {}
1909 constexpr value_type(decimal value) noexcept : _decimal(value) {}
1910 constexpr value_type(
bool value) noexcept : _bool(value) {}
1911 constexpr value_type(std::chrono::year_month_day value) noexcept : _year_month_day(value) {}
1912 constexpr value_type(
std::string *value) noexcept : _string(value) {}
1913 constexpr value_type(vector_type *value) noexcept : _vector(value) {}
1914 constexpr value_type(map_type *value) noexcept : _map(value) {}
1915 constexpr value_type(URL *value) noexcept : _url(value) {}
1916 constexpr value_type(bstring *value) noexcept : _bstring(value) {}
1921 [[nodiscard]]
constexpr bool is_scalar() const noexcept
1923 return to_underlying(_tag) >= 0;
1926 [[nodiscard]]
constexpr bool is_pointer() const noexcept
1928 return to_underlying(_tag) < 0;
1931 hi_no_inline
void copy_pointer(datum
const &other)
noexcept
1933 hi_axiom(other.is_pointer());
1934 switch (other._tag) {
1935 case tag_type::string: _value._string =
new std::string{*other._value._string};
return;
1936 case tag_type::vector: _value._vector =
new vector_type{*other._value._vector};
return;
1937 case tag_type::map: _value._map =
new map_type{*other._value._map};
return;
1938 case tag_type::url: _value._url =
new URL{*other._value._url};
return;
1939 case tag_type::bstring: _value._bstring =
new bstring{*other._value._bstring};
return;
1940 default: hi_no_default();
1944 hi_no_inline
void _delete_pointer() noexcept
1946 hi_axiom(is_pointer());
1948 case tag_type::string:
delete _value._string;
return;
1949 case tag_type::vector:
delete _value._vector;
return;
1950 case tag_type::map:
delete _value._map;
return;
1951 case tag_type::url:
delete _value._url;
return;
1952 case tag_type::bstring:
delete _value._bstring;
return;
1953 default: hi_no_default();
1957 constexpr void delete_pointer() noexcept
1964 void find_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *> &r)
noexcept
1966 if (
auto vector = get_if<datum::vector_type>(*
this)) {
1967 for (
auto &item : *vector) {
1968 item.find(it + 1, it_end, r);
1971 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
1972 for (
auto &item : *map) {
1973 item.second.find(it + 1, it_end, r);
1978 void find_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
std::vector<datum *> &r)
noexcept
1980 this->
find(it + 1, it_end, r);
1982 if (
auto vector = get_if<datum::vector_type>(*
this)) {
1983 for (
auto &item : *vector) {
1984 item.find(it, it_end, r);
1987 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
1988 for (
auto &item : *map) {
1989 item.second.find(it, it_end, r);
1995 jsonpath_indices
const &indices,
1996 jsonpath::const_iterator it,
1997 jsonpath::const_iterator it_end,
2000 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2001 for (
hilet index : indices.filter(ssize(*vector))) {
2002 (*vector)[index].find(it + 1, it_end, r);
2008 jsonpath_names
const &names,
2009 jsonpath::const_iterator it,
2010 jsonpath::const_iterator it_end,
2013 if (
auto map = get_if<datum::map_type>(*
this)) {
2014 for (
hilet &name : names) {
2015 hilet name_ = datum{name};
2016 auto jt = map->find(name_);
2017 if (jt != map->cend()) {
2018 jt->second.find(it + 1, it_end, r);
2025 jsonpath_slice
const &slice,
2026 jsonpath::const_iterator it,
2027 jsonpath::const_iterator it_end,
2030 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2031 hilet first = slice.begin(vector->size());
2032 hilet last = slice.end(vector->size());
2034 for (
auto index = first; index != last; index += slice.step) {
2035 if (index >= 0 and index < vector->size()) {
2036 (*this)[index].find(it + 1, it_end, r);
2047 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2048 find(it + 1, it_end, r);
2050 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2051 find(it + 1, it_end, r);
2053 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2054 find_wildcard(it, it_end, r);
2056 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2057 find_descend(it, it_end, r);
2059 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2060 find_indices(*indices, it, it_end, r);
2062 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2063 find_names(*names, it, it_end, r);
2065 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2066 find_slice(*slice, it, it_end, r);
2073 [[nodiscard]]
int remove_wildcard(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2077 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2078 auto jt = vector->begin();
2079 while (jt != vector->end()) {
2080 hilet match = jt->remove(it + 1, it_end);
2084 jt = vector->erase(jt);
2089 return vector->empty() ? 2 : r;
2091 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2092 auto jt = map->begin();
2093 while (jt != map->end()) {
2094 hilet match = jt->second.remove(it + 1, it_end);
2098 jt = map->erase(jt);
2103 return map->empty() ? 2 : r;
2110 [[nodiscard]]
int remove_descend(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2122 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2123 auto jt = vector->begin();
2124 while (jt != vector->end()) {
2125 hilet match = jt->remove(it, it_end);
2129 jt = vector->erase(jt);
2134 return vector->empty() ? 2 : r;
2136 }
else if (
auto map = get_if<datum::map_type>(*
this)) {
2137 auto jt = map->begin();
2138 while (jt != map->end()) {
2139 hilet match = jt->second.remove(it, it_end);
2143 jt = map->erase(jt);
2148 return map->empty() ? 2 : r;
2156 remove_indices(jsonpath_indices
const &indices, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2158 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2162 for (
hilet index : indices.filter(ssize(*vector))) {
2163 hilet match = (*vector)[index - offset].remove(it + 1, it_end);
2166 vector->erase(vector->begin() + (index - offset));
2171 return vector->empty() ? 2 : r;
2179 remove_names(jsonpath_names
const &names, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2181 if (
auto map = get_if<datum::map_type>(*
this)) {
2184 for (
hilet &name : names) {
2185 hilet name_ = datum{name};
2186 auto jt = map->find(name_);
2187 if (jt != map->cend()) {
2188 hilet match = jt->second.remove(it + 1, it_end);
2196 return map->empty() ? 2 : r;
2204 remove_slice(jsonpath_slice
const &slice, jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2206 if (
auto vector = get_if<datum::vector_type>(*
this)) {
2209 hilet first = slice.begin(vector->size());
2210 hilet last = slice.end(vector->size());
2213 for (
auto index = first; index != last; index += slice.step) {
2214 if (index >= 0 and index < vector->size()) {
2215 hilet match = (*this)[index - offset].remove(it + 1, it_end);
2219 vector->erase(vector->begin() + (index - offset));
2225 return vector->empty() ? 2 : r;
2232 [[nodiscard]]
int remove(jsonpath::const_iterator it, jsonpath::const_iterator it_end)
noexcept
2238 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2239 return remove(it + 1, it_end);
2241 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2242 return remove(it + 1, it_end);
2244 }
else if (std::holds_alternative<jsonpath_wildcard>(*it)) {
2245 return remove_wildcard(it, it_end);
2247 }
else if (std::holds_alternative<jsonpath_descend>(*it)) {
2248 return remove_descend(it, it_end);
2250 }
else if (
auto indices = std::get_if<jsonpath_indices>(&*it)) {
2251 return remove_indices(*indices, it, it_end);
2253 }
else if (
auto names = std::get_if<jsonpath_names>(&*it)) {
2254 return remove_names(*names, it, it_end);
2256 }
else if (
auto slice = std::get_if<jsonpath_slice>(&*it)) {
2257 return remove_slice(*slice, it, it_end);
2264 [[nodiscard]] datum *
2265 find_one_name(datum
const &name, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2267 hi_axiom(holds_alternative<std::string>(name));
2269 if (
auto *map = get_if<map_type>(*
this)) {
2270 auto i = map->find(name);
2271 if (i != map->end()) {
2272 return i->second.find_one(it + 1, it_end, create);
2274 }
else if (create) {
2275 (*map)[name] = datum{std::monostate{}};
2276 return find_one_name(name, it, it_end, create);
2282 }
else if (holds_alternative<std::monostate>(*
this) and create) {
2283 *
this = datum::make_map(name, std::monostate{});
2284 return find_one_name(name, it, it_end, create);
2291 [[nodiscard]] datum *
2292 find_one_index(
std::size_t index, jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2294 if (
auto *vector = get_if<vector_type>(*
this)) {
2295 if (index < vector->size()) {
2296 return (*vector)[index].find_one(it + 1, it_end, create);
2297 }
else if (index == vector->size() and create) {
2298 vector->push_back(datum{std::monostate{}});
2299 return find_one_index(index, it, it_end, create);
2304 }
else if (holds_alternative<std::monostate>(*
this) and index == 0 and create) {
2305 *
this = datum::make_vector(std::monostate{});
2306 return find_one_index(index, it, it_end, create);
2313 [[nodiscard]] datum *find_one(jsonpath::const_iterator it, jsonpath::const_iterator it_end,
bool create)
noexcept
2318 }
else if (std::holds_alternative<jsonpath_root>(*it)) {
2319 return find_one(it + 1, it_end, create);
2321 }
else if (std::holds_alternative<jsonpath_current>(*it)) {
2322 return find_one(it + 1, it_end, create);
2324 }
else if (
hilet *indices = std::get_if<jsonpath_indices>(&*it)) {
2325 hi_axiom(indices->size() == 1);
2326 return find_one_index(indices->front(), it, it_end, create);
2328 }
else if (
hilet *names = std::get_if<jsonpath_names>(&*it)) {
2329 hi_axiom(names->size() == 1);
2330 return find_one_name(datum{names->front()}, it, it_end, create);