Line data Source code
1 : /*
2 : * Copyright 2009-2010 Cybozu Labs, Inc.
3 : * Copyright 2011-2014 Kazuho Oku
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are met:
8 : *
9 : * 1. Redistributions of source code must retain the above copyright notice,
10 : * this list of conditions and the following disclaimer.
11 : *
12 : * 2. Redistributions in binary form must reproduce the above copyright notice,
13 : * this list of conditions and the following disclaimer in the documentation
14 : * and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 : * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 : * POSSIBILITY OF SUCH DAMAGE.
27 : */
28 : #ifndef picojson_h
29 : #define picojson_h
30 :
31 : #include <algorithm>
32 : #include <cstdio>
33 : #include <cstdlib>
34 : #include <cstring>
35 : #include <cstddef>
36 : #include <iostream>
37 : #include <iterator>
38 : #include <limits>
39 : #include <map>
40 : #include <stdexcept>
41 : #include <string>
42 : #include <vector>
43 : #include <utility>
44 :
45 : // for isnan/isinf
46 : #if __cplusplus >= 201103L
47 : #include <cmath>
48 : #else
49 : extern "C" {
50 : #ifdef _MSC_VER
51 : #include <float.h>
52 : #elif defined(__INTEL_COMPILER)
53 : #include <mathimf.h>
54 : #else
55 : #include <math.h>
56 : #endif
57 : }
58 : #endif
59 :
60 : #ifndef PICOJSON_USE_RVALUE_REFERENCE
61 : #if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600)
62 : #define PICOJSON_USE_RVALUE_REFERENCE 1
63 : #else
64 : #define PICOJSON_USE_RVALUE_REFERENCE 0
65 : #endif
66 : #endif // PICOJSON_USE_RVALUE_REFERENCE
67 :
68 : #ifndef PICOJSON_NOEXCEPT
69 : #if PICOJSON_USE_RVALUE_REFERENCE
70 : #define PICOJSON_NOEXCEPT noexcept
71 : #else
72 : #define PICOJSON_NOEXCEPT throw()
73 : #endif
74 : #endif
75 :
76 : // experimental support for int64_t (see README.mkdn for detail)
77 : #ifdef PICOJSON_USE_INT64
78 : #define __STDC_FORMAT_MACROS
79 : #include <cerrno>
80 : #if __cplusplus >= 201103L
81 : #include <cinttypes>
82 : #else
83 : extern "C" {
84 : #include <inttypes.h>
85 : }
86 : #endif
87 : #endif
88 :
89 : // to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0
90 : #ifndef PICOJSON_USE_LOCALE
91 : #define PICOJSON_USE_LOCALE 1
92 : #endif
93 : #if PICOJSON_USE_LOCALE
94 : extern "C" {
95 : #include <locale.h>
96 : }
97 : #endif
98 :
99 : #ifndef PICOJSON_ASSERT
100 : #define PICOJSON_ASSERT(e) \
101 : do { \
102 : if (!(e)) \
103 : throw std::runtime_error(#e); \
104 : } while (0)
105 : #endif
106 :
107 : #ifdef _MSC_VER
108 : #define SNPRINTF _snprintf_s
109 : #pragma warning(push)
110 : #pragma warning(disable : 4244) // conversion from int to char
111 : #pragma warning(disable : 4127) // conditional expression is constant
112 : #pragma warning(disable : 4702) // unreachable code
113 : #pragma warning(disable : 4706) // assignment within conditional expression
114 : #else
115 : #define SNPRINTF snprintf
116 : #endif
117 :
118 : namespace picojson {
119 :
120 : enum {
121 : null_type,
122 : boolean_type,
123 : number_type,
124 : string_type,
125 : array_type,
126 : object_type
127 : #ifdef PICOJSON_USE_INT64
128 : ,
129 : int64_type
130 : #endif
131 : };
132 :
133 : enum { INDENT_WIDTH = 2, DEFAULT_MAX_DEPTHS = 100 };
134 :
135 : struct null {};
136 :
137 : class value {
138 : public:
139 : typedef std::vector<value> array;
140 : typedef std::map<std::string, value> object;
141 : union _storage {
142 : bool boolean_;
143 : double number_;
144 : #ifdef PICOJSON_USE_INT64
145 : int64_t int64_;
146 : #endif
147 : std::string *string_;
148 : array *array_;
149 : object *object_;
150 : };
151 :
152 : protected:
153 : int type_;
154 : _storage u_;
155 :
156 : public:
157 : value();
158 : value(int type, bool);
159 : explicit value(bool b);
160 : #ifdef PICOJSON_USE_INT64
161 : explicit value(int64_t i);
162 : #endif
163 : explicit value(double n);
164 : explicit value(const std::string &s);
165 : explicit value(const array &a);
166 : explicit value(const object &o);
167 : #if PICOJSON_USE_RVALUE_REFERENCE
168 : explicit value(std::string &&s);
169 : explicit value(array &&a);
170 : explicit value(object &&o);
171 : #endif
172 : explicit value(const char *s);
173 : value(const char *s, size_t len);
174 : ~value();
175 : value(const value &x);
176 : value &operator=(const value &x);
177 : #if PICOJSON_USE_RVALUE_REFERENCE
178 : value(value &&x) PICOJSON_NOEXCEPT;
179 : value &operator=(value &&x) PICOJSON_NOEXCEPT;
180 : #endif
181 : void swap(value &x) PICOJSON_NOEXCEPT;
182 : template <typename T> bool is() const;
183 : template <typename T> const T &get() const;
184 : template <typename T> T &get();
185 : template <typename T> void set(const T &);
186 : #if PICOJSON_USE_RVALUE_REFERENCE
187 : template <typename T> void set(T &&);
188 : #endif
189 : bool evaluate_as_boolean() const;
190 : const value &get(const size_t idx) const;
191 : const value &get(const std::string &key) const;
192 : value &get(const size_t idx);
193 : value &get(const std::string &key);
194 :
195 : bool contains(const size_t idx) const;
196 : bool contains(const std::string &key) const;
197 : std::string to_str() const;
198 : template <typename Iter> void serialize(Iter os, bool prettify = false) const;
199 : std::string serialize(bool prettify = false) const;
200 :
201 : private:
202 : template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
203 : template <typename Iter> static void _indent(Iter os, int indent);
204 : template <typename Iter> void _serialize(Iter os, int indent) const;
205 : std::string _serialize(int indent) const;
206 : void clear();
207 : };
208 :
209 : typedef value::array array;
210 : typedef value::object object;
211 :
212 134 : inline value::value() : type_(null_type), u_() {
213 134 : }
214 :
215 126 : inline value::value(int type, bool) : type_(type), u_() {
216 126 : switch (type) {
217 : #define INIT(p, v) \
218 : case p##type: \
219 : u_.p = v; \
220 : break
221 0 : INIT(boolean_, false);
222 0 : INIT(number_, 0.0);
223 : #ifdef PICOJSON_USE_INT64
224 0 : INIT(int64_, 0);
225 : #endif
226 62 : INIT(string_, new std::string());
227 24 : INIT(array_, new array());
228 40 : INIT(object_, new object());
229 : #undef INIT
230 0 : default:
231 0 : break;
232 : }
233 126 : }
234 :
235 2 : inline value::value(bool b) : type_(boolean_type), u_() {
236 2 : u_.boolean_ = b;
237 2 : }
238 :
239 : #ifdef PICOJSON_USE_INT64
240 6 : inline value::value(int64_t i) : type_(int64_type), u_() {
241 6 : u_.int64_ = i;
242 6 : }
243 : #endif
244 :
245 0 : inline value::value(double n) : type_(number_type), u_() {
246 0 : if (
247 : #ifdef _MSC_VER
248 : !_finite(n)
249 : #elif __cplusplus >= 201103L
250 0 : std::isnan(n) || std::isinf(n)
251 : #else
252 : isnan(n) || isinf(n)
253 : #endif
254 : ) {
255 0 : throw std::overflow_error("");
256 : }
257 0 : u_.number_ = n;
258 0 : }
259 :
260 : inline value::value(const std::string &s) : type_(string_type), u_() {
261 : u_.string_ = new std::string(s);
262 : }
263 :
264 : inline value::value(const array &a) : type_(array_type), u_() {
265 : u_.array_ = new array(a);
266 : }
267 :
268 : inline value::value(const object &o) : type_(object_type), u_() {
269 : u_.object_ = new object(o);
270 : }
271 :
272 : #if PICOJSON_USE_RVALUE_REFERENCE
273 : inline value::value(std::string &&s) : type_(string_type), u_() {
274 : u_.string_ = new std::string(std::move(s));
275 : }
276 :
277 : inline value::value(array &&a) : type_(array_type), u_() {
278 : u_.array_ = new array(std::move(a));
279 : }
280 :
281 : inline value::value(object &&o) : type_(object_type), u_() {
282 : u_.object_ = new object(std::move(o));
283 : }
284 : #endif
285 :
286 : inline value::value(const char *s) : type_(string_type), u_() {
287 : u_.string_ = new std::string(s);
288 : }
289 :
290 : inline value::value(const char *s, size_t len) : type_(string_type), u_() {
291 : u_.string_ = new std::string(s, len);
292 : }
293 :
294 372 : inline void value::clear() {
295 372 : switch (type_) {
296 : #define DEINIT(p) \
297 : case p##type: \
298 : delete u_.p; \
299 : break
300 115 : DEINIT(string_);
301 28 : DEINIT(array_);
302 40 : DEINIT(object_);
303 : #undef DEINIT
304 189 : default:
305 189 : break;
306 : }
307 372 : }
308 :
309 744 : inline value::~value() {
310 372 : clear();
311 372 : }
312 :
313 57 : inline value::value(const value &x) : type_(x.type_), u_() {
314 57 : switch (type_) {
315 : #define INIT(p, v) \
316 : case p##type: \
317 : u_.p = v; \
318 : break
319 53 : INIT(string_, new std::string(*x.u_.string_));
320 4 : INIT(array_, new array(*x.u_.array_));
321 0 : INIT(object_, new object(*x.u_.object_));
322 : #undef INIT
323 0 : default:
324 0 : u_ = x.u_;
325 0 : break;
326 : }
327 57 : }
328 :
329 : inline value &value::operator=(const value &x) {
330 : if (this != &x) {
331 : value t(x);
332 : swap(t);
333 : }
334 : return *this;
335 : }
336 :
337 : #if PICOJSON_USE_RVALUE_REFERENCE
338 47 : inline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() {
339 47 : swap(x);
340 47 : }
341 134 : inline value &value::operator=(value &&x) PICOJSON_NOEXCEPT {
342 134 : swap(x);
343 134 : return *this;
344 : }
345 : #endif
346 181 : inline void value::swap(value &x) PICOJSON_NOEXCEPT {
347 181 : std::swap(type_, x.type_);
348 181 : std::swap(u_, x.u_);
349 181 : }
350 :
351 : #define IS(ctype, jtype) \
352 : template <> inline bool value::is<ctype>() const { \
353 : return type_ == jtype##_type; \
354 : }
355 : IS(null, null)
356 3 : IS(bool, boolean)
357 : #ifdef PICOJSON_USE_INT64
358 0 : IS(int64_t, int64)
359 : #endif
360 171 : IS(std::string, string)
361 82 : IS(array, array)
362 100 : IS(object, object)
363 : #undef IS
364 : template <> inline bool value::is<double>() const {
365 : return type_ == number_type
366 : #ifdef PICOJSON_USE_INT64
367 : || type_ == int64_type
368 : #endif
369 : ;
370 : }
371 :
372 : #define GET(ctype, var) \
373 : template <> inline const ctype &value::get<ctype>() const { \
374 : PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
375 : return var; \
376 : } \
377 : template <> inline ctype &value::get<ctype>() { \
378 : PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
379 : return var; \
380 : }
381 1 : GET(bool, u_.boolean_)
382 122 : GET(std::string, *u_.string_)
383 56 : GET(array, *u_.array_)
384 100 : GET(object, *u_.object_)
385 : #ifdef PICOJSON_USE_INT64
386 : GET(double,
387 : (type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, (const_cast<value *>(this)->u_.number_ = u_.int64_)),
388 : u_.number_))
389 0 : GET(int64_t, u_.int64_)
390 : #else
391 : GET(double, u_.number_)
392 : #endif
393 : #undef GET
394 :
395 : #define SET(ctype, jtype, setter) \
396 : template <> inline void value::set<ctype>(const ctype &_val) { \
397 : clear(); \
398 : type_ = jtype##_type; \
399 : setter \
400 : }
401 : SET(bool, boolean, u_.boolean_ = _val;)
402 : SET(std::string, string, u_.string_ = new std::string(_val);)
403 : SET(array, array, u_.array_ = new array(_val);)
404 : SET(object, object, u_.object_ = new object(_val);)
405 : SET(double, number, u_.number_ = _val;)
406 : #ifdef PICOJSON_USE_INT64
407 : SET(int64_t, int64, u_.int64_ = _val;)
408 : #endif
409 : #undef SET
410 :
411 : #if PICOJSON_USE_RVALUE_REFERENCE
412 : #define MOVESET(ctype, jtype, setter) \
413 : template <> inline void value::set<ctype>(ctype && _val) { \
414 : clear(); \
415 : type_ = jtype##_type; \
416 : setter \
417 : }
418 : MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
419 : MOVESET(array, array, u_.array_ = new array(std::move(_val));)
420 : MOVESET(object, object, u_.object_ = new object(std::move(_val));)
421 : #undef MOVESET
422 : #endif
423 :
424 : inline bool value::evaluate_as_boolean() const {
425 : switch (type_) {
426 : case null_type:
427 : return false;
428 : case boolean_type:
429 : return u_.boolean_;
430 : case number_type:
431 : return u_.number_ != 0;
432 : #ifdef PICOJSON_USE_INT64
433 : case int64_type:
434 : return u_.int64_ != 0;
435 : #endif
436 : case string_type:
437 : return !u_.string_->empty();
438 : default:
439 : return true;
440 : }
441 : }
442 :
443 : inline const value &value::get(const size_t idx) const {
444 : static value s_null;
445 : PICOJSON_ASSERT(is<array>());
446 : return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
447 : }
448 :
449 : inline value &value::get(const size_t idx) {
450 : static value s_null;
451 : PICOJSON_ASSERT(is<array>());
452 : return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
453 : }
454 :
455 : inline const value &value::get(const std::string &key) const {
456 : static value s_null;
457 : PICOJSON_ASSERT(is<object>());
458 : object::const_iterator i = u_.object_->find(key);
459 : return i != u_.object_->end() ? i->second : s_null;
460 : }
461 :
462 : inline value &value::get(const std::string &key) {
463 : static value s_null;
464 : PICOJSON_ASSERT(is<object>());
465 : object::iterator i = u_.object_->find(key);
466 : return i != u_.object_->end() ? i->second : s_null;
467 : }
468 :
469 : inline bool value::contains(const size_t idx) const {
470 : PICOJSON_ASSERT(is<array>());
471 : return idx < u_.array_->size();
472 : }
473 :
474 : inline bool value::contains(const std::string &key) const {
475 : PICOJSON_ASSERT(is<object>());
476 : object::const_iterator i = u_.object_->find(key);
477 : return i != u_.object_->end();
478 : }
479 :
480 : inline std::string value::to_str() const {
481 : switch (type_) {
482 : case null_type:
483 : return "null";
484 : case boolean_type:
485 : return u_.boolean_ ? "true" : "false";
486 : #ifdef PICOJSON_USE_INT64
487 : case int64_type: {
488 : char buf[sizeof("-9223372036854775808")];
489 : SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
490 : return buf;
491 : }
492 : #endif
493 : case number_type: {
494 : char buf[256];
495 : double tmp;
496 : SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
497 : #if PICOJSON_USE_LOCALE
498 : char *decimal_point = localeconv()->decimal_point;
499 : if (strcmp(decimal_point, ".") != 0) {
500 : size_t decimal_point_len = strlen(decimal_point);
501 : for (char *p = buf; *p != '\0'; ++p) {
502 : if (strncmp(p, decimal_point, decimal_point_len) == 0) {
503 : return std::string(buf, p) + "." + (p + decimal_point_len);
504 : }
505 : }
506 : }
507 : #endif
508 : return buf;
509 : }
510 : case string_type:
511 : return *u_.string_;
512 : case array_type:
513 : return "array";
514 : case object_type:
515 : return "object";
516 : default:
517 : PICOJSON_ASSERT(0);
518 : #ifdef _MSC_VER
519 : __assume(0);
520 : #endif
521 : }
522 : return std::string();
523 : }
524 :
525 : template <typename Iter> void copy(const std::string &s, Iter oi) {
526 : std::copy(s.begin(), s.end(), oi);
527 : }
528 :
529 : template <typename Iter> struct serialize_str_char {
530 : Iter oi;
531 : void operator()(char c) {
532 : switch (c) {
533 : #define MAP(val, sym) \
534 : case val: \
535 : copy(sym, oi); \
536 : break
537 : MAP('"', "\\\"");
538 : MAP('\\', "\\\\");
539 : MAP('/', "\\/");
540 : MAP('\b', "\\b");
541 : MAP('\f', "\\f");
542 : MAP('\n', "\\n");
543 : MAP('\r', "\\r");
544 : MAP('\t', "\\t");
545 : #undef MAP
546 : default:
547 : if (static_cast<unsigned char>(c) < 0x20 || c == 0x7f) {
548 : char buf[7];
549 : SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff);
550 : copy(buf, buf + 6, oi);
551 : } else {
552 : *oi++ = c;
553 : }
554 : break;
555 : }
556 : }
557 : };
558 :
559 : template <typename Iter> void serialize_str(const std::string &s, Iter oi) {
560 : *oi++ = '"';
561 : serialize_str_char<Iter> process_char = {oi};
562 : std::for_each(s.begin(), s.end(), process_char);
563 : *oi++ = '"';
564 : }
565 :
566 : template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
567 : return _serialize(oi, prettify ? 0 : -1);
568 : }
569 :
570 : inline std::string value::serialize(bool prettify) const {
571 : return _serialize(prettify ? 0 : -1);
572 : }
573 :
574 : template <typename Iter> void value::_indent(Iter oi, int indent) {
575 : *oi++ = '\n';
576 : for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
577 : *oi++ = ' ';
578 : }
579 : }
580 :
581 : template <typename Iter> void value::_serialize(Iter oi, int indent) const {
582 : switch (type_) {
583 : case string_type:
584 : serialize_str(*u_.string_, oi);
585 : break;
586 : case array_type: {
587 : *oi++ = '[';
588 : if (indent != -1) {
589 : ++indent;
590 : }
591 : for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) {
592 : if (i != u_.array_->begin()) {
593 : *oi++ = ',';
594 : }
595 : if (indent != -1) {
596 : _indent(oi, indent);
597 : }
598 : i->_serialize(oi, indent);
599 : }
600 : if (indent != -1) {
601 : --indent;
602 : if (!u_.array_->empty()) {
603 : _indent(oi, indent);
604 : }
605 : }
606 : *oi++ = ']';
607 : break;
608 : }
609 : case object_type: {
610 : *oi++ = '{';
611 : if (indent != -1) {
612 : ++indent;
613 : }
614 : for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) {
615 : if (i != u_.object_->begin()) {
616 : *oi++ = ',';
617 : }
618 : if (indent != -1) {
619 : _indent(oi, indent);
620 : }
621 : serialize_str(i->first, oi);
622 : *oi++ = ':';
623 : if (indent != -1) {
624 : *oi++ = ' ';
625 : }
626 : i->second._serialize(oi, indent);
627 : }
628 : if (indent != -1) {
629 : --indent;
630 : if (!u_.object_->empty()) {
631 : _indent(oi, indent);
632 : }
633 : }
634 : *oi++ = '}';
635 : break;
636 : }
637 : default:
638 : copy(to_str(), oi);
639 : break;
640 : }
641 : if (indent == 0) {
642 : *oi++ = '\n';
643 : }
644 : }
645 :
646 : inline std::string value::_serialize(int indent) const {
647 : std::string s;
648 : _serialize(std::back_inserter(s), indent);
649 : return s;
650 : }
651 :
652 : template <typename Iter> class input {
653 : protected:
654 : Iter cur_, end_;
655 : bool consumed_;
656 : int line_;
657 :
658 : public:
659 38 : input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) {
660 38 : }
661 6507 : int getc() {
662 6507 : if (consumed_) {
663 5855 : if (*cur_ == '\n') {
664 72 : ++line_;
665 : }
666 5855 : ++cur_;
667 : }
668 6507 : if (cur_ == end_) {
669 20 : consumed_ = false;
670 20 : return -1;
671 : }
672 6487 : consumed_ = true;
673 6487 : return *cur_ & 0xff;
674 : }
675 614 : void ungetc() {
676 614 : consumed_ = false;
677 614 : }
678 38 : Iter cur() const {
679 38 : if (consumed_) {
680 34 : input<Iter> *self = const_cast<input<Iter> *>(this);
681 34 : self->consumed_ = false;
682 34 : ++self->cur_;
683 : }
684 38 : return cur_;
685 : }
686 4 : int line() const {
687 4 : return line_;
688 : }
689 1972 : void skip_ws() {
690 1490 : while (1) {
691 1972 : int ch = getc();
692 1972 : if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
693 482 : ungetc();
694 482 : break;
695 : }
696 : }
697 482 : }
698 348 : bool expect(const int expected) {
699 348 : skip_ws();
700 348 : if (getc() != expected) {
701 120 : ungetc();
702 120 : return false;
703 : }
704 228 : return true;
705 : }
706 2 : bool match(const std::string &pattern) {
707 9 : for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
708 7 : if (getc() != *pi) {
709 0 : ungetc();
710 0 : return false;
711 : }
712 : }
713 2 : return true;
714 : }
715 : };
716 :
717 0 : template <typename Iter> inline int _parse_quadhex(input<Iter> &in) {
718 0 : int uni_ch = 0, hex;
719 0 : for (int i = 0; i < 4; i++) {
720 0 : if ((hex = in.getc()) == -1) {
721 0 : return -1;
722 : }
723 0 : if ('0' <= hex && hex <= '9') {
724 0 : hex -= '0';
725 0 : } else if ('A' <= hex && hex <= 'F') {
726 0 : hex -= 'A' - 0xa;
727 0 : } else if ('a' <= hex && hex <= 'f') {
728 0 : hex -= 'a' - 0xa;
729 : } else {
730 0 : in.ungetc();
731 0 : return -1;
732 : }
733 0 : uni_ch = uni_ch * 16 + hex;
734 : }
735 0 : return uni_ch;
736 : }
737 :
738 0 : template <typename String, typename Iter> inline bool _parse_codepoint(String &out, input<Iter> &in) {
739 : int uni_ch;
740 0 : if ((uni_ch = _parse_quadhex(in)) == -1) {
741 0 : return false;
742 : }
743 0 : if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
744 0 : if (0xdc00 <= uni_ch) {
745 : // a second 16-bit of a surrogate pair appeared
746 0 : return false;
747 : }
748 : // first 16-bit of surrogate pair, get the next one
749 0 : if (in.getc() != '\\' || in.getc() != 'u') {
750 0 : in.ungetc();
751 0 : return false;
752 : }
753 0 : int second = _parse_quadhex(in);
754 0 : if (!(0xdc00 <= second && second <= 0xdfff)) {
755 0 : return false;
756 : }
757 0 : uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
758 0 : uni_ch += 0x10000;
759 : }
760 0 : if (uni_ch < 0x80) {
761 0 : out.push_back(static_cast<char>(uni_ch));
762 : } else {
763 0 : if (uni_ch < 0x800) {
764 0 : out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6)));
765 : } else {
766 0 : if (uni_ch < 0x10000) {
767 0 : out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12)));
768 : } else {
769 0 : out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18)));
770 0 : out.push_back(static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));
771 : }
772 0 : out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));
773 : }
774 0 : out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));
775 : }
776 0 : return true;
777 : }
778 :
779 3799 : template <typename String, typename Iter> inline bool _parse_string(String &out, input<Iter> &in) {
780 3673 : while (1) {
781 3799 : int ch = in.getc();
782 3799 : if (ch < ' ') {
783 0 : in.ungetc();
784 0 : return false;
785 3799 : } else if (ch == '"') {
786 126 : return true;
787 3673 : } else if (ch == '\\') {
788 231 : if ((ch = in.getc()) == -1) {
789 0 : return false;
790 : }
791 231 : switch (ch) {
792 : #define MAP(sym, val) \
793 : case sym: \
794 : out.push_back(val); \
795 : break
796 18 : MAP('"', '\"');
797 213 : MAP('\\', '\\');
798 0 : MAP('/', '/');
799 0 : MAP('b', '\b');
800 0 : MAP('f', '\f');
801 0 : MAP('n', '\n');
802 0 : MAP('r', '\r');
803 0 : MAP('t', '\t');
804 : #undef MAP
805 0 : case 'u':
806 0 : if (!_parse_codepoint(out, in)) {
807 0 : return false;
808 : }
809 0 : break;
810 0 : default:
811 0 : return false;
812 : }
813 : } else {
814 3442 : out.push_back(static_cast<char>(ch));
815 : }
816 : }
817 : return false;
818 : }
819 :
820 24 : template <typename Context, typename Iter> inline bool _parse_array(Context &ctx, input<Iter> &in) {
821 24 : if (!ctx.parse_array_start()) {
822 0 : return false;
823 : }
824 24 : size_t idx = 0;
825 24 : if (in.expect(']')) {
826 2 : return ctx.parse_array_stop(idx);
827 : }
828 10 : do {
829 32 : if (!ctx.parse_array_item(in, idx)) {
830 0 : return false;
831 : }
832 32 : idx++;
833 32 : } while (in.expect(','));
834 22 : return in.expect(']') && ctx.parse_array_stop(idx);
835 : }
836 :
837 40 : template <typename Context, typename Iter> inline bool _parse_object(Context &ctx, input<Iter> &in) {
838 40 : if (!ctx.parse_object_start()) {
839 0 : return false;
840 : }
841 40 : if (in.expect('}')) {
842 2 : return ctx.parse_object_stop();
843 : }
844 30 : do {
845 68 : std::string key;
846 68 : if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
847 4 : return false;
848 : }
849 64 : if (!ctx.parse_object_item(in, key)) {
850 0 : return false;
851 : }
852 64 : } while (in.expect(','));
853 34 : return in.expect('}') && ctx.parse_object_stop();
854 : }
855 :
856 6 : template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
857 6 : std::string num_str;
858 6 : while (1) {
859 12 : int ch = in.getc();
860 12 : if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') {
861 6 : num_str.push_back(static_cast<char>(ch));
862 6 : } else if (ch == '.') {
863 : #if PICOJSON_USE_LOCALE
864 0 : num_str += localeconv()->decimal_point;
865 : #else
866 : num_str.push_back('.');
867 : #endif
868 : } else {
869 6 : in.ungetc();
870 6 : break;
871 : }
872 : }
873 6 : return num_str;
874 : }
875 :
876 134 : template <typename Context, typename Iter> inline bool _parse(Context &ctx, input<Iter> &in) {
877 134 : in.skip_ws();
878 134 : int ch = in.getc();
879 134 : switch (ch) {
880 : #define IS(ch, text, op) \
881 : case ch: \
882 : if (in.match(text) && op) { \
883 : return true; \
884 : } else { \
885 : return false; \
886 : }
887 0 : IS('n', "ull", ctx.set_null());
888 2 : IS('f', "alse", ctx.set_bool(false));
889 2 : IS('t', "rue", ctx.set_bool(true));
890 : #undef IS
891 62 : case '"':
892 62 : return ctx.parse_string(in);
893 24 : case '[':
894 24 : return _parse_array(ctx, in);
895 40 : case '{':
896 40 : return _parse_object(ctx, in);
897 6 : default:
898 6 : if (('0' <= ch && ch <= '9') || ch == '-') {
899 : double f;
900 : char *endp;
901 6 : in.ungetc();
902 12 : std::string num_str(_parse_number(in));
903 6 : if (num_str.empty()) {
904 0 : return false;
905 : }
906 : #ifdef PICOJSON_USE_INT64
907 : {
908 6 : errno = 0;
909 6 : intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
910 12 : if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() &&
911 6 : endp == num_str.c_str() + num_str.size()) {
912 6 : ctx.set_int64(ival);
913 6 : return true;
914 : }
915 : }
916 : #endif
917 0 : f = strtod(num_str.c_str(), &endp);
918 0 : if (endp == num_str.c_str() + num_str.size()) {
919 0 : ctx.set_number(f);
920 0 : return true;
921 : }
922 0 : return false;
923 : }
924 0 : break;
925 : }
926 0 : in.ungetc();
927 0 : return false;
928 : }
929 :
930 : class deny_parse_context {
931 : public:
932 : bool set_null() {
933 : return false;
934 : }
935 : bool set_bool(bool) {
936 : return false;
937 : }
938 : #ifdef PICOJSON_USE_INT64
939 : bool set_int64(int64_t) {
940 : return false;
941 : }
942 : #endif
943 : bool set_number(double) {
944 : return false;
945 : }
946 : template <typename Iter> bool parse_string(input<Iter> &) {
947 : return false;
948 : }
949 : bool parse_array_start() {
950 : return false;
951 : }
952 : template <typename Iter> bool parse_array_item(input<Iter> &, size_t) {
953 : return false;
954 : }
955 : bool parse_array_stop(size_t) {
956 : return false;
957 : }
958 : bool parse_object_start() {
959 : return false;
960 : }
961 : template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) {
962 : return false;
963 : }
964 : };
965 :
966 : class default_parse_context {
967 : protected:
968 : value *out_;
969 : size_t depths_;
970 :
971 : public:
972 134 : default_parse_context(value *out, size_t depths = DEFAULT_MAX_DEPTHS) : out_(out), depths_(depths) {
973 134 : }
974 0 : bool set_null() {
975 0 : *out_ = value();
976 0 : return true;
977 : }
978 2 : bool set_bool(bool b) {
979 2 : *out_ = value(b);
980 2 : return true;
981 : }
982 : #ifdef PICOJSON_USE_INT64
983 6 : bool set_int64(int64_t i) {
984 6 : *out_ = value(i);
985 6 : return true;
986 : }
987 : #endif
988 0 : bool set_number(double f) {
989 0 : *out_ = value(f);
990 0 : return true;
991 : }
992 62 : template <typename Iter> bool parse_string(input<Iter> &in) {
993 62 : *out_ = value(string_type, false);
994 62 : return _parse_string(out_->get<std::string>(), in);
995 : }
996 24 : bool parse_array_start() {
997 24 : if (depths_ == 0)
998 0 : return false;
999 24 : --depths_;
1000 24 : *out_ = value(array_type, false);
1001 24 : return true;
1002 : }
1003 32 : template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
1004 32 : array &a = out_->get<array>();
1005 32 : a.push_back(value());
1006 32 : default_parse_context ctx(&a.back(), depths_);
1007 64 : return _parse(ctx, in);
1008 : }
1009 24 : bool parse_array_stop(size_t) {
1010 24 : ++depths_;
1011 24 : return true;
1012 : }
1013 40 : bool parse_object_start() {
1014 40 : if (depths_ == 0)
1015 0 : return false;
1016 40 : *out_ = value(object_type, false);
1017 40 : return true;
1018 : }
1019 64 : template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key) {
1020 64 : object &o = out_->get<object>();
1021 64 : default_parse_context ctx(&o[key], depths_);
1022 128 : return _parse(ctx, in);
1023 : }
1024 36 : bool parse_object_stop() {
1025 36 : ++depths_;
1026 36 : return true;
1027 : }
1028 :
1029 : private:
1030 : default_parse_context(const default_parse_context &);
1031 : default_parse_context &operator=(const default_parse_context &);
1032 : };
1033 :
1034 : class null_parse_context {
1035 : protected:
1036 : size_t depths_;
1037 :
1038 : public:
1039 : struct dummy_str {
1040 : void push_back(int) {
1041 : }
1042 : };
1043 :
1044 : public:
1045 : null_parse_context(size_t depths = DEFAULT_MAX_DEPTHS) : depths_(depths) {
1046 : }
1047 : bool set_null() {
1048 : return true;
1049 : }
1050 : bool set_bool(bool) {
1051 : return true;
1052 : }
1053 : #ifdef PICOJSON_USE_INT64
1054 : bool set_int64(int64_t) {
1055 : return true;
1056 : }
1057 : #endif
1058 : bool set_number(double) {
1059 : return true;
1060 : }
1061 : template <typename Iter> bool parse_string(input<Iter> &in) {
1062 : dummy_str s;
1063 : return _parse_string(s, in);
1064 : }
1065 : bool parse_array_start() {
1066 : if (depths_ == 0)
1067 : return false;
1068 : --depths_;
1069 : return true;
1070 : }
1071 : template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
1072 : return _parse(*this, in);
1073 : }
1074 : bool parse_array_stop(size_t) {
1075 : ++depths_;
1076 : return true;
1077 : }
1078 : bool parse_object_start() {
1079 : if (depths_ == 0)
1080 : return false;
1081 : --depths_;
1082 : return true;
1083 : }
1084 : template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) {
1085 : ++depths_;
1086 : return _parse(*this, in);
1087 : }
1088 : bool parse_object_stop() {
1089 : return true;
1090 : }
1091 :
1092 : private:
1093 : null_parse_context(const null_parse_context &);
1094 : null_parse_context &operator=(const null_parse_context &);
1095 : };
1096 :
1097 : // obsolete, use the version below
1098 : template <typename Iter> inline std::string parse(value &out, Iter &pos, const Iter &last) {
1099 : std::string err;
1100 : pos = parse(out, pos, last, &err);
1101 : return err;
1102 : }
1103 :
1104 38 : template <typename Context, typename Iter> inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) {
1105 38 : input<Iter> in(first, last);
1106 38 : if (!_parse(ctx, in) && err != NULL) {
1107 : char buf[64];
1108 4 : SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
1109 4 : *err = buf;
1110 0 : while (1) {
1111 4 : int ch = in.getc();
1112 4 : if (ch == -1 || ch == '\n') {
1113 : break;
1114 0 : } else if (ch >= ' ') {
1115 0 : err->push_back(static_cast<char>(ch));
1116 : }
1117 : }
1118 : }
1119 76 : return in.cur();
1120 : }
1121 :
1122 38 : template <typename Iter> inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) {
1123 38 : default_parse_context ctx(&out);
1124 76 : return _parse(ctx, first, last, err);
1125 : }
1126 :
1127 0 : inline std::string parse(value &out, const std::string &s) {
1128 0 : std::string err;
1129 0 : parse(out, s.begin(), s.end(), &err);
1130 0 : return err;
1131 : }
1132 :
1133 38 : inline std::string parse(value &out, std::istream &is) {
1134 38 : std::string err;
1135 38 : parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
1136 38 : return err;
1137 : }
1138 :
1139 : template <typename T> struct last_error_t { static std::string s; };
1140 : template <typename T> std::string last_error_t<T>::s;
1141 :
1142 42 : inline void set_last_error(const std::string &s) {
1143 42 : last_error_t<bool>::s = s;
1144 42 : }
1145 :
1146 25 : inline const std::string &get_last_error() {
1147 25 : return last_error_t<bool>::s;
1148 : }
1149 :
1150 : inline bool operator==(const value &x, const value &y) {
1151 : if (x.is<null>())
1152 : return y.is<null>();
1153 : #define PICOJSON_CMP(type) \
1154 : if (x.is<type>()) \
1155 : return y.is<type>() && x.get<type>() == y.get<type>()
1156 : PICOJSON_CMP(bool);
1157 : PICOJSON_CMP(double);
1158 : PICOJSON_CMP(std::string);
1159 : PICOJSON_CMP(array);
1160 : PICOJSON_CMP(object);
1161 : #undef PICOJSON_CMP
1162 : PICOJSON_ASSERT(0);
1163 : #ifdef _MSC_VER
1164 : __assume(0);
1165 : #endif
1166 : return false;
1167 : }
1168 :
1169 : inline bool operator!=(const value &x, const value &y) {
1170 : return !(x == y);
1171 : }
1172 : }
1173 :
1174 : #if !PICOJSON_USE_RVALUE_REFERENCE
1175 : namespace std {
1176 : template <> inline void swap(picojson::value &x, picojson::value &y) {
1177 : x.swap(y);
1178 : }
1179 : }
1180 : #endif
1181 :
1182 38 : inline std::istream &operator>>(std::istream &is, picojson::value &x) {
1183 38 : picojson::set_last_error(std::string());
1184 38 : const std::string err(picojson::parse(x, is));
1185 38 : if (!err.empty()) {
1186 4 : picojson::set_last_error(err);
1187 4 : is.setstate(std::ios::failbit);
1188 : }
1189 76 : return is;
1190 : }
1191 :
1192 : inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) {
1193 : x.serialize(std::ostream_iterator<char>(os));
1194 : return os;
1195 : }
1196 : #ifdef _MSC_VER
1197 : #pragma warning(pop)
1198 : #endif
1199 :
1200 : #endif
|