Make CFX_StringData be scoped by CFX_Bytestring and add methods.

This is a precondition for someday combining Byte/Wide strings
via templates.

R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1142533002
diff --git a/core/include/fxcrt/fx_string.h b/core/include/fxcrt/fx_string.h
index 8bb29da..a7b9a23 100644
--- a/core/include/fxcrt/fx_string.h
+++ b/core/include/fxcrt/fx_string.h
@@ -171,19 +171,6 @@
 #define FX_BSTRC(str) CFX_ByteStringC(str, sizeof str-1)
 #define FXBSTR_ID(c1, c2, c3, c4) ((c1 << 24) | (c2 << 16) | (c3 << 8) | (c4))
 
-// 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; we need not go
-// larger.
-struct CFX_StringData {
-    intptr_t	m_nRefs;  // Would prefer ssize_t, but no windows support.
-    FX_STRSIZE	m_nDataLength;
-    FX_STRSIZE	m_nAllocLength;
-    FX_CHAR		m_String[1];
-};
-
 // A mutable string with shared buffers using copy-on-write semantics that
 // avoids the cost of std::string's iterator stability guarantees.
 class CFX_ByteString
@@ -363,17 +350,45 @@
 #define FXFORMAT_CAPITAL		4
 
     static CFX_ByteString	FormatInteger(int i, FX_DWORD flags = 0);
-
     static CFX_ByteString	FormatFloat(FX_FLOAT f, int precision = 0);
-protected:
 
-    struct CFX_StringData*	m_pData;
+protected:
+    // 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; we need not go
+    // larger.
+    class StringData {
+      public:
+        static StringData* Create(int nLen);
+        void Retain() { ++m_nRefs; }
+        void Release() { if (--m_nRefs <= 0) FX_Free(this); }
+
+        intptr_t    m_nRefs;  // Would prefer ssize_t, but no windows support.
+        FX_STRSIZE  m_nDataLength;
+        FX_STRSIZE  m_nAllocLength;
+        FX_CHAR     m_String[1];
+
+      private:
+        StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
+                : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
+            FXSYS_assert(dataLen >= 0);
+            FXSYS_assert(allocLen >= 0);
+            FXSYS_assert(dataLen <= allocLen);
+            m_String[dataLen] = 0;
+        }
+        ~StringData() = delete;
+    };
+
     void					AllocCopy(CFX_ByteString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const;
     void					AssignCopy(FX_STRSIZE nSrcLen, FX_LPCSTR lpszSrcData);
     void					ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCSTR lpszSrc2Data);
     void					ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCSTR lpszSrcData);
     void					CopyBeforeWrite();
     void					AllocBeforeWrite(FX_STRSIZE nLen);
+
+    StringData* m_pData;
 };
 inline CFX_ByteStringC::CFX_ByteStringC(const CFX_ByteString& src)
 {
@@ -600,13 +615,6 @@
 typedef const CFX_WideStringC&	FX_WSTR;
 #define FX_WSTRC(wstr) CFX_WideStringC(wstr, FX_ArraySize(wstr) - 1)
 
-struct CFX_StringDataW {
-    intptr_t	m_nRefs;  // Would prefer ssize_t, but no windows support.
-    FX_STRSIZE	m_nDataLength;
-    FX_STRSIZE	m_nAllocLength;
-    FX_WCHAR	m_String[1];
-};
-
 // A mutable string with shared buffers using copy-on-write semantics that
 // avoids the cost of std::string's iterator stability guarantees.
 class CFX_WideString
@@ -777,14 +785,36 @@
     void					ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap = NULL);
 
 protected:
-    void					CopyBeforeWrite();
-    void					AllocBeforeWrite(FX_STRSIZE nLen);
-    void					ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
-    void					ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data);
-    void					AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
-    void					AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const;
+    class StringData {
+      public:
+        static StringData* Create(int nLen);
+        void Retain() { ++m_nRefs; }
+        void Release() { if (--m_nRefs <= 0) FX_Free(this); }
 
-    CFX_StringDataW*		m_pData;
+        intptr_t    m_nRefs;  // Would prefer ssize_t, but no windows support.
+        FX_STRSIZE  m_nDataLength;
+        FX_STRSIZE  m_nAllocLength;
+        FX_WCHAR    m_String[1];
+
+      private:
+        StringData(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
+                : m_nRefs(1), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
+            FXSYS_assert(dataLen >= 0);
+            FXSYS_assert(allocLen >= 0);
+            FXSYS_assert(dataLen <= allocLen);
+            m_String[dataLen] = 0;
+        }
+        ~StringData() = delete;
+    };
+
+    void                    CopyBeforeWrite();
+    void                    AllocBeforeWrite(FX_STRSIZE nLen);
+    void                    ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
+    void                    ConcatCopy(FX_STRSIZE nSrc1Len, FX_LPCWSTR lpszSrc1Data, FX_STRSIZE nSrc2Len, FX_LPCWSTR lpszSrc2Data);
+    void                    AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData);
+    void                    AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const;
+
+    StringData* m_pData;
 };
 inline CFX_WideStringC::CFX_WideStringC(const CFX_WideString& src)
 {
diff --git a/core/src/fxcrt/fx_basic_bstring.cpp b/core/src/fxcrt/fx_basic_bstring.cpp
index 65f4b36..87e50e7 100644
--- a/core/src/fxcrt/fx_basic_bstring.cpp
+++ b/core/src/fxcrt/fx_basic_bstring.cpp
@@ -47,7 +47,9 @@
     char buf[32];
     return CFX_ByteStringC(buf, _Buffer_itoa(buf, i, flags));
 }
-static CFX_StringData* FX_AllocString(int nLen)
+
+// static
+CFX_ByteString::StringData* CFX_ByteString::StringData::Create(int nLen)
 {
     // |nLen| is currently declared as in |int|. TODO(palmer): It should be
     // a |size_t|, or at least unsigned.
@@ -57,7 +59,7 @@
 
     // 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(CFX_StringData, m_String) + sizeof(FX_CHAR);
+    int overhead = offsetof(StringData, m_String) + sizeof(FX_CHAR);
     pdfium::base::CheckedNumeric<int> nSize = nLen;
     nSize += overhead;
 
@@ -70,34 +72,16 @@
     int usableSize = totalSize - overhead;
     FXSYS_assert(usableSize >= nLen);
 
-    CFX_StringData* pData = (CFX_StringData*)FX_Alloc(FX_BYTE, totalSize);
+    void* pData = FX_Alloc(FX_BYTE, totalSize);
     if (!pData) {
         return NULL;
     }
-    pData->m_nAllocLength = usableSize;
-    pData->m_nDataLength = nLen;
-    pData->m_nRefs = 1;
-    pData->m_String[nLen] = 0;
-    return pData;
-}
-static void FX_ReleaseString(CFX_StringData* pData)
-{
-    if (pData == NULL) {
-        return;
-    }
-    pData->m_nRefs --;
-    if (pData->m_nRefs <= 0) {
-        FX_Free(pData);
-    }
+    return new (pData) StringData(nLen, usableSize);
 }
 CFX_ByteString::~CFX_ByteString()
 {
-    if (m_pData == NULL) {
-        return;
-    }
-    m_pData->m_nRefs --;
-    if (m_pData->m_nRefs < 1) {
-        FX_Free(m_pData);
+    if (m_pData) {
+        m_pData->Release();
     }
 }
 CFX_ByteString::CFX_ByteString(FX_LPCSTR lpsz, FX_STRSIZE nLen)
@@ -106,7 +90,7 @@
         nLen = lpsz ? FXSYS_strlen(lpsz) : 0;
     }
     if (nLen) {
-        m_pData = FX_AllocString(nLen);
+        m_pData = StringData::Create(nLen);
         if (m_pData) {
             FXSYS_memcpy32(m_pData->m_String, lpsz, nLen);
         }
@@ -117,7 +101,7 @@
 CFX_ByteString::CFX_ByteString(FX_LPCBYTE lpsz, FX_STRSIZE nLen)
 {
     if (nLen > 0) {
-        m_pData = FX_AllocString(nLen);
+        m_pData = StringData::Create(nLen);
         if (m_pData) {
             FXSYS_memcpy32(m_pData->m_String, lpsz, nLen);
         }
@@ -127,7 +111,7 @@
 }
 CFX_ByteString::CFX_ByteString(char ch)
 {
-    m_pData = FX_AllocString(1);
+    m_pData = StringData::Create(1);
     if (m_pData) {
         m_pData->m_String[0] = ch;
     }
@@ -140,7 +124,7 @@
     }
     if (stringSrc.m_pData->m_nRefs >= 0) {
         m_pData = stringSrc.m_pData;
-        m_pData->m_nRefs ++;
+        m_pData->Retain();
     } else {
         m_pData = NULL;
         *this = stringSrc;
@@ -163,7 +147,7 @@
     if (nNewLen == 0) {
         return;
     }
-    m_pData = FX_AllocString(nNewLen);
+    m_pData = StringData::Create(nNewLen);
     if (m_pData) {
         FXSYS_memcpy32(m_pData->m_String, str1.GetCStr(), str1.GetLength());
         FXSYS_memcpy32(m_pData->m_String + str1.GetLength(), str2.GetCStr(), str2.GetLength());
@@ -201,7 +185,7 @@
         Empty();
         m_pData = stringSrc.m_pData;
         if (m_pData) {
-            m_pData->m_nRefs ++;
+            m_pData->Retain();
         }
     }
     return *this;
@@ -215,7 +199,7 @@
 {
     Empty();
     if (len) {
-        m_pData = FX_AllocString(len);
+        m_pData = StringData::Create(len);
         if (m_pData) {
             FXSYS_memcpy32(m_pData->m_String, buf, len);
         }
@@ -259,7 +243,7 @@
     if (!ptr) {
         return m_pData->m_nDataLength == 0;
     }
-    return strlen(ptr) == m_pData->m_nDataLength &&
+    return FXSYS_strlen(ptr) == m_pData->m_nDataLength &&
         FXSYS_memcmp32(ptr, m_pData->m_String, m_pData->m_nDataLength) == 0;
 }
 bool CFX_ByteString::Equal(const CFX_ByteStringC& str) const
@@ -285,15 +269,10 @@
 }
 void CFX_ByteString::Empty()
 {
-    if (m_pData == NULL) {
-        return;
+    if (m_pData) {
+        m_pData->Release();
+        m_pData = NULL;
     }
-    if (m_pData->m_nRefs > 1) {
-        m_pData->m_nRefs --;
-    } else {
-        FX_Free(m_pData);
-    }
-    m_pData = NULL;
 }
 bool CFX_ByteString::EqualNoCase(FX_BSTR str) const
 {
@@ -337,10 +316,10 @@
     if (m_pData == NULL || m_pData->m_nRefs <= 1) {
         return;
     }
-    CFX_StringData* pData = m_pData;
-    m_pData->m_nRefs --;
+    StringData* pData = m_pData;
+    m_pData->Release();
     FX_STRSIZE nDataLength = pData->m_nDataLength;
-    m_pData = FX_AllocString(nDataLength);
+    m_pData = StringData::Create(nDataLength);
     if (m_pData != NULL) {
         FXSYS_memcpy32(m_pData->m_String, pData->m_String, nDataLength + 1);
     }
@@ -351,7 +330,7 @@
         return;
     }
     Empty();
-    m_pData = FX_AllocString(nLen);
+    m_pData = StringData::Create(nLen);
 }
 void CFX_ByteString::ReleaseBuffer(FX_STRSIZE nNewLength)
 {
@@ -384,7 +363,7 @@
         return m_pData->m_String;
     }
     if (m_pData == NULL) {
-        m_pData = FX_AllocString(nMinBufLength);
+        m_pData = StringData::Create(nMinBufLength);
         if (!m_pData) {
             return NULL;
         }
@@ -392,21 +371,18 @@
         m_pData->m_String[0] = 0;
         return m_pData->m_String;
     }
-    CFX_StringData* pOldData = m_pData;
+    StringData* pOldData = m_pData;
     FX_STRSIZE nOldLen = pOldData->m_nDataLength;
     if (nMinBufLength < nOldLen) {
         nMinBufLength = nOldLen;
     }
-    m_pData = FX_AllocString(nMinBufLength);
+    m_pData = StringData::Create(nMinBufLength);
     if (!m_pData) {
         return NULL;
     }
     FXSYS_memcpy32(m_pData->m_String, pOldData->m_String, (nOldLen + 1));
     m_pData->m_nDataLength = nOldLen;
-    pOldData->m_nRefs --;
-    if (pOldData->m_nRefs <= 0) {
-        FX_Free(pOldData);
-    }
+    pOldData->Release();
     return m_pData->m_String;
 }
 FX_STRSIZE CFX_ByteString::Delete(FX_STRSIZE nIndex, FX_STRSIZE nCount)
@@ -438,7 +414,7 @@
         return;
     }
     if (m_pData == NULL) {
-        m_pData = FX_AllocString(nSrcLen);
+        m_pData = StringData::Create(nSrcLen);
         if (!m_pData) {
             return;
         }
@@ -446,9 +422,9 @@
         return;
     }
     if (m_pData->m_nRefs > 1 || m_pData->m_nDataLength + nSrcLen > m_pData->m_nAllocLength) {
-        CFX_StringData* pOldData = m_pData;
+        StringData* pOldData = m_pData;
         ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcData);
-        FX_ReleaseString(pOldData);
+        pOldData->Release();
     } else {
         FXSYS_memcpy32(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, nSrcLen);
         m_pData->m_nDataLength += nSrcLen;
@@ -462,7 +438,7 @@
     if (nNewLen == 0) {
         return;
     }
-    m_pData = FX_AllocString(nNewLen);
+    m_pData = StringData::Create(nNewLen);
     if (m_pData) {
         FXSYS_memcpy32(m_pData->m_String, lpszSrc1Data, nSrc1Len);
         FXSYS_memcpy32(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len);
@@ -504,7 +480,7 @@
         return;
     }
     ASSERT(dest.m_pData == NULL);
-    dest.m_pData = FX_AllocString(nCopyLen);
+    dest.m_pData = StringData::Create(nCopyLen);
     if (dest.m_pData) {
         FXSYS_memcpy32(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, nCopyLen);
     }
@@ -745,15 +721,15 @@
     }
     nNewLength++;
     if (m_pData == NULL || m_pData->m_nAllocLength < nNewLength) {
-        CFX_StringData* pOldData = m_pData;
+        StringData* pOldData = m_pData;
         FX_LPCSTR pstr = m_pData->m_String;
-        m_pData = FX_AllocString(nNewLength);
+        m_pData = StringData::Create(nNewLength);
         if (!m_pData) {
             return 0;
         }
         if(pOldData != NULL) {
             FXSYS_memmove32(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1));
-            FX_ReleaseString(pOldData);
+            pOldData->Release();
         } else {
             m_pData->m_String[0] = 0;
         }
@@ -929,7 +905,7 @@
         Empty();
         return nCount;
     }
-    CFX_StringData* pNewData = FX_AllocString(nNewLength);
+    StringData* pNewData = StringData::Create(nNewLength);
     if (!pNewData) {
         return 0;
     }
@@ -944,7 +920,7 @@
         pStart = pTarget + nSourceLen;
     }
     FXSYS_memcpy32(pDest, pStart, pEnd - pStart);
-    FX_ReleaseString(m_pData);
+    m_pData->Release();
     m_pData = pNewData;
     return nCount;
 }
diff --git a/core/src/fxcrt/fx_basic_wstring.cpp b/core/src/fxcrt/fx_basic_wstring.cpp
index 0511b84..da02205 100644
--- a/core/src/fxcrt/fx_basic_wstring.cpp
+++ b/core/src/fxcrt/fx_basic_wstring.cpp
@@ -9,7 +9,8 @@
 #include "../../include/fxcrt/fx_basic.h"
 #include "../../../third_party/base/numerics/safe_math.h"
 
-static CFX_StringDataW* FX_AllocStringW(int nLen)
+// static
+CFX_WideString::StringData* CFX_WideString::StringData::Create(int nLen)
 {
     // TODO(palmer): |nLen| should really be declared as |size_t|, or
     // at least unsigned.
@@ -18,7 +19,7 @@
     }
 
     // Fixed portion of header plus a NUL wide char not in m_nAllocLength.
-    int overhead = offsetof(CFX_StringDataW, m_String) + sizeof(FX_WCHAR);
+    int overhead = offsetof(StringData, m_String) + sizeof(FX_WCHAR);
     pdfium::base::CheckedNumeric<int> iSize = nLen;
     iSize *= sizeof(FX_WCHAR);
     iSize += overhead;
@@ -32,35 +33,16 @@
     int usableLen = (totalSize - overhead) / sizeof(FX_WCHAR);
     FXSYS_assert(usableLen >= nLen);
 
-    CFX_StringDataW* pData = (CFX_StringDataW*)FX_Alloc(FX_BYTE, iSize.ValueOrDie());
+    void* pData = FX_Alloc(FX_BYTE, iSize.ValueOrDie());
     if (!pData) {
         return NULL;
     }
-
-    pData->m_nAllocLength = usableLen;
-    pData->m_nDataLength = nLen;
-    pData->m_nRefs = 1;
-    pData->m_String[nLen] = 0;
-    return pData;
-}
-static void FX_ReleaseStringW(CFX_StringDataW* pData)
-{
-    if (pData == NULL) {
-        return;
-    }
-    pData->m_nRefs --;
-    if (pData->m_nRefs <= 0) {
-        FX_Free(pData);
-    }
+    return new (pData) StringData(nLen, usableLen);
 }
 CFX_WideString::~CFX_WideString()
 {
-    if (m_pData == NULL) {
-        return;
-    }
-    m_pData->m_nRefs --;
-    if (m_pData->m_nRefs < 1) {
-        FX_Free(m_pData);
+    if (m_pData) {
+        m_pData->Release();
     }
 }
 CFX_WideString::CFX_WideString(const CFX_WideString& stringSrc)
@@ -71,7 +53,7 @@
     }
     if (stringSrc.m_pData->m_nRefs >= 0) {
         m_pData = stringSrc.m_pData;
-        m_pData->m_nRefs ++;
+        m_pData->Retain();
     } else {
         m_pData = NULL;
         *this = stringSrc;
@@ -82,7 +64,7 @@
         nLen = lpsz ? FXSYS_wcslen(lpsz) : 0;
     }
     if (nLen) {
-        m_pData = FX_AllocStringW(nLen);
+        m_pData = StringData::Create(nLen);
         if (m_pData) {
             FXSYS_memcpy32(m_pData->m_String, lpsz, nLen * sizeof(FX_WCHAR));
         }
@@ -92,7 +74,7 @@
 }
 CFX_WideString::CFX_WideString(FX_WCHAR ch)
 {
-    m_pData = FX_AllocStringW(1);
+    m_pData = StringData::Create(1);
     if (m_pData) {
         m_pData->m_String[0] = ch;
     }
@@ -103,7 +85,7 @@
         m_pData = NULL;
         return;
     }
-    m_pData = FX_AllocStringW(str.GetLength());
+    m_pData = StringData::Create(str.GetLength());
     if (m_pData) {
         FXSYS_memcpy32(m_pData->m_String, str.GetPtr(), str.GetLength()*sizeof(FX_WCHAR));
     }
@@ -115,7 +97,7 @@
     if (nNewLen == 0) {
         return;
     }
-    m_pData = FX_AllocStringW(nNewLen);
+    m_pData = StringData::Create(nNewLen);
     if (m_pData) {
         FXSYS_memcpy32(m_pData->m_String, str1.GetPtr(), str1.GetLength()*sizeof(FX_WCHAR));
         FXSYS_memcpy32(m_pData->m_String + str1.GetLength(), str2.GetPtr(), str2.GetLength()*sizeof(FX_WCHAR));
@@ -170,7 +152,7 @@
         Empty();
         m_pData = stringSrc.m_pData;
         if (m_pData) {
-            m_pData->m_nRefs ++;
+            m_pData->Retain();
         }
     }
     return *this;
@@ -237,15 +219,10 @@
 }
 void CFX_WideString::Empty()
 {
-    if (m_pData == NULL) {
-        return;
+    if (m_pData) {
+        m_pData->Release();
+        m_pData = NULL;
     }
-    if (m_pData->m_nRefs > 1) {
-        m_pData->m_nRefs --;
-    } else {
-        FX_Free(m_pData);
-    }
-    m_pData = NULL;
 }
 void CFX_WideString::ConcatInPlace(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData)
 {
@@ -253,16 +230,16 @@
         return;
     }
     if (m_pData == NULL) {
-        m_pData = FX_AllocStringW(nSrcLen);
+        m_pData = StringData::Create(nSrcLen);
         if (m_pData) {
             FXSYS_memcpy32(m_pData->m_String, lpszSrcData, nSrcLen * sizeof(FX_WCHAR));
         }
         return;
     }
     if (m_pData->m_nRefs > 1 || m_pData->m_nDataLength + nSrcLen > m_pData->m_nAllocLength) {
-        CFX_StringDataW* pOldData = m_pData;
+        StringData* pOldData = m_pData;
         ConcatCopy(m_pData->m_nDataLength, m_pData->m_String, nSrcLen, lpszSrcData);
-        FX_ReleaseStringW(pOldData);
+        pOldData->Release();
     } else {
         FXSYS_memcpy32(m_pData->m_String + m_pData->m_nDataLength, lpszSrcData, nSrcLen * sizeof(FX_WCHAR));
         m_pData->m_nDataLength += nSrcLen;
@@ -276,7 +253,7 @@
     if (nNewLen == 0) {
         return;
     }
-    m_pData = FX_AllocStringW(nNewLen);
+    m_pData = StringData::Create(nNewLen);
     if (m_pData) {
         FXSYS_memcpy32(m_pData->m_String, lpszSrc1Data, nSrc1Len * sizeof(FX_WCHAR));
         FXSYS_memcpy32(m_pData->m_String + nSrc1Len, lpszSrc2Data, nSrc2Len * sizeof(FX_WCHAR));
@@ -287,10 +264,10 @@
     if (m_pData == NULL || m_pData->m_nRefs <= 1) {
         return;
     }
-    CFX_StringDataW* pData = m_pData;
-    m_pData->m_nRefs --;
+    StringData* pData = m_pData;
+    m_pData->Release();
     FX_STRSIZE nDataLength = pData->m_nDataLength;
-    m_pData = FX_AllocStringW(nDataLength);
+    m_pData = StringData::Create(nDataLength);
     if (m_pData != NULL) {
         FXSYS_memcpy32(m_pData->m_String, pData->m_String, (nDataLength + 1) * sizeof(FX_WCHAR));
     }
@@ -301,7 +278,7 @@
         return;
     }
     Empty();
-    m_pData = FX_AllocStringW(nLen);
+    m_pData = StringData::Create(nLen);
 }
 void CFX_WideString::AssignCopy(FX_STRSIZE nSrcLen, FX_LPCWSTR lpszSrcData)
 {
@@ -359,7 +336,7 @@
         return m_pData->m_String;
     }
     if (m_pData == NULL) {
-        m_pData = FX_AllocStringW(nMinBufLength);
+        m_pData = StringData::Create(nMinBufLength);
         if (!m_pData) {
             return NULL;
         }
@@ -367,21 +344,18 @@
         m_pData->m_String[0] = 0;
         return m_pData->m_String;
     }
-    CFX_StringDataW* pOldData = m_pData;
+    StringData* pOldData = m_pData;
     FX_STRSIZE nOldLen = pOldData->m_nDataLength;
     if (nMinBufLength < nOldLen) {
         nMinBufLength = nOldLen;
     }
-    m_pData = FX_AllocStringW(nMinBufLength);
+    m_pData = StringData::Create(nMinBufLength);
     if (!m_pData) {
         return NULL;
     }
     FXSYS_memcpy32(m_pData->m_String, pOldData->m_String, (nOldLen + 1)*sizeof(FX_WCHAR));
     m_pData->m_nDataLength = nOldLen;
-    pOldData->m_nRefs --;
-    if (pOldData->m_nRefs <= 0) {
-        FX_Free(pOldData);
-    }
+    pOldData->Release();
     return m_pData->m_String;
 }
 CFX_WideString CFX_WideString::FromLocal(const char* str, FX_STRSIZE len)
@@ -436,7 +410,7 @@
     pdfium::base::CheckedNumeric<FX_STRSIZE> iSize = static_cast<FX_STRSIZE>(sizeof(FX_WCHAR));
     iSize *= nCopyLen;
     ASSERT(dest.m_pData == NULL);
-    dest.m_pData = FX_AllocStringW(nCopyLen);
+    dest.m_pData = StringData::Create(nCopyLen);
     if (dest.m_pData) {
         FXSYS_memcpy32(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, iSize.ValueOrDie());
     }
@@ -678,14 +652,14 @@
         FX_STRSIZE nOldLength = m_pData->m_nDataLength;
         FX_STRSIZE nNewLength =  nOldLength + (nReplacementLen - nSourceLen) * nCount;
         if (m_pData->m_nAllocLength < nNewLength || m_pData->m_nRefs > 1) {
-            CFX_StringDataW* pOldData = m_pData;
+            StringData* pOldData = m_pData;
             FX_LPCWSTR pstr = m_pData->m_String;
-            m_pData = FX_AllocStringW(nNewLength);
+            m_pData = StringData::Create(nNewLength);
             if (!m_pData) {
                 return 0;
             }
             FXSYS_memcpy32(m_pData->m_String, pstr, pOldData->m_nDataLength * sizeof(FX_WCHAR));
-            FX_ReleaseStringW(pOldData);
+            pOldData->Release();
         }
         lpszStart = m_pData->m_String;
         lpszEnd = m_pData->m_String + FX_MAX(m_pData->m_nDataLength, nNewLength);
@@ -716,15 +690,15 @@
     }
     nNewLength++;
     if (m_pData == NULL || m_pData->m_nAllocLength < nNewLength) {
-        CFX_StringDataW* pOldData = m_pData;
+        StringData* pOldData = m_pData;
         FX_LPCWSTR pstr = m_pData->m_String;
-        m_pData = FX_AllocStringW(nNewLength);
+        m_pData = StringData::Create(nNewLength);
         if (!m_pData) {
             return 0;
         }
         if(pOldData != NULL) {
             FXSYS_memmove32(m_pData->m_String, pstr, (pOldData->m_nDataLength + 1)*sizeof(FX_WCHAR));
-            FX_ReleaseStringW(pOldData);
+            pOldData->Release();
         } else {
             m_pData->m_String[0] = 0;
         }