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