46 #if __cplusplus >= 201103L
52 #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
66 #endif // PICOJSON_USE_RVALUE_REFERENCE
69 #ifdef PICOJSON_USE_INT64
70 #define __STDC_FORMAT_MACROS
76 #ifndef PICOJSON_USE_LOCALE
77 #define PICOJSON_USE_LOCALE 1
79 #if PICOJSON_USE_LOCALE
85 #ifndef PICOJSON_ASSERT
86 #define PICOJSON_ASSERT(e) \
89 throw std::runtime_error(#e); \
94 #define SNPRINTF _snprintf_s
96 #pragma warning(disable : 4244) // conversion from int to char
97 #pragma warning(disable : 4127) // conditional expression is constant
98 #pragma warning(disable : 4702) // unreachable code
100 #define SNPRINTF snprintf
112 #ifdef PICOJSON_USE_INT64
125 typedef std::map<std::string, value>
object;
129 #ifdef PICOJSON_USE_INT64
143 value(
int type,
bool);
144 explicit value(
bool b);
145 #ifdef PICOJSON_USE_INT64
146 explicit value(int64_t i);
148 explicit value(
double n);
149 explicit value(
const std::string &s);
151 explicit value(
const object &o);
152 #if PICOJSON_USE_RVALUE_REFERENCE
153 explicit value(std::string &&s);
155 explicit value(
object &&o);
157 explicit value(
const char *s);
158 value(
const char *s,
size_t len);
162 #if PICOJSON_USE_RVALUE_REFERENCE
167 template <
typename T>
bool is()
const;
168 template <
typename T>
const T &
get()
const;
169 template <
typename T> T &
get();
170 template <
typename T>
void set(
const T &);
171 #if PICOJSON_USE_RVALUE_REFERENCE
172 template <
typename T>
void set(T &&);
175 const value &
get(
const size_t idx)
const;
176 const value &
get(
const std::string &key)
const;
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>
void serialize(Iter os,
bool prettify =
false)
const;
184 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;
206 INIT(boolean_,
false);
208 #ifdef PICOJSON_USE_INT64
211 INIT(string_,
new std::string());
213 INIT(object_,
new object());
224 #ifdef PICOJSON_USE_INT64
225 inline value::value(int64_t i) : type_(int64_type), u_() {
234 #elif __cplusplus >= 201103L
235 std::isnan(n) || std::isinf(n)
240 throw std::overflow_error(
"");
257 #if PICOJSON_USE_RVALUE_REFERENCE
259 u_.
string_ =
new std::string(std::move(s));
322 #if PICOJSON_USE_RVALUE_REFERENCE
336 #define IS(ctype, jtype) \
337 template <> inline bool value::is<ctype>() const { \
338 return type_ == jtype##_type; \
342 #ifdef PICOJSON_USE_INT64
345 IS(std::string,
string)
349 template <>
inline bool value::is<double>()
const {
351 #ifdef PICOJSON_USE_INT64
352 ||
type_ == int64_type
357 #define GET(ctype, var) \
358 template <> inline const ctype &value::get<ctype>() const { \
359 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
362 template <> inline ctype &value::get<ctype>() { \
363 PICOJSON_ASSERT("type mismatch! call is<type>() before get<type>()" && is<ctype>()); \
367 GET(
std::
string, *u_.string_)
369 GET(
object, *u_.object_)
370 #ifdef PICOJSON_USE_INT64
372 (type_ == int64_type && (
const_cast<value *
>(
this)->type_ =
number_type,
const_cast<value *
>(
this)->u_.
number_ = u_.int64_),
374 GET(int64_t, u_.int64_)
380 #define SET(ctype, jtype, setter) \
381 template <> inline void value::set<ctype>(const ctype &_val) { \
383 type_ = jtype##_type; \
387 SET(std::string,
string, u_.
string_ =
new std::string(_val);)
389 SET(
object,
object, u_.
object_ =
new object(_val);)
391 #ifdef PICOJSON_USE_INT64
392 SET(int64_t, int64, u_.int64_ = _val;)
396 #if PICOJSON_USE_RVALUE_REFERENCE
397 #define MOVESET(ctype, jtype, setter) \
398 template <> inline void value::set<ctype>(ctype && _val) { \
400 type_ = jtype##_type; \
403 MOVESET(std::string,
string, u_.
string_ =
new std::string(std::move(_val));)
405 MOVESET(
object,
object, u_.
object_ =
new object(std::move(_val));)
417 #ifdef PICOJSON_USE_INT64
419 return u_.int64_ != 0;
443 object::const_iterator i =
u_.
object_->find(key);
444 return i !=
u_.
object_->end() ? i->second : s_null;
451 return i !=
u_.
object_->end() ? i->second : s_null;
461 object::const_iterator i =
u_.
object_->find(key);
471 #ifdef PICOJSON_USE_INT64
473 char buf[
sizeof(
"-9223372036854775808")];
474 SNPRINTF(buf,
sizeof(buf),
"%" PRId64,
u_.int64_);
482 #if PICOJSON_USE_LOCALE
483 char *decimal_point = localeconv()->decimal_point;
484 if (strcmp(decimal_point,
".") != 0) {
485 size_t decimal_point_len = strlen(decimal_point);
486 for (
char *p = buf; *p !=
'\0'; ++p) {
487 if (strncmp(p, decimal_point, decimal_point_len) == 0) {
488 return std::string(buf, p) +
"." + (p + decimal_point_len);
507 return std::string();
510 template <
typename Iter>
void copy(
const std::string &s, Iter oi) {
518 #define MAP(val, sym) \
532 if (
static_cast<unsigned char>(
c) < 0x20 ||
c == 0x7f) {
534 SNPRINTF(buf,
sizeof(buf),
"\\u%04x",
c & 0xff);
544 template <
typename Iter>
void serialize_str(
const std::string &s, Iter oi) {
547 std::for_each(s.begin(), s.end(), process_char);
576 for (array::const_iterator i =
u_.
array_->begin(); i !=
u_.
array_->end(); ++i) {
583 i->serialize_(oi, indent);
611 i->second.serialize_(oi, indent);
637 template <
typename Iter>
class input {
677 if (!(ch ==
' ' || ch ==
'\t' || ch ==
'\n' || ch ==
'\r')) {
685 if (
getc() != expected) {
691 bool match(
const std::string &pattern) {
692 for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
704 for (
int i = 0; i < 4; i++) {
705 if ((hex = in.
getc()) == -1) {
708 if (
'0' <= hex && hex <=
'9') {
710 }
else if (
'A' <= hex && hex <=
'F') {
712 }
else if (
'a' <= hex && hex <=
'f') {
718 uni_ch = uni_ch * 16 + hex;
728 if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
729 if (0xdc00 <= uni_ch) {
734 if (in.
getc() !=
'\\' || in.
getc() !=
'u') {
739 if (!(0xdc00 <= second && second <= 0xdfff)) {
742 uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
746 out.push_back(
static_cast<char>(uni_ch));
748 if (uni_ch < 0x800) {
749 out.push_back(
static_cast<char>(0xc0 | (uni_ch >> 6)));
751 if (uni_ch < 0x10000) {
752 out.push_back(
static_cast<char>(0xe0 | (uni_ch >> 12)));
754 out.push_back(
static_cast<char>(0xf0 | (uni_ch >> 18)));
755 out.push_back(
static_cast<char>(0x80 | ((uni_ch >> 12) & 0x3f)));
757 out.push_back(
static_cast<char>(0x80 | ((uni_ch >> 6) & 0x3f)));
759 out.push_back(
static_cast<char>(0x80 | (uni_ch & 0x3f)));
770 }
else if (ch ==
'"') {
772 }
else if (ch ==
'\\') {
773 if ((ch = in.
getc()) == -1) {
777 #define MAP(sym, val) \
779 out.push_back(val); \
799 out.push_back(
static_cast<char>(ch));
806 if (!ctx.parse_array_start()) {
811 return ctx.parse_array_stop(idx);
814 if (!ctx.parse_array_item(in, idx)) {
819 return in.
expect(
']') && ctx.parse_array_stop(idx);
823 if (!ctx.parse_object_start()) {
834 if (!ctx.parse_object_item(in, key)) {
845 if ((
'0' <= ch && ch <=
'9') || ch ==
'+' || ch ==
'-' || ch ==
'e' || ch ==
'E') {
846 num_str.push_back(
static_cast<char>(ch));
847 }
else if (ch ==
'.') {
848 #if PICOJSON_USE_LOCALE
849 num_str += localeconv()->decimal_point;
851 num_str.push_back(
'.');
865 #define IS(ch, text, op) \
867 if (in.match(text) && op) { \
872 IS(
'n',
"ull", ctx.set_null());
873 IS(
'f',
"alse", ctx.set_bool(
false));
874 IS(
't',
"rue", ctx.set_bool(
true));
877 return ctx.parse_string(in);
883 if ((
'0' <= ch && ch <=
'9') || ch ==
'-') {
888 if (num_str.empty()) {
891 #ifdef PICOJSON_USE_INT64
894 intmax_t ival = strtoimax(num_str.c_str(), &endp, 10);
895 if (errno == 0 && std::numeric_limits<int64_t>::min() <= ival && ival <= std::numeric_limits<int64_t>::max() &&
896 endp == num_str.c_str() + num_str.size()) {
902 f = strtod(num_str.c_str(), &endp);
903 if (endp == num_str.c_str() + num_str.size()) {
923 #ifdef PICOJSON_USE_INT64
924 bool set_int64(int64_t) {
966 #ifdef PICOJSON_USE_INT64
967 bool set_int64(int64_t i) {
986 a.push_back(
value());
998 object &o =
out_->
get<
object>();
1024 #ifdef PICOJSON_USE_INT64
1025 bool set_int64(int64_t) {
1040 return _parse(*
this, in);
1049 return _parse(*
this, in);
1058 template <
typename Iter>
inline std::string
parse(
value &out, Iter &pos,
const Iter &last) {
1060 pos =
parse(out, pos, last, &err);
1064 template <
typename Context,
typename Iter>
inline Iter
_parse(Context &ctx,
const Iter &first,
const Iter &last, std::string *err) {
1066 if (!
_parse(ctx, in) && err !=
nullptr) {
1068 SNPRINTF(buf,
sizeof(buf),
"syntax error at line %d near: ", in.
line());
1072 if (ch == -1 || ch ==
'\n') {
1074 }
else if (ch >=
' ') {
1075 err->push_back(
static_cast<char>(ch));
1082 template <
typename Iter>
inline Iter
parse(
value &out,
const Iter &first,
const Iter &last, std::string *err) {
1084 return _parse(ctx, first, last, err);
1089 parse(out, s.begin(), s.end(), &err);
1095 parse(out, std::istreambuf_iterator<char>(is.rdbuf()), std::istreambuf_iterator<char>(), &err);
1112 return y.
is<
null>();
1113 #define PICOJSON_CMP(type) \
1115 return y.is<type>() && x.get<type>() == y.get<type>()
1134 #if !PICOJSON_USE_RVALUE_REFERENCE
1147 is.setstate(std::ios::failbit);
1153 x.
serialize(std::ostream_iterator<char>(os));
1157 #pragma warning(pop)