2 * Copyright 2009-2010 Cybozu Labs, Inc.
3 * Copyright 2011-2014 Kazuho Oku
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
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.
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.
47 #include "common/assert.h"
50 #if __cplusplus >= 201103L
56 #elif defined(__INTEL_COMPILER)
64 #ifndef PICOJSON_USE_RVALUE_REFERENCE
65 #if (defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || \
66 (defined(_MSC_VER) && _MSC_VER >= 1600)
67 #define PICOJSON_USE_RVALUE_REFERENCE 1
69 #define PICOJSON_USE_RVALUE_REFERENCE 0
71 #endif // PICOJSON_USE_RVALUE_REFERENCE
73 #ifndef PICOJSON_NOEXCEPT
74 #if PICOJSON_USE_RVALUE_REFERENCE
75 #define PICOJSON_NOEXCEPT noexcept
77 #define PICOJSON_NOEXCEPT throw()
81 // experimental support for int64_t (see README.mkdn for detail)
82 #ifdef PICOJSON_USE_INT64
83 #define __STDC_FORMAT_MACROS
89 #define SNPRINTF _snprintf_s
91 #pragma warning(disable : 4244) // conversion from int to char
92 #pragma warning(disable : 4127) // conditional expression is constant
93 #pragma warning(disable : 4702) // unreachable code
95 #define SNPRINTF snprintf
107 #ifdef PICOJSON_USE_INT64
113 enum { INDENT_WIDTH = 2 };
119 typedef std::vector<value> array;
120 typedef std::map<std::string, value> object;
124 #ifdef PICOJSON_USE_INT64
127 std::string *string_;
138 value(int type, bool);
139 explicit value(bool b);
140 #ifdef PICOJSON_USE_INT64
141 explicit value(int64_t i);
143 explicit value(double n);
144 explicit value(const std::string &s);
145 explicit value(const array &a);
146 explicit value(const object &o);
147 #if PICOJSON_USE_RVALUE_REFERENCE
148 explicit value(std::string &&s);
149 explicit value(array &&a);
150 explicit value(object &&o);
152 explicit value(const char *s);
153 value(const char *s, size_t len);
155 value(const value &x);
156 value &operator=(const value &x);
157 #if PICOJSON_USE_RVALUE_REFERENCE
158 value(value &&x) PICOJSON_NOEXCEPT;
159 value &operator=(value &&x) PICOJSON_NOEXCEPT;
161 void swap(value &x) PICOJSON_NOEXCEPT;
162 template <typename T>
164 template <typename T>
165 const T &get() const;
166 template <typename T>
168 template <typename T>
170 #if PICOJSON_USE_RVALUE_REFERENCE
171 template <typename T>
174 bool evaluate_as_boolean() const;
175 const value &get(const size_t idx) const;
176 const value &get(const std::string &key) const;
177 value &get(const size_t idx);
178 value &get(const std::string &key);
180 bool contains(const size_t idx) const;
181 bool contains(const std::string &key) const;
182 std::string to_str() const;
183 template <typename Iter>
184 void serialize(Iter os, bool prettify = false) const;
185 std::string serialize(bool prettify = false) const;
188 template <typename T>
189 value(const T *); // intentionally defined to block implicit conversion of pointer to bool
190 template <typename Iter>
191 static void _indent(Iter os, int indent);
192 template <typename Iter>
193 void _serialize(Iter os, int indent) const;
194 std::string _serialize(int indent) const;
198 typedef value::array array;
199 typedef value::object object;
201 inline value::value() : type_(null_type), u_() {
204 inline value::value(int type, bool) : type_(type), u_() {
210 INIT(boolean_, false);
212 #ifdef PICOJSON_USE_INT64
215 INIT(string_, new std::string());
216 INIT(array_, new array());
217 INIT(object_, new object());
224 inline value::value(bool b) : type_(boolean_type), u_() {
228 #ifdef PICOJSON_USE_INT64
229 inline value::value(int64_t i) : type_(int64_type), u_() {
234 inline value::value(double n) : type_(number_type), u_() {
238 #elif __cplusplus >= 201103L
239 std::isnan(n) || std::isinf(n)
244 throw std::overflow_error("");
249 inline value::value(const std::string &s) : type_(string_type), u_() {
250 u_.string_ = new std::string(s);
253 inline value::value(const array &a) : type_(array_type), u_() {
254 u_.array_ = new array(a);
257 inline value::value(const object &o) : type_(object_type), u_() {
258 u_.object_ = new object(o);
261 #if PICOJSON_USE_RVALUE_REFERENCE
262 inline value::value(std::string &&s) : type_(string_type), u_() {
263 u_.string_ = new std::string(std::move(s));
266 inline value::value(array &&a) : type_(array_type), u_() {
267 u_.array_ = new array(std::move(a));
270 inline value::value(object &&o) : type_(object_type), u_() {
271 u_.object_ = new object(std::move(o));
275 inline value::value(const char *s) : type_(string_type), u_() {
276 u_.string_ = new std::string(s);
279 inline value::value(const char *s, size_t len) : type_(string_type), u_() {
280 u_.string_ = new std::string(s, len);
283 inline void value::clear() {
298 inline value::~value() {
302 inline value::value(const value &x) : type_(x.type_), u_() {
308 INIT(string_, new std::string(*x.u_.string_));
309 INIT(array_, new array(*x.u_.array_));
310 INIT(object_, new object(*x.u_.object_));
318 inline value &value::operator=(const value &x) {
326 #if PICOJSON_USE_RVALUE_REFERENCE
327 inline value::value(value &&x) PICOJSON_NOEXCEPT : type_(null_type), u_() {
330 inline value &value::operator=(value &&x) PICOJSON_NOEXCEPT {
335 inline void value::swap(value &x) PICOJSON_NOEXCEPT {
336 std::swap(type_, x.type_);
340 #define IS(ctype, jtype) \
342 inline bool value::is<ctype>() const { \
343 return type_ == jtype##_type; \
347 #ifdef PICOJSON_USE_INT64
350 IS(std::string, string)
355 inline bool value::is<double>() const {
356 return type_ == number_type
357 #ifdef PICOJSON_USE_INT64
358 || type_ == int64_type
363 #define GET(ctype, var) \
365 inline const ctype &value::get<ctype>() const { \
366 Assert("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
370 inline ctype &value::get<ctype>() { \
371 Assert("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
374 GET(bool, u_.boolean_)
375 GET(std::string, *u_.string_)
376 GET(array, *u_.array_)
377 GET(object, *u_.object_)
378 #ifdef PICOJSON_USE_INT64
379 GET(double, (type_ == int64_type && (const_cast<value *>(this)->type_ = number_type,
380 const_cast<value *>(this)->u_.number_ = u_.int64_),
382 GET(int64_t, u_.int64_)
384 GET(double, u_.number_)
388 #define SET(ctype, jtype, setter) \
390 inline void value::set<ctype>(const ctype &_val) { \
392 type_ = jtype##_type; \
395 SET(bool, boolean, u_.boolean_ = _val;)
396 SET(std::string, string, u_.string_ = new std::string(_val);)
397 SET(array, array, u_.array_ = new array(_val);)
398 SET(object, object, u_.object_ = new object(_val);)
399 SET(double, number, u_.number_ = _val;)
400 #ifdef PICOJSON_USE_INT64
401 SET(int64_t, int64, u_.int64_ = _val;)
405 #if PICOJSON_USE_RVALUE_REFERENCE
406 #define MOVESET(ctype, jtype, setter) \
408 inline void value::set<ctype>(ctype && _val) { \
410 type_ = jtype##_type; \
413 MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
414 MOVESET(array, array, u_.array_ = new array(std::move(_val));)
415 MOVESET(object, object, u_.object_ = new object(std::move(_val));)
419 inline bool value::evaluate_as_boolean() const {
426 return u_.number_ != 0;
427 #ifdef PICOJSON_USE_INT64
429 return u_.int64_ != 0;
432 return !u_.string_->empty();
438 inline const value &value::get(const size_t idx) const {
441 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
444 inline value &value::get(const size_t idx) {
447 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
450 inline const value &value::get(const std::string &key) const {
452 Assert(is<object>());
453 object::const_iterator i = u_.object_->find(key);
454 return i != u_.object_->end() ? i->second : s_null;
457 inline value &value::get(const std::string &key) {
459 Assert(is<object>());
460 object::iterator i = u_.object_->find(key);
461 return i != u_.object_->end() ? i->second : s_null;
464 inline bool value::contains(const size_t idx) const {
466 return idx < u_.array_->size();
469 inline bool value::contains(const std::string &key) const {
470 Assert(is<object>());
471 object::const_iterator i = u_.object_->find(key);
472 return i != u_.object_->end();
475 inline std::string value::to_str() const {
480 return u_.boolean_ ? "true" : "false";
481 #ifdef PICOJSON_USE_INT64
483 char buf[sizeof("-9223372036854775808")];
484 SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
489 std::stringstream num_str;
490 num_str.imbue(std::locale::classic());
491 num_str << std::setprecision(16) << u_.number_;
492 return num_str.str();
506 return std::string();
509 template <typename Iter>
510 void copy(const std::string &s, Iter oi) {
511 std::copy(s.begin(), s.end(), oi);
514 template <typename Iter>
515 struct serialize_str_char {
517 void operator()(char c) {
518 // C0 control characters, 00-1F
519 static const char *u_map[] = {
520 "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007",
521 "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f",
522 "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
523 "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f"};
524 // To be sure we could rewrite C1 control characters also (first decode UTF-8, check, then map
526 // \u sequence), but for now chromium allows C1 in JSON.parse
538 if ((unsigned char)c < 0x20) {
539 const char *u = u_map[(unsigned char)c];
551 template <typename Iter>
552 void serialize_str(const std::string &s, Iter oi) {
554 serialize_str_char<Iter> process_char = {oi};
555 std::for_each(s.begin(), s.end(), process_char);
559 template <typename Iter>
560 void value::serialize(Iter oi, bool prettify) const {
561 return _serialize(oi, prettify ? 0 : -1);
564 inline std::string value::serialize(bool prettify) const {
565 return _serialize(prettify ? 0 : -1);
568 template <typename Iter>
569 void value::_indent(Iter oi, int indent) {
571 for (int i = 0; i < indent * INDENT_WIDTH; ++i) {
576 template <typename Iter>
577 void value::_serialize(Iter oi, int indent) const {
580 serialize_str(*u_.string_, oi);
587 for (array::const_iterator i = u_.array_->begin(); i != u_.array_->end(); ++i) {
588 if (i != u_.array_->begin()) {
594 i->_serialize(oi, indent);
598 if (!u_.array_->empty()) {
610 for (object::const_iterator i = u_.object_->begin(); i != u_.object_->end(); ++i) {
611 if (i != u_.object_->begin()) {
617 serialize_str(i->first, oi);
622 i->second._serialize(oi, indent);
626 if (!u_.object_->empty()) {
642 inline std::string value::_serialize(int indent) const {
644 _serialize(std::back_inserter(s), indent);
648 template <typename Iter>
656 input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1) {
677 input<Iter> *self = const_cast<input<Iter> *>(this);
678 self->consumed_ = false;
689 if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
695 bool expect(const int expected) {
697 if (getc() != expected) {
703 bool match(const std::string &pattern) {
704 for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
714 template <typename Iter>
715 inline int _parse_quadhex(input<Iter> &in) {
717 for (int i = 0; i < 4; i++) {
718 if ((hex = in.getc()) == -1) {
721 if ('0' <= hex && hex <= '9') {
723 } else if ('A' <= hex && hex <= 'F') {
725 } else if ('a' <= hex && hex <= 'f') {
731 uni_ch = uni_ch * 16 + hex;
736 template <typename String, typename Iter>
737 inline bool _parse_codepoint(String &out, input<Iter> &in) {
739 if ((uni_ch = _parse_quadhex(in)) == -1) {
742 if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
743 if (0xdc00 <= uni_ch) {
744 // a second 16-bit of a surrogate pair appeared
747 // first 16-bit of surrogate pair, get the next one
748 if (in.getc() != '\\' || in.getc() != 'u') {
752 int second = _parse_quadhex(in);
753 if (!(0xdc00 <= second && second <= 0xdfff)) {
756 uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
760 out.push_back(static_cast<char>(uni_ch));
762 if (uni_ch < 0x800) {
763 out.push_back(static_cast<char>(0xc0 | (uni_ch >> 6)));
765 if (uni_ch < 0x10000) {
766 out.push_back(static_cast<char>(0xe0 | (uni_ch >> 12)));
768 out.push_back(static_cast<char>(0xf0 | (uni_ch >> 18)));
769 out.push_back(static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));
771 out.push_back(static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));
773 out.push_back(static_cast<char>(0x80 | (uni_ch & 0x3f)));
778 template <typename String, typename Iter>
779 inline bool _parse_string(String &out, input<Iter> &in) {
785 } else if (ch == '"') {
787 } else if (ch == '\\') {
788 if ((ch = in.getc()) == -1) {
792 #define MAP(sym, val) \
794 out.push_back(val); \
806 if (!_parse_codepoint(out, in)) {
814 out.push_back(static_cast<char>(ch));
820 template <typename Context, typename Iter>
821 inline bool _parse_array(Context &ctx, input<Iter> &in) {
822 if (!ctx.parse_array_start()) {
826 if (in.expect(']')) {
827 return ctx.parse_array_stop(idx);
830 if (!ctx.parse_array_item(in, idx)) {
834 } while (in.expect(','));
835 return in.expect(']') && ctx.parse_array_stop(idx);
838 template <typename Context, typename Iter>
839 inline bool _parse_object(Context &ctx, input<Iter> &in) {
840 if (!ctx.parse_object_start()) {
843 if (in.expect('}')) {
848 if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
851 if (!ctx.parse_object_item(in, key)) {
854 } while (in.expect(','));
855 return in.expect('}');
858 template <typename Iter>
859 inline std::string _parse_number(input<Iter> &in) {
860 std::stringstream num_str;
861 num_str.imbue(std::locale::classic());
865 if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E' || ch == '.') {
873 return num_str.str();
876 template <typename Context, typename Iter>
877 inline bool _parse(Context &ctx, input<Iter> &in) {
881 #define IS(ch, text, op) \
883 if (in.match(text) && op) { \
888 IS('n', "ull", ctx.set_null());
889 IS('f', "alse", ctx.set_bool(false));
890 IS('t', "rue", ctx.set_bool(true));
893 return ctx.parse_string(in);
895 return _parse_array(ctx, in);
897 return _parse_object(ctx, in);
899 if (('0' <= ch && ch <= '9') || ch == '-') {
903 std::string num_str(_parse_number(in));
904 if (num_str.empty()) {
907 #ifdef PICOJSON_USE_INT64
910 intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
911 if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival &&
912 ival <= std::numeric_limits<int64_t>::max() &&
913 endp == num_str.c_str() + num_str.size()) {
919 locale_t loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
920 f = strtod_l(num_str.c_str(), &endp, loc);
922 if (endp == num_str.c_str() + num_str.size()) {
934 class deny_parse_context {
939 bool set_bool(bool) {
942 #ifdef PICOJSON_USE_INT64
943 bool set_int64(int64_t) {
947 bool set_number(double) {
950 template <typename Iter>
951 bool parse_string(input<Iter> &) {
954 bool parse_array_start() {
957 template <typename Iter>
958 bool parse_array_item(input<Iter> &, size_t) {
961 bool parse_array_stop(size_t) {
964 bool parse_object_start() {
967 template <typename Iter>
968 bool parse_object_item(input<Iter> &, const std::string &) {
973 class default_parse_context {
978 default_parse_context(value *out) : out_(out) {
984 bool set_bool(bool b) {
988 #ifdef PICOJSON_USE_INT64
989 bool set_int64(int64_t i) {
994 bool set_number(double f) {
998 template <typename Iter>
999 bool parse_string(input<Iter> &in) {
1000 *out_ = value(string_type, false);
1001 return _parse_string(out_->get<std::string>(), in);
1003 bool parse_array_start() {
1004 *out_ = value(array_type, false);
1007 template <typename Iter>
1008 bool parse_array_item(input<Iter> &in, size_t) {
1009 array &a = out_->get<array>();
1010 a.push_back(value());
1011 default_parse_context ctx(&a.back());
1012 return _parse(ctx, in);
1014 bool parse_array_stop(size_t) {
1017 bool parse_object_start() {
1018 *out_ = value(object_type, false);
1021 template <typename Iter>
1022 bool parse_object_item(input<Iter> &in, const std::string &key) {
1023 object &o = out_->get<object>();
1024 default_parse_context ctx(&o[key]);
1025 return _parse(ctx, in);
1029 default_parse_context(const default_parse_context &);
1030 default_parse_context &operator=(const default_parse_context &);
1033 class null_parse_context {
1036 void push_back(int) {
1041 null_parse_context() {
1046 bool set_bool(bool) {
1049 #ifdef PICOJSON_USE_INT64
1050 bool set_int64(int64_t) {
1054 bool set_number(double) {
1057 template <typename Iter>
1058 bool parse_string(input<Iter> &in) {
1060 return _parse_string(s, in);
1062 bool parse_array_start() {
1065 template <typename Iter>
1066 bool parse_array_item(input<Iter> &in, size_t) {
1067 return _parse(*this, in);
1069 bool parse_array_stop(size_t) {
1072 bool parse_object_start() {
1075 template <typename Iter>
1076 bool parse_object_item(input<Iter> &in, const std::string &) {
1077 return _parse(*this, in);
1081 null_parse_context(const null_parse_context &);
1082 null_parse_context &operator=(const null_parse_context &);
1085 // obsolete, use the version below
1086 template <typename Iter>
1087 inline std::string parse(value &out, Iter &pos, const Iter &last) {
1089 pos = parse(out, pos, last, &err);
1093 template <typename Context, typename Iter>
1094 inline Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err) {
1095 input<Iter> in(first, last);
1096 if (!_parse(ctx, in) && err != NULL) {
1098 SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
1102 if (ch == -1 || ch == '\n') {
1104 } else if (ch >= ' ') {
1105 err->push_back(static_cast<char>(ch));
1112 template <typename Iter>
1113 inline Iter parse(value &out, const Iter &first, const Iter &last, std::string *err) {
1114 default_parse_context ctx(&out);
1115 return _parse(ctx, first, last, err);
1118 inline std::string parse(value &out, const std::string &s) {
1120 parse(out, s.begin(), s.end(), &err);
1124 inline std::string parse(value &out, std::istream &is) {
1126 parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
1130 template <typename T>
1131 struct last_error_t {
1132 static std::string s;
1134 template <typename T>
1135 std::string last_error_t<T>::s;
1137 inline void set_last_error(const std::string &s) {
1138 last_error_t<bool>::s = s;
1141 inline const std::string &get_last_error() {
1142 return last_error_t<bool>::s;
1145 inline bool operator==(const value &x, const value &y) {
1146 if (x.is<null>()) return y.is<null>();
1147 #define PICOJSON_CMP(type) \
1148 if (x.is<type>()) return y.is<type>() && x.get<type>() == y.get<type>()
1150 PICOJSON_CMP(double);
1151 PICOJSON_CMP(std::string);
1152 PICOJSON_CMP(array);
1153 PICOJSON_CMP(object);
1162 inline bool operator!=(const value &x, const value &y) {
1167 #if !PICOJSON_USE_RVALUE_REFERENCE
1170 inline void swap(picojson::value &x, picojson::value &y) {
1176 inline std::istream &operator>>(std::istream &is, picojson::value &x) {
1177 picojson::set_last_error(std::string());
1178 const std::string err(picojson::parse(x, is));
1180 picojson::set_last_error(err);
1181 is.setstate(std::ios::failbit);
1186 inline std::ostream &operator<<(std::ostream &os, const picojson::value &x) {
1187 x.serialize(std::ostream_iterator<char>(os));
1191 #pragma warning(pop)