Save 8 bytes in each CFX_ByteString/WideString (on "LP64" platforms).
[pdfium.git] / core / src / fxcrt / fx_basic_wstring.cpp
index 192579f..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/numerics/safe_math.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;
     }
 
-    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;
@@ -323,25 +335,21 @@ CFX_ByteString CFX_WideString::UTF8Encode() const
 {
     return FX_UTF8Encode(*this);
 }
-CFX_ByteString CFX_WideString::UTF16LE_Encode(FX_BOOL bTerminate) const
+CFX_ByteString CFX_WideString::UTF16LE_Encode() const
 {
     if (m_pData == NULL) {
-        return bTerminate ? CFX_ByteString(FX_BSTRC("\0\0")) : CFX_ByteString();
+        return CFX_ByteString(FX_BSTRC("\0\0"));
     }
     int len = m_pData->m_nDataLength;
     CFX_ByteString result;
-    FX_LPSTR buffer = result.GetBuffer(len * 2 + (bTerminate ? 2 : 0));
+    FX_LPSTR buffer = result.GetBuffer(len * 2 + 2);
     for (int i = 0; i < len; i ++) {
         buffer[i * 2] = m_pData->m_String[i] & 0xff;
         buffer[i * 2 + 1] = m_pData->m_String[i] >> 8;
     }
-    if (bTerminate) {
-        buffer[len * 2] = 0;
-        buffer[len * 2 + 1] = 0;
-        result.ReleaseBuffer(len * 2 + 2);
-    } else {
-        result.ReleaseBuffer(len * 2);
-    }
+    buffer[len * 2] = 0;
+    buffer[len * 2 + 1] = 0;
+    result.ReleaseBuffer(len * 2 + 2);
     return result;
 }
 void CFX_WideString::ConvertFrom(const CFX_ByteString& str, CFX_CharMap* pCharMap)
@@ -398,15 +406,10 @@ CFX_WideString CFX_WideString::FromLocal(const char* str, FX_STRSIZE len)
 }
 CFX_WideString CFX_WideString::FromUTF8(const char* str, FX_STRSIZE len)
 {
-    if (!str) {
+    if (!str || 0 == len) {
         return CFX_WideString();
     }
-    if (len < 0) {
-        len = 0;
-        while (str[len]) {
-            len ++;
-        }
-    }
+
     CFX_UTF8Decoder decoder;
     for (FX_STRSIZE i = 0; i < len; i ++) {
         decoder.Input(str[i]);
@@ -415,15 +418,10 @@ CFX_WideString CFX_WideString::FromUTF8(const char* str, FX_STRSIZE len)
 }
 CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, FX_STRSIZE wlen)
 {
-    if (!wstr || !wlen) {
+    if (!wstr || 0 == wlen) {
         return CFX_WideString();
     }
-    if (wlen < 0) {
-        wlen = 0;
-        while (wstr[wlen]) {
-            wlen ++;
-        }
-    }
+
     CFX_WideString result;
     FX_WCHAR* buf = result.GetBuffer(wlen);
     for (int i = 0; i < wlen; i ++) {
@@ -432,6 +430,16 @@ CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, FX_STRSIZ
     result.ReleaseBuffer(wlen);
     return result;
 }
+FX_STRSIZE CFX_WideString::WStringLength(const unsigned short* str)
+{
+    FX_STRSIZE len = 0;
+    if (str)
+        while (str[len]) len++;
+    return len;
+}
+
+
+
 void CFX_WideString::AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex) const
 {
     // |FX_STRSIZE| is currently typedef'd as in |int|. TODO(palmer): It
@@ -439,7 +447,7 @@ void CFX_WideString::AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STR
     if (nCopyLen == 0 || nCopyLen < 0) {
         return;
     }
-    base::CheckedNumeric<FX_STRSIZE> iSize = static_cast<FX_STRSIZE>(sizeof(FX_WCHAR));
+    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);
@@ -539,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) {
@@ -586,7 +585,7 @@ FX_STRSIZE CFX_WideString::Find(FX_LPCWSTR lpszSub, FX_STRSIZE nStart) const
     if (nLength < 1 || nStart > nLength) {
         return -1;
     }
-    FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcsstr(m_pData->m_String + nStart, lpszSub);
+    FX_LPCWSTR lpsz = FXSYS_wcsstr(m_pData->m_String + nStart, lpszSub);
     return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String);
 }
 FX_STRSIZE CFX_WideString::Find(FX_WCHAR ch, FX_STRSIZE nStart) const
@@ -598,7 +597,7 @@ FX_STRSIZE CFX_WideString::Find(FX_WCHAR ch, FX_STRSIZE nStart) const
     if (nStart >= nLength) {
         return -1;
     }
-    FX_LPCWSTR lpsz = (FX_LPCWSTR)FXSYS_wcschr(m_pData->m_String + nStart, ch);
+    FX_LPCWSTR lpsz = FXSYS_wcschr(m_pData->m_String + nStart, ch);
     return (lpsz == NULL) ? -1 : (int)(lpsz - m_pData->m_String);
 }
 void CFX_WideString::TrimRight(FX_LPCWSTR lpszTargetList)
@@ -829,7 +828,7 @@ void CFX_WideString::FormatV(FX_LPCWSTR lpszFormat, va_list argList)
                 ;
         }
         if (nWidth < 0 || nWidth > 128 * 1024) {
-            lpszFormat = (FX_LPCWSTR)L"Bad width";
+            lpszFormat = L"Bad width";
             nMaxLen = 10;
             break;
         }
@@ -846,7 +845,7 @@ void CFX_WideString::FormatV(FX_LPCWSTR lpszFormat, va_list argList)
             }
         }
         if (nPrecision < 0 || nPrecision > 128 * 1024) {
-            lpszFormat = (FX_LPCWSTR)L"Bad precision";
+            lpszFormat = L"Bad precision";
             nMaxLen = 14;
             break;
         }
@@ -1066,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;
 }