| OLD | NEW |
| 1 /* | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 * | 3 // found in the LICENSE file. |
| 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 | 4 |
| 31 #include "platform/JSONParser.h" | 5 #include "platform/inspector_protocol/Parser.h" |
| 32 | 6 |
| 33 #include "platform/Decimal.h" | 7 #include "platform/Decimal.h" |
| 34 #include "platform/JSONValues.h" | 8 #include "platform/inspector_protocol/Values.h" |
| 35 #include "wtf/text/StringBuilder.h" | 9 #include "wtf/text/StringBuilder.h" |
| 36 #include "wtf/text/UTF8.h" | 10 #include "wtf/text/UTF8.h" |
| 37 | 11 |
| 38 namespace blink { | 12 namespace blink { |
| 13 namespace protocol { |
| 39 | 14 |
| 40 namespace { | 15 namespace { |
| 41 | 16 |
| 42 const int stackLimit = 1000; | 17 const int stackLimit = 1000; |
| 43 | 18 |
| 44 enum Token { | 19 enum Token { |
| 45 ObjectBegin, | 20 ObjectBegin, |
| 46 ObjectEnd, | 21 ObjectEnd, |
| 47 ArrayBegin, | 22 ArrayBegin, |
| 48 ArrayEnd, | 23 ArrayEnd, |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 if (!decodeString(start, end, &buffer)) | 412 if (!decodeString(start, end, &buffer)) |
| 438 return false; | 413 return false; |
| 439 *output = buffer.toString(); | 414 *output = buffer.toString(); |
| 440 // Validate constructed utf16 string. | 415 // Validate constructed utf16 string. |
| 441 if (output->utf8(StrictUTF8Conversion).isNull()) | 416 if (output->utf8(StrictUTF8Conversion).isNull()) |
| 442 return false; | 417 return false; |
| 443 return true; | 418 return true; |
| 444 } | 419 } |
| 445 | 420 |
| 446 template<typename CharType> | 421 template<typename CharType> |
| 447 PassRefPtr<JSONValue> buildValue(const CharType* start, const CharType* end, con
st CharType** valueTokenEnd, int depth) | 422 PassRefPtr<Value> buildValue(const CharType* start, const CharType* end, const C
harType** valueTokenEnd, int depth) |
| 448 { | 423 { |
| 449 if (depth > stackLimit) | 424 if (depth > stackLimit) |
| 450 return nullptr; | 425 return nullptr; |
| 451 | 426 |
| 452 RefPtr<JSONValue> result; | 427 RefPtr<Value> result; |
| 453 const CharType* tokenStart; | 428 const CharType* tokenStart; |
| 454 const CharType* tokenEnd; | 429 const CharType* tokenEnd; |
| 455 Token token = parseToken(start, end, &tokenStart, &tokenEnd); | 430 Token token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 456 switch (token) { | 431 switch (token) { |
| 457 case InvalidToken: | 432 case InvalidToken: |
| 458 return nullptr; | 433 return nullptr; |
| 459 case NullToken: | 434 case NullToken: |
| 460 result = JSONValue::null(); | 435 result = Value::null(); |
| 461 break; | 436 break; |
| 462 case BoolTrue: | 437 case BoolTrue: |
| 463 result = JSONBasicValue::create(true); | 438 result = FundamentalValue::create(true); |
| 464 break; | 439 break; |
| 465 case BoolFalse: | 440 case BoolFalse: |
| 466 result = JSONBasicValue::create(false); | 441 result = FundamentalValue::create(false); |
| 467 break; | 442 break; |
| 468 case Number: { | 443 case Number: { |
| 469 bool ok; | 444 bool ok; |
| 470 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok
); | 445 double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok
); |
| 471 if (Decimal::fromDouble(value).isInfinity()) | 446 if (Decimal::fromDouble(value).isInfinity()) |
| 472 ok = false; | 447 ok = false; |
| 473 if (!ok) | 448 if (!ok) |
| 474 return nullptr; | 449 return nullptr; |
| 475 result = JSONBasicValue::create(value); | 450 result = FundamentalValue::create(value); |
| 476 break; | 451 break; |
| 477 } | 452 } |
| 478 case StringLiteral: { | 453 case StringLiteral: { |
| 479 String value; | 454 String value; |
| 480 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); | 455 bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value); |
| 481 if (!ok) | 456 if (!ok) |
| 482 return nullptr; | 457 return nullptr; |
| 483 result = JSONString::create(value); | 458 result = StringValue::create(value); |
| 484 break; | 459 break; |
| 485 } | 460 } |
| 486 case ArrayBegin: { | 461 case ArrayBegin: { |
| 487 RefPtr<JSONArray> array = JSONArray::create(); | 462 RefPtr<ListValue> array = ListValue::create(); |
| 488 start = tokenEnd; | 463 start = tokenEnd; |
| 489 token = parseToken(start, end, &tokenStart, &tokenEnd); | 464 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 490 while (token != ArrayEnd) { | 465 while (token != ArrayEnd) { |
| 491 RefPtr<JSONValue> arrayNode = buildValue(start, end, &tokenEnd, dept
h + 1); | 466 RefPtr<Value> arrayNode = buildValue(start, end, &tokenEnd, depth +
1); |
| 492 if (!arrayNode) | 467 if (!arrayNode) |
| 493 return nullptr; | 468 return nullptr; |
| 494 array->pushValue(arrayNode); | 469 array->pushValue(arrayNode); |
| 495 | 470 |
| 496 // After a list value, we expect a comma or the end of the list. | 471 // After a list value, we expect a comma or the end of the list. |
| 497 start = tokenEnd; | 472 start = tokenEnd; |
| 498 token = parseToken(start, end, &tokenStart, &tokenEnd); | 473 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 499 if (token == ListSeparator) { | 474 if (token == ListSeparator) { |
| 500 start = tokenEnd; | 475 start = tokenEnd; |
| 501 token = parseToken(start, end, &tokenStart, &tokenEnd); | 476 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 502 if (token == ArrayEnd) | 477 if (token == ArrayEnd) |
| 503 return nullptr; | 478 return nullptr; |
| 504 } else if (token != ArrayEnd) { | 479 } else if (token != ArrayEnd) { |
| 505 // Unexpected value after list value. Bail out. | 480 // Unexpected value after list value. Bail out. |
| 506 return nullptr; | 481 return nullptr; |
| 507 } | 482 } |
| 508 } | 483 } |
| 509 if (token != ArrayEnd) | 484 if (token != ArrayEnd) |
| 510 return nullptr; | 485 return nullptr; |
| 511 result = array.release(); | 486 result = array.release(); |
| 512 break; | 487 break; |
| 513 } | 488 } |
| 514 case ObjectBegin: { | 489 case ObjectBegin: { |
| 515 RefPtr<JSONObject> object = JSONObject::create(); | 490 RefPtr<DictionaryValue> object = DictionaryValue::create(); |
| 516 start = tokenEnd; | 491 start = tokenEnd; |
| 517 token = parseToken(start, end, &tokenStart, &tokenEnd); | 492 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 518 while (token != ObjectEnd) { | 493 while (token != ObjectEnd) { |
| 519 if (token != StringLiteral) | 494 if (token != StringLiteral) |
| 520 return nullptr; | 495 return nullptr; |
| 521 String key; | 496 String key; |
| 522 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) | 497 if (!decodeString(tokenStart + 1, tokenEnd - 1, &key)) |
| 523 return nullptr; | 498 return nullptr; |
| 524 start = tokenEnd; | 499 start = tokenEnd; |
| 525 | 500 |
| 526 token = parseToken(start, end, &tokenStart, &tokenEnd); | 501 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 527 if (token != ObjectPairSeparator) | 502 if (token != ObjectPairSeparator) |
| 528 return nullptr; | 503 return nullptr; |
| 529 start = tokenEnd; | 504 start = tokenEnd; |
| 530 | 505 |
| 531 RefPtr<JSONValue> value = buildValue(start, end, &tokenEnd, depth +
1); | 506 RefPtr<Value> value = buildValue(start, end, &tokenEnd, depth + 1); |
| 532 if (!value) | 507 if (!value) |
| 533 return nullptr; | 508 return nullptr; |
| 534 object->setValue(key, value); | 509 object->setValue(key, value); |
| 535 start = tokenEnd; | 510 start = tokenEnd; |
| 536 | 511 |
| 537 // After a key/value pair, we expect a comma or the end of the | 512 // After a key/value pair, we expect a comma or the end of the |
| 538 // object. | 513 // object. |
| 539 token = parseToken(start, end, &tokenStart, &tokenEnd); | 514 token = parseToken(start, end, &tokenStart, &tokenEnd); |
| 540 if (token == ListSeparator) { | 515 if (token == ListSeparator) { |
| 541 start = tokenEnd; | 516 start = tokenEnd; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 556 default: | 531 default: |
| 557 // We got a token that's not a value. | 532 // We got a token that's not a value. |
| 558 return nullptr; | 533 return nullptr; |
| 559 } | 534 } |
| 560 | 535 |
| 561 skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd); | 536 skipWhitespaceAndComments(tokenEnd, end, valueTokenEnd); |
| 562 return result.release(); | 537 return result.release(); |
| 563 } | 538 } |
| 564 | 539 |
| 565 template<typename CharType> | 540 template<typename CharType> |
| 566 PassRefPtr<JSONValue> parseJSONInternal(const CharType* start, unsigned length) | 541 PassRefPtr<Value> parseJSONInternal(const CharType* start, unsigned length) |
| 567 { | 542 { |
| 568 const CharType* end = start + length; | 543 const CharType* end = start + length; |
| 569 const CharType *tokenEnd; | 544 const CharType *tokenEnd; |
| 570 RefPtr<JSONValue> value = buildValue(start, end, &tokenEnd, 0); | 545 RefPtr<Value> value = buildValue(start, end, &tokenEnd, 0); |
| 571 if (!value || tokenEnd != end) | 546 if (!value || tokenEnd != end) |
| 572 return nullptr; | 547 return nullptr; |
| 573 return value.release(); | 548 return value.release(); |
| 574 } | 549 } |
| 575 | 550 |
| 576 } // anonymous namespace | 551 } // anonymous namespace |
| 577 | 552 |
| 578 PassRefPtr<JSONValue> parseJSON(const String& json) | 553 PassRefPtr<Value> parseJSON(const String& json) |
| 579 { | 554 { |
| 580 if (json.isEmpty()) | 555 if (json.isEmpty()) |
| 581 return nullptr; | 556 return nullptr; |
| 582 if (json.is8Bit()) | 557 if (json.is8Bit()) |
| 583 return parseJSONInternal(json.characters8(), json.length()); | 558 return parseJSONInternal(json.characters8(), json.length()); |
| 584 return parseJSONInternal(json.characters16(), json.length()); | 559 return parseJSONInternal(json.characters16(), json.length()); |
| 585 } | 560 } |
| 586 | 561 |
| 562 } // namespace protocol |
| 587 } // namespace blink | 563 } // namespace blink |
| OLD | NEW |