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