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