Save 8 bytes in each CFX_ByteString/WideString (on "LP64" platforms).
[pdfium.git] / core / src / fxcrt / fx_basic_wstring.cpp
index e255aa0..742f249 100644 (file)
@@ -4,28 +4,40 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
+#include <stddef.h>  // For offsetof().
+
 #include "../../include/fxcrt/fx_basic.h"
 #include "../../../third_party/base/numerics/safe_math.h"
 
 static CFX_StringDataW* FX_AllocStringW(int nLen)
 {
+    // TODO(palmer): |nLen| should really be declared as |size_t|, or
+    // at least unsigned.
     if (nLen == 0 || nLen < 0) {
         return NULL;
     }
 
-    pdfium::base::CheckedNumeric<int> iSize = static_cast<int>(sizeof(FX_WCHAR));
-    iSize *= nLen + 1;
-    iSize += sizeof(long) * 3;
+    // Fixed portion of header plus a NUL wide char not in m_nAllocLength.
+    int overhead = offsetof(CFX_StringDataW, m_String) + sizeof(FX_WCHAR);
+    pdfium::base::CheckedNumeric<int> iSize = nLen;
+    iSize *= sizeof(FX_WCHAR);
+    iSize += 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.
+    iSize += 7;
+    int totalSize = iSize.ValueOrDie() & ~7;
+    int usableLen = (totalSize - overhead) / sizeof(FX_WCHAR);
+    FXSYS_assert(usableLen >= nLen);
+
     CFX_StringDataW* pData = (CFX_StringDataW*)FX_Alloc(FX_BYTE, iSize.ValueOrDie());
     if (!pData) {
         return NULL;
     }
 
-    // TODO(palmer): |nLen| should really be declared as |size_t|, but for
-    // now I just want to fix the overflow without changing any interfaces.
-    // Declaring |nLen| as |size_t| will also simplify the above code
-    // somewhat.
-    pData->m_nAllocLength = nLen;
+    pData->m_nAllocLength = usableLen;
     pData->m_nDataLength = nLen;
     pData->m_nRefs = 1;
     pData->m_String[nLen] = 0;
@@ -535,15 +547,6 @@ int CFX_WideString::Compare(const CFX_WideString& str) const
     }
     return 0;
 }
-FX_LPWSTR CFX_WideString::LockBuffer()
-{
-    if (m_pData == NULL) {
-        return NULL;
-    }
-    FX_LPWSTR lpsz = GetBuffer(0);
-    m_pData->m_nRefs = -1;
-    return lpsz;
-}
 void CFX_WideString::SetAt(FX_STRSIZE nIndex, FX_WCHAR ch)
 {
     if (m_pData == NULL) {