[DevTools] Reduce API surface of String16.

Also, do not mention WTF::String anywhere except for String16WTF.
Drive-by: improved performance of String16Builder.

BUG=580337

Review-Url: https://codereview.chromium.org/2226863003
Cr-Original-Commit-Position: refs/heads/master@{#411882}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 16523d99c644c8513ad586eaca935fa2bea877b1
diff --git a/Array.h b/Array.h
index 7201822..acdf4d2 100644
--- a/Array.h
+++ b/Array.h
@@ -126,7 +126,7 @@
     std::vector<T> m_vector;
 };
 
-template<> class Array<String> : public ArrayBase<String> {};
+template<> class Array<InspectorProtocolConvenienceStringType> : public ArrayBase<InspectorProtocolConvenienceStringType> {};
 template<> class Array<String16> : public ArrayBase<String16> {};
 template<> class Array<int> : public ArrayBase<int> {};
 template<> class Array<double> : public ArrayBase<double> {};
diff --git a/DispatcherBase.cpp b/DispatcherBase.cpp
index 8f154f4..86ac058 100644
--- a/DispatcherBase.cpp
+++ b/DispatcherBase.cpp
@@ -154,7 +154,7 @@
         return;
 
     size_t dotIndex = method.find(".");
-    if (dotIndex == kNotFound) {
+    if (dotIndex == String16::kNotFound) {
         reportProtocolError(m_frontendChannel, callId, DispatcherBase::MethodNotFound, "'" + method + "' wasn't found", nullptr);
         return;
     }
diff --git a/Maybe.h b/Maybe.h
index cf372e0..560e7da 100644
--- a/Maybe.h
+++ b/Maybe.h
@@ -13,8 +13,6 @@
 namespace blink {
 namespace protocol {
 
-class String16;
-
 template<typename T>
 class Maybe {
 public:
@@ -70,10 +68,10 @@
 };
 
 template<>
-class Maybe<String> : public MaybeBase<String> {
+class Maybe<InspectorProtocolConvenienceStringType> : public MaybeBase<InspectorProtocolConvenienceStringType> {
 public:
     Maybe() { }
-    Maybe(const String& value) : MaybeBase(value) { }
+    Maybe(const InspectorProtocolConvenienceStringType& value) : MaybeBase(value) { }
     using MaybeBase::operator=;
 };
 
diff --git a/Parser.cpp b/Parser.cpp
index 4193108..1a8a10e 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -200,7 +200,7 @@
 void skipWhitespaceAndComments(const UChar* start, const UChar* end, const UChar** whitespaceEnd)
 {
     while (start < end) {
-        if (isSpaceOrNewline(*start)) {
+        if (String16::isSpaceOrNewLine(*start)) {
             ++start;
         } else if (*start == '/') {
             const UChar* commentEnd;
diff --git a/String16.cpp b/String16.cpp
new file mode 100644
index 0000000..d9443fc
--- /dev/null
+++ b/String16.cpp
@@ -0,0 +1,101 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/inspector_protocol/String16.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+namespace blink {
+namespace protocol {
+
+namespace internal {
+
+void intToStr(int number, char* buffer, size_t length)
+{
+    std::snprintf(buffer, length, "%d", number);
+}
+
+void doubleToStr(double number, char* buffer, size_t length)
+{
+    std::snprintf(buffer, length, "%f", number);
+}
+
+void doubleToStr3(double number, char* buffer, size_t length)
+{
+    std::snprintf(buffer, length, "%.3g", number);
+}
+
+void doubleToStr6(double number, char* buffer, size_t length)
+{
+    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;
+    int result = std::strtol(buffer, &endptr, 10);
+    if (ok)
+        *ok = !(*endptr);
+    return result;
+}
+
+} // namespace internal
+
+String16Builder::String16Builder()
+{
+}
+
+void String16Builder::append(const String16& s)
+{
+    m_buffer.insert(m_buffer.end(), s.characters16(), s.characters16() + s.length());
+}
+
+void String16Builder::append(UChar c)
+{
+    m_buffer.push_back(c);
+}
+
+void String16Builder::append(char c)
+{
+    UChar u = c;
+    m_buffer.push_back(u);
+}
+
+void String16Builder::append(const UChar* characters, size_t length)
+{
+    m_buffer.insert(m_buffer.end(), characters, characters + length);
+}
+
+void String16Builder::append(const char* characters, size_t length)
+{
+    m_buffer.reserve(m_buffer.size() + length);
+    for (size_t i = 0; i < length; ++i, ++characters) {
+        UChar u = *characters;
+        m_buffer.push_back(u);
+    }
+}
+
+String16 String16Builder::toString()
+{
+    return String16(m_buffer.data(), m_buffer.size());
+}
+
+void String16Builder::reserveCapacity(size_t capacity)
+{
+    m_buffer.reserve(capacity);
+}
+
+} // namespace protocol
+} // namespace blink
diff --git a/String16.h b/String16.h
index 6a1b4a0..6713f69 100644
--- a/String16.h
+++ b/String16.h
@@ -5,10 +5,180 @@
 #ifndef String16_h
 #define String16_h
 
+#include "platform/inspector_protocol/Collections.h"
+#include "platform/inspector_protocol/Platform.h"
+
+#include <vector>
+
+namespace blink {
+namespace protocol {
+
+namespace internal {
+PLATFORM_EXPORT void intToStr(int, char*, size_t);
+PLATFORM_EXPORT void doubleToStr(double, char*, size_t);
+PLATFORM_EXPORT void doubleToStr3(double, char*, size_t);
+PLATFORM_EXPORT void doubleToStr6(double, char*, size_t);
+PLATFORM_EXPORT double strToDouble(const char*, bool*);
+PLATFORM_EXPORT int strToInt(const char*, bool*);
+} // namespace internal
+
+template <typename T, typename C>
+class PLATFORM_EXPORT String16Base {
+public:
+    static bool isASCII(C c)
+    {
+        return !(c & ~0x7F);
+    }
+
+    static bool isSpaceOrNewLine(C c)
+    {
+        return isASCII(c) && c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
+    }
+
+    static T fromInteger(int number)
+    {
+        char buffer[50];
+        internal::intToStr(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer));
+        return T(buffer);
+    }
+
+    static T fromDouble(double number)
+    {
+        char buffer[100];
+        internal::doubleToStr(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer));
+        return T(buffer);
+    }
+
+    static T fromDoublePrecision3(double number)
+    {
+        char buffer[100];
+        internal::doubleToStr3(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer));
+        return T(buffer);
+    }
+
+    static T fromDoublePrecision6(double number)
+    {
+        char buffer[100];
+        internal::doubleToStr6(number, buffer, PROTOCOL_ARRAY_LENGTH(buffer));
+        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;
+        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::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();
+        size_t length = static_cast<const T&>(*this).length();
+        return charactersToInteger(characters, length, ok);
+    }
+
+    T stripWhiteSpace() const
+    {
+        size_t length = static_cast<const T&>(*this).length();
+        if (!length)
+            return T();
+
+        unsigned start = 0;
+        unsigned end = length - 1;
+        const C* characters = static_cast<const T&>(*this).characters16();
+
+        // skip white space from start
+        while (start <= end && isSpaceOrNewLine(characters[start]))
+            ++start;
+
+        // only white space
+        if (start > end)
+            return T();
+
+        // skip white space from end
+        while (end && isSpaceOrNewLine(characters[end]))
+            --end;
+
+        if (!start && end == length - 1)
+            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
+} // namespace blink
+
 #if V8_INSPECTOR_USE_STL
 #include "platform/inspector_protocol/String16STL.h"
 #else
 #include "platform/inspector_protocol/String16WTF.h"
 #endif // V8_INSPECTOR_USE_STL
 
+namespace blink {
+namespace protocol {
+
+class PLATFORM_EXPORT String16Builder {
+public:
+    String16Builder();
+    void append(const String16&);
+    void append(UChar);
+    void append(char);
+    void append(const UChar*, size_t);
+    void append(const char*, size_t);
+    String16 toString();
+    void reserveCapacity(size_t);
+
+private:
+    std::vector<UChar> m_buffer;
+};
+
+} // namespace protocol
+} // namespace blink
+
+using String16 = blink::protocol::String16;
+using String16Builder = blink::protocol::String16Builder;
+
 #endif // !defined(String16_h)
diff --git a/String16STL.cpp b/String16STL.cpp
index 10c7fa6..87d6b1c 100644
--- a/String16STL.cpp
+++ b/String16STL.cpp
@@ -2,116 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "platform/inspector_protocol/String16STL.h"
-
-#include "platform/inspector_protocol/Platform.h"
+#include "platform/inspector_protocol/String16.h"
 
 #include <algorithm>
 #include <cctype>
 #include <cstdio>
-#include <functional>
 #include <locale>
 
 namespace blink {
 namespace protocol {
 
 const UChar replacementCharacter = 0xFFFD;
-
-template<typename CharType> inline bool isASCII(CharType c)
-{
-    return !(c & ~0x7F);
-}
-
-template<typename CharType> inline bool isASCIIAlpha(CharType c)
-{
-    return (c | 0x20) >= 'a' && (c | 0x20) <= 'z';
-}
-
-template<typename CharType> inline bool isASCIIDigit(CharType c)
-{
-    return c >= '0' && c <= '9';
-}
-
-template<typename CharType> inline bool isASCIIAlphanumeric(CharType c)
-{
-    return isASCIIDigit(c) || isASCIIAlpha(c);
-}
-
-template<typename CharType> inline bool isASCIIHexDigit(CharType c)
-{
-    return isASCIIDigit(c) || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
-}
-
-template<typename CharType> inline bool isASCIIOctalDigit(CharType c)
-{
-    return (c >= '0') & (c <= '7');
-}
-
-template<typename CharType> inline bool isASCIIPrintable(CharType c)
-{
-    return c >= ' ' && c <= '~';
-}
-
-/*
- Statistics from a run of Apple's page load test for callers of isASCIISpace:
-
- character          count
- ---------          -----
- non-spaces         689383
- 20  space          294720
- 0A  \n             89059
- 09  \t             28320
- 0D  \r             0
- 0C  \f             0
- 0B  \v             0
- */
-template<typename CharType> inline bool isASCIISpace(CharType c)
-{
-    return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9));
-}
-
-extern const LChar ASCIICaseFoldTable[256] = {
-    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-    0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};
-
-template<typename CharType> inline int toASCIIHexValue(CharType c)
-{
-    DCHECK(isASCIIHexDigit(c));
-    return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF;
-}
-
-template<typename CharType> inline int toASCIIHexValue(CharType upperValue, CharType lowerValue)
-{
-    DCHECK(isASCIIHexDigit(upperValue) && isASCIIHexDigit(lowerValue));
-    return ((toASCIIHexValue(upperValue) << 4) & 0xF0) | toASCIIHexValue(lowerValue);
-}
-
-inline char lowerNibbleToASCIIHexDigit(char c)
-{
-    char nibble = c & 0xF;
-    return nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
-}
-
-inline char upperNibbleToASCIIHexDigit(char c)
-{
-    char nibble = (c >> 4) & 0xF;
-    return nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
-}
+using UChar32 = uint32_t;
 
 inline int inlineUTF8SequenceLengthNonASCII(char b0)
 {
@@ -128,7 +30,7 @@
 
 inline int inlineUTF8SequenceLength(char b0)
 {
-    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
+    return String16::isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
 }
 
 // Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
@@ -145,48 +47,6 @@
     sourceIllegal // source sequence is illegal/malformed
 } ConversionResult;
 
-ConversionResult convertLatin1ToUTF8(
-    const LChar** sourceStart, const LChar* sourceEnd,
-    char** targetStart, char* targetEnd)
-{
-    ConversionResult result = conversionOK;
-    const LChar* source = *sourceStart;
-    char* target = *targetStart;
-    while (source < sourceEnd) {
-        UChar32 ch;
-        unsigned short bytesToWrite = 0;
-        const UChar32 byteMask = 0xBF;
-        const UChar32 byteMark = 0x80;
-        const LChar* oldSource = source; // In case we have to back up because of target overflow.
-        ch = static_cast<unsigned short>(*source++);
-
-        // Figure out how many bytes the result will require
-        if (ch < (UChar32)0x80)
-            bytesToWrite = 1;
-        else
-            bytesToWrite = 2;
-
-        target += bytesToWrite;
-        if (target > targetEnd) {
-            source = oldSource; // Back up source pointer!
-            target -= bytesToWrite;
-            result = targetExhausted;
-            break;
-        }
-        switch (bytesToWrite) { // note: everything falls through.
-        case 2:
-            *--target = (char)((ch | byteMark) & byteMask);
-            ch >>= 6;
-        case 1:
-            *--target =  (char)(ch | firstByteMark[bytesToWrite]);
-        }
-        target += bytesToWrite;
-    }
-    *sourceStart = source;
-    *targetStart = target;
-    return result;
-}
-
 ConversionResult convertUTF16ToUTF8(
     const UChar** sourceStart, const UChar* sourceEnd,
     char** targetStart, char* targetEnd, bool strict)
@@ -495,42 +355,6 @@
     return String16(bufferStart, utf16Length);
 }
 
-// trim from start
-static inline wstring &ltrim(wstring &s)
-{
-    s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
-        return s;
-}
-
-// trim from end
-static inline wstring &rtrim(wstring &s)
-{
-    s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
-        return s;
-}
-
-// trim from both ends
-static inline wstring &trim(wstring &s)
-{
-    return ltrim(rtrim(s));
-}
-
-// static
-std::string String16::intToString(int i)
-{
-    char buffer[50];
-    std::sprintf(buffer, "%d", i);
-    return std::string(buffer);
-}
-
-// static
-std::string String16::doubleToString(double d)
-{
-    char buffer[100];
-    std::sprintf(buffer, "%f", d);
-    return std::string(buffer);
-}
-
 std::string String16::utf8() const
 {
     unsigned length = this->length();
@@ -577,12 +401,5 @@
     return std::string(bufferVector.data(), buffer - bufferVector.data());
 }
 
-String16 String16::stripWhiteSpace() const
-{
-    wstring result(m_impl);
-    trim(result);
-    return result;
-}
-
 } // namespace protocol
 } // namespace blink
diff --git a/String16STL.h b/String16STL.h
index 9e6f41f..51da506 100644
--- a/String16STL.h
+++ b/String16STL.h
@@ -13,21 +13,17 @@
 #include <vector>
 
 using UChar = uint16_t;
-using UChar32 = uint32_t;
-using LChar = unsigned char;
-// presubmit: allow wstring
-using wstring = std::basic_string<UChar>;
-const size_t kNotFound = static_cast<size_t>(-1);
 
 namespace blink {
 namespace protocol {
 
-class String16 {
+class String16 : public String16Base<String16, UChar> {
 public:
+    static const size_t kNotFound = static_cast<size_t>(-1);
+
     String16() { }
     String16(const String16& other) : m_impl(other.m_impl) { }
-    // presubmit: allow wstring
-    String16(const wstring& impl) : m_impl(impl) { }
+    String16(const UChar* characters, size_t size) : m_impl(characters, size) { }
     String16(const UChar* characters) : m_impl(characters) { }
     String16(const char* characters) : String16(characters, std::strlen(characters)) { }
     String16(const char* characters, size_t size)
@@ -36,88 +32,22 @@
         for (size_t i = 0; i < size; ++i)
             m_impl[i] = characters[i];
     }
-    String16(const UChar* characters, size_t size) : m_impl(characters, size) { }
+
     String16 isolatedCopy() const { return String16(m_impl); }
-
-    size_t charactersSizeInBytes() const { return m_impl.size() * sizeof(UChar); }
     const UChar* characters16() const { return m_impl.c_str(); }
-    std::string utf8() const;
-    static String16 fromUTF8(const char* stringStart, size_t length);
-    static String16 fromInteger(int i) { return String16(String16::intToString(i).c_str()); }
-    static String16 fromDouble(double d) { return String16(String16::doubleToString(d).c_str()); }
-    static String16 fromDoubleFixedPrecision(double d, int len) { return String16(String16::doubleToString(d).c_str()); }
-
-    static double charactersToDouble(const UChar* characters, size_t length, bool* ok = 0)
-    {
-        std::string str;
-        str.resize(length);
-        for (size_t i = 0; i < length; ++i)
-            str[i] = static_cast<char>(characters[i]);
-
-        const char* buffer = str.c_str();
-        char* endptr;
-        double result = strtod(buffer, &endptr);
-        if (ok)
-            *ok = buffer + length == endptr;
-        return result;
-    }
-
-    String16 substring(unsigned pos, unsigned len = 0xFFFFFFFF) const
-    {
-        return String16(m_impl.substr(pos, len));
-    }
-
-    String16 stripWhiteSpace() const;
-
-    int toInt(bool* ok = 0) const
-    {
-        size_t length = m_impl.length();
-        std::string str;
-        str.resize(length);
-        for (size_t i = 0; i < length; ++i)
-            str[i] = static_cast<char>(m_impl[i]);
-
-        const char* buffer = str.c_str();
-        char* endptr;
-        int result = strtol(buffer, &endptr, 10);
-        if (ok)
-            *ok = buffer + length == endptr;
-        return result;
-    }
-
     size_t length() const { return m_impl.length(); }
     bool isEmpty() const { return !m_impl.length(); }
     UChar operator[](unsigned index) const { return m_impl[index]; }
+    String16 substring(unsigned pos, unsigned len = UINT_MAX) const { return String16(m_impl.substr(pos, len)); }
+    size_t find(const String16& str, unsigned start = 0) const { return m_impl.find(str.m_impl, start); }
+    size_t reverseFind(const String16& str, unsigned start = UINT_MAX) const { return m_impl.rfind(str.m_impl, start); }
 
-    size_t find(UChar c, unsigned start = 0) const
-    {
-        return m_impl.find(c, start);
-    }
+    // Convenience methods.
+    std::string utf8() const;
+    static String16 fromUTF8(const char* stringStart, size_t length);
 
-    size_t find(const String16& str, unsigned start = 0) const
-    {
-        return m_impl.find(str.m_impl, start);
-    }
-
-    size_t reverseFind(const String16& str, unsigned start = 0xFFFFFFFF) const
-    {
-        return m_impl.rfind(str.m_impl, start);
-    }
-
-    bool startWith(const String16& s) const
-    {
-        if (m_impl.length() < s.m_impl.length())
-            return false;
-        return m_impl.substr(0, s.m_impl.length()) == s.m_impl;
-    }
-
-    bool endsWith(UChar character) const
-    {
-        return m_impl.length() && m_impl[m_impl.length() - 1] == character;
-    }
-
-    // presubmit: allow wstring
-    const wstring& impl() const { return m_impl; }
+    const std::basic_string<UChar>& impl() const { return m_impl; }
+    explicit String16(const std::basic_string<UChar>& impl) : m_impl(impl) { }
 
     std::size_t hash() const
     {
@@ -132,123 +62,26 @@
     }
 
 private:
-    static std::string intToString(int);
-    static std::string doubleToString(double);
-    // presubmit: allow wstring
-    wstring m_impl;
+    std::basic_string<UChar> m_impl;
     mutable bool has_hash = false;
     mutable std::size_t hash_code = 0;
 };
 
-static inline bool isSpaceOrNewline(UChar c)
-{
-    return std::isspace(c);  // NOLINT
-}
-
-class String16Builder {
-public:
-    String16Builder() { }
-
-    void append(const String16& str)
-    {
-        m_impl += str.impl();
-    }
-
-    void append(UChar c)
-    {
-        m_impl += c;
-    }
-
-    void append(LChar c)
-    {
-        m_impl += c;
-    }
-
-    void append(char c)
-    {
-        m_impl += c;
-    }
-
-    void appendNumber(int i)
-    {
-        m_impl = m_impl + String16::fromInteger(i).impl();
-    }
-
-    void appendNumber(double d)
-    {
-        m_impl = m_impl + String16::fromDoubleFixedPrecision(d, 6).impl();
-    }
-
-    void append(const UChar* c, size_t length)
-    {
-        // presubmit: allow wstring
-        m_impl += wstring(c, length);
-    }
-
-    void append(const char* c, size_t length)
-    {
-        m_impl += String16(c, length).impl();
-    }
-
-    String16 toString()
-    {
-        return String16(m_impl);
-    }
-
-    void reserveCapacity(unsigned newCapacity)
-    {
-    }
-
-private:
-    // presubmit: allow wstring
-    wstring m_impl;
-};
-
 inline bool operator==(const String16& a, const String16& b) { return a.impl() == b.impl(); }
 inline bool operator!=(const String16& a, const String16& b) { return a.impl() != b.impl(); }
 inline bool operator==(const String16& a, const char* b) { return a.impl() == String16(b).impl(); }
-inline bool operator<(const String16& a, const String16& b) { return a.impl() < b.impl(); }
-
-inline String16 operator+(const String16& a, const char* b)
-{
-    return String16(a.impl() + String16(b).impl());
-}
-
-inline String16 operator+(const char* a, const String16& b)
-{
-    return String16(String16(a).impl() + b.impl());
-}
-
-inline String16 operator+(const String16& a, const String16& b)
-{
-    return String16(a.impl() + b.impl());
-}
+inline String16 operator+(const String16& a, const char* b) { return String16(a.impl() + String16(b).impl()); }
+inline String16 operator+(const char* a, const String16& b) { return String16(String16(a).impl() + b.impl()); }
+inline String16 operator+(const String16& a, const String16& b) { return String16(a.impl() + b.impl()); }
 
 } // namespace protocol
 } // namespace blink
 
-using String16 = blink::protocol::String16;
-using String16Builder = blink::protocol::String16Builder;
-
-
-namespace WTF {
-// Interim solution for those headers that reference WTF::String for overrides.
-// It does nothing. If the code actually relies on WTF:String, it will not
-// compile!
-// TODO(eostroukhov): Eradicate
-class String {
-public:
-    String() {};
-    String(const String16& other) {};
-    operator String16() const { return String16(); };
-};
-} // namespace WTF
-
 #if !defined(__APPLE__) || defined(_LIBCPP_VERSION)
 
 namespace std {
-template<> struct hash<String16> {
-    std::size_t operator()(const String16& string) const
+template<> struct hash<blink::protocol::String16> {
+    std::size_t operator()(const blink::protocol::String16& string) const
     {
         return string.hash();
     }
@@ -258,6 +91,12 @@
 
 #endif // !defined(__APPLE__) || defined(_LIBCPP_VERSION)
 
-using String = WTF::String;
+class InspectorProtocolConvenienceStringType {
+public:
+    // This class should not be ever instantiated, so we don't implement constructors.
+    InspectorProtocolConvenienceStringType();
+    InspectorProtocolConvenienceStringType(const blink::protocol::String16& other);
+    operator blink::protocol::String16() const { return blink::protocol::String16(); };
+};
 
 #endif // !defined(String16STL_h)
diff --git a/String16WTF.cpp b/String16WTF.cpp
deleted file mode 100644
index 387ecc3..0000000
--- a/String16WTF.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "platform/inspector_protocol/String16WTF.h"
-
-namespace blink {
-namespace protocol {
-
-String16::String16(const String16& other) : m_impl(other.m_impl) { }
-
-String16::String16(const UChar* u, unsigned length) : m_impl(u, length) { }
-
-String16::String16(const char* characters) : String16(characters, strlen(characters)) { }
-
-String16::String16(const WTF::String& other)
-{
-    if (other.isNull())
-        return;
-    if (!other.is8Bit()) {
-        m_impl = other;
-        return;
-    }
-
-    UChar* data;
-    const LChar* characters = other.characters8();
-    size_t length = other.length();
-    m_impl = String::createUninitialized(length, data);
-    for (size_t i = 0; i < length; ++i)
-        data[i] = characters[i];
-}
-
-String16::String16(const char* characters, size_t length)
-{
-    UChar* data;
-    m_impl = String::createUninitialized(length, data);
-    for (size_t i = 0; i < length; ++i)
-        data[i] = characters[i];
-}
-
-String16 String16::createUninitialized(unsigned length, UChar*& data)
-{
-    return String::createUninitialized(length, data);
-}
-
-} // namespace protocol
-} // namespace blink
diff --git a/String16WTF.h b/String16WTF.h
index 15292f0..b65383a 100644
--- a/String16WTF.h
+++ b/String16WTF.h
@@ -17,111 +17,78 @@
 namespace blink {
 namespace protocol {
 
-class PLATFORM_EXPORT String16 {
+class PLATFORM_EXPORT String16 : public String16Base<String16, UChar> {
 public:
+    static const size_t kNotFound = WTF::kNotFound;
+
     String16() { }
-    String16(const String16& other);
-    String16(const UChar*, unsigned);
-    String16(const char*);
-    String16(const char*, size_t);
-    static String16 createUninitialized(unsigned length, UChar*& data);
+    String16(const String16& other) : m_impl(other.m_impl) { }
+    String16(const UChar* characters, unsigned length) : m_impl(characters, length) { }
+    String16(const char* characters) : String16(characters, strlen(characters)) { }
+    String16(const char* characters, size_t length)
+    {
+        UChar* data;
+        m_impl = WTF::String::createUninitialized(length, data);
+        for (size_t i = 0; i < length; ++i)
+            data[i] = characters[i];
+    }
+
+    ~String16() { }
+
+    String16 isolatedCopy() const { return String16(m_impl.isolatedCopy()); }
+    const UChar* characters16() const { return m_impl.isEmpty() ? nullptr : m_impl.characters16(); }
+    size_t length() const { return m_impl.length(); }
+    bool isEmpty() const { return m_impl.isEmpty(); }
+    UChar operator[](unsigned index) const { return m_impl[index]; }
+    String16 substring(unsigned pos, unsigned len = UINT_MAX) const { return m_impl.substring(pos, len); }
+    size_t find(const String16& str, unsigned start = 0) const { return m_impl.find(str.impl(), start); }
+    size_t reverseFind(const String16& str, unsigned start = UINT_MAX) const { return m_impl.reverseFind(str.impl(), start); }
 
     // WTF convenience constructors and helper methods.
     String16(const WebString& other) : String16(String(other)) { }
     template<typename StringType1, typename StringType2>
     String16(const WTF::StringAppend<StringType1, StringType2>& impl) : String16(String(impl)) { }
     String16(const WTF::AtomicString& impl) : String16(String(impl)) { }
-    String16(const WTF::String& impl);
+    String16(const WTF::String& impl) : m_impl(impl) { m_impl.ensure16Bit(); }
     String16(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
     bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
     operator WTF::String() const { return m_impl; }
     operator WTF::StringView() const { return StringView(m_impl); }
     operator WebString() { return m_impl; }
     const WTF::String& impl() const { return m_impl; }
-    String16 isolatedCopy() const { return String16(m_impl.isolatedCopy()); }
-
-    ~String16() { }
-
-    static String16 fromInteger(int i) { return String::number(i); }
-    static String16 fromDouble(double number) { return Decimal::fromDouble(number).toString(); }
-    static String16 fromDoubleFixedPrecision(double number, int precision) { return String::numberToStringFixedWidth(number, precision); }
-
-    size_t length() const { return m_impl.length(); }
-    bool isEmpty() const { return m_impl.isEmpty(); }
-    UChar operator[](unsigned index) const { return m_impl[index]; }
-
-    size_t charactersSizeInBytes() const { return m_impl.charactersSizeInBytes(); }
-    const UChar* characters16() const { return m_impl.isEmpty() ? nullptr : m_impl.characters16(); }
-
-    static double charactersToDouble(const LChar* characters, size_t length, bool* ok = 0) { return ::charactersToDouble(characters, length, ok); }
-    static double charactersToDouble(const UChar* characters, size_t length, bool* ok = 0) { return ::charactersToDouble(characters, length, ok); }
-
-    String16 substring(unsigned pos, unsigned len = UINT_MAX) const { return m_impl.substring(pos, len); }
-    String16 stripWhiteSpace() const { return m_impl.stripWhiteSpace(); }
-
-    int toInt(bool* ok = 0) const { return m_impl.toInt(ok); }
-
-    size_t find(UChar c, unsigned start = 0) const { return m_impl.find(c, start); }
-    size_t find(const String16& str, unsigned start = 0) const { return m_impl.find(str.impl(), start); }
-    size_t reverseFind(const String16& str, unsigned start = UINT_MAX) const { return m_impl.reverseFind(str.impl(), start); }
-
-    bool startWith(const String16& s) const { return m_impl.startsWith(s); }
-    bool startWith(UChar character) const { return m_impl.startsWith(character); }
-    bool endsWith(const String16& s) const { return m_impl.endsWith(s); }
-    bool endsWith(UChar character) const { return m_impl.endsWith(character); }
 
 private:
     WTF::String m_impl;
 };
 
-class String16Builder {
-public:
-    String16Builder() { }
-    void append(const String16& str) { m_impl.append(str); };
-    void append(UChar c) { m_impl.append(c); };
-    void append(LChar c) { m_impl.append(c); };
-    void append(char c) { m_impl.append(c); };
-    void append(const UChar* c, size_t size) { m_impl.append(c, size); };
-    void append(const char* characters, unsigned length) { m_impl.append(characters, length); }
-    void appendNumber(int number) { m_impl.appendNumber(number); }
-    void appendNumber(double number) { m_impl.appendNumber(number); }
-    String16 toString() { return m_impl.toString(); }
-    void reserveCapacity(unsigned newCapacity) { m_impl.reserveCapacity(newCapacity); }
-
-private:
-    WTF::StringBuilder m_impl;
-};
-
 inline bool operator==(const String16& a, const String16& b) { return a.impl() == b.impl(); }
 inline bool operator!=(const String16& a, const String16& b) { return a.impl() != b.impl(); }
 inline bool operator==(const String16& a, const char* b) { return a.impl() == b; }
-
-inline String16 operator+(const String16& a, const char* b)
-{
-    return String(a.impl() + b);
-}
-
-inline String16 operator+(const char* a, const String16& b)
-{
-    return String(a + b.impl());
-}
-
-inline String16 operator+(const String16& a, const String16& b)
-{
-    return String(a.impl() + b.impl());
-}
+inline String16 operator+(const String16& a, const char* b) { return String16(a.impl() + b); }
+inline String16 operator+(const char* a, const String16& b) { return String16(a + b.impl()); }
+inline String16 operator+(const String16& a, const String16& b) { return String16(a.impl() + b.impl()); }
 
 } // namespace protocol
 } // namespace blink
 
-using String16 = blink::protocol::String16;
-using String16Builder = blink::protocol::String16Builder;
+namespace std {
+template<> struct hash<blink::protocol::String16> {
+    std::size_t operator()(const blink::protocol::String16& string) const
+    {
+        return StringHash::hash(string.impl());
+    }
+};
+} // namespace std
+
+using InspectorProtocolConvenienceStringType = WTF::String;
+
+// WTF helpers below this line.
 
 namespace WTF {
 
 struct String16Hash {
-    static unsigned hash(const String16& key) { return StringHash::hash(key.impl()); }
-    static bool equal(const String16& a, const String16& b)
+    static unsigned hash(const blink::protocol::String16& key) { return StringHash::hash(key.impl()); }
+    static bool equal(const blink::protocol::String16& a, const blink::protocol::String16& b)
     {
         return StringHash::equal(a.impl(), b.impl());
     }
@@ -129,26 +96,16 @@
 };
 
 template<typename T> struct DefaultHash;
-template<> struct DefaultHash<String16> {
+template<> struct DefaultHash<blink::protocol::String16> {
     typedef String16Hash Hash;
 };
 
 template<>
-struct HashTraits<String16> : SimpleClassHashTraits<String16> {
+struct HashTraits<blink::protocol::String16> : SimpleClassHashTraits<blink::protocol::String16> {
     static const bool hasIsEmptyValueFunction = true;
-    static bool isEmptyValue(const String16& a) { return a.impl().isNull(); }
+    static bool isEmptyValue(const blink::protocol::String16& a) { return a.impl().isNull(); }
 };
 
 } // namespace WTF
 
-namespace std {
-template<> struct hash<String16> {
-    std::size_t operator()(const String16& string) const
-    {
-        return StringHash::hash(string.impl());
-    }
-};
-
-} // namespace std
-
 #endif // !defined(String16WTF_h)
diff --git a/ValueConversions.h b/ValueConversions.h
index ba1d080..fe30a4e 100644
--- a/ValueConversions.h
+++ b/ValueConversions.h
@@ -83,8 +83,8 @@
 };
 
 template<>
-struct ValueConversions<String> {
-    static String parse(protocol::Value* value, ErrorSupport* errors)
+struct ValueConversions<InspectorProtocolConvenienceStringType> {
+    static InspectorProtocolConvenienceStringType parse(protocol::Value* value, ErrorSupport* errors)
     {
         String16 result;
         bool success = value ? value->asString(&result) : false;
@@ -93,7 +93,7 @@
         return result;
     }
 
-    static std::unique_ptr<protocol::Value> serialize(const String& value)
+    static std::unique_ptr<protocol::Value> serialize(const InspectorProtocolConvenienceStringType& value)
     {
         return StringValue::create(value);
     }
diff --git a/Values.cpp b/Values.cpp
index 5b8f13b..33a89da 100644
--- a/Values.cpp
+++ b/Values.cpp
@@ -35,13 +35,14 @@
     return true;
 }
 
-const LChar hexDigits[17] = "0123456789ABCDEF";
+const char hexDigits[17] = "0123456789ABCDEF";
 
 void appendUnsignedAsHex(UChar number, String16Builder* dst)
 {
     dst->append("\\u");
     for (size_t i = 0; i < 4; ++i) {
-        dst->append(hexDigits[(number & 0xF000) >> 12]);
+        UChar c = hexDigits[(number & 0xF000) >> 12];
+        dst->append(c);
         number <<= 4;
     }
 }