join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
value.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_DATA_VALUE_HPP
26#define JOIN_DATA_VALUE_HPP
27
28// libjoin.
29#include <join/sax_error.hpp>
30#include <join/variant.hpp>
31#include <join/utils.hpp>
32
33// C++.
34#include <string_view>
35#include <stdexcept>
36#include <compare>
37#include <sstream>
38#include <fstream>
39#include <string>
40#include <vector>
41#include <limits>
42
43// C.
44#include <cstdint>
45#include <cmath>
46
47namespace join
48{
50 class Value;
51
53 using Array = std::vector<Value>;
54
58 template <typename Type>
60 {
66 constexpr bool operator== (const BasicMember& other) const = default;
67
73 constexpr std::partial_ordering operator<=> (const BasicMember& other) const = default;
74
76 Type first;
77
79 Type second;
80 };
81
84
86 using Object = std::vector<Member>;
87
91 class Value
92 {
94 using Data =
96
97 public:
114
118 constexpr Value () = default;
119
124 constexpr Value (std::nullptr_t value)
125 : _data (std::in_place_index<NullValue>, value)
126 {
127 }
128
133 constexpr Value (bool value)
134 : _data (std::in_place_index<BooleanValue>, value)
135 {
136 }
137
142 constexpr Value (int32_t value)
143 : _data (std::in_place_index<IntegerValue>, value)
144 {
145 }
146
151 constexpr Value (uint32_t value)
152 : _data (std::in_place_index<UnsignedValue>, value)
153 {
154 }
155
160 constexpr Value (int64_t value)
161 : _data (std::in_place_index<Integer64Value>, value)
162 {
163 }
164
169 constexpr Value (uint64_t value)
170 : _data (std::in_place_index<Unsigned64Value>, value)
171 {
172 }
173
178 constexpr Value (double value)
179 : _data (std::in_place_index<RealValue>, value)
180 {
181 }
182
187 Value (const char* value)
188 : _data (std::in_place_index<StringValue>, value)
189 {
190 }
191
196 Value (std::string_view value)
197 : _data (std::in_place_index<StringValue>, value)
198 {
199 }
200
205 Value (const std::string& value)
206 : _data (std::in_place_index<StringValue>, value)
207 {
208 }
209
214 Value (std::string&& value)
215 : _data (std::in_place_index<StringValue>, std::move (value))
216 {
217 }
218
223 Value (const Array& value)
224 : _data (std::in_place_index<ArrayValue>, value)
225 {
226 }
227
232 Value (Array&& value)
233 : _data (std::in_place_index<ArrayValue>, std::move (value))
234 {
235 }
236
241 Value (const Object& value)
242 : _data (std::in_place_index<ObjectValue>, value)
243 {
244 }
245
250 Value (Object&& value)
251 : _data (std::in_place_index<ObjectValue>, std::move (value))
252 {
253 }
254
259 constexpr Value (const Value& other) = default;
260
266 Value& operator= (const Value& other) = default;
267
272 constexpr Value (Value&& other) = default;
273
279 Value& operator= (Value&& other) = default;
280
284 ~Value () = default;
285
290 constexpr std::size_t index () const noexcept
291 {
292 return _data.index ();
293 }
294
299 constexpr bool isNull () const
300 {
301 return _data.index () == NullValue;
302 }
303
308 constexpr bool isBool () const
309 {
310 return _data.index () == BooleanValue;
311 }
312
318 constexpr bool getBool () const
319 {
320 if (_data.index () == BooleanValue)
321 {
322 return _data.get<BooleanValue> ();
323 }
324
325 return convertBool ();
326 }
327
333 explicit operator bool () const
334 {
335 return getBool ();
336 }
337
343 constexpr bool isTrue () const
344 {
345 return getBool ();
346 }
347
353 constexpr bool isFalse () const
354 {
355 return !getBool ();
356 }
357
362 constexpr bool isNumber () const
363 {
364 return _data.index () == IntegerValue || _data.index () == UnsignedValue ||
365 _data.index () == Integer64Value || _data.index () == Unsigned64Value || _data.index () == RealValue;
366 }
367
372 constexpr bool isInt8 () const
373 {
374 switch (_data.index ())
375 {
376 case IntegerValue:
377 return _data.get<IntegerValue> () >= static_cast<int32_t> (std::numeric_limits<int8_t>::min ()) &&
378 _data.get<IntegerValue> () <= static_cast<int32_t> (std::numeric_limits<int8_t>::max ());
379
380 case UnsignedValue:
381 return _data.get<UnsignedValue> () <= static_cast<uint32_t> (std::numeric_limits<int8_t>::max ());
382
383 case Integer64Value:
384 return _data.get<Integer64Value> () >= static_cast<int64_t> (std::numeric_limits<int8_t>::min ()) &&
385 _data.get<Integer64Value> () <= static_cast<int64_t> (std::numeric_limits<int8_t>::max ());
386
387 case Unsigned64Value:
388 return _data.get<Unsigned64Value> () <= static_cast<uint64_t> (std::numeric_limits<int8_t>::max ());
389
390 case RealValue:
391 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
392 _data.get<RealValue> () >= static_cast<double> (std::numeric_limits<int8_t>::min ()) &&
393 _data.get<RealValue> () <= static_cast<double> (std::numeric_limits<int8_t>::max ());
394
395 default:
396 break;
397 }
398
399 return false;
400 }
401
407 constexpr int8_t getInt8 () const
408 {
409 if (isInt8 ())
410 {
411 switch (_data.index ())
412 {
413 case IntegerValue:
414 return static_cast<int8_t> (_data.get<IntegerValue> ());
415
416 case UnsignedValue:
417 return static_cast<int8_t> (_data.get<UnsignedValue> ());
418
419 case Integer64Value:
420 return static_cast<int8_t> (_data.get<Integer64Value> ());
421
422 case Unsigned64Value:
423 return static_cast<int8_t> (_data.get<Unsigned64Value> ());
424
425 default:
426 return static_cast<int8_t> (_data.get<RealValue> ());
427 }
428 }
429
430 throwException<std::bad_cast> ();
431 }
432
438 explicit operator int8_t () const
439 {
440 return getInt8 ();
441 }
442
447 constexpr bool isUint8 () const
448 {
449 switch (_data.index ())
450 {
451 case IntegerValue:
452 return _data.get<IntegerValue> () >= 0 &&
453 _data.get<IntegerValue> () <= static_cast<int32_t> (std::numeric_limits<uint8_t>::max ());
454
455 case UnsignedValue:
456 return _data.get<UnsignedValue> () <= static_cast<uint32_t> (std::numeric_limits<uint8_t>::max ());
457
458 case Integer64Value:
459 return _data.get<Integer64Value> () >= 0 &&
460 _data.get<Integer64Value> () <= static_cast<int64_t> (std::numeric_limits<uint8_t>::max ());
461
462 case Unsigned64Value:
463 return _data.get<Unsigned64Value> () <=
464 static_cast<uint64_t> (std::numeric_limits<uint8_t>::max ());
465
466 case RealValue:
467 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
468 _data.get<RealValue> () >= 0 &&
469 _data.get<RealValue> () <= static_cast<double> (std::numeric_limits<uint8_t>::max ());
470
471 default:
472 break;
473 }
474
475 return false;
476 }
477
483 constexpr uint8_t getUint8 () const
484 {
485 if (isUint8 ())
486 {
487 switch (_data.index ())
488 {
489 case IntegerValue:
490 return static_cast<uint8_t> (_data.get<IntegerValue> ());
491
492 case UnsignedValue:
493 return static_cast<uint8_t> (_data.get<UnsignedValue> ());
494
495 case Integer64Value:
496 return static_cast<uint8_t> (_data.get<Integer64Value> ());
497
498 case Unsigned64Value:
499 return static_cast<uint8_t> (_data.get<Unsigned64Value> ());
500
501 default:
502 return static_cast<uint8_t> (_data.get<RealValue> ());
503 }
504 }
505
506 throwException<std::bad_cast> ();
507 }
508
514 explicit operator uint8_t () const
515 {
516 return getUint8 ();
517 }
518
523 constexpr bool isInt16 () const
524 {
525 switch (_data.index ())
526 {
527 case IntegerValue:
528 return _data.get<IntegerValue> () >= static_cast<int32_t> (std::numeric_limits<int16_t>::min ()) &&
529 _data.get<IntegerValue> () <= static_cast<int32_t> (std::numeric_limits<int16_t>::max ());
530
531 case UnsignedValue:
532 return _data.get<UnsignedValue> () <= static_cast<uint32_t> (std::numeric_limits<int16_t>::max ());
533
534 case Integer64Value:
535 return _data.get<Integer64Value> () >=
536 static_cast<int64_t> (std::numeric_limits<int16_t>::min ()) &&
537 _data.get<Integer64Value> () <= static_cast<int64_t> (std::numeric_limits<int16_t>::max ());
538
539 case Unsigned64Value:
540 return _data.get<Unsigned64Value> () <=
541 static_cast<uint64_t> (std::numeric_limits<int16_t>::max ());
542
543 case RealValue:
544 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
545 _data.get<RealValue> () >= static_cast<double> (std::numeric_limits<int16_t>::min ()) &&
546 _data.get<RealValue> () <= static_cast<double> (std::numeric_limits<int16_t>::max ());
547
548 default:
549 break;
550 }
551
552 return false;
553 }
554
560 constexpr int16_t getInt16 () const
561 {
562 if (isInt16 ())
563 {
564 switch (_data.index ())
565 {
566 case IntegerValue:
567 return static_cast<int16_t> (_data.get<IntegerValue> ());
568
569 case UnsignedValue:
570 return static_cast<int16_t> (_data.get<UnsignedValue> ());
571
572 case Integer64Value:
573 return static_cast<int16_t> (_data.get<Integer64Value> ());
574
575 case Unsigned64Value:
576 return static_cast<int16_t> (_data.get<Unsigned64Value> ());
577
578 default:
579 return static_cast<int16_t> (_data.get<RealValue> ());
580 }
581 }
582
583 throwException<std::bad_cast> ();
584 }
585
591 explicit operator int16_t () const
592 {
593 return getInt16 ();
594 }
595
600 constexpr bool isUint16 () const
601 {
602 switch (_data.index ())
603 {
604 case IntegerValue:
605 return _data.get<IntegerValue> () >= 0 &&
606 _data.get<IntegerValue> () <= static_cast<int32_t> (std::numeric_limits<uint16_t>::max ());
607
608 case UnsignedValue:
609 return _data.get<UnsignedValue> () <= static_cast<uint32_t> (std::numeric_limits<uint16_t>::max ());
610
611 case Integer64Value:
612 return _data.get<Integer64Value> () >= 0 &&
613 _data.get<Integer64Value> () <= static_cast<int64_t> (std::numeric_limits<uint16_t>::max ());
614
615 case Unsigned64Value:
616 return _data.get<Unsigned64Value> () <=
617 static_cast<uint64_t> (std::numeric_limits<uint16_t>::max ());
618
619 case RealValue:
620 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
621 _data.get<RealValue> () >= 0 &&
622 _data.get<RealValue> () <= static_cast<double> (std::numeric_limits<uint16_t>::max ());
623
624 default:
625 break;
626 }
627
628 return false;
629 }
630
636 constexpr uint16_t getUint16 () const
637 {
638 if (isUint16 ())
639 {
640 switch (_data.index ())
641 {
642 case IntegerValue:
643 return static_cast<uint16_t> (_data.get<IntegerValue> ());
644
645 case UnsignedValue:
646 return static_cast<uint16_t> (_data.get<UnsignedValue> ());
647
648 case Integer64Value:
649 return static_cast<uint16_t> (_data.get<Integer64Value> ());
650
651 case Unsigned64Value:
652 return static_cast<uint16_t> (_data.get<Unsigned64Value> ());
653
654 default:
655 return static_cast<uint16_t> (_data.get<RealValue> ());
656 }
657 }
658
659 throwException<std::bad_cast> ();
660 }
661
667 explicit operator uint16_t () const
668 {
669 return getUint16 ();
670 }
671
676 constexpr bool isInt () const
677 {
678 switch (_data.index ())
679 {
680 case IntegerValue:
681 return true;
682
683 case UnsignedValue:
684 return _data.get<UnsignedValue> () <= static_cast<uint32_t> (std::numeric_limits<int32_t>::max ());
685
686 case Integer64Value:
687 return _data.get<Integer64Value> () >=
688 static_cast<int64_t> (std::numeric_limits<int32_t>::min ()) &&
689 _data.get<Integer64Value> () <= static_cast<int64_t> (std::numeric_limits<int32_t>::max ());
690
691 case Unsigned64Value:
692 return _data.get<Unsigned64Value> () <=
693 static_cast<uint64_t> (std::numeric_limits<int32_t>::max ());
694
695 case RealValue:
696 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
697 _data.get<RealValue> () >= static_cast<double> (std::numeric_limits<int32_t>::min ()) &&
698 _data.get<RealValue> () <= static_cast<double> (std::numeric_limits<int32_t>::max ());
699
700 default:
701 break;
702 }
703
704 return false;
705 }
706
712 constexpr int32_t getInt () const
713 {
714 if (_data.index () == IntegerValue)
715 {
716 return _data.get<IntegerValue> ();
717 }
718
719 return convertInt ();
720 }
721
727 explicit operator int32_t () const
728 {
729 return getInt ();
730 }
731
736 constexpr bool isUint () const
737 {
738 switch (_data.index ())
739 {
740 case IntegerValue:
741 return _data.get<IntegerValue> () >= 0;
742
743 case UnsignedValue:
744 return true;
745
746 case Integer64Value:
747 return _data.get<Integer64Value> () >= 0 &&
748 _data.get<Integer64Value> () <= static_cast<int64_t> (std::numeric_limits<uint32_t>::max ());
749
750 case Unsigned64Value:
751 return _data.get<Unsigned64Value> () <=
752 static_cast<uint64_t> (std::numeric_limits<uint32_t>::max ());
753
754 case RealValue:
755 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
756 _data.get<RealValue> () >= 0 &&
757 _data.get<RealValue> () <= static_cast<double> (std::numeric_limits<uint32_t>::max ());
758
759 default:
760 break;
761 }
762
763 return false;
764 }
765
771 constexpr uint32_t getUint () const
772 {
773 if (_data.index () == UnsignedValue)
774 {
775 return _data.get<UnsignedValue> ();
776 }
777
778 return convertUint ();
779 }
780
786 explicit operator uint32_t () const
787 {
788 return getUint ();
789 }
790
795 constexpr bool isInt64 () const
796 {
797 switch (_data.index ())
798 {
799 case IntegerValue:
800 case UnsignedValue:
801 case Integer64Value:
802 return true;
803
804 case Unsigned64Value:
805 return _data.get<Unsigned64Value> () <=
806 static_cast<uint64_t> (std::numeric_limits<int64_t>::max ());
807
808 case RealValue:
809 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
810 _data.get<RealValue> () >= static_cast<double> (std::numeric_limits<int64_t>::min ()) &&
811 _data.get<RealValue> () < static_cast<double> (std::numeric_limits<int64_t>::max ());
812
813 default:
814 break;
815 }
816
817 return false;
818 }
819
825 constexpr int64_t getInt64 () const
826 {
827 if (_data.index () == Integer64Value)
828 {
829 return _data.get<Integer64Value> ();
830 }
831
832 return convertInt64 ();
833 }
834
840 explicit operator int64_t () const
841 {
842 return getInt64 ();
843 }
844
849 constexpr bool isUint64 () const
850 {
851 switch (_data.index ())
852 {
853 case IntegerValue:
854 return _data.get<IntegerValue> () >= 0;
855
856 case UnsignedValue:
857 return true;
858
859 case Integer64Value:
860 return _data.get<Integer64Value> () >= 0;
861
862 case Unsigned64Value:
863 return true;
864
865 case RealValue:
866 return std::trunc (_data.get<RealValue> ()) == _data.get<RealValue> () &&
867 _data.get<RealValue> () >= 0 &&
868 _data.get<RealValue> () < static_cast<double> (std::numeric_limits<uint64_t>::max ());
869
870 default:
871 break;
872 }
873
874 return false;
875 }
876
882 constexpr uint64_t getUint64 () const
883 {
884 if (_data.index () == Unsigned64Value)
885 {
886 return _data.get<Unsigned64Value> ();
887 }
888
889 return convertUint64 ();
890 }
891
897 explicit operator uint64_t () const
898 {
899 return getUint64 ();
900 }
901
906 constexpr bool isFloat () const
907 {
908 return isNumber ();
909 }
910
916 constexpr float getFloat () const
917 {
918 if (_data.index () == RealValue)
919 {
920 return static_cast<float> (_data.get<RealValue> ());
921 }
922
923 return convertFloat ();
924 }
925
931 explicit operator float () const
932 {
933 return getFloat ();
934 }
935
940 constexpr bool isDouble () const
941 {
942 return isNumber ();
943 }
944
950 constexpr double getDouble () const
951 {
952 if (_data.index () == RealValue)
953 {
954 return _data.get<RealValue> ();
955 }
956
957 return convertDouble ();
958 }
959
965 explicit operator double () const
966 {
967 return getDouble ();
968 }
969
974 constexpr bool isString () const
975 {
976 return _data.index () == StringValue;
977 }
978
984 constexpr std::string_view getString () const
985 {
986 return _data.get<StringValue> ();
987 }
988
994 explicit operator std::string_view () const
995 {
996 return getString ();
997 }
998
1003 constexpr bool isArray () const
1004 {
1005 return _data.index () == ArrayValue;
1006 }
1007
1013 constexpr const Array& getArray () const
1014 {
1015 return _data.get<ArrayValue> ();
1016 }
1017
1023 constexpr Array& getArray ()
1024 {
1025 return _data.get<ArrayValue> ();
1026 }
1027
1032 constexpr bool isObject () const
1033 {
1034 return _data.index () == ObjectValue;
1035 }
1036
1042 constexpr const Object& getObject () const
1043 {
1044 return _data.get<ObjectValue> ();
1045 }
1046
1052 constexpr Object& getObject ()
1053 {
1054 return _data.get<ObjectValue> ();
1055 }
1056
1063 Value& at ([[maybe_unused]] std::nullptr_t key)
1064 {
1065 for (auto& member : _data.get<ObjectValue> ())
1066 {
1067 if (member.first.isNull ())
1068 {
1069 return member.second;
1070 }
1071 }
1072
1073 throwException<std::out_of_range> ("invalid key");
1074 }
1075
1082 Value& at (bool key)
1083 {
1084 for (auto& member : _data.get<ObjectValue> ())
1085 {
1086 if (member.first.isBool () && member.first.getBool () == key)
1087 {
1088 return member.second;
1089 }
1090 }
1091
1092 throwException<std::out_of_range> ("invalid key");
1093 }
1094
1101 Value& at (int32_t key)
1102 {
1103 if (_data.index () == ArrayValue)
1104 {
1105 return _data.get<ArrayValue> ().at (key);
1106 }
1107
1108 for (auto& member : _data.get<ObjectValue> ())
1109 {
1110 if (member.first.isInt () && member.first.getInt () == key)
1111 {
1112 return member.second;
1113 }
1114 }
1115
1116 throwException<std::out_of_range> ("invalid key");
1117 }
1118
1125 Value& at (uint32_t key)
1126 {
1127 if (_data.index () == ArrayValue)
1128 {
1129 return _data.get<ArrayValue> ().at (key);
1130 }
1131
1132 for (auto& member : _data.get<ObjectValue> ())
1133 {
1134 if (member.first.isUint () && member.first.getUint () == key)
1135 {
1136 return member.second;
1137 }
1138 }
1139
1140 throwException<std::out_of_range> ("invalid key");
1141 }
1142
1149 Value& at (int64_t key)
1150 {
1151 if (_data.index () == ArrayValue)
1152 {
1153 return _data.get<ArrayValue> ().at (key);
1154 }
1155
1156 for (auto& member : _data.get<ObjectValue> ())
1157 {
1158 if (member.first.isInt64 () && member.first.getInt64 () == key)
1159 {
1160 return member.second;
1161 }
1162 }
1163
1164 throwException<std::out_of_range> ("invalid key");
1165 }
1166
1173 Value& at (uint64_t key)
1174 {
1175 if (_data.index () == ArrayValue)
1176 {
1177 return _data.get<ArrayValue> ().at (key);
1178 }
1179
1180 for (auto& member : _data.get<ObjectValue> ())
1181 {
1182 if (member.first.isUint64 () && member.first.getUint64 () == key)
1183 {
1184 return member.second;
1185 }
1186 }
1187
1188 throwException<std::out_of_range> ("invalid key");
1189 }
1190
1197 Value& at (double key)
1198 {
1199 for (auto& member : _data.get<ObjectValue> ())
1200 {
1201 if (member.first.isDouble () && member.first.getDouble () == key)
1202 {
1203 return member.second;
1204 }
1205 }
1206
1207 throwException<std::out_of_range> ("invalid key");
1208 }
1209
1216 Value& at (std::string_view key)
1217 {
1218 for (auto& member : _data.get<ObjectValue> ())
1219 {
1220 if (member.first.isString () && member.first.getString () == key)
1221 {
1222 return member.second;
1223 }
1224 }
1225
1226 throwException<std::out_of_range> ("invalid key");
1227 }
1228
1235 Value& at (const char* key)
1236 {
1237 return at (std::string_view (key));
1238 }
1239
1246 const Value& at ([[maybe_unused]] std::nullptr_t key) const
1247 {
1248 for (auto const& member : _data.get<ObjectValue> ())
1249 {
1250 if (member.first.isNull ())
1251 {
1252 return member.second;
1253 }
1254 }
1255
1256 throwException<std::out_of_range> ("invalid key");
1257 }
1258
1265 const Value& at (bool key) const
1266 {
1267 for (auto const& member : _data.get<ObjectValue> ())
1268 {
1269 if (member.first.isBool () && member.first.getBool () == key)
1270 {
1271 return member.second;
1272 }
1273 }
1274
1275 throwException<std::out_of_range> ("invalid key");
1276 }
1277
1284 const Value& at (int32_t key) const
1285 {
1286 if (_data.index () == ArrayValue)
1287 {
1288 return _data.get<ArrayValue> ().at (key);
1289 }
1290
1291 for (auto const& member : _data.get<ObjectValue> ())
1292 {
1293 if (member.first.isInt () && member.first.getInt () == key)
1294 {
1295 return member.second;
1296 }
1297 }
1298
1299 throwException<std::out_of_range> ("invalid key");
1300 }
1301
1308 const Value& at (uint32_t key) const
1309 {
1310 if (_data.index () == ArrayValue)
1311 {
1312 return _data.get<ArrayValue> ().at (key);
1313 }
1314
1315 for (auto const& member : _data.get<ObjectValue> ())
1316 {
1317 if (member.first.isUint () && member.first.getUint () == key)
1318 {
1319 return member.second;
1320 }
1321 }
1322
1323 throwException<std::out_of_range> ("invalid key");
1324 }
1325
1332 const Value& at (int64_t key) const
1333 {
1334 if (_data.index () == ArrayValue)
1335 {
1336 return _data.get<ArrayValue> ().at (key);
1337 }
1338
1339 for (auto const& member : _data.get<ObjectValue> ())
1340 {
1341 if (member.first.isInt64 () && member.first.getInt64 () == key)
1342 {
1343 return member.second;
1344 }
1345 }
1346
1347 throwException<std::out_of_range> ("invalid key");
1348 }
1349
1356 const Value& at (uint64_t key) const
1357 {
1358 if (_data.index () == ArrayValue)
1359 {
1360 return _data.get<ArrayValue> ().at (key);
1361 }
1362
1363 for (auto const& member : _data.get<ObjectValue> ())
1364 {
1365 if (member.first.isUint64 () && member.first.getUint64 () == key)
1366 {
1367 return member.second;
1368 }
1369 }
1370
1371 throwException<std::out_of_range> ("invalid key");
1372 }
1373
1380 const Value& at (double key) const
1381 {
1382 for (auto const& member : _data.get<ObjectValue> ())
1383 {
1384 if (member.first.isDouble () && member.first.getDouble () == key)
1385 {
1386 return member.second;
1387 }
1388 }
1389
1390 throwException<std::out_of_range> ("invalid key");
1391 }
1392
1399 const Value& at (std::string_view key) const
1400 {
1401 for (auto const& member : _data.get<ObjectValue> ())
1402 {
1403 if (member.first.isString () && member.first.getString () == key)
1404 {
1405 return member.second;
1406 }
1407 }
1408
1409 throwException<std::out_of_range> ("invalid key");
1410 }
1411
1418 const Value& at (const char* key) const
1419 {
1420 return at (std::string_view (key));
1421 }
1422
1429 Value& operator[] (std::nullptr_t key)
1430 {
1431 if (_data.index () == NullValue)
1432 {
1433 _data.set<ObjectValue> ();
1434 }
1435
1436 for (auto& member : _data.get<ObjectValue> ())
1437 {
1438 if (member.first.isNull ())
1439 {
1440 return member.second;
1441 }
1442 }
1443
1444 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1445
1446 return _data.get<ObjectValue> ().back ().second;
1447 }
1448
1456 {
1457 if (_data.index () == NullValue)
1458 {
1459 _data.set<ObjectValue> ();
1460 }
1461
1462 for (auto& member : _data.get<ObjectValue> ())
1463 {
1464 if (member.first.isBool () && member.first.getBool () == key)
1465 {
1466 return member.second;
1467 }
1468 }
1469
1470 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1471
1472 return _data.get<ObjectValue> ().back ().second;
1473 }
1474
1482 {
1483 if (_data.index () == ArrayValue)
1484 {
1485 return _data.get<ArrayValue> ()[key];
1486 }
1487
1488 if (_data.index () == NullValue)
1489 {
1490 _data.set<ObjectValue> ();
1491 }
1492
1493 for (auto& member : _data.get<ObjectValue> ())
1494 {
1495 if (member.first.isInt () && member.first.getInt () == key)
1496 {
1497 return member.second;
1498 }
1499 }
1500
1501 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1502
1503 return _data.get<ObjectValue> ().back ().second;
1504 }
1505
1513 {
1514 if (_data.index () == ArrayValue)
1515 {
1516 return _data.get<ArrayValue> ()[key];
1517 }
1518
1519 if (_data.index () == NullValue)
1520 {
1521 _data.set<ObjectValue> ();
1522 }
1523
1524 for (auto& member : _data.get<ObjectValue> ())
1525 {
1526 if (member.first.isUint () && member.first.getUint () == key)
1527 {
1528 return member.second;
1529 }
1530 }
1531
1532 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1533
1534 return _data.get<ObjectValue> ().back ().second;
1535 }
1536
1544 {
1545 if (_data.index () == ArrayValue)
1546 {
1547 return _data.get<ArrayValue> ()[key];
1548 }
1549
1550 if (_data.index () == NullValue)
1551 {
1552 _data.set<ObjectValue> ();
1553 }
1554
1555 for (auto& member : _data.get<ObjectValue> ())
1556 {
1557 if (member.first.isInt64 () && member.first.getInt64 () == key)
1558 {
1559 return member.second;
1560 }
1561 }
1562
1563 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1564
1565 return _data.get<ObjectValue> ().back ().second;
1566 }
1567
1575 {
1576 if (_data.index () == ArrayValue)
1577 {
1578 return _data.get<ArrayValue> ()[key];
1579 }
1580
1581 if (_data.index () == NullValue)
1582 {
1583 _data.set<ObjectValue> ();
1584 }
1585
1586 for (auto& member : _data.get<ObjectValue> ())
1587 {
1588 if (member.first.isUint64 () && member.first.getUint64 () == key)
1589 {
1590 return member.second;
1591 }
1592 }
1593
1594 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1595
1596 return _data.get<ObjectValue> ().back ().second;
1597 }
1598
1606 {
1607 if (_data.index () == NullValue)
1608 {
1609 _data.set<ObjectValue> ();
1610 }
1611
1612 for (auto& member : _data.get<ObjectValue> ())
1613 {
1614 if (member.first.isDouble () && member.first.getDouble () == key)
1615 {
1616 return member.second;
1617 }
1618 }
1619
1620 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1621
1622 return _data.get<ObjectValue> ().back ().second;
1623 }
1624
1631 Value& operator[] (std::string_view key)
1632 {
1633 if (_data.index () == NullValue)
1634 {
1635 _data.set<ObjectValue> ();
1636 }
1637
1638 for (auto& member : _data.get<ObjectValue> ())
1639 {
1640 if (member.first.isString () && member.first.getString () == key)
1641 {
1642 return member.second;
1643 }
1644 }
1645
1646 _data.get<ObjectValue> ().emplace_back (key, nullptr);
1647
1648 return _data.get<ObjectValue> ().back ().second;
1649 }
1650
1657 Value& operator[] (const char* key)
1658 {
1659 return operator[] (std::string_view (key));
1660 }
1661
1667 bool empty () const
1668 {
1669 switch (_data.index ())
1670 {
1671 case StringValue:
1672 return _data.get<StringValue> ().empty ();
1673
1674 case ArrayValue:
1675 return _data.get<ArrayValue> ().empty ();
1676
1677 case ObjectValue:
1678 return _data.get<ObjectValue> ().empty ();
1679
1680 default:
1681 break;
1682 }
1683
1684 throwException<std::bad_cast> ();
1685 }
1686
1692 size_t size () const
1693 {
1694 switch (_data.index ())
1695 {
1696 case StringValue:
1697 return _data.get<StringValue> ().size ();
1698
1699 case ArrayValue:
1700 return _data.get<ArrayValue> ().size ();
1701
1702 case ObjectValue:
1703 return _data.get<ObjectValue> ().size ();
1704
1705 default:
1706 break;
1707 }
1708
1709 throwException<std::bad_cast> ();
1710 }
1711
1717 void reserve (size_t cap)
1718 {
1719 switch (_data.index ())
1720 {
1721 case StringValue:
1722 _data.get<StringValue> ().reserve (cap);
1723 return;
1724
1725 case ArrayValue:
1726 _data.get<ArrayValue> ().reserve (cap);
1727 return;
1728
1729 case ObjectValue:
1730 _data.get<ObjectValue> ().reserve (cap);
1731 return;
1732
1733 default:
1734 break;
1735 }
1736
1737 throwException<std::bad_cast> ();
1738 }
1739
1744 void clear ()
1745 {
1746 switch (_data.index ())
1747 {
1748 case StringValue:
1749 _data.get<StringValue> ().clear ();
1750 return;
1751
1752 case ArrayValue:
1753 _data.get<ArrayValue> ().clear ();
1754 return;
1755
1756 case ObjectValue:
1757 _data.get<ObjectValue> ().clear ();
1758 return;
1759
1760 default:
1761 break;
1762 }
1763
1764 throwException<std::bad_cast> ();
1765 }
1766
1773 Value& insert (const Member& member)
1774 {
1775 _data.get<ObjectValue> ().push_back (member);
1776 return _data.get<ObjectValue> ().back ().second;
1777 }
1778
1785 Value& insert (Member&& member)
1786 {
1787 _data.get<ObjectValue> ().emplace_back (std::move (member));
1788 return _data.get<ObjectValue> ().back ().second;
1789 }
1790
1797 size_t erase ([[maybe_unused]] std::nullptr_t key)
1798 {
1799 auto beg = _data.get<ObjectValue> ().begin ();
1800 auto end = _data.get<ObjectValue> ().end ();
1801
1802 for (auto it = beg; it != end; ++it)
1803 {
1804 if (it->first.isNull ())
1805 {
1806 _data.get<ObjectValue> ().erase (it);
1807 return 1;
1808 }
1809 }
1810
1811 return 0;
1812 }
1813
1820 size_t erase (bool key)
1821 {
1822 auto beg = _data.get<ObjectValue> ().begin ();
1823 auto end = _data.get<ObjectValue> ().end ();
1824
1825 for (auto it = beg; it != end; ++it)
1826 {
1827 if (it->first.isBool () && it->first.getBool () == key)
1828 {
1829 _data.get<ObjectValue> ().erase (it);
1830 return 1;
1831 }
1832 }
1833
1834 return 0;
1835 }
1836
1843 size_t erase (int32_t key)
1844 {
1845 auto beg = _data.get<ObjectValue> ().begin ();
1846 auto end = _data.get<ObjectValue> ().end ();
1847
1848 for (auto it = beg; it != end; ++it)
1849 {
1850 if (it->first.isInt () && it->first.getInt () == key)
1851 {
1852 _data.get<ObjectValue> ().erase (it);
1853 return 1;
1854 }
1855 }
1856
1857 return 0;
1858 }
1859
1866 size_t erase (uint32_t key)
1867 {
1868 auto beg = _data.get<ObjectValue> ().begin ();
1869 auto end = _data.get<ObjectValue> ().end ();
1870
1871 for (auto it = beg; it != end; ++it)
1872 {
1873 if (it->first.isUint () && it->first.getUint () == key)
1874 {
1875 _data.get<ObjectValue> ().erase (it);
1876 return 1;
1877 }
1878 }
1879
1880 return 0;
1881 }
1882
1889 size_t erase (int64_t key)
1890 {
1891 auto beg = _data.get<ObjectValue> ().begin ();
1892 auto end = _data.get<ObjectValue> ().end ();
1893
1894 for (auto it = beg; it != end; ++it)
1895 {
1896 if (it->first.isInt64 () && it->first.getInt64 () == key)
1897 {
1898 _data.get<ObjectValue> ().erase (it);
1899 return 1;
1900 }
1901 }
1902
1903 return 0;
1904 }
1905
1912 size_t erase (uint64_t key)
1913 {
1914 auto beg = _data.get<ObjectValue> ().begin ();
1915 auto end = _data.get<ObjectValue> ().end ();
1916
1917 for (auto it = beg; it != end; ++it)
1918 {
1919 if (it->first.isUint64 () && it->first.getUint64 () == key)
1920 {
1921 _data.get<ObjectValue> ().erase (it);
1922 return 1;
1923 }
1924 }
1925
1926 return 0;
1927 }
1928
1935 size_t erase (double key)
1936 {
1937 auto beg = _data.get<ObjectValue> ().begin ();
1938 auto end = _data.get<ObjectValue> ().end ();
1939
1940 for (auto it = beg; it != end; ++it)
1941 {
1942 if (it->first.isDouble () && it->first.getDouble () == key)
1943 {
1944 _data.get<ObjectValue> ().erase (it);
1945 return 1;
1946 }
1947 }
1948
1949 return 0;
1950 }
1951
1958 size_t erase (std::string_view key)
1959 {
1960 auto beg = _data.get<ObjectValue> ().begin ();
1961 auto end = _data.get<ObjectValue> ().end ();
1962
1963 for (auto it = beg; it != end; ++it)
1964 {
1965 if (it->first.isString () && it->first.getString () == key)
1966 {
1967 _data.get<ObjectValue> ().erase (it);
1968 return 1;
1969 }
1970 }
1971
1972 return 0;
1973 }
1974
1981 size_t erase (const char* key)
1982 {
1983 return erase (std::string_view (key));
1984 }
1985
1992 template <typename... Args>
1993 Value& emplaceBack (Args&&... args)
1994 {
1995 if (_data.index () == NullValue)
1996 {
1997 _data.set<ArrayValue> ();
1998 }
1999 _data.get<ArrayValue> ().emplace_back (std::forward<Args> (args)...);
2000 return _data.get<ArrayValue> ().back ();
2001 }
2002
2009 Value& pushBack (const Value& value)
2010 {
2011 if (_data.index () == NullValue)
2012 {
2013 _data.set<ArrayValue> ();
2014 }
2015 _data.get<ArrayValue> ().push_back (value);
2016 return _data.get<ArrayValue> ().back ();
2017 }
2018
2026 {
2027 if (_data.index () == NullValue)
2028 {
2029 _data.set<ArrayValue> ();
2030 }
2031 _data.get<ArrayValue> ().emplace_back (std::move (value));
2032 return _data.get<ArrayValue> ().back ();
2033 }
2034
2039 void popBack ()
2040 {
2041 _data.get<ArrayValue> ().pop_back ();
2042 }
2043
2050 bool contains ([[maybe_unused]] std::nullptr_t key) const
2051 {
2052 for (auto const& member : _data.get<ObjectValue> ())
2053 {
2054 if (member.first.isNull ())
2055 {
2056 return true;
2057 }
2058 }
2059
2060 return false;
2061 }
2062
2069 bool contains (bool key) const
2070 {
2071 for (auto const& member : _data.get<ObjectValue> ())
2072 {
2073 if (member.first.isBool () && member.first.getBool () == key)
2074 {
2075 return true;
2076 }
2077 }
2078
2079 return false;
2080 }
2081
2088 bool contains (int32_t key) const
2089 {
2090 if (_data.index () == ArrayValue)
2091 {
2092 return key >= 0 && static_cast<uint64_t> (key) < _data.get<ArrayValue> ().size ();
2093 }
2094
2095 for (auto const& member : _data.get<ObjectValue> ())
2096 {
2097 if (member.first.isInt () && member.first.getInt () == key)
2098 {
2099 return true;
2100 }
2101 }
2102
2103 return false;
2104 }
2105
2112 bool contains (uint32_t key) const
2113 {
2114 if (_data.index () == ArrayValue)
2115 {
2116 return key < _data.get<ArrayValue> ().size ();
2117 }
2118
2119 for (auto const& member : _data.get<ObjectValue> ())
2120 {
2121 if (member.first.isUint () && member.first.getUint () == key)
2122 {
2123 return true;
2124 }
2125 }
2126
2127 return false;
2128 }
2129
2136 bool contains (int64_t key) const
2137 {
2138 if (_data.index () == ArrayValue)
2139 {
2140 return key >= 0 && static_cast<uint64_t> (key) < _data.get<ArrayValue> ().size ();
2141 }
2142
2143 for (auto const& member : _data.get<ObjectValue> ())
2144 {
2145 if (member.first.isInt64 () && member.first.getInt64 () == key)
2146 {
2147 return true;
2148 }
2149 }
2150
2151 return false;
2152 }
2153
2160 bool contains (uint64_t key) const
2161 {
2162 if (_data.index () == ArrayValue)
2163 {
2164 return key < _data.get<ArrayValue> ().size ();
2165 }
2166
2167 for (auto const& member : _data.get<ObjectValue> ())
2168 {
2169 if (member.first.isUint64 () && member.first.getUint64 () == key)
2170 {
2171 return true;
2172 }
2173 }
2174
2175 return false;
2176 }
2177
2184 bool contains (double key) const
2185 {
2186 for (auto const& member : _data.get<ObjectValue> ())
2187 {
2188 if (member.first.isDouble () && member.first.getDouble () == key)
2189 {
2190 return true;
2191 }
2192 }
2193
2194 return false;
2195 }
2196
2203 bool contains (std::string_view key) const
2204 {
2205 for (auto const& member : _data.get<ObjectValue> ())
2206 {
2207 if (member.first.isString () && member.first.getString () == key)
2208 {
2209 return true;
2210 }
2211 }
2212
2213 return false;
2214 }
2215
2222 bool contains (const char* key) const
2223 {
2224 return contains (std::string_view (key));
2225 }
2226
2231 void swap (Value& other)
2232 {
2233 Value temp (std::move (*this));
2234 *this = std::move (other);
2235 other = std::move (temp);
2236 }
2237
2243 template <typename Handler>
2244 int serialize (Handler& handler) const
2245 {
2246 try
2247 {
2248 if (JOIN_LIKELY (setValue (*this, handler) == 0))
2249 {
2250 return 0;
2251 }
2252 }
2253 catch (...)
2254 {
2255 handler.reset ();
2256 throw;
2257 }
2258 handler.reset ();
2259 return -1;
2260 }
2261
2267 template <typename Reader, typename... Args>
2268 int deserialize (Args&&... args)
2269 {
2270 Reader reader;
2271 return reader.deserialize (std::forward<Args> (args)..., *this);
2272 }
2273
2280 template <typename Writer, typename... Args>
2281 int serialize (std::ostream& document, Args&&... args) const
2282 {
2283 Writer writer (document, std::forward<Args> (args)...);
2284 return serialize (writer);
2285 }
2286
2293 int jsonRead (const char* document, size_t length);
2294
2301 int jsonRead (const char* first, const char* last);
2302
2308 int jsonRead (std::string_view document);
2309
2315 int jsonRead (std::stringstream& document);
2316
2322 int jsonRead (std::istringstream& document);
2323
2329 int jsonRead (std::fstream& document);
2330
2336 int jsonRead (std::ifstream& document);
2337
2343 int jsonRead (std::iostream& document);
2344
2350 int jsonRead (std::istream& document);
2351
2358 int jsonWrite (std::ostream& document, size_t indentation = 0) const;
2359
2365 int jsonCanonicalize (std::ostream& document) const;
2366
2373 int packRead (const char* document, size_t length);
2374
2381 int packRead (const char* first, const char* last);
2382
2388 int packRead (std::string_view document);
2389
2395 int packRead (std::stringstream& document);
2396
2402 int packRead (std::istringstream& document);
2403
2409 int packRead (std::fstream& document);
2410
2416 int packRead (std::ifstream& document);
2417
2423 int packRead (std::iostream& document);
2424
2430 int packRead (std::istream& document);
2431
2437 int packWrite (std::ostream& document) const;
2438
2439 // friendship with equal operator.
2440 friend constexpr bool operator== (const Value& lhs, const Value& rhs);
2441
2442 // friendship with three-way comparison operator.
2443 friend constexpr std::partial_ordering operator<=> (const Value& lhs, const Value& rhs);
2444
2445 private:
2452 template <typename Handler>
2453 static int setValue (const Value& value, Handler& handler)
2454 {
2455 switch (value.index ())
2456 {
2458 return handler.setBool (value.getBool ());
2459
2461 return handler.setInt (value.getInt ());
2462
2464 return handler.setUint (value.getUint ());
2465
2467 return handler.setInt64 (value.getInt64 ());
2468
2470 return handler.setUint64 (value.getUint64 ());
2471
2472 case Value::RealValue:
2473 return handler.setDouble (value.getDouble ());
2474
2475 case Value::StringValue:
2476 return handler.setString (value.getString ());
2477
2478 case Value::ArrayValue:
2479 return setArray (value.getArray (), handler);
2480
2481 case Value::ObjectValue:
2482 return setObject (value.getObject (), handler);
2483
2484 default:
2485 return handler.setNull ();
2486 }
2487 }
2488
2495 template <typename Handler>
2496 static int setArray (const Array& array, Handler& handler)
2497 {
2498 if (handler.startArray (array.size ()) == -1)
2499 {
2500 return -1;
2501 }
2502
2503 for (auto const& element : array)
2504 {
2505 if (setValue (element, handler) == -1)
2506 {
2507 return -1;
2508 }
2509 }
2510
2511 return handler.stopArray ();
2512 }
2513
2520 template <typename Handler>
2521 static int setObject (const Object& object, Handler& handler)
2522 {
2523 if (handler.startObject (object.size ()) == -1)
2524 {
2525 return -1;
2526 }
2527
2528 for (const Member& member : handler.members (object))
2529 {
2530 int result = -1;
2531
2532 if (JOIN_LIKELY (member.first.isString ()))
2533 {
2534 result = handler.setKey (member.first.getString ());
2535 }
2536 else
2537 {
2538 switch (member.first.index ())
2539 {
2541 result = handler.setKey (member.first.getBool ());
2542 break;
2543
2545 result = handler.setKey (member.first.getInt ());
2546 break;
2547
2549 result = handler.setKey (member.first.getUint ());
2550 break;
2551
2553 result = handler.setKey (member.first.getInt64 ());
2554 break;
2555
2557 result = handler.setKey (member.first.getUint64 ());
2558 break;
2559
2560 case Value::RealValue:
2561 result = handler.setKey (member.first.getDouble ());
2562 break;
2563
2564 case Value::ArrayValue:
2565 case Value::ObjectValue:
2567 break;
2568
2569 default:
2570 result = handler.setKey (nullptr);
2571 break;
2572 }
2573 }
2574
2575 if (result == -1)
2576 {
2577 return -1;
2578 }
2579
2580 if (setValue (member.second, handler) == -1)
2581 {
2582 return -1;
2583 }
2584 }
2585
2586 return handler.stopObject ();
2587 }
2588
2593 float convertFloat () const
2594 {
2595 switch (_data.index ())
2596 {
2597 case IntegerValue:
2598 return static_cast<float> (_data.get<IntegerValue> ());
2599
2600 case UnsignedValue:
2601 return static_cast<float> (_data.get<UnsignedValue> ());
2602
2603 case Integer64Value:
2604 return static_cast<float> (_data.get<Integer64Value> ());
2605
2606 case Unsigned64Value:
2607 return static_cast<float> (_data.get<Unsigned64Value> ());
2608
2609 default:
2610 break;
2611 }
2612
2613 throwException<std::bad_cast> ();
2614 }
2615
2620 bool convertBool () const
2621 {
2622 switch (_data.index ())
2623 {
2624 case NullValue:
2625 return false;
2626
2627 case IntegerValue:
2628 return _data.get<IntegerValue> ();
2629
2630 case UnsignedValue:
2631 return _data.get<UnsignedValue> ();
2632
2633 case Integer64Value:
2634 return _data.get<Integer64Value> ();
2635
2636 case Unsigned64Value:
2637 return _data.get<Unsigned64Value> ();
2638
2639 case RealValue:
2640 return _data.get<RealValue> ();
2641
2642 default:
2643 break;
2644 }
2645
2646 throwException<std::bad_cast> ();
2647 }
2648
2653 int32_t convertInt () const
2654 {
2655 if (isInt ())
2656 {
2657 switch (_data.index ())
2658 {
2659 case UnsignedValue:
2660 return static_cast<int32_t> (_data.get<UnsignedValue> ());
2661
2662 case Integer64Value:
2663 return static_cast<int32_t> (_data.get<Integer64Value> ());
2664
2665 case Unsigned64Value:
2666 return static_cast<int32_t> (_data.get<Unsigned64Value> ());
2667
2668 default:
2669 return static_cast<int32_t> (_data.get<RealValue> ());
2670 }
2671 }
2672
2673 throwException<std::bad_cast> ();
2674 }
2675
2680 uint32_t convertUint () const
2681 {
2682 if (isUint ())
2683 {
2684 switch (_data.index ())
2685 {
2686 case IntegerValue:
2687 return static_cast<uint32_t> (_data.get<IntegerValue> ());
2688
2689 case Integer64Value:
2690 return static_cast<uint32_t> (_data.get<Integer64Value> ());
2691
2692 case Unsigned64Value:
2693 return static_cast<uint32_t> (_data.get<Unsigned64Value> ());
2694
2695 default:
2696 return static_cast<uint32_t> (_data.get<RealValue> ());
2697 }
2698 }
2699
2700 throwException<std::bad_cast> ();
2701 }
2702
2707 int64_t convertInt64 () const
2708 {
2709 if (isInt64 ())
2710 {
2711 switch (_data.index ())
2712 {
2713 case IntegerValue:
2714 return static_cast<int64_t> (_data.get<IntegerValue> ());
2715
2716 case UnsignedValue:
2717 return static_cast<int64_t> (_data.get<UnsignedValue> ());
2718
2719 case Unsigned64Value:
2720 return static_cast<int64_t> (_data.get<Unsigned64Value> ());
2721
2722 default:
2723 return static_cast<int64_t> (_data.get<RealValue> ());
2724 }
2725 }
2726
2727 throwException<std::bad_cast> ();
2728 }
2729
2734 uint64_t convertUint64 () const
2735 {
2736 if (isUint64 ())
2737 {
2738 switch (_data.index ())
2739 {
2740 case IntegerValue:
2741 return static_cast<uint64_t> (_data.get<IntegerValue> ());
2742
2743 case UnsignedValue:
2744 return static_cast<uint64_t> (_data.get<UnsignedValue> ());
2745
2746 case Integer64Value:
2747 return static_cast<uint64_t> (_data.get<Integer64Value> ());
2748
2749 default:
2750 return static_cast<uint64_t> (_data.get<RealValue> ());
2751 }
2752 }
2753
2754 throwException<std::bad_cast> ();
2755 }
2756
2761 double convertDouble () const
2762 {
2763 switch (_data.index ())
2764 {
2765 case IntegerValue:
2766 return static_cast<double> (_data.get<IntegerValue> ());
2767
2768 case UnsignedValue:
2769 return static_cast<double> (_data.get<UnsignedValue> ());
2770
2771 case Integer64Value:
2772 return static_cast<double> (_data.get<Integer64Value> ());
2773
2774 case Unsigned64Value:
2775 return static_cast<double> (_data.get<Unsigned64Value> ());
2776
2777 default:
2778 break;
2779 }
2780
2781 throwException<std::bad_cast> ();
2782 }
2783
2785 Data _data;
2786 };
2787
2794 constexpr bool operator== (const Value& lhs, const Value& rhs)
2795 {
2796 if (lhs.isNumber () && rhs.isNumber () && (lhs.index () != rhs.index ()))
2797 {
2798 if (lhs.isInt64 () && rhs.isUint64 ())
2799 {
2800 return lhs.getInt64 () >= 0 && uint64_t (lhs.getInt64 ()) == rhs.getUint64 ();
2801 }
2802 else if (lhs.isUint64 () && rhs.isInt64 ())
2803 {
2804 return rhs.getInt64 () >= 0 && uint64_t (rhs.getInt64 ()) == lhs.getUint64 ();
2805 }
2806 else
2807 {
2808 return lhs.getDouble () == rhs.getDouble ();
2809 }
2810 }
2811
2812 return lhs._data == rhs._data;
2813 }
2814
2821 constexpr std::partial_ordering operator<=> (const Value& lhs, const Value& rhs)
2822 {
2823 if (lhs.isNumber () && rhs.isNumber () && (lhs.index () != rhs.index ()))
2824 {
2825 if (lhs.isInt64 () && rhs.isUint64 ())
2826 {
2827 if (lhs.getInt64 () < 0)
2828 {
2829 return std::partial_ordering::less;
2830 }
2831 return uint64_t (lhs.getInt64 ()) <=> rhs.getUint64 ();
2832 }
2833 else if (lhs.isUint64 () && rhs.isInt64 ())
2834 {
2835 if (rhs.getInt64 () < 0)
2836 {
2837 return std::partial_ordering::greater;
2838 }
2839 return lhs.getUint64 () <=> uint64_t (rhs.getInt64 ());
2840 }
2841 else
2842 {
2843 return lhs.getDouble () <=> rhs.getDouble ();
2844 }
2845 }
2846
2847 return lhs._data <=> rhs._data;
2848 }
2849}
2850
2851#endif
value class.
Definition value.hpp:92
constexpr int32_t getInt() const
get variable held by value as a 32 bits integer.
Definition value.hpp:712
constexpr bool isFloat() const
check if the variable held by value is a float value.
Definition value.hpp:906
Value & at(std::string_view key)
returns a reference to the value mapped to key.
Definition value.hpp:1216
int serialize(Handler &handler) const
serialize the value, resetting the handler on failure.
Definition value.hpp:2244
bool contains(double key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2184
size_t size() const
returns the number of elements in the nested container.
Definition value.hpp:1692
size_t erase(uint64_t key)
removes member with the key equivalent to key.
Definition value.hpp:1912
Value & operator=(const Value &other)=default
copy assignment.
Value(Object &&value)
constructs an object value.
Definition value.hpp:250
void clear()
erases all elements in the nested container.
Definition value.hpp:1744
Value(std::string_view value)
constructs a string value from a string view.
Definition value.hpp:196
const Value & at(std::nullptr_t key) const
returns a reference to the value mapped to key.
Definition value.hpp:1246
void swap(Value &other)
exchanges the contents of the value with those of other.
Definition value.hpp:2231
constexpr bool isFalse() const
check if the content of the value is false.
Definition value.hpp:353
bool contains(std::string_view key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2203
int deserialize(Args &&... args)
deserialize a document into the value.
Definition value.hpp:2268
Value & at(uint64_t key)
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1173
bool contains(uint32_t key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2112
Value & at(std::nullptr_t key)
returns a reference to the value mapped to key.
Definition value.hpp:1063
constexpr int16_t getInt16() const
get variable held by value as a 16 bits integer.
Definition value.hpp:560
constexpr bool isInt() const
check if the variable held by value is a 32 bits integer value.
Definition value.hpp:676
size_t erase(std::string_view key)
removes member with the key equivalent to key.
Definition value.hpp:1958
friend constexpr bool operator==(const Value &lhs, const Value &rhs)
compare if equal.
Definition value.hpp:2794
size_t erase(std::nullptr_t key)
removes member with the key equivalent to key.
Definition value.hpp:1797
constexpr bool isInt64() const
check if the variable held by value is a 64 bits integer value.
Definition value.hpp:795
constexpr bool isUint16() const
check if the variable held by value is a 16 bits unsigned integer value.
Definition value.hpp:600
void popBack()
removes the last element of the nested container.
Definition value.hpp:2039
bool contains(int32_t key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2088
constexpr bool isTrue() const
check if the content of the value is true.
Definition value.hpp:343
Value(const Object &value)
constructs an object value.
Definition value.hpp:241
const Value & at(const char *key) const
returns a reference to the value mapped to key.
Definition value.hpp:1418
constexpr Value(uint32_t value)
constructs an unsigned integer value.
Definition value.hpp:151
constexpr const Array & getArray() const
get variable held by value as an array.
Definition value.hpp:1013
Value & insert(Member &&member)
insert element in the nested container.
Definition value.hpp:1785
constexpr Value(bool value)
constructs a boolean value.
Definition value.hpp:133
constexpr bool isArray() const
check if the variable held by value is an array.
Definition value.hpp:1003
int serialize(std::ostream &document, Args &&... args) const
serialize the value to a stream.
Definition value.hpp:2281
constexpr bool isUint64() const
check if the variable held by value is a 64 bits unsigned integer value.
Definition value.hpp:849
bool contains(bool key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2069
Value & at(bool key)
returns a reference to the value mapped to key.
Definition value.hpp:1082
Value & at(int64_t key)
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1149
constexpr std::string_view getString() const
get variable held by value as a string value.
Definition value.hpp:984
Value & pushBack(Value &&value)
appends element at the end of the nested container.
Definition value.hpp:2025
constexpr Object & getObject()
get variable held by value as an object.
Definition value.hpp:1052
constexpr bool isObject() const
check if the variable held by value is an object.
Definition value.hpp:1032
constexpr const Object & getObject() const
get variable held by value as an object.
Definition value.hpp:1042
void reserve(size_t cap)
increase the capacity of the nested container.
Definition value.hpp:1717
constexpr uint8_t getUint8() const
get variable held by value as a 8 bits unsigned integer.
Definition value.hpp:483
const Value & at(int32_t key) const
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1284
size_t erase(bool key)
removes member with the key equivalent to key.
Definition value.hpp:1820
bool contains(std::nullptr_t key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2050
constexpr bool isUint() const
check if the variable held by value is a 32 bits unsigned integer value.
Definition value.hpp:736
constexpr bool isInt16() const
check if the variable held by value is a 16 bits integer value.
Definition value.hpp:523
Value(Array &&value)
constructs an array value.
Definition value.hpp:232
constexpr bool getBool() const
get variable held by value as a boolean value.
Definition value.hpp:318
Value & at(int32_t key)
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1101
bool contains(uint64_t key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2160
size_t erase(double key)
removes member with the key equivalent to key.
Definition value.hpp:1935
constexpr Value(std::nullptr_t value)
constructs a null value.
Definition value.hpp:124
int jsonCanonicalize(std::ostream &document) const
serialize canonicalized json data.
Definition value.cpp:132
constexpr std::size_t index() const noexcept
get the index of the alternative in use.
Definition value.hpp:290
Index
nested value type index.
Definition value.hpp:102
@ StringValue
Definition value.hpp:110
@ RealValue
Definition value.hpp:109
@ UnsignedValue
Definition value.hpp:106
@ BooleanValue
Definition value.hpp:104
@ NullValue
Definition value.hpp:103
@ Integer64Value
Definition value.hpp:107
@ Unsigned64Value
Definition value.hpp:108
@ ArrayValue
Definition value.hpp:111
@ IntegerValue
Definition value.hpp:105
@ ObjectValue
Definition value.hpp:112
Value & pushBack(const Value &value)
appends element at the end of the nested container.
Definition value.hpp:2009
const Value & at(uint32_t key) const
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1308
const Value & at(std::string_view key) const
returns a reference to the value mapped to key.
Definition value.hpp:1399
Value(const std::string &value)
constructs a string value.
Definition value.hpp:205
constexpr Value(Value &&other)=default
move constructor.
constexpr int8_t getInt8() const
get variable held by value as a 8 bits integer.
Definition value.hpp:407
const Value & at(int64_t key) const
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1332
Value(const Array &value)
constructs an array value.
Definition value.hpp:223
Value & at(double key)
returns a reference to the value mapped to key.
Definition value.hpp:1197
constexpr double getDouble() const
get variable held by value as a double value.
Definition value.hpp:950
constexpr Value(const Value &other)=default
copy constructor.
constexpr uint32_t getUint() const
get variable held by value as a 32 bits unsigned integer value.
Definition value.hpp:771
constexpr bool isBool() const
check if the variable held by value is a boolean value.
Definition value.hpp:308
constexpr Value()=default
default constructor.
Value & operator[](std::nullptr_t key)
returns a reference to the value mapped to key.
Definition value.hpp:1429
bool contains(int64_t key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2136
const Value & at(uint64_t key) const
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1356
bool contains(const char *key) const
checks if the nested container contains an element that is mapped to key.
Definition value.hpp:2222
Value & at(const char *key)
returns a reference to the value mapped to key.
Definition value.hpp:1235
int jsonRead(const char *document, size_t length)
deserialize a json document.
Definition value.cpp:42
friend constexpr std::partial_ordering operator<=>(const Value &lhs, const Value &rhs)
three-way compare values.
Definition value.hpp:2821
constexpr bool isString() const
check if the variable held by value is a string value.
Definition value.hpp:974
constexpr float getFloat() const
get variable held by value as a float value.
Definition value.hpp:916
Value & at(uint32_t key)
returns a reference to the value at position pos or mapped to key.
Definition value.hpp:1125
constexpr bool isDouble() const
check if the variable held by value is a double value.
Definition value.hpp:940
constexpr Value(int64_t value)
constructs a 64 bits integer value.
Definition value.hpp:160
size_t erase(int64_t key)
removes member with the key equivalent to key.
Definition value.hpp:1889
size_t erase(uint32_t key)
removes member with the key equivalent to key.
Definition value.hpp:1866
constexpr Value(double value)
constructs a real value.
Definition value.hpp:178
const Value & at(double key) const
returns a reference to the value mapped to key.
Definition value.hpp:1380
size_t erase(int32_t key)
removes member with the key equivalent to key.
Definition value.hpp:1843
~Value()=default
destroy the Value instance.
Value & insert(const Member &member)
insert element in the nested container.
Definition value.hpp:1773
Value(std::string &&value)
constructs a string value.
Definition value.hpp:214
Value & emplaceBack(Args &&... args)
constructs an element in place at the end of the nested container.
Definition value.hpp:1993
constexpr uint64_t getUint64() const
get variable held by value as a 64 bits unsigned integer value.
Definition value.hpp:882
int packRead(const char *document, size_t length)
deserialize a msgpack document.
Definition value.cpp:141
size_t erase(const char *key)
removes member with the key equivalent to key.
Definition value.hpp:1981
constexpr Value(int32_t value)
constructs an integer value.
Definition value.hpp:142
bool empty() const
check if the nested container is empty.
Definition value.hpp:1667
constexpr bool isNumber() const
check if the variable held by value is a number value.
Definition value.hpp:362
int jsonWrite(std::ostream &document, size_t indentation=0) const
serialize json data.
Definition value.cpp:123
const Value & at(bool key) const
returns a reference to the value mapped to key.
Definition value.hpp:1265
constexpr bool isNull() const
check if the variable held by value is a null value.
Definition value.hpp:299
Value(const char *value)
constructs a string value from a C-style string.
Definition value.hpp:187
constexpr uint16_t getUint16() const
get variable held by value as a 16 bits unsigned integer.
Definition value.hpp:636
constexpr bool isUint8() const
check if the variable held by value is a 8 bits unsigned integer value.
Definition value.hpp:447
constexpr int64_t getInt64() const
get variable held by value as a 64 bits integer value.
Definition value.hpp:825
int packWrite(std::ostream &document) const
serialize msgpack data.
Definition value.cpp:222
constexpr Value(uint64_t value)
constructs a 64 bits unsigned integer value.
Definition value.hpp:169
constexpr bool isInt8() const
check if the variable held by value is a 8 bits integer value.
Definition value.hpp:372
constexpr Array & getArray()
get variable held by value as an array.
Definition value.hpp:1023
constexpr std::size_t index() const noexcept
return the index of the alternative that is currently held by the variant.
Definition variant.hpp:624
constexpr T & set(Args &&... args)
set the variable type of the object identified by type and assign it a value.
Definition variant.hpp:456
constexpr T & get()
get the variable value of the object type identified by type.
Definition variant.hpp:505
const std::string key(65, 'a')
key.
Definition acceptor.hpp:32
bool operator==(const BasicLinkLayerEndpoint< Protocol > &a, const BasicLinkLayerEndpoint< Protocol > &b) noexcept
compare if endpoints are equal.
Definition endpoint.hpp:196
BasicMember< Value > Member
object member.
Definition value.hpp:83
std::vector< Value > Array
array.
Definition value.hpp:53
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
thread_local std::error_code lastError
last error.
Definition error.cpp:32
std::vector< Member > Object
object.
Definition value.hpp:86
std::strong_ordering operator<=>(const BasicLinkLayerEndpoint< Protocol > &a, const BasicLinkLayerEndpoint< Protocol > &b) noexcept
three-way compare endpoints.
Definition endpoint.hpp:208
Definition error.hpp:144
member.
Definition value.hpp:60
Type first
member key.
Definition value.hpp:76
Type second
member value.
Definition value.hpp:79
constexpr bool operator==(const BasicMember &other) const =default
compare members.
constexpr std::partial_ordering operator<=>(const BasicMember &other) const =default
three-way compare members.
#define JOIN_LIKELY(x)
Definition utils.hpp:50