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 |