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 |