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