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