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: Create(size_t nLen)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 = GetStringPartitionAllocator().root()->Alloc( 40 totalSize, "StringDataTemplate"); 41 return new (pData) StringDataTemplate(nLen, usableLen); 42 } 43 Create(const CharType * pStr,size_t nLen)44 static StringDataTemplate* Create(const CharType* pStr, size_t nLen) { 45 StringDataTemplate* result = Create(nLen); 46 result->CopyContents(pStr, nLen); 47 return result; 48 } 49 Retain()50 void Retain() { ++m_nRefs; } Release()51 void Release() { 52 if (--m_nRefs <= 0) 53 GetStringPartitionAllocator().root()->Free(this); 54 } 55 CanOperateInPlace(size_t nTotalLen)56 bool CanOperateInPlace(size_t nTotalLen) const { 57 return m_nRefs <= 1 && nTotalLen <= m_nAllocLength; 58 } 59 CopyContents(const StringDataTemplate & other)60 void CopyContents(const StringDataTemplate& other) { 61 ASSERT(other.m_nDataLength <= m_nAllocLength); 62 memcpy(m_String, other.m_String, 63 (other.m_nDataLength + 1) * sizeof(CharType)); 64 } 65 CopyContents(const CharType * pStr,size_t nLen)66 void CopyContents(const CharType* pStr, size_t nLen) { 67 ASSERT(nLen >= 0); 68 ASSERT(nLen <= m_nAllocLength); 69 70 memcpy(m_String, pStr, nLen * sizeof(CharType)); 71 m_String[nLen] = 0; 72 } 73 CopyContentsAt(size_t offset,const CharType * pStr,size_t nLen)74 void CopyContentsAt(size_t offset, const CharType* pStr, size_t nLen) { 75 ASSERT(offset >= 0); 76 ASSERT(nLen >= 0); 77 ASSERT(offset + nLen <= m_nAllocLength); 78 79 memcpy(m_String + offset, pStr, nLen * sizeof(CharType)); 80 m_String[offset + nLen] = 0; 81 } 82 83 // To ensure ref counts do not overflow, consider the worst possible case: 84 // the entire address space contains nothing but pointers to this object. 85 // Since the count increments with each new pointer, the largest value is 86 // the number of pointers that can fit into the address space. The size of 87 // the address space itself is a good upper bound on it. 88 intptr_t m_nRefs; 89 90 // These lengths are in terms of number of characters, not bytes, and do not 91 // include the terminating NUL character, but the underlying buffer is sized 92 // to be capable of holding it. 93 size_t m_nDataLength; 94 size_t m_nAllocLength; 95 96 // Not really 1, variable size. 97 CharType m_String[1]; 98 99 private: StringDataTemplate(size_t dataLen,size_t allocLen)100 StringDataTemplate(size_t dataLen, size_t allocLen) 101 : m_nRefs(0), m_nDataLength(dataLen), m_nAllocLength(allocLen) { 102 ASSERT(dataLen >= 0); 103 ASSERT(dataLen <= allocLen); 104 m_String[dataLen] = 0; 105 } 106 107 ~StringDataTemplate() = delete; 108 }; 109 110 extern template class StringDataTemplate<char>; 111 extern template class StringDataTemplate<wchar_t>; 112 113 } // namespace fxcrt 114 115 using fxcrt::StringDataTemplate; 116 117 #endif // CORE_FXCRT_STRING_DATA_TEMPLATE_H_ 118