mbedからGluinサーバへ接続するライブラリです

Dependents:   Servo_DxDevice

Committer:
komoritan
Date:
Sat Feb 14 00:28:40 2015 +0000
Revision:
0:735163979ecf
First Release

Who changed what in which revision?

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