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 "config.h" 32 #include "platform/JSONValues.h" 33 34 #include "platform/Decimal.h" 35 #include "wtf/MathExtras.h" 36 #include "wtf/text/StringBuilder.h" 37 38 namespace blink { 39 40 namespace { 41 42 const char* const nullString = "null"; 43 const char* const trueString = "true"; 44 const char* const falseString = "false"; 45 46 inline bool escapeChar(UChar c, StringBuilder* dst) 47 { 48 switch (c) { 49 case '\b': dst->appendLiteral("\\b"); break; 50 case '\f': dst->appendLiteral("\\f"); break; 51 case '\n': dst->appendLiteral("\\n"); break; 52 case '\r': dst->appendLiteral("\\r"); break; 53 case '\t': dst->appendLiteral("\\t"); break; 54 case '\\': dst->appendLiteral("\\\\"); break; 55 case '"': dst->appendLiteral("\\\""); break; 56 default: 57 return false; 58 } 59 return true; 60 } 61 62 inline void doubleQuoteString(const String& str, StringBuilder* dst) 63 { 64 dst->append('"'); 65 for (unsigned i = 0; i < str.length(); ++i) { 66 UChar c = str[i]; 67 if (!escapeChar(c, dst)) { 68 if (c < 32 || c > 126 || c == '<' || c == '>') { 69 // 1. Escaping <, > to prevent script execution. 70 // 2. Technically, we could also pass through c > 126 as UTF8, but this 71 // is also optional. It would also be a pain to implement here. 72 unsigned symbol = static_cast<unsigned>(c); 73 String symbolCode = String::format("\\u%04X", symbol); 74 dst->append(symbolCode); 75 } else { 76 dst->append(c); 77 } 78 } 79 } 80 dst->append('"'); 81 } 82 83 void writeIndent(int depth, StringBuilder* output) 84 { 85 for (int i = 0; i < depth; ++i) 86 output->appendLiteral(" "); 87 } 88 89 } // anonymous namespace 90 91 bool JSONValue::asBoolean(bool*) const 92 { 93 return false; 94 } 95 96 bool JSONValue::asNumber(double*) const 97 { 98 return false; 99 } 100 101 bool JSONValue::asNumber(long*) const 102 { 103 return false; 104 } 105 106 bool JSONValue::asNumber(int*) const 107 { 108 return false; 109 } 110 111 bool JSONValue::asNumber(unsigned long*) const 112 { 113 return false; 114 } 115 116 bool JSONValue::asNumber(unsigned*) const 117 { 118 return false; 119 } 120 121 bool JSONValue::asString(String*) const 122 { 123 return false; 124 } 125 126 bool JSONValue::asValue(RefPtr<JSONValue>* output) 127 { 128 *output = this; 129 return true; 130 } 131 132 bool JSONValue::asObject(RefPtr<JSONObject>*) 133 { 134 return false; 135 } 136 137 bool JSONValue::asArray(RefPtr<JSONArray>*) 138 { 139 return false; 140 } 141 142 PassRefPtr<JSONObject> JSONValue::asObject() 143 { 144 return nullptr; 145 } 146 147 PassRefPtr<JSONArray> JSONValue::asArray() 148 { 149 return nullptr; 150 } 151 152 String JSONValue::toJSONString() const 153 { 154 StringBuilder result; 155 result.reserveCapacity(512); 156 writeJSON(&result); 157 return result.toString(); 158 } 159 160 String JSONValue::toPrettyJSONString() const 161 { 162 StringBuilder result; 163 result.reserveCapacity(512); 164 prettyWriteJSON(&result); 165 return result.toString(); 166 } 167 168 void JSONValue::writeJSON(StringBuilder* output) const 169 { 170 ASSERT(m_type == TypeNull); 171 output->append(nullString, 4); 172 } 173 174 void JSONValue::prettyWriteJSON(StringBuilder* output) const 175 { 176 prettyWriteJSONInternal(output, 0); 177 output->append('\n'); 178 } 179 180 void JSONValue::prettyWriteJSONInternal(StringBuilder* output, int depth) const 181 { 182 writeJSON(output); 183 } 184 185 bool JSONBasicValue::asBoolean(bool* output) const 186 { 187 if (type() != TypeBoolean) 188 return false; 189 *output = m_boolValue; 190 return true; 191 } 192 193 bool JSONBasicValue::asNumber(double* output) const 194 { 195 if (type() != TypeNumber) 196 return false; 197 *output = m_doubleValue; 198 return true; 199 } 200 201 bool JSONBasicValue::asNumber(long* output) const 202 { 203 if (type() != TypeNumber) 204 return false; 205 *output = static_cast<long>(m_doubleValue); 206 return true; 207 } 208 209 bool JSONBasicValue::asNumber(int* output) const 210 { 211 if (type() != TypeNumber) 212 return false; 213 *output = static_cast<int>(m_doubleValue); 214 return true; 215 } 216 217 bool JSONBasicValue::asNumber(unsigned long* output) const 218 { 219 if (type() != TypeNumber) 220 return false; 221 *output = static_cast<unsigned long>(m_doubleValue); 222 return true; 223 } 224 225 bool JSONBasicValue::asNumber(unsigned* output) const 226 { 227 if (type() != TypeNumber) 228 return false; 229 *output = static_cast<unsigned>(m_doubleValue); 230 return true; 231 } 232 233 void JSONBasicValue::writeJSON(StringBuilder* output) const 234 { 235 ASSERT(type() == TypeBoolean || type() == TypeNumber); 236 if (type() == TypeBoolean) { 237 if (m_boolValue) 238 output->append(trueString, 4); 239 else 240 output->append(falseString, 5); 241 } else if (type() == TypeNumber) { 242 if (!std::isfinite(m_doubleValue)) { 243 output->append(nullString, 4); 244 return; 245 } 246 output->append(Decimal::fromDouble(m_doubleValue).toString()); 247 } 248 } 249 250 bool JSONString::asString(String* output) const 251 { 252 *output = m_stringValue; 253 return true; 254 } 255 256 void JSONString::writeJSON(StringBuilder* output) const 257 { 258 ASSERT(type() == TypeString); 259 doubleQuoteString(m_stringValue, output); 260 } 261 262 JSONObjectBase::~JSONObjectBase() 263 { 264 } 265 266 bool JSONObjectBase::asObject(RefPtr<JSONObject>* output) 267 { 268 COMPILE_ASSERT(sizeof(JSONObject) == sizeof(JSONObjectBase), cannot_cast); 269 *output = static_cast<JSONObject*>(this); 270 return true; 271 } 272 273 PassRefPtr<JSONObject> JSONObjectBase::asObject() 274 { 275 return openAccessors(); 276 } 277 278 void JSONObjectBase::setBoolean(const String& name, bool value) 279 { 280 setValue(name, JSONBasicValue::create(value)); 281 } 282 283 void JSONObjectBase::setNumber(const String& name, double value) 284 { 285 setValue(name, JSONBasicValue::create(value)); 286 } 287 288 void JSONObjectBase::setString(const String& name, const String& value) 289 { 290 setValue(name, JSONString::create(value)); 291 } 292 293 void JSONObjectBase::setValue(const String& name, PassRefPtr<JSONValue> value) 294 { 295 ASSERT(value); 296 if (m_data.set(name, value).isNewEntry) 297 m_order.append(name); 298 } 299 300 void JSONObjectBase::setObject(const String& name, PassRefPtr<JSONObject> value) 301 { 302 ASSERT(value); 303 if (m_data.set(name, value).isNewEntry) 304 m_order.append(name); 305 } 306 307 void JSONObjectBase::setArray(const String& name, PassRefPtr<JSONArray> value) 308 { 309 ASSERT(value); 310 if (m_data.set(name, value).isNewEntry) 311 m_order.append(name); 312 } 313 314 JSONObject* JSONObjectBase::openAccessors() 315 { 316 COMPILE_ASSERT(sizeof(JSONObject) == sizeof(JSONObjectBase), cannot_cast); 317 return static_cast<JSONObject*>(this); 318 } 319 320 JSONObjectBase::iterator JSONObjectBase::find(const String& name) 321 { 322 return m_data.find(name); 323 } 324 325 JSONObjectBase::const_iterator JSONObjectBase::find(const String& name) const 326 { 327 return m_data.find(name); 328 } 329 330 bool JSONObjectBase::getBoolean(const String& name, bool* output) const 331 { 332 RefPtr<JSONValue> value = get(name); 333 if (!value) 334 return false; 335 return value->asBoolean(output); 336 } 337 338 bool JSONObjectBase::getString(const String& name, String* output) const 339 { 340 RefPtr<JSONValue> value = get(name); 341 if (!value) 342 return false; 343 return value->asString(output); 344 } 345 346 PassRefPtr<JSONObject> JSONObjectBase::getObject(const String& name) const 347 { 348 RefPtr<JSONValue> value = get(name); 349 if (!value) 350 return nullptr; 351 return value->asObject(); 352 } 353 354 PassRefPtr<JSONArray> JSONObjectBase::getArray(const String& name) const 355 { 356 RefPtr<JSONValue> value = get(name); 357 if (!value) 358 return nullptr; 359 return value->asArray(); 360 } 361 362 PassRefPtr<JSONValue> JSONObjectBase::get(const String& name) const 363 { 364 Dictionary::const_iterator it = m_data.find(name); 365 if (it == m_data.end()) 366 return nullptr; 367 return it->value; 368 } 369 370 void JSONObjectBase::remove(const String& name) 371 { 372 m_data.remove(name); 373 for (size_t i = 0; i < m_order.size(); ++i) { 374 if (m_order[i] == name) { 375 m_order.remove(i); 376 break; 377 } 378 } 379 } 380 381 void JSONObjectBase::writeJSON(StringBuilder* output) const 382 { 383 output->append('{'); 384 for (size_t i = 0; i < m_order.size(); ++i) { 385 Dictionary::const_iterator it = m_data.find(m_order[i]); 386 ASSERT_WITH_SECURITY_IMPLICATION(it != m_data.end()); 387 if (i) 388 output->append(','); 389 doubleQuoteString(it->key, output); 390 output->append(':'); 391 it->value->writeJSON(output); 392 } 393 output->append('}'); 394 } 395 396 void JSONObjectBase::prettyWriteJSONInternal(StringBuilder* output, int depth) const 397 { 398 output->appendLiteral("{\n"); 399 for (size_t i = 0; i < m_order.size(); ++i) { 400 Dictionary::const_iterator it = m_data.find(m_order[i]); 401 ASSERT_WITH_SECURITY_IMPLICATION(it != m_data.end()); 402 if (i) 403 output->appendLiteral(",\n"); 404 writeIndent(depth + 1, output); 405 doubleQuoteString(it->key, output); 406 output->appendLiteral(": "); 407 it->value->prettyWriteJSONInternal(output, depth + 1); 408 } 409 output->append('\n'); 410 writeIndent(depth, output); 411 output->append('}'); 412 } 413 414 JSONObjectBase::JSONObjectBase() 415 : JSONValue(TypeObject) 416 , m_data() 417 , m_order() 418 { 419 } 420 421 JSONArrayBase::~JSONArrayBase() 422 { 423 } 424 425 bool JSONArrayBase::asArray(RefPtr<JSONArray>* output) 426 { 427 COMPILE_ASSERT(sizeof(JSONArrayBase) == sizeof(JSONArray), cannot_cast); 428 *output = static_cast<JSONArray*>(this); 429 return true; 430 } 431 432 PassRefPtr<JSONArray> JSONArrayBase::asArray() 433 { 434 COMPILE_ASSERT(sizeof(JSONArrayBase) == sizeof(JSONArray), cannot_cast); 435 return static_cast<JSONArray*>(this); 436 } 437 438 void JSONArrayBase::writeJSON(StringBuilder* output) const 439 { 440 output->append('['); 441 for (Vector<RefPtr<JSONValue> >::const_iterator it = m_data.begin(); it != m_data.end(); ++it) { 442 if (it != m_data.begin()) 443 output->append(','); 444 (*it)->writeJSON(output); 445 } 446 output->append(']'); 447 } 448 449 void JSONArrayBase::prettyWriteJSONInternal(StringBuilder* output, int depth) const 450 { 451 output->append('['); 452 bool lastIsArrayOrObject = false; 453 for (Vector<RefPtr<JSONValue> >::const_iterator it = m_data.begin(); it != m_data.end(); ++it) { 454 bool isArrayOrObject = (*it)->type() == JSONValue::TypeObject || (*it)->type() == JSONValue::TypeArray; 455 if (it == m_data.begin()) { 456 if (isArrayOrObject) { 457 output->append('\n'); 458 writeIndent(depth + 1, output); 459 } 460 } else { 461 output->append(','); 462 if (lastIsArrayOrObject) { 463 output->append('\n'); 464 writeIndent(depth + 1, output); 465 } else { 466 output->append(' '); 467 } 468 } 469 (*it)->prettyWriteJSONInternal(output, depth + 1); 470 lastIsArrayOrObject = isArrayOrObject; 471 } 472 if (lastIsArrayOrObject) { 473 output->append('\n'); 474 writeIndent(depth, output); 475 } 476 output->append(']'); 477 } 478 479 JSONArrayBase::JSONArrayBase() 480 : JSONValue(TypeArray) 481 , m_data() 482 { 483 } 484 485 void JSONArrayBase::pushBoolean(bool value) 486 { 487 m_data.append(JSONBasicValue::create(value)); 488 } 489 490 void JSONArrayBase::pushInt(int value) 491 { 492 m_data.append(JSONBasicValue::create(value)); 493 } 494 495 void JSONArrayBase::pushNumber(double value) 496 { 497 m_data.append(JSONBasicValue::create(value)); 498 } 499 500 void JSONArrayBase::pushString(const String& value) 501 { 502 m_data.append(JSONString::create(value)); 503 } 504 505 void JSONArrayBase::pushValue(PassRefPtr<JSONValue> value) 506 { 507 ASSERT(value); 508 m_data.append(value); 509 } 510 511 void JSONArrayBase::pushObject(PassRefPtr<JSONObject> value) 512 { 513 ASSERT(value); 514 m_data.append(value); 515 } 516 517 void JSONArrayBase::pushArray(PassRefPtr<JSONArray> value) 518 { 519 ASSERT(value); 520 m_data.append(value); 521 } 522 523 PassRefPtr<JSONValue> JSONArrayBase::get(size_t index) 524 { 525 ASSERT_WITH_SECURITY_IMPLICATION(index < m_data.size()); 526 return m_data[index]; 527 } 528 529 } // namespace blink 530