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