| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 #include "platform/JSONValues.h" | |
| 32 | |
| 33 #include "platform/Decimal.h" | |
| 34 #include "wtf/MathExtras.h" | |
| 35 #include "wtf/text/StringBuilder.h" | |
| 36 #include <algorithm> | |
| 37 #include <cmath> | |
| 38 | |
| 39 namespace blink { | |
| 40 | |
| 41 namespace { | |
| 42 | |
| 43 const char* const nullString = "null"; | |
| 44 const char* const trueString = "true"; | |
| 45 const char* const falseString = "false"; | |
| 46 | |
| 47 inline bool escapeChar(UChar c, StringBuilder* dst) | |
| 48 { | |
| 49 switch (c) { | |
| 50 case '\b': dst->append("\\b"); break; | |
| 51 case '\f': dst->append("\\f"); break; | |
| 52 case '\n': dst->append("\\n"); break; | |
| 53 case '\r': dst->append("\\r"); break; | |
| 54 case '\t': dst->append("\\t"); break; | |
| 55 case '\\': dst->append("\\\\"); break; | |
| 56 case '"': dst->append("\\\""); break; | |
| 57 default: | |
| 58 return false; | |
| 59 } | |
| 60 return true; | |
| 61 } | |
| 62 | |
| 63 const LChar hexDigits[17] = "0123456789ABCDEF"; | |
| 64 | |
| 65 void appendUnsignedAsHex(UChar number, StringBuilder* dst) | |
| 66 { | |
| 67 dst->append("\\u"); | |
| 68 for (size_t i = 0; i < 4; ++i) { | |
| 69 dst->append(hexDigits[(number & 0xF000) >> 12]); | |
| 70 number <<= 4; | |
| 71 } | |
| 72 } | |
| 73 | |
| 74 void writeIndent(int depth, StringBuilder* output) | |
| 75 { | |
| 76 for (int i = 0; i < depth; ++i) | |
| 77 output->append(" "); | |
| 78 } | |
| 79 | |
| 80 } // anonymous namespace | |
| 81 | |
| 82 void escapeStringForJSON(const String& str, StringBuilder* dst) | |
| 83 { | |
| 84 for (unsigned i = 0; i < str.length(); ++i) { | |
| 85 UChar c = str[i]; | |
| 86 if (!escapeChar(c, dst)) { | |
| 87 if (c < 32 || c > 126 || c == '<' || c == '>') { | |
| 88 // 1. Escaping <, > to prevent script execution. | |
| 89 // 2. Technically, we could also pass through c > 126 as UTF8, b
ut this | |
| 90 // is also optional. It would also be a pain to implement her
e. | |
| 91 appendUnsignedAsHex(c, dst); | |
| 92 } else { | |
| 93 dst->append(c); | |
| 94 } | |
| 95 } | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 void doubleQuoteStringForJSON(const String& str, StringBuilder* dst) | |
| 100 { | |
| 101 dst->append('"'); | |
| 102 escapeStringForJSON(str, dst); | |
| 103 dst->append('"'); | |
| 104 } | |
| 105 | |
| 106 String JSONValue::quoteString(const String& input) | |
| 107 { | |
| 108 StringBuilder builder; | |
| 109 doubleQuoteStringForJSON(input, &builder); | |
| 110 return builder.toString(); | |
| 111 } | |
| 112 | |
| 113 bool JSONValue::asBoolean(bool*) const | |
| 114 { | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 bool JSONValue::asDouble(double*) const | |
| 119 { | |
| 120 return false; | |
| 121 } | |
| 122 | |
| 123 bool JSONValue::asInteger(int*) const | |
| 124 { | |
| 125 return false; | |
| 126 } | |
| 127 | |
| 128 bool JSONValue::asString(String*) const | |
| 129 { | |
| 130 return false; | |
| 131 } | |
| 132 | |
| 133 String JSONValue::toJSONString() const | |
| 134 { | |
| 135 StringBuilder result; | |
| 136 result.reserveCapacity(512); | |
| 137 writeJSON(&result); | |
| 138 return result.toString(); | |
| 139 } | |
| 140 | |
| 141 String JSONValue::toPrettyJSONString() const | |
| 142 { | |
| 143 StringBuilder result; | |
| 144 result.reserveCapacity(512); | |
| 145 prettyWriteJSON(&result); | |
| 146 return result.toString(); | |
| 147 } | |
| 148 | |
| 149 void JSONValue::writeJSON(StringBuilder* output) const | |
| 150 { | |
| 151 DCHECK(m_type == TypeNull); | |
| 152 output->append(nullString, 4); | |
| 153 } | |
| 154 | |
| 155 void JSONValue::prettyWriteJSON(StringBuilder* output) const | |
| 156 { | |
| 157 prettyWriteJSONInternal(output, 0); | |
| 158 output->append('\n'); | |
| 159 } | |
| 160 | |
| 161 void JSONValue::prettyWriteJSONInternal(StringBuilder* output, int depth) const | |
| 162 { | |
| 163 writeJSON(output); | |
| 164 } | |
| 165 | |
| 166 std::unique_ptr<JSONValue> JSONValue::clone() const | |
| 167 { | |
| 168 return JSONValue::null(); | |
| 169 } | |
| 170 | |
| 171 bool JSONBasicValue::asBoolean(bool* output) const | |
| 172 { | |
| 173 if (getType() != TypeBoolean) | |
| 174 return false; | |
| 175 *output = m_boolValue; | |
| 176 return true; | |
| 177 } | |
| 178 | |
| 179 bool JSONBasicValue::asDouble(double* output) const | |
| 180 { | |
| 181 if (getType() == TypeDouble) { | |
| 182 *output = m_doubleValue; | |
| 183 return true; | |
| 184 } | |
| 185 if (getType() == TypeInteger) { | |
| 186 *output = m_integerValue; | |
| 187 return true; | |
| 188 } | |
| 189 return false; | |
| 190 } | |
| 191 | |
| 192 bool JSONBasicValue::asInteger(int* output) const | |
| 193 { | |
| 194 if (getType() != TypeInteger) | |
| 195 return false; | |
| 196 *output = m_integerValue; | |
| 197 return true; | |
| 198 } | |
| 199 | |
| 200 void JSONBasicValue::writeJSON(StringBuilder* output) const | |
| 201 { | |
| 202 DCHECK(getType() == TypeBoolean || getType() == TypeInteger || getType() ==
TypeDouble); | |
| 203 if (getType() == TypeBoolean) { | |
| 204 if (m_boolValue) | |
| 205 output->append(trueString, 4); | |
| 206 else | |
| 207 output->append(falseString, 5); | |
| 208 } else if (getType() == TypeDouble) { | |
| 209 if (!std::isfinite(m_doubleValue)) { | |
| 210 output->append(nullString, 4); | |
| 211 return; | |
| 212 } | |
| 213 output->append(Decimal::fromDouble(m_doubleValue).toString()); | |
| 214 } else if (getType() == TypeInteger) { | |
| 215 output->append(String::number(m_integerValue)); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 std::unique_ptr<JSONValue> JSONBasicValue::clone() const | |
| 220 { | |
| 221 switch (getType()) { | |
| 222 case TypeDouble: return JSONBasicValue::create(m_doubleValue); | |
| 223 case TypeInteger: return JSONBasicValue::create(m_integerValue); | |
| 224 case TypeBoolean: return JSONBasicValue::create(m_boolValue); | |
| 225 default: | |
| 226 NOTREACHED(); | |
| 227 } | |
| 228 return nullptr; | |
| 229 } | |
| 230 | |
| 231 bool JSONString::asString(String* output) const | |
| 232 { | |
| 233 *output = m_stringValue; | |
| 234 return true; | |
| 235 } | |
| 236 | |
| 237 void JSONString::writeJSON(StringBuilder* output) const | |
| 238 { | |
| 239 DCHECK(getType() == TypeString); | |
| 240 doubleQuoteStringForJSON(m_stringValue, output); | |
| 241 } | |
| 242 | |
| 243 std::unique_ptr<JSONValue> JSONString::clone() const | |
| 244 { | |
| 245 return JSONString::create(m_stringValue); | |
| 246 } | |
| 247 | |
| 248 JSONObject::~JSONObject() | |
| 249 { | |
| 250 } | |
| 251 | |
| 252 void JSONObject::setBoolean(const String& name, bool value) | |
| 253 { | |
| 254 setValue(name, JSONBasicValue::create(value)); | |
| 255 } | |
| 256 | |
| 257 void JSONObject::setInteger(const String& name, int value) | |
| 258 { | |
| 259 setValue(name, JSONBasicValue::create(value)); | |
| 260 } | |
| 261 | |
| 262 void JSONObject::setDouble(const String& name, double value) | |
| 263 { | |
| 264 setValue(name, JSONBasicValue::create(value)); | |
| 265 } | |
| 266 | |
| 267 void JSONObject::setString(const String& name, const String& value) | |
| 268 { | |
| 269 setValue(name, JSONString::create(value)); | |
| 270 } | |
| 271 | |
| 272 void JSONObject::setValue(const String& name, std::unique_ptr<JSONValue> value) | |
| 273 { | |
| 274 set(name, value); | |
| 275 } | |
| 276 | |
| 277 void JSONObject::setObject(const String& name, std::unique_ptr<JSONObject> value
) | |
| 278 { | |
| 279 set(name, value); | |
| 280 } | |
| 281 | |
| 282 void JSONObject::setArray(const String& name, std::unique_ptr<JSONArray> value) | |
| 283 { | |
| 284 set(name, value); | |
| 285 } | |
| 286 | |
| 287 bool JSONObject::getBoolean(const String& name, bool* output) const | |
| 288 { | |
| 289 JSONValue* value = get(name); | |
| 290 if (!value) | |
| 291 return false; | |
| 292 return value->asBoolean(output); | |
| 293 } | |
| 294 | |
| 295 bool JSONObject::getInteger(const String& name, int* output) const | |
| 296 { | |
| 297 JSONValue* value = get(name); | |
| 298 if (!value) | |
| 299 return false; | |
| 300 return value->asInteger(output); | |
| 301 } | |
| 302 | |
| 303 bool JSONObject::getDouble(const String& name, double* output) const | |
| 304 { | |
| 305 JSONValue* value = get(name); | |
| 306 if (!value) | |
| 307 return false; | |
| 308 return value->asDouble(output); | |
| 309 } | |
| 310 | |
| 311 bool JSONObject::getString(const String& name, String* output) const | |
| 312 { | |
| 313 JSONValue* value = get(name); | |
| 314 if (!value) | |
| 315 return false; | |
| 316 return value->asString(output); | |
| 317 } | |
| 318 | |
| 319 JSONObject* JSONObject::getObject(const String& name) const | |
| 320 { | |
| 321 return JSONObject::cast(get(name)); | |
| 322 } | |
| 323 | |
| 324 JSONArray* JSONObject::getArray(const String& name) const | |
| 325 { | |
| 326 return JSONArray::cast(get(name)); | |
| 327 } | |
| 328 | |
| 329 JSONValue* JSONObject::get(const String& name) const | |
| 330 { | |
| 331 Dictionary::const_iterator it = m_data.find(name); | |
| 332 if (it == m_data.end()) | |
| 333 return nullptr; | |
| 334 return it->value.get(); | |
| 335 } | |
| 336 | |
| 337 JSONObject::Entry JSONObject::at(size_t index) const | |
| 338 { | |
| 339 const String key = m_order[index]; | |
| 340 return std::make_pair(key, m_data.find(key)->value.get()); | |
| 341 } | |
| 342 | |
| 343 bool JSONObject::booleanProperty(const String& name, bool defaultValue) const | |
| 344 { | |
| 345 bool result = defaultValue; | |
| 346 getBoolean(name, &result); | |
| 347 return result; | |
| 348 } | |
| 349 | |
| 350 int JSONObject::integerProperty(const String& name, int defaultValue) const | |
| 351 { | |
| 352 int result = defaultValue; | |
| 353 getInteger(name, &result); | |
| 354 return result; | |
| 355 } | |
| 356 | |
| 357 double JSONObject::doubleProperty(const String& name, double defaultValue) const | |
| 358 { | |
| 359 double result = defaultValue; | |
| 360 getDouble(name, &result); | |
| 361 return result; | |
| 362 } | |
| 363 | |
| 364 void JSONObject::remove(const String& name) | |
| 365 { | |
| 366 m_data.remove(name); | |
| 367 for (size_t i = 0; i < m_order.size(); ++i) { | |
| 368 if (m_order[i] == name) { | |
| 369 m_order.remove(i); | |
| 370 break; | |
| 371 } | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 void JSONObject::writeJSON(StringBuilder* output) const | |
| 376 { | |
| 377 output->append('{'); | |
| 378 for (size_t i = 0; i < m_order.size(); ++i) { | |
| 379 Dictionary::const_iterator it = m_data.find(m_order[i]); | |
| 380 CHECK(it != m_data.end()); | |
| 381 if (i) | |
| 382 output->append(','); | |
| 383 doubleQuoteStringForJSON(it->key, output); | |
| 384 output->append(':'); | |
| 385 it->value->writeJSON(output); | |
| 386 } | |
| 387 output->append('}'); | |
| 388 } | |
| 389 | |
| 390 void JSONObject::prettyWriteJSONInternal(StringBuilder* output, int depth) const | |
| 391 { | |
| 392 output->append("{\n"); | |
| 393 for (size_t i = 0; i < m_order.size(); ++i) { | |
| 394 Dictionary::const_iterator it = m_data.find(m_order[i]); | |
| 395 CHECK(it != m_data.end()); | |
| 396 if (i) | |
| 397 output->append(",\n"); | |
| 398 writeIndent(depth + 1, output); | |
| 399 doubleQuoteStringForJSON(it->key, output); | |
| 400 output->append(": "); | |
| 401 it->value->prettyWriteJSONInternal(output, depth + 1); | |
| 402 } | |
| 403 output->append('\n'); | |
| 404 writeIndent(depth, output); | |
| 405 output->append('}'); | |
| 406 } | |
| 407 | |
| 408 std::unique_ptr<JSONValue> JSONObject::clone() const | |
| 409 { | |
| 410 std::unique_ptr<JSONObject> result = JSONObject::create(); | |
| 411 for (size_t i = 0; i < m_order.size(); ++i) { | |
| 412 String key = m_order[i]; | |
| 413 Dictionary::const_iterator value = m_data.find(key); | |
| 414 DCHECK(value != m_data.end() && value->value); | |
| 415 result->setValue(key, value->value->clone()); | |
| 416 } | |
| 417 return std::move(result); | |
| 418 } | |
| 419 | |
| 420 JSONObject::JSONObject() | |
| 421 : JSONValue(TypeObject) | |
| 422 , m_data() | |
| 423 , m_order() | |
| 424 { | |
| 425 } | |
| 426 | |
| 427 JSONArray::~JSONArray() | |
| 428 { | |
| 429 } | |
| 430 | |
| 431 void JSONArray::writeJSON(StringBuilder* output) const | |
| 432 { | |
| 433 output->append('['); | |
| 434 bool first = true; | |
| 435 for (const std::unique_ptr<JSONValue>& value : m_data) { | |
| 436 if (!first) | |
| 437 output->append(','); | |
| 438 value->writeJSON(output); | |
| 439 first = false; | |
| 440 } | |
| 441 output->append(']'); | |
| 442 } | |
| 443 | |
| 444 void JSONArray::prettyWriteJSONInternal(StringBuilder* output, int depth) const | |
| 445 { | |
| 446 output->append('['); | |
| 447 bool first = true; | |
| 448 bool lastInsertedNewLine = false; | |
| 449 for (const std::unique_ptr<JSONValue>& value : m_data) { | |
| 450 bool insertNewLine = value->getType() == JSONValue::TypeObject || value-
>getType() == JSONValue::TypeArray || value->getType() == JSONValue::TypeString; | |
| 451 if (first) { | |
| 452 if (insertNewLine) { | |
| 453 output->append('\n'); | |
| 454 writeIndent(depth + 1, output); | |
| 455 } | |
| 456 first = false; | |
| 457 } else { | |
| 458 output->append(','); | |
| 459 if (lastInsertedNewLine) { | |
| 460 output->append('\n'); | |
| 461 writeIndent(depth + 1, output); | |
| 462 } else { | |
| 463 output->append(' '); | |
| 464 } | |
| 465 } | |
| 466 value->prettyWriteJSONInternal(output, depth + 1); | |
| 467 lastInsertedNewLine = insertNewLine; | |
| 468 } | |
| 469 if (lastInsertedNewLine) { | |
| 470 output->append('\n'); | |
| 471 writeIndent(depth, output); | |
| 472 } | |
| 473 output->append(']'); | |
| 474 } | |
| 475 | |
| 476 std::unique_ptr<JSONValue> JSONArray::clone() const | |
| 477 { | |
| 478 std::unique_ptr<JSONArray> result = JSONArray::create(); | |
| 479 for (const std::unique_ptr<JSONValue>& value : m_data) | |
| 480 result->pushValue(value->clone()); | |
| 481 return std::move(result); | |
| 482 } | |
| 483 | |
| 484 JSONArray::JSONArray() | |
| 485 : JSONValue(TypeArray) | |
| 486 { | |
| 487 } | |
| 488 | |
| 489 void JSONArray::pushBoolean(bool value) | |
| 490 { | |
| 491 m_data.append(JSONBasicValue::create(value)); | |
| 492 } | |
| 493 | |
| 494 void JSONArray::pushInteger(int value) | |
| 495 { | |
| 496 m_data.append(JSONBasicValue::create(value)); | |
| 497 } | |
| 498 | |
| 499 void JSONArray::pushDouble(double value) | |
| 500 { | |
| 501 m_data.append(JSONBasicValue::create(value)); | |
| 502 } | |
| 503 | |
| 504 void JSONArray::pushString(const String& value) | |
| 505 { | |
| 506 m_data.append(JSONString::create(value)); | |
| 507 } | |
| 508 | |
| 509 void JSONArray::pushValue(std::unique_ptr<JSONValue> value) | |
| 510 { | |
| 511 DCHECK(value); | |
| 512 m_data.append(std::move(value)); | |
| 513 } | |
| 514 | |
| 515 void JSONArray::pushObject(std::unique_ptr<JSONObject> value) | |
| 516 { | |
| 517 DCHECK(value); | |
| 518 m_data.append(std::move(value)); | |
| 519 } | |
| 520 | |
| 521 void JSONArray::pushArray(std::unique_ptr<JSONArray> value) | |
| 522 { | |
| 523 DCHECK(value); | |
| 524 m_data.append(std::move(value)); | |
| 525 } | |
| 526 | |
| 527 JSONValue* JSONArray::at(size_t index) | |
| 528 { | |
| 529 DCHECK_LT(index, m_data.size()); | |
| 530 return m_data[index].get(); | |
| 531 } | |
| 532 | |
| 533 } // namespace blink | |
| OLD | NEW |