[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