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