| Index: third_party/WebKit/Source/platform/JSONParser.cpp
|
| diff --git a/third_party/WebKit/Source/platform/inspector_protocol/Parser.cpp b/third_party/WebKit/Source/platform/JSONParser.cpp
|
| similarity index 76%
|
| copy from third_party/WebKit/Source/platform/inspector_protocol/Parser.cpp
|
| copy to third_party/WebKit/Source/platform/JSONParser.cpp
|
| index 4193108b279162d232f681cdd0f74ff250c16fff..a9a35d4daf50f4361ae6d8a381126eea1e62c6d5 100644
|
| --- a/third_party/WebKit/Source/platform/inspector_protocol/Parser.cpp
|
| +++ b/third_party/WebKit/Source/platform/JSONParser.cpp
|
| @@ -2,13 +2,14 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "platform/inspector_protocol/Parser.h"
|
| +#include "platform/JSONParser.h"
|
|
|
| -#include "platform/inspector_protocol/String16.h"
|
| -#include "platform/inspector_protocol/Values.h"
|
| +#include "platform/Decimal.h"
|
| +#include "platform/JSONValues.h"
|
| +#include "wtf/text/StringBuilder.h"
|
| +#include "wtf/text/StringToNumber.h"
|
|
|
| namespace blink {
|
| -namespace protocol {
|
|
|
| namespace {
|
|
|
| @@ -33,7 +34,8 @@ const char* const nullString = "null";
|
| const char* const trueString = "true";
|
| const char* const falseString = "false";
|
|
|
| -bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token)
|
| +template<typename CharType>
|
| +bool parseConstToken(const CharType* start, const CharType* end, const CharType** tokenEnd, const char* token)
|
| {
|
| while (start < end && *token != '\0' && *start++ == *token++) { }
|
| if (*token != '\0')
|
| @@ -42,7 +44,8 @@ bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEn
|
| return true;
|
| }
|
|
|
| -bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
|
| +template<typename CharType>
|
| +bool readInt(const CharType* start, const CharType* end, const CharType** tokenEnd, bool canHaveLeadingZeros)
|
| {
|
| if (start == end)
|
| return false;
|
| @@ -60,13 +63,14 @@ bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool
|
| return true;
|
| }
|
|
|
| -bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
|
| +template<typename CharType>
|
| +bool parseNumberToken(const CharType* start, const CharType* end, const CharType** tokenEnd)
|
| {
|
| // We just grab the number here. We validate the size in DecodeNumber.
|
| // According to RFC4627, a valid number is: [minus] int [frac] [exp]
|
| if (start == end)
|
| return false;
|
| - UChar c = *start;
|
| + CharType c = *start;
|
| if ('-' == c)
|
| ++start;
|
|
|
| @@ -109,12 +113,13 @@ bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenE
|
| return true;
|
| }
|
|
|
| -bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
|
| +template<typename CharType>
|
| +bool readHexDigits(const CharType* start, const CharType* end, const CharType** tokenEnd, int digits)
|
| {
|
| if (end - start < digits)
|
| return false;
|
| for (int i = 0; i < digits; ++i) {
|
| - UChar c = *start++;
|
| + CharType c = *start++;
|
| if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')))
|
| return false;
|
| }
|
| @@ -122,10 +127,11 @@ bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd,
|
| return true;
|
| }
|
|
|
| -bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
|
| +template<typename CharType>
|
| +bool parseStringToken(const CharType* start, const CharType* end, const CharType** tokenEnd)
|
| {
|
| while (start < end) {
|
| - UChar c = *start++;
|
| + CharType c = *start++;
|
| if ('\\' == c) {
|
| c = *start++;
|
| // Make sure the escaped char is valid.
|
| @@ -159,7 +165,8 @@ bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenE
|
| return false;
|
| }
|
|
|
| -bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd)
|
| +template<typename CharType>
|
| +bool skipComment(const CharType* start, const CharType* end, const CharType** commentEnd)
|
| {
|
| if (start == end)
|
| return false;
|
| @@ -182,7 +189,7 @@ bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd)
|
| }
|
|
|
| if (*start == '*') {
|
| - UChar previous = '\0';
|
| + CharType previous = '\0';
|
| // Block comment, read until end marker.
|
| for (++start; start < end; previous = *start++) {
|
| if (previous == '*' && *start == '/') {
|
| @@ -197,13 +204,14 @@ bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd)
|
| return false;
|
| }
|
|
|
| -void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar** whitespaceEnd)
|
| +template<typename CharType>
|
| +void skipWhitespaceAndComments(const CharType* start, const CharType* end, const CharType** whitespaceEnd)
|
| {
|
| while (start < end) {
|
| if (isSpaceOrNewline(*start)) {
|
| ++start;
|
| } else if (*start == '/') {
|
| - const UChar* commentEnd;
|
| + const CharType* commentEnd;
|
| if (!skipComment(start, end, &commentEnd))
|
| break;
|
| start = commentEnd;
|
| @@ -214,7 +222,8 @@ void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar
|
| *whitespaceEnd = start;
|
| }
|
|
|
| -Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
|
| +template<typename CharType>
|
| +Token parseToken(const CharType* start, const CharType* end, const CharType** tokenStart, const CharType** tokenEnd)
|
| {
|
| skipWhitespaceAndComments(start, end, tokenStart);
|
| start = *tokenStart;
|
| @@ -275,7 +284,8 @@ Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart,
|
| return InvalidToken;
|
| }
|
|
|
| -inline int hexToInt(UChar c)
|
| +template<typename CharType>
|
| +inline int hexToInt(CharType c)
|
| {
|
| if ('0' <= c && c <= '9')
|
| return c - '0';
|
| @@ -287,7 +297,8 @@ inline int hexToInt(UChar c)
|
| return 0;
|
| }
|
|
|
| -bool decodeString(const UChar* start, const UChar* end, String16Builder* output)
|
| +template<typename CharType>
|
| +bool decodeString(const CharType* start, const CharType* end, StringBuilder* output)
|
| {
|
| while (start < end) {
|
| UChar c = *start++;
|
| @@ -340,7 +351,8 @@ bool decodeString(const UChar* start, const UChar* end, String16Builder* output)
|
| return true;
|
| }
|
|
|
| -bool decodeString(const UChar* start, const UChar* end, String16* output)
|
| +template<typename CharType>
|
| +bool decodeString(const CharType* start, const CharType* end, String* output)
|
| {
|
| if (start == end) {
|
| *output = "";
|
| @@ -348,61 +360,67 @@ bool decodeString(const UChar* start, const UChar* end, String16* output)
|
| }
|
| if (start > end)
|
| return false;
|
| - String16Builder buffer;
|
| + StringBuilder buffer;
|
| buffer.reserveCapacity(end - start);
|
| if (!decodeString(start, end, &buffer))
|
| return false;
|
| *output = buffer.toString();
|
| + // Validate constructed utf16 string.
|
| + if (output->utf8(StrictUTF8Conversion).isNull())
|
| + return false;
|
| return true;
|
| }
|
|
|
| -std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
|
| +template<typename CharType>
|
| +std::unique_ptr<JSONValue> buildValue(const CharType* start, const CharType* end, const CharType** valueTokenEnd, int depth)
|
| {
|
| if (depth > stackLimit)
|
| return nullptr;
|
|
|
| - std::unique_ptr<Value> result;
|
| - const UChar* tokenStart;
|
| - const UChar* tokenEnd;
|
| + std::unique_ptr<JSONValue> result;
|
| + const CharType* tokenStart;
|
| + const CharType* tokenEnd;
|
| Token token = parseToken(start, end, &tokenStart, &tokenEnd);
|
| switch (token) {
|
| case InvalidToken:
|
| return nullptr;
|
| case NullToken:
|
| - result = Value::null();
|
| + result = JSONValue::null();
|
| break;
|
| case BoolTrue:
|
| - result = FundamentalValue::create(true);
|
| + result = JSONBasicValue::create(true);
|
| break;
|
| case BoolFalse:
|
| - result = FundamentalValue::create(false);
|
| + result = JSONBasicValue::create(false);
|
| break;
|
| case Number: {
|
| bool ok;
|
| - double value = String16::charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
|
| + double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
|
| + if (Decimal::fromDouble(value).isInfinity())
|
| + ok = false;
|
| if (!ok)
|
| return nullptr;
|
| int number = static_cast<int>(value);
|
| if (number == value)
|
| - result = FundamentalValue::create(number);
|
| + result = JSONBasicValue::create(number);
|
| else
|
| - result = FundamentalValue::create(value);
|
| + result = JSONBasicValue::create(value);
|
| break;
|
| }
|
| case StringLiteral: {
|
| - String16 value;
|
| + String value;
|
| bool ok = decodeString(tokenStart + 1, tokenEnd - 1, &value);
|
| if (!ok)
|
| return nullptr;
|
| - result = StringValue::create(value);
|
| + result = JSONString::create(value);
|
| break;
|
| }
|
| case ArrayBegin: {
|
| - std::unique_ptr<ListValue> array = ListValue::create();
|
| + std::unique_ptr<JSONArray> array = JSONArray::create();
|
| start = tokenEnd;
|
| token = parseToken(start, end, &tokenStart, &tokenEnd);
|
| while (token != ArrayEnd) {
|
| - std::unique_ptr<Value> arrayNode = buildValue(start, end, &tokenEnd, depth + 1);
|
| + std::unique_ptr<JSONValue> arrayNode = buildValue(start, end, &tokenEnd, depth + 1);
|
| if (!arrayNode)
|
| return nullptr;
|
| array->pushValue(std::move(arrayNode));
|
| @@ -426,13 +444,13 @@ std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UC
|
| break;
|
| }
|
| case ObjectBegin: {
|
| - std::unique_ptr<DictionaryValue> object = DictionaryValue::create();
|
| + std::unique_ptr<JSONObject> object = JSONObject::create();
|
| start = tokenEnd;
|
| token = parseToken(start, end, &tokenStart, &tokenEnd);
|
| while (token != ObjectEnd) {
|
| if (token != StringLiteral)
|
| return nullptr;
|
| - String16 key;
|
| + String key;
|
| if (!decodeString(tokenStart + 1, tokenEnd - 1, &key))
|
| return nullptr;
|
| start = tokenEnd;
|
| @@ -442,7 +460,7 @@ std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UC
|
| return nullptr;
|
| start = tokenEnd;
|
|
|
| - std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, depth + 1);
|
| + std::unique_ptr<JSONValue> value = buildValue(start, end, &tokenEnd, depth + 1);
|
| if (!value)
|
| return nullptr;
|
| object->setValue(key, std::move(value));
|
| @@ -476,11 +494,12 @@ std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UC
|
| return result;
|
| }
|
|
|
| -std::unique_ptr<Value> parseJSONInternal(const UChar* start, unsigned length)
|
| +template<typename CharType>
|
| +std::unique_ptr<JSONValue> parseJSONInternal(const CharType* start, unsigned length)
|
| {
|
| - const UChar* end = start + length;
|
| - const UChar *tokenEnd;
|
| - std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, 0);
|
| + const CharType* end = start + length;
|
| + const CharType *tokenEnd;
|
| + std::unique_ptr<JSONValue> value = buildValue(start, end, &tokenEnd, 0);
|
| if (!value || tokenEnd != end)
|
| return nullptr;
|
| return value;
|
| @@ -488,12 +507,13 @@ std::unique_ptr<Value> parseJSONInternal(const UChar* start, unsigned length)
|
|
|
| } // anonymous namespace
|
|
|
| -std::unique_ptr<Value> parseJSON(const String16& json)
|
| +std::unique_ptr<JSONValue> parseJSON(const String& json)
|
| {
|
| if (json.isEmpty())
|
| return nullptr;
|
| + if (json.is8Bit())
|
| + return parseJSONInternal(json.characters8(), json.length());
|
| return parseJSONInternal(json.characters16(), json.length());
|
| }
|
|
|
| -} // namespace protocol
|
| } // namespace blink
|
|
|