join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_DATA_JSON_HPP
26#define JOIN_DATA_JSON_HPP
27
28// libjoin.
29#include <join/atodpow.hpp>
30#include <join/dtoa.hpp>
31#include <join/sax.hpp>
32
33// C++.
34#include <codecvt>
35#include <memory>
36#include <locale>
37
38namespace join
39{
40 namespace details
41 {
42 constexpr char digitPairs[201] = {
43 "00010203040506070809"
44 "10111213141516171819"
45 "20212223242526272829"
46 "30313233343536373839"
47 "40414243444546474849"
48 "50515253545556575859"
49 "60616263646566676869"
50 "70717273747576777879"
51 "80818283848586878889"
52 "90919293949596979899"};
53
55 {
56 uint8_t data[256];
57
58 constexpr UnescapedTable ()
59 : data{}
60 {
61 for (int i = 0; i < 32; ++i)
62 {
63 data[i] = 'u';
64 }
65 data[static_cast<unsigned char> ('\b')] = 'b';
66 data[static_cast<unsigned char> ('\t')] = 't';
67 data[static_cast<unsigned char> ('\n')] = 'n';
68 data[static_cast<unsigned char> ('\f')] = 'f';
69 data[static_cast<unsigned char> ('\r')] = 'r';
70 data[static_cast<unsigned char> ('"')] = '"';
71 data[static_cast<unsigned char> ('\\')] = '\\';
72 }
73 };
74
76 }
77
79 {
80 constexpr LocaleDelete () noexcept = default;
81
82 void operator() (locale_t loc) noexcept
83 {
84 freelocale (loc);
85 }
86 };
87
88 using LocalePtr = std::unique_ptr<std::remove_pointer_t<locale_t>, LocaleDelete>;
89
106
110 class JsonCategory : public std::error_category
111 {
112 public:
117 virtual const char* name () const noexcept;
118
124 virtual std::string message (int code) const;
125 };
126
131 const std::error_category& jsonCategory () noexcept;
132
138 std::error_code make_error_code (JsonErrc code) noexcept;
139
145 std::error_condition make_error_condition (JsonErrc code) noexcept;
146
151 {
152 public:
158 JsonWriter (std::ostream& document, size_t indentation = 0)
159 : StreamWriter (document)
160 , _indentation (indentation)
161 {
162 }
163
168 JsonWriter (const JsonWriter& other) = delete;
169
175 JsonWriter& operator= (const JsonWriter& other) = delete;
176
181 JsonWriter (JsonWriter&& other) = delete;
182
188 JsonWriter& operator= (JsonWriter&& other) = delete;
189
193 virtual ~JsonWriter () = default;
194
199 virtual int setNull () override
200 {
201 array ();
202 append4 ("null");
203 _first = false;
204 return 0;
205 }
206
212 virtual int setBool (bool value) override
213 {
214 array ();
215 if (value)
216 {
217 append4 ("true");
218 }
219 else
220 {
221 append5 ("false");
222 }
223 _first = false;
224 return 0;
225 }
226
232 virtual int setInt (int32_t value) override
233 {
234 array ();
235 writeInt (value);
236 _first = false;
237 return 0;
238 }
239
245 virtual int setUint (uint32_t value) override
246 {
247 array ();
248 writeUint (value);
249 _first = false;
250 return 0;
251 }
252
258 virtual int setInt64 (int64_t value) override
259 {
260 array ();
261 writeInt64 (value);
262 _first = false;
263 return 0;
264 }
265
271 virtual int setUint64 (uint64_t value) override
272 {
273 array ();
274 writeUint64 (value);
275 _first = false;
276 return 0;
277 }
278
284 virtual int setDouble (double value) override
285 {
286 array ();
287 uint64_t bits;
288 memcpy (&bits, &value, sizeof (bits));
289 const bool neg = (bits >> 63) != 0;
290 const uint64_t exp = (bits >> 52) & 0x7FFULL;
291 const uint64_t frac = bits & 0x000FFFFFFFFFFFFFULL;
292 if (exp != 0x7FFULL)
293 {
294 writeDouble (value);
295 }
296 else if (frac != 0)
297 {
298 if (neg)
299 {
300 append4 ("-NaN");
301 }
302 else
303 {
304 append3 ("NaN");
305 }
306 }
307 else
308 {
309 if (neg)
310 {
311 append4 ("-Inf");
312 }
313 else
314 {
315 append3 ("Inf");
316 }
317 }
318 _first = false;
319 return 0;
320 }
321
327 virtual int setString (const std::string& value) override
328 {
329 array ();
330 append ('"');
331 if (writeEscaped (value) == -1)
332 {
333 return -1;
334 }
335 append ('"');
336 _first = false;
337 return 0;
338 }
339
345 virtual int startArray ([[maybe_unused]] uint32_t size = 0) override
346 {
347 array ();
348 append ('[');
349 _tab.append (_indentation, ' ');
350 _first = true;
351 _stack.push (true);
352 return 0;
353 }
354
359 virtual int stopArray () override
360 {
361 _tab.erase (_tab.size () - _indentation);
362 if (!_first)
363 {
364 endLine ();
365 indent ();
366 }
367 append (']');
368 _first = false;
369 _stack.pop ();
370 return 0;
371 }
372
378 virtual int startObject ([[maybe_unused]] uint32_t size = 0) override
379 {
380 array ();
381 append ('{');
382 _tab.append (_indentation, ' ');
383 _first = true;
384 _stack.push (false);
385 return 0;
386 }
387
393 virtual int setKey (const Value& key) override
394 {
395 if (JOIN_UNLIKELY (!key.isString ()))
396 {
398 return -1;
399 }
400 comma ();
401 endLine ();
402 indent ();
403 append ('"');
404 if (writeEscaped (key.getString ()) == -1)
405 {
406 return -1;
407 }
408 append ('"');
409 append (':');
410 space ();
411 _first = true;
412 return 0;
413 }
414
419 virtual int stopObject () override
420 {
421 _tab.erase (_tab.size () - _indentation);
422 if (!_first)
423 {
424 endLine ();
425 indent ();
426 }
427 append ('}');
428 _first = false;
429 _stack.pop ();
430 return 0;
431 }
432
433 protected:
438 virtual void writeInt (int32_t value)
439 {
440 if (value == std::numeric_limits<int32_t>::min ())
441 {
442 append ('-');
443 writeUint64 (static_cast<uint64_t> (std::numeric_limits<int32_t>::max ()) + 1);
444 return;
445 }
446
447 if (value < 0)
448 {
449 append ('-');
450 writeUint64 (static_cast<uint64_t> (-value));
451 return;
452 }
453
454 writeUint64 (static_cast<uint64_t> (value));
455 }
456
461 virtual void writeUint (uint32_t value)
462 {
463 writeUint64 (static_cast<uint64_t> (value));
464 }
465
470 virtual void writeInt64 (int64_t value)
471 {
472 if (value == std::numeric_limits<int64_t>::min ())
473 {
474 append ('-');
475 writeUint64 (static_cast<uint64_t> (std::numeric_limits<int64_t>::max ()) + 1);
476 return;
477 }
478
479 if (value < 0)
480 {
481 append ('-');
482 writeUint64 (static_cast<uint64_t> (-value));
483 return;
484 }
485
486 writeUint64 (static_cast<uint64_t> (value));
487 }
488
493 virtual void writeUint64 (uint64_t value)
494 {
495 if (value == 0)
496 {
497 append ('0');
498 return;
499 }
500
501 char buffer[20];
502 char* ptr = buffer + 20;
503
504 while (value >= 100)
505 {
506 uint64_t r = value % 100;
507 value /= 100;
508 ptr -= 2;
509 std::memcpy (ptr, &details::digitPairs[r * 2], 2);
510 }
511
512 if (value >= 10)
513 {
514 ptr -= 2;
515 std::memcpy (ptr, &details::digitPairs[value * 2], 2);
516 }
517 else
518 {
519 *--ptr = '0' + static_cast<char> (value);
520 }
521
522 size_t length = (buffer + 20) - ptr;
523 append (ptr, length);
524 }
525
530 virtual void writeDouble (double value)
531 {
532 char buf[25];
533 char* end = join::dtoa (buf, value);
534 append (buf, end - buf);
535 }
536
544 virtual int utf8Codepoint (std::string::const_iterator& cur, std::string::const_iterator& end,
545 uint32_t& codepoint)
546 {
547 uint8_t u0 = static_cast<uint8_t> (*cur);
548 if (u0 < 0x80)
549 {
550 codepoint = u0;
551 return 0;
552 }
553
554 if (++cur == end)
555 {
556 return -1;
557 }
558
559 uint8_t u1 = static_cast<uint8_t> (*cur);
560 if (u0 < 0xE0)
561 {
562 codepoint = ((u0 & 0x1F) << 6) | (u1 & 0x3F);
563 if (codepoint < 0x80)
564 {
565 return -1;
566 }
567 return 0;
568 }
569
570 if (++cur == end)
571 {
572 return -1;
573 }
574
575 uint8_t u2 = static_cast<uint8_t> (*cur);
576 if (u0 < 0xF0)
577 {
578 codepoint = ((u0 & 0x0F) << 12) | ((u1 & 0x3F) << 6) | (u2 & 0x3F);
579 if ((codepoint > 0xD7FF) && (codepoint < 0xE000))
580 {
581 return -1;
582 }
583 if (codepoint < 0x800)
584 {
585 return -1;
586 }
587 return 0;
588 }
589
590 if (++cur == end)
591 {
592 return -1;
593 }
594
595 uint8_t u3 = static_cast<uint8_t> (*cur);
596 if (u0 < 0xF8)
597 {
598 codepoint = ((u0 & 0x07) << 18) | ((u1 & 0x3F) << 12) | ((u2 & 0x3F) << 6) | (u3 & 0x3F);
599 if (codepoint < 0x10000)
600 {
601 return -1;
602 }
603 return 0;
604 }
605
606 return -1;
607 }
608
614 virtual int writeEscaped (const std::string& value)
615 {
616 auto cur = value.cbegin ();
617 auto end = value.cend ();
618
619 while (cur != end)
620 {
621 auto beg = cur;
622
623 while (cur != end && details::unescapedLookup.data[static_cast<uint8_t> (*cur)] == 0)
624 {
625 ++cur;
626 }
627
628 if (cur != beg)
629 {
630 append (&(*beg), cur - beg);
631 }
632
633 if (cur == end)
634 {
635 break;
636 }
637
638 uint8_t ch = static_cast<uint8_t> (*cur);
639 uint8_t esc = details::unescapedLookup.data[ch];
640 if (esc == 'u')
641 {
642 uint32_t codepoint = 0;
643 char hex[5];
644
645 if (utf8Codepoint (cur, end, codepoint) == -1)
646 {
648 return -1;
649 }
650
651 if (codepoint <= 0xFFFF)
652 {
653 append2 ("\\u");
654 snprintf (hex, sizeof (hex), "%04x", uint16_t (codepoint));
655 append4 (hex);
656 }
657 else
658 {
659 codepoint -= 0x10000;
660 append2 ("\\u");
661 snprintf (hex, sizeof (hex), "%04x", uint16_t (0xD800 + ((codepoint >> 10) & 0x3FF)));
662 append4 (hex);
663 append2 ("\\u");
664 snprintf (hex, sizeof (hex), "%04x", uint16_t (0xDC00 + (codepoint & 0x3FF)));
665 append4 (hex);
666 }
667 }
668 else
669 {
670 char escapeSeq[2] = {'\\', static_cast<char> (esc)};
671 append2 (escapeSeq);
672 }
673
674 ++cur;
675 }
676
677 return 0;
678 }
679
683 inline void comma () noexcept
684 {
685 if (!_stack.empty () && !_first)
686 {
687 append (',');
688 }
689 }
690
694 inline void indent () noexcept
695 {
696 if (_indentation)
697 {
698 append (_tab.c_str (), _tab.size ());
699 }
700 }
701
705 inline void space () noexcept
706 {
707 if (_indentation)
708 {
709 append (' ');
710 }
711 }
712
716 inline void endLine () noexcept
717 {
718 if (_indentation)
719 {
720 append ('\n');
721 }
722 }
723
727 inline void array () noexcept
728 {
729 comma ();
730 if (!_stack.empty () && _stack.top ())
731 {
732 endLine ();
733 indent ();
734 }
735 }
736
738 std::stack<bool> _stack;
739
742
744 std::string _tab;
745
747 bool _first = true;
748 };
749
754 {
755 public:
760 JsonCanonicalizer (std::ostream& document)
761 : JsonWriter (document, 0)
762 {
763 }
764
769 JsonCanonicalizer (const JsonCanonicalizer& other) = delete;
770
777
783
790
794 virtual ~JsonCanonicalizer () = default;
795
801 virtual int setDouble (double value) override
802 {
803 array ();
804 if (std::isfinite (value))
805 {
806 if ((std::trunc (value) == value) && (value >= 0) &&
807 (value < static_cast<double> (std::numeric_limits<uint64_t>::max ())))
808 {
809 writeUint64 (static_cast<uint64_t> (value));
810 }
811 else if ((std::trunc (value) == value) &&
812 (value >= static_cast<double> (std::numeric_limits<int64_t>::min ())) &&
813 (value < static_cast<double> (std::numeric_limits<int64_t>::max ())))
814 {
815 writeInt64 (static_cast<int64_t> (value));
816 }
817 else
818 {
819 writeDouble (value);
820 }
821 }
822 else
823 {
824 append4 ("null");
825 }
826 _first = false;
827 return 0;
828 }
829
830 protected:
836 virtual int setObject (const Object& object) override
837 {
838 startObject (object.size ());
839 std::vector<const Member*> members;
840 std::transform (object.begin (), object.end (), std::back_inserter (members), [] (const Member& member) {
841 return &member;
842 });
843 std::sort (members.begin (), members.end (), [] (const Member* a, const Member* b) {
844#pragma GCC diagnostic push
845#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
846 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> cvt_utf8_utf16;
847#pragma GCC diagnostic pop
848 std::u16string wa = cvt_utf8_utf16.from_bytes (a->first.getString ().data ());
849 std::u16string wb = cvt_utf8_utf16.from_bytes (b->first.getString ().data ());
850 return wa < wb;
851 });
852 for (auto const& member : members)
853 {
854 setKey (member->first);
855 setValue (member->second);
856 }
857 stopObject ();
858 return 0;
859 }
860
865 virtual void writeDouble (double value) noexcept override
866 {
867 char beg[25];
868 char* end = join::dtoa (beg, value);
869 for (char* pos = beg; pos < end; ++pos)
870 {
871 append (*pos);
872 if ((*pos == 'e') && (*(pos + 1) != '-'))
873 {
874 append ('+');
875 }
876 }
877 }
878 };
879
884 {
885 None = 0,
886 ParseComments = 1L << 0,
889 };
890
898 {
899 return JsonReadMode (static_cast<int> (a) & static_cast<int> (b));
900 }
901
909 {
910 return JsonReadMode (static_cast<int> (a) | static_cast<int> (b));
911 }
912
919 constexpr const JsonReadMode& operator&= (JsonReadMode& a, JsonReadMode b) noexcept
920 {
921 return a = a & b;
922 }
923
930 constexpr const JsonReadMode& operator|= (JsonReadMode& a, JsonReadMode b) noexcept
931 {
932 return a = a | b;
933 }
934
939 {
940 public:
946 : StreamReader (root)
947 {
948 }
949
954 JsonReader (const JsonReader& other) = delete;
955
961 JsonReader& operator= (const JsonReader& other) = delete;
962
967 JsonReader (JsonReader&& other) = delete;
968
974 JsonReader& operator= (JsonReader&& other) = delete;
975
979 virtual ~JsonReader () = default;
980
987 template <JsonReadMode ReadMode = JsonReadMode::None>
988 int deserialize (const char* document, size_t length)
989 {
990 StringView in (document, length);
991 return read<ReadMode> (in);
992 }
993
1000 int deserialize (const char* document, size_t length) override
1001 {
1002 return deserialize<> (document, length);
1003 }
1004
1011 template <JsonReadMode ReadMode = JsonReadMode::None>
1012 int deserialize (const char* first, const char* last)
1013 {
1014 StringView in (first, last);
1015 return read<ReadMode> (in);
1016 }
1017
1024 int deserialize (const char* first, const char* last) override
1025 {
1026 return deserialize<> (first, last);
1027 }
1028
1034 template <JsonReadMode ReadMode = JsonReadMode::None>
1035 int deserialize (const std::string& document)
1036 {
1037 StringView in (document.c_str (), document.size ());
1038 return read<ReadMode> (in);
1039 }
1040
1046 int deserialize (const std::string& document) override
1047 {
1048 return deserialize<> (document);
1049 }
1050
1056 template <JsonReadMode ReadMode = JsonReadMode::None>
1057 int deserialize (std::stringstream& document)
1058 {
1059 StringStreamView in (document);
1060 return read<ReadMode> (in);
1061 }
1062
1068 int deserialize (std::stringstream& document) override
1069 {
1070 return deserialize<> (document);
1071 }
1072
1078 template <JsonReadMode ReadMode = JsonReadMode::None>
1079 int deserialize (std::istringstream& document)
1080 {
1081 StringStreamView in (document);
1082 return read<ReadMode> (in);
1083 }
1084
1090 int deserialize (std::istringstream& document) override
1091 {
1092 return deserialize<> (document);
1093 }
1094
1100 template <JsonReadMode ReadMode = JsonReadMode::None>
1101 int deserialize (std::fstream& document)
1102 {
1103 FileStreamView in (document);
1104 return read<ReadMode> (in);
1105 }
1106
1112 int deserialize (std::fstream& document) override
1113 {
1114 return deserialize<> (document);
1115 }
1116
1122 template <JsonReadMode ReadMode = JsonReadMode::None>
1123 int deserialize (std::ifstream& document)
1124 {
1125 FileStreamView in (document);
1126 return read<ReadMode> (in);
1127 }
1128
1134 int deserialize (std::ifstream& document) override
1135 {
1136 return deserialize<> (document);
1137 }
1138
1144 template <JsonReadMode ReadMode = JsonReadMode::None>
1145 int deserialize (std::iostream& document)
1146 {
1147 StreamView in (document);
1148 return read<ReadMode> (in);
1149 }
1150
1156 int deserialize (std::iostream& document) override
1157 {
1158 return deserialize<> (document);
1159 }
1160
1166 template <JsonReadMode ReadMode = JsonReadMode::None>
1167 int deserialize (std::istream& document)
1168 {
1169 StreamView in (document);
1170 return read<ReadMode> (in);
1171 }
1172
1178 int deserialize (std::istream& document) override
1179 {
1180 return deserialize<> (document);
1181 }
1182
1183 protected:
1189 template <JsonReadMode ReadMode, typename ViewType>
1190 int read (ViewType& document)
1191 {
1192 if (skipWhitespaces<ReadMode> (document) != 0)
1193 {
1194 return -1;
1195 }
1196
1197 if (readValue<ReadMode> (document) != 0)
1198 {
1199 return -1;
1200 }
1201
1202 if (ReadMode & JsonReadMode::StopParsingOnDone)
1203 {
1204 return 0;
1205 }
1206
1207 if (skipWhitespaces<ReadMode> (document) != 0)
1208 {
1209 return -1;
1210 }
1211
1212 if (document.peek () != std::char_traits<char>::eof ())
1213 {
1215 return -1;
1216 }
1217
1218 return 0;
1219 }
1220
1226 template <JsonReadMode ReadMode, typename ViewType>
1227 int readValue (ViewType& document)
1228 {
1229 int ch = document.peek ();
1230 switch (ch)
1231 {
1232 case '[':
1233 document.get ();
1234 return readArray<ReadMode> (document);
1235 case '{':
1236 document.get ();
1237 return readObject<ReadMode> (document);
1238 case '"':
1239 document.get ();
1240 return readString (document);
1241 case 'n':
1242 document.get ();
1243 return readNull (document);
1244 case 't':
1245 document.get ();
1246 return readTrue (document);
1247 case 'f':
1248 document.get ();
1249 return readFalse (document);
1250 default:
1251 return readNumber (document);
1252 }
1253 }
1254
1260 template <typename ViewType>
1261 int readNull (ViewType& document)
1262 {
1263 if (JOIN_UNLIKELY ((document.get () != 'u') || (document.get () != 'l') || (document.get () != 'l')))
1264 {
1266 return -1;
1267 }
1268
1269 return setNull ();
1270 }
1271
1277 template <typename ViewType>
1278 int readTrue (ViewType& document)
1279 {
1280 if (JOIN_UNLIKELY ((document.get () != 'r') || (document.get () != 'u') || (document.get () != 'e')))
1281 {
1283 return -1;
1284 }
1285
1286 return setBool (true);
1287 }
1288
1294 template <typename ViewType>
1295 int readFalse (ViewType& document)
1296 {
1297 if (JOIN_UNLIKELY ((document.get () != 'a') || (document.get () != 'l') || (document.get () != 's') ||
1298 (document.get () != 'e')))
1299 {
1301 return -1;
1302 }
1303
1304 return setBool (false);
1305 }
1306
1312 template <typename ViewType>
1313 int readInf (ViewType& document, bool negative)
1314 {
1315 if (JOIN_UNLIKELY (!(document.getIfNoCase ('n') && document.getIfNoCase ('f'))))
1316 {
1318 return -1;
1319 }
1320
1321 if (JOIN_UNLIKELY (document.getIfNoCase ('i') &&
1322 !(document.getIfNoCase ('n') && document.getIfNoCase ('i') &&
1323 document.getIfNoCase ('t') && document.getIfNoCase ('y'))))
1324 {
1326 return -1;
1327 }
1328
1329 return setDouble (negative ? -std::numeric_limits<double>::infinity ()
1330 : std::numeric_limits<double>::infinity ());
1331 }
1332
1338 template <typename ViewType>
1339 int readNan (ViewType& document, bool negative)
1340 {
1341 if (JOIN_UNLIKELY (!(document.getIfNoCase ('a') && document.getIfNoCase ('n'))))
1342 {
1344 return -1;
1345 }
1346
1347 return setDouble (negative ? -std::numeric_limits<double>::quiet_NaN ()
1348 : std::numeric_limits<double>::quiet_NaN ());
1349 }
1350
1360 inline void umul192 (uint64_t hi, uint64_t lo, uint64_t significand, uint64_t& high, uint64_t& middle,
1361 uint64_t& low) noexcept
1362 {
1363#if defined(__SIZEOF_INT128__)
1364 __uint128_t h = static_cast<__uint128_t> (hi) * significand;
1365 __uint128_t l = static_cast<__uint128_t> (lo) * significand;
1366 __uint128_t s = h + (l >> 64);
1367
1368 high = static_cast<uint64_t> (s >> 64);
1369 middle = static_cast<uint64_t> (s);
1370 low = static_cast<uint64_t> (l);
1371#else
1372 uint64_t hi_hi, hi_lo, lo_hi, lo_lo;
1373
1374 uint64_t m_lo = static_cast<uint32_t> (significand);
1375 uint64_t m_hi = significand >> 32;
1376 uint64_t p0 = (hi & 0xFFFFFFFF) * m_lo;
1377 uint64_t p1 = (hi >> 32) * m_lo;
1378 uint64_t p2 = (hi & 0xFFFFFFFF) * m_hi;
1379 uint64_t p3 = (hi >> 32) * m_hi;
1380 uint64_t carry = (p0 >> 32) + (p1 & 0xFFFFFFFF) + (p2 & 0xFFFFFFFF);
1381 hi_lo = (carry << 32) | (p0 & 0xFFFFFFFF);
1382 hi_hi = (carry >> 32) + (p1 >> 32) + (p2 >> 32) + p3;
1383
1384 p0 = (lo & 0xFFFFFFFF) * m_lo;
1385 p1 = (lo >> 32) * m_lo;
1386 p2 = (lo & 0xFFFFFFFF) * m_hi;
1387 p3 = (lo >> 32) * m_hi;
1388 carry = (p0 >> 32) + (p1 & 0xFFFFFFFF) + (p2 & 0xFFFFFFFF);
1389 lo_lo = (carry << 32) | (p0 & 0xFFFFFFFF);
1390 lo_hi = (carry >> 32) + (p1 >> 32) + (p2 >> 32) + p3;
1391
1392 low = lo_lo;
1393 middle = hi_lo + lo_hi;
1394 high = hi_hi + (middle < hi_lo ? 1 : 0);
1395#endif
1396 }
1397
1405 inline bool strtodFast (uint64_t significand, int64_t exponent, double& value)
1406 {
1407 constexpr double pow10[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
1408 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
1409
1410 value = static_cast<double> (significand);
1411
1412 if (JOIN_UNLIKELY ((exponent > 22) && (exponent < (22 + 16))))
1413 {
1414 value *= pow10[exponent - 22];
1415 exponent = 22;
1416 }
1417
1418 if (JOIN_LIKELY ((exponent >= -22) && (exponent <= 22) && (value <= 9007199254740991.0)))
1419 {
1420 value = (exponent < 0) ? (value / pow10[-exponent]) : (value * pow10[exponent]);
1421 return true;
1422 }
1423
1424 if (JOIN_UNLIKELY (value == 0.0))
1425 {
1426 return true;
1427 }
1428
1429 if (JOIN_UNLIKELY (exponent < -325 || exponent > 308))
1430 {
1431 return false;
1432 }
1433
1434 uint64_t high, middle, low;
1435 const details::Power& power = details::atodpow[exponent + 325];
1436 umul192 (power.hi, power.lo, significand, high, middle, low);
1437 int64_t exp = ((exponent * 217706) >> 16) + 1087;
1438
1439 int lz;
1440 if (high != 0)
1441 {
1442 lz = __builtin_clzll (high);
1443 exp -= lz;
1444 }
1445 else if (middle != 0)
1446 {
1447 lz = __builtin_clzll (middle);
1448 exp -= lz + 64;
1449 }
1450 else
1451 {
1452 return false; // LCOV_EXCL_LINE
1453 }
1454
1455 if (JOIN_UNLIKELY (exp <= 0 || exp >= 2047))
1456 {
1457 return false;
1458 }
1459
1460 if (high == 0)
1461 {
1462 high = middle << lz;
1463 middle = 0;
1464 }
1465 else if (lz != 0)
1466 {
1467 high = (high << lz) | (middle >> (64 - lz));
1468 middle <<= lz;
1469 }
1470
1471 middle |= (low != 0);
1472
1473 uint64_t mant = (high >> 11) & 0xFFFFFFFFFFFFF;
1474 uint64_t bits = (static_cast<uint64_t> (exp) << 52) | mant;
1475 uint64_t frac = high & 0x7FF;
1476
1477 bool roundUp = ((frac > 0x400) | ((frac == 0x400) && ((middle != 0) || (mant & 1))) |
1478 ((frac == 0x3FF) && ((middle != 0))));
1479
1480 bits += roundUp;
1481 std::memcpy (&value, &bits, sizeof (double));
1482
1483 return true;
1484 }
1485
1492 inline bool strtodSlow (const std::string& num, double& d)
1493 {
1494 static LocalePtr locale (newlocale (LC_ALL_MASK, "C", nullptr));
1495 char* end = nullptr;
1496 d = strtod_l (num.c_str (), &end, locale.get ());
1497 return (end && (*end == '\0'));
1498 }
1499
1505 template <typename ViewType>
1506 int readNumber (ViewType& document)
1507 {
1508 BufferingView<ViewType> view (document);
1509
1510 bool negative = view.getIf ('-');
1511
1512 uint64_t max64 = std::numeric_limits<uint64_t>::max ();
1513 if (negative)
1514 {
1515 max64 = static_cast<uint64_t> (std::numeric_limits<int64_t>::max ()) + 1;
1516 }
1517
1518 uint64_t digits = 0;
1519 bool isDouble = false;
1520 uint64_t u = 0;
1521
1522 if (JOIN_UNLIKELY (view.getIf ('0')))
1523 {
1524 if (JOIN_UNLIKELY (isDigit (view.peek ())))
1525 {
1527 return -1;
1528 }
1529 }
1530 else if (JOIN_LIKELY (isDigit (view.peek ())))
1531 {
1532 u = view.get () - '0';
1533 ++digits;
1534
1535 while (JOIN_LIKELY (isDigit (view.peek ())))
1536 {
1537 int digit = view.peek () - '0';
1538
1539 if (JOIN_UNLIKELY (u > ((max64 - digit) / 10)))
1540 {
1541 isDouble = true;
1542 break;
1543 }
1544
1545 u = (u * 10) + (view.get () - '0');
1546 ++digits;
1547 }
1548 }
1549 else if (JOIN_LIKELY (document.getIfNoCase ('i')))
1550 {
1551 return readInf (document, negative);
1552 }
1553 else if (JOIN_LIKELY (document.getIfNoCase ('n')))
1554 {
1555 return readNan (document, negative);
1556 }
1557 else
1558 {
1560 return -1;
1561 }
1562
1563 if (isDouble)
1564 {
1565 while (JOIN_LIKELY (isDigit (view.peek ())))
1566 {
1567 u = (u * 10) + (view.get () - '0');
1568 ++digits;
1569 }
1570 }
1571
1572 int64_t frac = 0;
1573 if (view.getIf ('.'))
1574 {
1575 isDouble = true;
1576
1577 while (JOIN_LIKELY (isDigit (view.peek ())))
1578 {
1579 u = (u * 10) + (view.get () - '0');
1580 if (JOIN_LIKELY (u || digits))
1581 {
1582 ++digits;
1583 }
1584 --frac;
1585 }
1586 }
1587
1588 int64_t exponent = 0;
1589 if (view.getIf ('e') || view.getIf ('E'))
1590 {
1591 isDouble = true;
1592
1593 bool negExp = false;
1594 if (isSign (view.peek ()))
1595 {
1596 negExp = (view.get () == '-');
1597 }
1598
1599 if (JOIN_LIKELY (isDigit (view.peek ())))
1600 {
1601 exponent = (view.get () - '0');
1602
1603 while (JOIN_LIKELY (isDigit (view.peek ())))
1604 {
1605 int digit = view.get () - '0';
1606
1607 if (JOIN_LIKELY (exponent <= ((std::numeric_limits<int>::max () - digit) / 10)))
1608 {
1609 exponent = (exponent * 10) + digit;
1610 }
1611 }
1612 }
1613 else
1614 {
1616 return -1;
1617 }
1618
1619 if (negExp)
1620 {
1621 exponent = -exponent;
1622 }
1623 }
1624
1625 if (!isDouble)
1626 {
1627 return negative ? setInt64 (-static_cast<int64_t> (u)) : setUint64 (u);
1628 }
1629
1630 if (JOIN_LIKELY (digits <= 19))
1631 {
1632 double d = 0.0;
1633 if (strtodFast (u, exponent + frac, d))
1634 {
1635 return setDouble (negative ? -d : d);
1636 }
1637 }
1638
1639 std::string number;
1640 view.snapshot (number);
1641
1642 double d = 0.0;
1643 if (strtodSlow (number, d))
1644 {
1645 return setDouble (d);
1646 }
1647
1649 return -1;
1650 }
1651
1658 template <typename ViewType>
1659 inline int readHex (ViewType& document, uint32_t& u)
1660 {
1661 for (int i = 0; i < 4; ++i)
1662 {
1663 char c = document.get ();
1664
1665 if (isDigit (c))
1666 {
1667 c -= '0';
1668 }
1669 else if (isUpperAlpha (c))
1670 {
1671 c = c - 'A' + 10;
1672 }
1673 else if (isLowerAlpha (c))
1674 {
1675 c = c - 'a' + 10;
1676 }
1677 else
1678 {
1680 return -1;
1681 }
1682
1683 u = (u << 4) + c;
1684 }
1685
1686 return 0;
1687 }
1688
1694 inline void encodeUtf8 (uint32_t codepoint, std::string& output)
1695 {
1696 if (codepoint < 0x80)
1697 {
1698 output.push_back (static_cast<char> (codepoint));
1699 }
1700 else if (codepoint < 0x800)
1701 {
1702 char buf[2];
1703 buf[0] = static_cast<char> (0xC0 | (codepoint >> 6));
1704 buf[1] = static_cast<char> (0x80 | (codepoint & 0x3F));
1705 output.append (buf, 2);
1706 }
1707 else if (codepoint < 0x10000)
1708 {
1709 char buf[3];
1710 buf[0] = static_cast<char> (0xE0 | (codepoint >> 12));
1711 buf[1] = static_cast<char> (0x80 | ((codepoint >> 6) & 0x3F));
1712 buf[2] = static_cast<char> (0x80 | (codepoint & 0x3F));
1713 output.append (buf, 3);
1714 }
1715 else
1716 {
1717 char buf[4];
1718 buf[0] = static_cast<char> (0xF0 | (codepoint >> 18));
1719 buf[1] = static_cast<char> (0x80 | ((codepoint >> 12) & 0x3F));
1720 buf[2] = static_cast<char> (0x80 | ((codepoint >> 6) & 0x3F));
1721 buf[3] = static_cast<char> (0x80 | (codepoint & 0x3F));
1722 output.append (buf, 4);
1723 }
1724 }
1725
1732 template <typename ViewType>
1733 inline int readUnicode (ViewType& document, std::string& output)
1734 {
1735 uint32_t u = 0;
1736
1737 if (readHex (document, u) == -1)
1738 {
1739 return -1;
1740 }
1741
1742 if (u >= 0xDC00 && u <= 0xDFFF)
1743 {
1745 return -1;
1746 }
1747
1748 if (u >= 0xD800 && u <= 0xDBFF)
1749 {
1750 if ((document.get () != '\\') || (document.get () != 'u'))
1751 {
1753 return -1;
1754 }
1755
1756 uint32_t v = 0;
1757
1758 if (readHex (document, v) == -1)
1759 {
1761 return -1;
1762 }
1763
1764 if (v < 0xDC00 || v > 0xDFFF)
1765 {
1767 return -1;
1768 }
1769
1770 u = 0x10000 + (((u - 0xD800) << 10) | (v - 0xDC00));
1771 }
1772
1773 if (u > 0x10FFFF)
1774 {
1776 return -1;
1777 }
1778
1779 encodeUtf8 (u, output);
1780
1781 return 0;
1782 }
1783
1790 template <typename ViewType>
1791 inline int readEscaped (ViewType& document, std::string& output)
1792 {
1793 int ch = document.get ();
1794 switch (ch)
1795 {
1796 case '"':
1797 output.push_back ('"');
1798 break;
1799 case '\\':
1800 output.push_back ('\\');
1801 break;
1802 case '/':
1803 output.push_back ('/');
1804 break;
1805 case 'b':
1806 output.push_back ('\b');
1807 break;
1808 case 'f':
1809 output.push_back ('\f');
1810 break;
1811 case 'n':
1812 output.push_back ('\n');
1813 break;
1814 case 'r':
1815 output.push_back ('\r');
1816 break;
1817 case 't':
1818 output.push_back ('\t');
1819 break;
1820 case 'u':
1821 return readUnicode (document, output);
1822 default:
1824 return -1;
1825 }
1826
1827 return 0;
1828 }
1829
1836 /*template <typename ViewType>
1837 inline int readUtf8 (ViewType& document, std::string& output) noexcept
1838 {
1839 size_t count = 0;
1840
1841 if (static_cast <uint8_t> (document.peek ()) < 0x80)
1842 {
1843 output.push_back (document.get ());
1844 }
1845 else if (static_cast <uint8_t> (document.peek ()) < 0xE0)
1846 {
1847 output.push_back (document.get ());
1848 count = 1;
1849 }
1850 else if (static_cast <uint8_t> (document.peek ()) < 0xF0)
1851 {
1852 output.push_back (document.get ());
1853 count = 2;
1854 }
1855 else if (static_cast <uint8_t> (document.peek ()) < 0xF8)
1856 {
1857 output.push_back (document.get ());
1858 count = 3;
1859 }
1860 else
1861 {
1862 join::lastError = make_error_code (JsonErrc::InvalidEncoding);
1863 return -1;
1864 }
1865
1866 for (size_t i = 0; i < count; ++i)
1867 {
1868 if (static_cast <uint8_t> (document.peek ()) < 0x80 || static_cast <uint8_t> (document.peek ()) > 0xBF)
1869 {
1870 join::lastError = make_error_code (JsonErrc::InvalidEncoding);
1871 return -1;
1872 }
1873
1874 output.push_back (document.get ());
1875 }
1876
1877 return 0;
1878 }*/
1879
1886 template <typename ViewType>
1887 int readString (ViewType& document, bool isKey = false)
1888 {
1889 thread_local Value output (in_place_index_t<Value::String>{});
1890 output.clear ();
1891 output.reserve (64);
1892
1893 for (;;)
1894 {
1895 document.readUntilEscaped (output.getString ());
1896 int ch = document.peek ();
1897
1898 if (ch == '"')
1899 {
1900 document.get ();
1901 break;
1902 }
1903
1904 if (ch == '\\')
1905 {
1906 document.get ();
1907 if (readEscaped (document, output.getString ()) == -1)
1908 {
1909 return -1;
1910 }
1911 continue;
1912 }
1913
1914 /*if (static_cast <uint8_t> (ch) > 0x7F)
1915 {
1916 if (readUtf8 (document, output) == -1)
1917 {
1918 return -1;
1919 }
1920 continue;
1921 }*/
1922
1923 if (ch < 0x20)
1924 {
1926 return -1;
1927 }
1928 }
1929
1930 return isKey ? setKey (output) : setString (output.getString ());
1931 }
1932
1938 template <JsonReadMode ReadMode, typename ViewType>
1939 int readArray (ViewType& document)
1940 {
1941 if (JOIN_UNLIKELY (startArray () == -1))
1942 {
1943 return -1;
1944 }
1945
1946 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
1947 {
1948 return -1;
1949 }
1950
1951 if (document.getIf (']'))
1952 {
1953 return stopArray ();
1954 }
1955
1956 for (;;)
1957 {
1958 if (JOIN_UNLIKELY (readValue<ReadMode> (document) == -1))
1959 {
1960 return -1;
1961 }
1962
1963 int ch = document.get ();
1964
1965 if (JOIN_UNLIKELY (details::whitespaceLookup.data[static_cast<unsigned char> (ch)]))
1966 {
1967 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
1968 {
1969 return -1;
1970 }
1971 ch = document.get ();
1972 }
1973
1974 if (JOIN_LIKELY (ch == ','))
1975 {
1976 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
1977 {
1978 return -1;
1979 }
1980 continue;
1981 }
1982
1983 if (JOIN_LIKELY (ch == ']'))
1984 {
1985 break;
1986 }
1987
1989 return -1;
1990 }
1991
1992 return stopArray ();
1993 }
1994
2000 template <JsonReadMode ReadMode, typename ViewType>
2001 int readObject (ViewType& document)
2002 {
2003 if (JOIN_UNLIKELY (startObject () == -1))
2004 {
2005 return -1;
2006 }
2007
2008 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2009 {
2010 return -1;
2011 }
2012
2013 if (document.getIf ('}'))
2014 {
2015 return stopObject ();
2016 }
2017
2018 for (;;)
2019 {
2020 if (JOIN_UNLIKELY (document.get () != '"'))
2021 {
2023 return -1;
2024 }
2025
2026 if (JOIN_UNLIKELY (readString (document, true) == -1))
2027 {
2028 return -1;
2029 }
2030
2031 if (document.peek () != ':')
2032 {
2033 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2034 {
2035 return -1;
2036 }
2037 }
2038
2039 if (JOIN_UNLIKELY (document.get () != ':'))
2040 {
2042 return -1;
2043 }
2044
2045 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2046 {
2047 return -1;
2048 }
2049
2050 if (JOIN_UNLIKELY (readValue<ReadMode> (document) == -1))
2051 {
2052 return -1;
2053 }
2054
2055 int ch = document.get ();
2056
2057 if (JOIN_UNLIKELY (details::whitespaceLookup.data[static_cast<unsigned char> (ch)]))
2058 {
2059 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2060 {
2061 return -1;
2062 }
2063 ch = document.get ();
2064 }
2065
2066 if (JOIN_LIKELY (ch == ','))
2067 {
2068 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2069 {
2070 return -1;
2071 }
2072 continue;
2073 }
2074
2075 if (JOIN_LIKELY (ch == '}'))
2076 {
2077 break;
2078 }
2079
2081 return -1;
2082 }
2083
2084 return stopObject ();
2085 }
2086
2092 template <JsonReadMode ReadMode, typename ViewType>
2093 inline typename std::enable_if<!(ReadMode & JsonReadMode::ParseComments), int>::type skipWhitespaces (
2094 ViewType& document)
2095 {
2096 return document.skipWhitespaces ();
2097 }
2098
2104 template <JsonReadMode ReadMode, typename ViewType>
2105 inline typename std::enable_if<(ReadMode & JsonReadMode::ParseComments), int>::type skipWhitespaces (
2106 ViewType& document)
2107 {
2108 return document.skipWhitespacesAndComments ();
2109 }
2110
2116 constexpr bool isUpperAlpha (char c) noexcept
2117 {
2118 return static_cast<unsigned char> (c - 'A') <= 5u;
2119 }
2120
2126 constexpr bool isLowerAlpha (char c) noexcept
2127 {
2128 return static_cast<unsigned char> (c - 'a') <= 5u;
2129 }
2130
2136 constexpr bool isDigit (char c) noexcept
2137 {
2138 return static_cast<unsigned char> (c - '0') <= 9u;
2139 }
2140
2146 constexpr bool isSign (char c) noexcept
2147 {
2148 return ((c ^ '+') & (c ^ '-')) == 0;
2149 }
2150 };
2151}
2152
2153namespace std
2154{
2156 template <>
2157 struct is_error_condition_enum<join::JsonErrc> : public true_type
2158 {
2159 };
2160}
2161
2162#endif
basic stream view.
Definition view.hpp:373
buffering view adapter
Definition view.hpp:646
JSON canonicalizer class.
Definition json.hpp:754
virtual void writeDouble(double value) noexcept override
write real value.
Definition json.hpp:865
JsonCanonicalizer(std::ostream &document)
create instance.
Definition json.hpp:760
JsonCanonicalizer & operator=(const JsonCanonicalizer &other)=delete
copy assignment.
JsonCanonicalizer(JsonCanonicalizer &&other)=delete
move constructor.
JsonCanonicalizer(const JsonCanonicalizer &other)=delete
copy constructor.
virtual int setObject(const Object &object) override
set object value.
Definition json.hpp:836
virtual ~JsonCanonicalizer()=default
destroy instance.
virtual int setDouble(double value) override
set real value.
Definition json.hpp:801
JSON error category.
Definition json.hpp:111
virtual std::string message(int code) const
translate JSON error code to human readable error string.
Definition json.cpp:44
virtual const char * name() const noexcept
get JSON error category name.
Definition json.cpp:35
JSON reader class.
Definition json.hpp:939
bool strtodSlow(const std::string &num, double &d)
convert double using strtod.
Definition json.hpp:1492
constexpr bool isSign(char c) noexcept
check if sign.
Definition json.hpp:2146
JsonReader(const JsonReader &other)=delete
copy constructor.
int readValue(ViewType &document)
parse a JSON value.
Definition json.hpp:1227
int deserialize(std::istringstream &document) override
deserialize a document.
Definition json.hpp:1090
constexpr bool isUpperAlpha(char c) noexcept
check if upper case alphanumeric character.
Definition json.hpp:2116
int deserialize(const char *first, const char *last) override
deserialize a document.
Definition json.hpp:1024
int readInf(ViewType &document, bool negative)
parse an infinity value.
Definition json.hpp:1313
int deserialize(const char *document, size_t length)
deserialize a document.
Definition json.hpp:988
int readUnicode(ViewType &document, std::string &output)
parse unicode.
Definition json.hpp:1733
int deserialize(std::stringstream &document) override
deserialize a document.
Definition json.hpp:1068
int readHex(ViewType &document, uint32_t &u)
parse a 4-digit hexadecimal sequence..
Definition json.hpp:1659
int readEscaped(ViewType &document, std::string &output)
parse escaped sequence.
Definition json.hpp:1791
int deserialize(const char *document, size_t length) override
deserialize a document.
Definition json.hpp:1000
int readString(ViewType &document, bool isKey=false)
parse UTF8.
Definition json.hpp:1887
std::enable_if<!(ReadMode &JsonReadMode::ParseComments), int >::type skipWhitespaces(ViewType &document)
skip whitespaces.
Definition json.hpp:2093
int deserialize(const char *first, const char *last)
deserialize a document.
Definition json.hpp:1012
JsonReader(JsonReader &&other)=delete
move constructor.
int readObject(ViewType &document)
parse an object value.
Definition json.hpp:2001
virtual ~JsonReader()=default
destroy instance.
void umul192(uint64_t hi, uint64_t lo, uint64_t significand, uint64_t &high, uint64_t &middle, uint64_t &low) noexcept
multiply 192 bits unsigned integer by 64 bits unsigned integer.
Definition json.hpp:1360
int read(ViewType &document)
parse a document.
Definition json.hpp:1190
int deserialize(std::iostream &document)
deserialize a document.
Definition json.hpp:1145
int deserialize(std::fstream &document)
deserialize a document.
Definition json.hpp:1101
int readNan(ViewType &document, bool negative)
parse a nan value.
Definition json.hpp:1339
void encodeUtf8(uint32_t codepoint, std::string &output)
encode a Unicode codepoint to UTF-8.
Definition json.hpp:1694
JsonReader & operator=(const JsonReader &other)=delete
copy assignment.
int readNull(ViewType &document)
parse a null value.
Definition json.hpp:1261
int deserialize(std::istream &document) override
deserialize a document.
Definition json.hpp:1178
int deserialize(const std::string &document) override
deserialize a document.
Definition json.hpp:1046
int deserialize(std::ifstream &document) override
deserialize a document.
Definition json.hpp:1134
constexpr bool isLowerAlpha(char c) noexcept
check if lower case alphanumeric character.
Definition json.hpp:2126
int deserialize(std::iostream &document) override
deserialize a document.
Definition json.hpp:1156
constexpr bool isDigit(char c) noexcept
check if digit.
Definition json.hpp:2136
int deserialize(const std::string &document)
deserialize a document.
Definition json.hpp:1035
JsonReader(Value &root)
default constructor.
Definition json.hpp:945
int deserialize(std::istringstream &document)
deserialize a document.
Definition json.hpp:1079
int readNumber(ViewType &document)
parse a number value.
Definition json.hpp:1506
int readArray(ViewType &document)
parse an array value.
Definition json.hpp:1939
int deserialize(std::istream &document)
deserialize a document.
Definition json.hpp:1167
int deserialize(std::fstream &document) override
deserialize a document.
Definition json.hpp:1112
int readFalse(ViewType &document)
parse a false value.
Definition json.hpp:1295
int readTrue(ViewType &document)
parse a true value.
Definition json.hpp:1278
int deserialize(std::ifstream &document)
deserialize a document.
Definition json.hpp:1123
int deserialize(std::stringstream &document)
deserialize a document.
Definition json.hpp:1057
bool strtodFast(uint64_t significand, int64_t exponent, double &value)
convert double using fast path.
Definition json.hpp:1405
JSON writer class.
Definition json.hpp:151
std::string _tab
tabulation.
Definition json.hpp:744
virtual void writeUint(uint32_t value)
write unsigned integer value.
Definition json.hpp:461
void indent() noexcept
write indentation.
Definition json.hpp:694
size_t _indentation
indentation.
Definition json.hpp:741
virtual int utf8Codepoint(std::string::const_iterator &cur, std::string::const_iterator &end, uint32_t &codepoint)
get UTF8 codepoint.
Definition json.hpp:544
virtual int setInt(int32_t value) override
set integer value.
Definition json.hpp:232
virtual int setInt64(int64_t value) override
set 64 bits integer value.
Definition json.hpp:258
virtual void writeDouble(double value)
write real value.
Definition json.hpp:530
JsonWriter(std::ostream &document, size_t indentation=0)
create instance.
Definition json.hpp:158
virtual int stopArray() override
stop array.
Definition json.hpp:359
virtual ~JsonWriter()=default
destroy instance.
virtual int startArray(uint32_t size=0) override
start array.
Definition json.hpp:345
virtual void writeInt(int32_t value)
write integer value.
Definition json.hpp:438
void comma() noexcept
write comma.
Definition json.hpp:683
virtual int stopObject() override
stop object.
Definition json.hpp:419
virtual void writeUint64(uint64_t value)
write 64 bits unsigned integer value.
Definition json.hpp:493
void array() noexcept
add comma, go to line and indent if in array.
Definition json.hpp:727
virtual int setUint(uint32_t value) override
set unsigned integer value.
Definition json.hpp:245
virtual void writeInt64(int64_t value)
write 64 bits integer value.
Definition json.hpp:470
virtual int writeEscaped(const std::string &value)
escape string value.
Definition json.hpp:614
virtual int setDouble(double value) override
set real value.
Definition json.hpp:284
virtual int setKey(const Value &key) override
set key.
Definition json.hpp:393
virtual int startObject(uint32_t size=0) override
start object.
Definition json.hpp:378
std::stack< bool > _stack
array stack.
Definition json.hpp:738
virtual int setNull() override
set null value.
Definition json.hpp:199
JsonWriter(const JsonWriter &other)=delete
copy constructor.
JsonWriter(JsonWriter &&other)=delete
move constructor.
virtual int setUint64(uint64_t value) override
set unsigned 64 bits integer value.
Definition json.hpp:271
virtual int setString(const std::string &value) override
set string value.
Definition json.hpp:327
void space() noexcept
write space.
Definition json.hpp:705
bool _first
is first element.
Definition json.hpp:747
void endLine() noexcept
write end of line.
Definition json.hpp:716
virtual int setBool(bool value) override
set boolean value.
Definition json.hpp:212
stream deserializer abstract class.
Definition sax.hpp:461
virtual int stopObject() override
stop object.
Definition sax.hpp:752
virtual int startArray(uint32_t size=0) override
start array.
Definition sax.hpp:654
virtual int setInt64(int64_t value) override
set 64 bits integer value.
Definition sax.hpp:614
virtual int setNull() override
set null value.
Definition sax.hpp:574
virtual int setUint64(uint64_t value) override
set unsigned 64 bits integer value.
Definition sax.hpp:624
virtual int setKey(const Value &key) override
set key.
Definition sax.hpp:742
virtual int startObject(uint32_t size=0) override
start object.
Definition sax.hpp:705
virtual int setBool(bool value) override
set boolean value.
Definition sax.hpp:584
virtual int stopArray() override
stop array.
Definition sax.hpp:690
virtual int setDouble(double value) override
set real value.
Definition sax.hpp:634
virtual int setString(const std::string &value) override
set string value.
Definition sax.hpp:644
stream serializer abstract class.
Definition sax.hpp:243
int setValue(const Value &value)
set value.
Definition sax.hpp:300
void append(char data) noexcept
append character to output stream in batch.
Definition sax.hpp:391
void append4(const char *data) noexcept
append 4-character literal to output stream in batch.
Definition sax.hpp:421
string view.
Definition view.hpp:83
value class.
Definition value.hpp:63
void clear()
erases all elements in the nested container.
Definition value.hpp:1186
const std::string key(65, 'a')
key.
constexpr UnescapedTable unescapedLookup
Definition json.hpp:75
constexpr char digitPairs[201]
Definition json.hpp:42
constexpr WhitespaceTable whitespaceLookup
Definition view.hpp:76
constexpr Power atodpow[]
Definition atodpow.hpp:40
Definition acceptor.hpp:32
constexpr const JsonReadMode & operator&=(JsonReadMode &a, JsonReadMode b) noexcept
perform binary AND on JsonReadMode.
Definition json.hpp:919
IpAddress operator&(const IpAddress &a, const IpAddress &b)
perform AND operation on IP address.
Definition ip_address.cpp:1665
char * dtoa(char *buffer, double value) noexcept
double to string conversion.
Definition dtoa.hpp:216
const std::error_category & jsonCategory() noexcept
get error category.
Definition json.cpp:77
std::pair< Value, Value > Member
object member.
Definition value.hpp:53
constexpr const JsonReadMode & operator|=(JsonReadMode &a, JsonReadMode b) noexcept
perform binary OR on JsonReadMode.
Definition json.hpp:930
JsonReadMode
JSON deserialization mode.
Definition json.hpp:884
@ StopParsingOnDone
Definition json.hpp:888
@ ParseComments
Definition json.hpp:886
@ ValidateEncoding
Definition json.hpp:887
@ None
Definition json.hpp:885
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
IpAddress operator|(const IpAddress &a, const IpAddress &b)
perform OR operation on IP address.
Definition ip_address.cpp:1692
thread_local std::error_code lastError
last error.
Definition error.cpp:32
std::vector< Member > Object
object.
Definition value.hpp:56
std::error_condition make_error_condition(join::Errc code) noexcept
Create an std::error_condition object.
Definition error.cpp:204
std::unique_ptr< std::remove_pointer_t< locale_t >, LocaleDelete > LocalePtr
Definition json.hpp:88
JsonErrc
JSON error codes.
Definition json.hpp:94
Definition error.hpp:144
Definition json.hpp:79
constexpr LocaleDelete() noexcept=default
Definition atodpow.hpp:35
uint64_t hi
Definition atodpow.hpp:36
uint64_t lo
Definition atodpow.hpp:37
Definition json.hpp:55
uint8_t data[256]
Definition json.hpp:56
constexpr UnescapedTable()
Definition json.hpp:58
disambiguation tag to indicate that the contained object should be constructed in-place.
Definition traits.hpp:57
#define JOIN_LIKELY(x)
Definition utils.hpp:45
#define JOIN_UNLIKELY(x)
Definition utils.hpp:46