1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef API_CORE_JSON_JSON_H
17 #define API_CORE_JSON_JSON_H
18
19 #include <cstdint>
20 #include <cstdio>
21 #include <new>
22
23 #include <base/containers/string.h>
24 #include <base/containers/string_view.h>
25 #include <base/containers/type_traits.h>
26 #include <base/containers/vector.h>
27 #include <base/namespace.h>
28 #include <core/namespace.h>
29
CORE_BEGIN_NAMESPACE()30 CORE_BEGIN_NAMESPACE()
31 namespace json {
32 using readonly_string_t = BASE_NS::string_view;
33 using writable_string_t = BASE_NS::string;
34 template<typename T>
35 using array_t = BASE_NS::vector<T>;
36
37 /** Type of a JSON value. */
38 enum class type : uint8_t {
39 uninitialized = 0,
40 object,
41 array,
42 string,
43 floating_point,
44 signed_int,
45 unsigned_int,
46 boolean,
47 null,
48 };
49
50 /** Tag for JSON values which contain read-only strings. The source JSON string must be kept alive until the parsing
51 * results are not used.*/
52 struct readonly_tag {};
53
54 /** Tag for JSON values which contain writable strings. Life time of the parsing results doens't depend on the source
55 * JSON string.*/
56 struct writable_tag {};
57
58 template<typename T = readonly_tag>
59 struct value_t;
60
61 /** JSON structure which contains read-only strings. The source JSON string must be kept alive until the parsing
62 * results are not used.*/
63 using value = value_t<readonly_tag>;
64
65 /** JSON structure which contains writable strings. String values can be modified and if the instance was generated by
66 * the parser, the source string doesn't need to be stored while the instance is used.*/
67 using standalone_value = value_t<writable_tag>;
68
69 /** Parses 'data' and returns JSON structure. the value::type will be 'uninitialized' if parsing failed.
70 * @param data JSON as a null terminated string.
71 * @return Parsed JSON structure.
72 */
73 template<typename T = readonly_tag>
74 value_t<T> parse(const char* data);
75
76 /** Converts a JSON structure into a string.
77 * @param value JSON structure.
78 * @return JSON as string.
79 */
80 template<typename T = readonly_tag>
81 BASE_NS::string to_string(const value_t<T>& value);
82
83 BASE_NS::string unescape(BASE_NS::string_view str);
84
85 BASE_NS::string escape(BASE_NS::string_view str);
86
87 /** JSON value. */
88 template<typename Tag>
89 struct value_t {
90 /** Type used for JSON strings and JSON object keys. */
91 using string =
92 typename BASE_NS::conditional_t<BASE_NS::is_same_v<Tag, writable_tag>, writable_string_t, readonly_string_t>;
93
94 /** Type used for JSON null */
95 struct null {};
96
97 /** Type used for key-value pairs inside JSON objects. */
98 struct pair {
99 pair(string&& k, value_t&& v) : key(BASE_NS::forward<string>(k)), value(BASE_NS::forward<value_t>(v)) {}
100 string key;
101 value_t value;
102 };
103
104 /** Type used for JSON objects. */
105 using object = array_t<pair>;
106
107 /** Type used for JSON arrays. */
108 using array = array_t<value_t>;
109
110 /** Type of this JSON value. */
111 type type { type::uninitialized };
112 union {
113 object object_;
114 array array_;
115 string string_;
116 double float_;
117 int64_t signed_;
118 uint64_t unsigned_;
119 bool boolean_;
120 };
121
122 value_t() noexcept : type { type::uninitialized } {}
123
124 value_t(object&& value) noexcept : type { type::object }, object_(BASE_NS::move(value)) {}
125
126 value_t(array&& value) noexcept : type { type::array }, array_(BASE_NS::move(value)) {}
127
128 value_t(string value) noexcept : type { type::string }, string_(value) {}
129
130 value_t(const char* value) noexcept : value_t(string(value)) {}
131
132 explicit value_t(bool value) noexcept : type { type::boolean }, boolean_(value) {}
133
134 value_t(null value) noexcept : type { type::null } {}
135
136 template<typename Number, BASE_NS::enable_if_t<BASE_NS::is_floating_point_v<Number>, bool> = true>
137 value_t(Number value) noexcept : type { type::floating_point }, float_(static_cast<double>(value))
138 {}
139
140 template<typename Number,
141 BASE_NS::enable_if_t<!BASE_NS::is_floating_point_v<Number> && BASE_NS::is_signed_v<Number>, bool> = true>
142 value_t(Number value) noexcept : type { type::signed_int }, signed_(static_cast<int64_t>(value))
143 {}
144
145 template<typename Number, BASE_NS::enable_if_t<BASE_NS::is_unsigned_v<Number>, bool> = true>
146 value_t(Number value) noexcept : type { type::unsigned_int }, unsigned_(static_cast<uint64_t>(value))
147 {}
148
149 template<typename Value>
150 value_t(array_t<Value> values) noexcept : type { type::array }, array_(array {})
151 {
152 array_.reserve(values.size());
153 for (const auto& value : values) {
154 array_.push_back(value);
155 }
156 }
157
158 template<typename Value, size_t N>
159 value_t(Value (&value)[N]) : type { type::array }, array_(array {})
160 {
161 array_.reserve(N);
162 for (size_t i = 0; i < N; ++i) {
163 array_.push_back(value[i]);
164 }
165 }
166
167 value_t(const value_t& other) : type(other.type)
168 {
169 switch (type) {
170 case type::uninitialized:
171 break;
172 case type::object:
173 new (&object_) object(other.object_);
174 break;
175 case type::array:
176 new (&array_) array(other.array_);
177 break;
178 case type::string:
179 new (&string_) string(other.string_);
180 break;
181 case type::floating_point:
182 float_ = other.float_;
183 break;
184 case type::signed_int:
185 signed_ = other.signed_;
186 break;
187 case type::unsigned_int:
188 unsigned_ = other.unsigned_;
189 break;
190 case type::boolean:
191 boolean_ = other.boolean_;
192 break;
193 case type::null:
194 break;
195 default:
196 break;
197 }
198 }
199
200 value_t& operator=(const value_t& other)
201 {
202 if (this != &other) {
203 cleanup();
204 type = other.type;
205 switch (type) {
206 case type::uninitialized:
207 break;
208 case type::object:
209 new (&object_) object(other.object_);
210 break;
211 case type::array:
212 new (&array_) array(other.array_);
213 break;
214 case type::string:
215 new (&string_) string(other.string_);
216 break;
217 case type::floating_point:
218 float_ = other.float_;
219 break;
220 case type::signed_int:
221 signed_ = other.signed_;
222 break;
223 case type::unsigned_int:
224 unsigned_ = other.unsigned_;
225 break;
226 case type::boolean:
227 boolean_ = other.boolean_;
228 break;
229 case type::null:
230 break;
231 default:
232 break;
233 }
234 }
235 return *this;
236 }
237
238 value_t(value_t&& rhs) noexcept : type { BASE_NS::exchange(rhs.type, type::uninitialized) }
239 {
240 switch (type) {
241 case type::uninitialized:
242 break;
243 case type::object:
244 new (&object_) object(BASE_NS::move(rhs.object_));
245 break;
246 case type::array:
247 new (&array_) array(BASE_NS::move(rhs.array_));
248 break;
249 case type::string:
250 new (&string_) string(BASE_NS::move(rhs.string_));
251 break;
252 case type::floating_point:
253 float_ = rhs.float_;
254 break;
255 case type::signed_int:
256 signed_ = rhs.signed_;
257 break;
258 case type::unsigned_int:
259 unsigned_ = rhs.unsigned_;
260 break;
261 case type::boolean:
262 boolean_ = rhs.boolean_;
263 break;
264 case type::null:
265 break;
266 default:
267 break;
268 }
269 }
270
271 value_t& operator=(value_t&& rhs) noexcept
272 {
273 if (this != &rhs) {
274 cleanup();
275 type = BASE_NS::exchange(rhs.type, type::uninitialized);
276 switch (type) {
277 case type::uninitialized:
278 break;
279 case type::object:
280 new (&object_) object(BASE_NS::move(rhs.object_));
281 break;
282 case type::array:
283 new (&array_) array(BASE_NS::move(rhs.array_));
284 break;
285 case type::string:
286 new (&string_) string(BASE_NS::move(rhs.string_));
287 break;
288 case type::floating_point:
289 float_ = rhs.float_;
290 break;
291 case type::signed_int:
292 signed_ = rhs.signed_;
293 break;
294 case type::unsigned_int:
295 unsigned_ = rhs.unsigned_;
296 break;
297 case type::boolean:
298 boolean_ = rhs.boolean_;
299 break;
300 case type::null:
301 break;
302 default:
303 break;
304 }
305 }
306 return *this;
307 }
308
309 template<typename OtherT>
310 operator value_t<OtherT>() const
311 {
312 value_t<OtherT> other;
313 other.type = type;
314 switch (type) {
315 case type::uninitialized:
316 break;
317 case type::object:
318 new (&other.object_) typename value_t<OtherT>::object(BASE_NS::default_allocator());
319 other.object_.reserve(object_.size());
320 for (const auto& p : object_) {
321 other.object_.emplace_back(typename value_t<OtherT>::string(p.key), p.value);
322 }
323 break;
324 case type::array:
325 new (&other.array_) typename value_t<OtherT>::array(BASE_NS::default_allocator());
326 other.array_.reserve(array_.size());
327 for (const auto& v : array_) {
328 other.array_.emplace_back(v);
329 }
330 break;
331 case type::string:
332 new (&other.string_) typename value_t<OtherT>::string(string_);
333 break;
334 case type::floating_point:
335 other.float_ = float_;
336 break;
337 case type::signed_int:
338 other.signed_ = signed_;
339 break;
340 case type::unsigned_int:
341 other.unsigned_ = unsigned_;
342 break;
343 case type::boolean:
344 other.boolean_ = boolean_;
345 break;
346 case type::null:
347 break;
348 default:
349 break;
350 }
351 return other;
352 }
353
354 #if _MSC_VER
355 #pragma warning(push)
356 #pragma warning(disable : 4583)
357 #endif
358 ~value_t()
359 {
360 cleanup();
361 }
362 #if _MSC_VER
363 #pragma warning(pop)
364 #endif
365 template<typename T>
366 inline void destroy(T& t)
367 {
368 t.~T();
369 }
370
371 void cleanup()
372 {
373 switch (type) {
374 case type::uninitialized:
375 break;
376 case type::object:
377 destroy(object_);
378 break;
379 case type::array:
380 destroy(array_);
381 break;
382 case type::string:
383 destroy(string_);
384 break;
385 case type::floating_point:
386 break;
387 case type::signed_int:
388 break;
389 case type::unsigned_int:
390 break;
391 case type::boolean:
392 break;
393 case type::null:
394 break;
395 default:
396 break;
397 }
398 }
399
400 explicit operator bool() const noexcept
401 {
402 return type != type::uninitialized;
403 }
404
405 bool is_object() const noexcept
406 {
407 return type == type::object;
408 }
409
410 bool is_array() const noexcept
411 {
412 return type == type::array;
413 }
414
415 bool is_string() const noexcept
416 {
417 return type == type::string;
418 }
419
420 bool is_floating_point() const noexcept
421 {
422 return type == type::floating_point;
423 }
424
425 bool is_signed_int() const noexcept
426 {
427 return type == type::signed_int;
428 }
429
430 bool is_unsigned_int() const noexcept
431 {
432 return type == type::unsigned_int;
433 }
434
435 bool is_number() const noexcept
436 {
437 return type == type::floating_point || type == type::signed_int || type == type::unsigned_int;
438 }
439
440 bool is_boolean() const noexcept
441 {
442 return type == type::boolean;
443 }
444
445 bool is_null() const noexcept
446 {
447 return type == type::null;
448 }
449
450 bool empty() const noexcept
451 {
452 if (is_object()) {
453 return object_.empty();
454 } else if (is_array()) {
455 return array_.empty();
456 }
457 return true;
458 }
459
460 template<typename T>
461 T as_number() const
462 {
463 switch (type) {
464 case type::floating_point:
465 return static_cast<T>(float_);
466 case type::signed_int:
467 return static_cast<T>(signed_);
468 case type::unsigned_int:
469 return static_cast<T>(unsigned_);
470 default:
471 return 0;
472 }
473 }
474
475 const value_t* find(BASE_NS::string_view key) const noexcept
476 {
477 if (type == type::object) {
478 for (auto& t : object_) {
479 if (t.key == key) {
480 return &t.value;
481 }
482 }
483 }
484 return nullptr;
485 }
486
487 value_t& operator[](const BASE_NS::string_view& key)
488 {
489 if (type == type::object) {
490 for (auto& t : object_) {
491 if (t.key == key) {
492 return t.value;
493 }
494 }
495 object_.emplace_back(value_t<Tag>::string(key), value_t<Tag> {});
496 return object_.back().value;
497 }
498 return *this;
499 }
500 };
501 } // namespace json
502 CORE_END_NAMESPACE()
503
504 #ifdef JSON_IMPL
505 #include <securec.h>
506
507 #include <base/containers/fixed_string.h>
508 #include <base/util/uid.h>
509
CORE_BEGIN_NAMESPACE()510 CORE_BEGIN_NAMESPACE()
511 namespace json {
512 inline bool isWhite(char data)
513 {
514 return ((data == ' ') || (data == '\n') || (data == '\r') || (data == '\t'));
515 }
516
517 inline bool isSign(char data)
518 {
519 return ((data == '+') || (data == '-'));
520 }
521
522 inline bool isDigit(char data)
523 {
524 return ((data >= '0') && (data <= '9'));
525 }
526
527 inline bool isHex(char data)
528 {
529 return ((data >= '0') && (data <= '9')) || ((data >= 'a') && (data <= 'f')) || ((data >= 'A') && (data <= 'F'));
530 }
531
532 inline const char* trim(const char* data)
533 {
534 while (*data && isWhite(*data)) {
535 data++;
536 }
537 return data;
538 }
539
540 // values
541 template<typename T>
542 const char* parse_string(const char* data, value_t<T>& res)
543 {
544 const char* start = data;
545 for (; *data != 0; data++) {
546 if (*data == '\\' && data[1]) {
547 // escape.. (parse just enough to not stop too early)
548 if (data[1] == '\\' || data[1] == '"' || data[1] == '/' || data[1] == 'b' || data[1] == 'f' ||
549 data[1] == 'n' || data[1] == 'r' || data[1] == 't') {
550 ++data;
551 continue;
552 } else if (data[1] == 'u') {
553 data += 2;
554 for (const char* end = data + 4; data != end; ++data) {
555 if (*data == 0 || !isHex(*data)) {
556 // invalid Unicode
557 return data;
558 }
559 }
560 --data;
561 } else {
562 // invalid escape
563 return data;
564 }
565 } else if (*data == '"') {
566 res = value_t<T> { typename value_t<T>::string { start, static_cast<size_t>(data - start) } };
567 return data + 1;
568 } else if (static_cast<unsigned char>(*data) < 0x20) {
569 // unescaped control
570 return data;
571 }
572 }
573 return data;
574 }
575
576 template<typename T>
577 const char* parse_number(const char* data, value_t<T>& res)
578 {
579 bool negative = false;
580 const char* beg = data;
581 if (*data == '-') {
582 negative = true;
583 data++;
584 if (!isDigit(*data)) {
585 // no digits after '-'
586 return data;
587 }
588 }
589 bool fraction = false;
590 bool exponent = false;
591
592 if (*data == '0') {
593 ++data;
594 // after leading zero only '.', 'e' and 'E' allowed
595 if (*data == '.') {
596 ++data;
597 fraction = true;
598 } else if (*data == 'e' || *data == 'E') {
599 ++data;
600 exponent = true;
601 }
602 } else {
603 while (isDigit(*data)) {
604 ++data;
605 }
606 if (*data == '.') {
607 ++data;
608 fraction = true;
609 } else if (*data == 'e' || *data == 'E') {
610 ++data;
611 exponent = true;
612 }
613 }
614
615 if (fraction) {
616 // fraction must start with a digit
617 if (isDigit(*data)) {
618 ++data;
619 } else {
620 // fraction missing first digit
621 return data;
622 }
623 // fraction may contain digits up to begining of exponent ('e' or 'E')
624 while (isDigit(*data)) {
625 ++data;
626 }
627 if (*data == 'e' || *data == 'E') {
628 ++data;
629 exponent = true;
630 }
631 }
632 if (exponent) {
633 // exponent must start with '-' or '+' followed by a digit, or digit
634 if (*data == '-' || *data == '+') {
635 ++data;
636 }
637 if (isDigit(*data)) {
638 ++data;
639 } else {
640 // exponent missing first digit
641 return data;
642 }
643 while (isDigit(*data)) {
644 ++data;
645 }
646 }
647 if (data != beg) {
648 char* end;
649 if (fraction || exponent) {
650 res = value_t<T>(strtod(beg, &end));
651 } else if (negative) {
652 res = value_t<T>(strtoll(beg, &end, 10));
653 } else {
654 res = value_t<T>(strtoull(beg, &end, 10));
655 }
656 return data;
657 }
658 // invalid json
659 return data;
660 }
661
662 template<typename T>
663 const char* parse_boolean(const char* data, value_t<T>& res)
664 {
665 if (*data == 't') {
666 ++data;
667 const char rue[] = { 'r', 'u', 'e' };
668 for (unsigned i = 0u; i < sizeof(rue); ++i) {
669 if (data[i] == 0 || data[i] != rue[i]) {
670 // non-string starting with 't' but != "true"
671 return data;
672 }
673 }
674
675 res = value_t<T>(true);
676 data += sizeof(rue);
677 } else if (*data == 'f') {
678 ++data;
679 const char alse[] = { 'a', 'l', 's', 'e' };
680 for (unsigned i = 0u; i < sizeof(alse); ++i) {
681 if (data[i] == 0 || data[i] != alse[i]) {
682 // non-string starting with 'f' but != "false"
683 return data;
684 }
685 }
686 res = value_t<T>(false);
687 data += sizeof(alse);
688 } else {
689 // non-string not starting with 'f' or 't'
690 return data;
691 }
692 return data;
693 }
694
695 template<typename T>
696 const char* parse_null(const char* data, value_t<T>& res)
697 {
698 if (*data == 'n') {
699 ++data;
700 const char ull[] = { 'u', 'l', 'l' };
701 for (unsigned i = 0u; i < sizeof(ull); ++i) {
702 if (data[i] == 0 || data[i] != ull[i]) {
703 // non-string starting with 'n' but != "null"
704 return data;
705 }
706 }
707 res = value_t<T>(typename value_t<T>::null {});
708 data += sizeof(ull);
709 } else {
710 // invalid json
711 return data;
712 }
713 return data;
714 }
715
716 template<typename T>
717 void add(value_t<T>& v, value_t<T>&& value)
718 {
719 switch (v.type) {
720 case type::uninitialized:
721 v = BASE_NS::move(value);
722 break;
723 case type::object:
724 v.object_.back().value = BASE_NS::move(value);
725 break;
726 case type::array:
727 v.array_.push_back(BASE_NS::move(value));
728 break;
729 case type::string:
730 case type::floating_point:
731 case type::signed_int:
732 case type::unsigned_int:
733 case type::boolean:
734 case type::null:
735 default:
736 break;
737 }
738 }
739
740 template<typename T>
741 value_t<T> parse(const char* data)
742 {
743 if (!data) {
744 return {};
745 }
746 using jsonValue = value_t<T>;
747 typename jsonValue::array stack;
748 // push an uninitialized value which will get the final value during parsing
749 stack.emplace_back();
750
751 bool acceptValue = true;
752 while (*data) {
753 data = trim(data);
754 if (*data == '{') {
755 // start of an object
756 if (!acceptValue) {
757 return {};
758 }
759 data = trim(data + 1);
760 if (*data == '}') {
761 data = trim(data + 1);
762 // handle empty object.
763 add(stack.back(), jsonValue(typename jsonValue::object {}));
764 acceptValue = false;
765 } else if (*data == '"') {
766 // try to read the key
767 jsonValue key;
768 data = trim(parse_string(data + 1, key));
769
770 if (*data != ':') {
771 // missing : after key
772 return {};
773 }
774 data = trim(data + 1);
775 // push the object with key and missing value on the stack and hope to find a value next
776 stack.emplace_back(typename jsonValue::object {})
777 .object_.emplace_back(BASE_NS::move(key.string_), jsonValue {});
778 acceptValue = true;
779 } else {
780 // missing start of key or end of object
781 return {};
782 }
783 } else if (*data == '}') {
784 // end of an object
785 if (stack.back().type != type::object) {
786 // unexpected }
787 return {};
788 }
789 // check are we missing a value ('{"":}', '{"":"",}' )
790 if (acceptValue) {
791 return {};
792 }
793 data = trim(data + 1);
794 // move this object to the next in the stack
795 auto value = BASE_NS::move(stack.back());
796 stack.pop_back();
797 if (stack.empty()) {
798 // invalid json
799 return {};
800 }
801 add(stack.back(), BASE_NS::move(value));
802 acceptValue = false;
803 } else if (*data == '[') {
804 // start of an array
805 if (!acceptValue) {
806 // unexpected [
807 return {};
808 }
809 data = trim(data + 1);
810 if (*data == ']') {
811 data = trim(data + 1);
812 // handle empty array.
813 add(stack.back(), jsonValue(typename jsonValue::array {}));
814 acceptValue = false;
815 } else {
816 // push the empty array on the stack and hope to find values
817 stack.push_back(typename jsonValue::array {});
818 acceptValue = true;
819 }
820 } else if (*data == ']') {
821 // end of an array
822 if (stack.back().type != type::array) {
823 // unexpected ]
824 return {};
825 }
826 // check are we missing a value ('[1,]' '[1]]')
827 if (acceptValue) {
828 // unexpected ]
829 return {};
830 }
831 data = trim(data + 1);
832
833 auto value = BASE_NS::move(stack.back());
834 stack.pop_back();
835 if (stack.empty()) {
836 // invalid json
837 return {};
838 }
839 add(stack.back(), BASE_NS::move(value));
840 acceptValue = false;
841 } else if (*data == ',') {
842 // comma is allowed when the previous value was complete and we have an incomplete object or array on the
843 // stack.
844 if (!acceptValue && stack.back().type == type::object) {
845 data = trim(data + 1);
846 if (*data != '"') {
847 // missing key for next object
848 return {};
849 }
850 // try to read the key
851 jsonValue key;
852 data = trim(parse_string(data + 1, key));
853
854 if (*data != ':') {
855 // missing value for next object
856 return {};
857 }
858 data = trim(data + 1);
859 stack.back().object_.emplace_back(BASE_NS::move(key.string_), jsonValue {});
860 acceptValue = true;
861 } else if (!acceptValue && stack.back().type == type::array) {
862 data = trim(data + 1);
863 acceptValue = true;
864 } else {
865 // comma allowed only between objects and values inside an array
866 return {};
867 }
868 } else if (*data == '"') {
869 jsonValue value;
870 data = trim(parse_string(data + 1, value));
871 if (acceptValue && value.type == type::string) {
872 add(stack.back(), BASE_NS::move(value));
873 acceptValue = false;
874 } else {
875 // unexpected "
876 return {};
877 }
878 } else if (isSign(*data) || isDigit(*data)) {
879 jsonValue value;
880 data = trim(parse_number(data, value));
881 if (acceptValue && value.type != type::uninitialized) {
882 add(stack.back(), BASE_NS::move(value));
883 acceptValue = false;
884 } else {
885 // failed parsing number
886 return {};
887 }
888 } else if ((*data == 't') || (*data == 'f')) {
889 jsonValue value;
890 data = trim(parse_boolean(data, value));
891 if (acceptValue && value.type == type::boolean) {
892 add(stack.back(), BASE_NS::move(value));
893 acceptValue = false;
894 } else {
895 // failed parsing boolean
896 return {};
897 }
898 } else if (*data == 'n') {
899 jsonValue value;
900 data = trim(parse_null(data, value));
901 if (acceptValue && value.type == type::null) {
902 add(stack.back(), BASE_NS::move(value));
903 acceptValue = false;
904 } else {
905 // failed parsing null
906 return {};
907 }
908 } else {
909 // unexpected character
910 return {};
911 }
912 }
913 // check if we are missing a value ('{"":' '[')
914 if (acceptValue) {
915 return {};
916 }
917
918 auto value = BASE_NS::move(stack.front());
919 return value;
920 }
921
922 template value parse(const char*);
923 template standalone_value parse(const char*);
924 // end of parser
925 template<typename T>
926 void append(BASE_NS::string& out, const typename value_t<T>::string& string)
927 {
928 out += '"';
929 out.append(escape(string));
930 out += '"';
931 }
932
933 template<typename T>
934 void append(BASE_NS::string& out, const typename value_t<T>::object& object)
935 {
936 out += '{';
937 int count = 0;
938 for (const auto& v : object) {
939 if (count++) {
940 out += ',';
941 }
942 append<T>(out, v.key);
943 out += ':';
944 out += to_string(v.value);
945 }
946 out += '}';
947 }
948
949 template<typename T>
950 void append(BASE_NS::string& out, const typename value_t<T>::array& array)
951 {
952 out += '[';
953 int count = 0;
954 for (const auto& v : array) {
955 if (count++) {
956 out += ',';
957 }
958 out += to_string(v);
959 }
960 out += ']';
961 }
962
963 template<typename T>
964 void append(BASE_NS::string& out, const double floatingPoint)
965 {
966 constexpr const char* FLOATING_FORMAT_STR = "%.17g";
967 if (const int size = snprintf(nullptr, 0, FLOATING_FORMAT_STR, floatingPoint); size > 0) {
968 const size_t oldSize = out.size();
969 out.resize(oldSize + size);
970 const size_t newSize = out.size();
971 // "At most bufsz - 1 characters are written." string has size() characters + 1 for null so use size() +
972 // 1 as the total size. If resize() failed string size() hasn't changed, buffer will point to the null
973 // character and bufsz will be 1 i.e. only the null character will be written.
974 snprintf_s(
975 out.data() + oldSize, newSize + 1 - oldSize, static_cast<size_t>(size), FLOATING_FORMAT_STR, floatingPoint);
976 }
977 }
978
979 template<typename T>
980 BASE_NS::string to_string(const value_t<T>& value)
981 {
982 BASE_NS::string out;
983 switch (value.type) {
984 case type::uninitialized:
985 break;
986
987 case type::object:
988 append<T>(out, value.object_);
989 break;
990
991 case type::array:
992 append<T>(out, value.array_);
993 break;
994
995 case type::string:
996 append<T>(out, value.string_);
997 break;
998
999 case type::floating_point:
1000 append<T>(out, value.float_);
1001 break;
1002
1003 case type::signed_int:
1004 out += BASE_NS::to_string(value.signed_);
1005 break;
1006
1007 case type::unsigned_int:
1008 out += BASE_NS::to_string(value.unsigned_);
1009 break;
1010
1011 case type::boolean:
1012 if (value.boolean_) {
1013 out += "true";
1014 } else {
1015 out += "false";
1016 }
1017 break;
1018
1019 case type::null:
1020 out += "null";
1021 break;
1022
1023 default:
1024 break;
1025 }
1026 return out;
1027 }
1028
1029 template BASE_NS::string to_string(const value& value);
1030 template BASE_NS::string to_string(const standalone_value& value);
1031
1032 int codepoint(BASE_NS::string_view str)
1033 {
1034 int code = 0;
1035 for (size_t u = 0; u < 4; ++u) {
1036 const char chr = str[u];
1037 code <<= 4U;
1038 code += BASE_NS::HexToDec(chr);
1039 }
1040 return code;
1041 }
1042
1043 BASE_NS::string unescape(BASE_NS::string_view str)
1044 {
1045 BASE_NS::string unescaped;
1046 unescaped.reserve(str.size());
1047 for (size_t i = 0; i < str.size();) {
1048 auto chr = str[i];
1049 if (chr == '\\') {
1050 ++i;
1051 chr = str[i];
1052 if (chr == '"') {
1053 unescaped += '"'; // Quotation mark
1054 } else if (chr == '\\') {
1055 unescaped += '\\'; // Reverse solidus
1056 } else if (chr == '/') {
1057 unescaped += '/'; // Solidus.. we do unescape this..
1058 } else if (chr == 'b') {
1059 unescaped += '\b'; // Backspace
1060 } else if (chr == 'f') {
1061 unescaped += '\f'; // Formfeed
1062 } else if (chr == 'n') {
1063 unescaped += '\n'; // Linefeed
1064 } else if (chr == 'r') {
1065 unescaped += '\r'; // Carriage return
1066 } else if (chr == 't') {
1067 unescaped += '\t'; // Horizontal tab
1068 } else if (chr == 'u') { // Unicode character
1069 if ((i + 4U) < str.size()) { // Expecting 4 hexadecimal values
1070 // Read the Unicode code point.
1071 int code = codepoint(str.substr(i + 1, 4U));
1072 i += 4U;
1073 // Codepoints U+010000 to U+10FFFF are encoded as UTF-16 surrogate pairs. High surrogate between
1074 // 0xD800-0xDBFF and low between 0xDC00-0xDFFF.
1075 if (code >= 0xd800 && code <= 0xdbff) {
1076 // See if there's an other \uXXXX value in the correct range.
1077 if ((i + 6U) < str.size()) {
1078 auto next = str.substr(i + 1, 6U);
1079 if (next[0] == '\\' && next[1] == 'u') {
1080 next.remove_prefix(2);
1081 int low = codepoint(next);
1082 i += 6U;
1083 if (low >= 0xdc00 && low <= 0xdfff) {
1084 // Surrogate pair encoding: 0x10000 + (Hi - 0xD800) * 0x400 + (Lo - 0xDC00)
1085 code = ((code << 10) + low - ((0xd800 << 10) + 0xdc00 - 0x10000));
1086 }
1087 }
1088 }
1089 }
1090 // Convert code point to UTF-8.
1091 if (code < 0x80) {
1092 // 1-byte characters: 0xxxxxxx (ASCII)
1093 unescaped += static_cast<char>(code);
1094 } else if (code < 0x7ff) {
1095 // 2-byte characters: 110xxxxx 10xxxxxx
1096 unescaped += static_cast<char>(0xc0U | (static_cast<unsigned int>(code) >> 6U));
1097 unescaped += static_cast<char>(0x80U | (static_cast<unsigned int>(code) & 0x3fU));
1098 } else if (code <= 0xffff) {
1099 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
1100 unescaped += static_cast<char>(0xe0U | (static_cast<unsigned int>(code) >> 12u));
1101 unescaped += static_cast<char>(0x80U | ((static_cast<unsigned int>(code) >> 6U) & 0x3FU));
1102 unescaped += static_cast<char>(0x80U | (static_cast<unsigned int>(code) & 0x3Fu));
1103 } else {
1104 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1105 unescaped += (static_cast<char>(0xf0U | (static_cast<unsigned int>(code) >> 18U)));
1106 unescaped += (static_cast<char>(0x80U | ((static_cast<unsigned int>(code) >> 12U) & 0x3fU)));
1107 unescaped += (static_cast<char>(0x80U | ((static_cast<unsigned int>(code) >> 6U) & 0x3fU)));
1108 unescaped += (static_cast<char>(0x80U | (static_cast<unsigned int>(code) & 0x3fU)));
1109 }
1110 }
1111 } else {
1112 }
1113 ++i;
1114 } else {
1115 unescaped += chr;
1116 ++i;
1117 }
1118 }
1119 return unescaped;
1120 }
1121
1122 BASE_NS::string escape(BASE_NS::string_view str)
1123 {
1124 BASE_NS::string escaped;
1125 escaped.reserve(str.size());
1126 for (size_t i = 0, end = str.size(); i < end;) {
1127 auto chr = static_cast<uint8_t>(str[i]);
1128 ++i;
1129 if (chr == '"') {
1130 escaped += "\\\""; // Quotation mark
1131 } else if (chr == '\\') {
1132 escaped += "\\\\"; // Reverse solidus
1133 } else if (chr == '\b') {
1134 escaped += "\\b"; // Backspace
1135 } else if (chr == '\f') {
1136 escaped += "\\f"; // Formfeed
1137 } else if (chr == '\n') {
1138 escaped += "\\n"; // Linefeed
1139 } else if (chr == '\r') {
1140 escaped += "\\r"; // Carriage return
1141 } else if (chr == '\t') {
1142 escaped += "\\t"; // Horizontal tab
1143 } else if (chr < 0x80) {
1144 escaped += static_cast<BASE_NS::string::value_type>(chr); // 1-byte characters: 0xxxxxxx (ASCII)
1145 } else {
1146 // Unicode
1147 unsigned code = 0U;
1148 unsigned left = 0U;
1149 // Decode first byte and figure out how many additional bytes are needed for the codepoint.
1150 if (chr < 0xE0) {
1151 // 2-byte characters: 110xxxxx 10xxxxxx
1152 if (i < end) {
1153 code = ((chr & ~0xC0U));
1154 left = 1U;
1155 }
1156 } else if (chr < 0xF0) {
1157 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
1158 if ((i + 1U) < end) {
1159 code = (chr & ~0xE0U);
1160 left = 2U;
1161 }
1162 } else if (chr < 0xF8) {
1163 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
1164 if ((i + 2U) < end) {
1165 code = (chr & ~0xF0U);
1166 left = 3U;
1167 }
1168 }
1169
1170 // Combine the remaining bytes.
1171 while (left--) {
1172 code = (code << 6U) + (str[i++] & 0x3FU);
1173 }
1174
1175 // Codepoints U+010000 to U+10FFFF are encoded as UTF-16 surrogate pairs.
1176 // Surrogate pair encoding: 0x10000 + (Hi - 0xD800) * 0x400 + (Lo - 0xDC00)
1177 if (code >= 0x010000 && code <= 0x10FFFF) {
1178 // First append the Hi value.
1179 code -= 0x10000U;
1180 const auto hi = (code >> 10U) + 0xD800U;
1181 escaped += '\\';
1182 escaped += 'u';
1183 escaped += BASE_NS::to_hex(hi);
1184
1185 // Calculate the Lo value.
1186 code = (code & 0x3FFU) + 0xDC00U;
1187 }
1188
1189 // Append the codepoint zero padded to four hex values.
1190 escaped += '\\';
1191 escaped += 'u';
1192 const auto codepoint = BASE_NS::to_hex(code);
1193 if (codepoint.size() < 4U) {
1194 escaped.append(4U - codepoint.size(), '0');
1195 }
1196 escaped += codepoint;
1197 }
1198 }
1199 return escaped;
1200 }
1201 } // namespace json
1202 CORE_END_NAMESPACE()
1203 #endif // JSON_IMPL
1204
1205 #endif // !API_CORE_JSON_JSON_H
1206