HIVE SDK for C++

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