Make StringData a templated class.

First step in making the same changes to CFX_WideString that we
just made to CFX_ByteString.

Review URL: https://codereview.chromium.org/1844073003
diff --git a/BUILD.gn b/BUILD.gn
index 8e9cc0c..806367e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -588,6 +588,7 @@
 
 static_library("fxcrt") {
   sources = [
+    "core/fxcrt/cfx_string_data_template.h",
     "core/fxcrt/extension.h",
     "core/fxcrt/fx_basic_array.cpp",
     "core/fxcrt/fx_basic_bstring.cpp",
diff --git a/core/fxcrt/cfx_string_data_template.h b/core/fxcrt/cfx_string_data_template.h
new file mode 100644
index 0000000..b53b251
--- /dev/null
+++ b/core/fxcrt/cfx_string_data_template.h
@@ -0,0 +1,115 @@
+// Copyright 2016 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_
+#define CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_
+
+#include "core/fxcrt/include/fx_memory.h"
+#include "core/fxcrt/include/fx_system.h"
+#include "third_party/base/numerics/safe_math.h"
+
+template <typename CharType>
+class CFX_StringDataTemplate {
+ public:
+  static CFX_StringDataTemplate* Create(FX_STRSIZE nLen) {
+    FXSYS_assert(nLen > 0);
+
+    // Calculate space needed for the fixed portion of the struct plus the
+    // NUL char that is not included in |m_nAllocLength|.
+    int overhead =
+        offsetof(CFX_StringDataTemplate, m_String) + sizeof(CharType);
+    pdfium::base::CheckedNumeric<int> nSize = nLen;
+    nSize *= sizeof(CharType);
+    nSize += overhead;
+
+    // Now round to an 8-byte boundary. We'd expect that this is the minimum
+    // granularity of any of the underlying allocators, so there may be cases
+    // where we can save a re-alloc when adding a few characters to a string
+    // by using this otherwise wasted space.
+    nSize += 7;
+    int totalSize = nSize.ValueOrDie() & ~7;
+    int usableLen = (totalSize - overhead) / sizeof(CharType);
+    FXSYS_assert(usableLen >= nLen);
+
+    void* pData = FX_Alloc(uint8_t, totalSize);
+    return new (pData) CFX_StringDataTemplate(nLen, usableLen);
+  }
+
+  static CFX_StringDataTemplate* Create(const CFX_StringDataTemplate& other) {
+    CFX_StringDataTemplate* result = Create(other.m_nDataLength);
+    result->CopyContents(other);
+    return result;
+  }
+
+  static CFX_StringDataTemplate* Create(const CharType* pStr, FX_STRSIZE nLen) {
+    CFX_StringDataTemplate* result = Create(nLen);
+    result->CopyContents(pStr, nLen);
+    return result;
+  }
+
+  void Retain() { ++m_nRefs; }
+  void Release() {
+    if (--m_nRefs <= 0)
+      FX_Free(this);
+  }
+
+  bool CanOperateInPlace(FX_STRSIZE nTotalLen) const {
+    return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
+  }
+
+  void CopyContents(const CFX_StringDataTemplate& other) {
+    FXSYS_assert(other.m_nDataLength <= m_nAllocLength);
+    FXSYS_memcpy(m_String, other.m_String,
+                 (other.m_nDataLength + 1) * sizeof(CharType));
+  }
+
+  void CopyContents(const CharType* pStr, FX_STRSIZE nLen) {
+    FXSYS_assert(nLen >= 0 && nLen <= m_nAllocLength);
+    FXSYS_memcpy(m_String, pStr, nLen * sizeof(CharType));
+    m_String[nLen] = 0;
+  }
+
+  void CopyContentsAt(FX_STRSIZE offset,
+                      const CharType* pStr,
+                      FX_STRSIZE nLen) {
+    FXSYS_assert(offset >= 0 && nLen >= 0 && offset + nLen <= m_nAllocLength);
+    FXSYS_memcpy(m_String + offset, pStr, nLen * sizeof(CharType));
+    m_String[offset + nLen] = 0;
+  }
+
+  // To ensure ref counts do not overflow, consider the worst possible case:
+  // the entire address space contains nothing but pointers to this object.
+  // Since the count increments with each new pointer, the largest value is
+  // the number of pointers that can fit into the address space. The size of
+  // the address space itself is a good upper bound on it.
+  intptr_t m_nRefs;  // Would prefer ssize_t, but no windows support.
+
+  // |FX_STRSIZE| is currently typedef'd as |int|.
+  // TODO(palmer): It should be a |size_t|, or at least unsigned.
+  // These lengths are in terms of number of characters, not bytes, and do not
+  // include the terminating NUL character, but the underlying buffer is sized
+  // to be capable of holding it.
+  FX_STRSIZE m_nDataLength;
+  FX_STRSIZE m_nAllocLength;
+
+  // Not really 1, variable size.
+  CharType m_String[1];
+
+ private:
+  CFX_StringDataTemplate(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
+      : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
+    FXSYS_assert(dataLen >= 0);
+    FXSYS_assert(dataLen <= allocLen);
+    m_String[dataLen] = 0;
+  }
+
+  ~CFX_StringDataTemplate() = delete;
+};
+
+extern template class CFX_StringDataTemplate<FX_CHAR>;
+extern template class CFX_StringDataTemplate<FX_WCHAR>;
+
+#endif  // CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_
diff --git a/core/fxcrt/fx_basic_bstring.cpp b/core/fxcrt/fx_basic_bstring.cpp
index aa63edf..3e4e9c3 100644
--- a/core/fxcrt/fx_basic_bstring.cpp
+++ b/core/fxcrt/fx_basic_bstring.cpp
@@ -11,7 +11,11 @@
 #include "core/fxcrt/include/fx_basic.h"
 #include "third_party/base/numerics/safe_math.h"
 
-static int _Buffer_itoa(char* buf, int i, uint32_t flags) {
+template class CFX_StringDataTemplate<FX_CHAR>;
+
+namespace {
+
+int Buffer_itoa(char* buf, int i, uint32_t flags) {
   if (i == 0) {
     buf[0] = '0';
     return 1;
@@ -44,76 +48,7 @@
   return len;
 }
 
-CFX_ByteString CFX_ByteString::FormatInteger(int i, uint32_t flags) {
-  char buf[32];
-  return CFX_ByteStringC(buf, _Buffer_itoa(buf, i, flags));
-}
-
-// static
-CFX_ByteString::StringData* CFX_ByteString::StringData::Create(
-    FX_STRSIZE nLen) {
-  FXSYS_assert(nLen > 0);
-
-  // Fixed portion of header plus a NUL char not included in m_nAllocLength.
-  // sizeof(FX_CHAR) is always 1, used for consistency with CFX_Widestring.
-  int overhead = offsetof(StringData, m_String) + sizeof(FX_CHAR);
-  pdfium::base::CheckedNumeric<int> nSize = nLen;
-  nSize += overhead;
-
-  // Now round to an 8-byte boundary. We'd expect that this is the minimum
-  // granularity of any of the underlying allocators, so there may be cases
-  // where we can save a re-alloc when adding a few characters to a string
-  // by using this otherwise wasted space.
-  nSize += 7;
-  int totalSize = nSize.ValueOrDie() & ~7;
-  int usableSize = totalSize - overhead;
-  FXSYS_assert(usableSize >= nLen);
-
-  void* pData = FX_Alloc(uint8_t, totalSize);
-  return new (pData) StringData(nLen, usableSize);
-}
-
-CFX_ByteString::StringData* CFX_ByteString::StringData::Create(
-    const StringData& other) {
-  StringData* result = Create(other.m_nDataLength);
-  result->CopyContents(other);
-  return result;
-}
-
-CFX_ByteString::StringData* CFX_ByteString::StringData::Create(
-    const FX_CHAR* pStr,
-    FX_STRSIZE nLen) {
-  StringData* result = Create(nLen);
-  result->CopyContents(pStr, nLen);
-  return result;
-}
-
-CFX_ByteString::StringData::StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
-    : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
-  FXSYS_assert(dataLen >= 0);
-  FXSYS_assert(dataLen <= allocLen);
-  m_String[dataLen] = 0;
-}
-
-void CFX_ByteString::StringData::CopyContents(const StringData& other) {
-  FXSYS_assert(other.m_nDataLength <= m_nAllocLength);
-  FXSYS_memcpy(m_String, other.m_String, other.m_nDataLength + 1);
-}
-
-void CFX_ByteString::StringData::CopyContents(const FX_CHAR* pStr,
-                                              FX_STRSIZE nLen) {
-  FXSYS_assert(nLen >= 0 && nLen <= m_nAllocLength);
-  FXSYS_memcpy(m_String, pStr, nLen);
-  m_String[nLen] = 0;
-}
-
-void CFX_ByteString::StringData::CopyContentsAt(FX_STRSIZE offset,
-                                                const FX_CHAR* pStr,
-                                                FX_STRSIZE nLen) {
-  FXSYS_assert(offset >= 0 && nLen >= 0 && offset + nLen <= m_nAllocLength);
-  FXSYS_memcpy(m_String + offset, pStr, nLen);
-  m_String[offset + nLen] = 0;
-}
+}  // namespace
 
 CFX_ByteString::CFX_ByteString(const FX_CHAR* pStr, FX_STRSIZE nLen) {
   if (nLen < 0)
@@ -451,6 +386,11 @@
 #define FORCE_UNICODE 0x20000
 #define FORCE_INT64 0x40000
 
+CFX_ByteString CFX_ByteString::FormatInteger(int i, uint32_t flags) {
+  char buf[32];
+  return CFX_ByteStringC(buf, Buffer_itoa(buf, i, flags));
+}
+
 void CFX_ByteString::FormatV(const FX_CHAR* pFormat, va_list argList) {
   va_list argListSave;
 #if defined(__ARMCC_VERSION) ||                                              \
diff --git a/core/fxcrt/include/fx_string.h b/core/fxcrt/include/fx_string.h
index 9373b05..e084f50 100644
--- a/core/fxcrt/include/fx_string.h
+++ b/core/fxcrt/include/fx_string.h
@@ -10,6 +10,7 @@
 #include <stdint.h>  // For intptr_t.
 #include <algorithm>
 
+#include "core/fxcrt/cfx_string_data_template.h"
 #include "core/fxcrt/include/cfx_retain_ptr.h"
 #include "core/fxcrt/include/fx_memory.h"
 #include "core/fxcrt/include/fx_system.h"
@@ -282,49 +283,7 @@
   static CFX_ByteString FormatFloat(FX_FLOAT f, int precision = 0);
 
  protected:
-  class StringData {
-   public:
-    static StringData* Create(FX_STRSIZE nLen);
-    static StringData* Create(const StringData& other);
-    static StringData* Create(const FX_CHAR* pStr, FX_STRSIZE nLen);
-
-    void Retain() { ++m_nRefs; }
-    void Release() {
-      if (--m_nRefs <= 0)
-        FX_Free(this);
-    }
-
-    bool CanOperateInPlace(FX_STRSIZE nTotalLen) const {
-      return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
-    }
-
-    void CopyContents(const StringData& other);
-    void CopyContents(const FX_CHAR* pStr, FX_STRSIZE nLen);
-    void CopyContentsAt(FX_STRSIZE offset,
-                        const FX_CHAR* pStr,
-                        FX_STRSIZE nLen);
-
-    // To ensure ref counts do not overflow, consider the worst possible case:
-    // the entire address space contains nothing but pointers to this object.
-    // Since the count increments with each new pointer, the largest value is
-    // the number of pointers that can fit into the address space. The size of
-    // the address space itself is a good upper bound on it.
-    intptr_t m_nRefs;  // Would prefer ssize_t, but no windows support.
-
-    // |FX_STRSIZE| is currently typedef'd as |int|.
-    // TODO(palmer): It should be a |size_t|, or at least unsigned.
-    // These lengths do not include the terminating NUL, but the underlying
-    // buffer is sized to be capable of holding it.
-    FX_STRSIZE m_nDataLength;
-    FX_STRSIZE m_nAllocLength;
-
-    // Not really 1, variable size.
-    FX_CHAR m_String[1];
-
-   private:
-    StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen);
-    ~StringData() = delete;
-  };
+  using StringData = CFX_StringDataTemplate<FX_CHAR>;
 
   void ReallocBeforeWrite(FX_STRSIZE nNewLen);
   void AllocBeforeWrite(FX_STRSIZE nNewLen);
diff --git a/pdfium.gyp b/pdfium.gyp
index 69aab07..dd864e9 100644
--- a/pdfium.gyp
+++ b/pdfium.gyp
@@ -610,6 +610,7 @@
       'target_name': 'fxcrt',
       'type': 'static_library',
       'sources': [
+        'core/fxcrt/cfx_string_data_template.h',
         'core/fxcrt/extension.h',
         'core/fxcrt/fx_basic_array.cpp',
         'core/fxcrt/fx_basic_bstring.cpp',