• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = pdfium::base::PartitionAllocGeneric(
40         gStringPartitionAllocator.root(), totalSize, "StringDataTemplate");
41     return new (pData) StringDataTemplate(nLen, usableLen);
42   }
43 
Create(const StringDataTemplate & other)44   static StringDataTemplate* Create(const StringDataTemplate& other) {
45     StringDataTemplate* result = Create(other.m_nDataLength);
46     result->CopyContents(other);
47     return result;
48   }
49 
Create(const CharType * pStr,size_t nLen)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 
Retain()56   void Retain() { ++m_nRefs; }
Release()57   void Release() {
58     if (--m_nRefs <= 0)
59       pdfium::base::PartitionFreeGeneric(gStringPartitionAllocator.root(),
60                                          this);
61   }
62 
CanOperateInPlace(size_t nTotalLen)63   bool CanOperateInPlace(size_t nTotalLen) const {
64     return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
65   }
66 
CopyContents(const StringDataTemplate & other)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 
CopyContents(const CharType * pStr,size_t nLen)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 
CopyContentsAt(size_t offset,const CharType * pStr,size_t nLen)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:
StringDataTemplate(size_t dataLen,size_t allocLen)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