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_STRING_DATA_TEMPLATE_H_
      8 #define CORE_FXCRT_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 namespace fxcrt {
     15 
     16 template <typename CharType>
     17 class StringDataTemplate {
     18  public:
     19   static StringDataTemplate* Create(size_t nLen) {
     20     ASSERT(nLen > 0);
     21 
     22     // Calculate space needed for the fixed portion of the struct plus the
     23     // NUL char that is not included in |m_nAllocLength|.
     24     int overhead = offsetof(StringDataTemplate, m_String) + sizeof(CharType);
     25     pdfium::base::CheckedNumeric<size_t> nSize = nLen;
     26     nSize *= sizeof(CharType);
     27     nSize += overhead;
     28 
     29     // Now round to an 8-byte boundary. We'd expect that this is the minimum
     30     // granularity of any of the underlying allocators, so there may be cases
     31     // where we can save a re-alloc when adding a few characters to a string
     32     // by using this otherwise wasted space.
     33     nSize += 7;
     34     nSize &= ~7;
     35     size_t totalSize = nSize.ValueOrDie();
     36     size_t usableLen = (totalSize - overhead) / sizeof(CharType);
     37     ASSERT(usableLen >= nLen);
     38 
     39     void* pData = pdfium::base::PartitionAllocGeneric(
     40         gStringPartitionAllocator.root(), totalSize, "StringDataTemplate");
     41     return new (pData) StringDataTemplate(nLen, usableLen);
     42   }
     43 
     44   static StringDataTemplate* Create(const StringDataTemplate& other) {
     45     StringDataTemplate* result = Create(other.m_nDataLength);
     46     result->CopyContents(other);
     47     return result;
     48   }
     49 
     50   static StringDataTemplate* Create(const CharType* pStr, size_t nLen) {
     51     StringDataTemplate* result = Create(nLen);
     52     result->CopyContents(pStr, nLen);
     53     return result;
     54   }
     55 
     56   void Retain() { ++m_nRefs; }
     57   void Release() {
     58     if (--m_nRefs <= 0)
     59       pdfium::base::PartitionFreeGeneric(gStringPartitionAllocator.root(),
     60                                          this);
     61   }
     62 
     63   bool CanOperateInPlace(size_t nTotalLen) const {
     64     return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
     65   }
     66 
     67   void CopyContents(const StringDataTemplate& other) {
     68     ASSERT(other.m_nDataLength <= m_nAllocLength);
     69     memcpy(m_String, other.m_String,
     70            (other.m_nDataLength + 1) * sizeof(CharType));
     71   }
     72 
     73   void CopyContents(const CharType* pStr, size_t nLen) {
     74     ASSERT(nLen >= 0 && nLen <= m_nAllocLength);
     75     memcpy(m_String, pStr, nLen * sizeof(CharType));
     76     m_String[nLen] = 0;
     77   }
     78 
     79   void CopyContentsAt(size_t offset, const CharType* pStr, size_t nLen) {
     80     ASSERT(offset >= 0 && nLen >= 0 && offset + nLen <= m_nAllocLength);
     81     memcpy(m_String + offset, pStr, nLen * sizeof(CharType));
     82     m_String[offset + nLen] = 0;
     83   }
     84 
     85   // To ensure ref counts do not overflow, consider the worst possible case:
     86   // the entire address space contains nothing but pointers to this object.
     87   // Since the count increments with each new pointer, the largest value is
     88   // the number of pointers that can fit into the address space. The size of
     89   // the address space itself is a good upper bound on it.
     90   intptr_t m_nRefs;
     91 
     92   // These lengths are in terms of number of characters, not bytes, and do not
     93   // include the terminating NUL character, but the underlying buffer is sized
     94   // to be capable of holding it.
     95   size_t m_nDataLength;
     96   size_t m_nAllocLength;
     97 
     98   // Not really 1, variable size.
     99   CharType m_String[1];
    100 
    101  private:
    102   StringDataTemplate(size_t dataLen, size_t allocLen)
    103       : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) {
    104     ASSERT(dataLen >= 0);
    105     ASSERT(dataLen <= allocLen);
    106     m_String[dataLen] = 0;
    107   }
    108 
    109   ~StringDataTemplate() = delete;
    110 };
    111 
    112 extern template class StringDataTemplate<char>;
    113 extern template class StringDataTemplate<wchar_t>;
    114 
    115 }  // namespace fxcrt
    116 
    117 using fxcrt::StringDataTemplate;
    118 
    119 #endif  // CORE_FXCRT_STRING_DATA_TEMPLATE_H_
    120