• 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_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:
Create(FX_STRSIZE nLen)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 
Create(const CFX_StringDataTemplate & other)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 
Create(const CharType * pStr,FX_STRSIZE nLen)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 
Retain()54   void Retain() { ++m_nRefs; }
Release()55   void Release() {
56     if (--m_nRefs <= 0)
57       FX_Free(this);
58   }
59 
CanOperateInPlace(FX_STRSIZE nTotalLen)60   bool CanOperateInPlace(FX_STRSIZE nTotalLen) const {
61     return m_nRefs <= 1 && nTotalLen <= m_nAllocLength;
62   }
63 
CopyContents(const CFX_StringDataTemplate & other)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 
CopyContents(const CharType * pStr,FX_STRSIZE nLen)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 
CopyContentsAt(FX_STRSIZE offset,const CharType * pStr,FX_STRSIZE nLen)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:
CFX_StringDataTemplate(FX_STRSIZE dataLen,FX_STRSIZE allocLen)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