Save 8 bytes in each CFX_ByteString/WideString (on "LP64" platforms).
[pdfium.git] / core / src / fxcrt / fx_basic_wstring.cpp
index ce6a1cd..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) {
@@ -976,9 +979,9 @@ void CFX_WideString::FormatV(FX_LPCWSTR lpszFormat, va_list argList)
                         nItemLen = nPrecision + nWidth + 128;
                     } else {
                         double f;
-                        char pszTemp[256] = {0};
+                        char pszTemp[256];
                         f = va_arg(argList, double);
-                        FXSYS_snprintf(pszTemp, sizeof(pszTemp) - 1, "%*.*f", nWidth, nPrecision + 6, f );
+                        FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth, nPrecision + 6, f );
                         nItemLen = (FX_STRSIZE)FXSYS_strlen(pszTemp);
                     }
                     break;
@@ -1062,13 +1065,13 @@ static CFX_ByteString _DefMap_GetByteString(CFX_CharMap* pCharMap, const CFX_Wid
 {
     int src_len = widestr.GetLength();
     int codepage = pCharMap->m_GetCodePage ? pCharMap->m_GetCodePage() : 0;
-    int dest_len = FXSYS_WideCharToMultiByte(codepage, 0, widestr, src_len, NULL, 0, NULL, NULL);
+    int dest_len = FXSYS_WideCharToMultiByte(codepage, 0, widestr.c_str(), src_len, NULL, 0, NULL, NULL);
     if (dest_len == 0) {
         return CFX_ByteString();
     }
     CFX_ByteString bytestr;
     FX_LPSTR dest_buf = bytestr.GetBuffer(dest_len);
-    FXSYS_WideCharToMultiByte(codepage, 0, widestr, src_len, dest_buf, dest_len, NULL, NULL);
+    FXSYS_WideCharToMultiByte(codepage, 0, widestr.c_str(), src_len, dest_buf, dest_len, NULL, NULL);
     bytestr.ReleaseBuffer(dest_len);
     return bytestr;
 }