1 // Copyright 2014 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 #include "core/fxcrt/fx_basic.h"
8 #include "third_party/base/numerics/safe_math.h"
9
CFX_BasicArray(int unit_size)10 CFX_BasicArray::CFX_BasicArray(int unit_size)
11 : m_pData(nullptr), m_nSize(0), m_nMaxSize(0) {
12 if (unit_size < 0 || unit_size > (1 << 28)) {
13 m_nUnitSize = 4;
14 } else {
15 m_nUnitSize = unit_size;
16 }
17 }
~CFX_BasicArray()18 CFX_BasicArray::~CFX_BasicArray() {
19 FX_Free(m_pData);
20 }
SetSize(int nNewSize)21 bool CFX_BasicArray::SetSize(int nNewSize) {
22 if (nNewSize <= 0) {
23 FX_Free(m_pData);
24 m_pData = nullptr;
25 m_nSize = m_nMaxSize = 0;
26 return 0 == nNewSize;
27 }
28
29 if (!m_pData) {
30 pdfium::base::CheckedNumeric<int> totalSize = nNewSize;
31 totalSize *= m_nUnitSize;
32 if (!totalSize.IsValid()) {
33 m_nSize = m_nMaxSize = 0;
34 return false;
35 }
36 m_pData =
37 FX_Alloc(uint8_t, pdfium::base::ValueOrDieForType<size_t>(totalSize));
38 m_nSize = m_nMaxSize = nNewSize;
39 } else if (nNewSize <= m_nMaxSize) {
40 if (nNewSize > m_nSize) {
41 FXSYS_memset(m_pData + m_nSize * m_nUnitSize, 0,
42 (nNewSize - m_nSize) * m_nUnitSize);
43 }
44 m_nSize = nNewSize;
45 } else {
46 int nNewMax = nNewSize < m_nMaxSize ? m_nMaxSize : nNewSize;
47 pdfium::base::CheckedNumeric<int> totalSize = nNewMax;
48 totalSize *= m_nUnitSize;
49 if (!totalSize.IsValid() || nNewMax < m_nSize) {
50 return false;
51 }
52 uint8_t* pNewData = FX_Realloc(
53 uint8_t, m_pData, pdfium::base::ValueOrDieForType<size_t>(totalSize));
54 if (!pNewData) {
55 return false;
56 }
57 FXSYS_memset(pNewData + m_nSize * m_nUnitSize, 0,
58 (nNewMax - m_nSize) * m_nUnitSize);
59 m_pData = pNewData;
60 m_nSize = nNewSize;
61 m_nMaxSize = nNewMax;
62 }
63 return true;
64 }
Append(const CFX_BasicArray & src)65 bool CFX_BasicArray::Append(const CFX_BasicArray& src) {
66 int nOldSize = m_nSize;
67 pdfium::base::CheckedNumeric<int> newSize = m_nSize;
68 newSize += src.m_nSize;
69 if (m_nUnitSize != src.m_nUnitSize || !newSize.IsValid() ||
70 !SetSize(newSize.ValueOrDie())) {
71 return false;
72 }
73
74 FXSYS_memcpy(m_pData + nOldSize * m_nUnitSize, src.m_pData,
75 src.m_nSize * m_nUnitSize);
76 return true;
77 }
Copy(const CFX_BasicArray & src)78 bool CFX_BasicArray::Copy(const CFX_BasicArray& src) {
79 if (!SetSize(src.m_nSize)) {
80 return false;
81 }
82 FXSYS_memcpy(m_pData, src.m_pData, src.m_nSize * m_nUnitSize);
83 return true;
84 }
InsertSpaceAt(int nIndex,int nCount)85 uint8_t* CFX_BasicArray::InsertSpaceAt(int nIndex, int nCount) {
86 if (nIndex < 0 || nCount <= 0) {
87 return nullptr;
88 }
89 if (nIndex >= m_nSize) {
90 if (!SetSize(nIndex + nCount)) {
91 return nullptr;
92 }
93 } else {
94 int nOldSize = m_nSize;
95 if (!SetSize(m_nSize + nCount)) {
96 return nullptr;
97 }
98 FXSYS_memmove(m_pData + (nIndex + nCount) * m_nUnitSize,
99 m_pData + nIndex * m_nUnitSize,
100 (nOldSize - nIndex) * m_nUnitSize);
101 FXSYS_memset(m_pData + nIndex * m_nUnitSize, 0, nCount * m_nUnitSize);
102 }
103 return m_pData + nIndex * m_nUnitSize;
104 }
RemoveAt(int nIndex,int nCount)105 bool CFX_BasicArray::RemoveAt(int nIndex, int nCount) {
106 if (nIndex < 0 || nCount <= 0 || m_nSize < nIndex + nCount) {
107 return false;
108 }
109 int nMoveCount = m_nSize - (nIndex + nCount);
110 if (nMoveCount) {
111 FXSYS_memmove(m_pData + nIndex * m_nUnitSize,
112 m_pData + (nIndex + nCount) * m_nUnitSize,
113 nMoveCount * m_nUnitSize);
114 }
115 m_nSize -= nCount;
116 return true;
117 }
InsertAt(int nStartIndex,const CFX_BasicArray * pNewArray)118 bool CFX_BasicArray::InsertAt(int nStartIndex,
119 const CFX_BasicArray* pNewArray) {
120 if (!pNewArray) {
121 return false;
122 }
123 if (pNewArray->m_nSize == 0) {
124 return true;
125 }
126 if (!InsertSpaceAt(nStartIndex, pNewArray->m_nSize)) {
127 return false;
128 }
129 FXSYS_memcpy(m_pData + nStartIndex * m_nUnitSize, pNewArray->m_pData,
130 pNewArray->m_nSize * m_nUnitSize);
131 return true;
132 }
GetDataPtr(int index) const133 const void* CFX_BasicArray::GetDataPtr(int index) const {
134 if (index < 0 || index >= m_nSize || !m_pData) {
135 return nullptr;
136 }
137 return m_pData + index * m_nUnitSize;
138 }
139