Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2016 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #ifndef CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_
      8 #define CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_
      9 
     10 #include "core/fxcrt/fx_memory.h"
     11 #include "core/fxcrt/fx_system.h"
     12 #include "third_party/base/numerics/safe_math.h"
     13 
     14 template <typename CharType>
     15 class CFX_StringDataTemplate {
     16  public:
     17   static CFX_StringDataTemplate* Create(FX_STRSIZE nLen) {
     18     ASSERT(nLen > 0);
     19 
     20     // Calculate space needed for the fixed portion of the struct plus the
     21     // NUL char that is not included in |m_nAllocLength|.
     22     int overhead =
     23         offsetof(CFX_StringDataTemplate, m_String) + sizeof(CharType);
     24     pdfium::base::CheckedNumeric<int> nSize = nLen;
     25     nSize *= sizeof(CharType);
     26     nSize += overhead;
     27 
     28     // Now round to an 8-byte boundary. We'd expect that this is the minimum
     29     // granularity of any of the underlying allocators, so there may be cases
     30     // where we can save a re-alloc when adding a few characters to a string
     31     // by using this otherwise wasted space.
     32     nSize += 7;
     33     nSize &= ~7;
     34     int totalSize = nSize.ValueOrDie();
     35     int usableLen = (totalSize - overhead) / sizeof(CharType);
     36     ASSERT(usableLen >= nLen);
     37 
     38     void* pData = FX_Alloc(uint8_t, totalSize);
     39     return new (pData) CFX_StringDataTemplate(nLen, usableLen);
     40   }
     41 
     42   static CFX_StringDataTemplate* Create(const CFX_StringDataTemplate& other) {
     43     CFX_StringDataTemplate* result = Create(other.m_nDataLength);
     44     result->CopyContents(other);
     45     return result;
     46   }
     47 
     48   static CFX_StringDataTemplate* Create(const CharType* pStr, FX_STRSIZE nLen) {
     49     CFX_StringDataTemplate* result = Create(nLen);
     50     result->CopyContents(pStr, nLen);
     51     return result;
     52   }
     53 
     54   void Retain() { ++m_nRefs; }
     55   void Release() {
     56     if (--m_nRefs <= 0)
     57       FX_Free(this);
     58   }
     59 
     60   bool CanOperateInPlace(FX_STRSIZE nTotalLen) const {
     61     return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
     62   }
     63 
     64   void CopyContents(const CFX_StringDataTemplate& other) {
     65     ASSERT(other.m_nDataLength <= m_nAllocLength);
     66     FXSYS_memcpy(m_String, other.m_String,
     67                  (other.m_nDataLength + 1) * sizeof(CharType));
     68   }
     69 
     70   void CopyContents(const CharType* pStr, FX_STRSIZE nLen) {
     71     ASSERT(nLen >= 0 && nLen <= m_nAllocLength);
     72     FXSYS_memcpy(m_String, pStr, nLen * sizeof(CharType));
     73     m_String[nLen] = 0;
     74   }
     75 
     76   void CopyContentsAt(FX_STRSIZE offset,
     77                       const CharType* pStr,
     78                       FX_STRSIZE nLen) {
     79     ASSERT(offset >= 0 && nLen >= 0 && offset + nLen <= m_nAllocLength);
     80     FXSYS_memcpy(m_String + offset, pStr, nLen * sizeof(CharType));
     81     m_String[offset + nLen] = 0;
     82   }
     83 
     84   // To ensure ref counts do not overflow, consider the worst possible case:
     85   // the entire address space contains nothing but pointers to this object.
     86   // Since the count increments with each new pointer, the largest value is
     87   // the number of pointers that can fit into the address space. The size of
     88   // the address space itself is a good upper bound on it.
     89   intptr_t m_nRefs;
     90 
     91   // |FX_STRSIZE| is currently typedef'd as |int|.
     92   // TODO(palmer): It should be a |size_t|, or at least unsigned.
     93   // These lengths are in terms of number of characters, not bytes, and do not
     94   // include the terminating NUL character, but the underlying buffer is sized
     95   // to be capable of holding it.
     96   FX_STRSIZE m_nDataLength;
     97   FX_STRSIZE m_nAllocLength;
     98 
     99   // Not really 1, variable size.
    100   CharType m_String[1];
    101 
    102  private:
    103   CFX_StringDataTemplate(FX_STRSIZE dataLen, FX_STRSIZE allocLen)
    104       : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
    105     ASSERT(dataLen >= 0);
    106     ASSERT(dataLen <= allocLen);
    107     m_String[dataLen] = 0;
    108   }
    109 
    110   ~CFX_StringDataTemplate() = delete;
    111 };
    112 
    113 extern template class CFX_StringDataTemplate<FX_CHAR>;
    114 extern template class CFX_StringDataTemplate<FX_WCHAR>;
    115 
    116 #endif  // CORE_FXCRT_CFX_STRING_DATA_TEMPLATE_H_
    117