mbedからGluinサーバへ接続するライブラリです
Embed:
(wiki syntax)
Show/hide line numbers
picojson.h
00001 /* 00002 * Copyright 2009-2010 Cybozu Labs, Inc. 00003 * Copyright 2011 Kazuho Oku 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright notice, 00011 * this list of conditions and the following disclaimer in the documentation 00012 * and/or other materials provided with the distribution. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY CYBOZU LABS, INC. ``AS IS'' AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00016 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 00017 * EVENT SHALL CYBOZU LABS, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00018 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00019 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00020 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00021 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 * The views and conclusions contained in the software and documentation are 00026 * those of the authors and should not be interpreted as representing official 00027 * policies, either expressed or implied, of Cybozu Labs, Inc. 00028 * 00029 */ 00030 #ifndef picojson_h 00031 #define picojson_h 00032 00033 #include <algorithm> 00034 #include <cassert> 00035 #include <cmath> 00036 #include <cstdio> 00037 #include <cstdlib> 00038 #include <cstring> 00039 #include <iostream> 00040 #include <iterator> 00041 #include <map> 00042 #include <string> 00043 #include <vector> 00044 00045 // to disable the use of localeconv(3), set PICOJSON_USE_LOCALE to 0 00046 #ifndef PICOJSON_USE_LOCALE 00047 # define PICOJSON_USE_LOCALE 1 00048 #endif 00049 #if PICOJSON_USE_LOCALE 00050 extern "C" { 00051 # include <locale.h> 00052 } 00053 #endif 00054 00055 #ifdef _MSC_VER 00056 #define SNPRINTF _snprintf_s 00057 #pragma warning(push) 00058 #pragma warning(disable : 4244) // conversion from int to char 00059 #else 00060 #define SNPRINTF snprintf 00061 #endif 00062 00063 namespace picojson { 00064 00065 enum { 00066 null_type, 00067 boolean_type, 00068 number_type, 00069 string_type, 00070 array_type, 00071 object_type 00072 }; 00073 00074 enum { 00075 INDENT_WIDTH = 2 00076 }; 00077 00078 struct null {}; 00079 00080 class value { 00081 public: 00082 typedef std::vector<value> array; 00083 typedef std::map<std::string, value> object; 00084 union _storage { 00085 bool boolean_; 00086 double number_; 00087 std::string* string_; 00088 array* array_; 00089 object* object_; 00090 }; 00091 protected: 00092 int type_; 00093 _storage u_; 00094 public: 00095 value(); 00096 value(int type, bool); 00097 explicit value(bool b); 00098 explicit value(double n); 00099 explicit value(const std::string& s); 00100 explicit value(const array& a); 00101 explicit value(const object& o); 00102 explicit value(const char* s); 00103 value(const char* s, size_t len); 00104 ~value(); 00105 value(const value& x); 00106 value& operator=(const value& x); 00107 void swap(value& x); 00108 template <typename T> bool is() const; 00109 template <typename T> const T& get() const; 00110 template <typename T> T& get(); 00111 bool evaluate_as_boolean() const; 00112 const value& get(size_t idx) const; 00113 const value& get(const std::string& key) const; 00114 value& get(size_t idx); 00115 value& get(const std::string& key); 00116 00117 bool contains(size_t idx) const; 00118 bool contains(const std::string& key) const; 00119 std::string to_str() const; 00120 template <typename Iter> void serialize(Iter os, bool prettify = false) const; 00121 std::string serialize(bool prettify = false) const; 00122 private: 00123 template <typename T> value(const T*); // intentionally defined to block implicit conversion of pointer to bool 00124 template <typename Iter> static void _indent(Iter os, int indent); 00125 template <typename Iter> void _serialize(Iter os, int indent) const; 00126 std::string _serialize(int indent) const; 00127 }; 00128 00129 typedef value::array array; 00130 typedef value::object object; 00131 00132 inline value::value() : type_(null_type) {} 00133 00134 inline value::value(int type, bool) : type_(type) { 00135 switch (type) { 00136 #define INIT(p, v) case p##type: u_.p = v; break 00137 INIT(boolean_, false); 00138 INIT(number_, 0.0); 00139 INIT(string_, new std::string()); 00140 INIT(array_, new array()); 00141 INIT(object_, new object()); 00142 #undef INIT 00143 default: break; 00144 } 00145 } 00146 00147 inline value::value(bool b) : type_(boolean_type) { 00148 u_.boolean_ = b; 00149 } 00150 00151 inline value::value(double n) : type_(number_type) { 00152 u_.number_ = n; 00153 } 00154 00155 inline value::value(const std::string& s) : type_(string_type) { 00156 u_.string_ = new std::string(s); 00157 } 00158 00159 inline value::value(const array& a) : type_(array_type) { 00160 u_.array_ = new array(a); 00161 } 00162 00163 inline value::value(const object& o) : type_(object_type) { 00164 u_.object_ = new object(o); 00165 } 00166 00167 inline value::value(const char* s) : type_(string_type) { 00168 u_.string_ = new std::string(s); 00169 } 00170 00171 inline value::value(const char* s, size_t len) : type_(string_type) { 00172 u_.string_ = new std::string(s, len); 00173 } 00174 00175 inline value::~value() { 00176 switch (type_) { 00177 #define DEINIT(p) case p##type: delete u_.p; break 00178 DEINIT(string_); 00179 DEINIT(array_); 00180 DEINIT(object_); 00181 #undef DEINIT 00182 default: break; 00183 } 00184 } 00185 00186 inline value::value(const value& x) : type_(x.type_) { 00187 switch (type_) { 00188 #define INIT(p, v) case p##type: u_.p = v; break 00189 INIT(string_, new std::string(*x.u_.string_)); 00190 INIT(array_, new array(*x.u_.array_)); 00191 INIT(object_, new object(*x.u_.object_)); 00192 #undef INIT 00193 default: 00194 u_ = x.u_; 00195 break; 00196 } 00197 } 00198 00199 inline value& value::operator=(const value& x) { 00200 if (this != &x) { 00201 this->~value(); 00202 new (this) value(x); 00203 } 00204 return *this; 00205 } 00206 00207 inline void value::swap(value& x) { 00208 std::swap(type_, x.type_); 00209 std::swap(u_, x.u_); 00210 } 00211 00212 #define IS(ctype, jtype) \ 00213 template <> inline bool value::is<ctype>() const { \ 00214 return type_ == jtype##_type; \ 00215 } 00216 IS(null, null) 00217 IS(bool, boolean) 00218 IS(int, number) 00219 IS(double, number) 00220 IS(std::string, string) 00221 IS(array, array) 00222 IS(object, object) 00223 #undef IS 00224 00225 #define GET(ctype, var) \ 00226 template <> inline const ctype& value::get<ctype>() const { \ 00227 assert("type mismatch! call vis<type>() before get<type>()" \ 00228 && is<ctype>()); \ 00229 return var; \ 00230 } \ 00231 template <> inline ctype& value::get<ctype>() { \ 00232 assert("type mismatch! call is<type>() before get<type>()" \ 00233 && is<ctype>()); \ 00234 return var; \ 00235 } 00236 GET(bool, u_.boolean_) 00237 GET(double, u_.number_) 00238 GET(std::string, *u_.string_) 00239 GET(array, *u_.array_) 00240 GET(object, *u_.object_) 00241 #undef GET 00242 00243 inline bool value::evaluate_as_boolean() const { 00244 switch (type_) { 00245 case null_type: 00246 return false; 00247 case boolean_type: 00248 return u_.boolean_; 00249 case number_type: 00250 return u_.number_ != 0; 00251 case string_type: 00252 return ! u_.string_->empty(); 00253 default: 00254 return true; 00255 } 00256 } 00257 00258 inline const value& value::get(size_t idx) const { 00259 static value s_null; 00260 assert(is<array>()); 00261 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; 00262 } 00263 00264 inline value& value::get(size_t idx) { 00265 static value s_null; 00266 assert(is<array>()); 00267 return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null; 00268 } 00269 00270 inline const value& value::get(const std::string& key) const { 00271 static value s_null; 00272 assert(is<object>()); 00273 object::const_iterator i = u_.object_->find(key); 00274 return i != u_.object_->end() ? i->second : s_null; 00275 } 00276 00277 inline value& value::get(const std::string& key) { 00278 static value s_null; 00279 assert(is<object>()); 00280 object::iterator i = u_.object_->find(key); 00281 return i != u_.object_->end() ? i->second : s_null; 00282 } 00283 00284 inline bool value::contains(size_t idx) const { 00285 assert(is<array>()); 00286 return idx < u_.array_->size(); 00287 } 00288 00289 inline bool value::contains(const std::string& key) const { 00290 assert(is<object>()); 00291 object::const_iterator i = u_.object_->find(key); 00292 return i != u_.object_->end(); 00293 } 00294 00295 inline std::string value::to_str() const { 00296 switch (type_) { 00297 case null_type: return "null"; 00298 case boolean_type: return u_.boolean_ ? "true" : "false"; 00299 case number_type: { 00300 char buf[256]; 00301 double tmp; 00302 SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_); 00303 #if PICOJSON_USE_LOCALE 00304 char *decimal_point = localeconv()->decimal_point; 00305 if (strcmp(decimal_point, ".") != 0) { 00306 size_t decimal_point_len = strlen(decimal_point); 00307 for (char *p = buf; *p != '\0'; ++p) { 00308 if (strncmp(p, decimal_point, decimal_point_len) == 0) { 00309 return std::string(buf, p) + "." + (p + decimal_point_len); 00310 } 00311 } 00312 } 00313 #endif 00314 return buf; 00315 } 00316 case string_type: return *u_.string_; 00317 case array_type: return "array"; 00318 case object_type: return "object"; 00319 default: assert(0); 00320 #ifdef _MSC_VER 00321 __assume(0); 00322 #endif 00323 } 00324 return std::string(); 00325 } 00326 00327 template <typename Iter> void copy(const std::string& s, Iter oi) { 00328 std::copy(s.begin(), s.end(), oi); 00329 } 00330 00331 template <typename Iter> void serialize_str(const std::string& s, Iter oi) { 00332 *oi++ = '"'; 00333 for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { 00334 switch (*i) { 00335 #define MAP(val, sym) case val: copy(sym, oi); break 00336 MAP('"', "\\\""); 00337 MAP('\\', "\\\\"); 00338 MAP('/', "\\/"); 00339 MAP('\b', "\\b"); 00340 MAP('\f', "\\f"); 00341 MAP('\n', "\\n"); 00342 MAP('\r', "\\r"); 00343 MAP('\t', "\\t"); 00344 #undef MAP 00345 default: 00346 if ((unsigned char)*i < 0x20 || *i == 0x7f) { 00347 char buf[7]; 00348 SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff); 00349 copy(buf, buf + 6, oi); 00350 } else { 00351 *oi++ = *i; 00352 } 00353 break; 00354 } 00355 } 00356 *oi++ = '"'; 00357 } 00358 00359 template <typename Iter> void value::serialize(Iter oi, bool prettify) const { 00360 return _serialize(oi, prettify ? 0 : -1); 00361 } 00362 00363 inline std::string value::serialize(bool prettify) const { 00364 return _serialize(prettify ? 0 : -1); 00365 } 00366 00367 template <typename Iter> void value::_indent(Iter oi, int indent) { 00368 *oi++ = '\n'; 00369 for (int i = 0; i < indent * INDENT_WIDTH; ++i) { 00370 *oi++ = ' '; 00371 } 00372 } 00373 00374 template <typename Iter> void value::_serialize(Iter oi, int indent) const { 00375 switch (type_) { 00376 case string_type: 00377 serialize_str(*u_.string_, oi); 00378 break; 00379 case array_type: { 00380 *oi++ = '['; 00381 if (indent != -1) { 00382 ++indent; 00383 } 00384 for (array::const_iterator i = u_.array_->begin(); 00385 i != u_.array_->end(); 00386 ++i) { 00387 if (i != u_.array_->begin()) { 00388 *oi++ = ','; 00389 } 00390 if (indent != -1) { 00391 _indent(oi, indent); 00392 } 00393 i->_serialize(oi, indent); 00394 } 00395 if (indent != -1) { 00396 --indent; 00397 if (! u_.array_->empty()) { 00398 _indent(oi, indent); 00399 } 00400 } 00401 *oi++ = ']'; 00402 break; 00403 } 00404 case object_type: { 00405 *oi++ = '{'; 00406 if (indent != -1) { 00407 ++indent; 00408 } 00409 for (object::const_iterator i = u_.object_->begin(); 00410 i != u_.object_->end(); 00411 ++i) { 00412 if (i != u_.object_->begin()) { 00413 *oi++ = ','; 00414 } 00415 if (indent != -1) { 00416 _indent(oi, indent); 00417 } 00418 serialize_str(i->first, oi); 00419 *oi++ = ':'; 00420 if (indent != -1) { 00421 *oi++ = ' '; 00422 } 00423 i->second._serialize(oi, indent); 00424 } 00425 if (indent != -1) { 00426 --indent; 00427 if (! u_.object_->empty()) { 00428 _indent(oi, indent); 00429 } 00430 } 00431 *oi++ = '}'; 00432 break; 00433 } 00434 default: 00435 copy(to_str(), oi); 00436 break; 00437 } 00438 if (indent == 0) { 00439 *oi++ = '\n'; 00440 } 00441 } 00442 00443 inline std::string value::_serialize(int indent) const { 00444 std::string s; 00445 _serialize(std::back_inserter(s), indent); 00446 return s; 00447 } 00448 00449 template <typename Iter> class input { 00450 protected: 00451 Iter cur_, end_; 00452 int last_ch_; 00453 bool ungot_; 00454 int line_; 00455 public: 00456 input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {} 00457 int getc() { 00458 if (ungot_) { 00459 ungot_ = false; 00460 return last_ch_; 00461 } 00462 if (cur_ == end_) { 00463 last_ch_ = -1; 00464 return -1; 00465 } 00466 if (last_ch_ == '\n') { 00467 line_++; 00468 } 00469 last_ch_ = *cur_ & 0xff; 00470 ++cur_; 00471 return last_ch_; 00472 } 00473 void ungetc() { 00474 if (last_ch_ != -1) { 00475 assert(! ungot_); 00476 ungot_ = true; 00477 } 00478 } 00479 Iter cur() const { return cur_; } 00480 int line() const { return line_; } 00481 void skip_ws() { 00482 while (1) { 00483 int ch = getc(); 00484 if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { 00485 ungetc(); 00486 break; 00487 } 00488 } 00489 } 00490 bool expect(int expect) { 00491 skip_ws(); 00492 if (getc() != expect) { 00493 ungetc(); 00494 return false; 00495 } 00496 return true; 00497 } 00498 bool match(const std::string& pattern) { 00499 for (std::string::const_iterator pi(pattern.begin()); 00500 pi != pattern.end(); 00501 ++pi) { 00502 if (getc() != *pi) { 00503 ungetc(); 00504 return false; 00505 } 00506 } 00507 return true; 00508 } 00509 }; 00510 00511 template<typename Iter> inline int _parse_quadhex(input<Iter> &in) { 00512 int uni_ch = 0, hex; 00513 for (int i = 0; i < 4; i++) { 00514 if ((hex = in.getc()) == -1) { 00515 return -1; 00516 } 00517 if ('0' <= hex && hex <= '9') { 00518 hex -= '0'; 00519 } else if ('A' <= hex && hex <= 'F') { 00520 hex -= 'A' - 0xa; 00521 } else if ('a' <= hex && hex <= 'f') { 00522 hex -= 'a' - 0xa; 00523 } else { 00524 in.ungetc(); 00525 return -1; 00526 } 00527 uni_ch = uni_ch * 16 + hex; 00528 } 00529 return uni_ch; 00530 } 00531 00532 template<typename String, typename Iter> inline bool _parse_codepoint(String& out, input<Iter>& in) { 00533 int uni_ch; 00534 if ((uni_ch = _parse_quadhex(in)) == -1) { 00535 return false; 00536 } 00537 if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { 00538 if (0xdc00 <= uni_ch) { 00539 // a second 16-bit of a surrogate pair appeared 00540 return false; 00541 } 00542 // first 16-bit of surrogate pair, get the next one 00543 if (in.getc() != '\\' || in.getc() != 'u') { 00544 in.ungetc(); 00545 return false; 00546 } 00547 int second = _parse_quadhex(in); 00548 if (! (0xdc00 <= second && second <= 0xdfff)) { 00549 return false; 00550 } 00551 uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); 00552 uni_ch += 0x10000; 00553 } 00554 if (uni_ch < 0x80) { 00555 out.push_back(uni_ch); 00556 } else { 00557 if (uni_ch < 0x800) { 00558 out.push_back(0xc0 | (uni_ch >> 6)); 00559 } else { 00560 if (uni_ch < 0x10000) { 00561 out.push_back(0xe0 | (uni_ch >> 12)); 00562 } else { 00563 out.push_back(0xf0 | (uni_ch >> 18)); 00564 out.push_back(0x80 | ((uni_ch >> 12) & 0x3f)); 00565 } 00566 out.push_back(0x80 | ((uni_ch >> 6) & 0x3f)); 00567 } 00568 out.push_back(0x80 | (uni_ch & 0x3f)); 00569 } 00570 return true; 00571 } 00572 00573 template<typename String, typename Iter> inline bool _parse_string(String& out, input<Iter>& in) { 00574 while (1) { 00575 int ch = in.getc(); 00576 if (ch < ' ') { 00577 in.ungetc(); 00578 return false; 00579 } else if (ch == '"') { 00580 return true; 00581 } else if (ch == '\\') { 00582 if ((ch = in.getc()) == -1) { 00583 return false; 00584 } 00585 switch (ch) { 00586 #define MAP(sym, val) case sym: out.push_back(val); break 00587 MAP('"', '\"'); 00588 MAP('\\', '\\'); 00589 MAP('/', '/'); 00590 MAP('b', '\b'); 00591 MAP('f', '\f'); 00592 MAP('n', '\n'); 00593 MAP('r', '\r'); 00594 MAP('t', '\t'); 00595 #undef MAP 00596 case 'u': 00597 if (! _parse_codepoint(out, in)) { 00598 return false; 00599 } 00600 break; 00601 default: 00602 return false; 00603 } 00604 } else { 00605 out.push_back(ch); 00606 } 00607 } 00608 return false; 00609 } 00610 00611 template <typename Context, typename Iter> inline bool _parse_array(Context& ctx, input<Iter>& in) { 00612 if (! ctx.parse_array_start()) { 00613 return false; 00614 } 00615 size_t idx = 0; 00616 if (in.expect(']')) { 00617 return ctx.parse_array_stop(idx); 00618 } 00619 do { 00620 if (! ctx.parse_array_item(in, idx)) { 00621 return false; 00622 } 00623 idx++; 00624 } while (in.expect(',')); 00625 return in.expect(']') && ctx.parse_array_stop(idx); 00626 } 00627 00628 template <typename Context, typename Iter> inline bool _parse_object(Context& ctx, input<Iter>& in) { 00629 if (! ctx.parse_object_start()) { 00630 return false; 00631 } 00632 if (in.expect('}')) { 00633 return true; 00634 } 00635 do { 00636 std::string key; 00637 if (! in.expect('"') 00638 || ! _parse_string(key, in) 00639 || ! in.expect(':')) { 00640 return false; 00641 } 00642 if (! ctx.parse_object_item(in, key)) { 00643 return false; 00644 } 00645 } while (in.expect(',')); 00646 return in.expect('}'); 00647 } 00648 00649 template <typename Iter> inline bool _parse_number(double& out, input<Iter>& in) { 00650 std::string num_str; 00651 while (1) { 00652 int ch = in.getc(); 00653 if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' 00654 || ch == 'e' || ch == 'E') { 00655 num_str.push_back(ch); 00656 } else if (ch == '.') { 00657 #if PICOJSON_USE_LOCALE 00658 num_str += localeconv()->decimal_point; 00659 #else 00660 num_str.push_back('.'); 00661 #endif 00662 } else { 00663 in.ungetc(); 00664 break; 00665 } 00666 } 00667 char* endp; 00668 out = strtod(num_str.c_str(), &endp); 00669 return endp == num_str.c_str() + num_str.size(); 00670 } 00671 00672 template <typename Context, typename Iter> inline bool _parse(Context& ctx, input<Iter>& in) { 00673 in.skip_ws(); 00674 int ch = in.getc(); 00675 switch (ch) { 00676 #define IS(ch, text, op) case ch: \ 00677 if (in.match(text) && op) { \ 00678 return true; \ 00679 } else { \ 00680 return false; \ 00681 } 00682 IS('n', "ull", ctx.set_null()); 00683 IS('f', "alse", ctx.set_bool(false)); 00684 IS('t', "rue", ctx.set_bool(true)); 00685 #undef IS 00686 case '"': 00687 return ctx.parse_string(in); 00688 case '[': 00689 return _parse_array(ctx, in); 00690 case '{': 00691 return _parse_object(ctx, in); 00692 default: 00693 if (('0' <= ch && ch <= '9') || ch == '-') { 00694 in.ungetc(); 00695 double f; 00696 if (_parse_number(f, in)) { 00697 ctx.set_number(f); 00698 return true; 00699 } else { 00700 return false; 00701 } 00702 } 00703 break; 00704 } 00705 in.ungetc(); 00706 return false; 00707 } 00708 00709 class deny_parse_context { 00710 public: 00711 bool set_null() { return false; } 00712 bool set_bool(bool) { return false; } 00713 bool set_number(double) { return false; } 00714 template <typename Iter> bool parse_string(input<Iter>&) { return false; } 00715 bool parse_array_start() { return false; } 00716 template <typename Iter> bool parse_array_item(input<Iter>&, size_t) { 00717 return false; 00718 } 00719 bool parse_array_stop(size_t) { return false; } 00720 bool parse_object_start() { return false; } 00721 template <typename Iter> bool parse_object_item(input<Iter>&, const std::string&) { 00722 return false; 00723 } 00724 }; 00725 00726 class default_parse_context { 00727 protected: 00728 value* out_; 00729 public: 00730 default_parse_context(value* out) : out_(out) {} 00731 bool set_null() { 00732 *out_ = value(); 00733 return true; 00734 } 00735 bool set_bool(bool b) { 00736 *out_ = value(b); 00737 return true; 00738 } 00739 bool set_number(double f) { 00740 *out_ = value(f); 00741 return true; 00742 } 00743 template<typename Iter> bool parse_string(input<Iter>& in) { 00744 *out_ = value(string_type, false); 00745 return _parse_string(out_->get<std::string>(), in); 00746 } 00747 bool parse_array_start() { 00748 *out_ = value(array_type, false); 00749 return true; 00750 } 00751 template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) { 00752 array& a = out_->get<array>(); 00753 a.push_back(value()); 00754 default_parse_context ctx(&a.back()); 00755 return _parse(ctx, in); 00756 } 00757 bool parse_array_stop(size_t) { return true; } 00758 bool parse_object_start() { 00759 *out_ = value(object_type, false); 00760 return true; 00761 } 00762 template <typename Iter> bool parse_object_item(input<Iter>& in, const std::string& key) { 00763 object& o = out_->get<object>(); 00764 default_parse_context ctx(&o[key]); 00765 return _parse(ctx, in); 00766 } 00767 private: 00768 default_parse_context(const default_parse_context&); 00769 default_parse_context& operator=(const default_parse_context&); 00770 }; 00771 00772 class null_parse_context { 00773 public: 00774 struct dummy_str { 00775 void push_back(int) {} 00776 }; 00777 public: 00778 null_parse_context() {} 00779 bool set_null() { return true; } 00780 bool set_bool(bool) { return true; } 00781 bool set_number(double) { return true; } 00782 template <typename Iter> bool parse_string(input<Iter>& in) { 00783 dummy_str s; 00784 return _parse_string(s, in); 00785 } 00786 bool parse_array_start() { return true; } 00787 template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) { 00788 return _parse(*this, in); 00789 } 00790 bool parse_array_stop(size_t) { return true; } 00791 bool parse_object_start() { return true; } 00792 template <typename Iter> bool parse_object_item(input<Iter>& in, const std::string&) { 00793 return _parse(*this, in); 00794 } 00795 private: 00796 null_parse_context(const null_parse_context&); 00797 null_parse_context& operator=(const null_parse_context&); 00798 }; 00799 00800 // obsolete, use the version below 00801 template <typename Iter> inline std::string parse(value& out, Iter& pos, const Iter& last) { 00802 std::string err; 00803 pos = parse(out, pos, last, &err); 00804 return err; 00805 } 00806 00807 template <typename Context, typename Iter> inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) { 00808 input<Iter> in(first, last); 00809 if (! _parse(ctx, in) && err != NULL) { 00810 char buf[64]; 00811 SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); 00812 *err = buf; 00813 while (1) { 00814 int ch = in.getc(); 00815 if (ch == -1 || ch == '\n') { 00816 break; 00817 } else if (ch >= ' ') { 00818 err->push_back(ch); 00819 } 00820 } 00821 } 00822 return in.cur(); 00823 } 00824 00825 template <typename Iter> inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) { 00826 default_parse_context ctx(&out); 00827 return _parse(ctx, first, last, err); 00828 } 00829 00830 inline std::string parse(value& out, std::istream& is) { 00831 std::string err; 00832 parse(out, std::istreambuf_iterator<char>(is.rdbuf()), 00833 std::istreambuf_iterator<char>(), &err); 00834 return err; 00835 } 00836 00837 template <typename T> struct last_error_t { 00838 static std::string s; 00839 }; 00840 template <typename T> std::string last_error_t<T>::s; 00841 00842 inline void set_last_error(const std::string& s) { 00843 last_error_t<bool>::s = s; 00844 } 00845 00846 inline const std::string& get_last_error() { 00847 return last_error_t<bool>::s; 00848 } 00849 00850 inline bool operator==(const value& x, const value& y) { 00851 if (x.is<null>()) 00852 return y.is<null>(); 00853 #define PICOJSON_CMP(type) \ 00854 if (x.is<type>()) \ 00855 return y.is<type>() && x.get<type>() == y.get<type>() 00856 PICOJSON_CMP(bool); 00857 PICOJSON_CMP(double); 00858 PICOJSON_CMP(std::string); 00859 PICOJSON_CMP(array); 00860 PICOJSON_CMP(object); 00861 #undef PICOJSON_CMP 00862 assert(0); 00863 #ifdef _MSC_VER 00864 __assume(0); 00865 #endif 00866 return false; 00867 } 00868 00869 inline bool operator!=(const value& x, const value& y) { 00870 return ! (x == y); 00871 } 00872 } 00873 00874 namespace std { 00875 template<> inline void swap(picojson::value& x, picojson::value& y) 00876 { 00877 x.swap(y); 00878 } 00879 } 00880 00881 inline std::istream& operator>>(std::istream& is, picojson::value& x) 00882 { 00883 picojson::set_last_error(std::string()); 00884 std::string err = picojson::parse(x, is); 00885 if (! err.empty()) { 00886 picojson::set_last_error(err); 00887 is.setstate(std::ios::failbit); 00888 } 00889 return is; 00890 } 00891 00892 inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) 00893 { 00894 x.serialize(std::ostream_iterator<char>(os)); 00895 return os; 00896 } 00897 #ifdef _MSC_VER 00898 #pragma warning(pop) 00899 #endif 00900 00901 #endif 00902 #ifdef TEST_PICOJSON 00903 #ifdef _MSC_VER 00904 #pragma warning(disable : 4127) // conditional expression is constant 00905 #endif 00906 00907 using namespace std; 00908 00909 static void plan(int num) 00910 { 00911 printf("1..%d\n", num); 00912 } 00913 00914 static bool success = true; 00915 00916 static void ok(bool b, const char* name = "") 00917 { 00918 static int n = 1; 00919 if (! b) 00920 success = false; 00921 printf("%s %d - %s\n", b ? "ok" : "ng", n++, name); 00922 } 00923 00924 template <typename T> void is(const T& x, const T& y, const char* name = "") 00925 { 00926 if (x == y) { 00927 ok(true, name); 00928 } else { 00929 ok(false, name); 00930 } 00931 } 00932 00933 #include <algorithm> 00934 #include <sstream> 00935 #include <float.h> 00936 #include <limits.h> 00937 00938 int main(void) 00939 { 00940 #if PICOJSON_USE_LOCALE 00941 setlocale(LC_ALL, ""); 00942 #endif 00943 00944 plan(85); 00945 00946 // constructors 00947 #define TEST(expr, expected) \ 00948 is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr) 00949 00950 TEST( (true), "true"); 00951 TEST( (false), "false"); 00952 TEST( (42.0), "42"); 00953 TEST( (string("hello")), "\"hello\""); 00954 TEST( ("hello"), "\"hello\""); 00955 TEST( ("hello", 4), "\"hell\""); 00956 00957 { 00958 double a = 1; 00959 for (int i = 0; i < 1024; i++) { 00960 picojson::value vi(a); 00961 std::stringstream ss; 00962 ss << vi; 00963 picojson::value vo; 00964 ss >> vo; 00965 double b = vo.get<double>(); 00966 if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) { 00967 printf("ng i=%d a=%.18e b=%.18e\n", i, a, b); 00968 } 00969 a *= 2; 00970 } 00971 } 00972 00973 #undef TEST 00974 00975 #define TEST(in, type, cmp, serialize_test) { \ 00976 picojson::value v; \ 00977 const char* s = in; \ 00978 string err = picojson::parse(v, s, s + strlen(s)); \ 00979 ok(err.empty(), in " no error"); \ 00980 ok(v.is<type>(), in " check type"); \ 00981 is<type>(v.get<type>(), cmp, in " correct output"); \ 00982 is(*s, '\0', in " read to eof"); \ 00983 if (serialize_test) { \ 00984 is(v.serialize(), string(in), in " serialize"); \ 00985 } \ 00986 } 00987 TEST("false", bool, false, true); 00988 TEST("true", bool, true, true); 00989 TEST("90.5", double, 90.5, false); 00990 TEST("1.7976931348623157e+308", double, DBL_MAX, false); 00991 TEST("\"hello\"", string, string("hello"), true); 00992 TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"), 00993 true); 00994 TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string, 00995 string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false); 00996 TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false); 00997 #undef TEST 00998 00999 #define TEST(type, expr) { \ 01000 picojson::value v; \ 01001 const char *s = expr; \ 01002 string err = picojson::parse(v, s, s + strlen(s)); \ 01003 ok(err.empty(), "empty " #type " no error"); \ 01004 ok(v.is<picojson::type>(), "empty " #type " check type"); \ 01005 ok(v.get<picojson::type>().empty(), "check " #type " array size"); \ 01006 } 01007 TEST(array, "[]"); 01008 TEST(object, "{}"); 01009 #undef TEST 01010 01011 { 01012 picojson::value v; 01013 const char *s = "[1,true,\"hello\"]"; 01014 string err = picojson::parse(v, s, s + strlen(s)); 01015 ok(err.empty(), "array no error"); 01016 ok(v.is<picojson::array>(), "array check type"); 01017 is(v.get<picojson::array>().size(), size_t(3), "check array size"); 01018 ok(v.contains(0), "check contains array[0]"); 01019 ok(v.get(0).is<double>(), "check array[0] type"); 01020 is(v.get(0).get<double>(), 1.0, "check array[0] value"); 01021 ok(v.contains(1), "check contains array[1]"); 01022 ok(v.get(1).is<bool>(), "check array[1] type"); 01023 ok(v.get(1).get<bool>(), "check array[1] value"); 01024 ok(v.contains(2), "check contains array[2]"); 01025 ok(v.get(2).is<string>(), "check array[2] type"); 01026 is(v.get(2).get<string>(), string("hello"), "check array[2] value"); 01027 ok(!v.contains(3), "check not contains array[3]"); 01028 } 01029 01030 { 01031 picojson::value v; 01032 const char *s = "{ \"a\": true }"; 01033 string err = picojson::parse(v, s, s + strlen(s)); 01034 ok(err.empty(), "object no error"); 01035 ok(v.is<picojson::object>(), "object check type"); 01036 is(v.get<picojson::object>().size(), size_t(1), "check object size"); 01037 ok(v.contains("a"), "check contains property"); 01038 ok(v.get("a").is<bool>(), "check bool property exists"); 01039 is(v.get("a").get<bool>(), true, "check bool property value"); 01040 is(v.serialize(), string("{\"a\":true}"), "serialize object"); 01041 ok(!v.contains("z"), "check not contains property"); 01042 } 01043 01044 #define TEST(json, msg) do { \ 01045 picojson::value v; \ 01046 const char *s = json; \ 01047 string err = picojson::parse(v, s, s + strlen(s)); \ 01048 is(err, string("syntax error at line " msg), msg); \ 01049 } while (0) 01050 TEST("falsoa", "1 near: oa"); 01051 TEST("{]", "1 near: ]"); 01052 TEST("\n\bbell", "2 near: bell"); 01053 TEST("\"abc\nd\"", "1 near: "); 01054 #undef TEST 01055 01056 { 01057 picojson::value v1, v2; 01058 const char *s; 01059 string err; 01060 s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 01061 err = picojson::parse(v1, s, s + strlen(s)); 01062 s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }"; 01063 err = picojson::parse(v2, s, s + strlen(s)); 01064 ok((v1 == v2), "check == operator in deep comparison"); 01065 } 01066 01067 { 01068 picojson::value v1, v2; 01069 const char *s; 01070 string err; 01071 s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 01072 err = picojson::parse(v1, s, s + strlen(s)); 01073 s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }"; 01074 err = picojson::parse(v2, s, s + strlen(s)); 01075 ok((v1 != v2), "check != operator for array in deep comparison"); 01076 } 01077 01078 { 01079 picojson::value v1, v2; 01080 const char *s; 01081 string err; 01082 s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 01083 err = picojson::parse(v1, s, s + strlen(s)); 01084 s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }"; 01085 err = picojson::parse(v2, s, s + strlen(s)); 01086 ok((v1 != v2), "check != operator for object in deep comparison"); 01087 } 01088 01089 { 01090 picojson::value v1, v2; 01091 const char *s; 01092 string err; 01093 s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; 01094 err = picojson::parse(v1, s, s + strlen(s)); 01095 picojson::object& o = v1.get<picojson::object>(); 01096 o.erase("b"); 01097 picojson::array& a = o["a"].get<picojson::array>(); 01098 picojson::array::iterator i; 01099 i = std::remove(a.begin(), a.end(), picojson::value(std::string("three"))); 01100 a.erase(i, a.end()); 01101 s = "{ \"a\": [1,2], \"d\": 2 }"; 01102 err = picojson::parse(v2, s, s + strlen(s)); 01103 ok((v1 == v2), "check erase()"); 01104 } 01105 01106 ok(picojson::value(3.0).serialize() == "3", 01107 "integral number should be serialized as a integer"); 01108 01109 { 01110 const char* s = "{ \"a\": [1,2], \"d\": 2 }"; 01111 picojson::null_parse_context ctx; 01112 string err; 01113 picojson::_parse(ctx, s, s + strlen(s), &err); 01114 ok(err.empty(), "null_parse_context"); 01115 } 01116 01117 { 01118 picojson::value v1, v2; 01119 v1 = picojson::value(true); 01120 swap(v1, v2); 01121 ok(v1.is<picojson::null>(), "swap (null)"); 01122 ok(v2.get<bool>() == true, "swap (bool)"); 01123 01124 v1 = picojson::value("a"); 01125 v2 = picojson::value(1.0); 01126 swap(v1, v2); 01127 ok(v1.get<double>() == 1.0, "swap (dobule)"); 01128 ok(v2.get<string>() == "a", "swap (string)"); 01129 01130 v1 = picojson::value(picojson::object()); 01131 v2 = picojson::value(picojson::array()); 01132 swap(v1, v2); 01133 ok(v1.is<picojson::array>(), "swap (array)"); 01134 ok(v2.is<picojson::object>(), "swap (object)"); 01135 } 01136 01137 { 01138 picojson::value v; 01139 const char *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }"; 01140 string err; 01141 err = picojson::parse(v, s, s + strlen(s)); 01142 ok(err.empty(), "parse test data for prettifying output"); 01143 ok(v.serialize() == "{\"a\":1,\"b\":[2,{\"b1\":\"abc\"}],\"c\":{},\"d\":[]}", "non-prettifying output"); 01144 ok(v.serialize(true) == "{\n \"a\": 1,\n \"b\": [\n 2,\n {\n \"b1\": \"abc\"\n }\n ],\n \"c\": {},\n \"d\": []\n}\n", "prettifying output"); 01145 } 01146 01147 return success ? 0 : 1; 01148 } 01149 01150 #endif
Generated on Tue Jul 12 2022 20:06:16 by 1.7.2