Botcraft 1.21.4
Loading...
Searching...
No Matches
Json.cpp
Go to the documentation of this file.
1#include <array>
2#include <iomanip>
3#include <sstream>
4#include <cmath>
5
8
9namespace ProtocolCraft
10{
11 using namespace Internal;
12
13 namespace Json
14 {
15 std::string EscapeChars(const std::string& s);
16 void SkipSpaces(std::string_view::const_iterator& iter, size_t& length);
17 Value NumberFromString(const std::string& s, const bool is_scientific, const bool is_double);
18 Value ParseNumber(std::string_view::const_iterator& iter, size_t& length);
19 Value ParseString(std::string_view::const_iterator& iter, size_t& length);
20 Value ParseObject(std::string_view::const_iterator& iter, size_t& length);
21 Value ParseArray(std::string_view::const_iterator& iter, size_t& length);
22 Value ParseValue(std::string_view::const_iterator& iter, size_t& length);
23
24 Value::Value(std::nullptr_t)
25 {
26
27 }
28
29 Value::Value(std::string_view s) : val(std::string(s))
30 {
31
32 }
33
34 Value::Value(const std::string& s) : val(s)
35 {
36
37 }
38
39 Value::Value(std::string&& s) : val(std::move(s))
40 {
41
42 }
43
44 Value::Value(const char* s) : val(std::string(s))
45 {
46
47 }
48
49 Value::Value(const bool b) : val(b)
50 {
51
52 }
53
54 Value::Value(const Object& o) : val(o)
55 {
56
57 }
58
59 Value::Value(Object&& o) : val(std::move(o))
60 {
61
62 }
63
64 Value::Value(const Array& a) : val(a)
65 {
66
67 }
68
69 Value::Value(Array&& a) : val(std::move(a))
70 {
71
72 }
73
74 Value::Value(const std::initializer_list<Value>& init)
75 {
76 if (init.size() == 2 && init.begin()->is_string())
77 {
78 val = Object({ { init.begin()->get<std::string>(), *(init.begin() + 1) } });
79 return;
80 }
81
82 // If all elements are pairs and first element is a string,
83 // this is an object, otherwise it's an array
84 for (const auto& j : init)
85 {
86 if (!j.is_object()
87 || j.size() != 1)
88 {
89 val = Array(init);
90 return;
91 }
92 }
93
94 Object new_val;
95
96 for (const auto& j : init)
97 {
98 new_val.insert(*j.get_object().begin());
99 }
100
101 val = std::move(new_val);
102 }
103
104 Value::Value(const NetworkType& o) : val(std::move(o.Serialize().val))
105 {
106
107 }
108
110 {
111 return get<Object>();
112 }
113
115 {
116 return get<Array>();
117 }
118
119 std::string& Value::get_string()
120 {
121 return get<std::string>();
122 }
123
125 {
126 return get<Object>();
127 }
128
129 const Array& Value::get_array() const
130 {
131 return get<Array>();
132 }
133
134 const std::string& Value::get_string() const
135 {
136 return get<std::string>();
137 }
138
139 bool Value::is_null() const
140 {
141 return is<std::monostate>();
142 }
143
144 bool Value::is_string() const
145 {
146 return is<std::string>();
147 }
148
149 bool Value::is_object() const
150 {
151 return is<Json::Object>();
152 }
153
154 bool Value::is_array() const
155 {
156 return is<Json::Array>();
157 }
158
159 bool Value::is_bool() const
160 {
161 return is<bool>();
162 }
163
164 bool Value::is_integer() const
165 {
166 return std::holds_alternative<long long int>(val)
167 || std::holds_alternative<unsigned long long int>(val);
168 }
169
170 bool Value::is_number() const
171 {
172 return std::holds_alternative<long long int>(val)
173 || std::holds_alternative<unsigned long long int>(val)
174 || std::holds_alternative<double>(val);
175 }
176
177 Value& Value::operator[](const std::string& s)
178 {
179 if (std::holds_alternative<std::monostate>(val))
180 {
181 val = Object();
182 }
183
184 if (!std::holds_alternative<RecursiveWrapper<Object>>(val))
185 {
186 throw std::runtime_error("Json::Value is not an object");
187 }
188
189 return get<Object>()[s];
190 }
191
192 const Value& Value::operator[](const std::string& s) const
193 {
194 if (!std::holds_alternative<RecursiveWrapper<Object>>(val))
195 {
196 throw std::runtime_error("Json::Value is not an object");
197 }
198
199 return get<Object>().at(s);
200 }
201
202 Value& Value::operator[](const size_t i)
203 {
204 if (!std::holds_alternative<RecursiveWrapper<Array>>(val))
205 {
206 throw std::runtime_error("Json::Value is not an array");
207 }
208
209 return get<Array>()[i];
210 }
211
212 const Value& Value::operator[](const size_t i) const
213 {
214 if (!std::holds_alternative<RecursiveWrapper<Array>>(val))
215 {
216 throw std::runtime_error("Json::Value is not an array");
217 }
218
219 return get<Array>().at(i);
220 }
221
222 std::istream& operator>>(std::istream& is, Value& v)
223 {
224 v = Json::Parse(std::string(
225 std::istreambuf_iterator<char>(is),
226 std::istreambuf_iterator<char>()
227 ));
228
229 return is;
230 }
231
232 bool Value::contains(const std::string& s) const
233 {
234 return is<Object>() && get<Object>().count(s);
235 }
236
237 size_t Value::size() const
238 {
239 if (std::holds_alternative<std::monostate>(val))
240 {
241 return 0;
242 }
243
244 if (std::holds_alternative<RecursiveWrapper<Object>>(val))
245 {
246 return get<Object>().size();
247 }
248
249 if (std::holds_alternative<RecursiveWrapper<Array>>(val))
250 {
251 return get<Array>().size();
252 }
253
254 throw std::runtime_error("Json::Value is neither an array nor an object");
255 }
256
257 void Value::push_back(const Value& value)
258 {
259 if (std::holds_alternative<std::monostate>(val))
260 {
261 val = Array();
262 }
263
264 if (!std::holds_alternative<RecursiveWrapper<Array>>(val))
265 {
266 throw std::runtime_error("Can't push_back in a non-array Json::Value");
267 }
268
269 get<Array>().push_back(value);
270 }
271
273 {
274 if (std::holds_alternative<std::monostate>(val))
275 {
276 val = Array();
277 }
278
279 if (!std::holds_alternative<RecursiveWrapper<Array>>(val))
280 {
281 throw std::runtime_error("Can't push_back in a non-array Json::Value");
282 }
283
284 get<Array>().push_back(std::move(value));
285 }
286
287 std::string Value::Dump(const int indent, const char indent_char) const
288 {
289 return Dump(0, indent, indent_char);
290 }
291
292 std::string Value::Dump(const size_t depth_level, const int indent, const char indent_char) const
293 {
294 std::ostringstream oss;
295
296 std::visit([&](auto&& arg)
297 {
298 using T = std::decay_t<decltype(arg)>;
299
300 if constexpr (std::is_same_v<T, std::monostate>)
301 {
302 oss << "null";
303 }
304 else if constexpr (std::is_same_v<T, RecursiveWrapper<Object>>)
305 {
306 const Object& o = arg.get();
307 if (o.empty())
308 {
309 oss << "{}";
310 return;
311 }
312
313 const std::string new_line = (indent == -1 ? "" : "\n");
314 const std::string line_indentation = indent > -1 ? std::string(depth_level * indent, indent_char) : "";
315 const std::string value_indentation = indent > -1 ? std::string(indent, indent_char) : "";
316
317 oss << "{" << new_line;
318 bool first = true;
319 for (const auto& [k, v] : o)
320 {
321 if (!first)
322 {
323 oss << "," << new_line;
324 }
325 else
326 {
327 first = false;
328 }
329 oss << line_indentation << value_indentation << "\"" << k << "\"" << (indent == -1 ? ":" : ": ") << v.Dump(depth_level + 1, indent, indent_char);
330 }
331 oss << new_line << line_indentation << "}";
332 }
333 else if constexpr (std::is_same_v<T, RecursiveWrapper<Array>>)
334 {
335 const Array& a = arg.get();
336 if (a.empty())
337 {
338 oss << "[]";
339 return;
340 }
341 const std::string new_line = (indent == -1 ? "" : "\n");
342 const std::string line_indentation = indent > -1 ? std::string(depth_level * indent, indent_char) : "";
343 const std::string value_indentation = indent > -1 ? std::string(indent, indent_char) : "";
344
345 oss << '[' << new_line;
346 bool first = true;
347 for (const auto& v : a)
348 {
349 if (!first)
350 {
351 oss << ',' << new_line;
352 }
353 else
354 {
355 first = false;
356 }
357 oss << line_indentation << value_indentation << v.Dump(depth_level + 1, indent, indent_char);
358 }
359 oss << new_line << line_indentation << ']';
360 }
361 else if constexpr (std::is_same_v<T, std::string>)
362 {
363 oss << "\"" << EscapeChars(arg) << "\"";
364 }
365 else if constexpr (std::is_same_v<T, bool>)
366 {
367 oss << (arg ? "true" : "false");
368 }
369 else if constexpr (std::is_same_v<T, double>)
370 {
371 if (arg == std::floor(arg))
372 {
373 oss << std::setprecision(1) << std::fixed << arg;
374 }
375 else
376 {
377 oss << arg;
378 }
379 }
380 else
381 {
382 oss << arg;
383 }
384 }, val);
385
386 return oss.str();
387 }
388
389
390 Value Parse(std::string_view::const_iterator iter, size_t length, bool no_except)
391 {
392 const size_t init_length = length;
393 try
394 {
395 Value out = ParseValue(iter, length);
396 if (length > 0)
397 {
398 throw std::runtime_error(std::to_string(length) + " unread characters remaining after parsing");
399 }
400 return out;
401 }
402 catch (const std::runtime_error& e)
403 {
404 if (no_except)
405 {
406 return Value();
407 }
408 throw std::runtime_error(e.what() + std::string(" (at pos ") + std::to_string(init_length - length) + ')');
409 }
410 }
411
412 Value Parse(const std::string& s, bool no_except)
413 {
414 if (s.empty())
415 {
416 return Value();
417 }
418
419 size_t length = s.size();
420 std::string_view sview(s.begin().operator->(), s.end() - s.begin());
421 try
422 {
423 return Parse(sview.begin(), length);
424 }
425 catch (const std::runtime_error& e)
426 {
427 if (no_except)
428 {
429 return Value();
430 }
431 throw std::runtime_error(e.what() + std::string(" (at pos ") + std::to_string(s.size() - length) + ')');
432 }
433 }
434
435 std::string EscapeChars(const std::string& s)
436 {
437 std::ostringstream out;
438 auto it = s.begin();
439 while (it != s.end())
440 {
441 switch (*it)
442 {
443 case '\\':
444 case '"':
445 out << '\\' << *it;
446 it += 1;
447 break;
448 case '\b':
449 out << '\\' << 'b';
450 it += 1;
451 break;
452 case '\f':
453 out << '\\' << 'f';
454 it += 1;
455 break;
456 case '\n':
457 out << '\\' << 'n';
458 it += 1;
459 break;
460 case '\r':
461 out << '\\' << 'r';
462 it += 1;
463 break;
464 case '\t':
465 out << '\\' << 't';
466 it += 1;
467 break;
468 default:
469 out << *it;
470 it += 1;
471 break;
472 }
473 }
474
475 return out.str();
476 }
477
478 void SkipSpaces(std::string_view::const_iterator& iter, size_t& length)
479 {
480 while (length)
481 {
482 switch (*iter)
483 {
484 case ' ':
485 case '\t':
486 case '\r':
487 case '\n':
488 iter += 1;
489 length -= 1;
490 break;
491 default:
492 return;
493 break;
494 }
495 }
496 }
497
498 void ValidateStringNumber(const std::string& s)
499 {
500 const size_t s_size = s.size();
501 // Validate the string format
502 for (size_t i = 0; i < s_size; ++i)
503 {
504 switch (s[i])
505 {
506 case '0':
507 if ((i == 0 && s_size > 1 && s[1] != '.' && s[1] != 'e' && s[1] != 'E') ||
508 (i == 1 && s_size > 2 && s[0] == '-' && s[2] != '.' && s[2] != 'e' && s[2] != 'E'))
509 {
510 throw std::runtime_error("Unexpected leading 0 when parsing number");
511 }
512 break;
513 case '-':
514 if (i == s_size - 1 ||
515 (i != 0 && (s[i - 1] == '.' || s[i - 1] == '+'))
516 )
517 {
518 throw std::runtime_error("Unexpected - character when parsing number");
519 }
520 break;
521 case '+':
522 if (i == 0 || i == s_size - 1 || (s[i - 1] != 'e' && s[i - 1] != 'E'))
523 {
524 throw std::runtime_error("Unexpected + character when parsing number");
525 }
526 break;
527 case 'e':
528 case 'E':
529 if (i == 0 ||
530 i == s_size - 1 ||
531 s[i - 1] == '.' ||
532 s[i - 1] == '+' ||
533 s[i - 1] == '-')
534 {
535 throw std::runtime_error("Unexpected exponent sign found when parsing a number");
536 }
537 break;
538 case '.':
539 if (i == 0 ||
540 i == s_size - 1 ||
541 s[i - 1] == 'e' ||
542 s[i - 1] == 'E' ||
543 s[i - 1] == '+' ||
544 s[i - 1] == '-')
545 {
546 throw std::runtime_error("Unexpected . sign found when parsing a number");
547 }
548 break;
549 default:
550 break;
551 }
552 }
553 }
554
555 Value NumberFromString(const std::string& s, const bool is_scientific, const bool is_double)
556 {
557 if (s.empty())
558 {
559 throw std::runtime_error("Trying to convert empty string to number");
560 }
561
563
564 if (is_scientific || is_double)
565 {
566 return std::stod(s);
567 }
568
569 if (s[0] == '-')
570 {
571 // min long long int (but with > because string comparison)
572 if (s.size() > 20 || (s.size() == 20 && s > "-9223372036854775808"))
573 {
574 return std::stod(s);
575 }
576 return std::stoll(s);
577 }
578
579 // max unsigned long long int
580 if (s.size() > 20 || (s.size() == 20 && s > "18446744073709551615"))
581 {
582 return std::stod(s);
583 }
584 return std::stoull(s);
585 }
586
587 Value ParseNumber(std::string_view::const_iterator& iter, size_t& length)
588 {
589 std::string_view::const_iterator start = iter;
590
591 bool is_scientific = false;
592 bool is_double = false;
593
594 while (length)
595 {
596 switch (*iter)
597 {
598 case 'e':
599 case 'E':
600 if (is_scientific)
601 {
602 throw std::runtime_error("Multiple exponent char encountered while parsing number");
603 }
604 is_scientific = true;
605 iter += 1;
606 length -= 1;
607 break;
608 case '.':
609 if (is_double)
610 {
611 throw std::runtime_error("Multiple decimal separator encountered while parsing number");
612 }
613 is_double = true;
614 iter += 1;
615 length -= 1;
616 break;
617 case '+':
618 case '-':
619 case '0':
620 case '1':
621 case '2':
622 case '3':
623 case '4':
624 case '5':
625 case '6':
626 case '7':
627 case '8':
628 case '9':
629 iter += 1;
630 length -= 1;
631 break;
632 default:
633 return NumberFromString(std::string(start, iter), is_scientific, is_double);
634 }
635 }
636
637 // This means the whole string was a number and no other character was present to stop the reading
638 return NumberFromString(std::string(start, iter), is_scientific, is_double);
639 }
640
641 bool IsValidCodepoint(const unsigned long cp)
642 {
643 // Is in range of valide codepoints and is not a surrogate
644 return cp <= 0x0010ffffu && !(cp >= 0xd800u && cp <= 0xdfffu);
645 }
646
647 std::string CodepointToUtf8(const std::string& hex_chars)
648 {
649 const unsigned long codepoint = std::stoul(hex_chars, nullptr, 16);
650
651 if (!IsValidCodepoint(codepoint))
652 {
653 throw std::runtime_error("Trying to parse an invalid codepoint to UTF8 while reading string");
654 }
655
656 if (codepoint < 0x80)
657 {
658 return std::string()
659 + static_cast<char>(codepoint);
660 }
661 else if (codepoint < 0x800)
662 {
663 return std::string()
664 + static_cast<char>((codepoint >> 6) | 0xc0)
665 + static_cast<char>((codepoint & 0x3f) | 0x80);
666 }
667 else if (codepoint < 0x10000)
668 {
669 return std::string()
670 + static_cast<char>((codepoint >> 12) | 0xe0)
671 + static_cast<char>(((codepoint >> 6) & 0x3f) | 0x80)
672 + static_cast<char>((codepoint & 0x3f) | 0x80);
673 }
674 else
675 {
676 return std::string()
677 + static_cast<char>((codepoint >> 18) | 0xf0)
678 + static_cast<char>(((codepoint >> 12) & 0x3f) | 0x80)
679 + static_cast<char>(((codepoint >> 6) & 0x3f) | 0x80)
680 + static_cast<char>((codepoint & 0x3f) | 0x80);
681 }
682 }
683
684 Value ParseString(std::string_view::const_iterator& iter, size_t& length)
685 {
686 if (length < 2)
687 {
688 throw std::runtime_error("Not enough input when reading string");
689 }
690 if (*iter != '\"')
691 {
692 throw std::runtime_error(std::string("Unexpected char found at beginning of string \"") + *iter + "\"");
693 }
694 iter += 1;
695 length -= 1;
696
697 std::ostringstream output;
698 while (length)
699 {
700 switch (*iter)
701 {
702 case '\b':
703 case '\f':
704 case '\n':
705 case '\r':
706 case '\t':
707 throw std::runtime_error("Unexpected unescaped special character encountered when parsing string");
708 case '"':
709 iter += 1;
710 length -= 1;
711 return output.str();
712 case '\\':
713 if (length == 1)
714 {
715 throw std::runtime_error("Missing data after escape character when parsing string");
716 }
717 else
718 {
719 switch (*(iter + 1))
720 {
721 case '\"':
722 output << *iter << *(iter + 1);
723 iter += 2;
724 length -= 2;
725 break;
726 case '\\':
727 output << '\\';
728 iter += 2;
729 length -= 2;
730 break;
731 case '/':
732 output << '/';
733 iter += 2;
734 length -= 2;
735 break;
736 case 'b':
737 output << '\b';
738 iter += 2;
739 length -= 2;
740 break;
741 case 'f':
742 output << '\f';
743 iter += 2;
744 length -= 2;
745 break;
746 case 'n':
747 output << '\n';
748 iter += 2;
749 length -= 2;
750 break;
751 case 'r':
752 output << '\r';
753 iter += 2;
754 length -= 2;
755 break;
756 case 't':
757 output << '\t';
758 iter += 2;
759 length -= 2;
760 break;
761 case 'u':
762 if (length < 6)
763 {
764 throw std::runtime_error("Missing data after \\u character when parsing string");
765 }
766 output << CodepointToUtf8(std::string(iter + 2, iter + 6));
767 iter += 6;
768 length -= 6;
769 break;
770 default:
771 throw std::runtime_error("Unexpected escape character encountered when parsing string");
772 break;
773 }
774 }
775 break;
776 default:
777 if (*iter > -1 && *iter < 32)
778 {
779 // Control characters are invalid
780 throw std::runtime_error("Unexpected control character encountered when parsing string");
781 }
782 output << *iter;
783 iter += 1;
784 length -= 1;
785 break;
786 }
787 }
788
789 throw std::runtime_error("Not enough input when reading string");
790 }
791
792 Value ParseObject(std::string_view::const_iterator& iter, size_t& length)
793 {
794 if (length < 2)
795 {
796 throw std::runtime_error("Not enough input when reading Json::Object");
797 }
798 if (*iter != '{')
799 {
800 throw std::runtime_error(std::string("Unexpected char found at beginning of Json::Object \"") + *iter + "\"");
801 }
802 iter += 1;
803 length -= 1;
804
805 SkipSpaces(iter, length);
806
807 if (length == 0)
808 {
809 throw std::runtime_error("Not enough input when reading Json::Object");
810 }
811
812 Object output;
813 if (*iter == '}')
814 {
815 iter += 1;
816 length -= 1;
817 return output;
818 }
819
820 while (length)
821 {
822 SkipSpaces(iter, length);
823
824 const Value key = ParseString(iter, length);
825
826 SkipSpaces(iter, length);
827
828 if (*iter != ':')
829 {
830 throw std::runtime_error(std::string("Unexpected char \"") + *iter + "\" when reading Json::Object while expecting :");
831 }
832 iter += 1;
833 length -= 1;
834
835 SkipSpaces(iter, length);
836
837 const Value value = ParseValue(iter, length);
838 output[key.get_string()] = value;
839
840 SkipSpaces(iter, length);
841
842 if (*iter == '}')
843 {
844 iter += 1;
845 length -= 1;
846 return output;
847 }
848 else if (*iter != ',')
849 {
850 throw std::runtime_error(std::string("Unexpected char \"") + *iter + "\" when reading Json::Object while expecting ,");
851 }
852
853 iter += 1;
854 length -= 1;
855 }
856
857 throw std::runtime_error("Not enough input when reading Json::Object");
858 }
859
860 Value ParseArray(std::string_view::const_iterator& iter, size_t& length)
861 {
862 if (length < 2)
863 {
864 throw std::runtime_error("Not enough input when reading Json::Array");
865 }
866 if (*iter != '[')
867 {
868 throw std::runtime_error(std::string("Unexpected char found at beginning of Json::Array \"") + *iter + "\"");
869 }
870 iter += 1;
871 length -= 1;
872
873 Array output;
874
875 SkipSpaces(iter, length);
876
877 if (length == 0)
878 {
879 throw std::runtime_error("Not enough input when reading Json::Array");
880 }
881
882 if (*iter == ']')
883 {
884 iter += 1;
885 length -= 1;
886 return output;
887 }
888
889 while (length)
890 {
891 SkipSpaces(iter, length);
892
893 const Value value = ParseValue(iter, length);
894 output.push_back(value);
895
896 SkipSpaces(iter, length);
897
898 if (*iter == ']')
899 {
900 iter += 1;
901 length -= 1;
902 return output;
903 }
904 else if (*iter != ',')
905 {
906 throw std::runtime_error(std::string("Unexpected char \"") + *iter + "\" when reading Json::Array while expecting ,");
907 }
908
909 iter += 1;
910 length -= 1;
911 }
912
913 throw std::runtime_error("Not enough input when reading Json::Array");
914 }
915
916 Value ParseValue(std::string_view::const_iterator& iter, size_t& length)
917 {
918 SkipSpaces(iter, length);
919
920 Value output;
921
922 switch (*iter)
923 {
924 case '{':
925 output = ParseObject(iter, length);
926 break;
927 case '[':
928 output = ParseArray(iter, length);
929 break;
930 case '\"':
931 output = ParseString(iter, length);
932 break;
933 case 'n':
934 if (length < 4
935 || *(iter + 1) != 'u'
936 || *(iter + 2) != 'l'
937 || *(iter + 3) != 'l')
938 {
939 throw std::runtime_error("Unexpected char \"n\"");
940 }
941 else
942 {
943 iter += 4;
944 length -= 4;
945 }
946 break;
947 case 't':
948 if (length < 4
949 || *(iter + 1) != 'r'
950 || *(iter + 2) != 'u'
951 || *(iter + 3) != 'e')
952 {
953 throw std::runtime_error("Unexpected char \"t\"");
954 }
955 else
956 {
957 iter += 4;
958 length -= 4;
959 output = true;
960 }
961 break;
962 case 'f':
963 if (length < 5
964 || *(iter + 1) != 'a'
965 || *(iter + 2) != 'l'
966 || *(iter + 3) != 's'
967 || *(iter + 4) != 'e')
968 {
969 throw std::runtime_error("Unexpected char \"f\"");
970 }
971 else
972 {
973 iter += 5;
974 length -= 5;
975 output = false;
976 }
977 break;
978 case '0':
979 case '1':
980 case '2':
981 case '3':
982 case '4':
983 case '5':
984 case '6':
985 case '7':
986 case '8':
987 case '9':
988 case '-':
989 output = ParseNumber(iter, length);
990 break;
991 default:
992 throw std::runtime_error(std::string("Unexpected char \"") + *iter + "\"");
993 break;
994 }
995
996 SkipSpaces(iter, length);
997
998 return output;
999 }
1000 }
1001}
Template magic to have a full type instead of an incomplete one as required for example by std::varia...
Real class declaration, just a derived class of std::vector<Value>
Definition Json.hpp:180
Real class declaration, just a derived class of std::map<std::string, Value>
Definition Json.hpp:186
Main class, basically a JsonVariant with extra utility functions it doesn't inherit JsonVariant direc...
Definition Json.hpp:45
bool is_string() const
Definition Json.cpp:144
size_t size() const
Definition Json.cpp:237
bool is_number() const
Definition Json.cpp:170
Internal::JsonVariant val
Definition Json.hpp:175
std::string Dump(const int indent=-1, const char indent_char=' ') const
public dump interface
Definition Json.cpp:287
bool is_integer() const
Definition Json.cpp:164
bool is_array() const
Definition Json.cpp:154
void push_back(const Value &value)
Definition Json.cpp:257
Value & operator[](const std::string &s)
Definition Json.cpp:177
Value(std::nullptr_t=nullptr)
Definition Json.cpp:24
bool is_object() const
Definition Json.cpp:149
bool contains(const std::string &s) const
Definition Json.cpp:232
std::string & get_string()
Definition Json.cpp:119
Value ParseString(std::string_view::const_iterator &iter, size_t &length)
Definition Json.cpp:684
Value ParseObject(std::string_view::const_iterator &iter, size_t &length)
Definition Json.cpp:792
Value ParseNumber(std::string_view::const_iterator &iter, size_t &length)
Definition Json.cpp:587
bool IsValidCodepoint(const unsigned long cp)
Definition Json.cpp:641
Value ParseValue(std::string_view::const_iterator &iter, size_t &length)
Definition Json.cpp:916
std::string CodepointToUtf8(const std::string &hex_chars)
Definition Json.cpp:647
Value ParseArray(std::string_view::const_iterator &iter, size_t &length)
Definition Json.cpp:860
Value NumberFromString(const std::string &s, const bool is_scientific, const bool is_double)
Definition Json.cpp:555
Value Parse(std::string_view::const_iterator iter, size_t length, bool no_except=false)
Parse a string_view from iter for at most length characters.
Definition Json.cpp:390
void SkipSpaces(std::string_view::const_iterator &iter, size_t &length)
Definition Json.cpp:478
std::istream & operator>>(std::istream &is, Value &v)
Definition Json.cpp:222
void ValidateStringNumber(const std::string &s)
Definition Json.cpp:498
std::string EscapeChars(const std::string &s)
Definition Json.cpp:435
STL namespace.