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