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