Alternate e697dbe9c5997e35395fe158628dd8c5209481da
for Visual Studio 2022 and Windows 11.
読み取り中…
検索中…
一致する文字列を見つけられません
picojson.h
[詳解]
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
49extern "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
83extern "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
94extern "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#else
114#define SNPRINTF snprintf
115#endif
116
117namespace picojson {
118
119enum {
126#ifdef PICOJSON_USE_INT64
127 ,
128 int64_type
129#endif
131
132enum { INDENT_WIDTH = 2 };
133
134struct null {};
135
136class value {
137public:
138 typedef std::vector<value> array;
139 typedef std::map<std::string, value> object;
140 union _storage {
142 double number_;
143#ifdef PICOJSON_USE_INT64
144 int64_t int64_;
145#endif
146 std::string *string_;
148 object *object_;
149 };
150
151protected:
152 int type_;
154
155public:
156 value();
157 value(int type, bool);
158 explicit value(bool b);
159#ifdef PICOJSON_USE_INT64
160 explicit value(int64_t i);
161#endif
162 explicit value(double n);
163 explicit value(const std::string &s);
164 explicit value(const array &a);
165 explicit value(const object &o);
166#if PICOJSON_USE_RVALUE_REFERENCE
167 explicit value(std::string &&s);
168 explicit value(array &&a);
169 explicit value(object &&o);
170#endif
171 explicit value(const char *s);
172 value(const char *s, size_t len);
173 ~value();
174 value(const value &x);
175 value &operator=(const value &x);
176#if PICOJSON_USE_RVALUE_REFERENCE
179#endif
181 template <typename T> bool is() const;
182 template <typename T> const T &get() const;
183 template <typename T> T &get();
184 template <typename T> void set(const T &);
185#if PICOJSON_USE_RVALUE_REFERENCE
186 template <typename T> void set(T &&);
187#endif
188 bool evaluate_as_boolean() const;
189 const value &get(const size_t idx) const;
190 const value &get(const std::string &key) const;
191 value &get(const size_t idx);
192 value &get(const std::string &key);
193
194 bool contains(const size_t idx) const;
195 bool contains(const std::string &key) const;
196 std::string to_str() const;
197 template <typename Iter> void serialize(Iter os, bool prettify = false) const;
198 std::string serialize(bool prettify = false) const;
199
200private:
201 template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
202 template <typename Iter> static void _indent(Iter os, int indent);
203 template <typename Iter> void _serialize(Iter os, int indent) const;
204 std::string _serialize(int indent) const;
205 void clear();
206};
207
210
211inline value::value() : type_(null_type), u_() {
212}
213
214inline value::value(int type, bool) : type_(type), u_() {
215 switch (type) {
216#define INIT(p, v) \
217 case p##type: \
218 u_.p = v; \
219 break
220 INIT(boolean_, false);
221 INIT(number_, 0.0);
222#ifdef PICOJSON_USE_INT64
223 INIT(int64_, 0);
224#endif
225 INIT(string_, new std::string());
226 INIT(array_, new array());
227 INIT(object_, new object());
228#undef INIT
229 default:
230 break;
231 }
232}
233
234inline value::value(bool b) : type_(boolean_type), u_() {
235 u_.boolean_ = b;
236}
237
238#ifdef PICOJSON_USE_INT64
239inline value::value(int64_t i) : type_(int64_type), u_() {
240 u_.int64_ = i;
241}
242#endif
243
244inline value::value(double n) : type_(number_type), u_() {
245 if (
246#ifdef _MSC_VER
247 !_finite(n)
248#elif __cplusplus >= 201103L
249 std::isnan(n) || std::isinf(n)
250#else
251 isnan(n) || isinf(n)
252#endif
253 ) {
254 throw std::overflow_error("");
255 }
256 u_.number_ = n;
257}
258
259inline value::value(const std::string &s) : type_(string_type), u_() {
260 u_.string_ = new std::string(s);
261}
262
263inline value::value(const array &a) : type_(array_type), u_() {
264 u_.array_ = new array(a);
265}
266
267inline value::value(const object &o) : type_(object_type), u_() {
268 u_.object_ = new object(o);
269}
270
271#if PICOJSON_USE_RVALUE_REFERENCE
272inline value::value(std::string &&s) : type_(string_type), u_() {
273 u_.string_ = new std::string(std::move(s));
274}
275
276inline value::value(array &&a) : type_(array_type), u_() {
277 u_.array_ = new array(std::move(a));
278}
279
280inline value::value(object &&o) : type_(object_type), u_() {
281 u_.object_ = new object(std::move(o));
282}
283#endif
284
285inline value::value(const char *s) : type_(string_type), u_() {
286 u_.string_ = new std::string(s);
287}
288
289inline value::value(const char *s, size_t len) : type_(string_type), u_() {
290 u_.string_ = new std::string(s, len);
291}
292
293inline void value::clear() {
294 switch (type_) {
295#define DEINIT(p) \
296 case p##type: \
297 delete u_.p; \
298 break
299 DEINIT(string_);
300 DEINIT(array_);
301 DEINIT(object_);
302#undef DEINIT
303 default:
304 break;
305 }
306}
307
309 clear();
310}
311
312inline value::value(const value &x) : type_(x.type_), u_() {
313 switch (type_) {
314#define INIT(p, v) \
315 case p##type: \
316 u_.p = v; \
317 break
318 INIT(string_, new std::string(*x.u_.string_));
319 INIT(array_, new array(*x.u_.array_));
320 INIT(object_, new object(*x.u_.object_));
321#undef INIT
322 default:
323 u_ = x.u_;
324 break;
325 }
326}
327
328inline value &value::operator=(const value &x) {
329 if (this != &x) {
330 value t(x);
331 swap(t);
332 }
333 return *this;
334}
335
336#if PICOJSON_USE_RVALUE_REFERENCE
337inline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() {
338 swap(x);
339}
340inline value &value::operator=(value &&x) PICOJSON_NOEXCEPT {
341 swap(x);
342 return *this;
343}
344#endif
346 std::swap(type_, x.type_);
347 std::swap(u_, x.u_);
348}
349
350#define IS(ctype, jtype) \
351 template <> inline bool value::is<ctype>() const { \
352 return type_ == jtype##_type; \
353 }
354IS(null, null)
355IS(bool, boolean)
356#ifdef PICOJSON_USE_INT64
357IS(int64_t, int64)
358#endif
359IS(std::string, string)
360IS(array, array)
361IS(object, object)
362#undef IS
363template <> inline bool value::is<double>() const {
364 return type_ == number_type
365#ifdef PICOJSON_USE_INT64
366 || type_ == int64_type
367#endif
368 ;
369}
370
371#define GET(ctype, var) \
372 template <> inline const ctype &value::get<ctype>() const { \
373 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
374 return var; \
375 } \
376 template <> inline ctype &value::get<ctype>() { \
377 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
378 return var; \
379 }
380GET(bool, u_.boolean_)
381GET(std::string, *u_.string_)
382GET(array, *u_.array_)
383GET(object, *u_.object_)
384#ifdef PICOJSON_USE_INT64
385GET(double,
386 (type_ == int64_type && (const_cast<value *>(this)->type_ = number_type, const_cast<value *>(this)->u_.number_ = u_.int64_),
387 u_.number_))
388GET(int64_t, u_.int64_)
389#else
390GET(double, u_.number_)
391#endif
392#undef GET
393
394#define SET(ctype, jtype, setter) \
395 template <> inline void value::set<ctype>(const ctype &_val) { \
396 clear(); \
397 type_ = jtype##_type; \
398 setter \
399 }
400SET(bool, boolean, u_.boolean_ = _val;)
401SET(std::string, string, u_.string_ = new std::string(_val);)
402SET(array, array, u_.array_ = new array(_val);)
403SET(object, object, u_.object_ = new object(_val);)
404SET(double, number, u_.number_ = _val;)
405#ifdef PICOJSON_USE_INT64
406SET(int64_t, int64, u_.int64_ = _val;)
407#endif
408#undef SET
409
410#if PICOJSON_USE_RVALUE_REFERENCE
411#define MOVESET(ctype, jtype, setter) \
412 template <> inline void value::set<ctype>(ctype && _val) { \
413 clear(); \
414 type_ = jtype##_type; \
415 setter \
416 }
417MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
418MOVESET(array, array, u_.array_ = new array(std::move(_val));)
419MOVESET(object, object, u_.object_ = new object(std::move(_val));)
420#undef MOVESET
421#endif
422
423inline bool value::evaluate_as_boolean() const {
424 switch (type_) {
425 case null_type:
426 return false;
427 case boolean_type:
428 return u_.boolean_;
429 case number_type:
430 return u_.number_ != 0;
431#ifdef PICOJSON_USE_INT64
432 case int64_type:
433 return u_.int64_ != 0;
434#endif
435 case string_type:
436 return !u_.string_->empty();
437 default:
438 return true;
439 }
440}
441
442inline const value &value::get(const size_t idx) const {
443 static value s_null;
444 PICOJSON_ASSERT(is<array>());
445 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
446}
447
448inline value &value::get(const size_t idx) {
449 static value s_null;
450 PICOJSON_ASSERT(is<array>());
451 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
452}
453
454inline const value &value::get(const std::string &key) const {
455 static value s_null;
456 PICOJSON_ASSERT(is<object>());
457 object::const_iterator i = u_.object_->find(key);
458 return i != u_.object_->end() ? i->second : s_null;
459}
460
461inline value &value::get(const std::string &key) {
462 static value s_null;
463 PICOJSON_ASSERT(is<object>());
464 object::iterator i = u_.object_->find(key);
465 return i != u_.object_->end() ? i->second : s_null;
466}
467
468inline bool value::contains(const size_t idx) const {
469 PICOJSON_ASSERT(is<array>());
470 return idx < u_.array_->size();
471}
472
473inline bool value::contains(const std::string &key) const {
474 PICOJSON_ASSERT(is<object>());
475 object::const_iterator i = u_.object_->find(key);
476 return i != u_.object_->end();
477}
478
479inline std::string value::to_str() const {
480 switch (type_) {
481 case null_type:
482 return "null";
483 case boolean_type:
484 return u_.boolean_ ? "true" : "false";
485#ifdef PICOJSON_USE_INT64
486 case int64_type: {
487 char buf[sizeof("-9223372036854775808")];
488 SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
489 return buf;
490 }
491#endif
492 case number_type: {
493 char buf[256];
494 double tmp;
495 SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
496#if PICOJSON_USE_LOCALE
497 char *decimal_point = localeconv()->decimal_point;
498 if (strcmp(decimal_point, ".") != 0) {
499 size_t decimal_point_len = strlen(decimal_point);
500 for (char *p = buf; *p != '\0'; ++p) {
501 if (strncmp(p, decimal_point, decimal_point_len) == 0) {
502 return std::string(buf, p) + "." + (p + decimal_point_len);
503 }
504 }
505 }
506#endif
507 return buf;
508 }
509 case string_type:
510 return *u_.string_;
511 case array_type:
512 return "array";
513 case object_type:
514 return "object";
515 default:
517#ifdef _MSC_VER
518 __assume(0);
519#endif
520 }
521 return std::string();
522}
523
524template <typename Iter> void copy(const std::string &s, Iter oi) {
525 std::copy(s.begin(), s.end(), oi);
526}
527
528template <typename Iter> struct serialize_str_char {
529 Iter oi;
530 void operator()(char c) {
531 switch (c) {
532#define MAP(val, sym) \
533 case val: \
534 copy(sym, oi); \
535 break
536 MAP('"', "\\\"");
537 MAP('\\', "\\\\");
538 MAP('/', "\\/");
539 MAP('\b', "\\b");
540 MAP('\f', "\\f");
541 MAP('\n', "\\n");
542 MAP('\r', "\\r");
543 MAP('\t', "\\t");
544#undef MAP
545 default:
546 if (static_cast<unsigned char>(c) < 0x20 || c == 0x7f) {
547 char buf[7];
548 SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff);
549 copy(buf, buf + 6, oi);
550 } else {
551 *oi++ = c;
552 }
553 break;
554 }
555 }
556};
557
558template <typename Iter> void serialize_str(const std::string &s, Iter oi) {
559 *oi++ = '"';
560 serialize_str_char<Iter> process_char = {oi};
561 std::for_each(s.begin(), s.end(), process_char);
562 *oi++ = '"';
563}
564
565template <typename Iter> void value::serialize(Iter oi, bool prettify) const {
566 return _serialize(oi, prettify ? 0 : -1);
567}
568
569inline std::string value::serialize(bool prettify) const {
570 return _serialize(prettify ? 0 : -1);
571}
572
573template <typename Iter> void value::_indent(Iter oi, int indent) {
574 *oi++ = '\n';
575 for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
576 *oi++ = ' ';
577 }
578}
579
580template <typename Iter> void value::_serialize(Iter oi, int indent) const {
581 switch (type_) {
582 case string_type:
584 break;
585 case array_type: {
586 *oi++ = '[';
587 if (indent != -1) {
588 ++indent;
589 }
590 for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) {
591 if (i != u_.array_->begin()) {
592 *oi++ = ',';
593 }
594 if (indent != -1) {
595 _indent(oi, indent);
596 }
597 i->_serialize(oi, indent);
598 }
599 if (indent != -1) {
600 --indent;
601 if (!u_.array_->empty()) {
602 _indent(oi, indent);
603 }
604 }
605 *oi++ = ']';
606 break;
607 }
608 case object_type: {
609 *oi++ = '{';
610 if (indent != -1) {
611 ++indent;
612 }
613 for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) {
614 if (i != u_.object_->begin()) {
615 *oi++ = ',';
616 }
617 if (indent != -1) {
618 _indent(oi, indent);
619 }
620 serialize_str(i->first, oi);
621 *oi++ = ':';
622 if (indent != -1) {
623 *oi++ = ' ';
624 }
625 i->second._serialize(oi, indent);
626 }
627 if (indent != -1) {
628 --indent;
629 if (!u_.object_->empty()) {
630 _indent(oi, indent);
631 }
632 }
633 *oi++ = '}';
634 break;
635 }
636 default:
637 copy(to_str(), oi);
638 break;
639 }
640 if (indent == 0) {
641 *oi++ = '\n';
642 }
643}
644
645inline std::string value::_serialize(int indent) const {
646 std::string s;
647 _serialize(std::back_inserter(s), indent);
648 return s;
649}
650
651template <typename Iter> class input {
652protected:
653 Iter cur_, end_;
655 int line_;
656
657public:
658 input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) {
659 }
660 int getc() {
661 if (consumed_) {
662 if (*cur_ == '\n') {
663 ++line_;
664 }
665 ++cur_;
666 }
667 if (cur_ == end_) {
668 consumed_ = false;
669 return -1;
670 }
671 consumed_ = true;
672 return *cur_ & 0xff;
673 }
674 void ungetc() {
675 consumed_ = false;
676 }
677 Iter cur() const {
678 if (consumed_) {
679 input<Iter> *self = const_cast<input<Iter> *>(this);
680 self->consumed_ = false;
681 ++self->cur_;
682 }
683 return cur_;
684 }
685 int line() const {
686 return line_;
687 }
688 void skip_ws() {
689 while (1) {
690 int ch = getc();
691 if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
692 ungetc();
693 break;
694 }
695 }
696 }
697 bool expect(const int expected) {
698 skip_ws();
699 if (getc() != expected) {
700 ungetc();
701 return false;
702 }
703 return true;
704 }
705 bool match(const std::string &pattern) {
706 for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
707 if (getc() != *pi) {
708 ungetc();
709 return false;
710 }
711 }
712 return true;
713 }
714};
715
716template <typename Iter> inline int _parse_quadhex(input<Iter> &in) {
717 int uni_ch = 0, hex;
718 for (int i = 0; i < 4; i++) {
719 if ((hex = in.getc()) == -1) {
720 return -1;
721 }
722 if ('0' <= hex && hex <= '9') {
723 hex -= '0';
724 } else if ('A' <= hex && hex <= 'F') {
725 hex -= 'A' - 0xa;
726 } else if ('a' <= hex && hex <= 'f') {
727 hex -= 'a' - 0xa;
728 } else {
729 in.ungetc();
730 return -1;
731 }
732 uni_ch = uni_ch * 16 + hex;
733 }
734 return uni_ch;
735}
736
737template <typename String, typename Iter> inline bool _parse_codepoint(String &out, input<Iter> &in) {
738 int uni_ch;
739 if ((uni_ch = _parse_quadhex(in)) == -1) {
740 return false;
741 }
742 if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
743 if (0xdc00 <= uni_ch) {
744 // a second 16-bit of a surrogate pair appeared
745 return false;
746 }
747 // first 16-bit of surrogate pair, get the next one
748 if (in.getc() != '\\' || in.getc() != 'u') {
749 in.ungetc();
750 return false;
751 }
752 int second = _parse_quadhex(in);
753 if (!(0xdc00 <= second && second <= 0xdfff)) {
754 return false;
755 }
756 uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
757 uni_ch += 0x10000;
758 }
759 if (uni_ch < 0x80) {
760 out.push_back(static_cast<char>(uni_ch));
761 } else {
762 if (uni_ch < 0x800) {
763 out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6)));
764 } else {
765 if (uni_ch < 0x10000) {
766 out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12)));
767 } else {
768 out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18)));
769 out.push_back(static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));
770 }
771 out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));
772 }
773 out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));
774 }
775 return true;
776}
777
778template <typename String, typename Iter> inline bool _parse_string(String &out, input<Iter> &in) {
779 while (1) {
780 int ch = in.getc();
781 if (ch < ' ') {
782 in.ungetc();
783 return false;
784 } else if (ch == '"') {
785 return true;
786 } else if (ch == '\\') {
787 if ((ch = in.getc()) == -1) {
788 return false;
789 }
790 switch (ch) {
791#define MAP(sym, val) \
792 case sym: \
793 out.push_back(val); \
794 break
795 MAP('"', '\"');
796 MAP('\\', '\\');
797 MAP('/', '/');
798 MAP('b', '\b');
799 MAP('f', '\f');
800 MAP('n', '\n');
801 MAP('r', '\r');
802 MAP('t', '\t');
803#undef MAP
804 case 'u':
805 if (!_parse_codepoint(out, in)) {
806 return false;
807 }
808 break;
809 default:
810 return false;
811 }
812 } else {
813 out.push_back(static_cast<char>(ch));
814 }
815 }
816 return false;
817}
818
819template <typename Context, typename Iter> inline bool _parse_array(Context &ctx, input<Iter> &in) {
820 if (!ctx.parse_array_start()) {
821 return false;
822 }
823 size_t idx = 0;
824 if (in.expect(']')) {
825 return ctx.parse_array_stop(idx);
826 }
827 do {
828 if (!ctx.parse_array_item(in, idx)) {
829 return false;
830 }
831 idx++;
832 } while (in.expect(','));
833 return in.expect(']') && ctx.parse_array_stop(idx);
834}
835
836template <typename Context, typename Iter> inline bool _parse_object(Context &ctx, input<Iter> &in) {
837 if (!ctx.parse_object_start()) {
838 return false;
839 }
840 if (in.expect('}')) {
841 return true;
842 }
843 do {
844 std::string key;
845 if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
846 return false;
847 }
848 if (!ctx.parse_object_item(in, key)) {
849 return false;
850 }
851 } while (in.expect(','));
852 return in.expect('}');
853}
854
855template <typename Iter> inline std::string _parse_number(input<Iter> &in) {
856 std::string num_str;
857 while (1) {
858 int ch = in.getc();
859 if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') {
860 num_str.push_back(static_cast<char>(ch));
861 } else if (ch == '.') {
862#if PICOJSON_USE_LOCALE
863 num_str += localeconv()->decimal_point;
864#else
865 num_str.push_back('.');
866#endif
867 } else {
868 in.ungetc();
869 break;
870 }
871 }
872 return num_str;
873}
874
875template <typename Context, typename Iter> inline bool _parse(Context &ctx, input<Iter> &in) {
876 in.skip_ws();
877 int ch = in.getc();
878 switch (ch) {
879#define IS(ch, text, op) \
880 case ch: \
881 if (in.match(text) && op) { \
882 return true; \
883 } else { \
884 return false; \
885 }
886 IS('n', "ull", ctx.set_null());
887 IS('f', "alse", ctx.set_bool(false));
888 IS('t', "rue", ctx.set_bool(true));
889#undef IS
890 case '"':
891 return ctx.parse_string(in);
892 case '[':
893 return _parse_array(ctx, in);
894 case '{':
895 return _parse_object(ctx, in);
896 default:
897 if (('0' <= ch && ch <= '9') || ch == '-') {
898 double f;
899 char *endp;
900 in.ungetc();
901 std::string num_str(_parse_number(in));
902 if (num_str.empty()) {
903 return false;
904 }
905#ifdef PICOJSON_USE_INT64
906 {
907 errno = 0;
908 intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
909 if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() &&
910 endp == num_str.c_str() + num_str.size()) {
911 ctx.set_int64(ival);
912 return true;
913 }
914 }
915#endif
916 f = strtod(num_str.c_str(), &endp);
917 if (endp == num_str.c_str() + num_str.size()) {
918 ctx.set_number(f);
919 return true;
920 }
921 return false;
922 }
923 break;
924 }
925 in.ungetc();
926 return false;
927}
928
930public:
931 bool set_null() {
932 return false;
933 }
934 bool set_bool(bool) {
935 return false;
936 }
937#ifdef PICOJSON_USE_INT64
938 bool set_int64(int64_t) {
939 return false;
940 }
941#endif
942 bool set_number(double) {
943 return false;
944 }
945 template <typename Iter> bool parse_string(input<Iter> &) {
946 return false;
947 }
949 return false;
950 }
951 template <typename Iter> bool parse_array_item(input<Iter> &, size_t) {
952 return false;
953 }
954 bool parse_array_stop(size_t) {
955 return false;
956 }
958 return false;
959 }
960 template <typename Iter> bool parse_object_item(input<Iter> &, const std::string &) {
961 return false;
962 }
963};
964
966protected:
968
969public:
971 }
972 bool set_null() {
973 *out_ = value();
974 return true;
975 }
976 bool set_bool(bool b) {
977 *out_ = value(b);
978 return true;
979 }
980#ifdef PICOJSON_USE_INT64
981 bool set_int64(int64_t i) {
982 *out_ = value(i);
983 return true;
984 }
985#endif
986 bool set_number(double f) {
987 *out_ = value(f);
988 return true;
989 }
990 template <typename Iter> bool parse_string(input<Iter> &in) {
991 *out_ = value(string_type, false);
992 return _parse_string(out_->get<std::string>(), in);
993 }
995 *out_ = value(array_type, false);
996 return true;
997 }
998 template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
999 array &a = out_->get<array>();
1000 a.push_back(value());
1001 default_parse_context ctx(&a.back());
1002 return _parse(ctx, in);
1003 }
1004 bool parse_array_stop(size_t) {
1005 return true;
1006 }
1008 *out_ = value(object_type, false);
1009 return true;
1010 }
1011 template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key) {
1012 object &o = out_->get<object>();
1013 default_parse_context ctx(&o[key]);
1014 return _parse(ctx, in);
1015 }
1016
1017private:
1020};
1021
1023public:
1024 struct dummy_str {
1025 void push_back(int) {
1026 }
1027 };
1028
1029public:
1031 }
1032 bool set_null() {
1033 return true;
1034 }
1035 bool set_bool(bool) {
1036 return true;
1037 }
1038#ifdef PICOJSON_USE_INT64
1039 bool set_int64(int64_t) {
1040 return true;
1041 }
1042#endif
1043 bool set_number(double) {
1044 return true;
1045 }
1046 template <typename Iter> bool parse_string(input<Iter> &in) {
1047 dummy_str s;
1048 return _parse_string(s, in);
1049 }
1051 return true;
1052 }
1053 template <typename Iter> bool parse_array_item(input<Iter> &in, size_t) {
1054 return _parse(*this, in);
1055 }
1056 bool parse_array_stop(size_t) {
1057 return true;
1058 }
1060 return true;
1061 }
1062 template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &) {
1063 return _parse(*this, in);
1064 }
1065
1066private:
1069};
1070
1071// obsolete, use the version below
1072template <typename Iter> inline std::string parse(value &out, Iter &pos, const Iter &last) {
1073 std::string err;
1074 pos = parse(out, pos, last, &err);
1075 return err;
1076}
1077
1078template <typename Context, typename Iter> inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) {
1079 input<Iter> in(first, last);
1080 if (!_parse(ctx, in) && err != NULL) {
1081 char buf[64];
1082 SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
1083 *err = buf;
1084 while (1) {
1085 int ch = in.getc();
1086 if (ch == -1 || ch == '\n') {
1087 break;
1088 } else if (ch >= ' ') {
1089 err->push_back(static_cast<char>(ch));
1090 }
1091 }
1092 }
1093 return in.cur();
1094}
1095
1096template <typename Iter> inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) {
1097 default_parse_context ctx(&out);
1098 return _parse(ctx, first, last, err);
1099}
1100
1101inline std::string parse(value &out, const std::string &s) {
1102 std::string err;
1103 parse(out, s.begin(), s.end(), &err);
1104 return err;
1105}
1106
1107inline std::string parse(value &out, std::istream &is) {
1108 std::string err;
1109 parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
1110 return err;
1111}
1112
1113template <typename T> struct last_error_t { static std::string s; };
1114template <typename T> std::string last_error_t<T>::s;
1115
1116inline void set_last_error(const std::string &s) {
1118}
1119
1120inline const std::string &get_last_error() {
1121 return last_error_t<bool>::s;
1122}
1123
1124inline bool operator==(const value &x, const value &y) {
1125 if (x.is<null>())
1126 return y.is<null>();
1127#define PICOJSON_CMP(type) \
1128 if (x.is<type>()) \
1129 return y.is<type>() && x.get<type>() == y.get<type>()
1130 PICOJSON_CMP(bool);
1131 PICOJSON_CMP(double);
1132 PICOJSON_CMP(std::string);
1134 PICOJSON_CMP(object);
1135#undef PICOJSON_CMP
1136 PICOJSON_ASSERT(0);
1137#ifdef _MSC_VER
1138 __assume(0);
1139#endif
1140 return false;
1141}
1142
1143inline bool operator!=(const value &x, const value &y) {
1144 return !(x == y);
1145}
1146}
1147
1148#if !PICOJSON_USE_RVALUE_REFERENCE
1149namespace std {
1150template <> inline void swap(picojson::value &x, picojson::value &y) {
1151 x.swap(y);
1152}
1153}
1154#endif
1155
1156inline std::istream &operator>>(std::istream &is, picojson::value &x) {
1157 picojson::set_last_error(std::string());
1158 const std::string err(picojson::parse(x, is));
1159 if (!err.empty()) {
1161 is.setstate(std::ios::failbit);
1162 }
1163 return is;
1164}
1165
1166inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) {
1167 x.serialize(std::ostream_iterator<char>(os));
1168 return os;
1169}
1170#ifdef _MSC_VER
1171#pragma warning(pop)
1172#endif
1173
1174#endif
default_parse_context(const default_parse_context &)
bool parse_string(input< Iter > &in)
Definition: picojson.h:990
bool parse_array_item(input< Iter > &in, size_t)
Definition: picojson.h:998
default_parse_context & operator=(const default_parse_context &)
bool parse_object_item(input< Iter > &in, const std::string &key)
Definition: picojson.h:1011
bool parse_object_item(input< Iter > &, const std::string &)
Definition: picojson.h:960
bool parse_string(input< Iter > &)
Definition: picojson.h:945
bool parse_array_stop(size_t)
Definition: picojson.h:954
bool parse_array_item(input< Iter > &, size_t)
Definition: picojson.h:951
int line() const
Definition: picojson.h:685
void ungetc()
Definition: picojson.h:674
void skip_ws()
Definition: picojson.h:688
input(const Iter &first, const Iter &last)
Definition: picojson.h:658
Iter cur() const
Definition: picojson.h:677
bool match(const std::string &pattern)
Definition: picojson.h:705
bool expect(const int expected)
Definition: picojson.h:697
null_parse_context(const null_parse_context &)
bool parse_array_item(input< Iter > &in, size_t)
Definition: picojson.h:1053
bool parse_array_stop(size_t)
Definition: picojson.h:1056
null_parse_context & operator=(const null_parse_context &)
bool parse_object_item(input< Iter > &in, const std::string &)
Definition: picojson.h:1062
bool parse_string(input< Iter > &in)
Definition: picojson.h:1046
std::string to_str() const
Definition: picojson.h:479
const T & get() const
void serialize(Iter os, bool prettify=false) const
Definition: picojson.h:565
bool evaluate_as_boolean() const
Definition: picojson.h:423
void set(const T &)
void swap(value &x) PICOJSON_NOEXCEPT
Definition: picojson.h:345
value(const T *)
void clear()
Definition: picojson.h:293
static void _indent(Iter os, int indent)
Definition: picojson.h:573
std::map< std::string, value > object
Definition: picojson.h:139
_storage u_
Definition: picojson.h:153
bool contains(const size_t idx) const
Definition: picojson.h:468
value & operator=(const value &x)
Definition: picojson.h:328
std::vector< value > array
Definition: picojson.h:138
void _serialize(Iter os, int indent) const
Definition: picojson.h:580
bool is() const
bool _parse_codepoint(String &out, input< Iter > &in)
Definition: picojson.h:737
void serialize_str(const std::string &s, Iter oi)
Definition: picojson.h:558
std::string parse(value &out, Iter &pos, const Iter &last)
Definition: picojson.h:1072
value::object object
Definition: picojson.h:209
bool _parse_object(Context &ctx, input< Iter > &in)
Definition: picojson.h:836
bool operator==(const value &x, const value &y)
Definition: picojson.h:1124
void set_last_error(const std::string &s)
Definition: picojson.h:1116
const std::string & get_last_error()
Definition: picojson.h:1120
std::string _parse_number(input< Iter > &in)
Definition: picojson.h:855
int _parse_quadhex(input< Iter > &in)
Definition: picojson.h:716
bool _parse_string(String &out, input< Iter > &in)
Definition: picojson.h:778
void copy(const std::string &s, Iter oi)
Definition: picojson.h:524
value::array array
Definition: picojson.h:208
@ object_type
Definition: picojson.h:125
@ number_type
Definition: picojson.h:122
@ string_type
Definition: picojson.h:123
@ null_type
Definition: picojson.h:120
@ boolean_type
Definition: picojson.h:121
@ array_type
Definition: picojson.h:124
bool _parse_array(Context &ctx, input< Iter > &in)
Definition: picojson.h:819
@ INDENT_WIDTH
Definition: picojson.h:132
bool operator!=(const value &x, const value &y)
Definition: picojson.h:1143
bool _parse(Context &ctx, input< Iter > &in)
Definition: picojson.h:875
STL namespace
void swap(picojson::value &x, picojson::value &y)
Definition: picojson.h:1150
#define PICOJSON_ASSERT(e)
Definition: picojson.h:100
#define INIT(p, v)
#define MAP(val, sym)
#define IS(ctype, jtype)
Definition: picojson.h:350
#define GET(ctype, var)
Definition: picojson.h:371
#define SNPRINTF
Definition: picojson.h:114
#define SET(ctype, jtype, setter)
Definition: picojson.h:394
std::istream & operator>>(std::istream &is, picojson::value &x)
Definition: picojson.h:1156
#define DEINIT(p)
#define PICOJSON_CMP(type)
#define PICOJSON_NOEXCEPT
Definition: picojson.h:72
std::ostream & operator<<(std::ostream &os, const picojson::value &x)
Definition: picojson.h:1166
static std::string s
Definition: picojson.h:1113
std::string * string_
Definition: picojson.h:146