Changeset 60774 in webkit
- Timestamp:
- Jun 7, 2010 4:33:11 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r60772 r60774 1 2010-06-07 Pavel Podivilov <podivilov@chromium.org> 2 3 Reviewed by Pavel Feldman. 4 5 Web Inspector: Implement JSON parsing for InspectorValue. 6 https://bugs.webkit.org/show_bug.cgi?id=40064 7 8 * inspector/InspectorValues.cpp: 9 (WebCore::): 10 (WebCore::InspectorValue::asBool): 11 (WebCore::InspectorValue::asNumber): 12 (WebCore::InspectorValue::asString): 13 (WebCore::InspectorValue::asObject): 14 (WebCore::InspectorValue::asArray): 15 (WebCore::InspectorValue::readJSON): 16 (WebCore::InspectorValue::writeJSON): 17 (WebCore::InspectorBasicValue::asBool): 18 (WebCore::InspectorBasicValue::asNumber): 19 (WebCore::InspectorBasicValue::writeJSON): 20 (WebCore::InspectorString::asString): 21 (WebCore::InspectorObject::asObject): 22 (WebCore::InspectorObject::getBool): 23 (WebCore::InspectorObject::getNumber): 24 (WebCore::InspectorObject::getString): 25 (WebCore::InspectorObject::getObject): 26 (WebCore::InspectorObject::getArray): 27 (WebCore::InspectorObject::get): 28 (WebCore::InspectorArray::asArray): 29 * inspector/InspectorValues.h: 30 (WebCore::InspectorObject::begin): 31 (WebCore::InspectorObject::end): 32 1 33 2010-06-07 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> 2 34 -
trunk/WebCore/inspector/InspectorValues.cpp
r60687 r60774 36 36 namespace WebCore { 37 37 38 namespace { 39 40 static const int stackLimit = 1000; 41 42 enum Token { 43 OBJECT_BEGIN, 44 OBJECT_END, 45 ARRAY_BEGIN, 46 ARRAY_END, 47 STRING, 48 NUMBER, 49 BOOL_TRUE, 50 BOOL_FALSE, 51 NULL_TOKEN, 52 LIST_SEPARATOR, 53 OBJECT_PAIR_SEPARATOR, 54 INVALID_TOKEN, 55 }; 56 57 const char* const nullString = "null"; 58 const char* const trueString = "true"; 59 const char* const falseString = "false"; 60 61 bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token) 62 { 63 while (start < end && *token != '\0' && *start++ == *token++) { } 64 if (*token != '\0') 65 return false; 66 *tokenEnd = start; 67 return true; 68 } 69 70 bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros) 71 { 72 if (start == end) 73 return false; 74 bool haveLeadingZero = '0' == *start; 75 int length = 0; 76 while (start < end && '0' <= *start && *start <= '9') { 77 ++start; 78 ++length; 79 } 80 if (!length) 81 return false; 82 if (!canHaveLeadingZeros && length > 1 && haveLeadingZero) 83 return false; 84 *tokenEnd = start; 85 return true; 86 } 87 88 bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd) 89 { 90 // We just grab the number here. We validate the size in DecodeNumber. 91 // According to RFC4627, a valid number is: [minus] int [frac] [exp] 92 if (start == end) 93 return false; 94 UChar c = *start; 95 if ('-' == c) 96 ++start; 97 98 if (!readInt(start, end, &start, false)) 99 return false; 100 if (start == end) { 101 *tokenEnd = start; 102 return true; 103 } 104 105 // Optional fraction part 106 c = *start; 107 if ('.' == c) { 108 ++start; 109 if (!readInt(start, end, &start, true)) 110 return false; 111 if (start == end) { 112 *tokenEnd = start; 113 return true; 114 } 115 c = *start; 116 } 117 118 // Optional exponent part 119 if ('e' == c || 'E' == c) { 120 ++start; 121 if (start == end) 122 return false; 123 c = *start; 124 if ('-' == c || '+' == c) { 125 ++start; 126 if (start == end) 127 return false; 128 } 129 if (!readInt(start, end, &start, true)) 130 return false; 131 } 132 133 *tokenEnd = start; 134 return true; 135 } 136 137 bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits) 138 { 139 if (end - start < digits) 140 return false; 141 for (int i = 0; i < digits; ++i) { 142 UChar c = *start++; 143 if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))) 144 return false; 145 } 146 *tokenEnd = start; 147 return true; 148 } 149 150 bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd) 151 { 152 while (start < end) { 153 UChar c = *start++; 154 if ('\\' == c) { 155 c = *start++; 156 // Make sure the escaped char is valid. 157 switch (c) { 158 case 'x': 159 if (!readHexDigits(start, end, &start, 2)) 160 return false; 161 break; 162 case 'u': 163 if (!readHexDigits(start, end, &start, 4)) 164 return false; 165 break; 166 case '\\': 167 case '/': 168 case 'b': 169 case 'f': 170 case 'n': 171 case 'r': 172 case 't': 173 case 'v': 174 case '"': 175 break; 176 default: 177 return false; 178 } 179 } else if ('"' == c) { 180 *tokenEnd = start; 181 return true; 182 } 183 } 184 return false; 185 } 186 187 Token parseToken(const UChar* start, const UChar* end, const UChar** tokenEnd) 188 { 189 if (start == end) 190 return INVALID_TOKEN; 191 192 switch (*start) { 193 case 'n': 194 if (parseConstToken(start, end, tokenEnd, nullString)) 195 return NULL_TOKEN; 196 break; 197 case 't': 198 if (parseConstToken(start, end, tokenEnd, trueString)) 199 return BOOL_TRUE; 200 break; 201 case 'f': 202 if (parseConstToken(start, end, tokenEnd, falseString)) 203 return BOOL_FALSE; 204 break; 205 case '[': 206 *tokenEnd = start + 1; 207 return ARRAY_BEGIN; 208 case ']': 209 *tokenEnd = start + 1; 210 return ARRAY_END; 211 case ',': 212 *tokenEnd = start + 1; 213 return LIST_SEPARATOR; 214 case '{': 215 *tokenEnd = start + 1; 216 return OBJECT_BEGIN; 217 case '}': 218 *tokenEnd = start + 1; 219 return OBJECT_END; 220 case ':': 221 *tokenEnd = start + 1; 222 return OBJECT_PAIR_SEPARATOR; 223 case '0': 224 case '1': 225 case '2': 226 case '3': 227 case '4': 228 case '5': 229 case '6': 230 case '7': 231 case '8': 232 case '9': 233 case '-': 234 if (parseNumberToken(start, end, tokenEnd)) 235 return NUMBER; 236 break; 237 case '"': 238 if (parseStringToken(start + 1, end, tokenEnd)) 239 return STRING; 240 break; 241 } 242 return INVALID_TOKEN; 243 } 244 245 inline int hexToInt(UChar c) 246 { 247 if ('0' <= c && c <= '9') 248 return c - '0'; 249 if ('A' <= c && c <= 'F') 250 return c - 'A' + 10; 251 if ('a' <= c && c <= 'f') 252 return c - 'a' + 10; 253 ASSERT_NOT_REACHED(); 254 return 0; 255 } 256 257 bool decodeString(const UChar* start, const UChar* end, Vector<UChar>* output) 258 { 259 while (start < end) { 260 UChar c = *start++; 261 if ('\\' != c) { 262 output->append(c); 263 continue; 264 } 265 c = *start++; 266 switch (c) { 267 case '"': 268 case '/': 269 case '\\': 270 break; 271 case 'b': 272 c = '\b'; 273 break; 274 case 'f': 275 c = '\f'; 276 break; 277 case 'n': 278 c = '\n'; 279 break; 280 case 'r': 281 c = '\r'; 282 break; 283 case 't': 284 c = '\t'; 285 break; 286 case 'v': 287 c = '\v'; 288 break; 289 case 'x': 290 c = (hexToInt(*start) << 4) + 291 hexToInt(*(start + 1)); 292 start += 2; 293 break; 294 case 'u': 295 c = (hexToInt(*start) << 12) + 296 (hexToInt(*(start + 1)) << 8) + 297 (hexToInt(*(start + 2)) << 4) + 298 hexToInt(*(start + 3)); 299 start += 4; 300 break; 301 default: 302 return false; 303 } 304 output->append(c); 305 } 306 return true; 307 } 308 309 bool decodeString(const UChar* start, const UChar* end, String* output) 310 { 311 if (start == end) { 312 *output = ""; 313 return true; 314 } 315 if (start > end) 316 return false; 317 Vector<UChar> buffer; 318 buffer.reserveCapacity(end - start); 319 if (!decodeString(start, end, &buffer)) 320 return false; 321 *output = String(buffer.data(), buffer.size()); 322 return true; 323 } 324 325 PassRefPtr<InspectorValue> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth) 326 { 327 if (depth > stackLimit) 328 return 0; 329 330 RefPtr<InspectorValue> result; 331 const UChar* tokenEnd; 332 Token token = parseToken(start, end, &tokenEnd); 333 switch (token) { 334 case INVALID_TOKEN: 335 return 0; 336 case NULL_TOKEN: 337 result = InspectorValue::null(); 338 break; 339 case BOOL_TRUE: 340 result = InspectorBasicValue::create(true); 341 break; 342 case BOOL_FALSE: 343 result = InspectorBasicValue::create(false); 344 break; 345 case NUMBER: { 346 bool ok; 347 double value = charactersToDouble(start, tokenEnd - start, &ok); 348 if (!ok) 349 return 0; 350 result = InspectorBasicValue::create(value); 351 break; 352 } 353 case STRING: { 354 String value; 355 bool ok = decodeString(start + 1, tokenEnd - 1, &value); 356 if (!ok) 357 return 0; 358 result = InspectorString::create(value); 359 break; 360 } 361 case ARRAY_BEGIN: { 362 RefPtr<InspectorArray> array = InspectorArray::create(); 363 start = tokenEnd; 364 token = parseToken(start, end, &tokenEnd); 365 while (token != ARRAY_END) { 366 RefPtr<InspectorValue> arrayNode = buildValue(start, end, &tokenEnd, depth + 1); 367 if (!arrayNode) 368 return 0; 369 array->push(arrayNode); 370 371 // After a list value, we expect a comma or the end of the list. 372 start = tokenEnd; 373 token = parseToken(start, end, &tokenEnd); 374 if (token == LIST_SEPARATOR) { 375 start = tokenEnd; 376 token = parseToken(start, end, &tokenEnd); 377 if (token == ARRAY_END) 378 return 0; 379 } else if (token != ARRAY_END) { 380 // Unexpected value after list value. Bail out. 381 return 0; 382 } 383 } 384 if (token != ARRAY_END) 385 return 0; 386 result = array.release(); 387 break; 388 } 389 case OBJECT_BEGIN: { 390 RefPtr<InspectorObject> object = InspectorObject::create(); 391 start = tokenEnd; 392 token = parseToken(start, end, &tokenEnd); 393 while (token != OBJECT_END) { 394 if (token != STRING) 395 return 0; 396 String key; 397 if (!decodeString(start + 1, tokenEnd - 1, &key)) 398 return 0; 399 start = tokenEnd; 400 401 token = parseToken(start, end, &tokenEnd); 402 if (token != OBJECT_PAIR_SEPARATOR) 403 return 0; 404 start = tokenEnd; 405 406 RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, depth + 1); 407 if (!value) 408 return 0; 409 object->set(key, value); 410 start = tokenEnd; 411 412 // After a key/value pair, we expect a comma or the end of the 413 // object. 414 token = parseToken(start, end, &tokenEnd); 415 if (token == LIST_SEPARATOR) { 416 start = tokenEnd; 417 token = parseToken(start, end, &tokenEnd); 418 if (token == OBJECT_END) 419 return 0; 420 } else if (token != OBJECT_END) { 421 // Unexpected value after last object value. Bail out. 422 return 0; 423 } 424 } 425 if (token != OBJECT_END) 426 return 0; 427 result = object.release(); 428 break; 429 } 430 431 default: 432 // We got a token that's not a value. 433 return 0; 434 } 435 *valueTokenEnd = tokenEnd; 436 return result.release(); 437 } 438 38 439 inline bool escapeChar(UChar c, Vector<UChar>* dst) 39 440 { … … 72 473 } 73 474 475 } // anonymous namespace 476 477 bool InspectorValue::asBool(bool*) const 478 { 479 return false; 480 } 481 482 bool InspectorValue::asNumber(double*) const 483 { 484 return false; 485 } 486 487 bool InspectorValue::asString(String*) const 488 { 489 return false; 490 } 491 492 PassRefPtr<InspectorObject> InspectorValue::asObject() 493 { 494 return 0; 495 } 496 497 PassRefPtr<InspectorArray> InspectorValue::asArray() 498 { 499 return 0; 500 } 501 502 PassRefPtr<InspectorValue> InspectorValue::readJSON(const String& json) 503 { 504 const UChar* start = json.characters(); 505 const UChar* end = json.characters() + json.length(); 506 const UChar *tokenEnd; 507 RefPtr<InspectorValue> value = buildValue(start, end, &tokenEnd, 0); 508 if (!value || tokenEnd != end) 509 return 0; 510 return value.release(); 511 } 512 74 513 String InspectorValue::toJSONString() const 75 514 { … … 83 522 { 84 523 ASSERT(m_type == TypeNull); 85 output->append("null", 4); 524 output->append(nullString, 4); 525 } 526 527 bool InspectorBasicValue::asBool(bool* output) const 528 { 529 if (type() != TypeBoolean) 530 return false; 531 *output = m_boolValue; 532 return true; 533 } 534 535 bool InspectorBasicValue::asNumber(double* output) const 536 { 537 if (type() != TypeDouble) 538 return false; 539 *output = m_doubleValue; 540 return true; 86 541 } 87 542 … … 91 546 if (type() == TypeBoolean) { 92 547 if (m_boolValue) 93 output->append( "true", 4);548 output->append(trueString, 4); 94 549 else 95 output->append( "false", 5);550 output->append(falseString, 5); 96 551 } else if (type() == TypeDouble) { 97 552 String value = String::format("%f", m_doubleValue); … … 100 555 } 101 556 557 bool InspectorString::asString(String* output) const 558 { 559 *output = m_stringValue; 560 return true; 561 } 562 102 563 void InspectorString::writeJSON(Vector<UChar>* output) const 103 564 { 104 565 ASSERT(type() == TypeString); 105 566 doubleQuoteString(m_stringValue, output); 567 } 568 569 PassRefPtr<InspectorObject> InspectorObject::asObject() 570 { 571 return this; 572 } 573 574 bool InspectorObject::getBool(const String& name, bool* output) const 575 { 576 RefPtr<InspectorValue> value = get(name); 577 if (!value) 578 return false; 579 return value->asBool(output); 580 } 581 582 bool InspectorObject::getNumber(const String& name, double* output) const 583 { 584 RefPtr<InspectorValue> value = get(name); 585 if (!value) 586 return false; 587 return value->asNumber(output); 588 } 589 590 bool InspectorObject::getString(const String& name, String* output) const 591 { 592 RefPtr<InspectorValue> value = get(name); 593 if (!value) 594 return false; 595 return value->asString(output); 596 } 597 598 PassRefPtr<InspectorObject> InspectorObject::getObject(const String& name) const 599 { 600 PassRefPtr<InspectorValue> value = get(name); 601 if (!value) 602 return false; 603 return value->asObject(); 604 } 605 606 PassRefPtr<InspectorArray> InspectorObject::getArray(const String& name) const 607 { 608 PassRefPtr<InspectorValue> value = get(name); 609 if (!value) 610 return false; 611 return value->asArray(); 612 } 613 614 PassRefPtr<InspectorValue> InspectorObject::get(const String& name) const 615 { 616 Dictionary::const_iterator it = m_data.find(name); 617 if (it == m_data.end()) 618 return 0; 619 return it->second; 106 620 } 107 621 … … 121 635 } 122 636 637 PassRefPtr<InspectorArray> InspectorArray::asArray() 638 { 639 return this; 640 } 641 123 642 void InspectorArray::writeJSON(Vector<UChar>* output) const 124 643 { -
trunk/WebCore/inspector/InspectorValues.h
r60687 r60774 43 43 namespace WebCore { 44 44 45 class InspectorArray; 46 class InspectorObject; 45 47 class String; 46 48 … … 66 68 Type type() const { return m_type; } 67 69 70 virtual bool asBool(bool* output) const; 71 virtual bool asNumber(double* output) const; 72 virtual bool asString(String* output) const; 73 virtual PassRefPtr<InspectorObject> asObject(); 74 virtual PassRefPtr<InspectorArray> asArray(); 75 76 static PassRefPtr<InspectorValue> readJSON(const String& json); 77 68 78 String toJSONString() const; 69 79 virtual void writeJSON(Vector<UChar>* output) const; … … 93 103 return adoptRef(new InspectorBasicValue(value)); 94 104 } 105 106 virtual bool asBool(bool* output) const; 107 virtual bool asNumber(double* output) const; 95 108 96 109 virtual void writeJSON(Vector<UChar>* output) const; … … 118 131 return adoptRef(new InspectorString(value)); 119 132 } 133 134 virtual bool asString(String* output) const; 135 120 136 virtual void writeJSON(Vector<UChar>* output) const; 121 137 … … 128 144 129 145 class InspectorObject : public InspectorValue { 146 private: 147 typedef HashMap<String, RefPtr<InspectorValue> > Dictionary; 148 149 public: 150 typedef Dictionary::iterator iterator; 151 typedef Dictionary::const_iterator const_iterator; 152 130 153 public: 131 154 static PassRefPtr<InspectorObject> create() … … 134 157 } 135 158 ~InspectorObject() { } 159 160 virtual PassRefPtr<InspectorObject> asObject(); 136 161 137 162 void setBool(const String& name, bool); … … 140 165 void set(const String& name, PassRefPtr<InspectorValue>); 141 166 142 virtual void writeJSON(Vector<UChar>* output) const; 167 bool getBool(const String& name, bool* output) const; 168 bool getNumber(const String& name, double* output) const; 169 bool getString(const String& name, String* output) const; 170 PassRefPtr<InspectorObject> getObject(const String& name) const; 171 PassRefPtr<InspectorArray> getArray(const String& name) const; 172 PassRefPtr<InspectorValue> get(const String& name) const; 173 174 virtual void writeJSON(Vector<UChar>* output) const; 175 176 iterator begin() { return m_data.begin(); } 177 iterator end() { return m_data.end(); } 178 const_iterator begin() const { return m_data.begin(); } 179 const_iterator end() const { return m_data.end(); } 143 180 144 181 private: 145 182 InspectorObject() : InspectorValue(TypeObject) { } 146 typedef HashMap<String, RefPtr<InspectorValue> > Dictionary;147 183 Dictionary m_data; 148 184 Vector<String> m_order; … … 156 192 } 157 193 ~InspectorArray() { } 194 195 virtual PassRefPtr<InspectorArray> asArray(); 158 196 159 197 void pushBool(bool); … … 215 253 #endif // ENABLE(INSPECTOR) 216 254 #endif // !defined(InspectorValues_h) 217
Note: See TracChangeset
for help on using the changeset viewer.