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.
46 #if __cplusplus >= 201103L
53 #elif defined(__INTEL_COMPILER)
61 #ifndef PICOJSON_USE_RVALUE_REFERENCE
62 #if(defined(__cpp_rvalue_references) && __cpp_rvalue_references >= 200610) || (defined(_MSC_VER) && _MSC_VER >= 1600)
63 #define PICOJSON_USE_RVALUE_REFERENCE 1
65 #define PICOJSON_USE_RVALUE_REFERENCE 0
67 #endif //PICOJSON_USE_RVALUE_REFERENCE
69 // experimental support for int64_t (see README.mkdn for detail)
70 #ifdef PICOJSON_USE_INT64
71 #define __STDC_FORMAT_MACROS
76 // to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0
77 #ifndef PICOJSON_USE_LOCALE
78 #define PICOJSON_USE_LOCALE 1
80 #if PICOJSON_USE_LOCALE
87 #ifndef PICOJSON_ASSERT
88 #define PICOJSON_ASSERT(e) \
91 if(!(e)) throw std::runtime_error(#e); \
96 #define SNPRINTF _snprintf_s
98 #pragma warning(disable : 4244) // conversion from int to char
99 #pragma warning(disable : 4127) // conditional expression is constant
100 #pragma warning(disable : 4702) // unreachable code
102 #define SNPRINTF snprintf
115 #ifdef PICOJSON_USE_INT64
133 typedef std::vector<value> array;
134 typedef std::map<std::string, value> object;
139 #ifdef PICOJSON_USE_INT64
142 std::string* string_;
153 value(int type, bool);
154 explicit value(bool b);
155 #ifdef PICOJSON_USE_INT64
156 explicit value(int64_t i);
158 explicit value(double n);
159 explicit value(const std::string& s);
160 explicit value(const array& a);
161 explicit value(const object& o);
162 explicit value(const char* s);
163 value(const char* s, size_t len);
165 value(const value& x);
166 value& operator=(const value& x);
167 #if PICOJSON_USE_RVALUE_REFERENCE
168 value(value&& x) throw();
169 value& operator=(value&& x) throw();
171 void swap(value& x) throw();
175 const T& get() const;
180 #if PICOJSON_USE_RVALUE_REFERENCE
184 bool evaluate_as_boolean() const;
185 const value& get(size_t idx) const;
186 const value& get(const std::string& key) const;
187 value& get(size_t idx);
188 value& get(const std::string& key);
190 bool contains(size_t idx) const;
191 bool contains(const std::string& key) const;
192 std::string to_str() const;
193 template<typename Iter>
194 void serialize(Iter os, bool prettify = false) const;
195 std::string serialize(bool prettify = false) const;
199 value(const T*); // intentionally defined to block implicit conversion of pointer to bool
200 template<typename Iter>
201 static void _indent(Iter os, int indent);
202 template<typename Iter>
203 void _serialize(Iter os, int indent) const;
204 std::string _serialize(int indent) const;
208 typedef value::array array;
209 typedef value::object object;
211 inline value::value()
216 inline value::value(int type, bool)
225 INIT(boolean_, false);
227 #ifdef PICOJSON_USE_INT64
230 INIT(string_, new std::string());
231 INIT(array_, new array());
232 INIT(object_, new object());
239 inline value::value(bool b)
240 : type_(boolean_type)
245 #ifdef PICOJSON_USE_INT64
246 inline value::value(int64_t i)
253 inline value::value(double n)
259 #elif __cplusplus >= 201103L || !(defined(isnan) && defined(isinf))
260 std::isnan(n) || std::isinf(n)
266 throw std::overflow_error("");
271 inline value::value(const std::string& s)
274 u_.string_ = new std::string(s);
277 inline value::value(const array& a)
280 u_.array_ = new array(a);
283 inline value::value(const object& o)
286 u_.object_ = new object(o);
289 inline value::value(const char* s)
292 u_.string_ = new std::string(s);
295 inline value::value(const char* s, size_t len)
298 u_.string_ = new std::string(s, len);
301 inline void value::clear()
318 inline value::~value()
323 inline value::value(const value& x)
332 INIT(string_, new std::string(*x.u_.string_));
333 INIT(array_, new array(*x.u_.array_));
334 INIT(object_, new object(*x.u_.object_));
342 inline value& value::operator=(const value& x)
352 #if PICOJSON_USE_RVALUE_REFERENCE
353 inline value::value(value&& x) throw()
358 inline value& value::operator=(value&& x) throw()
364 inline void value::swap(value& x) throw()
366 std::swap(type_, x.type_);
370 #define IS(ctype, jtype) \
372 inline bool value::is<ctype>() const \
374 return type_ == jtype##_type; \
378 #ifdef PICOJSON_USE_INT64
381 IS(std::string, string)
386 inline bool value::is<double>() const
388 return type_ == number_type
389 #ifdef PICOJSON_USE_INT64
390 || type_ == int64_type
395 #define GET(ctype, var) \
397 inline const ctype& value::get<ctype>() const \
399 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
403 inline ctype& value::get<ctype>() \
405 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
408 GET(bool, u_.boolean_)
409 GET(std::string, *u_.string_)
410 GET(array, *u_.array_)
411 GET(object, *u_.object_)
412 #ifdef PICOJSON_USE_INT64
413 GET(double, (type_ == int64_type && (const_cast<value*>(this)->type_ = number_type, const_cast<value*>(this)->u_.number_ = u_.int64_), u_.number_))
414 GET(int64_t, u_.int64_)
416 GET(double, u_.number_)
420 #define SET(ctype, jtype, setter) \
422 inline void value::set<ctype>(const ctype& _val) \
425 type_ = jtype##_type; \
428 SET(bool, boolean, u_.boolean_ = _val;)
429 SET(std::string, string, u_.string_ = new std::string(_val);)
430 SET(array, array, u_.array_ = new array(_val);)
431 SET(object, object, u_.object_ = new object(_val);)
432 SET(double, number, u_.number_ = _val;)
433 #ifdef PICOJSON_USE_INT64
434 SET(int64_t, int64, u_.int64_ = _val;)
438 #if PICOJSON_USE_RVALUE_REFERENCE
439 #define MOVESET(ctype, jtype, setter) \
441 inline void value::set<ctype>(ctype && _val) \
444 type_ = jtype##_type; \
447 MOVESET(std::string, string, u_.string_ = new std::string(std::move(_val));)
448 MOVESET(array, array, u_.array_ = new array(std::move(_val));)
449 MOVESET(object, object, u_.object_ = new object(std::move(_val));)
453 inline bool value::evaluate_as_boolean() const
462 return u_.number_ != 0;
463 #ifdef PICOJSON_USE_INT64
465 return u_.int64_ != 0;
468 return !u_.string_->empty();
474 inline const value& value::get(size_t idx) const
477 PICOJSON_ASSERT(is<array>());
478 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
481 inline value& value::get(size_t idx)
484 PICOJSON_ASSERT(is<array>());
485 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
488 inline const value& value::get(const std::string& key) const
491 PICOJSON_ASSERT(is<object>());
492 object::const_iterator i = u_.object_->find(key);
493 return i != u_.object_->end() ? i->second : s_null;
496 inline value& value::get(const std::string& key)
499 PICOJSON_ASSERT(is<object>());
500 object::iterator i = u_.object_->find(key);
501 return i != u_.object_->end() ? i->second : s_null;
504 inline bool value::contains(size_t idx) const
506 PICOJSON_ASSERT(is<array>());
507 return idx < u_.array_->size();
510 inline bool value::contains(const std::string& key) const
512 PICOJSON_ASSERT(is<object>());
513 object::const_iterator i = u_.object_->find(key);
514 return i != u_.object_->end();
517 inline std::string value::to_str() const
524 return u_.boolean_ ? "true" : "false";
525 #ifdef PICOJSON_USE_INT64
528 char buf[sizeof("-9223372036854775808")];
529 SNPRINTF(buf, sizeof(buf), "%" PRId64, u_.int64_);
537 SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
538 #if PICOJSON_USE_LOCALE
539 char* decimal_point = localeconv()->decimal_point;
540 if(strcmp(decimal_point, ".") != 0)
542 size_t decimal_point_len = strlen(decimal_point);
543 for(char* p = buf; *p != '\0'; ++p)
545 if(strncmp(p, decimal_point, decimal_point_len) == 0)
547 return std::string(buf, p) + "." + (p + decimal_point_len);
566 return std::string();
569 template<typename Iter>
570 void copy(const std::string& s, Iter oi)
572 std::copy(s.begin(), s.end(), oi);
575 template<typename Iter>
576 struct serialize_str_char
579 void operator()(char c)
583 #define MAP(val, sym) \
597 if(static_cast<unsigned char>(c) < 0x20 || c == 0x7f)
600 SNPRINTF(buf, sizeof(buf), "\\u%04x", c & 0xff);
601 copy(buf, buf + 6, oi);
612 template<typename Iter>
613 void serialize_str(const std::string& s, Iter oi)
616 serialize_str_char<Iter> process_char = {oi};
617 std::for_each(s.begin(), s.end(), process_char);
621 template<typename Iter>
622 void value::serialize(Iter oi, bool prettify) const
624 return _serialize(oi, prettify ? 0 : -1);
627 inline std::string value::serialize(bool prettify) const
629 return _serialize(prettify ? 0 : -1);
632 template<typename Iter>
633 void value::_indent(Iter oi, int indent)
636 for(int i = 0; i < indent * INDENT_WIDTH; ++i)
642 template<typename Iter>
643 void value::_serialize(Iter oi, int indent) const
648 serialize_str(*u_.string_, oi);
657 for(array::const_iterator i = u_.array_->begin();
658 i != u_.array_->end();
661 if(i != u_.array_->begin())
669 i->_serialize(oi, indent);
674 if(!u_.array_->empty())
689 for(object::const_iterator i = u_.object_->begin();
690 i != u_.object_->end();
693 if(i != u_.object_->begin())
701 serialize_str(i->first, oi);
707 i->second._serialize(oi, indent);
712 if(!u_.object_->empty())
730 inline std::string value::_serialize(int indent) const
733 _serialize(std::back_inserter(s), indent);
737 template<typename Iter>
746 input(const Iter& first, const Iter& last)
779 input<Iter>* self = const_cast<input<Iter>*>(this);
780 self->consumed_ = false;
794 if(!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'))
801 bool expect(int expect)
811 bool match(const std::string& pattern)
813 for(std::string::const_iterator pi(pattern.begin());
827 template<typename Iter>
828 inline int _parse_quadhex(input<Iter>& in)
831 for(int i = 0; i < 4; i++)
833 if((hex = in.getc()) == -1)
837 if('0' <= hex && hex <= '9')
841 else if('A' <= hex && hex <= 'F')
845 else if('a' <= hex && hex <= 'f')
854 uni_ch = uni_ch * 16 + hex;
859 template<typename String, typename Iter>
860 inline bool _parse_codepoint(String& out, input<Iter>& in)
863 if((uni_ch = _parse_quadhex(in)) == -1)
867 if(0xd800 <= uni_ch && uni_ch <= 0xdfff)
871 // a second 16-bit of a surrogate pair appeared
874 // first 16-bit of surrogate pair, get the next one
875 if(in.getc() != '\\' || in.getc() != 'u')
880 int second = _parse_quadhex(in);
881 if(!(0xdc00 <= second && second <= 0xdfff))
885 uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
890 out.push_back(uni_ch);
896 out.push_back(0xc0 | (uni_ch >> 6));
902 out.push_back(0xe0 | (uni_ch >> 12));
906 out.push_back(0xf0 | (uni_ch >> 18));
907 out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
909 out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
911 out.push_back(0x80 | (uni_ch & 0x3f));
916 template<typename String, typename Iter>
917 inline bool _parse_string(String& out, input<Iter>& in)
933 if((ch = in.getc()) == -1)
939 #define MAP(sym, val) \
941 out.push_back(val); \
953 if(!_parse_codepoint(out, in))
970 template<typename Context, typename Iter>
971 inline bool _parse_array(Context& ctx, input<Iter>& in)
973 if(!ctx.parse_array_start())
980 return ctx.parse_array_stop(idx);
984 if(!ctx.parse_array_item(in, idx))
989 } while(in.expect(','));
990 return in.expect(']') && ctx.parse_array_stop(idx);
993 template<typename Context, typename Iter>
994 inline bool _parse_object(Context& ctx, input<Iter>& in)
996 if(!ctx.parse_object_start())
1007 if(!in.expect('"') || !_parse_string(key, in) || !in.expect(':'))
1011 if(!ctx.parse_object_item(in, key))
1015 } while(in.expect(','));
1016 return in.expect('}');
1019 template<typename Iter>
1020 inline std::string _parse_number(input<Iter>& in)
1022 std::string num_str;
1026 if(('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E')
1028 num_str.push_back(ch);
1032 #if PICOJSON_USE_LOCALE
1033 num_str += localeconv()->decimal_point;
1035 num_str.push_back('.');
1047 template<typename Context, typename Iter>
1048 inline bool _parse(Context& ctx, input<Iter>& in)
1054 #define IS(ch, text, op) \
1056 if(in.match(text) && op) \
1064 IS('n', "ull", ctx.set_null());
1065 IS('f', "alse", ctx.set_bool(false));
1066 IS('t', "rue", ctx.set_bool(true));
1069 return ctx.parse_string(in);
1071 return _parse_array(ctx, in);
1073 return _parse_object(ctx, in);
1075 if(('0' <= ch && ch <= '9') || ch == '-')
1080 std::string num_str = _parse_number(in);
1085 #ifdef PICOJSON_USE_INT64
1088 intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
1089 if(errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() && endp == num_str.c_str() + num_str.size())
1091 ctx.set_int64(ival);
1096 f = strtod(num_str.c_str(), &endp);
1097 if(endp == num_str.c_str() + num_str.size())
1110 class deny_parse_context
1121 #ifdef PICOJSON_USE_INT64
1122 bool set_int64(int64_t)
1127 bool set_number(double)
1131 template<typename Iter>
1132 bool parse_string(input<Iter>&)
1136 bool parse_array_start()
1140 template<typename Iter>
1141 bool parse_array_item(input<Iter>&, size_t)
1145 bool parse_array_stop(size_t)
1149 bool parse_object_start()
1153 template<typename Iter>
1154 bool parse_object_item(input<Iter>&, const std::string&)
1160 class default_parse_context
1166 default_parse_context(value* out)
1175 bool set_bool(bool b)
1180 #ifdef PICOJSON_USE_INT64
1181 bool set_int64(int64_t i)
1187 bool set_number(double f)
1192 template<typename Iter>
1193 bool parse_string(input<Iter>& in)
1195 *out_ = value(string_type, false);
1196 return _parse_string(out_->get<std::string>(), in);
1198 bool parse_array_start()
1200 *out_ = value(array_type, false);
1203 template<typename Iter>
1204 bool parse_array_item(input<Iter>& in, size_t)
1206 array& a = out_->get<array>();
1207 a.push_back(value());
1208 default_parse_context ctx(&a.back());
1209 return _parse(ctx, in);
1211 bool parse_array_stop(size_t)
1215 bool parse_object_start()
1217 *out_ = value(object_type, false);
1220 template<typename Iter>
1221 bool parse_object_item(input<Iter>& in, const std::string& key)
1223 object& o = out_->get<object>();
1224 default_parse_context ctx(&o[key]);
1225 return _parse(ctx, in);
1229 default_parse_context(const default_parse_context&);
1230 default_parse_context& operator=(const default_parse_context&);
1233 class null_parse_context
1244 null_parse_context()
1255 #ifdef PICOJSON_USE_INT64
1256 bool set_int64(int64_t)
1261 bool set_number(double)
1265 template<typename Iter>
1266 bool parse_string(input<Iter>& in)
1269 return _parse_string(s, in);
1271 bool parse_array_start()
1275 template<typename Iter>
1276 bool parse_array_item(input<Iter>& in, size_t)
1278 return _parse(*this, in);
1280 bool parse_array_stop(size_t)
1284 bool parse_object_start()
1288 template<typename Iter>
1289 bool parse_object_item(input<Iter>& in, const std::string&)
1291 return _parse(*this, in);
1295 null_parse_context(const null_parse_context&);
1296 null_parse_context& operator=(const null_parse_context&);
1299 // obsolete, use the version below
1300 template<typename Iter>
1301 inline std::string parse(value& out, Iter& pos, const Iter& last)
1304 pos = parse(out, pos, last, &err);
1308 template<typename Context, typename Iter>
1309 inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err)
1311 input<Iter> in(first, last);
1312 if(!_parse(ctx, in) && err != NULL)
1315 SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
1320 if(ch == -1 || ch == '\n')
1333 template<typename Iter>
1334 inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err)
1336 default_parse_context ctx(&out);
1337 return _parse(ctx, first, last, err);
1340 inline std::string parse(value& out, const std::string& s)
1343 parse(out, s.begin(), s.end(), &err);
1347 inline std::string parse(value& out, std::istream& is)
1350 parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
1354 template<typename T>
1357 static std::string s;
1359 template<typename T>
1360 std::string last_error_t<T>::s;
1362 inline void set_last_error(const std::string& s)
1364 last_error_t<bool>::s = s;
1367 inline const std::string& get_last_error()
1369 return last_error_t<bool>::s;
1372 inline bool operator==(const value& x, const value& y)
1375 return y.is<null>();
1376 #define PICOJSON_CMP(type) \
1378 return y.is<type>() && x.get<type>() == y.get<type>()
1380 PICOJSON_CMP(double);
1381 PICOJSON_CMP(std::string);
1382 PICOJSON_CMP(array);
1383 PICOJSON_CMP(object);
1392 inline bool operator!=(const value& x, const value& y)
1396 } // namespace picojson
1398 #if !PICOJSON_USE_RVALUE_REFERENCE
1402 inline void swap(picojson::value& x, picojson::value& y)
1409 inline std::istream& operator>>(std::istream& is, picojson::value& x)
1411 picojson::set_last_error(std::string());
1412 std::string err = picojson::parse(x, is);
1415 picojson::set_last_error(err);
1416 is.setstate(std::ios::failbit);
1421 inline std::ostream& operator<<(std::ostream& os, const picojson::value& x)
1423 x.serialize(std::ostream_iterator<char>(os));
1427 #pragma warning(pop)