bsnes: redump sprite/palette functions
[lsnes.git] / src / library / json.cpp
blob28861f86bbf7425d250d9ba97c73d8e3f14f9ec3
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 sprintf(buffer, "%s (while expecting %s) at byte %llu", error_desc[code], state_desc[state],
109 (unsigned long long)position);
110 return buffer;
114 std::string error::extended_error(const std::string& doc)
116 if(state == PARSE_NOT_PARSING)
117 return error_desc[code];
118 std::ostringstream s;
119 size_t pos = position;
120 while(pos < doc.length() && (doc[pos] == '\t' || doc[pos] == '\v' || doc[pos] == '\r' || doc[pos] == '\n' ||
121 doc[pos] == ' '))
122 pos++;
123 auto p2 = get_position_lc(doc, pos);
124 s << error_desc[code] << " (while expecting " << state_desc[state] << ") at ";
125 if(position == doc.length())
126 s << "end of input";
127 else {
128 std::ostringstream sample;
129 size_t p = pos;
130 for(size_t i = 0; i < 32; i++) {
131 if(p >= doc.length())
132 break;
133 if(doc[p] < 32) {
134 sample << "<" << asciinames[doc[p++]] << ">";
135 } else if(doc[p] < 127)
136 sample << doc[p++];
137 else if(doc[p] < 128)
138 sample << "<DEL>";
139 else if(doc[p] < 192)
140 sample << "<" << (int)doc[p++] << ">";
141 else if(doc[p] < 224) {
142 sample << doc[p++];
143 sample << doc[p++];
144 } else if(doc[p] < 240) {
145 sample << doc[p++];
146 sample << doc[p++];
147 sample << doc[p++];
148 } else if(doc[p] < 248) {
149 sample << doc[p++];
150 sample << doc[p++];
151 sample << doc[p++];
152 sample << doc[p++];
153 } else
154 sample << "<" << (int)doc[p++] << ">";
156 s << "line " << p2.first << " byte " << p2.second << " [near: '" << sample.str() << "']";
158 return s.str();
161 node number_tag::operator()(double v) const { return node(*this, v); }
162 node number_tag::operator()(uint64_t v) const { return node(*this, v); }
163 node number_tag::operator()(int64_t v) const { return node(*this, v); }
164 node string_tag::operator()(const std::string& s) const { return node(*this, s); }
165 node string_tag::operator()(const std::u32string& s) const { return node(*this, s); }
166 node boolean_tag::operator()(bool v) { return node(*this, v); }
167 node array_tag::operator()() const { return node(*this); }
168 node object_tag::operator()() const { return node(*this); }
169 node null_tag::operator()() const { return node(*this); }
171 node i(int64_t n) { return number(n); }
172 node u(uint64_t n) { return number(n); }
173 node f(double n) { return number(n); }
174 node b(bool bl) { return boolean(bl); }
175 node s(const std::string& st) { return string(st); }
176 node s(const std::u32string& st) { return string(st); }
177 node n() { return null(); }
179 number_tag number;
180 string_tag string;
181 boolean_tag boolean;
182 array_tag array;
183 object_tag object;
184 null_tag null;
185 none_tag none;
187 template<> void node::number_holder::from(double val) { sub = 0; n.n0 = val; }
188 template<> void node::number_holder::from(uint64_t val) { sub = 1; n.n1 = val; }
189 template<> void node::number_holder::from(int64_t val) { sub = 2; n.n2 = val; }
191 namespace
193 unsigned numchar(char c)
195 switch(c) {
196 case '0': return 0;
197 case '1': case '2': case '3': case '4': case '5':
198 case '6': case '7': case '8': case '9': return 1;
199 case '.': return 2;
200 case 'e': return 3;
201 case '+': return 4;
202 case '-': return 5;
203 default: return 6;
207 uint32_t numdfa[] = {
208 0x0F1FFF32, //0: STATE_INITIAL
209 0x0FFFFF32, //1: STATE_AFTER_MINUS
210 0x1FFF64FF, //2: STATE_INT_Z
211 0x1FFF6433, //3: STATE_INT_NZ
212 0x0FFFFF55, //4: STATE_DECIMAL
213 0x1FFF6F55, //5: STATE_DECIMAL_N
214 0x0F77FF88, //6: STATE_EXP
215 0x0FFFFF88, //7: STATE_EXP_SIGN
216 0x1FFFFF88, //8: STATE_EXP_N
220 node::number_holder::number_holder(const std::string& expr, size_t& ptr, size_t len)
222 //-?(0|1-9[0-9]+)(.[0-9]+)?([eE][+-]?[0-9]+)?
223 int state = 0;
224 size_t tmp = ptr;
225 size_t tmp2 = ptr;
226 std::string x;
227 while(tmp < len) {
228 unsigned c = numchar(expr[tmp]);
229 unsigned ns = (numdfa[state] >> (4 * c)) & 0xF;
230 if(ns == 0xF)
231 break;
232 else
233 state = ns;
234 tmp++;
236 if(!(numdfa[state] >> 28))
237 goto bad;
238 x = expr.substr(ptr, tmp - ptr);
239 ptr = tmp;
240 try {
241 if(regex_match("[0-9]+", x)) {
242 n.n1 = parse_value<uint64_t>(x);
243 sub = 1;
244 return;
246 } catch(...) {}
247 try {
248 if(regex_match("[+-]?[0-9]+", x)) {
249 n.n2 = parse_value<int64_t>(x);
250 sub = 2;
251 return;
253 } catch(...) {}
254 try {
255 n.n0 = parse_value<double>(x);
256 sub = 0;
257 return;
258 } catch(...) {}
259 bad:
260 throw error(ERR_INVALID_NUMBER, PARSE_NUMBER, tmp2);
264 void node::number_holder::write(std::ostream& s) const
266 switch(sub) {
267 case 0: s << n.n0; break;
268 case 1: s << n.n1; break;
269 case 2: s << n.n2; break;
273 template<typename T> bool node::number_holder::cmp(const T& num) const
275 switch(sub) {
276 case 0: return n.n0 == num;
277 case 1: return n.n1 == num;
278 case 2: return n.n2 == num;
280 throw error(ERR_UNKNOWN_SUBTYPE);
283 template<> bool node::number_holder::cmp(const int64_t& num) const
285 switch(sub) {
286 case 0: return n.n0 == num;
287 case 1: return num >= 0 && n.n1 == static_cast<uint64_t>(num);
288 case 2: return n.n2 == num;
290 throw error(ERR_UNKNOWN_SUBTYPE);
293 template<> bool node::number_holder::cmp(const uint64_t& num) const
295 switch(sub) {
296 case 0: return n.n0 == num;
297 case 1: return n.n1 == num;
298 case 2: return n.n2 >= 0 && static_cast<uint64_t>(n.n2) == num;
300 throw error(ERR_UNKNOWN_SUBTYPE);
304 bool node::number_holder::operator==(const number_holder& h) const
306 switch(sub) {
307 case 0: return h.cmp(n.n0);
308 case 1: return h.cmp(n.n1);
309 case 2: return h.cmp(n.n2);
311 throw error(ERR_UNKNOWN_SUBTYPE);
314 node::node() throw() : node(null) {}
315 node::node(null_tag) throw() { vtype = null; }
316 node::node(boolean_tag, bool b) throw() { vtype = boolean; _boolean = b; }
317 node::node(string_tag, const std::u32string& str) throw(std::bad_alloc) { vtype = string; _string = str; }
318 node::node(string_tag, const std::string& str) throw(std::bad_alloc) { vtype = string; _string = utf8::to32(str); }
319 node::node(number_tag, double n) throw() { vtype = number; _number.from<double>(n); }
320 node::node(number_tag, int64_t n) throw() { vtype = number; _number.from<int64_t>(n); }
321 node::node(number_tag, uint64_t n) throw() { vtype = number; _number.from<uint64_t>(n); }
322 node::node(array_tag) throw() { vtype = array; }
323 node::node(object_tag) throw() { vtype = object; }
324 int node::type() const throw() { return vtype; }
326 node& node::set(null_tag) throw() { set_helper<uint64_t>(0); vtype = null; return *this; }
327 node& node::set(boolean_tag, bool n) throw() { set_helper<uint64_t>(0); vtype = boolean; _boolean = n; return *this; }
328 node& node::set(number_tag, double n) throw() { set_helper<double>(n); return *this; }
329 node& node::set(number_tag, int64_t n) throw() { set_helper<int64_t>(n); return *this; }
330 node& node::set(number_tag, uint64_t n) throw() { set_helper<int64_t>(n); return *this; }
332 node& node::set(string_tag, const std::u32string& key) throw(std::bad_alloc)
334 std::u32string tmp = key;
335 std::swap(_string, tmp);
336 vtype = string;
337 xarray.clear();
338 xobject.clear();
339 return *this;
342 double node::as_double() const throw(error)
344 return get_number_helper<double>();
347 int64_t node::as_int() const throw(error)
349 return get_number_helper<int64_t>();
352 uint64_t node::as_uint() const throw(error)
354 return get_number_helper<uint64_t>();
357 const std::u32string& node::as_string() const throw(std::bad_alloc, error)
359 if(vtype != string)
360 throw error(ERR_NOT_A_STRING);
361 return _string;
364 bool node::as_bool() const throw(error)
366 if(vtype != boolean)
367 throw error(ERR_NOT_A_BOOLEAN);
368 return _boolean;
371 size_t node::index_count() const throw(error)
373 if(vtype != array)
374 throw error(ERR_NOT_AN_ARRAY);
375 return xarray.size();
378 errorcode node::index_soft(size_t index, const node*& out) const throw()
380 if(vtype != array)
381 return ERR_NOT_AN_ARRAY;
382 if(index >= xarray_index.size())
383 return ERR_INDEX_INVALID;
384 out = xarray_index[index];
385 return ERR_OK;
388 errorcode node::index_soft(size_t index, node*& out) throw()
390 if(vtype != array)
391 return ERR_NOT_AN_ARRAY;
392 if(index >= xarray_index.size())
393 return ERR_INDEX_INVALID;
394 out = xarray_index[index];
395 return ERR_OK;
398 size_t node::field_count(const std::u32string& key) const throw(error)
400 if(vtype != object)
401 throw error(ERR_NOT_AN_OBJECT);
402 if(!xobject.count(key))
403 return 0;
404 return xobject.find(key)->second.size();
407 bool node::field_exists(const std::u32string& key) const throw(error)
409 return (field_count(key) > 0);
412 errorcode node::field_soft(const std::u32string& key, size_t subindex, const node*& out) const throw()
414 if(vtype != object)
415 return ERR_NOT_AN_OBJECT;
416 if(!xobject.count(key))
417 return ERR_KEY_INVALID;
418 const std::list<node>& l = xobject.find(key)->second;
419 size_t j = 0;
420 for(auto i = l.begin(); i != l.end(); i++, j++) {
421 if(j == subindex) {
422 out = &*i;
423 return ERR_OK;
426 return ERR_INSTANCE_INVALID;
429 errorcode node::field_soft(const std::u32string& key, size_t subindex, node*& out) throw()
431 if(vtype != object)
432 return ERR_NOT_AN_OBJECT;
433 if(!xobject.count(key))
434 return ERR_KEY_INVALID;
435 std::list<node>& l = xobject.find(key)->second;
436 size_t j = 0;
437 for(auto i = l.begin(); i != l.end(); i++, j++) {
438 if(j == subindex) {
439 out = &*i;
440 return ERR_OK;
443 return ERR_INSTANCE_INVALID;
446 node::node(const node& _node) throw(std::bad_alloc)
448 std::u32string tmp1 = _node._string;
449 std::list<node> tmp2 = _node.xarray;
450 std::map<std::u32string, std::list<node>> tmp3 = _node.xobject;
451 std::vector<node*> tmp4 = _node.xarray_index;
453 vtype = _node.vtype;
454 _number = _node._number;
455 _boolean = _node._boolean;
456 _string = _node._string;
457 xarray = _node.xarray;
458 xobject = _node.xobject;
459 xarray_index = _node.xarray_index;
460 fixup_nodes(_node);
463 node& node::operator=(const node& _node) throw(std::bad_alloc)
465 if(this == &_node)
466 return *this;
467 std::u32string tmp1 = _node._string;
468 std::list<node> tmp2 = _node.xarray;
469 std::map<std::u32string, std::list<node>> tmp3 = _node.xobject;
470 std::vector<node*> tmp4 = _node.xarray_index;
472 vtype = _node.vtype;
473 _number = _node._number;
474 _boolean = _node._boolean;
475 std::swap(_string, tmp1);
476 std::swap(xarray, tmp2);
477 std::swap(xobject, tmp3);
478 std::swap(xarray_index, tmp4);
479 fixup_nodes(_node);
480 return *this;
483 node& node::append(const node& _node) throw(std::bad_alloc, error)
485 if(vtype != array)
486 throw error(ERR_NOT_AN_ARRAY);
487 bool p = false;
488 try {
489 xarray.push_back(_node);
490 p = true;
491 node* ptr = &*xarray.rbegin();
492 xarray_index.push_back(ptr);
493 return *ptr;
494 } catch(std::bad_alloc& e) {
495 if(p)
496 xarray.pop_back();
497 throw;
501 node& node::insert(const std::u32string& key, const node& _node) throw(std::bad_alloc, error)
503 if(vtype != object)
504 throw error(ERR_NOT_AN_OBJECT);
505 try {
506 xobject[key].push_back(_node);
507 return *xobject[key].rbegin();
508 } catch(...) {
509 if(xobject.count(key) && xobject[key].empty())
510 xobject.erase(key);
511 throw;
515 namespace
517 errorcode jsonptr_unescape_soft(const std::u32string& c, size_t start, size_t end, std::u32string& _out)
519 std::basic_ostringstream<char32_t> out;
520 for(size_t ptr = start; ptr < end; ptr++) {
521 if(c[ptr] == '~') {
522 if(ptr == end - 1)
523 return ERR_POINTER_TRAILING_ESCAPE;
524 ptr++;
525 if(c[ptr] == '0')
526 out << U"~";
527 else if(c[ptr] == '1')
528 out << U"/";
529 else
530 return ERR_POINTER_INVALID_ESCAPE;
531 } else
532 out << c[ptr];
534 _out = out.str();
535 return ERR_OK;
538 std::u32string jsonptr_unescape(const std::u32string& c, size_t start, size_t end)
540 std::u32string o;
541 auto e = jsonptr_unescape_soft(c, start, end, o);
542 if(e != ERR_OK) throw error(e);
543 return o;
548 errorcode node::follow_soft(const std::u32string& pointer, const node*& current) const throw(std::bad_alloc)
550 errorcode e;
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 errorcode e;
582 size_t ptr = 0;
583 while(ptr < pointer.length()) {
584 size_t p = pointer.find_first_of(U"/", ptr);
585 if(p > pointer.length())
586 p = pointer.length();
587 std::u32string c;
588 auto e = jsonptr_unescape_soft(pointer, ptr, p, c);
589 if(e != ERR_OK) return e;
590 if(current->vtype == array) {
591 if(c == U"-")
592 return ERR_POINTER_BAD_APPEND;
593 size_t idx;
594 if(!parse_size_t(c, idx))
595 return ERR_POINTER_BAD_INDEX;
596 e = current->index_soft(idx, current);
597 if(e != ERR_OK) return e;
598 } else if(current->vtype == object) {
599 e = current->field_soft(c, 0, current);
600 if(e != ERR_OK) return e;
601 } else
602 return ERR_NOT_ARRAY_NOR_OBJECT;
603 ptr = p + 1;
605 return ERR_OK;
608 namespace
610 struct json_token
612 enum ttype { TSTRING, TNUMBER, TOBJECT, TARRAY, TINVALID, TCOMMA, TOBJECT_END, TARRAY_END, TCOLON,
613 TEOF, TTRUE, TFALSE, TNULL };
614 ttype type;
615 std::u32string value;
616 json_token(enum ttype t, const std::u32string& v) { type = t; value = v; }
617 json_token(enum ttype t) { type = t; }
620 uint32_t parse_hex(int32_t ch, parsestate state, size_t pos)
622 switch(ch) {
623 case '0': return 0;
624 case '1': return 1;
625 case '2': return 2;
626 case '3': return 3;
627 case '4': return 4;
628 case '5': return 5;
629 case '6': return 6;
630 case '7': return 7;
631 case '8': return 8;
632 case '9': return 9;
633 case 'A': case 'a': return 10;
634 case 'B': case 'b': return 11;
635 case 'C': case 'c': return 12;
636 case 'D': case 'd': return 13;
637 case 'E': case 'e': return 14;
638 case 'F': case 'f': return 15;
639 default: throw error(ERR_BAD_HEX, state, pos);
643 class iterator_counter
645 public:
646 iterator_counter(size_t& _count) : count(_count) { count = 0; }
647 char32_t& operator*() { count++; return x; }
648 iterator_counter& operator++() { return *this; }
649 size_t get_count() { return count; }
650 private:
651 char32_t x;
652 size_t& count;
655 //STATE_NORMAL 0
656 //STATE_ESCAPE 1
657 //STATE_ESCAPE_HEX0 2
658 //STATE_ESCAPE_HEX1 3
659 //STATE_ESCAPE_HEX2 4
660 //STATE_ESCAPE_HEX3 5
661 //STATE_ESCAPE_SURROGATE 6
662 //STATE_ESCAPE_SURROGATE2 7
663 //STATE_ESCAPE_SURROGATE_HEX0 8
664 //STATE_ESCAPE_SURROGATE_HEX1 9
665 //STATE_ESCAPE_SURROGATE_HEX2 10
666 //STATE_ESCAPE_SURROGATE_HEX3 11
668 template<typename T> size_t read_string_impl(T target, const std::string& doc, size_t ptr, size_t len)
670 uint16_t ustate = utf8::initial_state;
671 int estate = 0;
672 uint32_t extra = 0;
673 uint32_t tmp;
674 size_t i;
675 size_t lc = ptr;
676 for(i = ptr; i <= len; i++) {
677 int ch = -1;
678 if(i < len)
679 ch = (unsigned char)doc[i];
680 int32_t uch = utf8::parse_byte(ch, ustate);
681 if(uch < 0)
682 continue;
683 //Okay, have Unicode codepoint decoded.
684 switch(estate) {
685 case 0:
686 lc = i;
687 extra = 0;
688 if(uch < 32)
689 throw error(ERR_CONTROL_CHARACTER, PARSE_STRING_BODY, lc);
690 if(uch == '\"')
691 goto out;
692 if(uch == '\\')
693 estate = 1;
694 else {
695 *target = uch;
696 ++target;
698 break;
699 case 1:
700 switch(uch) {
701 case '\"': *target = U'\"'; ++target; estate = 0; break;
702 case '\\': *target = U'\\'; ++target; estate = 0; break;
703 case '/': *target = U'/'; ++target; estate = 0; break;
704 case 'b': *target = U'\b'; ++target; estate = 0; break;
705 case 'f': *target = U'\f'; ++target; estate = 0; break;
706 case 'n': *target = U'\n'; ++target; estate = 0; break;
707 case 'r': *target = U'\r'; ++target; estate = 0; break;
708 case 't': *target = U'\t'; ++target; estate = 0; break;
709 case 'u':
710 estate = 2;
711 break;
712 default:
713 throw error(ERR_INVALID_ESCAPE, PARSE_STRING_ESCAPE, lc);
715 break;
716 case 2: case 3: case 4: case 8: case 9: case 10:
717 extra = (extra << 4) | parse_hex(uch, PARSE_STRING_ESCAPE, lc);
718 estate++;
719 break;
720 case 5:
721 extra = (extra << 4) | parse_hex(uch, PARSE_STRING_ESCAPE, lc);
722 if((extra & 0xFC00) == 0xDC00)
723 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
724 else if((extra & 0xFC00) == 0xD800)
725 estate = 6;
726 else if((extra & 0xFFFE) == 0xFFFE)
727 throw error(ERR_ILLEGAL_CHARACTER, PARSE_STRING_ESCAPE, lc);
728 else {
729 estate = 0;
730 *target = extra;
731 ++target;
733 break;
734 case 6:
735 if(uch != '\\')
736 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
737 estate = 7;
738 break;
739 case 7:
740 if(uch != 'u')
741 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
742 estate = 8;
743 break;
744 case 11:
745 extra = (extra << 4) | parse_hex(uch, PARSE_STRING_ESCAPE, lc);
746 if((extra & 0xFC00FC00UL) != 0xD800DC00)
747 throw error(ERR_INVALID_SURROGATE, PARSE_STRING_ESCAPE, lc);
748 tmp = ((extra & 0x3FF0000) >> 6) + (extra & 0x3FF) + 0x10000;
749 if((tmp & 0xFFFE) == 0xFFFE)
750 throw error(ERR_ILLEGAL_CHARACTER, PARSE_STRING_ESCAPE, lc);
751 *target = tmp;
752 ++target;
753 estate = 0;
754 break;
757 throw error(ERR_TRUNCATED_STRING, estate ? PARSE_STRING_ESCAPE : PARSE_STRING_BODY, len);
758 out:
759 return i;
762 void read_string(std::u32string& target, const std::string& doc, size_t& ptr, size_t len)
764 size_t cpcnt;
765 read_string_impl(iterator_counter(cpcnt), doc, ptr, len);
766 target.resize(cpcnt);
767 ptr = read_string_impl(target.begin(), doc, ptr, len) + 1;
770 json_token parse_token(const std::string& doc, size_t& ptr, size_t len)
772 while(ptr < len && (doc[ptr] == ' ' || doc[ptr] == '\t' || doc[ptr] == '\r' || doc[ptr] == '\n'))
773 ptr++;
774 if(ptr >= len)
775 return json_token(json_token::TEOF);
776 if(doc[ptr] == '{') {
777 ptr++;
778 return json_token(json_token::TOBJECT);
780 if(doc[ptr] == '}') {
781 ptr++;
782 return json_token(json_token::TOBJECT_END);
784 if(doc[ptr] == '[') {
785 ptr++;
786 return json_token(json_token::TARRAY);
788 if(doc[ptr] == ']') {
789 ptr++;
790 return json_token(json_token::TARRAY_END);
792 if(doc[ptr] == ',') {
793 ptr++;
794 return json_token(json_token::TCOMMA);
796 if(doc[ptr] == ':') {
797 ptr++;
798 return json_token(json_token::TCOLON);
800 if(doc[ptr] == '\"') {
801 //String.
802 ptr++;
803 return json_token(json_token::TSTRING);
805 if(doc[ptr] == '-' || (doc[ptr] >= '0' && doc[ptr] <= '9')) {
806 //Number.
807 return json_token(json_token::TNUMBER);
809 if(doc[ptr] == 'n') {
810 if(ptr >= len || doc[ptr++] != 'n') goto bad;
811 if(ptr >= len || doc[ptr++] != 'u') goto bad;
812 if(ptr >= len || doc[ptr++] != 'l') goto bad;
813 if(ptr >= len || doc[ptr++] != 'l') goto bad;
814 return json_token(json_token::TNULL);
816 if(doc[ptr] == 'f') {
817 if(ptr >= len || doc[ptr++] != 'f') goto bad;
818 if(ptr >= len || doc[ptr++] != 'a') goto bad;
819 if(ptr >= len || doc[ptr++] != 'l') goto bad;
820 if(ptr >= len || doc[ptr++] != 's') goto bad;
821 if(ptr >= len || doc[ptr++] != 'e') goto bad;
822 return json_token(json_token::TFALSE);
824 if(doc[ptr] == 't') {
825 if(ptr >= len || doc[ptr++] != 't') goto bad;
826 if(ptr >= len || doc[ptr++] != 'r') goto bad;
827 if(ptr >= len || doc[ptr++] != 'u') goto bad;
828 if(ptr >= len || doc[ptr++] != 'e') goto bad;
829 return json_token(json_token::TTRUE);
831 bad:
832 return json_token(json_token::TINVALID);
835 std::string json_string_escape(const std::u32string& c)
837 std::ostringstream out;
838 out << "\"";
839 size_t len = c.length();
840 for(size_t i = 0; i < len; i++) {
841 if(c[i] == '\b') out << "\\b";
842 else if(c[i] == '\n') out << "\\n";
843 else if(c[i] == '\r') out << "\\r";
844 else if(c[i] == '\t') out << "\\t";
845 else if(c[i] == '\f') out << "\\f";
846 else if((c[i] & 0xFFFFFFE0) == 0)
847 out << "\\u" << hex::to16(c[i]);
848 else if(c[i] == U'\\')
849 out << "\\\\";
850 else if(c[i] == U'\"')
851 out << "\\\"";
852 else if(c[i] < 0x80)
853 out << (unsigned char)c[i];
854 else if(c[i] < 0x800) {
855 out << (unsigned char)(0xC0 + (c[i] >> 6));
856 out << (unsigned char)(0x80 + (c[i] & 0x3F));
857 } else if(c[i] < 0x10000) {
858 out << (unsigned char)(0xE0 + (c[i] >> 12));
859 out << (unsigned char)(0x80 + ((c[i] >> 6) & 0x3F));
860 out << (unsigned char)(0x80 + (c[i] & 0x3F));
861 } else if(c[i] < 0x10FFFF) {
862 out << (unsigned char)(0xF0 + (c[i] >> 18));
863 out << (unsigned char)(0x80 + ((c[i] >> 12) & 0x3F));
864 out << (unsigned char)(0x80 + ((c[i] >> 6) & 0x3F));
865 out << (unsigned char)(0x80 + (c[i] & 0x3F));
868 out << "\"";
869 return out.str();
872 void skip_ws(const std::string& doc, size_t& ptr, size_t len) {
873 while(ptr < len && (doc[ptr] == ' ' || doc[ptr] == '\t' || doc[ptr] == '\v' || doc[ptr] == '\r' ||
874 doc[ptr] == '\n')) {
875 ptr++;
879 std::u32string pointer_escape_field(const std::u32string& orig) throw(std::bad_alloc)
881 std::basic_stringstream<char32_t> x;
882 for(auto i : orig) {
883 if(i == U'~')
884 x << U"~0";
885 else if(i == U'/')
886 x << U"~1";
887 else
888 x << i;
890 return x.str();
893 std::u32string pointer_escape_index(uint64_t idx) throw(std::bad_alloc)
895 std::string orig = (stringfmt() << idx).str();
896 std::basic_ostringstream<char32_t> x;
897 for(auto i : orig)
898 x << (char32_t)i;
899 return x.str();
903 std::string node::serialize(printer* _printer) const throw(std::bad_alloc, error)
905 printer xprinter;
906 _printer = _printer ? _printer : &xprinter;
907 printer& oprinter = *_printer;
908 std::ostringstream out;
909 bool first = true;
910 switch(vtype) {
911 case null_tag::id: return oprinter.value_val("null");
912 case boolean_tag::id: return oprinter.value_val(_boolean ? "true" : "false");
913 case number_tag::id:
914 _number.write(out);
915 return oprinter.value_val(out.str());
916 case string_tag::id:
917 return oprinter.value_string(_string);
918 case array_tag::id:
919 out << oprinter.array_begin();
920 for(auto& i : xarray_index) {
921 if(!first) out << oprinter.array_separator();
922 out << i->serialize(_printer);
923 first = false;
925 out << oprinter.array_end();
926 return out.str();
927 case object_tag::id:
928 out << oprinter.object_begin();
929 for(auto& i : xobject) {
930 for(auto& j : i.second) {
931 if(!first) out << oprinter.object_separator();
932 out << oprinter.object_key(i.first);
933 out << j.serialize(_printer);
934 first = false;
937 out << oprinter.object_end();
938 return out.str();
940 throw error(ERR_UNKNOWN_TYPE);
943 node::node(const std::string& doc) throw(std::bad_alloc, error)
945 size_t tmp = 0;
946 ctor(doc, tmp, doc.length());
947 skip_ws(doc, tmp, doc.length());
948 if(tmp < doc.length())
949 throw error(ERR_GARBAGE_AFTER_END, PARSE_END_OF_DOCUMENT, tmp);
952 void node::ctor(const std::string& doc, size_t& ptr, size_t len) throw(std::bad_alloc, error)
954 size_t tmp3;
955 tmp3 = ptr;
956 json_token t = parse_token(doc, ptr, len);
957 size_t tmp = ptr;
958 std::string tmp2;
959 switch(t.type) {
960 case json_token::TTRUE:
961 set(boolean, true);
962 return;
963 case json_token::TFALSE:
964 set(boolean, false);
965 return;
966 case json_token::TNULL:
967 set(null);
968 return;
969 case json_token::TEOF:
970 throw error(ERR_TRUNCATED_JSON, PARSE_VALUE_START, ptr);
971 case json_token::TCOMMA:
972 throw error(ERR_UNEXPECTED_COMMA, PARSE_VALUE_START, tmp3);
973 case json_token::TCOLON:
974 throw error(ERR_UNEXPECTED_COLON, PARSE_VALUE_START, tmp3);
975 case json_token::TARRAY_END:
976 throw error(ERR_UNEXPECTED_RIGHT_BRACKET, PARSE_VALUE_START, tmp3);
977 case json_token::TOBJECT_END:
978 throw error(ERR_UNEXPECTED_RIGHT_BRACE, PARSE_VALUE_START, tmp3);
979 case json_token::TSTRING:
980 set(string, U"");
981 read_string(_string, doc, ptr, len);
982 break;
983 case json_token::TNUMBER:
984 set(number, 0.0);
985 _number = number_holder(doc, ptr, len);
986 break;
987 case json_token::TOBJECT:
988 *this = object();
989 if(parse_token(doc, tmp, len).type == json_token::TOBJECT_END) {
990 ptr = tmp;
991 break;
993 while(true) {
994 tmp3 = ptr;
995 json_token t2 = parse_token(doc, ptr, len);
996 if(t2.type == json_token::TEOF)
997 throw error(ERR_TRUNCATED_JSON, PARSE_OBJECT_NAME, ptr);
998 if(t2.type != json_token::TSTRING)
999 throw error(ERR_EXPECTED_STRING_KEY, PARSE_OBJECT_NAME, tmp3);
1000 std::u32string key;
1001 read_string(key, doc, ptr, len);
1002 tmp3 = ptr;
1003 t2 = parse_token(doc, ptr, len);
1004 if(t2.type == json_token::TEOF)
1005 throw error(ERR_TRUNCATED_JSON, PARSE_OBJECT_COLON, ptr);
1006 if(t2.type != json_token::TCOLON)
1007 throw error(ERR_EXPECTED_COLON, PARSE_OBJECT_COLON, tmp3);
1008 insert(key, node(doc, ptr, len));
1009 tmp3 = ptr;
1010 t2 = parse_token(doc, ptr, len);
1011 if(t2.type == json_token::TEOF)
1012 throw error(ERR_TRUNCATED_JSON, PARSE_OBJECT_AFTER_VALUE, ptr);
1013 if(t2.type == json_token::TOBJECT_END)
1014 break;
1015 if(t2.type != json_token::TCOMMA)
1016 throw error(ERR_EXPECTED_COMMA, PARSE_OBJECT_AFTER_VALUE, tmp3);
1018 break;
1019 case json_token::TARRAY:
1020 *this = array();
1021 if(parse_token(doc, tmp, len).type == json_token::TARRAY_END) {
1022 ptr = tmp;
1023 break;
1025 while(true) {
1026 append(node(doc, ptr, len));
1027 tmp3 = ptr;
1028 json_token t2 = parse_token(doc, ptr, len);
1029 if(t2.type == json_token::TEOF)
1030 throw error(ERR_TRUNCATED_JSON, PARSE_ARRAY_AFTER_VALUE, ptr);
1031 if(t2.type == json_token::TARRAY_END)
1032 break;
1033 if(t2.type != json_token::TCOMMA)
1034 throw error(ERR_EXPECTED_COMMA, PARSE_ARRAY_AFTER_VALUE, tmp3);
1036 break;
1037 case json_token::TINVALID:
1038 throw error(ERR_UNKNOWN_CHARACTER, PARSE_VALUE_START, tmp3);
1042 node::node(const std::string& doc, size_t& ptr, size_t len) throw(std::bad_alloc, error)
1044 ctor(doc, ptr, len);
1047 node& node::operator[](const std::u32string& pointer) throw(std::bad_alloc, error)
1049 node* current = this;
1050 size_t ptr = 0;
1051 while(ptr < pointer.length()) {
1052 size_t p = pointer.find_first_of(U"/", ptr);
1053 if(p > pointer.length())
1054 p = pointer.length();
1055 std::u32string c = jsonptr_unescape(pointer, ptr, p);
1056 if(current->vtype == array) {
1057 if(c == U"-") {
1058 //End-of-array.
1059 if(p < pointer.length())
1060 throw error(ERR_POINTER_BAD_APPEND);
1061 return current->append(n());
1063 size_t idx;
1064 if(!parse_size_t(c, idx))
1065 throw error(ERR_POINTER_BAD_INDEX);
1066 if(idx > current->xarray.size())
1067 throw error(ERR_POINTER_BAD_APPEND);
1068 else if(idx == current->xarray.size())
1069 return current->append(n());
1070 current = &current->index(idx);
1071 } else if(current->vtype == object) {
1072 if(!current->field_exists(c) && p == pointer.length())
1073 return current->insert(c, n());
1074 current = &current->field(c);
1075 } else
1076 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1077 ptr = p + 1;
1079 return *current;
1082 node& node::insert_node(const std::u32string& pointer, const node& nwn) throw(std::bad_alloc, error)
1084 size_t s = pointer.find_last_of(U"/");
1085 node* base;
1086 std::u32string rest;
1087 size_t ptrlen = pointer.length();
1088 if(s < ptrlen) {
1089 base = &follow(pointer.substr(0, s));
1090 rest = jsonptr_unescape(pointer, s + 1, ptrlen);
1091 } else {
1092 base = this;
1093 rest = jsonptr_unescape(pointer, 0, ptrlen);
1095 if(base->type() == array) {
1096 if(rest == U"-")
1097 return base->append(nwn);
1098 size_t idx;
1099 if(!parse_size_t(rest, idx))
1100 throw error(ERR_POINTER_BAD_INDEX);
1101 if(idx > base->xarray.size())
1102 throw error(ERR_POINTER_BAD_APPEND);
1103 else if(idx == base->xarray.size())
1104 return base->append(nwn);
1105 bool p = false;
1106 try {
1107 base->xarray.push_back(nwn);
1108 p = true;
1109 node* ptr = &*base->xarray.rbegin();
1110 base->xarray_index.insert(base->xarray_index.begin() + idx, ptr);
1111 return *ptr;
1112 } catch(std::bad_alloc& e) {
1113 if(p)
1114 base->xarray.pop_back();
1115 throw;
1117 } else if(base->type() == object) {
1118 if(xobject.count(rest))
1119 return *base->xobject[rest].begin() = nwn;
1120 else {
1121 try {
1122 base->xobject[rest].push_back(nwn);
1123 return *base->xobject[rest].begin();
1124 } catch(...) {
1125 base->xobject.erase(rest);
1126 throw;
1129 } else
1130 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1133 node node::delete_node(const std::u32string& pointer) throw(std::bad_alloc, error)
1135 size_t s = pointer.find_last_of(U"/");
1136 node* base;
1137 std::u32string rest;
1138 size_t ptrlen = pointer.length();
1139 if(s < ptrlen) {
1140 base = &follow(pointer.substr(0, s));
1141 rest = jsonptr_unescape(pointer, s + 1, ptrlen);
1142 } else {
1143 base = this;
1144 rest = jsonptr_unescape(pointer, 0, ptrlen);
1146 if(base->type() == array) {
1147 if(rest == U"-")
1148 throw error(ERR_POINTER_BAD_APPEND);
1149 size_t idx;
1150 if(!parse_size_t(rest, idx))
1151 throw error(ERR_POINTER_BAD_INDEX);
1152 if(idx >= base->xarray.size())
1153 throw error(ERR_INDEX_INVALID);
1154 node* dptr = base->xarray_index[idx];
1155 node tmp = *dptr;
1156 for(auto i = base->xarray.begin(); i != base->xarray.end(); ++i)
1157 if(&*i == dptr) {
1158 base->xarray.erase(i);
1159 break;
1161 base->xarray_index.erase(base->xarray_index.begin() + idx);
1162 return tmp;
1163 } else if(base->type() == object) {
1164 if(xobject.count(rest)) {
1165 node tmp = *base->xobject[rest].begin();
1166 base->xobject.erase(rest);
1167 return tmp;
1168 } else
1169 throw error(ERR_KEY_INVALID);
1170 } else
1171 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1174 node node::patch(const node& patch) const throw(std::bad_alloc, error)
1176 node obj(*this);
1177 if(patch.type() != array)
1178 throw error(ERR_PATCH_BAD);
1179 for(auto& i : patch) {
1180 if(i.type() != object || i.field_count(U"op") != 1 || i.field(U"op").type() != string)
1181 throw error(ERR_PATCH_BAD);
1182 std::u32string op = i.field(U"op").as_string();
1183 if(op == U"test") {
1184 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1185 throw error(ERR_PATCH_BAD);
1186 if(i.field_count(U"value") != 1)
1187 throw error(ERR_PATCH_BAD);
1188 if(obj.follow(i.field(U"path").as_string()) != i.field("value"))
1189 throw error(ERR_PATCH_TEST_FAILED);
1190 } else if(op == U"remove") {
1191 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1192 throw error(ERR_PATCH_BAD);
1193 obj.delete_node(i.field(U"path").as_string());
1194 } else if(op == U"add") {
1195 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1196 throw error(ERR_PATCH_BAD);
1197 if(i.field_count(U"value") != 1)
1198 throw error(ERR_PATCH_BAD);
1199 obj.insert_node(i.field(U"path").as_string(), i.field("value"));
1200 } else if(op == U"replace") {
1201 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1202 throw error(ERR_PATCH_BAD);
1203 if(i.field_count(U"value") != 1)
1204 throw error(ERR_PATCH_BAD);
1205 obj.delete_node(i.field(U"path").as_string());
1206 obj.insert_node(i.field(U"path").as_string(), i.field("value"));
1207 } else if(op == U"move") {
1208 if(i.field_count(U"from") != 1 || i.field(U"from").type() != string)
1209 throw error(ERR_PATCH_BAD);
1210 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1211 throw error(ERR_PATCH_BAD);
1212 std::u32string from = i.field(U"from").as_string();
1213 std::u32string to = i.field(U"path").as_string();
1214 if(to.substr(0, from.length()) == from) {
1215 if(to.length() == from.length())
1216 continue;
1217 if(to.length() > from.length() && to[from.length()] == U'/')
1218 throw error(ERR_PATCH_ILLEGAL_MOVE);
1220 node tmp = obj.delete_node(from);
1221 obj.insert_node(to, tmp);
1222 } else if(op == U"copy") {
1223 if(i.field_count(U"from") != 1 || i.field(U"from").type() != string)
1224 throw error(ERR_PATCH_BAD);
1225 if(i.field_count(U"path") != 1 || i.field(U"path").type() != string)
1226 throw error(ERR_PATCH_BAD);
1227 const node& tmp = obj.follow(i.field(U"from").as_string());
1228 obj.insert_node(i.field(U"path").as_string(), tmp);
1229 } else
1230 throw error(ERR_PATCH_BAD);
1232 return obj;
1236 node::iterator::iterator() throw() { n = NULL; }
1238 node::iterator::iterator(node& _n) throw(error)
1240 n = &_n;
1241 idx = 0;
1242 if(n->type() == object) {
1243 if(n->xobject.empty())
1244 n = NULL;
1245 else
1246 _key = n->xobject.begin()->first;
1247 } else if(n->type() == array) {
1248 if(n->xarray.empty())
1249 n = NULL;
1250 } else
1251 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1254 std::u32string node::iterator::key() throw(std::bad_alloc, error)
1256 if(!n)
1257 throw error(ERR_ITERATOR_END);
1258 return (n->type() == object) ? _key : U"";
1261 size_t node::iterator::index() throw(error)
1263 if(!n)
1264 throw error(ERR_ITERATOR_END);
1265 return idx;
1268 node& node::iterator::operator*() throw(error)
1270 if(!n)
1271 throw error(ERR_ITERATOR_END);
1272 if(n->type() == object) {
1273 if(!n->xobject.count(_key))
1274 throw error(ERR_ITERATOR_DELETED);
1275 auto& l = n->xobject.find(_key)->second;
1276 size_t j = 0;
1277 for(auto i = l.begin(); i != l.end(); i++, j++) {
1278 if(j == idx)
1279 return *i;
1281 throw error(ERR_ITERATOR_DELETED);
1282 } else {
1283 if(idx >= n->xarray.size())
1284 throw error(ERR_ITERATOR_DELETED);
1285 return *n->xarray_index[idx];
1289 node* node::iterator::operator->() throw(error)
1291 return &**this;
1294 node::iterator node::iterator::operator++(int) throw(error)
1296 iterator tmp = *this;
1297 ++*this;
1298 return tmp;
1301 node::iterator& node::iterator::operator++() throw(error)
1303 if(!n)
1304 throw error(ERR_ITERATOR_END);
1305 idx++;
1306 if(n->type() == object) {
1307 if(!n->xobject.count(_key) || n->xobject.find(_key)->second.size() <= idx) {
1308 auto i = n->xobject.upper_bound(_key);
1309 if(i == n->xobject.end())
1310 n = NULL;
1311 else
1312 _key = i->first;
1313 idx = 0;
1315 } else {
1316 if(idx >= n->xarray_index.size())
1317 n = NULL;
1319 return *this;
1322 bool node::iterator::operator==(const iterator& i) throw()
1324 if(n != i.n)
1325 return false;
1326 if(!n && !i.n)
1327 return true;
1328 return (n == i.n && _key == i._key && idx == i.idx);
1331 bool node::iterator::operator!=(const iterator& i) throw() { return !(*this == i); }
1333 node::const_iterator::const_iterator() throw() { n = NULL; }
1335 node::const_iterator::const_iterator(const node& _n) throw(error)
1337 n = &_n;
1338 idx = 0;
1339 if(n->type() == object) {
1340 if(n->xobject.empty())
1341 n = NULL;
1342 else
1343 _key = n->xobject.begin()->first;
1344 } else if(n->type() == array) {
1345 if(n->xarray.empty())
1346 n = NULL;
1347 } else
1348 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1351 std::u32string node::const_iterator::key() throw(std::bad_alloc, error)
1353 if(!n)
1354 throw error(ERR_ITERATOR_END);
1355 return (n->type() == object) ? _key : U"";
1358 size_t node::const_iterator::index() throw(error)
1360 if(!n)
1361 throw error(ERR_ITERATOR_END);
1362 return idx;
1365 const node& node::const_iterator::operator*() throw(error)
1367 if(!n)
1368 throw error(ERR_ITERATOR_END);
1369 if(n->type() == object) {
1370 if(!n->xobject.count(_key))
1371 throw error(ERR_ITERATOR_DELETED);
1372 auto& l = n->xobject.find(_key)->second;
1373 size_t j = 0;
1374 for(auto i = l.begin(); i != l.end(); i++, j++) {
1375 if(j == idx)
1376 return *i;
1378 throw error(ERR_ITERATOR_DELETED);
1379 } else {
1380 if(idx >= n->xarray.size())
1381 throw error(ERR_ITERATOR_DELETED);
1382 return *n->xarray_index[idx];
1386 const node* node::const_iterator::operator->() throw(error)
1388 return &**this;
1391 node::const_iterator node::const_iterator::operator++(int) throw(error)
1393 const_iterator tmp = *this;
1394 ++*this;
1395 return tmp;
1398 node::const_iterator& node::const_iterator::operator++() throw(error)
1400 if(!n)
1401 throw error(ERR_ITERATOR_END);
1402 idx++;
1403 if(n->type() == object) {
1404 if(!n->xobject.count(_key) || n->xobject.find(_key)->second.size() <= idx) {
1405 auto i = n->xobject.upper_bound(_key);
1406 if(i == n->xobject.end())
1407 n = NULL;
1408 else
1409 _key = i->first;
1410 idx = 0;
1412 } else {
1413 if(idx >= n->xarray_index.size())
1414 n = NULL;
1416 return *this;
1419 bool node::const_iterator::operator==(const const_iterator& i) throw()
1421 if(n != i.n)
1422 return false;
1423 if(!n && !i.n)
1424 return true;
1425 return (n == i.n && _key == i._key && idx == i.idx);
1428 bool node::const_iterator::operator!=(const const_iterator& i) throw() { return !(*this == i); }
1430 void node::erase_index(size_t idx) throw(error)
1432 if(type() == array) {
1433 if(idx >= xarray_index.size())
1434 return;
1435 node* n = xarray_index[idx];
1436 xarray_index.erase(xarray_index.begin() + idx);
1437 for(auto i = xarray.begin(); i != xarray.end(); i++)
1438 if(&*i == n) {
1439 xarray.erase(i);
1440 return;
1442 } else
1443 throw error(ERR_NOT_AN_ARRAY);
1446 void node::erase_field(const std::u32string& fld, size_t idx) throw(error)
1448 if(type() == object) {
1449 if(xobject.count(fld)) {
1450 auto& l = xobject[fld];
1451 size_t j = 0;
1452 for(auto i = l.begin(); i != l.end(); i++, j++)
1453 if(j == idx) {
1454 l.erase(i);
1455 break;
1457 if(l.empty())
1458 xobject.erase(fld);
1460 } else
1461 throw error(ERR_NOT_AN_OBJECT);
1464 void node::erase_field_all(const std::u32string& fld) throw(error)
1466 if(type() == object) {
1467 if(xobject.count(fld))
1468 xobject.erase(fld);
1469 } else
1470 throw error(ERR_NOT_AN_OBJECT);
1473 void node::clear() throw(error)
1475 if(type() == object)
1476 xobject.clear();
1477 else if(type() == array) {
1478 xarray_index.clear();
1479 xobject.clear();
1480 } else
1481 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1484 node::iterator node::erase(node::iterator itr) throw(error)
1486 if(itr.n != this)
1487 throw error(ERR_WRONG_OBJECT);
1488 if(type() == object) {
1489 erase_field(itr._key, itr.idx);
1490 if(!xobject.count(itr._key) || itr.idx >= xobject[itr._key].size())
1491 itr++;
1492 return itr;
1493 } else if(type() == array) {
1494 erase_index(itr.idx);
1495 if(itr.idx >= xarray_index.size())
1496 itr.n = NULL;
1497 return itr;
1498 } else
1499 throw error(ERR_NOT_ARRAY_NOR_OBJECT);
1502 void node::fixup_nodes(const node& _node)
1504 auto i = xarray.begin();
1505 auto j = _node.xarray.begin();
1506 for(; i != xarray.end(); i++, j++) {
1507 for(size_t k = 0; k < _node.xarray_index.size(); k++)
1508 if(_node.xarray_index[k] == &*j)
1509 xarray_index[k] = &*i;
1513 bool node::operator==(const node& n) const
1515 if(this == &n)
1516 return true;
1517 if(vtype != n.vtype)
1518 return false;
1519 switch(vtype) {
1520 case null_tag::id:
1521 return true;
1522 case boolean_tag::id:
1523 return (_boolean == n._boolean);
1524 case number_tag::id:
1525 return (_number == n._number);
1526 case string_tag::id:
1527 return (_string == n._string);
1528 case array_tag::id:
1529 if(xarray_index.size() != n.xarray_index.size())
1530 return false;
1531 for(size_t i = 0; i < xarray_index.size(); i++)
1532 if(*xarray_index[i] != *n.xarray_index[i])
1533 return false;
1534 return true;
1535 case object_tag::id:
1536 for(auto& i : xobject)
1537 if(!n.xobject.count(i.first))
1538 return false;
1539 for(auto& i : n.xobject)
1540 if(!xobject.count(i.first))
1541 return false;
1542 for(auto& i : xobject) {
1543 auto& j = *xobject.find(i.first);
1544 auto& k = *n.xobject.find(i.first);
1545 if(j.second.size() != k.second.size())
1546 return false;
1547 auto j2 = j.second.begin();
1548 auto k2 = k.second.begin();
1549 for(; j2 != j.second.end(); j2++, k2++)
1550 if(*j2 != *k2)
1551 return false;
1553 return true;
1554 default:
1555 throw error(ERR_UNKNOWN_TYPE);
1559 int node::type_of(const std::u32string& pointer) const throw(std::bad_alloc)
1561 try {
1562 const node* n;
1563 if(follow_soft(pointer, n) != ERR_OK)
1564 return none.id;
1565 return n->type();
1566 } catch(std::bad_alloc& e) {
1567 throw;
1568 } catch(std::exception& e) {
1569 //Shouldn't happen.
1570 return none.id;
1574 int node::type_of_indirect(const std::u32string& pointer) const throw(std::bad_alloc)
1576 try {
1577 const node* n;
1578 if(follow_soft(pointer, n) != ERR_OK)
1579 return none.id;
1580 if(n->type() == string)
1581 return type_of(n->as_string());
1582 else
1583 return n->type();
1584 } catch(std::bad_alloc& e) {
1585 throw;
1586 } catch(std::exception& e) {
1587 //Shouldn't happen.
1588 return none.id;
1592 std::u32string node::resolve_indirect(const std::u32string& pointer) const throw(std::bad_alloc)
1594 try {
1595 const node& n = follow(pointer);
1596 if(n.type() == string)
1597 return n.as_string();
1598 else
1599 return pointer;
1600 } catch(std::bad_alloc& e) {
1601 throw;
1602 } catch(std::exception& e) {
1603 return pointer;
1607 pointer::pointer()
1611 pointer::pointer(const std::string& ptr) throw(std::bad_alloc)
1613 _pointer = utf8::to32(ptr);
1616 pointer::pointer(const std::u32string& ptr) throw(std::bad_alloc)
1618 _pointer = ptr;
1621 pointer pointer::index(uint64_t idx) const throw(std::bad_alloc)
1623 if(_pointer.length())
1624 return pointer(_pointer + U"/" + pointer_escape_index(idx));
1625 else
1626 return pointer(pointer_escape_index(idx));
1629 pointer& pointer::index_inplace(uint64_t idx) throw(std::bad_alloc)
1631 if(_pointer.length())
1632 _pointer = _pointer + U"/" + pointer_escape_index(idx);
1633 else
1634 _pointer = pointer_escape_index(idx);
1635 return *this;
1638 pointer pointer::field(const std::u32string& fld) const throw(std::bad_alloc)
1640 if(_pointer.length())
1641 return pointer(_pointer + U"/" + pointer_escape_field(fld));
1642 else
1643 return pointer(pointer_escape_field(fld));
1646 pointer& pointer::field_inplace(const std::u32string& fld) throw(std::bad_alloc)
1648 if(_pointer.length())
1649 _pointer = _pointer + U"/" + pointer_escape_field(fld);
1650 else
1651 _pointer = pointer_escape_field(fld);
1652 return *this;
1655 pointer pointer::remove() const throw(std::bad_alloc)
1657 size_t p = _pointer.find_last_of(U"/");
1658 if(p >= _pointer.length())
1659 return pointer();
1660 else
1661 return pointer(_pointer.substr(0, p));
1664 pointer& pointer::remove_inplace() throw(std::bad_alloc)
1666 size_t p = _pointer.find_last_of(U"/");
1667 if(p >= _pointer.length())
1668 _pointer = U"";
1669 else
1670 _pointer = _pointer.substr(0, p);
1671 return *this;
1674 std::ostream& operator<<(std::ostream& s, const pointer& p)
1676 return s << utf8::to8(p._pointer);
1679 std::basic_ostream<char32_t>& operator<<(std::basic_ostream<char32_t>& s, const pointer& p)
1681 return s << p._pointer;
1684 printer::~printer() throw()
1688 std::string printer::value_val(const std::string& val)
1690 return val;
1693 std::string printer::value_string(const std::u32string& s)
1695 return json_string_escape(s);
1698 std::string printer::array_begin()
1700 return "[";
1703 std::string printer::array_separator()
1705 return ",";
1708 std::string printer::array_end()
1710 return "]";
1713 std::string printer::object_begin()
1715 return "{";
1718 std::string printer::object_key(const std::u32string& s)
1720 return json_string_escape(s) + ":";
1723 std::string printer::object_separator()
1725 return ",";
1728 std::string printer::object_end()
1730 return "}";
1733 printer_indenting::printer_indenting()
1735 depth = 0;
1736 state = S_NORMAL;
1739 printer_indenting::~printer_indenting() throw()
1743 std::string printer_indenting::linestart(size_t _depth)
1745 std::ostringstream s;
1746 s << "\n";
1747 for(size_t i = 0; i < _depth; i++)
1748 s << " ";
1749 return s.str();
1752 std::string printer_indenting::value_val(const std::string& val)
1754 if(depth == 0)
1755 return val + "\n";
1756 switch(state) {
1757 case S_NORMAL:
1758 return val;
1759 default:
1760 //According to JSON rules, value is not allowed immediately after end of array/object, so
1761 //states S_END and S_START_END really have comma right before.
1762 state = S_NORMAL;
1763 return linestart(depth) + val;
1767 std::string printer_indenting::value_string(const std::u32string& s)
1769 if(depth == 0)
1770 return json_string_escape(s) + "\n";
1771 switch(state) {
1772 case S_NORMAL:
1773 return json_string_escape(s);
1774 default:
1775 //According to JSON rules, value is not allowed immediately after end of array/object, so
1776 //states S_END and S_START_END really have comma right before.
1777 state = S_NORMAL;
1778 return linestart(depth) + json_string_escape(s);
1782 std::string printer_indenting::array_begin()
1784 switch(state) {
1785 case S_NORMAL:
1786 //This can only happen in beginning of expression or after key.
1787 state = S_START;
1788 depth++;
1789 return "[";
1790 case S_END:
1791 //This is really after ], or },
1792 state = S_START;
1793 depth++;
1794 return "[";
1795 case S_COMMA:
1796 case S_START:
1797 case S_START_END:
1798 //S_START_END really has comma right before due to JSON rules.
1799 state = S_START;
1800 return linestart(depth++) + "[";
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_NORMAL:
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");
1836 std::string printer_indenting::object_begin()
1838 switch(state) {
1839 case S_NORMAL:
1840 //This can only happen in beginning of expression or after key.
1841 state = S_START;
1842 depth++;
1843 return "{";
1844 case S_END:
1845 //This is really ], or },
1846 state = S_START;
1847 depth++;
1848 return "{";
1849 case S_COMMA:
1850 case S_START:
1851 case S_START_END:
1852 //S_START_END really has comma right before due to JSON rules.
1853 state = S_START;
1854 return linestart(depth++) + "{";
1858 std::string printer_indenting::object_key(const std::u32string& s)
1860 switch(state) {
1861 case S_START:
1862 case S_COMMA:
1863 case S_END:
1864 case S_START_END:
1865 state = S_NORMAL;
1866 return linestart(depth) + json_string_escape(s) + ":";
1867 default:
1868 //Can't actually happe
1869 state = S_NORMAL;
1870 return json_string_escape(s) + ":";
1874 std::string printer_indenting::object_separator()
1876 switch(state) {
1877 case S_END:
1878 case S_START_END:
1879 //These states don't transition to comma.
1880 return ",";
1881 default:
1882 state = S_COMMA;
1883 return ",";
1887 std::string printer_indenting::object_end()
1889 switch(state) {
1890 case S_NORMAL:
1891 case S_END:
1892 case S_COMMA:
1893 case S_START_END:
1894 //S_END or S_START_END is after ']' or '}'.
1895 //S_COMMA can't actually happen per JSON rules.
1896 state = S_END;
1897 --depth;
1898 return linestart(depth) + "}" + (depth ? "" : "\n");
1899 case S_START:
1900 state = S_START_END;
1901 --depth;
1902 return "}";
1908 bool operator==(const int& n, const JSON::number_tag& v) { return v == n; }
1909 bool operator==(const int& n, const JSON::string_tag& v) { return v == n; }
1910 bool operator==(const int& n, const JSON::boolean_tag& v) { return v == n; }
1911 bool operator==(const int& n, const JSON::array_tag& v) { return v == n; }
1912 bool operator==(const int& n, const JSON::object_tag& v) { return v == n; }
1913 bool operator==(const int& n, const JSON::null_tag& v) { return v == n; }
1914 bool operator!=(const int& n, const JSON::number_tag& v) { return v != n; }
1915 bool operator!=(const int& n, const JSON::string_tag& v) { return v != n; }
1916 bool operator!=(const int& n, const JSON::boolean_tag& v) { return v != n; }
1917 bool operator!=(const int& n, const JSON::array_tag& v) { return v != n; }
1918 bool operator!=(const int& n, const JSON::object_tag& v) { return v != n; }
1919 bool operator!=(const int& n, const JSON::null_tag& v) { return v != n; }