[DevTools] Migrate v8_inspector/public from String16 to String{View,Buffer}.
Using StringView for inbound parameters and StringBuffer for outbound helps to avoid copies in important places (mostly when passing large protocol messages around).
This opens possibility to:
- use WTF::String in core/inspector instead of String16;
- make String16 an alias to std::basic_string<uint16_t> to leverage all existing
optimizations.
One possible optimization is to migrate search utility (in V8StringUtil) to
StringView and avoid any copies of content there.
BUG=637032
Review-Url: https://codereview.chromium.org/2260233002
Cr-Original-Commit-Position: refs/heads/master@{#414846}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 101f402f95f5a67df948347edc4dce050ce482c7
diff --git a/DispatcherBase_cpp.template b/DispatcherBase_cpp.template
index 2f842e7..c9b70e7 100644
--- a/DispatcherBase_cpp.template
+++ b/DispatcherBase_cpp.template
@@ -127,9 +127,8 @@
m_dispatchers[name] = std::move(dispatcher);
}
-void UberDispatcher::dispatch(const String16& message)
+void UberDispatcher::dispatch(std::unique_ptr<Value> parsedMessage)
{
- std::unique_ptr<protocol::Value> parsedMessage = parseJSON(message);
if (!parsedMessage)
return;
std::unique_ptr<protocol::DictionaryValue> messageObject = DictionaryValue::cast(std::move(parsedMessage));
diff --git a/DispatcherBase_h.template b/DispatcherBase_h.template
index 4402d96..6ba27f6 100644
--- a/DispatcherBase_h.template
+++ b/DispatcherBase_h.template
@@ -83,7 +83,7 @@
public:
explicit UberDispatcher(FrontendChannel*);
void registerBackend(const String16& name, std::unique_ptr<protocol::DispatcherBase>);
- void dispatch(const String16& message);
+ void dispatch(std::unique_ptr<Value> message);
FrontendChannel* channel() { return m_frontendChannel; }
virtual ~UberDispatcher();
diff --git a/InspectorProtocol_cpp.template b/InspectorProtocol_cpp.template
index e7c49fd..b181f0d 100644
--- a/InspectorProtocol_cpp.template
+++ b/InspectorProtocol_cpp.template
@@ -3,3 +3,5 @@
// found in the LICENSE file.
#include "{{config.lib_package}}/InspectorProtocol.h"
+
+#include <cstring>
diff --git a/Parser_cpp.template b/Parser_cpp.template
index 34d8ff0..c6449c8 100644
--- a/Parser_cpp.template
+++ b/Parser_cpp.template
@@ -28,7 +28,40 @@
const char* const trueString = "true";
const char* const falseString = "false";
-bool parseConstToken(const UChar* start, const UChar* end, const UChar** tokenEnd, const char* token)
+bool isASCII(uint16_t c)
+{
+ return !(c & ~0x7F);
+}
+
+double charactersToDouble(const uint16_t* characters, size_t length, bool* ok)
+{
+ std::vector<char> buffer;
+ buffer.reserve(length + 1);
+ for (size_t i = 0; i < length; ++i) {
+ if (!isASCII(characters[i])) {
+ *ok = false;
+ return 0;
+ }
+ buffer.push_back(static_cast<char>(characters[i]));
+ }
+ buffer.push_back('\0');
+ char* endptr;
+ double result = std::strtod(buffer.data(), &endptr);
+ *ok = !(*endptr);
+ return result;
+}
+
+double charactersToDouble(const uint8_t* characters, size_t length, bool* ok)
+{
+ std::string buffer(reinterpret_cast<const char*>(characters), length);
+ char* endptr;
+ double result = std::strtod(buffer.data(), &endptr);
+ *ok = !(*endptr);
+ return result;
+}
+
+template<typename Char>
+bool parseConstToken(const Char* start, const Char* end, const Char** tokenEnd, const char* token)
{
while (start < end && *token != '\0' && *start++ == *token++) { }
if (*token != '\0')
@@ -37,7 +70,8 @@
return true;
}
-bool readInt(const UChar* start, const UChar* end, const UChar** tokenEnd, bool canHaveLeadingZeros)
+template<typename Char>
+bool readInt(const Char* start, const Char* end, const Char** tokenEnd, bool canHaveLeadingZeros)
{
if (start == end)
return false;
@@ -55,13 +89,14 @@
return true;
}
-bool parseNumberToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
+template<typename Char>
+bool parseNumberToken(const Char* start, const Char* end, const Char** 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;
+ Char c = *start;
if ('-' == c)
++start;
@@ -104,12 +139,13 @@
return true;
}
-bool readHexDigits(const UChar* start, const UChar* end, const UChar** tokenEnd, int digits)
+template<typename Char>
+bool readHexDigits(const Char* start, const Char* end, const Char** tokenEnd, int digits)
{
if (end - start < digits)
return false;
for (int i = 0; i < digits; ++i) {
- UChar c = *start++;
+ Char c = *start++;
if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')))
return false;
}
@@ -117,10 +153,11 @@
return true;
}
-bool parseStringToken(const UChar* start, const UChar* end, const UChar** tokenEnd)
+template<typename Char>
+bool parseStringToken(const Char* start, const Char* end, const Char** tokenEnd)
{
while (start < end) {
- UChar c = *start++;
+ Char c = *start++;
if ('\\' == c) {
c = *start++;
// Make sure the escaped char is valid.
@@ -154,7 +191,8 @@
return false;
}
-bool skipComment(const UChar* start, const UChar* end, const UChar** commentEnd)
+template<typename Char>
+bool skipComment(const Char* start, const Char* end, const Char** commentEnd)
{
if (start == end)
return false;
@@ -177,7 +215,7 @@
}
if (*start == '*') {
- UChar previous = '\0';
+ Char previous = '\0';
// Block comment, read until end marker.
for (++start; start < end; previous = *start++) {
if (previous == '*' && *start == '/') {
@@ -192,13 +230,14 @@
return false;
}
-void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar** whitespaceEnd)
+template<typename Char>
+void skipWhitespaceAndComments(const Char* start, const Char* end, const Char** whitespaceEnd)
{
while (start < end) {
if (String16::isSpaceOrNewLine(*start)) {
++start;
} else if (*start == '/') {
- const UChar* commentEnd;
+ const Char* commentEnd;
if (!skipComment(start, end, &commentEnd))
break;
start = commentEnd;
@@ -209,7 +248,8 @@
*whitespaceEnd = start;
}
-Token parseToken(const UChar* start, const UChar* end, const UChar** tokenStart, const UChar** tokenEnd)
+template<typename Char>
+Token parseToken(const Char* start, const Char* end, const Char** tokenStart, const Char** tokenEnd)
{
skipWhitespaceAndComments(start, end, tokenStart);
start = *tokenStart;
@@ -270,7 +310,8 @@
return InvalidToken;
}
-inline int hexToInt(UChar c)
+template<typename Char>
+int hexToInt(Char c)
{
if ('0' <= c && c <= '9')
return c - '0';
@@ -282,7 +323,8 @@
return 0;
}
-bool decodeString(const UChar* start, const UChar* end, String16Builder* output)
+template<typename Char>
+bool decodeString(const Char* start, const Char* end, String16Builder* output)
{
while (start < end) {
UChar c = *start++;
@@ -335,7 +377,8 @@
return true;
}
-bool decodeString(const UChar* start, const UChar* end, String16* output)
+template<typename Char>
+bool decodeString(const Char* start, const Char* end, String16* output)
{
if (start == end) {
*output = "";
@@ -351,14 +394,15 @@
return true;
}
-std::unique_ptr<Value> buildValue(const UChar* start, const UChar* end, const UChar** valueTokenEnd, int depth)
+template<typename Char>
+std::unique_ptr<Value> buildValue(const Char* start, const Char* end, const Char** valueTokenEnd, int depth)
{
if (depth > stackLimit)
return nullptr;
std::unique_ptr<Value> result;
- const UChar* tokenStart;
- const UChar* tokenEnd;
+ const Char* tokenStart;
+ const Char* tokenEnd;
Token token = parseToken(start, end, &tokenStart, &tokenEnd);
switch (token) {
case InvalidToken:
@@ -374,7 +418,7 @@
break;
case Number: {
bool ok;
- double value = String16::charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
+ double value = charactersToDouble(tokenStart, tokenEnd - tokenStart, &ok);
if (!ok)
return nullptr;
int number = static_cast<int>(value);
@@ -471,10 +515,11 @@
return result;
}
-std::unique_ptr<Value> parseJSONInternal(const UChar* start, unsigned length)
+template<typename Char>
+std::unique_ptr<Value> parseJSONInternal(const Char* start, unsigned length)
{
- const UChar* end = start + length;
- const UChar *tokenEnd;
+ const Char* end = start + length;
+ const Char *tokenEnd;
std::unique_ptr<Value> value = buildValue(start, end, &tokenEnd, 0);
if (!value || tokenEnd != end)
return nullptr;
@@ -483,11 +528,21 @@
} // anonymous namespace
+std::unique_ptr<Value> parseJSON(const uint16_t* characters, unsigned length)
+{
+ return parseJSONInternal<uint16_t>(characters, length);
+}
+
+std::unique_ptr<Value> parseJSON(const uint8_t* characters, unsigned length)
+{
+ return parseJSONInternal<uint8_t>(characters, length);
+}
+
std::unique_ptr<Value> parseJSON(const String16& json)
{
if (json.isEmpty())
return nullptr;
- return parseJSONInternal(json.characters16(), json.length());
+ return parseJSONInternal<uint16_t>(reinterpret_cast<const uint16_t*>(json.characters16()), json.length());
}
} // namespace protocol
diff --git a/Parser_h.template b/Parser_h.template
index 1f3a1b6..98c4f2b 100644
--- a/Parser_h.template
+++ b/Parser_h.template
@@ -14,6 +14,8 @@
class Value;
+{{config.class_export.macro}} std::unique_ptr<Value> parseJSON(const uint8_t*, unsigned);
+{{config.class_export.macro}} std::unique_ptr<Value> parseJSON(const uint16_t*, unsigned);
{{config.class_export.macro}} std::unique_ptr<Value> parseJSON(const String16& json);
} // namespace platform
diff --git a/String16_cpp.template b/String16_cpp.template
index d795aef..dd411f7 100644
--- a/String16_cpp.template
+++ b/String16_cpp.template
@@ -31,15 +31,6 @@
std::snprintf(buffer, length, "%.6g", number);
}
-double strToDouble(const char* buffer, bool* ok)
-{
- char* endptr;
- double result = std::strtod(buffer, &endptr);
- if (ok)
- *ok = !(*endptr);
- return result;
-}
-
int strToInt(const char* buffer, bool* ok)
{
char* endptr;
diff --git a/String16_h.template b/String16_h.template
index e6f8f0c..9bef5d0 100644
--- a/String16_h.template
+++ b/String16_h.template
@@ -19,7 +19,6 @@
{{config.class_export.macro}} void doubleToStr(double, char*, size_t);
{{config.class_export.macro}} void doubleToStr3(double, char*, size_t);
{{config.class_export.macro}} void doubleToStr6(double, char*, size_t);
-{{config.class_export.macro}} double strToDouble(const char*, bool*);
{{config.class_export.macro}} int strToInt(const char*, bool*);
} // namespace internal
@@ -64,22 +63,6 @@
return T(buffer);
}
- static double charactersToDouble(const C* characters, size_t length, bool* ok = nullptr)
- {
- std::vector<char> buffer;
- buffer.reserve(length + 1);
- for (size_t i = 0; i < length; ++i) {
- if (!isASCII(characters[i])) {
- if (ok)
- *ok = false;
- return 0;
- }
- buffer.push_back(static_cast<char>(characters[i]));
- }
- buffer.push_back('\0');
- return internal::strToDouble(buffer.data(), ok);
- }
-
static int charactersToInteger(const C* characters, size_t length, bool* ok = nullptr)
{
std::vector<char> buffer;
@@ -96,13 +79,6 @@
return internal::strToInt(buffer.data(), ok);
}
- double toDouble(bool* ok = nullptr) const
- {
- const C* characters = static_cast<const T&>(*this).characters16();
- size_t length = static_cast<const T&>(*this).length();
- return charactersToDouble(characters, length, ok);
- }
-
int toInteger(bool* ok = nullptr) const
{
const C* characters = static_cast<const T&>(*this).characters16();
@@ -136,17 +112,6 @@
return T(static_cast<const T&>(*this));
return T(characters + start, end + 1 - start);
}
-
- bool startsWith(const char* prefix) const
- {
- const C* characters = static_cast<const T&>(*this).characters16();
- size_t length = static_cast<const T&>(*this).length();
- for (size_t i = 0, j = 0; prefix[j] && i < length; ++i, ++j) {
- if (characters[i] != prefix[j])
- return false;
- }
- return true;
- }
};
} // namespace protocol