Fix Win32 build
[lsnes.git] / src / library / json.cpp
bloba72744e214c2f92b06634810259cb2cc82dd394b
1 #include "json.hpp"
2 #include "hex.hpp"
3 #include "string.hpp"
4 #include <limits>
5 #include <climits>
6 #include <sstream>
8 namespace JSON
10 const char* error_desc[] = {
11 "Success",
12 "Not a number",
13 "Not a string",
14 "Not a boolean",
15 "Not an array",
16 "Not an object",
17 "Not array nor object",
18 "Invalid index",
19 "Invalid key",
20 "Invalid instance",
21 "Trailing pointer escape character",
22 "Invalid pointer escape",
23 "Bad hexadecimal character",
24 "Invalid surrogate escape",
25 "Invalid escape sequence",
26 "Truncated string",
27 "Unknown value type",
28 "Garbage after end of JSON",
29 "Truncated JSON",
30 "Unexpected comma",
31 "Unexpected colon",
32 "Unexpected right brace",
33 "Unexpected right braket",
34 "Invalid number syntax",
35 "Expected string as object key",
36 "Expected colon",
37 "Expected comma",
38 "Unknown token type",
39 "Bad pointer append",
40 "Bad pointer index",
41 "Iterator past the end",
42 "Iterator points to deleted object",
43 "Iterator points to wrong object",
44 "Illegal character escaped",
45 "Control character in string",
46 "Invalid value subtype",
47 "Bad JSON patch",
48 "JSON patch test failed",
49 "JSON patch illegal move",
52 const char* state_desc[] = {
53 "",
54 "array next",
55 "end of document",
56 "object next",
57 "object colon",
58 "object name",
59 "string body",
60 "string escape",
61 "value start",
62 "number"
65 const char* asciinames[] = {
66 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
67 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
70 bool parse_size_t(const std::u32string& s, size_t& x)
72 x = 0;
73 for(size_t i = 0; i < s.length(); i++) {
74 if(s[i] < 48 || s[i] > 57)
75 return false;
76 if((std::numeric_limits<size_t>::max() - (size_t)(s[i] - 48)) / 10 < x)
77 return false;
78 x = 10 * x + (s[i] - 48);
80 return true;
83 std::pair<size_t, size_t> error::get_position_lc(const std::string& doc, size_t pos)
85 size_t r = 1, c = 1;
86 bool last_cr = false;
87 for(size_t i = 0; i < pos; i++) {
88 if(doc[i] == 13 || (doc[i] == 10 && !last_cr)) {
89 c = 1;
90 r++;
91 last_cr = (doc[i] == 13);
92 continue;
94 if(last_cr && doc[i] == 10) {
95 last_cr = false;
96 continue;
98 c++;
100 return std::make_pair(r, c);
103 const char* error::what() const throw()
105 if(state == PARSE_NOT_PARSING)
106 return error_desc[code];
107 else {
108 //Windows is crap.
109 sprintf(buffer, "%s (while expecting %s) at byte %u", error_desc[code], state_desc[state],
110 (unsigned)position);
111 return buffer;
115 std::string error::extended_error(const std::string& doc)
117 if(state == PARSE_NOT_PARSING)
118 return error_desc[code];
119 std::ostringstream s;
120 size_t pos = position;
121 while(pos < doc.length() && (doc[pos] == '\t' || doc[pos] == '\v' || doc[pos] == '\r' || doc[pos] == '\n' ||
122 doc[pos] == ' '))
123 pos++;
124 auto p2 = get_position_lc(doc, pos);
125 s << error_desc[code] << " (while expecting " << state_desc[state] << ") at ";
126 if(position == doc.length())
127 s << "end of input";
128 else {
129 std::ostringstream sample;
130 size_t p = pos;
131 for(size_t i = 0; i < 32; i++) {
132 if(p >= doc.length())
133 break;
134 if(doc[p] < 32) {
135 sample << "<" << asciinames[(unsigned char)doc[p++]] << ">";
136 } else if(doc[p] < 127)
137 sample << doc[p++];
138 else if(doc[p] < 128)
139 sample << "<DEL>";
140 else if(doc[p] < 192)
141 sample << "<" << (int)doc[p++] << ">";
142 else if(doc[p] < 224) {
143 sample << doc[p++];
144 sample << doc[p++];
145 } else if(doc[p] < 240) {
146 sample << doc[p++];
147 sample << doc[p++];
148 sample << doc[p++];
149 } else if(doc[p] < 248) {
150 sample << doc[p++];
151 sample << doc[p++];
152 sample << doc[p++];
153 sample << doc[p++];
154 } else
155 sample << "<" << (int)doc[p++] << ">";
157 s << "line " << p2.first << " byte " << p2.second << " [near: '" << sample.str() << "']";
159 return s.str();
162 node number_tag::operator()(double v) const { return node(*this, v); }
163 node number_tag::operator()(uint64_t v) const { return node(*this, v); }
164 node number_tag::operator()(int64_t v) const { return node(*this, v); }
165 node string_tag::operator()(const std::string& s) const { return node(*this, s); }
166 node string_tag::operator()(const std::u32string& s) const { return node(*this, s); }
167 node boolean_tag::operator()(bool v) { return node(*this, v); }
168 node array_tag::operator()() const { return node(*this); }
169 node object_tag::operator()() const { return node(*this); }
170 node null_tag::operator()() const { return node(*this); }
172 node i(int64_t n) { return number(n); }
173 node u(uint64_t n) { return number(n); }
174 node f(double n) { return number(n); }
175 node b(bool bl) { return boolean(bl); }
176 node s(const std::string& st) { return string(st); }
177 node s(const std::u32string& st) { return string(st); }
178 node n() { return null(); }
180 number_tag number;
181 string_tag string;
182 boolean_tag boolean;
183 array_tag array;
184 object_tag object;
185 null_tag null;
186 none_tag none;
188 template<> void node::number_holder::from(double val) { sub = 0; n.n0 = val; }
189 template<> void node::number_holder::from(uint64_t val) { sub = 1; n.n1 = val; }
190 template<> void node::number_holder::from(int64_t val) { sub = 2; n.n2 = val; }
192 namespace
194 unsigned numchar(char c)
196 switch(c) {
197 case '0': return 0;
198 case '1': case '2': case '3': case '4': case '5':
199 case '6': case '7': case '8': case '9': return 1;
200 case '.': return 2;
201 case 'e': return 3;
202 case '+': return 4;
203 case '-': return 5;
204 default: return 6;
208 uint32_t numdfa[] = {
209 0x0F1FFF32, //0: STATE_INITIAL
210 0x0FFFFF32, //1: STATE_AFTER_MINUS
211 0x1FFF64FF, //2: STATE_INT_Z
212 0x1FFF6433, //3: STATE_INT_NZ
213 0x0FFFFF55, //4: STATE_DECIMAL
214 0x1FFF6F55, //5: STATE_DECIMAL_N
215 0x0F77FF88, //6: STATE_EXP
216 0x0FFFFF88, //7: STATE_EXP_SIGN
217 0x1FFFFF88, //8: STATE_EXP_N
221 node::number_holder::number_holder(const std::string& expr, size_t& ptr, size_t len)
223 //-?(0|1-9[0-9]+)(.[0-9]+)?([eE][+-]?[0-9]+)?
224 int state = 0;
225 size_t tmp = ptr;
226 size_t tmp2 = ptr;
227 std::string x;
228 while(tmp < len) {
229 unsigned c = numchar(expr[tmp]);
230 unsigned ns = (numdfa[state] >> (4 * c)) & 0xF;
231 if(ns == 0xF)
232 break;
233 else
234 state = ns;
235 tmp++;
237 if(!(numdfa[state] >> 28))
238 goto bad;
239 x = expr.substr(ptr, tmp - ptr);
240 ptr = tmp;
241 try {
242 if(regex_match("[0-9]+", x)) {
243 n.n1 = parse_value<uint64_t>(x);
244 sub = 1;
245 return;
247 } catch(...) {}
248 try {
249 if(regex_match("[+-]?[0-9]+", x)) {
250 n.n2 = parse_value<int64_t>(x);
251 sub = 2;
252 return;
254 } catch(...) {}
255 try {
256 n.n0 = parse_value<double>(x);
257 sub = 0;
258 return;
259 } catch(...) {}
260 bad:
261 throw error(ERR_INVALID_NUMBER, PARSE_NUMBER, tmp2);
265 void node::number_holder::write(std::ostream& s) const
267 switch(sub) {
268 case 0: s << n.n0; break;
269 case 1: s << n.n1; break;
270 case 2: s << n.n2; break;
274 template<typename T> bool node::number_holder::cmp(const T& num) const
276 switch(sub) {
277 case 0: return n.n0 == num;
278 case 1: return n.n1 == num;
279 case 2: return n.n2 == num;
281 throw error(ERR_UNKNOWN_SUBTYPE);
284 template<> bool node::number_holder::cmp(const int64_t& num) const
286 switch(sub) {
287 case 0: return n.n0 == num;
288 case 1: return num >= 0 && n.n1 == static_cast<uint64_t>(num);
289 case 2: return n.n2 == num;
291 throw error(ERR_UNKNOWN_SUBTYPE);
294 template<> bool node::number_holder::cmp(const uint64_t& num) const
296 switch(sub) {
297 case 0: return n.n0 == num;
298 case 1: return n.n1 == num;
299 case 2: return n.n2 >= 0 && static_cast<uint64_t>(n.n2) == num;
301 throw error(ERR_UNKNOWN_SUBTYPE);
305 bool node::number_holder::operator==(const number_holder& h) const
307 switch(sub) {
308 case 0: return h.cmp(n.n0);
309 case 1: return h.cmp(n.n1);
310 case 2: return h.cmp(n.n2);
312 throw error(ERR_UNKNOWN_SUBTYPE);
315 node::node() throw() : node(null) {}
316 node::node(null_tag) throw() { vtype = null; }
317 node::node(boolean_tag, bool b) throw() { vtype = boolean; _boolean = b; }
318 node::node(string_tag, const std::u32string& str) throw(std::bad_alloc) { vtype = string; _string = str; }
319 node::node(string_tag, const std::string& str) throw(std::bad_alloc) { vtype = string; _string = utf8::to32(str); }
320 node::node(number_tag, double n) throw() { vtype = number; _number.from<double>(n); }
321 node::node(number_tag, int64_t n) throw() { vtype = number; _number.from<int64_t>(n); }
322 node::node(number_tag, uint64_t n) throw() { vtype = number; _number.from<uint64_t>(n); }
323 node::node(array_tag) throw() { vtype = array; }
324 node::node(object_tag) throw() { vtype = object; }
325 int node::type() const throw() { return vtype; }
327 node& node::set(null_tag) throw() { set_helper<uint64_t>(0); vtype = null; return *this; }
328 node& node::set(boolean_tag, bool n) throw() { set_helper<uint64_t>(0); vtype = boolean; _boolean = n; return *this; }
329 node& node::set(number_tag, double n) throw() { set_helper<double>(n); return *this; }
330 node& node::set(number_tag, int64_t n) throw() { set_helper<int64_t>(n); return *this; }
331 node& node::set(number_tag, uint64_t n) throw() { set_helper<int64_t>(n); return *this; }
333 node& node::set(string_tag, const std::u32string& key) throw(std::bad_alloc)
335 std::u32string tmp = key;
336 std::swap(_string, tmp);
337 vtype = string;
338 xarray.clear();
339 xobject.clear();
340 return *this;
343 double node::as_double() const throw(error)
345 return get_number_helper<double>();
348 int64_t node::as_int() const throw(error)
350 return get_number_helper<int64_t>();
353 uint64_t node::as_uint() const throw(error)
355 return get_number_helper<uint64_t>();
358 const std::u32string& node::as_string() const throw(std::bad_alloc, error)
360 if(vtype != string)
361 throw error(ERR_NOT_A_STRING);
362 return _string;
365 bool node::as_bool() const throw(error)
367 if(vtype != boolean)
368 throw error(ERR_NOT_A_BOOLEAN);
369 return _boolean;
372 size_t node::index_count() const throw(error)
374 if(vtype != array)
375 throw error(ERR_NOT_AN_ARRAY);
376 return xarray.size();
379 errorcode node::index_soft(size_t index, const node*& out) const throw()
381 if(vtype != array)
382 return ERR_NOT_AN_ARRAY;
383 if(index >= xarray_index.size())
384 return ERR_INDEX_INVALID;
385 out = xarray_index[index];
386 return ERR_OK;
389 errorcode node::index_soft(size_t index, node*& out) throw()
391 if(vtype != array)
392 return ERR_NOT_AN_ARRAY;
393 if(index >= xarray_index.size())
394 return ERR_INDEX_INVALID;
395 out = xarray_index[index];
396 return ERR_OK;
399 size_t node::field_count(const std::u32string& key) const throw(error)
401 if(vtype != object)
402 throw error(ERR_NOT_AN_OBJECT);
403 if(!xobject.count(key))
404 return 0;
405 return xobject.find(key)->second.size();
408 bool node::field_exists(const std::u32string& key) const throw(error)
410 return (field_count(key) > 0);
413 errorcode node::field_soft(const std::u32string& key, size_t subindex, const node*& out) const throw()
415 if(vtype != object)
416 return ERR_NOT_AN_OBJECT;
417 if(!xobject.count(key))
418 return ERR_KEY_INVALID;
419 const std::list<node>& l = xobject.find(key)->second;
420 size_t j = 0;
421 for(auto i = l.begin(); i != l.end(); i++, j++) {
422 if(j == subindex) {
423 out = &*i;
424 return ERR_OK;
427 return ERR_INSTANCE_INVALID;
430 errorcode node::field_soft(const std::u32string& key, size_t subindex, node*& out) throw()
432 if(vtype != object)
433 return ERR_NOT_AN_OBJECT;
434 if(!xobject.count(key))
435 return ERR_KEY_INVALID;
436 std::list<node>& l = xobject.find(key)->second;
437 size_t j = 0;
438 for(auto i = l.begin(); i != l.end(); i++, j++) {
439 if(j == subindex) {
440 out = &*i;
441 return ERR_OK;
444 return ERR_INSTANCE_INVALID;
447 node::node(const node& _node) throw(std::bad_alloc)
449 std::u32string tmp1 = _node._string;
450 std::list<node> tmp2 = _node.xarray;
451 std::map<std::u32string, std::list<node>> tmp3 = _node.xobject;
452 std::vector<node*> tmp4 = _node.xarray_index;
454 vtype = _node.vtype;
455 _number = _node._number;
456 _boolean = _node._boolean;
457 _string = _node._string;
458 xarray = _node.xarray;
459 xobject = _node.xobject;
460 xarray_index = _node.xarray_index;
461 fixup_nodes(_node);
464 node& node::operator=(const node& _node) throw(std::bad_alloc)
466 if(this == &_node)
467 return *this;
468 std::u32string tmp1 = _node._string;
469 std::list<node> tmp2 = _node.xarray;
470 std::map<std::u32string, std::list<node>> tmp3 = _node.xobject;
471 std::vector<node*> tmp4 = _node.xarray_index;
473 vtype = _node.vtype;
474 _number = _node._number;
475 _boolean = _node._boolean;
476 std::swap(_string, tmp1);
477 std::swap(xarray, tmp2);
478 std::swap(xobject, tmp3);
479 std::swap(xarray_index, tmp4);
480 fixup_nodes(_node);
481 return *this;
484 node& node::append(const node& _node) throw(std::bad_alloc, error)
486 if(vtype != array)
487 throw error(ERR_NOT_AN_ARRAY);
488 bool p = false;
489 try {
490 xarray.push_back(_node);
491 p = true;
492 node* ptr = &*xarray.rbegin();
493 xarray_index.push_back(ptr);
494 return *ptr;
495 } catch(std::bad_alloc& e) {
496 if(p)
497 xarray.pop_back();
498 throw;
502 node& node::insert(const std::u32string& key, const node& _node) throw(std::bad_alloc, error)
504 if(vtype != object)
505 throw error(ERR_NOT_AN_OBJECT);
506 try {
507 xobject[key].push_back(_node);
508 return *xobject[key].rbegin();
509 } catch(...) {
510 if(xobject.count(key) && xobject[key].empty())
511 xobject.erase(key);
512 throw;
516 namespace
518 errorcode jsonptr_unescape_soft(const std::u32string& c, size_t start, size_t end, std::u32string& _out)
520 std::basic_ostringstream<char32_t> out;
521 for(size_t ptr = start; ptr < end; ptr++) {
522 if(c[ptr] == '~') {
523 if(ptr == end - 1)
524 return ERR_POINTER_TRAILING_ESCAPE;
525 ptr++;
526 if(c[ptr] == '0')
527 out << U"~";
528 else if(c[ptr] == '1')
529 out << U"/";
530 else
531 return ERR_POINTER_INVALID_ESCAPE;
532 } else
533 out << c[ptr];
535 _out = out.str();
536 return ERR_OK;
539 std::u32string jsonptr_unescape(const std::u32string& c, size_t start, size_t end)
541 std::u32string o;
542 auto e = jsonptr_unescape_soft(c, start, end, o);
543 if(e != ERR_OK) throw error(e);
544 return o;
549 errorcode node::follow_soft(const std::u32string& pointer, const node*& current) const throw(std::bad_alloc)
551 current = this;
552 size_t ptr = 0;
553 while(ptr < pointer.length()) {
554 size_t p = pointer.find_first_of(U"/", ptr);
555 if(p > pointer.length())
556 p = pointer.length();
557 std::u32string c;
558 auto e = jsonptr_unescape_soft(pointer, ptr, p, c);
559 if(e != ERR_OK) return e;
560 if(current->vtype == array) {
561 if(c == U"-")
562 return ERR_POINTER_BAD_APPEND;
563 size_t idx;
564 if(!parse_size_t(c, idx))
565 return ERR_POINTER_BAD_INDEX;
566 e = current->index_soft(idx, current);
567 if(e != ERR_OK) return e;
568 } else if(current->vtype == object) {
569 e = current->field_soft(c, 0, current);
570 if(e != ERR_OK) return e;
571 } else
572 return ERR_NOT_ARRAY_NOR_OBJECT;
573 ptr = p + 1;
575 return ERR_OK;
578 errorcode node::follow_soft(const std::u32string& pointer, node*& current) throw(std::bad_alloc)
580 current = this;
581 size_t ptr = 0;
582 while(ptr < pointer.length()) {
583 size_t p = pointer.find_first_of(U"/", ptr);
584 if(p > pointer.length())
585 p = pointer.length();
586 std::u32string c;
587 auto e = jsonptr_unescape_soft(pointer, ptr, p, c);
588 if(e != ERR_OK) return e;
589 if(current->vtype == array) {
590 if(c == U"-")
591 return ERR_POINTER_BAD_APPEND;
592 size_t idx;
593 if(!parse_size_t(c, idx))
594 return ERR_POINTER_BAD_INDEX;
595 e = current->index_soft(idx, current);
596 if(e != ERR_OK) return e;
597 } else if(current->vtype == object) {
598 e = current->field_soft(c, 0, current);
599 if(e != ERR_OK) return e;
600 } else
601 return ERR_NOT_ARRAY_NOR_OBJECT;
602 ptr = p + 1;
604 return ERR_OK;
607 namespace
609 struct json_token
611 enum ttype { TSTRING, TNUMBER, TOBJECT, TARRAY, TINVALID, TCOMMA, TOBJECT_END, TARRAY_END, TCOLON,
612 TEOF, TTRUE, TFALSE, TNULL };
613 ttype type;
614 std::u32string value;
615 json_token(enum ttype t, const std::u32string& v) { type = t; value = v; }
616 json_token(enum ttype t) { type = t; }
619 uint32_t parse_hex(int32_t ch, parsestate state, size_t pos)
621 switch(ch) {
622 case '0': return 0;
623 case '1': return 1;
624 case '2': return 2;
625 case '3': return 3;
626 case '4': return 4;
627 case '5': return 5;
628 case '6': return 6;
629 case '7': return 7;
630 case '8': return 8;
631 case '9': return 9;
632 case 'A': case 'a': return 10;
633 case 'B': case 'b': return 11;
634 case 'C': case 'c': return 12;
635 case 'D': case 'd': return 13;
636 case 'E': case 'e': return 14;
637 case 'F': case 'f': return 15;
638 default: throw error(ERR_BAD_HEX, state, pos);
642 class iterator_counter
644 public:
645 iterator_counter(size_t& _count) : count(_count) { count = 0; }
646 char32_t& operator*() { count++; return x; }
647 iterator_counter& operator++() { return *this; }
648 size_t get_count() { return count; }
649 private:
650 char32_t x;
651 size_t& count;
654 //STATE_NORMAL 0
655 //STATE_ESCAPE 1
656 //STATE_ESCAPE_HEX0 2
657 //STATE_ESCAPE_HEX1 3
658 //STATE_ESCAPE_HEX2 4
659 //STATE_ESCAPE_HEX3 5
660 //STATE_ESCAPE_SURROGATE 6
661 //STATE_ESCAPE_SURROGATE2 7
662 //STATE_ESCAPE_SURROGATE_HEX0 8
663 //STATE_ESCAPE_SURROGATE_HEX1 9
664 //STATE_ESCAPE_SURROGATE_HEX2 10
665 //STATE_ESCAPE_SURROGATE_HEX3 11
667 template<typename T> size_t read_string_impl(T target, const std::string& doc, size_t ptr, size_t len)
669 uint16_t ustate = utf8::initial_state;
670 int estate = 0;
671 uint32_t extra = 0;
672 uint32_t tmp;
673 size_t i;
674 size_t lc = ptr;
675 for(i = ptr; i <= len; i++) {
676 int ch = -1;
677 if(i < len)
678 ch = (unsigned char)doc[i];
679 int32_t uch = utf8::parse_byte(ch, ustate);
680 if(uch < 0)
681 continue;
682 //Okay, have Unicode codepoint decoded.
683 switch(estate) {
684 case 0:
685 lc = i;
686 extra = 0;
687 if(uch < 32)
688 throw error(ERR_CONTROL_CHARACTER, PARSE_STRING_BODY, lc);
689 if(uch == '\"')
690 goto out;
691 if(uch == '\\')
692 estate = 1;
693 else {
694 *target = uch;
695 ++target;
697 break;
698 case 1:
699 switch(uch) {
700 case '\"': *target = U'\"'; ++target; estate = 0; break;
701 case '\\': *target = U'\\'; ++target; estate = 0; break;
702 case '/': *target = U'/'; ++target; estate = 0; break;
703 case 'b': *target = U'\b'; ++target; estate = 0; break;
704 case 'f': *target = U'\f'; ++target; estate = 0; break;
705 case 'n': *target = U'\n'; ++target; estate = 0; break;
706 case 'r': *target = U'\r'; ++target; estate = 0; break;
707 case 't': *target = U'\t'; ++target; estate = 0; break;
708 case 'u':
709 estate = 2;
710 break;
711 default:
712 throw error(ERR_INVALID_ESCAPE, PARSE_STRING_ESCAPE, lc);
714 break;
715 case 2: case 3: case 4: case 8: case 9: case 10:
716 extra = (extra << 4) | parse_hex(uch, PARSE_STRING_ESCAPE, lc);
717 estate++;
718 break;
719 case 5:
720 extra = (extra << 4) | parse_hex(uch, PARSE_STRING_ESCAPE, lc);
721 if((extra & 0xFC00) == 0xDC00)
722 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
723 else if((extra & 0xFC00) == 0xD800)
724 estate = 6;
725 else if((extra & 0xFFFE) == 0xFFFE)
726 throw error(ERR_ILLEGAL_CHARACTER, PARSE_STRING_ESCAPE, lc);
727 else {
728 estate = 0;
729 *target = extra;
730 ++target;
732 break;
733 case 6:
734 if(uch != '\\')
735 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
736 estate = 7;
737 break;
738 case 7:
739 if(uch != 'u')
740 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
741 estate = 8;
742 break;
743 case 11:
744 extra = (extra << 4) | parse_hex(uch, PARSE_STRING_ESCAPE, lc);
745 if((extra & 0xFC00FC00UL) != 0xD800DC00)
746 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
747 tmp = ((extra & 0x3FF0000) >> 6) + (extra & 0x3FF) + 0x10000;
748 if((tmp & 0xFFFE) == 0xFFFE)
749 throw error(ERR_ILLEGAL_CHARACTER, PARSE_STRING_ESCAPE, lc);
750 *target = tmp;
751 ++target;
752 estate = 0;
753 break;
756 throw error(ERR_TRUNCATED_STRING, estate ? PARSE_STRING_ESCAPE : PARSE_STRING_BODY, len);
757 out:
758 return i;
761 void read_string(std::u32string& target, const std::string& doc, size_t& ptr, size_t len)
763 size_t cpcnt;
764 read_string_impl(iterator_counter(cpcnt), doc, ptr, len);
765 target.resize(cpcnt);
766 ptr = read_string_impl(target.begin(), doc, ptr, len) + 1;
769 json_token parse_token(const std::string& doc, size_t& ptr, size_t len)
771 while(ptr < len && (doc[ptr] == ' ' || doc[ptr] == '\t' || doc[ptr] == '\r' || doc[ptr] == '\n'))
772 ptr++;
773 if(ptr >= len)
774 return json_token(json_token::TEOF);
775 if(doc[ptr] == '{') {
776 ptr++;
777 return json_token(json_token::TOBJECT);
779 if(doc[ptr] == '}') {
780 ptr++;
781 return json_token(json_token::TOBJECT_END);
783 if(doc[ptr] == '[') {
784 ptr++;
785 return json_token(json_token::TARRAY);
787 if(doc[ptr] == ']') {
788 ptr++;
789 return json_token(json_token::TARRAY_END);
791 if(doc[ptr] == ',') {
792 ptr++;
793 return json_token(json_token::TCOMMA);
795 if(doc[ptr] == ':') {
796 ptr++;
797 return json_token(json_token::TCOLON);
799 if(doc[ptr] == '\"') {
800 //String.
801 ptr++;
802 return json_token(json_token::TSTRING);
804 if(doc[ptr] == '-' || (doc[ptr] >= '0' && doc[ptr] <= '9')) {
805 //Number.
806 return json_token(json_token::TNUMBER);
808 if(doc[ptr] == 'n') {
809 if(ptr >= len || doc[ptr++] != 'n') goto bad;
810 if(ptr >= len || doc[ptr++] != 'u') goto bad;
811 if(ptr >= len || doc[ptr++] != 'l') goto bad;
812 if(ptr >= len || doc[ptr++] != 'l') goto bad;
813 return json_token(json_token::TNULL);
815 if(doc[ptr] == 'f') {
816 if(ptr >= len || doc[ptr++] != 'f') goto bad;
817 if(ptr >= len || doc[ptr++] != 'a') goto bad;
818 if(ptr >= len || doc[ptr++] != 'l') goto bad;
819 if(ptr >= len || doc[ptr++] != 's') goto bad;
820 if(ptr >= len || doc[ptr++] != 'e') goto bad;
821 return json_token(json_token::TFALSE);
823 if(doc[ptr] == 't') {
824 if(ptr >= len || doc[ptr++] != 't') goto bad;
825 if(ptr >= len || doc[ptr++] != 'r') goto bad;
826 if(ptr >= len || doc[ptr++] != 'u') goto bad;
827 if(ptr >= len || doc[ptr++] != 'e') goto bad;
828 return json_token(json_token::TTRUE);
830 bad:
831 return json_token(json_token::TINVALID);
834 std::string json_string_escape(const std::u32string& c)
836 std::ostringstream out;
837 out << "\"";
838 size_t len = c.length();
839 for(size_t i = 0; i < len; i++) {
840 if(c[i] == '\b') out << "\\b";
841 else if(c[i] == '\n') out << "\\n";
842 else if(c[i] == '\r') out << "\\r";
843 else if(c[i] == '\t') out << "\\t";
844 else if(c[i] == '\f') out << "\\f";
845 else if((c[i] & 0xFFFFFFE0) == 0)
846 out << "\\u" << hex::to16(c[i]);
847 else if(c[i] == U'\\')
848 out << "\\\\";
849 else if(c[i] == U'\"')
850 out << "\\\"";
851 else if(c[i] < 0x80)
852 out << (unsigned char)c[i];
853 else if(c[i] < 0x800) {
854 out << (unsigned char)(0xC0 + (c[i] >> 6));
855 out << (unsigned char)(0x80 + (c[i] & 0x3F));
856 } else if(c[i] < 0x10000) {
857 out << (unsigned char)(0xE0 + (c[i] >> 12));
858 out << (unsigned char)(0x80 + ((c[i] >> 6) & 0x3F));
859 out << (unsigned char)(0x80 + (c[i] & 0x3F));
860 } else if(c[i] < 0x10FFFF) {
861 out << (unsigned char)(0xF0 + (c[i] >> 18));
862 out << (unsigned char)(0x80 + ((c[i] >> 12) & 0x3F));
863 out << (unsigned char)(0x80 + ((c[i] >> 6) & 0x3F));
864 out << (unsigned char)(0x80 + (c[i] & 0x3F));
867 out << "\"";
868 return out.str();
871 void skip_ws(const std::string& doc, size_t& ptr, size_t len) {
872 while(ptr < len && (doc[ptr] == ' ' || doc[ptr] == '\t' || doc[ptr] == '\v' || doc[ptr] == '\r' ||
873 doc[ptr] == '\n')) {
874 ptr++;
878 std::u32string pointer_escape_field(const std::u32string& orig) throw(std::bad_alloc)
880 std::basic_stringstream<char32_t> x;
881 for(auto i : orig) {
882 if(i == U'~')
883 x << U"~0";
884 else if(i == U'/')
885 x << U"~1";
886 else
887 x << i;
889 return x.str();
892 std::u32string pointer_escape_index(uint64_t idx) throw(std::bad_alloc)
894 std::string orig = (stringfmt() << idx).str();
895 std::basic_ostringstream<char32_t> x;
896 for(auto i : orig)
897 x << (char32_t)i;
898 return x.str();
902 std::string node::serialize(printer* _printer) const throw(std::bad_alloc, error)
904 printer xprinter;
905 _printer = _printer ? _printer : &xprinter;
906 printer& oprinter = *_printer;
907 std::ostringstream out;
908 bool first = true;
909 switch(vtype) {
910 case null_tag::id: return oprinter.value_val("null");
911 case boolean_tag::id: return oprinter.value_val(_boolean ? "true" : "false");
912 case number_tag::id:
913 _number.write(out);
914 return oprinter.value_val(out.str());
915 case string_tag::id:
916 return oprinter.value_string(_string);
917 case array_tag::id:
918 out << oprinter.array_begin();
919 for(auto& i : xarray_index) {
920 if(!first) out << oprinter.array_separator();
921 out << i->serialize(_printer);
922 first = false;
924 out << oprinter.array_end();
925 return out.str();
926 case object_tag::id:
927 out << oprinter.object_begin();
928 for(auto& i : xobject) {
929 for(auto& j : i.second) {
930 if(!first) out << oprinter.object_separator();
931 out << oprinter.object_key(i.first);
932 out << j.serialize(_printer);
933 first = false;
936 out << oprinter.object_end();
937 return out.str();
939 throw error(ERR_UNKNOWN_TYPE);
942 node::node(const std::string& doc) throw(std::bad_alloc, error)
944 size_t tmp = 0;
945 ctor(doc, tmp, doc.length());
946 skip_ws(doc, tmp, doc.length());
947 if(tmp < doc.length())
948 throw error(ERR_GARBAGE_AFTER_END, PARSE_END_OF_DOCUMENT, tmp);
951 void node::ctor(const std::string& doc, size_t& ptr, size_t len) throw(std::bad_alloc, error)
953 size_t tmp3;
954 tmp3 = ptr;
955 json_token t = parse_token(doc, ptr, len);
956 size_t tmp = ptr;
957 std::string tmp2;
958 switch(t.type) {
959 case json_token::TTRUE:
960 set(boolean, true);
961 return;
962 case json_token::TFALSE:
963 set(boolean, false);
964 return;
965 case json_token::TNULL:
966 set(null);
967 return;
968 case json_token::TEOF:
969 throw error(ERR_TRUNCATED_JSON, PARSE_VALUE_START, ptr);
970 case json_token::TCOMMA:
971 throw error(ERR_UNEXPECTED_COMMA, PARSE_VALUE_START, tmp3);
972 case json_token::TCOLON:
973 throw error(ERR_UNEXPECTED_COLON, PARSE_VALUE_START, tmp3);
974 case json_token::TARRAY_END:
975 throw error(ERR_UNEXPECTED_RIGHT_BRACKET, PARSE_VALUE_START, tmp3);
976 case json_token::TOBJECT_END:
977 throw error(ERR_UNEXPECTED_RIGHT_BRACE, PARSE_VALUE_START, tmp3);
978 case json_token::TSTRING:
979 set(string, U"");
980 read_string(_string, doc, ptr, len);
981 break;
982 case json_token::TNUMBER:
983 set(number, 0.0);
984 _number = number_holder(doc, ptr, len);
985 break;
986 case json_token::TOBJECT:
987 *this = object();
988 if(parse_token(doc, tmp, len).type == json_token::TOBJECT_END) {
989 ptr = tmp;
990 break;
992 while(true) {
993 tmp3 = ptr;
994 json_token t2 = parse_token(doc, ptr, len);
995 if(t2.type == json_token::TEOF)
996 throw error(ERR_TRUNCATED_JSON, PARSE_OBJECT_NAME, ptr);
997 if(t2.type != json_token::TSTRING)
998 throw error(ERR_EXPECTED_STRING_KEY, PARSE_OBJECT_NAME, tmp3);
999 std::u32string key;
1000 read_string(key, doc, ptr, len);
1001 tmp3 = ptr;
1002 t2 = parse_token(doc, ptr, len);
1003 if(t2.type == json_token::TEOF)
1004 throw error(ERR_TRUNCATED_JSON, PARSE_OBJECT_COLON, ptr);
1005 if(t2.type != json_token::TCOLON)
1006 throw error(ERR_EXPECTED_COLON, PARSE_OBJECT_COLON, tmp3);
1007 insert(key, node(doc, ptr, len));
1008 tmp3 = ptr;
1009 t2 = parse_token(doc, ptr, len);
1010 if(t2.type == json_token::TEOF)
1011 throw error(ERR_TRUNCATED_JSON, PARSE_OBJECT_AFTER_VALUE, ptr);
1012 if(t2.type == json_token::TOBJECT_END)
1013 break;
1014 if(t2.type != json_token::TCOMMA)
1015 throw error(ERR_EXPECTED_COMMA, PARSE_OBJECT_AFTER_VALUE, tmp3);
1017 break;
1018 case json_token::TARRAY:
1019 *this = array();
1020 if(parse_token(doc, tmp, len).type == json_token::TARRAY_END) {
1021 ptr = tmp;
1022 break;
1024 while(true) {
1025 append(node(doc, ptr, len));
1026 tmp3 = ptr;
1027 json_token t2 = parse_token(doc, ptr, len);
1028 if(t2.type == json_token::TEOF)
1029 throw error(ERR_TRUNCATED_JSON, PARSE_ARRAY_AFTER_VALUE, ptr);
1030 if(t2.type == json_token::TARRAY_END)
1031 break;
1032 if(t2.type != json_token::TCOMMA)
1033 throw error(ERR_EXPECTED_COMMA, PARSE_ARRAY_AFTER_VALUE, tmp3);
1035 break;
1036 case json_token::TINVALID:
1037 throw error(ERR_UNKNOWN_CHARACTER, PARSE_VALUE_START, tmp3);
1041 node::node(const std::string& doc, size_t& ptr, size_t len) throw(std::bad_alloc, error)
1043 ctor(doc, ptr, len);
1046 node& node::operator[](const std::u32string& pointer) throw(std::bad_alloc, error)
1048 node* current = this;
1049 size_t ptr = 0;
1050 while(ptr < pointer.length()) {
1051 size_t p = pointer.find_first_of(U"/", ptr);
1052 if(p > pointer.length())
1053 p = pointer.length();
1054 std::u32string c = jsonptr_unescape(pointer, ptr, p);
1055 if(current->vtype == array) {
1056 if(c == U"-") {
1057 //End-of-array.
1058 if(p < pointer.length())
1059 throw error(ERR_POINTER_BAD_APPEND);
1060 return current->append(n());
1062 size_t idx;
1063 if(!parse_size_t(c, idx))
1064 throw error(ERR_POINTER_BAD_INDEX);
1065 if(idx > current->xarray.size())
1066 throw error(ERR_POINTER_BAD_APPEND);
1067 else if(idx == current->xarray.size())
1068 return current->append(n());
1069 current = &current->index(idx);
1070 } else if(current->vtype == object) {
1071 if(!current->field_exists(c) && p == pointer.length())
1072 return current->insert(c, n());
1073 current = &current->field(c);
1074 } else
1075 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1076 ptr = p + 1;
1078 return *current;
1081 node& node::insert_node(const std::u32string& pointer, const node& nwn) throw(std::bad_alloc, error)
1083 size_t s = pointer.find_last_of(U"/");
1084 node* base;
1085 std::u32string rest;
1086 size_t ptrlen = pointer.length();
1087 if(s < ptrlen) {
1088 base = &follow(pointer.substr(0, s));
1089 rest = jsonptr_unescape(pointer, s + 1, ptrlen);
1090 } else {
1091 base = this;
1092 rest = jsonptr_unescape(pointer, 0, ptrlen);
1094 if(base->type() == array) {
1095 if(rest == U"-")
1096 return base->append(nwn);
1097 size_t idx;
1098 if(!parse_size_t(rest, idx))
1099 throw error(ERR_POINTER_BAD_INDEX);
1100 if(idx > base->xarray.size())
1101 throw error(ERR_POINTER_BAD_APPEND);
1102 else if(idx == base->xarray.size())
1103 return base->append(nwn);
1104 bool p = false;
1105 try {
1106 base->xarray.push_back(nwn);
1107 p = true;
1108 node* ptr = &*base->xarray.rbegin();
1109 base->xarray_index.insert(base->xarray_index.begin() + idx, ptr);
1110 return *ptr;
1111 } catch(std::bad_alloc& e) {
1112 if(p)
1113 base->xarray.pop_back();
1114 throw;
1116 } else if(base->type() == object) {
1117 if(xobject.count(rest))
1118 return *base->xobject[rest].begin() = nwn;
1119 else {
1120 try {
1121 base->xobject[rest].push_back(nwn);
1122 return *base->xobject[rest].begin();
1123 } catch(...) {
1124 base->xobject.erase(rest);
1125 throw;
1128 } else
1129 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1132 node node::delete_node(const std::u32string& pointer) throw(std::bad_alloc, error)
1134 size_t s = pointer.find_last_of(U"/");
1135 node* base;
1136 std::u32string rest;
1137 size_t ptrlen = pointer.length();
1138 if(s < ptrlen) {
1139 base = &follow(pointer.substr(0, s));
1140 rest = jsonptr_unescape(pointer, s + 1, ptrlen);
1141 } else {
1142 base = this;
1143 rest = jsonptr_unescape(pointer, 0, ptrlen);
1145 if(base->type() == array) {
1146 if(rest == U"-")
1147 throw error(ERR_POINTER_BAD_APPEND);
1148 size_t idx;
1149 if(!parse_size_t(rest, idx))
1150 throw error(ERR_POINTER_BAD_INDEX);
1151 if(idx >= base->xarray.size())
1152 throw error(ERR_INDEX_INVALID);
1153 node* dptr = base->xarray_index[idx];
1154 node tmp = *dptr;
1155 for(auto i = base->xarray.begin(); i != base->xarray.end(); ++i)
1156 if(&*i == dptr) {
1157 base->xarray.erase(i);
1158 break;
1160 base->xarray_index.erase(base->xarray_index.begin() + idx);
1161 return tmp;
1162 } else if(base->type() == object) {
1163 if(xobject.count(rest)) {
1164 node tmp = *base->xobject[rest].begin();
1165 base->xobject.erase(rest);
1166 return tmp;
1167 } else
1168 throw error(ERR_KEY_INVALID);
1169 } else
1170 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1173 node node::patch(const node& patch) const throw(std::bad_alloc, error)
1175 node obj(*this);
1176 if(patch.type() != array)
1177 throw error(ERR_PATCH_BAD);
1178 for(auto& i : patch) {
1179 if(i.type() != object || i.field_count(U"op") != 1 || i.field(U"op").type() != string)
1180 throw error(ERR_PATCH_BAD);
1181 std::u32string op = i.field(U"op").as_string();
1182 if(op == U"test") {
1183 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1184 throw error(ERR_PATCH_BAD);
1185 if(i.field_count(U"value") != 1)
1186 throw error(ERR_PATCH_BAD);
1187 if(obj.follow(i.field(U"path").as_string()) != i.field("value"))
1188 throw error(ERR_PATCH_TEST_FAILED);
1189 } else if(op == U"remove") {
1190 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1191 throw error(ERR_PATCH_BAD);
1192 obj.delete_node(i.field(U"path").as_string());
1193 } else if(op == U"add") {
1194 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1195 throw error(ERR_PATCH_BAD);
1196 if(i.field_count(U"value") != 1)
1197 throw error(ERR_PATCH_BAD);
1198 obj.insert_node(i.field(U"path").as_string(), i.field("value"));
1199 } else if(op == U"replace") {
1200 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1201 throw error(ERR_PATCH_BAD);
1202 if(i.field_count(U"value") != 1)
1203 throw error(ERR_PATCH_BAD);
1204 obj.delete_node(i.field(U"path").as_string());
1205 obj.insert_node(i.field(U"path").as_string(), i.field("value"));
1206 } else if(op == U"move") {
1207 if(i.field_count(U"from") != 1 || i.field(U"from").type() != string)
1208 throw error(ERR_PATCH_BAD);
1209 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1210 throw error(ERR_PATCH_BAD);
1211 std::u32string from = i.field(U"from").as_string();
1212 std::u32string to = i.field(U"path").as_string();
1213 if(to.substr(0, from.length()) == from) {
1214 if(to.length() == from.length())
1215 continue;
1216 if(to.length() > from.length() && to[from.length()] == U'/')
1217 throw error(ERR_PATCH_ILLEGAL_MOVE);
1219 node tmp = obj.delete_node(from);
1220 obj.insert_node(to, tmp);
1221 } else if(op == U"copy") {
1222 if(i.field_count(U"from") != 1 || i.field(U"from").type() != string)
1223 throw error(ERR_PATCH_BAD);
1224 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1225 throw error(ERR_PATCH_BAD);
1226 const node& tmp = obj.follow(i.field(U"from").as_string());
1227 obj.insert_node(i.field(U"path").as_string(), tmp);
1228 } else
1229 throw error(ERR_PATCH_BAD);
1231 return obj;
1235 node::iterator::iterator() throw() { n = NULL; }
1237 node::iterator::iterator(node& _n) throw(error)
1239 n = &_n;
1240 idx = 0;
1241 if(n->type() == object) {
1242 if(n->xobject.empty())
1243 n = NULL;
1244 else
1245 _key = n->xobject.begin()->first;
1246 } else if(n->type() == array) {
1247 if(n->xarray.empty())
1248 n = NULL;
1249 } else
1250 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1253 std::u32string node::iterator::key() throw(std::bad_alloc, error)
1255 if(!n)
1256 throw error(ERR_ITERATOR_END);
1257 return (n->type() == object) ? _key : U"";
1260 size_t node::iterator::index() throw(error)
1262 if(!n)
1263 throw error(ERR_ITERATOR_END);
1264 return idx;
1267 node& node::iterator::operator*() throw(error)
1269 if(!n)
1270 throw error(ERR_ITERATOR_END);
1271 if(n->type() == object) {
1272 if(!n->xobject.count(_key))
1273 throw error(ERR_ITERATOR_DELETED);
1274 auto& l = n->xobject.find(_key)->second;
1275 size_t j = 0;
1276 for(auto i = l.begin(); i != l.end(); i++, j++) {
1277 if(j == idx)
1278 return *i;
1280 throw error(ERR_ITERATOR_DELETED);
1281 } else {
1282 if(idx >= n->xarray.size())
1283 throw error(ERR_ITERATOR_DELETED);
1284 return *n->xarray_index[idx];
1288 node* node::iterator::operator->() throw(error)
1290 return &**this;
1293 node::iterator node::iterator::operator++(int) throw(error)
1295 iterator tmp = *this;
1296 ++*this;
1297 return tmp;
1300 node::iterator& node::iterator::operator++() throw(error)
1302 if(!n)
1303 throw error(ERR_ITERATOR_END);
1304 idx++;
1305 if(n->type() == object) {
1306 if(!n->xobject.count(_key) || n->xobject.find(_key)->second.size() <= idx) {
1307 auto i = n->xobject.upper_bound(_key);
1308 if(i == n->xobject.end())
1309 n = NULL;
1310 else
1311 _key = i->first;
1312 idx = 0;
1314 } else {
1315 if(idx >= n->xarray_index.size())
1316 n = NULL;
1318 return *this;
1321 bool node::iterator::operator==(const iterator& i) throw()
1323 if(n != i.n)
1324 return false;
1325 if(!n && !i.n)
1326 return true;
1327 return (n == i.n && _key == i._key && idx == i.idx);
1330 bool node::iterator::operator!=(const iterator& i) throw() { return !(*this == i); }
1332 node::const_iterator::const_iterator() throw() { n = NULL; }
1334 node::const_iterator::const_iterator(const node& _n) throw(error)
1336 n = &_n;
1337 idx = 0;
1338 if(n->type() == object) {
1339 if(n->xobject.empty())
1340 n = NULL;
1341 else
1342 _key = n->xobject.begin()->first;
1343 } else if(n->type() == array) {
1344 if(n->xarray.empty())
1345 n = NULL;
1346 } else
1347 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1350 std::u32string node::const_iterator::key() throw(std::bad_alloc, error)
1352 if(!n)
1353 throw error(ERR_ITERATOR_END);
1354 return (n->type() == object) ? _key : U"";
1357 size_t node::const_iterator::index() throw(error)
1359 if(!n)
1360 throw error(ERR_ITERATOR_END);
1361 return idx;
1364 const node& node::const_iterator::operator*() throw(error)
1366 if(!n)
1367 throw error(ERR_ITERATOR_END);
1368 if(n->type() == object) {
1369 if(!n->xobject.count(_key))
1370 throw error(ERR_ITERATOR_DELETED);
1371 auto& l = n->xobject.find(_key)->second;
1372 size_t j = 0;
1373 for(auto i = l.begin(); i != l.end(); i++, j++) {
1374 if(j == idx)
1375 return *i;
1377 throw error(ERR_ITERATOR_DELETED);
1378 } else {
1379 if(idx >= n->xarray.size())
1380 throw error(ERR_ITERATOR_DELETED);
1381 return *n->xarray_index[idx];
1385 const node* node::const_iterator::operator->() throw(error)
1387 return &**this;
1390 node::const_iterator node::const_iterator::operator++(int) throw(error)
1392 const_iterator tmp = *this;
1393 ++*this;
1394 return tmp;
1397 node::const_iterator& node::const_iterator::operator++() throw(error)
1399 if(!n)
1400 throw error(ERR_ITERATOR_END);
1401 idx++;
1402 if(n->type() == object) {
1403 if(!n->xobject.count(_key) || n->xobject.find(_key)->second.size() <= idx) {
1404 auto i = n->xobject.upper_bound(_key);
1405 if(i == n->xobject.end())
1406 n = NULL;
1407 else
1408 _key = i->first;
1409 idx = 0;
1411 } else {
1412 if(idx >= n->xarray_index.size())
1413 n = NULL;
1415 return *this;
1418 bool node::const_iterator::operator==(const const_iterator& i) throw()
1420 if(n != i.n)
1421 return false;
1422 if(!n && !i.n)
1423 return true;
1424 return (n == i.n && _key == i._key && idx == i.idx);
1427 bool node::const_iterator::operator!=(const const_iterator& i) throw() { return !(*this == i); }
1429 void node::erase_index(size_t idx) throw(error)
1431 if(type() == array) {
1432 if(idx >= xarray_index.size())
1433 return;
1434 node* n = xarray_index[idx];
1435 xarray_index.erase(xarray_index.begin() + idx);
1436 for(auto i = xarray.begin(); i != xarray.end(); i++)
1437 if(&*i == n) {
1438 xarray.erase(i);
1439 return;
1441 } else
1442 throw error(ERR_NOT_AN_ARRAY);
1445 void node::erase_field(const std::u32string& fld, size_t idx) throw(error)
1447 if(type() == object) {
1448 if(xobject.count(fld)) {
1449 auto& l = xobject[fld];
1450 size_t j = 0;
1451 for(auto i = l.begin(); i != l.end(); i++, j++)
1452 if(j == idx) {
1453 l.erase(i);
1454 break;
1456 if(l.empty())
1457 xobject.erase(fld);
1459 } else
1460 throw error(ERR_NOT_AN_OBJECT);
1463 void node::erase_field_all(const std::u32string& fld) throw(error)
1465 if(type() == object) {
1466 if(xobject.count(fld))
1467 xobject.erase(fld);
1468 } else
1469 throw error(ERR_NOT_AN_OBJECT);
1472 void node::clear() throw(error)
1474 if(type() == object)
1475 xobject.clear();
1476 else if(type() == array) {
1477 xarray_index.clear();
1478 xobject.clear();
1479 } else
1480 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1483 node::iterator node::erase(node::iterator itr) throw(error)
1485 if(itr.n != this)
1486 throw error(ERR_WRONG_OBJECT);
1487 if(type() == object) {
1488 erase_field(itr._key, itr.idx);
1489 if(!xobject.count(itr._key) || itr.idx >= xobject[itr._key].size())
1490 itr++;
1491 return itr;
1492 } else if(type() == array) {
1493 erase_index(itr.idx);
1494 if(itr.idx >= xarray_index.size())
1495 itr.n = NULL;
1496 return itr;
1497 } else
1498 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1501 void node::fixup_nodes(const node& _node)
1503 auto i = xarray.begin();
1504 auto j = _node.xarray.begin();
1505 for(; i != xarray.end(); i++, j++) {
1506 for(size_t k = 0; k < _node.xarray_index.size(); k++)
1507 if(_node.xarray_index[k] == &*j)
1508 xarray_index[k] = &*i;
1512 bool node::operator==(const node& n) const
1514 if(this == &n)
1515 return true;
1516 if(vtype != n.vtype)
1517 return false;
1518 switch(vtype) {
1519 case null_tag::id:
1520 return true;
1521 case boolean_tag::id:
1522 return (_boolean == n._boolean);
1523 case number_tag::id:
1524 return (_number == n._number);
1525 case string_tag::id:
1526 return (_string == n._string);
1527 case array_tag::id:
1528 if(xarray_index.size() != n.xarray_index.size())
1529 return false;
1530 for(size_t i = 0; i < xarray_index.size(); i++)
1531 if(*xarray_index[i] != *n.xarray_index[i])
1532 return false;
1533 return true;
1534 case object_tag::id:
1535 for(auto& i : xobject)
1536 if(!n.xobject.count(i.first))
1537 return false;
1538 for(auto& i : n.xobject)
1539 if(!xobject.count(i.first))
1540 return false;
1541 for(auto& i : xobject) {
1542 auto& j = *xobject.find(i.first);
1543 auto& k = *n.xobject.find(i.first);
1544 if(j.second.size() != k.second.size())
1545 return false;
1546 auto j2 = j.second.begin();
1547 auto k2 = k.second.begin();
1548 for(; j2 != j.second.end(); j2++, k2++)
1549 if(*j2 != *k2)
1550 return false;
1552 return true;
1553 default:
1554 throw error(ERR_UNKNOWN_TYPE);
1558 int node::type_of(const std::u32string& pointer) const throw(std::bad_alloc)
1560 try {
1561 const node* n;
1562 if(follow_soft(pointer, n) != ERR_OK)
1563 return none.id;
1564 return n->type();
1565 } catch(std::bad_alloc& e) {
1566 throw;
1567 } catch(std::exception& e) {
1568 //Shouldn't happen.
1569 return none.id;
1573 int node::type_of_indirect(const std::u32string& pointer) const throw(std::bad_alloc)
1575 try {
1576 const node* n;
1577 if(follow_soft(pointer, n) != ERR_OK)
1578 return none.id;
1579 if(n->type() == string)
1580 return type_of(n->as_string());
1581 else
1582 return n->type();
1583 } catch(std::bad_alloc& e) {
1584 throw;
1585 } catch(std::exception& e) {
1586 //Shouldn't happen.
1587 return none.id;
1591 std::u32string node::resolve_indirect(const std::u32string& pointer) const throw(std::bad_alloc)
1593 try {
1594 const node& n = follow(pointer);
1595 if(n.type() == string)
1596 return n.as_string();
1597 else
1598 return pointer;
1599 } catch(std::bad_alloc& e) {
1600 throw;
1601 } catch(std::exception& e) {
1602 return pointer;
1606 pointer::pointer()
1610 pointer::pointer(const std::string& ptr) throw(std::bad_alloc)
1612 _pointer = utf8::to32(ptr);
1615 pointer::pointer(const std::u32string& ptr) throw(std::bad_alloc)
1617 _pointer = ptr;
1620 pointer pointer::index(uint64_t idx) const throw(std::bad_alloc)
1622 if(_pointer.length())
1623 return pointer(_pointer + U"/" + pointer_escape_index(idx));
1624 else
1625 return pointer(pointer_escape_index(idx));
1628 pointer& pointer::index_inplace(uint64_t idx) throw(std::bad_alloc)
1630 if(_pointer.length())
1631 _pointer = _pointer + U"/" + pointer_escape_index(idx);
1632 else
1633 _pointer = pointer_escape_index(idx);
1634 return *this;
1637 pointer pointer::field(const std::u32string& fld) const throw(std::bad_alloc)
1639 if(_pointer.length())
1640 return pointer(_pointer + U"/" + pointer_escape_field(fld));
1641 else
1642 return pointer(pointer_escape_field(fld));
1645 pointer& pointer::field_inplace(const std::u32string& fld) throw(std::bad_alloc)
1647 if(_pointer.length())
1648 _pointer = _pointer + U"/" + pointer_escape_field(fld);
1649 else
1650 _pointer = pointer_escape_field(fld);
1651 return *this;
1654 pointer pointer::remove() const throw(std::bad_alloc)
1656 size_t p = _pointer.find_last_of(U"/");
1657 if(p >= _pointer.length())
1658 return pointer();
1659 else
1660 return pointer(_pointer.substr(0, p));
1663 pointer& pointer::remove_inplace() throw(std::bad_alloc)
1665 size_t p = _pointer.find_last_of(U"/");
1666 if(p >= _pointer.length())
1667 _pointer = U"";
1668 else
1669 _pointer = _pointer.substr(0, p);
1670 return *this;
1673 std::ostream& operator<<(std::ostream& s, const pointer& p)
1675 return s << utf8::to8(p._pointer);
1678 std::basic_ostream<char32_t>& operator<<(std::basic_ostream<char32_t>& s, const pointer& p)
1680 return s << p._pointer;
1683 printer::~printer() throw()
1687 std::string printer::value_val(const std::string& val)
1689 return val;
1692 std::string printer::value_string(const std::u32string& s)
1694 return json_string_escape(s);
1697 std::string printer::array_begin()
1699 return "[";
1702 std::string printer::array_separator()
1704 return ",";
1707 std::string printer::array_end()
1709 return "]";
1712 std::string printer::object_begin()
1714 return "{";
1717 std::string printer::object_key(const std::u32string& s)
1719 return json_string_escape(s) + ":";
1722 std::string printer::object_separator()
1724 return ",";
1727 std::string printer::object_end()
1729 return "}";
1732 printer_indenting::printer_indenting()
1734 depth = 0;
1735 state = S_STANDARD;
1738 printer_indenting::~printer_indenting() throw()
1742 std::string printer_indenting::linestart(size_t _depth)
1744 std::ostringstream s;
1745 s << "\n";
1746 for(size_t i = 0; i < _depth; i++)
1747 s << " ";
1748 return s.str();
1751 std::string printer_indenting::value_val(const std::string& val)
1753 if(depth == 0)
1754 return val + "\n";
1755 switch(state) {
1756 case S_STANDARD:
1757 return val;
1758 default:
1759 //According to JSON rules, value is not allowed immediately after end of array/object, so
1760 //states S_END and S_START_END really have comma right before.
1761 state = S_STANDARD;
1762 return linestart(depth) + val;
1766 std::string printer_indenting::value_string(const std::u32string& s)
1768 if(depth == 0)
1769 return json_string_escape(s) + "\n";
1770 switch(state) {
1771 case S_STANDARD:
1772 return json_string_escape(s);
1773 default:
1774 //According to JSON rules, value is not allowed immediately after end of array/object, so
1775 //states S_END and S_START_END really have comma right before.
1776 state = S_STANDARD;
1777 return linestart(depth) + json_string_escape(s);
1781 std::string printer_indenting::array_begin()
1783 switch(state) {
1784 case S_STANDARD:
1785 //This can only happen in beginning of expression or after key.
1786 state = S_START;
1787 depth++;
1788 return "[";
1789 case S_END:
1790 //This is really after ], or },
1791 state = S_START;
1792 depth++;
1793 return "[";
1794 case S_COMMA:
1795 case S_START:
1796 case S_START_END:
1797 //S_START_END really has comma right before due to JSON rules.
1798 state = S_START;
1799 return linestart(depth++) + "[";
1801 return "<WTF?>"; //NOTREACHED.
1804 std::string printer_indenting::array_separator()
1806 switch(state) {
1807 case S_END:
1808 case S_START_END:
1809 //These states don't transition to comma.
1810 return ",";
1811 default:
1812 state = S_COMMA;
1813 return ",";
1817 std::string printer_indenting::array_end()
1819 switch(state) {
1820 case S_STANDARD:
1821 case S_END:
1822 case S_COMMA:
1823 case S_START_END:
1824 //S_END or S_START_END is after ']' or '}'.
1825 //S_COMMA can't actually happen per JSON rules.
1826 state = S_END;
1827 --depth;
1828 return linestart(depth) + "]" + (depth ? "" : "\n");
1829 case S_START:
1830 state = S_START_END;
1831 --depth;
1832 return std::string("]") + (depth ? "" : "\n");
1834 return "<WTF?>"; //NOTREACHED.
1837 std::string printer_indenting::object_begin()
1839 switch(state) {
1840 case S_STANDARD:
1841 //This can only happen in beginning of expression or after key.
1842 state = S_START;
1843 depth++;
1844 return "{";
1845 case S_END:
1846 //This is really ], or },
1847 state = S_START;
1848 depth++;
1849 return "{";
1850 case S_COMMA:
1851 case S_START:
1852 case S_START_END:
1853 //S_START_END really has comma right before due to JSON rules.
1854 state = S_START;
1855 return linestart(depth++) + "{";
1857 return "<WTF?>"; //NOTREACHED.
1860 std::string printer_indenting::object_key(const std::u32string& s)
1862 switch(state) {
1863 case S_START:
1864 case S_COMMA:
1865 case S_END:
1866 case S_START_END:
1867 state = S_STANDARD;
1868 return linestart(depth) + json_string_escape(s) + ":";
1869 default:
1870 //Can't actually happe
1871 state = S_STANDARD;
1872 return json_string_escape(s) + ":";
1874 return "<WTF?>"; //NOTREACHED.
1877 std::string printer_indenting::object_separator()
1879 switch(state) {
1880 case S_END:
1881 case S_START_END:
1882 //These states don't transition to comma.
1883 return ",";
1884 default:
1885 state = S_COMMA;
1886 return ",";
1890 std::string printer_indenting::object_end()
1892 switch(state) {
1893 case S_STANDARD:
1894 case S_END:
1895 case S_COMMA:
1896 case S_START_END:
1897 //S_END or S_START_END is after ']' or '}'.
1898 //S_COMMA can't actually happen per JSON rules.
1899 state = S_END;
1900 --depth;
1901 return linestart(depth) + "}" + (depth ? "" : "\n");
1902 case S_START:
1903 state = S_START_END;
1904 --depth;
1905 return "}";
1907 return "<WTF?>"; //NOTREACHED.
1912 bool operator==(const int& n, const JSON::number_tag& v) { return v == n; }
1913 bool operator==(const int& n, const JSON::string_tag& v) { return v == n; }
1914 bool operator==(const int& n, const JSON::boolean_tag& v) { return v == n; }
1915 bool operator==(const int& n, const JSON::array_tag& v) { return v == n; }
1916 bool operator==(const int& n, const JSON::object_tag& v) { return v == n; }
1917 bool operator==(const int& n, const JSON::null_tag& v) { return v == n; }
1918 bool operator!=(const int& n, const JSON::number_tag& v) { return v != n; }
1919 bool operator!=(const int& n, const JSON::string_tag& v) { return v != n; }
1920 bool operator!=(const int& n, const JSON::boolean_tag& v) { return v != n; }
1921 bool operator!=(const int& n, const JSON::array_tag& v) { return v != n; }
1922 bool operator!=(const int& n, const JSON::object_tag& v) { return v != n; }
1923 bool operator!=(const int& n, const JSON::null_tag& v) { return v != n; }