9 const char* error_desc
[] = {
16 "Not array nor object",
20 "Trailing pointer escape character",
21 "Invalid pointer escape",
22 "Bad hexadecimal character",
23 "Invalid surrogate escape",
24 "Invalid escape sequence",
27 "Garbage after end of JSON",
31 "Unexpected right brace",
32 "Unexpected right braket",
33 "Invalid number syntax",
34 "Expected string as object key",
40 "Iterator past the end",
41 "Iterator points to deleted object",
42 "Iterator points to wrong object",
43 "Illegal character escaped",
44 "Control character in string",
45 "Invalid value subtype",
47 "JSON patch test failed",
48 "JSON patch illegal move",
51 const char* state_desc
[] = {
64 const char* asciinames
[] = {
65 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
66 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
69 bool parse_size_t(const std::u32string
& s
, size_t& x
)
72 for(size_t i
= 0; i
< s
.length(); i
++) {
73 if(s
[i
] < 48 || s
[i
] > 57)
75 if((std::numeric_limits
<size_t>::max() - (size_t)(s
[i
] - 48)) / 10 < x
)
77 x
= 10 * x
+ (s
[i
] - 48);
82 std::pair
<size_t, size_t> error::get_position_lc(const std::string
& doc
, size_t pos
)
86 for(size_t i
= 0; i
< pos
; i
++) {
87 if(doc
[i
] == 13 || (doc
[i
] == 10 && !last_cr
)) {
90 last_cr
= (doc
[i
] == 13);
93 if(last_cr
&& doc
[i
] == 10) {
99 return std::make_pair(r
, c
);
102 const char* error::what() const throw()
104 if(state
== PARSE_NOT_PARSING
)
105 return error_desc
[code
];
107 sprintf(buffer
, "%s (while expecting %s) at byte %llu", error_desc
[code
], state_desc
[state
],
108 (unsigned long long)position
);
113 std::string
error::extended_error(const std::string
& doc
)
115 if(state
== PARSE_NOT_PARSING
)
116 return error_desc
[code
];
117 std::ostringstream s
;
118 size_t pos
= position
;
119 while(pos
< doc
.length() && (doc
[pos
] == '\t' || doc
[pos
] == '\v' || doc
[pos
] == '\r' || doc
[pos
] == '\n' ||
122 auto p2
= get_position_lc(doc
, pos
);
123 s
<< error_desc
[code
] << " (while expecting " << state_desc
[state
] << ") at ";
124 if(position
== doc
.length())
127 std::ostringstream sample
;
129 for(size_t i
= 0; i
< 32; i
++) {
130 if(p
>= doc
.length())
133 sample
<< "<" << asciinames
[doc
[p
++]] << ">";
134 } else if(doc
[p
] < 127)
136 else if(doc
[p
] < 128)
138 else if(doc
[p
] < 192)
139 sample
<< "<" << (int)doc
[p
++] << ">";
140 else if(doc
[p
] < 224) {
143 } else if(doc
[p
] < 240) {
147 } else if(doc
[p
] < 248) {
153 sample
<< "<" << (int)doc
[p
++] << ">";
155 s
<< "line " << p2
.first
<< " byte " << p2
.second
<< " [near: '" << sample
.str() << "']";
160 node
number_tag::operator()(double v
) const { return node(*this, v
); }
161 node
number_tag::operator()(uint64_t v
) const { return node(*this, v
); }
162 node
number_tag::operator()(int64_t v
) const { return node(*this, v
); }
163 node
string_tag::operator()(const std::string
& s
) const { return node(*this, s
); }
164 node
string_tag::operator()(const std::u32string
& s
) const { return node(*this, s
); }
165 node
boolean_tag::operator()(bool v
) { return node(*this, v
); }
166 node
array_tag::operator()() const { return node(*this); }
167 node
object_tag::operator()() const { return node(*this); }
168 node
null_tag::operator()() const { return node(*this); }
170 node
i(int64_t n
) { return number(n
); }
171 node
u(uint64_t n
) { return number(n
); }
172 node
f(double n
) { return number(n
); }
173 node
b(bool bl
) { return boolean(bl
); }
174 node
s(const std::string
& st
) { return string(st
); }
175 node
s(const std::u32string
& st
) { return string(st
); }
176 node
n() { return null(); }
186 template<> void node::number_holder::from(double val
) { sub
= 0; n
.n0
= val
; }
187 template<> void node::number_holder::from(uint64_t val
) { sub
= 1; n
.n1
= val
; }
188 template<> void node::number_holder::from(int64_t val
) { sub
= 2; n
.n2
= val
; }
192 unsigned numchar(char c
)
196 case '1': case '2': case '3': case '4': case '5':
197 case '6': case '7': case '8': case '9': return 1;
206 uint32_t numdfa
[] = {
207 0x0F1FFF32, //0: STATE_INITIAL
208 0x0FFFFF32, //1: STATE_AFTER_MINUS
209 0x1FFF64FF, //2: STATE_INT_Z
210 0x1FFF6433, //3: STATE_INT_NZ
211 0x0FFFFF55, //4: STATE_DECIMAL
212 0x1FFF6F55, //5: STATE_DECIMAL_N
213 0x0F77FF88, //6: STATE_EXP
214 0x0FFFFF88, //7: STATE_EXP_SIGN
215 0x1FFFFF88, //8: STATE_EXP_N
219 node::number_holder::number_holder(const std::string
& expr
, size_t& ptr
, size_t len
)
221 //-?(0|1-9[0-9]+)(.[0-9]+)?([eE][+-]?[0-9]+)?
227 unsigned c
= numchar(expr
[tmp
]);
228 unsigned ns
= (numdfa
[state
] >> (4 * c
)) & 0xF;
235 if(!(numdfa
[state
] >> 28))
237 x
= expr
.substr(ptr
, tmp
- ptr
);
240 if(regex_match("[0-9]+", x
)) {
241 n
.n1
= parse_value
<uint64_t>(x
);
247 if(regex_match("[+-]?[0-9]+", x
)) {
248 n
.n2
= parse_value
<int64_t>(x
);
254 n
.n0
= parse_value
<double>(x
);
259 throw error(ERR_INVALID_NUMBER
, PARSE_NUMBER
, tmp2
);
263 void node::number_holder::write(std::ostream
& s
) const
266 case 0: s
<< n
.n0
; break;
267 case 1: s
<< n
.n1
; break;
268 case 2: s
<< n
.n2
; break;
272 template<typename T
> bool node::number_holder::cmp(const T
& num
) const
275 case 0: return n
.n0
== num
;
276 case 1: return n
.n1
== num
;
277 case 2: return n
.n2
== num
;
279 throw error(ERR_UNKNOWN_SUBTYPE
);
282 template<> bool node::number_holder::cmp(const int64_t& num
) const
285 case 0: return n
.n0
== num
;
286 case 1: return num
>= 0 && n
.n1
== static_cast<uint64_t>(num
);
287 case 2: return n
.n2
== num
;
289 throw error(ERR_UNKNOWN_SUBTYPE
);
292 template<> bool node::number_holder::cmp(const uint64_t& num
) const
295 case 0: return n
.n0
== num
;
296 case 1: return n
.n1
== num
;
297 case 2: return n
.n2
>= 0 && static_cast<uint64_t>(n
.n2
) == num
;
299 throw error(ERR_UNKNOWN_SUBTYPE
);
303 bool node::number_holder::operator==(const number_holder
& h
) const
306 case 0: return h
.cmp(n
.n0
);
307 case 1: return h
.cmp(n
.n1
);
308 case 2: return h
.cmp(n
.n2
);
310 throw error(ERR_UNKNOWN_SUBTYPE
);
313 node::node() throw() : node(null
) {}
314 node::node(null_tag
) throw() { vtype
= null
; }
315 node::node(boolean_tag
, bool b
) throw() { vtype
= boolean
; _boolean
= b
; }
316 node::node(string_tag
, const std::u32string
& str
) throw(std::bad_alloc
) { vtype
= string
; _string
= str
; }
317 node::node(string_tag
, const std::string
& str
) throw(std::bad_alloc
) { vtype
= string
; _string
= to_u32string(str
); }
318 node::node(number_tag
, double n
) throw() { vtype
= number
; _number
.from
<double>(n
); }
319 node::node(number_tag
, int64_t n
) throw() { vtype
= number
; _number
.from
<int64_t>(n
); }
320 node::node(number_tag
, uint64_t n
) throw() { vtype
= number
; _number
.from
<uint64_t>(n
); }
321 node::node(array_tag
) throw() { vtype
= array
; }
322 node::node(object_tag
) throw() { vtype
= object
; }
323 int node::type() const throw() { return vtype
; }
325 node
& node::set(null_tag
) throw() { set_helper
<uint64_t>(0); vtype
= null
; return *this; }
326 node
& node::set(boolean_tag
, bool n
) throw() { set_helper
<uint64_t>(0); vtype
= boolean
; _boolean
= n
; return *this; }
327 node
& node::set(number_tag
, double n
) throw() { set_helper
<double>(n
); return *this; }
328 node
& node::set(number_tag
, int64_t n
) throw() { set_helper
<int64_t>(n
); return *this; }
329 node
& node::set(number_tag
, uint64_t n
) throw() { set_helper
<int64_t>(n
); return *this; }
331 node
& node::set(string_tag
, const std::u32string
& key
) throw(std::bad_alloc
)
333 std::u32string tmp
= key
;
334 std::swap(_string
, tmp
);
341 double node::as_double() const throw(error
)
343 return get_number_helper
<double>();
346 int64_t node::as_int() const throw(error
)
348 return get_number_helper
<int64_t>();
351 uint64_t node::as_uint() const throw(error
)
353 return get_number_helper
<uint64_t>();
356 const std::u32string
& node::as_string() const throw(std::bad_alloc
, error
)
359 throw error(ERR_NOT_A_STRING
);
363 bool node::as_bool() const throw(error
)
366 throw error(ERR_NOT_A_BOOLEAN
);
370 size_t node::index_count() const throw(error
)
373 throw error(ERR_NOT_AN_ARRAY
);
374 return xarray
.size();
377 errorcode
node::index_soft(size_t index
, const node
*& out
) const throw()
380 return ERR_NOT_AN_ARRAY
;
381 if(index
>= xarray_index
.size())
382 return ERR_INDEX_INVALID
;
383 out
= xarray_index
[index
];
387 errorcode
node::index_soft(size_t index
, node
*& out
) throw()
390 return ERR_NOT_AN_ARRAY
;
391 if(index
>= xarray_index
.size())
392 return ERR_INDEX_INVALID
;
393 out
= xarray_index
[index
];
397 size_t node::field_count(const std::u32string
& key
) const throw(error
)
400 throw error(ERR_NOT_AN_OBJECT
);
401 if(!xobject
.count(key
))
403 return xobject
.find(key
)->second
.size();
406 bool node::field_exists(const std::u32string
& key
) const throw(error
)
408 return (field_count(key
) > 0);
411 errorcode
node::field_soft(const std::u32string
& key
, size_t subindex
, const node
*& out
) const throw()
414 return ERR_NOT_AN_OBJECT
;
415 if(!xobject
.count(key
))
416 return ERR_KEY_INVALID
;
417 const std::list
<node
>& l
= xobject
.find(key
)->second
;
419 for(auto i
= l
.begin(); i
!= l
.end(); i
++, j
++) {
425 return ERR_INSTANCE_INVALID
;
428 errorcode
node::field_soft(const std::u32string
& key
, size_t subindex
, node
*& out
) throw()
431 return ERR_NOT_AN_OBJECT
;
432 if(!xobject
.count(key
))
433 return ERR_KEY_INVALID
;
434 std::list
<node
>& l
= xobject
.find(key
)->second
;
436 for(auto i
= l
.begin(); i
!= l
.end(); i
++, j
++) {
442 return ERR_INSTANCE_INVALID
;
445 node::node(const node
& _node
) throw(std::bad_alloc
)
447 std::u32string tmp1
= _node
._string
;
448 std::list
<node
> tmp2
= _node
.xarray
;
449 std::map
<std::u32string
, std::list
<node
>> tmp3
= _node
.xobject
;
450 std::vector
<node
*> tmp4
= _node
.xarray_index
;
453 _number
= _node
._number
;
454 _boolean
= _node
._boolean
;
455 _string
= _node
._string
;
456 xarray
= _node
.xarray
;
457 xobject
= _node
.xobject
;
458 xarray_index
= _node
.xarray_index
;
462 node
& node::operator=(const node
& _node
) throw(std::bad_alloc
)
466 std::u32string tmp1
= _node
._string
;
467 std::list
<node
> tmp2
= _node
.xarray
;
468 std::map
<std::u32string
, std::list
<node
>> tmp3
= _node
.xobject
;
469 std::vector
<node
*> tmp4
= _node
.xarray_index
;
472 _number
= _node
._number
;
473 _boolean
= _node
._boolean
;
474 std::swap(_string
, tmp1
);
475 std::swap(xarray
, tmp2
);
476 std::swap(xobject
, tmp3
);
477 std::swap(xarray_index
, tmp4
);
482 node
& node::append(const node
& _node
) throw(std::bad_alloc
, error
)
485 throw error(ERR_NOT_AN_ARRAY
);
488 xarray
.push_back(_node
);
490 node
* ptr
= &*xarray
.rbegin();
491 xarray_index
.push_back(ptr
);
493 } catch(std::bad_alloc
& e
) {
500 node
& node::insert(const std::u32string
& key
, const node
& _node
) throw(std::bad_alloc
, error
)
503 throw error(ERR_NOT_AN_OBJECT
);
505 xobject
[key
].push_back(_node
);
506 return *xobject
[key
].rbegin();
508 if(xobject
.count(key
) && xobject
[key
].empty())
516 errorcode
jsonptr_unescape_soft(const std::u32string
& c
, size_t start
, size_t end
, std::u32string
& _out
)
518 std::basic_ostringstream
<char32_t
> out
;
519 for(size_t ptr
= start
; ptr
< end
; ptr
++) {
522 return ERR_POINTER_TRAILING_ESCAPE
;
526 else if(c
[ptr
] == '1')
529 return ERR_POINTER_INVALID_ESCAPE
;
537 std::u32string
jsonptr_unescape(const std::u32string
& c
, size_t start
, size_t end
)
540 auto e
= jsonptr_unescape_soft(c
, start
, end
, o
);
541 if(e
!= ERR_OK
) throw error(e
);
547 errorcode
node::follow_soft(const std::u32string
& pointer
, const node
*& current
) const throw(std::bad_alloc
)
552 while(ptr
< pointer
.length()) {
553 size_t p
= pointer
.find_first_of(U
"/", ptr
);
554 if(p
> pointer
.length())
555 p
= pointer
.length();
557 auto e
= jsonptr_unescape_soft(pointer
, ptr
, p
, c
);
558 if(e
!= ERR_OK
) return e
;
559 if(current
->vtype
== array
) {
561 return ERR_POINTER_BAD_APPEND
;
563 if(!parse_size_t(c
, idx
))
564 return ERR_POINTER_BAD_INDEX
;
565 e
= current
->index_soft(idx
, current
);
566 if(e
!= ERR_OK
) return e
;
567 } else if(current
->vtype
== object
) {
568 e
= current
->field_soft(c
, 0, current
);
569 if(e
!= ERR_OK
) return e
;
571 return ERR_NOT_ARRAY_NOR_OBJECT
;
577 errorcode
node::follow_soft(const std::u32string
& pointer
, node
*& current
) throw(std::bad_alloc
)
582 while(ptr
< pointer
.length()) {
583 size_t p
= pointer
.find_first_of(U
"/", ptr
);
584 if(p
> pointer
.length())
585 p
= pointer
.length();
587 auto e
= jsonptr_unescape_soft(pointer
, ptr
, p
, c
);
588 if(e
!= ERR_OK
) return e
;
589 if(current
->vtype
== array
) {
591 return ERR_POINTER_BAD_APPEND
;
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
;
601 return ERR_NOT_ARRAY_NOR_OBJECT
;
611 enum ttype
{ TSTRING
, TNUMBER
, TOBJECT
, TARRAY
, TINVALID
, TCOMMA
, TOBJECT_END
, TARRAY_END
, TCOLON
,
612 TEOF
, TTRUE
, TFALSE
, TNULL
};
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
)
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
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
; }
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
;
675 for(i
= ptr
; i
<= len
; i
++) {
678 ch
= (unsigned char)doc
[i
];
679 int32_t uch
= utf8_parse_byte(ch
, ustate
);
682 //Okay, have Unicode codepoint decoded.
688 throw error(ERR_CONTROL_CHARACTER
, PARSE_STRING_BODY
, lc
);
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;
712 throw error(ERR_INVALID_ESCAPE
, PARSE_STRING_ESCAPE
, lc
);
715 case 2: case 3: case 4: case 8: case 9: case 10:
716 extra
= (extra
<< 4) | parse_hex(uch
, PARSE_STRING_ESCAPE
, lc
);
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)
725 else if((extra
& 0xFFFE) == 0xFFFE)
726 throw error(ERR_ILLEGAL_CHARACTER
, PARSE_STRING_ESCAPE
, lc
);
735 throw error(ERR_INVALID_SURROGATE
, PARSE_STRING_ESCAPE
, lc
);
740 throw error(ERR_INVALID_SURROGATE
, PARSE_STRING_ESCAPE
, lc
);
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
);
756 throw error(ERR_TRUNCATED_STRING
, estate
? PARSE_STRING_ESCAPE
: PARSE_STRING_BODY
, len
);
761 void read_string(std::u32string
& target
, const std::string
& doc
, size_t& ptr
, size_t len
)
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'))
774 return json_token(json_token::TEOF
);
775 if(doc
[ptr
] == '{') {
777 return json_token(json_token::TOBJECT
);
779 if(doc
[ptr
] == '}') {
781 return json_token(json_token::TOBJECT_END
);
783 if(doc
[ptr
] == '[') {
785 return json_token(json_token::TARRAY
);
787 if(doc
[ptr
] == ']') {
789 return json_token(json_token::TARRAY_END
);
791 if(doc
[ptr
] == ',') {
793 return json_token(json_token::TCOMMA
);
795 if(doc
[ptr
] == ':') {
797 return json_token(json_token::TCOLON
);
799 if(doc
[ptr
] == '\"') {
802 return json_token(json_token::TSTRING
);
804 if(doc
[ptr
] == '-' || (doc
[ptr
] >= '0' && doc
[ptr
] <= '9')) {
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
);
831 return json_token(json_token::TINVALID
);
835 const char* hexes
= "0123456789abcdef";
837 std::string
json_string_escape(const std::u32string
& c
)
839 std::ostringstream out
;
841 size_t len
= c
.length();
842 for(size_t i
= 0; i
< len
; i
++) {
843 if(c
[i
] == '\b') out
<< "\\b";
844 else if(c
[i
] == '\n') out
<< "\\n";
845 else if(c
[i
] == '\r') out
<< "\\r";
846 else if(c
[i
] == '\t') out
<< "\\t";
847 else if(c
[i
] == '\f') out
<< "\\f";
848 else if((c
[i
] & 0xFFFFFFE0) == 0)
849 out
<< "\\u00" << hexes
[c
[i
] >> 4] << hexes
[c
[i
] % 16];
850 else if(c
[i
] == U
'\\')
852 else if(c
[i
] == U
'\"')
855 out
<< (unsigned char)c
[i
];
856 else if(c
[i
] < 0x800) {
857 out
<< (unsigned char)(0xC0 + (c
[i
] >> 6));
858 out
<< (unsigned char)(0x80 + (c
[i
] & 0x3F));
859 } else if(c
[i
] < 0x10000) {
860 out
<< (unsigned char)(0xE0 + (c
[i
] >> 12));
861 out
<< (unsigned char)(0x80 + ((c
[i
] >> 6) & 0x3F));
862 out
<< (unsigned char)(0x80 + (c
[i
] & 0x3F));
863 } else if(c
[i
] < 0x10FFFF) {
864 out
<< (unsigned char)(0xF0 + (c
[i
] >> 18));
865 out
<< (unsigned char)(0x80 + ((c
[i
] >> 12) & 0x3F));
866 out
<< (unsigned char)(0x80 + ((c
[i
] >> 6) & 0x3F));
867 out
<< (unsigned char)(0x80 + (c
[i
] & 0x3F));
874 void skip_ws(const std::string
& doc
, size_t& ptr
, size_t len
) {
875 while(ptr
< len
&& (doc
[ptr
] == ' ' || doc
[ptr
] == '\t' || doc
[ptr
] == '\v' || doc
[ptr
] == '\r' ||
881 std::u32string
pointer_escape_field(const std::u32string
& orig
) throw(std::bad_alloc
)
883 std::basic_stringstream
<char32_t
> x
;
895 std::u32string
pointer_escape_index(uint64_t idx
) throw(std::bad_alloc
)
897 std::string orig
= (stringfmt() << idx
).str();
898 std::basic_ostringstream
<char32_t
> x
;
905 std::string
node::serialize() const throw(std::bad_alloc
, error
)
907 std::ostringstream out
;
910 case null_tag::id
: return "null";
911 case boolean_tag::id
: return _boolean
? "true" : "false";
916 return json_string_escape(_string
);
919 for(auto& i
: xarray_index
) {
920 if(!first
) out
<< ",";
921 out
<< i
->serialize();
928 for(auto& i
: xobject
) {
929 for(auto& j
: i
.second
) {
930 if(!first
) out
<< ",";
931 out
<< json_string_escape(i
.first
) << ":" << j
.serialize();
938 throw error(ERR_UNKNOWN_TYPE
);
941 node::node(const std::string
& doc
) throw(std::bad_alloc
, error
)
944 ctor(doc
, tmp
, doc
.length());
945 skip_ws(doc
, tmp
, doc
.length());
946 if(tmp
< doc
.length())
947 throw error(ERR_GARBAGE_AFTER_END
, PARSE_END_OF_DOCUMENT
, tmp
);
950 void node::ctor(const std::string
& doc
, size_t& ptr
, size_t len
) throw(std::bad_alloc
, error
)
954 json_token t
= parse_token(doc
, ptr
, len
);
958 case json_token::TTRUE
:
961 case json_token::TFALSE
:
964 case json_token::TNULL
:
967 case json_token::TEOF
:
968 throw error(ERR_TRUNCATED_JSON
, PARSE_VALUE_START
, ptr
);
969 case json_token::TCOMMA
:
970 throw error(ERR_UNEXPECTED_COMMA
, PARSE_VALUE_START
, tmp3
);
971 case json_token::TCOLON
:
972 throw error(ERR_UNEXPECTED_COLON
, PARSE_VALUE_START
, tmp3
);
973 case json_token::TARRAY_END
:
974 throw error(ERR_UNEXPECTED_RIGHT_BRACKET
, PARSE_VALUE_START
, tmp3
);
975 case json_token::TOBJECT_END
:
976 throw error(ERR_UNEXPECTED_RIGHT_BRACE
, PARSE_VALUE_START
, tmp3
);
977 case json_token::TSTRING
:
979 read_string(_string
, doc
, ptr
, len
);
981 case json_token::TNUMBER
:
983 _number
= number_holder(doc
, ptr
, len
);
985 case json_token::TOBJECT
:
987 if(parse_token(doc
, tmp
, len
).type
== json_token::TOBJECT_END
) {
993 json_token t2
= parse_token(doc
, ptr
, len
);
994 if(t2
.type
== json_token::TEOF
)
995 throw error(ERR_TRUNCATED_JSON
, PARSE_OBJECT_NAME
, ptr
);
996 if(t2
.type
!= json_token::TSTRING
)
997 throw error(ERR_EXPECTED_STRING_KEY
, PARSE_OBJECT_NAME
, tmp3
);
999 read_string(key
, doc
, ptr
, len
);
1001 t2
= parse_token(doc
, ptr
, len
);
1002 if(t2
.type
== json_token::TEOF
)
1003 throw error(ERR_TRUNCATED_JSON
, PARSE_OBJECT_COLON
, ptr
);
1004 if(t2
.type
!= json_token::TCOLON
)
1005 throw error(ERR_EXPECTED_COLON
, PARSE_OBJECT_COLON
, tmp3
);
1006 insert(key
, node(doc
, ptr
, len
));
1008 t2
= parse_token(doc
, ptr
, len
);
1009 if(t2
.type
== json_token::TEOF
)
1010 throw error(ERR_TRUNCATED_JSON
, PARSE_OBJECT_AFTER_VALUE
, ptr
);
1011 if(t2
.type
== json_token::TOBJECT_END
)
1013 if(t2
.type
!= json_token::TCOMMA
)
1014 throw error(ERR_EXPECTED_COMMA
, PARSE_OBJECT_AFTER_VALUE
, tmp3
);
1017 case json_token::TARRAY
:
1019 if(parse_token(doc
, tmp
, len
).type
== json_token::TARRAY_END
) {
1024 append(node(doc
, ptr
, len
));
1026 json_token t2
= parse_token(doc
, ptr
, len
);
1027 if(t2
.type
== json_token::TEOF
)
1028 throw error(ERR_TRUNCATED_JSON
, PARSE_ARRAY_AFTER_VALUE
, ptr
);
1029 if(t2
.type
== json_token::TARRAY_END
)
1031 if(t2
.type
!= json_token::TCOMMA
)
1032 throw error(ERR_EXPECTED_COMMA
, PARSE_ARRAY_AFTER_VALUE
, tmp3
);
1035 case json_token::TINVALID
:
1036 throw error(ERR_UNKNOWN_CHARACTER
, PARSE_VALUE_START
, tmp3
);
1040 node::node(const std::string
& doc
, size_t& ptr
, size_t len
) throw(std::bad_alloc
, error
)
1042 ctor(doc
, ptr
, len
);
1045 node
& node::operator[](const std::u32string
& pointer
) throw(std::bad_alloc
, error
)
1047 node
* current
= this;
1049 while(ptr
< pointer
.length()) {
1050 size_t p
= pointer
.find_first_of(U
"/", ptr
);
1051 if(p
> pointer
.length())
1052 p
= pointer
.length();
1053 std::u32string c
= jsonptr_unescape(pointer
, ptr
, p
);
1054 if(current
->vtype
== array
) {
1057 if(p
< pointer
.length())
1058 throw error(ERR_POINTER_BAD_APPEND
);
1059 return current
->append(n());
1062 if(!parse_size_t(c
, idx
))
1063 throw error(ERR_POINTER_BAD_INDEX
);
1064 if(idx
> current
->xarray
.size())
1065 throw error(ERR_POINTER_BAD_APPEND
);
1066 else if(idx
== current
->xarray
.size())
1067 return current
->append(n());
1068 current
= ¤t
->index(idx
);
1069 } else if(current
->vtype
== object
) {
1070 if(!current
->field_exists(c
) && p
== pointer
.length())
1071 return current
->insert(c
, n());
1072 current
= ¤t
->field(c
);
1074 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1080 node
& node::insert_node(const std::u32string
& pointer
, const node
& nwn
) throw(std::bad_alloc
, error
)
1082 size_t s
= pointer
.find_last_of(U
"/");
1084 std::u32string rest
;
1085 size_t ptrlen
= pointer
.length();
1087 base
= &follow(pointer
.substr(0, s
));
1088 rest
= jsonptr_unescape(pointer
, s
+ 1, ptrlen
);
1091 rest
= jsonptr_unescape(pointer
, 0, ptrlen
);
1093 if(base
->type() == array
) {
1095 return base
->append(nwn
);
1097 if(!parse_size_t(rest
, idx
))
1098 throw error(ERR_POINTER_BAD_INDEX
);
1099 if(idx
> base
->xarray
.size())
1100 throw error(ERR_POINTER_BAD_APPEND
);
1101 else if(idx
== base
->xarray
.size())
1102 return base
->append(nwn
);
1105 base
->xarray
.push_back(nwn
);
1107 node
* ptr
= &*base
->xarray
.rbegin();
1108 base
->xarray_index
.insert(base
->xarray_index
.begin() + idx
, ptr
);
1110 } catch(std::bad_alloc
& e
) {
1112 base
->xarray
.pop_back();
1115 } else if(base
->type() == object
) {
1116 if(xobject
.count(rest
))
1117 return *base
->xobject
[rest
].begin() = nwn
;
1120 base
->xobject
[rest
].push_back(nwn
);
1121 return *base
->xobject
[rest
].begin();
1123 base
->xobject
.erase(rest
);
1128 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1131 node
node::delete_node(const std::u32string
& pointer
) throw(std::bad_alloc
, error
)
1133 size_t s
= pointer
.find_last_of(U
"/");
1135 std::u32string rest
;
1136 size_t ptrlen
= pointer
.length();
1138 base
= &follow(pointer
.substr(0, s
));
1139 rest
= jsonptr_unescape(pointer
, s
+ 1, ptrlen
);
1142 rest
= jsonptr_unescape(pointer
, 0, ptrlen
);
1144 if(base
->type() == array
) {
1146 throw error(ERR_POINTER_BAD_APPEND
);
1148 if(!parse_size_t(rest
, idx
))
1149 throw error(ERR_POINTER_BAD_INDEX
);
1150 if(idx
>= base
->xarray
.size())
1151 throw error(ERR_INDEX_INVALID
);
1152 node
* dptr
= base
->xarray_index
[idx
];
1154 for(auto i
= base
->xarray
.begin(); i
!= base
->xarray
.end(); ++i
)
1156 base
->xarray
.erase(i
);
1159 base
->xarray_index
.erase(base
->xarray_index
.begin() + idx
);
1161 } else if(base
->type() == object
) {
1162 if(xobject
.count(rest
)) {
1163 node tmp
= *base
->xobject
[rest
].begin();
1164 base
->xobject
.erase(rest
);
1167 throw error(ERR_KEY_INVALID
);
1169 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1172 node
node::patch(const node
& patch
) const throw(std::bad_alloc
, error
)
1175 if(patch
.type() != array
)
1176 throw error(ERR_PATCH_BAD
);
1177 for(auto& i
: patch
) {
1178 if(i
.type() != object
|| i
.field_count(U
"op") != 1 || i
.field(U
"op").type() != string
)
1179 throw error(ERR_PATCH_BAD
);
1180 std::u32string op
= i
.field(U
"op").as_string();
1182 if(i
.field_count(U
"path") != 1 || i
.field(U
"path").type() != string
)
1183 throw error(ERR_PATCH_BAD
);
1184 if(i
.field_count(U
"value") != 1)
1185 throw error(ERR_PATCH_BAD
);
1186 if(obj
.follow(i
.field(U
"path").as_string()) != i
.field("value"))
1187 throw error(ERR_PATCH_TEST_FAILED
);
1188 } else if(op
== U
"remove") {
1189 if(i
.field_count(U
"path") != 1 || i
.field(U
"path").type() != string
)
1190 throw error(ERR_PATCH_BAD
);
1191 obj
.delete_node(i
.field(U
"path").as_string());
1192 } else if(op
== U
"add") {
1193 if(i
.field_count(U
"path") != 1 || i
.field(U
"path").type() != string
)
1194 throw error(ERR_PATCH_BAD
);
1195 if(i
.field_count(U
"value") != 1)
1196 throw error(ERR_PATCH_BAD
);
1197 obj
.insert_node(i
.field(U
"path").as_string(), i
.field("value"));
1198 } else if(op
== U
"replace") {
1199 if(i
.field_count(U
"path") != 1 || i
.field(U
"path").type() != string
)
1200 throw error(ERR_PATCH_BAD
);
1201 if(i
.field_count(U
"value") != 1)
1202 throw error(ERR_PATCH_BAD
);
1203 obj
.delete_node(i
.field(U
"path").as_string());
1204 obj
.insert_node(i
.field(U
"path").as_string(), i
.field("value"));
1205 } else if(op
== U
"move") {
1206 if(i
.field_count(U
"from") != 1 || i
.field(U
"from").type() != string
)
1207 throw error(ERR_PATCH_BAD
);
1208 if(i
.field_count(U
"path") != 1 || i
.field(U
"path").type() != string
)
1209 throw error(ERR_PATCH_BAD
);
1210 std::u32string from
= i
.field(U
"from").as_string();
1211 std::u32string to
= i
.field(U
"path").as_string();
1212 if(to
.substr(0, from
.length()) == from
) {
1213 if(to
.length() == from
.length())
1215 if(to
.length() > from
.length() && to
[from
.length()] == U
'/')
1216 throw error(ERR_PATCH_ILLEGAL_MOVE
);
1218 node tmp
= obj
.delete_node(from
);
1219 obj
.insert_node(to
, tmp
);
1220 } else if(op
== U
"copy") {
1221 if(i
.field_count(U
"from") != 1 || i
.field(U
"from").type() != string
)
1222 throw error(ERR_PATCH_BAD
);
1223 if(i
.field_count(U
"path") != 1 || i
.field(U
"path").type() != string
)
1224 throw error(ERR_PATCH_BAD
);
1225 const node
& tmp
= obj
.follow(i
.field(U
"from").as_string());
1226 obj
.insert_node(i
.field(U
"path").as_string(), tmp
);
1228 throw error(ERR_PATCH_BAD
);
1234 node::iterator::iterator() throw() { n
= NULL
; }
1236 node::iterator::iterator(node
& _n
) throw(error
)
1240 if(n
->type() == object
) {
1241 if(n
->xobject
.empty())
1244 _key
= n
->xobject
.begin()->first
;
1245 } else if(n
->type() == array
) {
1246 if(n
->xarray
.empty())
1249 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1252 std::u32string
node::iterator::key() throw(std::bad_alloc
, error
)
1255 throw error(ERR_ITERATOR_END
);
1256 return (n
->type() == object
) ? _key
: U
"";
1259 size_t node::iterator::index() throw(error
)
1262 throw error(ERR_ITERATOR_END
);
1266 node
& node::iterator::operator*() throw(error
)
1269 throw error(ERR_ITERATOR_END
);
1270 if(n
->type() == object
) {
1271 if(!n
->xobject
.count(_key
))
1272 throw error(ERR_ITERATOR_DELETED
);
1273 auto& l
= n
->xobject
.find(_key
)->second
;
1275 for(auto i
= l
.begin(); i
!= l
.end(); i
++, j
++) {
1279 throw error(ERR_ITERATOR_DELETED
);
1281 if(idx
>= n
->xarray
.size())
1282 throw error(ERR_ITERATOR_DELETED
);
1283 return *n
->xarray_index
[idx
];
1287 node
* node::iterator::operator->() throw(error
)
1292 node::iterator
node::iterator::operator++(int) throw(error
)
1294 iterator tmp
= *this;
1299 node::iterator
& node::iterator::operator++() throw(error
)
1302 throw error(ERR_ITERATOR_END
);
1304 if(n
->type() == object
) {
1305 if(!n
->xobject
.count(_key
) || n
->xobject
.find(_key
)->second
.size() <= idx
) {
1306 auto i
= n
->xobject
.upper_bound(_key
);
1307 if(i
== n
->xobject
.end())
1314 if(idx
>= n
->xarray_index
.size())
1320 bool node::iterator::operator==(const iterator
& i
) throw()
1326 return (n
== i
.n
&& _key
== i
._key
&& idx
== i
.idx
);
1329 bool node::iterator::operator!=(const iterator
& i
) throw() { return !(*this == i
); }
1331 node::const_iterator::const_iterator() throw() { n
= NULL
; }
1333 node::const_iterator::const_iterator(const node
& _n
) throw(error
)
1337 if(n
->type() == object
) {
1338 if(n
->xobject
.empty())
1341 _key
= n
->xobject
.begin()->first
;
1342 } else if(n
->type() == array
) {
1343 if(n
->xarray
.empty())
1346 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1349 std::u32string
node::const_iterator::key() throw(std::bad_alloc
, error
)
1352 throw error(ERR_ITERATOR_END
);
1353 return (n
->type() == object
) ? _key
: U
"";
1356 size_t node::const_iterator::index() throw(error
)
1359 throw error(ERR_ITERATOR_END
);
1363 const node
& node::const_iterator::operator*() throw(error
)
1366 throw error(ERR_ITERATOR_END
);
1367 if(n
->type() == object
) {
1368 if(!n
->xobject
.count(_key
))
1369 throw error(ERR_ITERATOR_DELETED
);
1370 auto& l
= n
->xobject
.find(_key
)->second
;
1372 for(auto i
= l
.begin(); i
!= l
.end(); i
++, j
++) {
1376 throw error(ERR_ITERATOR_DELETED
);
1378 if(idx
>= n
->xarray
.size())
1379 throw error(ERR_ITERATOR_DELETED
);
1380 return *n
->xarray_index
[idx
];
1384 const node
* node::const_iterator::operator->() throw(error
)
1389 node::const_iterator
node::const_iterator::operator++(int) throw(error
)
1391 const_iterator tmp
= *this;
1396 node::const_iterator
& node::const_iterator::operator++() throw(error
)
1399 throw error(ERR_ITERATOR_END
);
1401 if(n
->type() == object
) {
1402 if(!n
->xobject
.count(_key
) || n
->xobject
.find(_key
)->second
.size() <= idx
) {
1403 auto i
= n
->xobject
.upper_bound(_key
);
1404 if(i
== n
->xobject
.end())
1411 if(idx
>= n
->xarray_index
.size())
1417 bool node::const_iterator::operator==(const const_iterator
& i
) throw()
1423 return (n
== i
.n
&& _key
== i
._key
&& idx
== i
.idx
);
1426 bool node::const_iterator::operator!=(const const_iterator
& i
) throw() { return !(*this == i
); }
1428 void node::erase_index(size_t idx
) throw(error
)
1430 if(type() == array
) {
1431 if(idx
>= xarray_index
.size())
1433 node
* n
= xarray_index
[idx
];
1434 xarray_index
.erase(xarray_index
.begin() + idx
);
1435 for(auto i
= xarray
.begin(); i
!= xarray
.end(); i
++)
1441 throw error(ERR_NOT_AN_ARRAY
);
1444 void node::erase_field(const std::u32string
& fld
, size_t idx
) throw(error
)
1446 if(type() == object
) {
1447 if(xobject
.count(fld
)) {
1448 auto& l
= xobject
[fld
];
1450 for(auto i
= l
.begin(); i
!= l
.end(); i
++, j
++)
1459 throw error(ERR_NOT_AN_OBJECT
);
1462 void node::erase_field_all(const std::u32string
& fld
) throw(error
)
1464 if(type() == object
) {
1465 if(xobject
.count(fld
))
1468 throw error(ERR_NOT_AN_OBJECT
);
1471 void node::clear() throw(error
)
1473 if(type() == object
)
1475 else if(type() == array
) {
1476 xarray_index
.clear();
1479 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1482 node::iterator
node::erase(node::iterator itr
) throw(error
)
1485 throw error(ERR_WRONG_OBJECT
);
1486 if(type() == object
) {
1487 erase_field(itr
._key
, itr
.idx
);
1488 if(!xobject
.count(itr
._key
) || itr
.idx
>= xobject
[itr
._key
].size())
1491 } else if(type() == array
) {
1492 erase_index(itr
.idx
);
1493 if(itr
.idx
>= xarray_index
.size())
1497 throw error(ERR_NOT_ARRAY_NOR_OBJECT
);
1500 void node::fixup_nodes(const node
& _node
)
1502 auto i
= xarray
.begin();
1503 auto j
= _node
.xarray
.begin();
1504 for(; i
!= xarray
.end(); i
++, j
++) {
1505 for(size_t k
= 0; k
< _node
.xarray_index
.size(); k
++)
1506 if(_node
.xarray_index
[k
] == &*j
)
1507 xarray_index
[k
] = &*i
;
1511 bool node::operator==(const node
& n
) const
1515 if(vtype
!= n
.vtype
)
1520 case boolean_tag::id
:
1521 return (_boolean
== n
._boolean
);
1522 case number_tag::id
:
1523 return (_number
== n
._number
);
1524 case string_tag::id
:
1525 return (_string
== n
._string
);
1527 if(xarray_index
.size() != n
.xarray_index
.size())
1529 for(size_t i
= 0; i
< xarray_index
.size(); i
++)
1530 if(*xarray_index
[i
] != *n
.xarray_index
[i
])
1533 case object_tag::id
:
1534 for(auto& i
: xobject
)
1535 if(!n
.xobject
.count(i
.first
))
1537 for(auto& i
: n
.xobject
)
1538 if(!xobject
.count(i
.first
))
1540 for(auto& i
: xobject
) {
1541 auto& j
= *xobject
.find(i
.first
);
1542 auto& k
= *n
.xobject
.find(i
.first
);
1543 if(j
.second
.size() != k
.second
.size())
1545 auto j2
= j
.second
.begin();
1546 auto k2
= k
.second
.begin();
1547 for(; j2
!= j
.second
.end(); j2
++, k2
++)
1553 throw error(ERR_UNKNOWN_TYPE
);
1557 int node::type_of(const std::u32string
& pointer
) const throw(std::bad_alloc
)
1561 if(follow_soft(pointer
, n
) != ERR_OK
)
1564 } catch(std::bad_alloc
& e
) {
1566 } catch(std::exception
& e
) {
1572 int node::type_of_indirect(const std::u32string
& pointer
) const throw(std::bad_alloc
)
1576 if(follow_soft(pointer
, n
) != ERR_OK
)
1578 if(n
->type() == string
)
1579 return type_of(n
->as_string());
1582 } catch(std::bad_alloc
& e
) {
1584 } catch(std::exception
& e
) {
1590 std::u32string
node::resolve_indirect(const std::u32string
& pointer
) const throw(std::bad_alloc
)
1593 const node
& n
= follow(pointer
);
1594 if(n
.type() == string
)
1595 return n
.as_string();
1598 } catch(std::bad_alloc
& e
) {
1600 } catch(std::exception
& e
) {
1609 pointer::pointer(const std::string
& ptr
) throw(std::bad_alloc
)
1611 _pointer
= to_u32string(ptr
);
1614 pointer::pointer(const std::u32string
& ptr
) throw(std::bad_alloc
)
1619 pointer
pointer::index(uint64_t idx
) const throw(std::bad_alloc
)
1621 if(_pointer
.length())
1622 return pointer(_pointer
+ U
"/" + pointer_escape_index(idx
));
1624 return pointer(pointer_escape_index(idx
));
1627 pointer
& pointer::index_inplace(uint64_t idx
) throw(std::bad_alloc
)
1629 if(_pointer
.length())
1630 _pointer
= _pointer
+ U
"/" + pointer_escape_index(idx
);
1632 _pointer
= pointer_escape_index(idx
);
1636 pointer
pointer::field(const std::u32string
& fld
) const throw(std::bad_alloc
)
1638 if(_pointer
.length())
1639 return pointer(_pointer
+ U
"/" + pointer_escape_field(fld
));
1641 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
);
1650 _pointer
= pointer_escape_field(fld
);
1654 pointer
pointer::remove() const throw(std::bad_alloc
)
1656 size_t p
= _pointer
.find_last_of(U
"/");
1657 if(p
>= _pointer
.length())
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())
1669 _pointer
= _pointer
.substr(0, p
);
1673 std::ostream
& operator<<(std::ostream
& s
, const pointer
& p
)
1675 return s
<< to_u8string(p
._pointer
);
1678 std::basic_ostream
<char32_t
>& operator<<(std::basic_ostream
<char32_t
>& s
, const pointer
& p
)
1680 return s
<< p
._pointer
;
1685 bool operator==(const int& n
, const JSON::number_tag
& v
) { return v
== n
; }
1686 bool operator==(const int& n
, const JSON::string_tag
& v
) { return v
== n
; }
1687 bool operator==(const int& n
, const JSON::boolean_tag
& v
) { return v
== n
; }
1688 bool operator==(const int& n
, const JSON::array_tag
& v
) { return v
== n
; }
1689 bool operator==(const int& n
, const JSON::object_tag
& v
) { return v
== n
; }
1690 bool operator==(const int& n
, const JSON::null_tag
& v
) { return v
== n
; }
1691 bool operator!=(const int& n
, const JSON::number_tag
& v
) { return v
!= n
; }
1692 bool operator!=(const int& n
, const JSON::string_tag
& v
) { return v
!= n
; }
1693 bool operator!=(const int& n
, const JSON::boolean_tag
& v
) { return v
!= n
; }
1694 bool operator!=(const int& n
, const JSON::array_tag
& v
) { return v
!= n
; }
1695 bool operator!=(const int& n
, const JSON::object_tag
& v
) { return v
!= n
; }
1696 bool operator!=(const int& n
, const JSON::null_tag
& v
) { return v
!= n
; }