Save 8 bytes in each CFX_ByteString/WideString (on "LP64" platforms).
[pdfium.git] / core / src / fxcrt / fx_basic_wstring.cpp
index 7af3303..742f249 100644 (file)
@@ -1,20 +1,43 @@
 // Copyright 2014 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
 
+#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)
 {
-    if (nLen == 0) {
+    // TODO(palmer): |nLen| should really be declared as |size_t|, or
+    // at least unsigned.
+    if (nLen == 0 || nLen < 0) {
         return NULL;
     }
-    CFX_StringDataW* pData = (CFX_StringDataW*)FX_Alloc(FX_BYTE, sizeof(long) * 3 + (nLen + 1) * sizeof(FX_WCHAR));
+
+    // 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;
     }
-    pData->m_nAllocLength = nLen;
+
+    pData->m_nAllocLength = usableLen;
     pData->m_nDataLength = nLen;
     pData->m_nRefs = 1;
     pData->m_String[nLen] = 0;
@@ -312,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)
@@ -387,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]);
@@ -404,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 ++) {
@@ -421,17 +430,29 @@ CFX_WideString CFX_WideString::FromUTF16LE(const unsigned short* wstr, FX_STRSIZ
     result.ReleaseBuffer(wlen);
     return result;
 }
-void CFX_WideString::AllocCopy(CFX_WideString& dest, FX_STRSIZE nCopyLen, FX_STRSIZE nCopyIndex,
-                               FX_STRSIZE nExtraLen) const
+FX_STRSIZE CFX_WideString::WStringLength(const unsigned short* str)
 {
-    FX_STRSIZE nNewLen = nCopyLen + nExtraLen;
-    if (nNewLen == 0) {
+    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
+    // should be a |size_t|, or at least unsigned.
+    if (nCopyLen == 0 || nCopyLen < 0) {
         return;
     }
+    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(nNewLen);
+    dest.m_pData = FX_AllocStringW(nCopyLen);
     if (dest.m_pData) {
-        FXSYS_memcpy32(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, nCopyLen * sizeof(FX_WCHAR));
+        FXSYS_memcpy32(dest.m_pData->m_String, m_pData->m_String + nCopyIndex, iSize.ValueOrDie());
     }
 }
 CFX_WideString CFX_WideString::Left(FX_STRSIZE nCount) const
@@ -446,7 +467,7 @@ CFX_WideString CFX_WideString::Left(FX_STRSIZE nCount) const
         return *this;
     }
     CFX_WideString dest;
-    AllocCopy(dest, nCount, 0, 0);
+    AllocCopy(dest, nCount, 0);
     return dest;
 }
 CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst) const
@@ -474,7 +495,7 @@ CFX_WideString CFX_WideString::Mid(FX_STRSIZE nFirst, FX_STRSIZE nCount) const
         return *this;
     }
     CFX_WideString dest;
-    AllocCopy(dest, nCount, nFirst, 0);
+    AllocCopy(dest, nCount, nFirst);
     return dest;
 }
 CFX_WideString CFX_WideString::Right(FX_STRSIZE nCount) const
@@ -489,7 +510,7 @@ CFX_WideString CFX_WideString::Right(FX_STRSIZE nCount) const
         return *this;
     }
     CFX_WideString dest;
-    AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount, 0);
+    AllocCopy(dest, nCount, m_pData->m_nDataLength - nCount);
     return dest;
 }
 int CFX_WideString::CompareNoCase(FX_LPCWSTR lpsz) const
@@ -526,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) {
@@ -573,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
@@ -585,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)
@@ -816,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;
         }
@@ -833,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;
         }
@@ -1049,69 +1061,17 @@ FX_FLOAT CFX_WideString::GetFloat() const
     }
     return FX_wtof(m_pData->m_String, m_pData->m_nDataLength);
 }
-void CFX_WideStringL::Empty(IFX_Allocator* pAllocator)
-{
-    if (m_Ptr) {
-        FX_Allocator_Free(pAllocator, (FX_LPVOID)m_Ptr);
-    }
-    m_Ptr = NULL, m_Length = 0;
-}
-void CFX_WideStringL::Set(FX_WSTR src, IFX_Allocator* pAllocator)
-{
-    Empty(pAllocator);
-    if (src.GetPtr() != NULL && src.GetLength() > 0) {
-        FX_LPWSTR str = FX_Allocator_Alloc(pAllocator, FX_WCHAR, src.GetLength() + 1);
-        if (!str) {
-            return;
-        }
-        FXSYS_memcpy32(str, src.GetPtr(), src.GetLength()*sizeof(FX_WCHAR));
-        str[src.GetLength()] = '\0';
-        *(FX_LPWSTR*)(&m_Ptr) = str;
-        m_Length = src.GetLength();
-    }
-}
-int CFX_WideStringL::GetInteger() const
-{
-    if (!m_Ptr) {
-        return 0;
-    }
-    return FXSYS_wtoi(m_Ptr);
-}
-FX_FLOAT CFX_WideStringL::GetFloat() const
-{
-    if (!m_Ptr) {
-        return 0.0f;
-    }
-    return FX_wtof(m_Ptr, m_Length);
-}
-void CFX_WideStringL::TrimRight(FX_LPCWSTR lpszTargets)
-{
-    if (!lpszTargets || *lpszTargets == 0 || !m_Ptr || m_Length < 1) {
-        return;
-    }
-    FX_STRSIZE pos = m_Length;
-    while (pos) {
-        if (FXSYS_wcschr(lpszTargets, m_Ptr[pos - 1]) == NULL) {
-            break;
-        }
-        pos --;
-    }
-    if (pos < m_Length) {
-        (*(FX_LPWSTR*)(&m_Ptr))[pos] = 0;
-        m_Length = pos;
-    }
-}
 static CFX_ByteString _DefMap_GetByteString(CFX_CharMap* pCharMap, const CFX_WideString& widestr)
 {
     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;
 }