CPPMyth
Library to interoperate with MythTV server
Loading...
Searching...
No Matches
sajson.h
1/*
2 * Copyright (c) 2012, 2013, 2014 Chad Austin
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#pragma once
26
27#include <assert.h>
28#include <stdarg.h>
29#include <stddef.h>
30#include <string.h>
31#include <math.h>
32#include <limits.h>
33#include <ostream>
34#include <algorithm>
35#include <cstdio>
36#include <limits>
37
38#include <string> // for error messages. kill someday?
39
40#if defined(__GNUC__) || defined(__clang__)
41#define SAJSON_LIKELY(x) __builtin_expect(!!(x), 1)
42#define SAJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
43#else
44#define SAJSON_LIKELY(x) x
45#define SAJSON_UNLIKELY(x) x
46#endif
47
48namespace sajson {
49 enum type {
50 TYPE_INTEGER = 0,
51 TYPE_DOUBLE = 1,
52 TYPE_NULL = 2,
53 TYPE_FALSE = 3,
54 TYPE_TRUE = 4,
55 TYPE_STRING = 5,
56 TYPE_ARRAY = 6,
57 TYPE_OBJECT = 7,
58 };
59
60 inline std::ostream& operator<<(std::ostream& os, type t) {
61 switch (t) {
62 case TYPE_INTEGER: return os << "<integer>";
63 case TYPE_DOUBLE: return os << "<double>";
64 case TYPE_NULL: return os << "<null>";
65 case TYPE_FALSE: return os << "<false>";
66 case TYPE_TRUE: return os << "<true>";
67 case TYPE_STRING: return os << "<string>";
68 case TYPE_ARRAY: return os << "<array>";
69 case TYPE_OBJECT: return os << "<object>";
70 default: return os << "<unknown type";
71 }
72 }
73
74 static const size_t TYPE_BITS = 3;
75 static const size_t TYPE_SHIFT = sizeof(size_t) * 8 - TYPE_BITS;
76 static const size_t TYPE_MASK = (1 << TYPE_BITS) - 1;
77 static const size_t VALUE_MASK = size_t(-1) >> TYPE_BITS;
78
79 static const size_t ROOT_MARKER = size_t(-1) & VALUE_MASK;
80
81 inline type get_element_type(size_t s) {
82 return static_cast<type>((s >> TYPE_SHIFT) & TYPE_MASK);
83 }
84
85 inline size_t get_element_value(size_t s) {
86 return s & VALUE_MASK;
87 }
88
89 inline size_t make_element(type t, size_t value) {
90 //assert(value & VALUE_MASK == 0);
91 //value &= VALUE_MASK;
92 return value | (static_cast<size_t>(t) << TYPE_SHIFT);
93 }
94
95 class string {
96 public:
97 string(const char* text, size_t length)
98 : text(text)
99 , _length(length)
100 {}
101
102 const char* data() const {
103 return text;
104 }
105
106 size_t length() const {
107 return _length;
108 }
109
110 std::string as_string() const {
111 return std::string(text, text + _length);
112 }
113
114 private:
115 const char* const text;
116 const size_t _length;
117
118 string(); /*=delete*/
119 };
120
121 class literal : public string {
122 public:
123 explicit literal(const char* text)
124 : string(text, strlen(text))
125 {}
126 };
127
129 {
130 size_t key_start;
131 size_t key_end;
132 size_t value;
133 };
134
135 struct object_key_comparator
136 {
137 object_key_comparator(const char* object_data)
138 : data(object_data)
139 {
140 }
141
142 bool operator()(const object_key_record& lhs, const string& rhs) const {
143 const size_t lhs_length = lhs.key_end - lhs.key_start;
144 const size_t rhs_length = rhs.length();
145 if (lhs_length < rhs_length) {
146 return true;
147 } else if (lhs_length > rhs_length) {
148 return false;
149 }
150 return memcmp(data + lhs.key_start, rhs.data(), lhs_length) < 0;
151 }
152
153 bool operator()(const string& lhs, const object_key_record& rhs) const {
154 return !(*this)(rhs, lhs);
155 }
156
157 bool operator()(const object_key_record& lhs, const
159 {
160 const size_t lhs_length = lhs.key_end - lhs.key_start;
161 const size_t rhs_length = rhs.key_end - rhs.key_start;
162 if (lhs_length < rhs_length) {
163 return true;
164 } else if (lhs_length > rhs_length) {
165 return false;
166 }
167 return memcmp(data + lhs.key_start, data + rhs.key_start,
168 lhs_length) < 0;
169 }
170
171 const char* data;
172 };
173
174 class refcount {
175 public:
176 refcount()
177 : pn(new size_t(1))
178 {}
179
180 refcount(const refcount& rc)
181 : pn(rc.pn)
182 {
183 ++*pn;
184 }
185
186 ~refcount() {
187 if (--*pn == 0) {
188 delete pn;
189 }
190 }
191
192 size_t count() const {
193 return *pn;
194 }
195
196 private:
197 size_t* pn;
198
199 refcount& operator=(const refcount&);
200 };
201
202 class mutable_string_view {
203 public:
204 mutable_string_view()
205 : length(0)
206 , data(0)
207 {}
208
209 mutable_string_view(const literal& s)
210 : length(s.length())
211 {
212 data = new char[length];
213 memcpy(data, s.data(), length);
214 }
215
216 mutable_string_view(const string& s)
217 : length(s.length())
218 {
219 data = new char[length];
220 memcpy(data, s.data(), length);
221 }
222
223 ~mutable_string_view() {
224 if (uses.count() == 1) {
225 delete[] data;
226 }
227 }
228
229 size_t get_length() const {
230 return length;
231 }
232
233 char* get_data() const {
234 return data;
235 }
236
237 private:
238 refcount uses;
239 size_t length;
240 char* data;
241 };
242
244 int i;
245 size_t u;
246 };
247 // TODO: reinstate with c++03 implementation
248 //static_assert(sizeof(integer_storage) == sizeof(size_t), "integer_storage must have same size as one structure slot");
249
251 enum {
252 word_length = sizeof(double) / sizeof(size_t)
253 };
254
255#if defined(_M_IX86) || defined(__i386__) || defined(_X86_)
256 static double load(const size_t* location) {
257 return *reinterpret_cast<const double*>(location);
258 }
259 static void store(size_t* location, double value) {
260 *reinterpret_cast<double*>(location) = value;
261 }
262#else
263 static double load(const size_t* location) {
265 for (unsigned i = 0; i < double_storage::word_length; ++i) {
266 s.u[i] = location[i];
267 }
268 return s.d;
269 }
270
271 static void store(size_t* location, double value) {
273 ns.d = value;
274
275 for (int i = 0; i < ns.word_length; ++i) {
276 location[i] = ns.u[i];
277 }
278 }
279
280 double d;
281 size_t u[word_length];
282#endif
283 };
284 // TODO: reinstate with c++03 implementation
285 //static_assert(sizeof(double_storage) == sizeof(double), "double_storage should have same size as double");
286
287 class value {
288 public:
289 explicit value(type value_type, const size_t* payload, const char* text)
290 : value_type(value_type)
291 , payload(payload)
292 , text(text)
293 {}
294
295 type get_type() const {
296 return value_type;
297 }
298
299 // valid iff get_type() is TYPE_ARRAY or TYPE_OBJECT
300 size_t get_length() const {
301 assert_type_2(TYPE_ARRAY, TYPE_OBJECT);
302 return payload[0];
303 }
304
305 // valid iff get_type() is TYPE_ARRAY
306 value get_array_element(size_t index) const {
307 assert_type(TYPE_ARRAY);
308 size_t element = payload[1 + index];
309 return value(get_element_type(element), payload + get_element_value(element), text);
310 }
311
312 // valid iff get_type() is TYPE_OBJECT
313 string get_object_key(size_t index) const {
314 assert_type(TYPE_OBJECT);
315 const size_t* s = payload + 1 + index * 3;
316 return string(text + s[0], s[1] - s[0]);
317 }
318
319 // valid iff get_type() is TYPE_OBJECT
320 value get_object_value(size_t index) const {
321 assert_type(TYPE_OBJECT);
322 size_t element = payload[3 + index * 3];
323 return value(get_element_type(element), payload + get_element_value(element), text);
324 }
325
326 // valid iff get_type() is TYPE_OBJECT
327 value get_value_of_key(const string& key) const {
328 assert_type(TYPE_OBJECT);
329 size_t i = find_object_key(key);
330 assert_in_bounds(i);
331 return get_object_value(i);
332 }
333
334 // valid iff get_type() is TYPE_OBJECT
335 // return get_length() if there is no such key
336 size_t find_object_key(const string& key) const {
337 assert_type(TYPE_OBJECT);
338 const object_key_record* start = reinterpret_cast<const object_key_record*>(payload + 1);
339 const object_key_record* end = start + get_length();
340 const object_key_record* i = std::lower_bound(start, end, key, object_key_comparator(text));
341 return (i != end
342 && (i->key_end - i->key_start) == key.length()
343 && memcmp(key.data(), text + i->key_start, key.length()) == 0)? i - start : get_length();
344 }
345
346 // valid iff get_type() is TYPE_INTEGER
347 int get_integer_value() const {
348 assert_type(TYPE_INTEGER);
350 s.u = payload[0];
351 return s.i;
352 }
353
354 // valid iff get_type() is TYPE_DOUBLE
355 double get_double_value() const {
356 assert_type(TYPE_DOUBLE);
357 return double_storage::load(payload);
358 }
359
360 // valid iff get_type() is TYPE_INTEGER or TYPE_DOUBLE
361 double get_number_value() const {
362 assert_type_2(TYPE_INTEGER, TYPE_DOUBLE);
363 if (get_type() == TYPE_INTEGER) {
364 return get_integer_value();
365 } else {
366 return get_double_value();
367 }
368 }
369
370 // valid iff get_type() is TYPE_STRING
371 size_t get_string_length() const {
372 assert_type(TYPE_STRING);
373 return payload[1] - payload[0];
374 }
375
376 // valid iff get_type() is TYPE_STRING
377 std::string as_string() const {
378 assert_type(TYPE_STRING);
379 return std::string(text + payload[0], text + payload[1]);
380 }
381
382 private:
383 void assert_type(type expected) const {
384 assert(expected == get_type());
385 (void)expected;
386 }
387
388 void assert_type_2(type e1, type e2) const {
389 assert(e1 == get_type() || e2 == get_type());
390 (void)e1;
391 (void)e2;
392 }
393
394 void assert_in_bounds(size_t i) const {
395 assert(i < get_length());
396 (void)i;
397 }
398
399 const type value_type;
400 const size_t* const payload;
401 const char* const text;
402
403 };
404
405 class document {
406 public:
407 explicit document(mutable_string_view& input, const size_t* structure, type root_type, const size_t* root, size_t error_line, size_t error_column, const std::string& error_message)
408 : input(input)
409 , structure(structure)
410 , root_type(root_type)
411 , root(root)
412 , error_line(error_line)
413 , error_column(error_column)
414 , error_message(error_message)
415 {}
416
417#if __cplusplus >= 201103L
418 document(const document&) = delete;
419 void operator=(const document&) = delete;
420
421 document(document&& rhs)
422 : uses(rhs.uses)
423 , input(rhs.input)
424 , structure(rhs.structure)
425 , root_type(rhs.root_type)
426 , root(rhs.root)
427 , error_line(rhs.error_line)
428 , error_column(rhs.error_column)
429 , error_message(rhs.error_message)
430 {}
431#else
432 private:
433 void operator=(const document& rhs);
434
435 public:
436 document(const document& rhs)
437 : uses(rhs.uses)
438 , input(rhs.input)
439 , structure(rhs.structure)
440 , root_type(rhs.root_type)
441 , root(rhs.root)
442 , error_line(rhs.error_line)
443 , error_column(rhs.error_column)
444 , error_message(rhs.error_message)
445 {}
446#endif
447
448 ~document() {
449 if (uses.count() == 1) {
450 delete[] structure;
451 }
452 }
453
454 bool is_valid() const {
455 return !!structure;
456 }
457
458 value get_root() const {
459 return value(root_type, root, input.get_data());
460 }
461
462 size_t get_error_line() const {
463 return error_line;
464 }
465
466 size_t get_error_column() const {
467 return error_column;
468 }
469
470 std::string get_error_message() const {
471 return error_message;
472 }
473
474 private:
475 refcount uses;
477 const size_t* const structure;
478 const type root_type;
479 const size_t* const root;
480 const size_t error_line;
481 const size_t error_column;
482 const std::string error_message;
483 };
484
485 class parser {
486 public:
487 parser(const mutable_string_view& msv, size_t* structure)
488 : input(msv)
489 , input_end(input.get_data() + input.get_length())
490 , structure(structure)
491 , p(input.get_data())
492 , temp(structure)
493 , root_type(TYPE_NULL)
494 , out(structure + input.get_length())
495 , error_line(0)
496 , error_column(0)
497 {}
498
499 document get_document() {
500 if (parse()) {
501 return document(input, structure, root_type, out, 0, 0, std::string());
502 } else {
503 delete[] structure;
504 return document(input, 0, TYPE_NULL, 0, error_line, error_column, error_message);
505 }
506 }
507
508 private:
510 operator bool() const {
511 return false;
512 }
513 };
514
515 struct parse_result {
516 parse_result(error_result)
517 : success(false)
518 , value_type(TYPE_NULL)
519 {}
520
521 parse_result(type t)
522 : success(true)
523 , value_type(t)
524 {}
525
526 bool operator!() const {
527 return !success;
528 }
529
530 bool success;
531 type value_type;
532 };
533
534 bool at_eof() {
535 return p == input_end;
536 }
537
538 char peek_structure() {
539 for (;;) {
540 if (p == input_end) {
541 // 0 is never legal as a structural character in json text so treat it as eof
542 return 0;
543 }
544 switch (*p) {
545 case 0x20:
546 case 0x09:
547 case 0x0A:
548 case 0x0D:
549 ++p;
550 continue;
551 default:
552 return *p;
553 }
554 }
555 }
556
557 error_result error(const char* format, ...) {
558 error_line = 1;
559 error_column = 1;
560
561 char* c = input.get_data();
562 while (c < p) {
563 if (*c == '\r') {
564 if (c + 1 < p && c[1] == '\n') {
565 ++error_line;
566 error_column = 1;
567 ++c;
568 } else {
569 ++error_line;
570 error_column = 1;
571 }
572 } else if (*c == '\n') {
573 ++error_line;
574 error_column = 1;
575 } else {
576 // TODO: count UTF-8 characters
577 ++error_column;
578 }
579 ++c;
580 }
581
582
583 char buf[1024];
584 buf[1023] = 0;
585 va_list ap;
586 va_start(ap, format);
587 vsnprintf(buf, 1023, format, ap);
588 va_end(ap);
589
590 error_message = buf;
591 return error_result();
592 }
593
594 bool parse() {
595 char c = peek_structure();
596 if (c == 0) {
597 return error("no root element");
598 }
599
600 type current_structure_type;
601 if (c == '[') {
602 current_structure_type = TYPE_ARRAY;
603 } else if (c == '{') {
604 current_structure_type = TYPE_OBJECT;
605 } else {
606 return error("document root must be object or array");
607 }
608 ++p;
609
610 size_t* current_base = temp;
611 *temp++ = make_element(current_structure_type, ROOT_MARKER);
612
613 parse_result result = error_result();
614
615 for (;;) {
616 const char closing_bracket = (current_structure_type == TYPE_OBJECT ? '}' : ']');
617 const bool is_first_element = temp == current_base + 1;
618 bool had_comma = false;
619
620 c = peek_structure();
621 if (is_first_element) {
622 if (c == ',') {
623 return error("unexpected comma");
624 }
625 } else {
626 if (c == ',') {
627 ++p;
628 c = peek_structure();
629 had_comma = true;
630 } else if (c != closing_bracket) {
631 return error("expected ,");
632 }
633 }
634
635 if (current_structure_type == TYPE_OBJECT && c != '}') {
636 if (c != '"') {
637 return error("object key must be quoted");
638 }
639 result = parse_string(temp);
640 if (!result) {
641 return error("invalid object key");
642 }
643 if (peek_structure() != ':') {
644 return error("expected :");
645 }
646 ++p;
647 temp += 2;
648 }
649
650 switch (peek_structure()) {
651 type next_type;
652 parse_result (parser::*structure_installer)(size_t* base);
653
654 case 0:
655 return error("unexpected end of input");
656 case 'n':
657 result = parse_null();
658 break;
659 case 'f':
660 result = parse_false();
661 break;
662 case 't':
663 result = parse_true();
664 break;
665 case '0':
666 case '1':
667 case '2':
668 case '3':
669 case '4':
670 case '5':
671 case '6':
672 case '7':
673 case '8':
674 case '9':
675 case '-':
676 result = parse_number();
677 break;
678 case '"':
679 result = parse_string();
680 break;
681
682 case '[':
683 next_type = TYPE_ARRAY;
684 goto push;
685 case '{':
686 next_type = TYPE_OBJECT;
687 goto push;
688 push: {
689 ++p;
690 size_t* previous_base = current_base;
691 current_base = temp;
692 *temp++ = make_element(current_structure_type, previous_base - structure);
693 current_structure_type = next_type;
694 continue;
695 }
696
697 case ']':
698 if (current_structure_type == TYPE_ARRAY) {
699 structure_installer = &parser::install_array;
700 goto pop;
701 } else {
702 return error("expected }");
703 }
704 case '}':
705 if (current_structure_type == TYPE_OBJECT) {
706 structure_installer = &parser::install_object;
707 goto pop;
708 } else {
709 return error("expected ]");
710 }
711 pop: {
712 if (had_comma) {
713 return error("trailing commas not allowed");
714 }
715 ++p;
716 size_t element = *current_base;
717 result = (this->*structure_installer)(current_base + 1);
718 size_t parent = get_element_value(element);
719 if (parent == ROOT_MARKER) {
720 root_type = result.value_type;
721 goto done;
722 }
723 temp = current_base;
724 current_base = structure + parent;
725 current_structure_type = get_element_type(element);
726 break;
727 }
728 case ',':
729 return error("unexpected comma");
730 default:
731 return error("cannot parse unknown value");
732 }
733
734 if (!result) {
735 return result.success;
736 }
737
738 *temp++ = make_element(result.value_type, out - current_base - 1);
739 }
740
741 done:
742 if (0 == peek_structure()) {
743 return true;
744 } else {
745 return error("expected end of input");
746 }
747 }
748
749 bool has_remaining_characters(ptrdiff_t remaining) {
750 return input_end - p >= remaining;
751 }
752
753 parse_result parse_null() {
754 if (SAJSON_UNLIKELY(!has_remaining_characters(4))) {
755 return error("unexpected end of input");
756 }
757 char p1 = p[1];
758 char p2 = p[2];
759 char p3 = p[3];
760 if (SAJSON_UNLIKELY(p1 != 'u' || p2 != 'l' || p3 != 'l')) {
761 return error("expected 'null'");
762 }
763 p += 4;
764 return TYPE_NULL;
765 }
766
767 parse_result parse_false() {
768 if (SAJSON_UNLIKELY(!has_remaining_characters(5))) {
769 return error("unexpected end of input");
770 }
771 char p1 = p[1];
772 char p2 = p[2];
773 char p3 = p[3];
774 char p4 = p[4];
775 if (SAJSON_UNLIKELY(p1 != 'a' || p2 != 'l' || p3 != 's' || p4 != 'e')) {
776 return error("expected 'false'");
777 }
778 p += 5;
779 return TYPE_FALSE;
780 }
781
782 parse_result parse_true() {
783 if (SAJSON_UNLIKELY(!has_remaining_characters(4))) {
784 return error("unexpected end of input");
785 }
786 char p1 = p[1];
787 char p2 = p[2];
788 char p3 = p[3];
789 if (SAJSON_UNLIKELY(p1 != 'r' || p2 != 'u' || p3 != 'e')) {
790 return error("expected 'true'");
791 }
792 p += 4;
793 return TYPE_TRUE;
794 }
795
796 static double pow10(int exponent) {
797 if (exponent > 308) {
798 return std::numeric_limits<double>::infinity();
799 } else if (exponent < -323) {
800 return 0.0;
801 }
802 static const double constants[] = {
803 1e-323,1e-322,1e-321,1e-320,1e-319,1e-318,1e-317,1e-316,1e-315,1e-314,
804 1e-313,1e-312,1e-311,1e-310,1e-309,1e-308,1e-307,1e-306,1e-305,1e-304,
805 1e-303,1e-302,1e-301,1e-300,1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,
806 1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,
807 1e-283,1e-282,1e-281,1e-280,1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,
808 1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,
809 1e-263,1e-262,1e-261,1e-260,1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,
810 1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,
811 1e-243,1e-242,1e-241,1e-240,1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,
812 1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,
813 1e-223,1e-222,1e-221,1e-220,1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,
814 1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,
815 1e-203,1e-202,1e-201,1e-200,1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,
816 1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,
817 1e-183,1e-182,1e-181,1e-180,1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,
818 1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,
819 1e-163,1e-162,1e-161,1e-160,1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,
820 1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,
821 1e-143,1e-142,1e-141,1e-140,1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,
822 1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,
823 1e-123,1e-122,1e-121,1e-120,1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,
824 1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,
825 1e-103,1e-102,1e-101,1e-100,1e-99,1e-98,1e-97,1e-96,1e-95,1e-94,1e-93,
826 1e-92,1e-91,1e-90,1e-89,1e-88,1e-87,1e-86,1e-85,1e-84,1e-83,1e-82,1e-81,
827 1e-80,1e-79,1e-78,1e-77,1e-76,1e-75,1e-74,1e-73,1e-72,1e-71,1e-70,1e-69,
828 1e-68,1e-67,1e-66,1e-65,1e-64,1e-63,1e-62,1e-61,1e-60,1e-59,1e-58,1e-57,
829 1e-56,1e-55,1e-54,1e-53,1e-52,1e-51,1e-50,1e-49,1e-48,1e-47,1e-46,1e-45,
830 1e-44,1e-43,1e-42,1e-41,1e-40,1e-39,1e-38,1e-37,1e-36,1e-35,1e-34,1e-33,
831 1e-32,1e-31,1e-30,1e-29,1e-28,1e-27,1e-26,1e-25,1e-24,1e-23,1e-22,1e-21,
832 1e-20,1e-19,1e-18,1e-17,1e-16,1e-15,1e-14,1e-13,1e-12,1e-11,1e-10,1e-9,
833 1e-8,1e-7,1e-6,1e-5,1e-4,1e-3,1e-2,1e-1,1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,
834 1e8,1e9,1e10,1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20,1e21,
835 1e22,1e23,1e24,1e25,1e26,1e27,1e28,1e29,1e30,1e31,1e32,1e33,1e34,1e35,
836 1e36,1e37,1e38,1e39,1e40,1e41,1e42,1e43,1e44,1e45,1e46,1e47,1e48,1e49,
837 1e50,1e51,1e52,1e53,1e54,1e55,1e56,1e57,1e58,1e59,1e60,1e61,1e62,1e63,
838 1e64,1e65,1e66,1e67,1e68,1e69,1e70,1e71,1e72,1e73,1e74,1e75,1e76,1e77,
839 1e78,1e79,1e80,1e81,1e82,1e83,1e84,1e85,1e86,1e87,1e88,1e89,1e90,1e91,
840 1e92,1e93,1e94,1e95,1e96,1e97,1e98,1e99,1e100,1e101,1e102,1e103,1e104,
841 1e105,1e106,1e107,1e108,1e109,1e110,1e111,1e112,1e113,1e114,1e115,1e116,
842 1e117,1e118,1e119,1e120,1e121,1e122,1e123,1e124,1e125,1e126,1e127,1e128,
843 1e129,1e130,1e131,1e132,1e133,1e134,1e135,1e136,1e137,1e138,1e139,1e140,
844 1e141,1e142,1e143,1e144,1e145,1e146,1e147,1e148,1e149,1e150,1e151,1e152,
845 1e153,1e154,1e155,1e156,1e157,1e158,1e159,1e160,1e161,1e162,1e163,1e164,
846 1e165,1e166,1e167,1e168,1e169,1e170,1e171,1e172,1e173,1e174,1e175,1e176,
847 1e177,1e178,1e179,1e180,1e181,1e182,1e183,1e184,1e185,1e186,1e187,1e188,
848 1e189,1e190,1e191,1e192,1e193,1e194,1e195,1e196,1e197,1e198,1e199,1e200,
849 1e201,1e202,1e203,1e204,1e205,1e206,1e207,1e208,1e209,1e210,1e211,1e212,
850 1e213,1e214,1e215,1e216,1e217,1e218,1e219,1e220,1e221,1e222,1e223,1e224,
851 1e225,1e226,1e227,1e228,1e229,1e230,1e231,1e232,1e233,1e234,1e235,1e236,
852 1e237,1e238,1e239,1e240,1e241,1e242,1e243,1e244,1e245,1e246,1e247,1e248,
853 1e249,1e250,1e251,1e252,1e253,1e254,1e255,1e256,1e257,1e258,1e259,1e260,
854 1e261,1e262,1e263,1e264,1e265,1e266,1e267,1e268,1e269,1e270,1e271,1e272,
855 1e273,1e274,1e275,1e276,1e277,1e278,1e279,1e280,1e281,1e282,1e283,1e284,
856 1e285,1e286,1e287,1e288,1e289,1e290,1e291,1e292,1e293,1e294,1e295,1e296,
857 1e297,1e298,1e299,1e300,1e301,1e302,1e303,1e304,1e305,1e306,1e307,1e308
858 };
859 return constants[exponent + 323];
860 }
861
862 parse_result parse_number() {
863 bool negative = false;
864 if ('-' == *p) {
865 ++p;
866 negative = true;
867
868 if (at_eof()) {
869 return error("unexpected end of input");
870 }
871 }
872
873 bool try_double = false;
874
875 int i = 0;
876 double d = 0.0; // gcc complains that d might be used uninitialized which isn't true. appease the warning anyway.
877 if (*p == '0') {
878 ++p;
879 } else for (;;) {
880 char c = *p;
881 if (c < '0' || c > '9') {
882 break;
883 }
884
885 ++p;
886 if (SAJSON_UNLIKELY(at_eof())) {
887 return error("unexpected end of input");
888 }
889
890 char digit = c - '0';
891
892 if (SAJSON_UNLIKELY(!try_double && i > INT_MAX / 10 - 9)) {
893 // TODO: could split this into two loops
894 try_double = true;
895 d = i;
896 }
897 if (SAJSON_UNLIKELY(try_double)) {
898 d = 10.0 * d + digit;
899 } else {
900 i = 10 * i + digit;
901 }
902 }
903
904 int exponent = 0;
905
906 if ('.' == *p) {
907 if (!try_double) {
908 try_double = true;
909 d = i;
910 }
911 ++p;
912 if (at_eof()) {
913 return error("unexpected end of input");
914 }
915 for (;;) {
916 char c = *p;
917 if (c < '0' || c > '9') {
918 break;
919 }
920
921 ++p;
922 if (at_eof()) {
923 return error("unexpected end of input");
924 }
925 d = d * 10 + (c - '0');
926 --exponent;
927 }
928 }
929
930 char e = *p;
931 if ('e' == e || 'E' == e) {
932 if (!try_double) {
933 try_double = true;
934 d = i;
935 }
936 ++p;
937 if (at_eof()) {
938 return error("unexpected end of input");
939 }
940
941 bool negativeExponent = false;
942 if ('-' == *p) {
943 negativeExponent = true;
944 ++p;
945 if (at_eof()) {
946 return error("unexpected end of input");
947 }
948 } else if ('+' == *p) {
949 ++p;
950 if (at_eof()) {
951 return error("unexpected end of input");
952 }
953 }
954
955 int exp = 0;
956
957 char c = *p;
958 if (SAJSON_UNLIKELY(c < '0' || c > '9')) {
959 return error("missing exponent");
960 }
961 for (;;) {
962 exp = 10 * exp + (c - '0');
963
964 ++p;
965 if (at_eof()) {
966 return error("unexpected end of input");
967 }
968
969 c = *p;
970 if (c < '0' || c > '9') {
971 break;
972 }
973 }
974 exponent += (negativeExponent ? -exp : exp);
975 }
976
977 if (exponent) {
978 assert(try_double);
979 d *= pow10(exponent);
980 }
981
982 if (negative) {
983 if (try_double) {
984 d = -d;
985 } else {
986 i = -i;
987 }
988 }
989 if (try_double) {
990 out -= double_storage::word_length;
991 double_storage::store(out, d);
992 return TYPE_DOUBLE;
993 } else {
994 integer_storage is;
995 is.i = i;
996
997 *--out = is.u;
998 return TYPE_INTEGER;
999 }
1000 }
1001
1002 parse_result install_array(size_t* array_base) {
1003 const size_t length = temp - array_base;
1004 size_t* const new_base = out - length - 1;
1005 while (temp > array_base) {
1006 // I think this addition is legal because the tag bits are at the top?
1007 *(--out) = *(--temp) + (array_base - new_base);
1008 }
1009 *(--out) = length;
1010
1011 return TYPE_ARRAY;
1012 }
1013
1014 parse_result install_object(size_t* object_base) {
1015 const size_t length = (temp - object_base) / 3;
1016 object_key_record* oir = reinterpret_cast<object_key_record*>(object_base);
1017 std::sort(
1018 oir,
1019 oir + length,
1020 object_key_comparator(input.get_data()));
1021
1022 size_t* const new_base = out - length * 3 - 1;
1023 size_t i = length;
1024 while (i--) {
1025 // I think this addition is legal because the tag bits are at the top?
1026 *(--out) = *(--temp) + (object_base - new_base);
1027 *(--out) = *(--temp);
1028 *(--out) = *(--temp);
1029 }
1030 *(--out) = length;
1031
1032 return TYPE_OBJECT;
1033 }
1034
1035 parse_result parse_string(size_t* tag = 0) {
1036 if (!tag) {
1037 out -= 2;
1038 tag = out;
1039 }
1040
1041 ++p; // "
1042 size_t start = p - input.get_data();
1043 for (;;) {
1044 if (SAJSON_UNLIKELY(p >= input_end)) {
1045 return error("unexpected end of input");
1046 }
1047
1048 if (SAJSON_UNLIKELY(*p >= 0 && *p < 0x20)) {
1049 *p = 0x20;
1050 }
1051
1052 switch (*p) {
1053 case '"':
1054 tag[0] = start;
1055 tag[1] = p - input.get_data();
1056 ++p;
1057 return TYPE_STRING;
1058
1059 case '\\':
1060 return parse_string_slow(tag, start);
1061
1062 default:
1063 ++p;
1064 break;
1065 }
1066 }
1067 }
1068
1069 parse_result read_hex(unsigned& u) {
1070 unsigned v = 0;
1071 int i = 4;
1072 while (i--) {
1073 unsigned char c = *p++;
1074 if (c >= '0' && c <= '9') {
1075 c -= '0';
1076 } else if (c >= 'a' && c <= 'f') {
1077 c = c - 'a' + 10;
1078 } else if (c >= 'A' && c <= 'F') {
1079 c = c - 'A' + 10;
1080 } else {
1081 return error("invalid character in unicode escape");
1082 }
1083 v = (v << 4) + c;
1084 }
1085
1086 u = v;
1087 return TYPE_NULL; // ???
1088 }
1089
1090 void write_utf8(unsigned codepoint, char*& end) {
1091 if (codepoint < 0x80) {
1092 *end++ = codepoint;
1093 } else if (codepoint < 0x800) {
1094 *end++ = 0xC0 | (codepoint >> 6);
1095 *end++ = 0x80 | (codepoint & 0x3F);
1096 } else if (codepoint < 0x10000) {
1097 *end++ = 0xE0 | (codepoint >> 12);
1098 *end++ = 0x80 | ((codepoint >> 6) & 0x3F);
1099 *end++ = 0x80 | (codepoint & 0x3F);
1100 } else {
1101 assert(codepoint < 0x200000);
1102 *end++ = 0xF0 | (codepoint >> 18);
1103 *end++ = 0x80 | ((codepoint >> 12) & 0x3F);
1104 *end++ = 0x80 | ((codepoint >> 6) & 0x3F);
1105 *end++ = 0x80 | (codepoint & 0x3F);
1106 }
1107 }
1108
1109 parse_result parse_string_slow(size_t* tag, size_t start) {
1110 char* end = p;
1111
1112 for (;;) {
1113 if (SAJSON_UNLIKELY(p >= input_end)) {
1114 return error("unexpected end of input");
1115 }
1116
1117 if (SAJSON_UNLIKELY(*p >= 0 && *p < 0x20)) {
1118 *p = 0x20;
1119 }
1120
1121 switch (*p) {
1122 case '"':
1123 tag[0] = start;
1124 tag[1] = end - input.get_data();
1125 ++p;
1126 return TYPE_STRING;
1127
1128 case '\\':
1129 ++p;
1130 if (SAJSON_UNLIKELY(p >= input_end)) {
1131 return error("unexpected end of input");
1132 }
1133
1134 char replacement;
1135 switch (*p) {
1136 case '"': replacement = '"'; goto replace;
1137 case '\\': replacement = '\\'; goto replace;
1138 case '/': replacement = '/'; goto replace;
1139 case 'b': replacement = '\b'; goto replace;
1140 case 'f': replacement = '\f'; goto replace;
1141 case 'n': replacement = '\n'; goto replace;
1142 case 'r': replacement = '\r'; goto replace;
1143 case 't': replacement = '\t'; goto replace;
1144 replace:
1145 *end++ = replacement;
1146 ++p;
1147 break;
1148 case 'u': {
1149 ++p;
1150 if (SAJSON_UNLIKELY(!has_remaining_characters(4))) {
1151 return error("unexpected end of input");
1152 }
1153 unsigned u = 0; // gcc's complaining that this could be used uninitialized. wrong.
1154 parse_result result = read_hex(u);
1155 if (!result) {
1156 return result;
1157 }
1158 if (u >= 0xD800 && u <= 0xDBFF) {
1159 if (SAJSON_UNLIKELY(!has_remaining_characters(6))) {
1160 return error("unexpected end of input during UTF-16 surrogate pair");
1161 }
1162 char p0 = p[0];
1163 char p1 = p[1];
1164 if (p0 != '\\' || p1 != 'u') {
1165 return error("expected \\u");
1166 }
1167 p += 2;
1168 unsigned v = 0; // gcc's complaining that this could be used uninitialized. wrong.
1169 result = read_hex(v);
1170 if (!result) {
1171 return result;
1172 }
1173
1174 if (v < 0xDC00 || v > 0xDFFF) {
1175 return error("invalid UTF-16 trail surrogate");
1176 }
1177 u = 0x10000 + (((u - 0xD800) << 10) | (v - 0xDC00));
1178 }
1179 write_utf8(u, end);
1180 break;
1181 }
1182 default:
1183 return error("unknown escape");
1184 }
1185 break;
1186
1187 default:
1188 *end++ = *p++;
1189 break;
1190 }
1191 }
1192 }
1193
1194 mutable_string_view input;
1195 char* const input_end;
1196 size_t* const structure;
1197
1198 char* p;
1199 size_t* temp;
1200 type root_type;
1201 size_t* out;
1202 size_t error_line;
1203 size_t error_column;
1204 std::string error_message;
1205 };
1206
1207 template<typename StringType>
1208 document parse(const StringType& string) {
1209 mutable_string_view ms(string);
1210
1211 size_t length = string.length();
1212 size_t* structure = new size_t[length];
1213
1214 return parser(ms, structure).get_document();
1215 }
1216}