45#if __cplusplus>=201103L
51# elif defined(__INTEL_COMPILER)
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
64# define PICOJSON_USE_RVALUE_REFERENCE 0
70#ifndef PICOJSON_USE_INT64
71#define PICOJSON_USE_INT64 1
73#ifdef PICOJSON_USE_INT64
74# define __STDC_FORMAT_MACROS
80#ifndef PICOJSON_USE_LOCALE
81# define PICOJSON_USE_LOCALE 0
83#if PICOJSON_USE_LOCALE
91#ifndef PICOJSON_USE_ASSERT
92# define PICOJSON_USE_ASSERT 0
94#if PICOJSON_USE_ASSERT
95# define PICOJSON_ASSERT(e) do { if (! (e)) throw std::runtime_error(#e); } while (0)
97# define PICOJSON_ASSERT(e)
101 #define SNPRINTF _snprintf_s
102 #pragma warning(push)
103 #pragma warning(disable : 4244)
104 #pragma warning(disable : 4127)
105 #pragma warning(disable : 4702)
107 #define SNPRINTF snprintf
123#ifdef PICOJSON_USE_INT64
136 typedef std::vector<value> array;
137 typedef std::map<std::string, value> object;
141#ifdef PICOJSON_USE_INT64
144 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();
172 template <
typename T>
bool is()
const;
173 template <
typename T>
const T& get()
const;
174 template <
typename T> T& get();
175 bool evaluate_as_boolean()
const;
176 const value& get(
size_t idx)
const;
177 const value& get(
const std::string& key)
const;
178 value& get(
size_t idx);
179 value& get(
const std::string& key);
181 bool contains(
size_t idx)
const;
182 bool contains(
const std::string& key)
const;
183 std::string to_str()
const;
184 template <
typename Iter>
void serialize(Iter os,
bool prettify =
false)
const;
185 std::string serialize(
bool prettify =
false)
const;
187 template <
typename T> value(
const T*);
188 template <
typename Iter>
static void _indent(Iter os,
int indent);
189 template <
typename Iter>
void _serialize(Iter os,
int indent)
const;
190 std::string _serialize(
int indent)
const;
193 typedef value::array array;
194 typedef value::object object;
196 inline value::value() : type_(null_type) {}
198 inline value::value(
int type,
bool) : type_(type) {
200#define INIT(p, v) case p##type: u_.p = v; break
201 INIT(boolean_,
false);
203#ifdef PICOJSON_USE_INT64
206 INIT(string_,
new std::string());
207 INIT(array_,
new array());
208 INIT(object_,
new object());
214 inline value::value(
bool b) : type_(boolean_type) {
218#ifdef PICOJSON_USE_INT64
219 inline value::value(int64_t i) : type_(int64_type) {
224 inline value::value(
double n) : type_(number_type) {
228#elif __cplusplus>=201103L || !(defined(isnan) && defined(isinf))
229 std::isnan(n) || std::isinf(n)
239 inline value::value(
const std::string& s) : type_(string_type) {
240 u_.string_ =
new std::string(s);
243 inline value::value(
const array& a) : type_(array_type) {
244 u_.array_ =
new array(a);
247 inline value::value(
const object& o) : type_(object_type) {
248 u_.object_ =
new object(o);
251 inline value::value(
const char* s) : type_(string_type) {
252 u_.string_ =
new std::string(s);
255 inline value::value(
const char* s,
size_t len) : type_(string_type) {
256 u_.string_ =
new std::string(s, len);
259 inline value::~value() {
261#define DEINIT(p) case p##type: delete u_.p; break
270 inline value::value(
const value& x) : type_(x.type_) {
272#define INIT(p, v) case p##type: u_.p = v; break
273 INIT(string_,
new std::string(*x.u_.string_));
274 INIT(array_,
new array(*x.u_.array_));
275 INIT(object_,
new object(*x.u_.object_));
283 inline value& value::operator=(
const value& x) {
291#if PICOJSON_USE_RVALUE_REFERENCE
292 inline value::value(value&& x)
throw() : type_(null_type) {
295 inline value& value::operator=(value&& x)
throw() {
300 inline void value::swap(value& x)
throw() {
301 std::swap(type_, x.type_);
305#define IS(ctype, jtype) \
306 template <> inline bool value::is<ctype>() const { \
307 return type_ == jtype##_type; \
311#ifdef PICOJSON_USE_INT64
314 IS(std::string,
string)
318 template <>
inline bool value::is<double>()
const {
319 return type_ == number_type
320#ifdef PICOJSON_USE_INT64
321 || type_ == int64_type
326#define GET(ctype, var) \
327 template <> inline const ctype& value::get<ctype>() const { \
328 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
332 template <> inline ctype& value::get<ctype>() { \
333 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" \
337 GET(
bool, u_.boolean_)
338 GET(std::
string, *u_.string_)
339 GET(array, *u_.array_)
340 GET(
object, *u_.object_)
341#ifdef PICOJSON_USE_INT64
342 GET(
double, (type_ == int64_type && (
const_cast<value*
>(
this)->type_ = number_type,
const_cast<value*
>(
this)->u_.number_ = u_.int64_), u_.number_))
343 GET(int64_t, u_.int64_)
345 GET(
double, u_.number_)
349 inline bool value::evaluate_as_boolean()
const {
356 return u_.number_ != 0;
357#ifdef PICOJSON_USE_INT64
359 return u_.int64_ != 0;
362 return ! u_.string_->empty();
368 inline const value& value::get(
size_t idx)
const {
370 PICOJSON_ASSERT(is<array>());
371 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
374 inline value& value::get(
size_t idx) {
376 PICOJSON_ASSERT(is<array>());
377 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
380 inline const value& value::get(
const std::string& key)
const {
382 PICOJSON_ASSERT(is<object>());
383 object::const_iterator i = u_.object_->find(key);
384 return i != u_.object_->end() ? i->second : s_null;
387 inline value& value::get(
const std::string& key) {
389 PICOJSON_ASSERT(is<object>());
390 object::iterator i = u_.object_->find(key);
391 return i != u_.object_->end() ? i->second : s_null;
394 inline bool value::contains(
size_t idx)
const {
395 PICOJSON_ASSERT(is<array>());
396 return idx < u_.array_->size();
399 inline bool value::contains(
const std::string& key)
const {
400 PICOJSON_ASSERT(is<object>());
401 object::const_iterator i = u_.object_->find(key);
402 return i != u_.object_->end();
407 inline std::string value::to_str()
const {
409 case null_type:
return "null";
410 case boolean_type:
return u_.boolean_ ?
"true" :
"false";
411#ifdef PICOJSON_USE_INT64
413 char buf[
sizeof(
"-9223372036854775808")];
414 SNPRINTF(buf,
sizeof(buf),
"%" PRId64, u_.int64_);
421 SNPRINTF(buf,
sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ?
"%.f" :
"%.17g", u_.number_);
422#if PICOJSON_USE_LOCALE
423 char *decimal_point = localeconv()->decimal_point;
424 if (strcmp(decimal_point,
".") != 0) {
425 size_t decimal_point_len = strlen(decimal_point);
426 for (
char *p = buf; *p !=
'\0'; ++p) {
427 if (strncmp(p, decimal_point, decimal_point_len) == 0) {
428 return std::string(buf, p) +
"." + (p + decimal_point_len);
435 case string_type:
return *u_.string_;
436 case array_type:
return "array";
437 case object_type:
return "object";
438 default: PICOJSON_ASSERT(0);
443 return std::string();
446 template <
typename Iter>
void copy(
const std::string& s, Iter oi) {
447 std::copy(s.begin(), s.end(), oi);
450 template <
typename Iter>
451 struct serialize_str_char {
453 void operator()(
char c) {
455#define MAP(val, sym) case val: copy(sym, oi); break
466 if (
static_cast<unsigned char>(c) < 0x20 || c == 0x7f) {
468 SNPRINTF(buf,
sizeof(buf),
"\\u%04x", c & 0xff);
469 copy(buf, buf + 6, oi);
478 template <
typename Iter>
void serialize_str(
const std::string& s, Iter oi) {
480 serialize_str_char<Iter> process_char = { oi };
481 std::for_each(s.begin(), s.end(), process_char);
485 template <
typename Iter>
void value::serialize(Iter oi,
bool prettify)
const {
486 return _serialize(oi, prettify ? 0 : -1);
489 inline std::string value::serialize(
bool prettify)
const {
490 return _serialize(prettify ? 0 : -1);
493 template <
typename Iter>
void value::_indent(Iter oi,
int indent) {
495 for (
int i = 0; i < indent * INDENT_WIDTH; ++i) {
500 template <
typename Iter>
void value::_serialize(Iter oi,
int indent)
const {
503 serialize_str(*u_.string_, oi);
510 for (array::const_iterator i = u_.array_->begin();
511 i != u_.array_->end();
513 if (i != u_.array_->begin()) {
519 i->_serialize(oi, indent);
523 if (! u_.array_->empty()) {
535 for (object::const_iterator i = u_.object_->begin();
536 i != u_.object_->end();
538 if (i != u_.object_->begin()) {
544 serialize_str(i->first, oi);
549 i->second._serialize(oi, indent);
553 if (! u_.object_->empty()) {
569 inline std::string value::_serialize(
int indent)
const {
571 _serialize(std::back_inserter(s), indent);
575 template <
typename Iter>
class input {
581 input(
const Iter& first,
const Iter& last) : cur_(first), end_(last), consumed_(false), line_(1) {}
601 input<Iter> *self =
const_cast<input<Iter>*
>(
this);
602 self->consumed_ =
false;
607 int line()
const {
return line_; }
611 if (! (ch ==
' ' || ch ==
'\t' || ch ==
'\n' || ch ==
'\r')) {
617 bool expect(
int expect) {
619 if (getc() != expect) {
625 bool match(
const std::string& pattern) {
626 for (std::string::const_iterator pi(pattern.begin());
638 template<
typename Iter>
inline int _parse_quadhex(input<Iter> &in) {
640 for (
int i = 0; i < 4; i++) {
641 if ((hex = in.getc()) == -1) {
644 if (
'0' <= hex && hex <=
'9') {
646 }
else if (
'A' <= hex && hex <=
'F') {
648 }
else if (
'a' <= hex && hex <=
'f') {
654 uni_ch = uni_ch * 16 + hex;
659 template<
typename String,
typename Iter>
inline bool _parse_codepoint(String& out, input<Iter>& in) {
661 if ((uni_ch = _parse_quadhex(in)) == -1) {
664 if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
665 if (0xdc00 <= uni_ch) {
670 if (in.getc() !=
'\\' || in.getc() !=
'u') {
674 int second = _parse_quadhex(in);
675 if (! (0xdc00 <= second && second <= 0xdfff)) {
678 uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
682 out.push_back(uni_ch);
684 if (uni_ch < 0x800) {
685 out.push_back(0xc0 | (uni_ch >> 6));
687 if (uni_ch < 0x10000) {
688 out.push_back(0xe0 | (uni_ch >> 12));
690 out.push_back(0xf0 | (uni_ch >> 18));
691 out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
693 out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
695 out.push_back(0x80 | (uni_ch & 0x3f));
700 template<
typename String,
typename Iter>
inline bool _parse_string(String& out, input<Iter>& in) {
706 }
else if (ch ==
'"') {
708 }
else if (ch ==
'\\') {
709 if ((ch = in.getc()) == -1) {
713#define MAP(sym, val) case sym: out.push_back(val); break
724 if (! _parse_codepoint(out, in)) {
738 template <
typename Context,
typename Iter>
inline bool _parse_array(Context& ctx, input<Iter>& in) {
739 if (! ctx.parse_array_start()) {
743 if (in.expect(
']')) {
744 return ctx.parse_array_stop(idx);
747 if (! ctx.parse_array_item(in, idx)) {
751 }
while (in.expect(
','));
752 return in.expect(
']') && ctx.parse_array_stop(idx);
755 template <
typename Context,
typename Iter>
inline bool _parse_object(Context& ctx, input<Iter>& in) {
756 if (! ctx.parse_object_start()) {
759 if (in.expect(
'}')) {
765 || ! _parse_string(key, in)
766 || ! in.expect(
':')) {
769 if (! ctx.parse_object_item(in, key)) {
772 }
while (in.expect(
','));
773 return in.expect(
'}');
776 template <
typename Iter>
inline std::string _parse_number(input<Iter>& in) {
780 if ((
'0' <= ch && ch <=
'9') || ch ==
'+' || ch ==
'-'
781 || ch ==
'e' || ch ==
'E') {
782 num_str.push_back(ch);
783 }
else if (ch ==
'.') {
784#if PICOJSON_USE_LOCALE
787 num_str.push_back(
'.');
797 template <
typename Context,
typename Iter>
inline bool _parse(Context& ctx, input<Iter>& in) {
801#define IS(ch, text, op) case ch: \
802 if (in.match(text) && op) { \
807 IS(
'n',
"ull", ctx.set_null());
808 IS(
'f',
"alse", ctx.set_bool(
false));
809 IS(
't',
"rue", ctx.set_bool(
true));
812 return ctx.parse_string(in);
814 return _parse_array(ctx, in);
816 return _parse_object(ctx, in);
818 if ((
'0' <= ch && ch <=
'9') || ch ==
'-') {
822 std::string num_str = _parse_number(in);
823 if (num_str.empty()) {
826#ifdef PICOJSON_USE_INT64
829 intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
833 && endp == num_str.c_str() + num_str.size()) {
839 f = strtod(num_str.c_str(), &endp);
840 if (endp == num_str.c_str() + num_str.size()) {
852 class deny_parse_context {
854 bool set_null() {
return false; }
855 bool set_bool(
bool) {
return false; }
856#ifdef PICOJSON_USE_INT64
857 bool set_int64(int64_t) {
return false; }
859 bool set_number(
double) {
return false; }
860 template <
typename Iter>
bool parse_string(input<Iter>&) {
return false; }
861 bool parse_array_start() {
return false; }
862 template <
typename Iter>
bool parse_array_item(input<Iter>&,
size_t) {
865 bool parse_array_stop(
size_t) {
return false; }
866 bool parse_object_start() {
return false; }
867 template <
typename Iter>
bool parse_object_item(input<Iter>&,
const std::string&) {
872 class default_parse_context {
876 default_parse_context(value* out) : out_(out) {}
881 bool set_bool(
bool b) {
885#ifdef PICOJSON_USE_INT64
886 bool set_int64(int64_t i) {
891 bool set_number(
double f) {
895 template<
typename Iter>
bool parse_string(input<Iter>& in) {
896 *out_ = value(string_type,
false);
897 return _parse_string(out_->get<std::string>(), in);
899 bool parse_array_start() {
900 *out_ = value(array_type,
false);
903 template <
typename Iter>
bool parse_array_item(input<Iter>& in,
size_t) {
904 array& a = out_->get<array>();
905 a.push_back(value());
906 default_parse_context ctx(&a.back());
907 return _parse(ctx, in);
909 bool parse_array_stop(
size_t) {
return true; }
910 bool parse_object_start() {
911 *out_ = value(object_type,
false);
914 template <
typename Iter>
bool parse_object_item(input<Iter>& in,
const std::string& key) {
915 object& o = out_->get<
object>();
916 default_parse_context ctx(&o[key]);
917 return _parse(ctx, in);
920 default_parse_context(
const default_parse_context&);
921 default_parse_context& operator=(
const default_parse_context&);
924 class null_parse_context {
927 void push_back(
int) {}
930 null_parse_context() {}
931 bool set_null() {
return true; }
932 bool set_bool(
bool) {
return true; }
933#ifdef PICOJSON_USE_INT64
934 bool set_int64(int64_t) {
return true; }
936 bool set_number(
double) {
return true; }
937 template <
typename Iter>
bool parse_string(input<Iter>& in) {
939 return _parse_string(s, in);
941 bool parse_array_start() {
return true; }
942 template <
typename Iter>
bool parse_array_item(input<Iter>& in,
size_t) {
943 return _parse(*
this, in);
945 bool parse_array_stop(
size_t) {
return true; }
946 bool parse_object_start() {
return true; }
947 template <
typename Iter>
bool parse_object_item(input<Iter>& in,
const std::string&) {
948 return _parse(*
this, in);
951 null_parse_context(
const null_parse_context&);
952 null_parse_context& operator=(
const null_parse_context&);
956 template <
typename Iter>
inline std::string parse(value& out, Iter& pos,
const Iter& last) {
958 pos = parse(out, pos, last, &err);
962 template <
typename Context,
typename Iter>
inline Iter _parse(Context& ctx,
const Iter& first,
const Iter& last, std::string* err) {
963 input<Iter> in(first, last);
964 if (! _parse(ctx, in) && err != NULL) {
966 SNPRINTF(buf,
sizeof(buf),
"syntax error at line %d near: ", in.line());
970 if (ch == -1 || ch ==
'\n') {
972 }
else if (ch >=
' ') {
980 template <
typename Iter>
inline Iter parse(value& out,
const Iter& first,
const Iter& last, std::string* err) {
981 default_parse_context ctx(&out);
982 return _parse(ctx, first, last, err);
985 inline std::string parse(value& out,
const std::string& s) {
987 parse(out, s.begin(), s.end(), &err);
991 inline std::string parse(value& out, std::istream& is) {
993 parse(out, std::istreambuf_iterator<char>(is.rdbuf()),
994 std::istreambuf_iterator<char>(), &err);
998 template <
typename T>
struct last_error_t {
999 static std::string s;
1001 template <
typename T> std::string last_error_t<T>::s;
1003 inline void set_last_error(
const std::string& s) {
1004 last_error_t<bool>::s = s;
1007 inline const std::string& get_last_error() {
1008 return last_error_t<bool>::s;
1011 inline bool operator==(
const value& x,
const value& y) {
1013 return y.is<null>();
1014#define PICOJSON_CMP(type) \
1016 return y.is<type>() && x.get<type>() == y.get<type>()
1018 PICOJSON_CMP(
double);
1019 PICOJSON_CMP(std::string);
1020 PICOJSON_CMP(array);
1021 PICOJSON_CMP(
object);
1030 inline bool operator!=(
const value& x,
const value& y) {
1035#if !PICOJSON_USE_RVALUE_REFERENCE
1037 template<>
inline void swap(picojson::value& x, picojson::value& y)
1044inline std::istream& operator>>(std::istream& is, picojson::value& x)
1046 picojson::set_last_error(std::string());
1047 std::string err = picojson::parse(x, is);
1048 if (! err.empty()) {
1049 picojson::set_last_error(err);
1050 is.setstate(std::ios::failbit);
1055inline std::ostream& operator<<(std::ostream& os,
const picojson::value& x)
1057 x.serialize(std::ostream_iterator<char>(os));
1061 #pragma warning(pop)