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['\b'] = 'b';
66 data['\t'] = 't';
67 data['\n'] = 'n';
68 data['\f'] = 'f';
69 data['\r'] = 'r';
70 data['"'] = '"';
71 data['\\'] = '\\';
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 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> cvt_utf8_utf16;
845 std::u16string wa = cvt_utf8_utf16.from_bytes (a->first.getString ().data ());
846 std::u16string wb = cvt_utf8_utf16.from_bytes (b->first.getString ().data ());
847 return wa < wb;
848 });
849 for (auto const& member : members)
850 {
851 setKey (member->first);
852 setValue (member->second);
853 }
854 stopObject ();
855 return 0;
856 }
857
862 virtual void writeDouble (double value) noexcept override
863 {
864 char beg[25];
865 char* end = join::dtoa (beg, value);
866 for (char* pos = beg; pos < end; ++pos)
867 {
868 append (*pos);
869 if ((*pos == 'e') && (*(pos + 1) != '-'))
870 {
871 append ('+');
872 }
873 }
874 }
875 };
876
881 {
882 None = 0,
883 ParseComments = 1L << 0,
886 };
887
895 {
896 return JsonReadMode (static_cast<int> (a) & static_cast<int> (b));
897 }
898
906 {
907 return JsonReadMode (static_cast<int> (a) | static_cast<int> (b));
908 }
909
916 constexpr const JsonReadMode& operator&= (JsonReadMode& a, JsonReadMode b) noexcept
917 {
918 return a = a & b;
919 }
920
927 constexpr const JsonReadMode& operator|= (JsonReadMode& a, JsonReadMode b) noexcept
928 {
929 return a = a | b;
930 }
931
936 {
937 public:
943 : StreamReader (root)
944 {
945 }
946
951 JsonReader (const JsonReader& other) = delete;
952
958 JsonReader& operator= (const JsonReader& other) = delete;
959
964 JsonReader (JsonReader&& other) = delete;
965
971 JsonReader& operator= (JsonReader&& other) = delete;
972
976 virtual ~JsonReader () = default;
977
984 template <JsonReadMode ReadMode = JsonReadMode::None>
985 int deserialize (const char* document, size_t length)
986 {
987 StringView in (document, length);
988 return read<ReadMode> (in);
989 }
990
997 int deserialize (const char* document, size_t length) override
998 {
999 return deserialize<> (document, length);
1000 }
1001
1008 template <JsonReadMode ReadMode = JsonReadMode::None>
1009 int deserialize (const char* first, const char* last)
1010 {
1011 StringView in (first, last);
1012 return read<ReadMode> (in);
1013 }
1014
1021 int deserialize (const char* first, const char* last) override
1022 {
1023 return deserialize<> (first, last);
1024 }
1025
1031 template <JsonReadMode ReadMode = JsonReadMode::None>
1032 int deserialize (const std::string& document)
1033 {
1034 StringView in (document.c_str (), document.size ());
1035 return read<ReadMode> (in);
1036 }
1037
1043 int deserialize (const std::string& document) override
1044 {
1045 return deserialize<> (document);
1046 }
1047
1053 template <JsonReadMode ReadMode = JsonReadMode::None>
1054 int deserialize (std::stringstream& document)
1055 {
1056 StringStreamView in (document);
1057 return read<ReadMode> (in);
1058 }
1059
1065 int deserialize (std::stringstream& document) override
1066 {
1067 return deserialize<> (document);
1068 }
1069
1075 template <JsonReadMode ReadMode = JsonReadMode::None>
1076 int deserialize (std::istringstream& document)
1077 {
1078 StringStreamView in (document);
1079 return read<ReadMode> (in);
1080 }
1081
1087 int deserialize (std::istringstream& document) override
1088 {
1089 return deserialize<> (document);
1090 }
1091
1097 template <JsonReadMode ReadMode = JsonReadMode::None>
1098 int deserialize (std::fstream& document)
1099 {
1100 FileStreamView in (document);
1101 return read<ReadMode> (in);
1102 }
1103
1109 int deserialize (std::fstream& document) override
1110 {
1111 return deserialize<> (document);
1112 }
1113
1119 template <JsonReadMode ReadMode = JsonReadMode::None>
1120 int deserialize (std::ifstream& document)
1121 {
1122 FileStreamView in (document);
1123 return read<ReadMode> (in);
1124 }
1125
1131 int deserialize (std::ifstream& document) override
1132 {
1133 return deserialize<> (document);
1134 }
1135
1141 template <JsonReadMode ReadMode = JsonReadMode::None>
1142 int deserialize (std::iostream& document)
1143 {
1144 StreamView in (document);
1145 return read<ReadMode> (in);
1146 }
1147
1153 int deserialize (std::iostream& document) override
1154 {
1155 return deserialize<> (document);
1156 }
1157
1163 template <JsonReadMode ReadMode = JsonReadMode::None>
1164 int deserialize (std::istream& document)
1165 {
1166 StreamView in (document);
1167 return read<ReadMode> (in);
1168 }
1169
1175 int deserialize (std::istream& document) override
1176 {
1177 return deserialize<> (document);
1178 }
1179
1180 protected:
1186 template <JsonReadMode ReadMode, typename ViewType>
1187 int read (ViewType& document)
1188 {
1189 if (skipWhitespaces<ReadMode> (document) != 0)
1190 {
1191 return -1;
1192 }
1193
1194 if (readValue<ReadMode> (document) != 0)
1195 {
1196 return -1;
1197 }
1198
1199 if (ReadMode & JsonReadMode::StopParsingOnDone)
1200 {
1201 return 0;
1202 }
1203
1204 if (skipWhitespaces<ReadMode> (document) != 0)
1205 {
1206 return -1;
1207 }
1208
1209 if (document.peek () != std::char_traits<char>::eof ())
1210 {
1212 return -1;
1213 }
1214
1215 return 0;
1216 }
1217
1223 template <JsonReadMode ReadMode, typename ViewType>
1224 int readValue (ViewType& document)
1225 {
1226 int ch = document.peek ();
1227 switch (ch)
1228 {
1229 case '[':
1230 document.get ();
1231 return readArray<ReadMode> (document);
1232 case '{':
1233 document.get ();
1234 return readObject<ReadMode> (document);
1235 case '"':
1236 document.get ();
1237 return readString (document);
1238 case 'n':
1239 document.get ();
1240 return readNull (document);
1241 case 't':
1242 document.get ();
1243 return readTrue (document);
1244 case 'f':
1245 document.get ();
1246 return readFalse (document);
1247 default:
1248 return readNumber (document);
1249 }
1250 }
1251
1257 template <typename ViewType>
1258 int readNull (ViewType& document)
1259 {
1260 if (JOIN_UNLIKELY ((document.get () != 'u') || (document.get () != 'l') || (document.get () != 'l')))
1261 {
1263 return -1;
1264 }
1265
1266 return setNull ();
1267 }
1268
1274 template <typename ViewType>
1275 int readTrue (ViewType& document)
1276 {
1277 if (JOIN_UNLIKELY ((document.get () != 'r') || (document.get () != 'u') || (document.get () != 'e')))
1278 {
1280 return -1;
1281 }
1282
1283 return setBool (true);
1284 }
1285
1291 template <typename ViewType>
1292 int readFalse (ViewType& document)
1293 {
1294 if (JOIN_UNLIKELY ((document.get () != 'a') || (document.get () != 'l') || (document.get () != 's') ||
1295 (document.get () != 'e')))
1296 {
1298 return -1;
1299 }
1300
1301 return setBool (false);
1302 }
1303
1309 template <typename ViewType>
1310 int readInf (ViewType& document, bool negative)
1311 {
1312 if (JOIN_UNLIKELY (!(document.getIfNoCase ('n') && document.getIfNoCase ('f'))))
1313 {
1315 return -1;
1316 }
1317
1318 if (JOIN_UNLIKELY (document.getIfNoCase ('i') &&
1319 !(document.getIfNoCase ('n') && document.getIfNoCase ('i') &&
1320 document.getIfNoCase ('t') && document.getIfNoCase ('y'))))
1321 {
1323 return -1;
1324 }
1325
1326 return setDouble (negative ? -std::numeric_limits<double>::infinity ()
1327 : std::numeric_limits<double>::infinity ());
1328 }
1329
1335 template <typename ViewType>
1336 int readNan (ViewType& document, bool negative)
1337 {
1338 if (JOIN_UNLIKELY (!(document.getIfNoCase ('a') && document.getIfNoCase ('n'))))
1339 {
1341 return -1;
1342 }
1343
1344 return setDouble (negative ? -std::numeric_limits<double>::quiet_NaN ()
1345 : std::numeric_limits<double>::quiet_NaN ());
1346 }
1347
1357 inline void umul192 (uint64_t hi, uint64_t lo, uint64_t significand, uint64_t& high, uint64_t& middle,
1358 uint64_t& low) noexcept
1359 {
1360#if defined(__SIZEOF_INT128__)
1361 __uint128_t h = static_cast<__uint128_t> (hi) * significand;
1362 __uint128_t l = static_cast<__uint128_t> (lo) * significand;
1363 __uint128_t s = h + (l >> 64);
1364
1365 high = static_cast<uint64_t> (s >> 64);
1366 middle = static_cast<uint64_t> (s);
1367 low = static_cast<uint64_t> (l);
1368#else
1369 uint64_t hi_hi, hi_lo, lo_hi, lo_lo;
1370
1371 uint64_t m_lo = static_cast<uint32_t> (significand);
1372 uint64_t m_hi = significand >> 32;
1373 uint64_t p0 = (hi & 0xFFFFFFFF) * m_lo;
1374 uint64_t p1 = (hi >> 32) * m_lo;
1375 uint64_t p2 = (hi & 0xFFFFFFFF) * m_hi;
1376 uint64_t p3 = (hi >> 32) * m_hi;
1377 uint64_t carry = (p0 >> 32) + (p1 & 0xFFFFFFFF) + (p2 & 0xFFFFFFFF);
1378 hi_lo = (carry << 32) | (p0 & 0xFFFFFFFF);
1379 hi_hi = (carry >> 32) + (p1 >> 32) + (p2 >> 32) + p3;
1380
1381 p0 = (lo & 0xFFFFFFFF) * m_lo;
1382 p1 = (lo >> 32) * m_lo;
1383 p2 = (lo & 0xFFFFFFFF) * m_hi;
1384 p3 = (lo >> 32) * m_hi;
1385 carry = (p0 >> 32) + (p1 & 0xFFFFFFFF) + (p2 & 0xFFFFFFFF);
1386 lo_lo = (carry << 32) | (p0 & 0xFFFFFFFF);
1387 lo_hi = (carry >> 32) + (p1 >> 32) + (p2 >> 32) + p3;
1388
1389 low = lo_lo;
1390 middle = hi_lo + lo_hi;
1391 high = hi_hi + (middle < hi_lo ? 1 : 0);
1392#endif
1393 }
1394
1402 inline bool strtodFast (uint64_t significand, int64_t exponent, double& value)
1403 {
1404 constexpr double pow10[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
1405 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
1406
1407 value = static_cast<double> (significand);
1408
1409 if (JOIN_UNLIKELY ((exponent > 22) && (exponent < (22 + 16))))
1410 {
1411 value *= pow10[exponent - 22];
1412 exponent = 22;
1413 }
1414
1415 if (JOIN_LIKELY ((exponent >= -22) && (exponent <= 22) && (value <= 9007199254740991.0)))
1416 {
1417 value = (exponent < 0) ? (value / pow10[-exponent]) : (value * pow10[exponent]);
1418 return true;
1419 }
1420
1421 if (JOIN_UNLIKELY (value == 0.0))
1422 {
1423 return true;
1424 }
1425
1426 if (JOIN_UNLIKELY (exponent < -325 || exponent > 308))
1427 {
1428 return false;
1429 }
1430
1431 uint64_t high, middle, low;
1432 const details::Power& power = details::atodpow[exponent + 325];
1433 umul192 (power.hi, power.lo, significand, high, middle, low);
1434 int64_t exp = ((exponent * 217706) >> 16) + 1087;
1435
1436 int lz;
1437 if (high != 0)
1438 {
1439 lz = __builtin_clzll (high);
1440 exp -= lz;
1441 }
1442 else if (middle != 0)
1443 {
1444 lz = __builtin_clzll (middle);
1445 exp -= lz + 64;
1446 }
1447 else
1448 {
1449 return false; // LCOV_EXCL_LINE
1450 }
1451
1452 if (JOIN_UNLIKELY (exp <= 0 || exp >= 2047))
1453 {
1454 return false;
1455 }
1456
1457 if (high == 0)
1458 {
1459 high = middle << lz;
1460 middle = 0;
1461 }
1462 else if (lz != 0)
1463 {
1464 high = (high << lz) | (middle >> (64 - lz));
1465 middle <<= lz;
1466 }
1467
1468 middle |= (low != 0);
1469
1470 uint64_t mant = (high >> 11) & 0xFFFFFFFFFFFFF;
1471 uint64_t bits = (static_cast<uint64_t> (exp) << 52) | mant;
1472 uint64_t frac = high & 0x7FF;
1473
1474 bool roundUp = ((frac > 0x400) | ((frac == 0x400) && ((middle != 0) || (mant & 1))) |
1475 ((frac == 0x3FF) && ((middle != 0))));
1476
1477 bits += roundUp;
1478 std::memcpy (&value, &bits, sizeof (double));
1479
1480 return true;
1481 }
1482
1489 inline bool strtodSlow (const std::string& num, double& d)
1490 {
1491 static LocalePtr locale (newlocale (LC_ALL_MASK, "C", nullptr));
1492 char* end = nullptr;
1493 d = strtod_l (num.c_str (), &end, locale.get ());
1494 return (end && (*end == '\0'));
1495 }
1496
1502 template <typename ViewType>
1503 int readNumber (ViewType& document)
1504 {
1505 BufferingView<ViewType> view (document);
1506
1507 bool negative = view.getIf ('-');
1508
1509 uint64_t max64 = std::numeric_limits<uint64_t>::max ();
1510 if (negative)
1511 {
1512 max64 = static_cast<uint64_t> (std::numeric_limits<int64_t>::max ()) + 1;
1513 }
1514
1515 uint64_t digits = 0;
1516 bool isDouble = false;
1517 uint64_t u = 0;
1518
1519 if (JOIN_UNLIKELY (view.getIf ('0')))
1520 {
1521 if (JOIN_UNLIKELY (isDigit (view.peek ())))
1522 {
1524 return -1;
1525 }
1526 }
1527 else if (JOIN_LIKELY (isDigit (view.peek ())))
1528 {
1529 u = view.get () - '0';
1530 ++digits;
1531
1532 while (JOIN_LIKELY (isDigit (view.peek ())))
1533 {
1534 int digit = view.peek () - '0';
1535
1536 if (JOIN_UNLIKELY (u > ((max64 - digit) / 10)))
1537 {
1538 isDouble = true;
1539 break;
1540 }
1541
1542 u = (u * 10) + (view.get () - '0');
1543 ++digits;
1544 }
1545 }
1546 else if (JOIN_LIKELY (document.getIfNoCase ('i')))
1547 {
1548 return readInf (document, negative);
1549 }
1550 else if (JOIN_LIKELY (document.getIfNoCase ('n')))
1551 {
1552 return readNan (document, negative);
1553 }
1554 else
1555 {
1557 return -1;
1558 }
1559
1560 if (isDouble)
1561 {
1562 while (JOIN_LIKELY (isDigit (view.peek ())))
1563 {
1564 u = (u * 10) + (view.get () - '0');
1565 ++digits;
1566 }
1567 }
1568
1569 int64_t frac = 0;
1570 if (view.getIf ('.'))
1571 {
1572 isDouble = true;
1573
1574 while (JOIN_LIKELY (isDigit (view.peek ())))
1575 {
1576 u = (u * 10) + (view.get () - '0');
1577 if (JOIN_LIKELY (u || digits))
1578 {
1579 ++digits;
1580 }
1581 --frac;
1582 }
1583 }
1584
1585 int64_t exponent = 0;
1586 if (view.getIf ('e') || view.getIf ('E'))
1587 {
1588 isDouble = true;
1589
1590 bool negExp = false;
1591 if (isSign (view.peek ()))
1592 {
1593 negExp = (view.get () == '-');
1594 }
1595
1596 if (JOIN_LIKELY (isDigit (view.peek ())))
1597 {
1598 exponent = (view.get () - '0');
1599
1600 while (JOIN_LIKELY (isDigit (view.peek ())))
1601 {
1602 int digit = view.get () - '0';
1603
1604 if (JOIN_LIKELY (exponent <= ((std::numeric_limits<int>::max () - digit) / 10)))
1605 {
1606 exponent = (exponent * 10) + digit;
1607 }
1608 }
1609 }
1610 else
1611 {
1613 return -1;
1614 }
1615
1616 if (negExp)
1617 {
1618 exponent = -exponent;
1619 }
1620 }
1621
1622 if (!isDouble)
1623 {
1624 return negative ? setInt64 (-static_cast<int64_t> (u)) : setUint64 (u);
1625 }
1626
1627 if (JOIN_LIKELY (digits <= 19))
1628 {
1629 double d = 0.0;
1630 if (strtodFast (u, exponent + frac, d))
1631 {
1632 return setDouble (negative ? -d : d);
1633 }
1634 }
1635
1636 std::string number;
1637 view.snapshot (number);
1638
1639 double d = 0.0;
1640 if (strtodSlow (number, d))
1641 {
1642 return setDouble (d);
1643 }
1644
1646 return -1;
1647 }
1648
1655 template <typename ViewType>
1656 inline int readHex (ViewType& document, uint32_t& u)
1657 {
1658 for (int i = 0; i < 4; ++i)
1659 {
1660 char c = document.get ();
1661
1662 if (isDigit (c))
1663 {
1664 c -= '0';
1665 }
1666 else if (isUpperAlpha (c))
1667 {
1668 c = c - 'A' + 10;
1669 }
1670 else if (isLowerAlpha (c))
1671 {
1672 c = c - 'a' + 10;
1673 }
1674 else
1675 {
1677 return -1;
1678 }
1679
1680 u = (u << 4) + c;
1681 }
1682
1683 return 0;
1684 }
1685
1691 inline void encodeUtf8 (uint32_t codepoint, std::string& output)
1692 {
1693 if (codepoint < 0x80)
1694 {
1695 output.push_back (static_cast<char> (codepoint));
1696 }
1697 else if (codepoint < 0x800)
1698 {
1699 char buf[2];
1700 buf[0] = static_cast<char> (0xC0 | (codepoint >> 6));
1701 buf[1] = static_cast<char> (0x80 | (codepoint & 0x3F));
1702 output.append (buf, 2);
1703 }
1704 else if (codepoint < 0x10000)
1705 {
1706 char buf[3];
1707 buf[0] = static_cast<char> (0xE0 | (codepoint >> 12));
1708 buf[1] = static_cast<char> (0x80 | ((codepoint >> 6) & 0x3F));
1709 buf[2] = static_cast<char> (0x80 | (codepoint & 0x3F));
1710 output.append (buf, 3);
1711 }
1712 else
1713 {
1714 char buf[4];
1715 buf[0] = static_cast<char> (0xF0 | (codepoint >> 18));
1716 buf[1] = static_cast<char> (0x80 | ((codepoint >> 12) & 0x3F));
1717 buf[2] = static_cast<char> (0x80 | ((codepoint >> 6) & 0x3F));
1718 buf[3] = static_cast<char> (0x80 | (codepoint & 0x3F));
1719 output.append (buf, 4);
1720 }
1721 }
1722
1729 template <typename ViewType>
1730 inline int readUnicode (ViewType& document, std::string& output)
1731 {
1732 uint32_t u = 0;
1733
1734 if (readHex (document, u) == -1)
1735 {
1736 return -1;
1737 }
1738
1739 if (u >= 0xDC00 && u <= 0xDFFF)
1740 {
1742 return -1;
1743 }
1744
1745 if (u >= 0xD800 && u <= 0xDBFF)
1746 {
1747 if ((document.get () != '\\') || (document.get () != 'u'))
1748 {
1750 return -1;
1751 }
1752
1753 uint32_t v = 0;
1754
1755 if (readHex (document, v) == -1)
1756 {
1758 return -1;
1759 }
1760
1761 if (v < 0xDC00 || v > 0xDFFF)
1762 {
1764 return -1;
1765 }
1766
1767 u = 0x10000 + (((u - 0xD800) << 10) | (v - 0xDC00));
1768 }
1769
1770 if (u > 0x10FFFF)
1771 {
1773 return -1;
1774 }
1775
1776 encodeUtf8 (u, output);
1777
1778 return 0;
1779 }
1780
1787 template <typename ViewType>
1788 inline int readEscaped (ViewType& document, std::string& output)
1789 {
1790 int ch = document.get ();
1791 switch (ch)
1792 {
1793 case '"':
1794 output.push_back ('"');
1795 break;
1796 case '\\':
1797 output.push_back ('\\');
1798 break;
1799 case '/':
1800 output.push_back ('/');
1801 break;
1802 case 'b':
1803 output.push_back ('\b');
1804 break;
1805 case 'f':
1806 output.push_back ('\f');
1807 break;
1808 case 'n':
1809 output.push_back ('\n');
1810 break;
1811 case 'r':
1812 output.push_back ('\r');
1813 break;
1814 case 't':
1815 output.push_back ('\t');
1816 break;
1817 case 'u':
1818 return readUnicode (document, output);
1819 default:
1821 return -1;
1822 }
1823
1824 return 0;
1825 }
1826
1833 /*template <typename ViewType>
1834 inline int readUtf8 (ViewType& document, std::string& output) noexcept
1835 {
1836 size_t count = 0;
1837
1838 if (static_cast <uint8_t> (document.peek ()) < 0x80)
1839 {
1840 output.push_back (document.get ());
1841 }
1842 else if (static_cast <uint8_t> (document.peek ()) < 0xE0)
1843 {
1844 output.push_back (document.get ());
1845 count = 1;
1846 }
1847 else if (static_cast <uint8_t> (document.peek ()) < 0xF0)
1848 {
1849 output.push_back (document.get ());
1850 count = 2;
1851 }
1852 else if (static_cast <uint8_t> (document.peek ()) < 0xF8)
1853 {
1854 output.push_back (document.get ());
1855 count = 3;
1856 }
1857 else
1858 {
1859 join::lastError = make_error_code (JsonErrc::InvalidEncoding);
1860 return -1;
1861 }
1862
1863 for (size_t i = 0; i < count; ++i)
1864 {
1865 if (static_cast <uint8_t> (document.peek ()) < 0x80 || static_cast <uint8_t> (document.peek ()) > 0xBF)
1866 {
1867 join::lastError = make_error_code (JsonErrc::InvalidEncoding);
1868 return -1;
1869 }
1870
1871 output.push_back (document.get ());
1872 }
1873
1874 return 0;
1875 }*/
1876
1883 template <typename ViewType>
1884 int readString (ViewType& document, bool isKey = false)
1885 {
1886 thread_local Value output (in_place_index_t<Value::String>{});
1887 output.clear ();
1888 output.reserve (64);
1889
1890 for (;;)
1891 {
1892 document.readUntilEscaped (output.getString ());
1893 int ch = document.peek ();
1894
1895 if (ch == '"')
1896 {
1897 document.get ();
1898 break;
1899 }
1900
1901 if (ch == '\\')
1902 {
1903 document.get ();
1904 if (readEscaped (document, output.getString ()) == -1)
1905 {
1906 return -1;
1907 }
1908 continue;
1909 }
1910
1911 /*if (static_cast <uint8_t> (ch) > 0x7F)
1912 {
1913 if (readUtf8 (document, output) == -1)
1914 {
1915 return -1;
1916 }
1917 continue;
1918 }*/
1919
1920 if (ch < 0x20)
1921 {
1923 return -1;
1924 }
1925 }
1926
1927 return isKey ? setKey (output) : setString (output.getString ());
1928 }
1929
1935 template <JsonReadMode ReadMode, typename ViewType>
1936 int readArray (ViewType& document)
1937 {
1938 if (JOIN_UNLIKELY (startArray () == -1))
1939 {
1940 return -1;
1941 }
1942
1943 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
1944 {
1945 return -1;
1946 }
1947
1948 if (document.getIf (']'))
1949 {
1950 return stopArray ();
1951 }
1952
1953 for (;;)
1954 {
1955 if (JOIN_UNLIKELY (readValue<ReadMode> (document) == -1))
1956 {
1957 return -1;
1958 }
1959
1960 int ch = document.get ();
1961
1962 if (JOIN_UNLIKELY (details::whitespaceLookup.data[static_cast<unsigned char> (ch)]))
1963 {
1964 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
1965 {
1966 return -1;
1967 }
1968 ch = document.get ();
1969 }
1970
1971 if (JOIN_LIKELY (ch == ','))
1972 {
1973 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
1974 {
1975 return -1;
1976 }
1977 continue;
1978 }
1979
1980 if (JOIN_LIKELY (ch == ']'))
1981 {
1982 break;
1983 }
1984
1986 return -1;
1987 }
1988
1989 return stopArray ();
1990 }
1991
1997 template <JsonReadMode ReadMode, typename ViewType>
1998 int readObject (ViewType& document)
1999 {
2000 if (JOIN_UNLIKELY (startObject () == -1))
2001 {
2002 return -1;
2003 }
2004
2005 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2006 {
2007 return -1;
2008 }
2009
2010 if (document.getIf ('}'))
2011 {
2012 return stopObject ();
2013 }
2014
2015 for (;;)
2016 {
2017 if (JOIN_UNLIKELY (document.get () != '"'))
2018 {
2020 return -1;
2021 }
2022
2023 if (JOIN_UNLIKELY (readString (document, true) == -1))
2024 {
2025 return -1;
2026 }
2027
2028 if (document.peek () != ':')
2029 {
2030 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2031 {
2032 return -1;
2033 }
2034 }
2035
2036 if (JOIN_UNLIKELY (document.get () != ':'))
2037 {
2039 return -1;
2040 }
2041
2042 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2043 {
2044 return -1;
2045 }
2046
2047 if (JOIN_UNLIKELY (readValue<ReadMode> (document) == -1))
2048 {
2049 return -1;
2050 }
2051
2052 int ch = document.get ();
2053
2054 if (JOIN_UNLIKELY (details::whitespaceLookup.data[static_cast<unsigned char> (ch)]))
2055 {
2056 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2057 {
2058 return -1;
2059 }
2060 ch = document.get ();
2061 }
2062
2063 if (JOIN_LIKELY (ch == ','))
2064 {
2065 if (JOIN_UNLIKELY (skipWhitespaces<ReadMode> (document) == -1))
2066 {
2067 return -1;
2068 }
2069 continue;
2070 }
2071
2072 if (JOIN_LIKELY (ch == '}'))
2073 {
2074 break;
2075 }
2076
2078 return -1;
2079 }
2080
2081 return stopObject ();
2082 }
2083
2089 template <JsonReadMode ReadMode, typename ViewType>
2090 inline typename std::enable_if<!(ReadMode & JsonReadMode::ParseComments), int>::type skipWhitespaces (
2091 ViewType& document)
2092 {
2093 return document.skipWhitespaces ();
2094 }
2095
2101 template <JsonReadMode ReadMode, typename ViewType>
2102 inline typename std::enable_if<(ReadMode & JsonReadMode::ParseComments), int>::type skipWhitespaces (
2103 ViewType& document)
2104 {
2105 return document.skipWhitespacesAndComments ();
2106 }
2107
2113 constexpr bool isUpperAlpha (char c) noexcept
2114 {
2115 return static_cast<unsigned char> (c - 'A') <= 5u;
2116 }
2117
2123 constexpr bool isLowerAlpha (char c) noexcept
2124 {
2125 return static_cast<unsigned char> (c - 'a') <= 5u;
2126 }
2127
2133 constexpr bool isDigit (char c) noexcept
2134 {
2135 return static_cast<unsigned char> (c - '0') <= 9u;
2136 }
2137
2143 constexpr bool isSign (char c) noexcept
2144 {
2145 return ((c ^ '+') & (c ^ '-')) == 0;
2146 }
2147 };
2148}
2149
2150namespace std
2151{
2153 template <>
2154 struct is_error_condition_enum<join::JsonErrc> : public true_type
2155 {
2156 };
2157}
2158
2159#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:862
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:936
bool strtodSlow(const std::string &num, double &d)
convert double using strtod.
Definition json.hpp:1489
constexpr bool isSign(char c) noexcept
check if sign.
Definition json.hpp:2143
JsonReader(const JsonReader &other)=delete
copy constructor.
int readValue(ViewType &document)
parse a JSON value.
Definition json.hpp:1224
int deserialize(std::istringstream &document) override
deserialize a document.
Definition json.hpp:1087
constexpr bool isUpperAlpha(char c) noexcept
check if upper case alphanumeric character.
Definition json.hpp:2113
int deserialize(const char *first, const char *last) override
deserialize a document.
Definition json.hpp:1021
int readInf(ViewType &document, bool negative)
parse an infinity value.
Definition json.hpp:1310
int deserialize(const char *document, size_t length)
deserialize a document.
Definition json.hpp:985
int readUnicode(ViewType &document, std::string &output)
parse unicode.
Definition json.hpp:1730
int deserialize(std::stringstream &document) override
deserialize a document.
Definition json.hpp:1065
int readHex(ViewType &document, uint32_t &u)
parse a 4-digit hexadecimal sequence..
Definition json.hpp:1656
int readEscaped(ViewType &document, std::string &output)
parse escaped sequence.
Definition json.hpp:1788
int deserialize(const char *document, size_t length) override
deserialize a document.
Definition json.hpp:997
int readString(ViewType &document, bool isKey=false)
parse UTF8.
Definition json.hpp:1884
std::enable_if<!(ReadMode &JsonReadMode::ParseComments), int >::type skipWhitespaces(ViewType &document)
skip whitespaces.
Definition json.hpp:2090
int deserialize(const char *first, const char *last)
deserialize a document.
Definition json.hpp:1009
JsonReader(JsonReader &&other)=delete
move constructor.
int readObject(ViewType &document)
parse an object value.
Definition json.hpp:1998
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:1357
int read(ViewType &document)
parse a document.
Definition json.hpp:1187
int deserialize(std::iostream &document)
deserialize a document.
Definition json.hpp:1142
int deserialize(std::fstream &document)
deserialize a document.
Definition json.hpp:1098
int readNan(ViewType &document, bool negative)
parse a nan value.
Definition json.hpp:1336
void encodeUtf8(uint32_t codepoint, std::string &output)
encode a Unicode codepoint to UTF-8.
Definition json.hpp:1691
JsonReader & operator=(const JsonReader &other)=delete
copy assignment.
int readNull(ViewType &document)
parse a null value.
Definition json.hpp:1258
int deserialize(std::istream &document) override
deserialize a document.
Definition json.hpp:1175
int deserialize(const std::string &document) override
deserialize a document.
Definition json.hpp:1043
int deserialize(std::ifstream &document) override
deserialize a document.
Definition json.hpp:1131
constexpr bool isLowerAlpha(char c) noexcept
check if lower case alphanumeric character.
Definition json.hpp:2123
int deserialize(std::iostream &document) override
deserialize a document.
Definition json.hpp:1153
constexpr bool isDigit(char c) noexcept
check if digit.
Definition json.hpp:2133
int deserialize(const std::string &document)
deserialize a document.
Definition json.hpp:1032
JsonReader(Value &root)
default constructor.
Definition json.hpp:942
int deserialize(std::istringstream &document)
deserialize a document.
Definition json.hpp:1076
int readNumber(ViewType &document)
parse a number value.
Definition json.hpp:1503
int readArray(ViewType &document)
parse an array value.
Definition json.hpp:1936
int deserialize(std::istream &document)
deserialize a document.
Definition json.hpp:1164
int deserialize(std::fstream &document) override
deserialize a document.
Definition json.hpp:1109
int readFalse(ViewType &document)
parse a false value.
Definition json.hpp:1292
int readTrue(ViewType &document)
parse a true value.
Definition json.hpp:1275
int deserialize(std::ifstream &document)
deserialize a document.
Definition json.hpp:1120
int deserialize(std::stringstream &document)
deserialize a document.
Definition json.hpp:1054
bool strtodFast(uint64_t significand, int64_t exponent, double &value)
convert double using fast path.
Definition json.hpp:1402
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:462
virtual int stopObject() override
stop object.
Definition sax.hpp:753
virtual int startArray(uint32_t size=0) override
start array.
Definition sax.hpp:655
virtual int setInt64(int64_t value) override
set 64 bits integer value.
Definition sax.hpp:615
virtual int setNull() override
set null value.
Definition sax.hpp:575
virtual int setUint64(uint64_t value) override
set unsigned 64 bits integer value.
Definition sax.hpp:625
virtual int setKey(const Value &key) override
set key.
Definition sax.hpp:743
virtual int startObject(uint32_t size=0) override
start object.
Definition sax.hpp:706
virtual int setBool(bool value) override
set boolean value.
Definition sax.hpp:585
virtual int stopArray() override
stop array.
Definition sax.hpp:691
virtual int setDouble(double value) override
set real value.
Definition sax.hpp:635
virtual int setString(const std::string &value) override
set string value.
Definition sax.hpp:645
stream serializer abstract class.
Definition sax.hpp:244
int setValue(const Value &value)
set value.
Definition sax.hpp:301
void append(char data) noexcept
append character to output stream in batch.
Definition sax.hpp:392
void append4(const char *data) noexcept
append 4-character literal to output stream in batch.
Definition sax.hpp:422
string view.
Definition view.hpp:83
value class.
Definition value.hpp:64
void clear()
erases all elements in the nested container.
Definition value.hpp:1187
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:916
IpAddress operator&(const IpAddress &a, const IpAddress &b)
perform AND operation on IP address.
Definition ipaddress.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:54
constexpr const JsonReadMode & operator|=(JsonReadMode &a, JsonReadMode b) noexcept
perform binary OR on JsonReadMode.
Definition json.hpp:927
JsonReadMode
JSON deserialization mode.
Definition json.hpp:881
@ StopParsingOnDone
Definition json.hpp:885
@ ParseComments
Definition json.hpp:883
@ ValidateEncoding
Definition json.hpp:884
@ None
Definition json.hpp:882
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:150
IpAddress operator|(const IpAddress &a, const IpAddress &b)
perform OR operation on IP address.
Definition ipaddress.cpp:1692
thread_local std::error_code lastError
last error.
Definition error.cpp:32
std::vector< Member > Object
object.
Definition value.hpp:57
std::error_condition make_error_condition(join::Errc code) noexcept
Create an std::error_condition object.
Definition error.cpp:159
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:137
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:46
#define JOIN_UNLIKELY(x)
Definition utils.hpp:47