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 <algorithm>
8
9 #include "xfa/src/fgas/include/fx_utl.h"
10 #include "xfa/src/fgas/src/fgas_base.h"
11 #include "fx_utils.h"
12
CFX_ThreadLock()13 CFX_ThreadLock::CFX_ThreadLock() {
14 }
~CFX_ThreadLock()15 CFX_ThreadLock::~CFX_ThreadLock() {}
Lock()16 void CFX_ThreadLock::Lock() {}
Unlock()17 void CFX_ThreadLock::Unlock() {}
18 class FX_BASEARRAYDATA : public CFX_Target {
19 public:
FX_BASEARRAYDATA(int32_t growsize,int32_t blocksize)20 FX_BASEARRAYDATA(int32_t growsize, int32_t blocksize)
21 : iGrowSize(growsize),
22 iBlockSize(blocksize),
23 iTotalCount(0),
24 iBlockCount(0),
25 pBuffer(nullptr) {}
26
~FX_BASEARRAYDATA()27 ~FX_BASEARRAYDATA() { FX_Free(pBuffer); }
28
29 int32_t iGrowSize;
30 int32_t iBlockSize;
31 int32_t iTotalCount;
32 int32_t iBlockCount;
33 uint8_t* pBuffer;
34 };
CFX_BaseArray(int32_t iGrowSize,int32_t iBlockSize)35 CFX_BaseArray::CFX_BaseArray(int32_t iGrowSize, int32_t iBlockSize) {
36 FXSYS_assert(iGrowSize > 0 && iBlockSize > 0);
37 m_pData = new FX_BASEARRAYDATA(iGrowSize, iBlockSize);
38 }
~CFX_BaseArray()39 CFX_BaseArray::~CFX_BaseArray() {
40 RemoveAll();
41 delete m_pData;
42 }
GetSize() const43 int32_t CFX_BaseArray::GetSize() const {
44 return m_pData->iBlockCount;
45 }
GetBlockSize() const46 int32_t CFX_BaseArray::GetBlockSize() const {
47 return m_pData->iBlockSize;
48 }
AddSpaceTo(int32_t index)49 uint8_t* CFX_BaseArray::AddSpaceTo(int32_t index) {
50 FXSYS_assert(index > -1);
51 uint8_t*& pBuffer = m_pData->pBuffer;
52 int32_t& iTotalCount = m_pData->iTotalCount;
53 int32_t iBlockSize = m_pData->iBlockSize;
54 if (index >= iTotalCount) {
55 int32_t iGrowSize = m_pData->iGrowSize;
56 iTotalCount = (index / iGrowSize + 1) * iGrowSize;
57 int32_t iNewSize = iTotalCount * iBlockSize;
58 if (!pBuffer) {
59 pBuffer = FX_Alloc(uint8_t, iNewSize);
60 } else {
61 pBuffer = FX_Realloc(uint8_t, pBuffer, iNewSize);
62 }
63 }
64 int32_t& iBlockCount = m_pData->iBlockCount;
65 if (index >= iBlockCount) {
66 iBlockCount = index + 1;
67 }
68 return pBuffer + index * iBlockSize;
69 }
GetAt(int32_t index) const70 uint8_t* CFX_BaseArray::GetAt(int32_t index) const {
71 FXSYS_assert(index > -1 && index < m_pData->iBlockCount);
72 return m_pData->pBuffer + index * m_pData->iBlockSize;
73 }
GetBuffer() const74 uint8_t* CFX_BaseArray::GetBuffer() const {
75 return m_pData->pBuffer;
76 }
Append(const CFX_BaseArray & src,int32_t iStart,int32_t iCount)77 int32_t CFX_BaseArray::Append(const CFX_BaseArray& src,
78 int32_t iStart,
79 int32_t iCount) {
80 int32_t iBlockSize = m_pData->iBlockSize;
81 FXSYS_assert(iBlockSize == src.m_pData->iBlockSize);
82 int32_t& iBlockCount = m_pData->iBlockCount;
83 int32_t iAdded = src.GetSize();
84 FXSYS_assert(iStart > -1 && iStart < iAdded);
85 if (iCount < 0) {
86 iCount = iAdded;
87 }
88 if (iStart + iCount > iAdded) {
89 iCount = iAdded - iStart;
90 }
91 if (iCount < 1) {
92 return 0;
93 }
94 uint8_t* pDst = m_pData->pBuffer + iBlockCount * iBlockSize;
95 AddSpaceTo(iBlockCount + iCount - 1);
96 FX_memcpy(pDst, src.m_pData->pBuffer + iStart * iBlockSize,
97 iCount * iBlockSize);
98 return iCount;
99 }
Copy(const CFX_BaseArray & src,int32_t iStart,int32_t iCount)100 int32_t CFX_BaseArray::Copy(const CFX_BaseArray& src,
101 int32_t iStart,
102 int32_t iCount) {
103 int32_t iBlockSize = m_pData->iBlockSize;
104 FXSYS_assert(iBlockSize == src.m_pData->iBlockSize);
105 int32_t iCopied = src.GetSize();
106 FXSYS_assert(iStart > -1 && iStart < iCopied);
107 if (iCount < 0) {
108 iCount = iCopied;
109 }
110 if (iStart + iCount > iCopied) {
111 iCount = iCopied - iStart;
112 }
113 if (iCount < 1) {
114 return 0;
115 }
116 RemoveAll(TRUE);
117 AddSpaceTo(iCount - 1);
118 FX_memcpy(m_pData->pBuffer, src.m_pData->pBuffer + iStart * iBlockSize,
119 iCount * iBlockSize);
120 return iCount;
121 }
RemoveLast(int32_t iCount)122 int32_t CFX_BaseArray::RemoveLast(int32_t iCount) {
123 int32_t& iBlockCount = m_pData->iBlockCount;
124 if (iCount < 0 || iCount > iBlockCount) {
125 iCount = iBlockCount;
126 iBlockCount = 0;
127 } else {
128 iBlockCount -= iCount;
129 }
130 return iCount;
131 }
RemoveAll(FX_BOOL bLeaveMemory)132 void CFX_BaseArray::RemoveAll(FX_BOOL bLeaveMemory) {
133 if (!bLeaveMemory) {
134 uint8_t*& pBuffer = m_pData->pBuffer;
135 if (pBuffer != NULL) {
136 FX_Free(pBuffer);
137 pBuffer = NULL;
138 }
139 m_pData->iTotalCount = 0;
140 }
141 m_pData->iBlockCount = 0;
142 }
CFX_BaseMassArrayImp(int32_t iChunkSize,int32_t iBlockSize)143 CFX_BaseMassArrayImp::CFX_BaseMassArrayImp(int32_t iChunkSize,
144 int32_t iBlockSize)
145 : m_iChunkSize(iChunkSize),
146 m_iBlockSize(iBlockSize),
147 m_iChunkCount(0),
148 m_iBlockCount(0) {
149 FXSYS_assert(m_iChunkSize > 0 && m_iBlockSize > 0);
150 m_pData = new CFX_PtrArray;
151 m_pData->SetSize(16);
152 }
~CFX_BaseMassArrayImp()153 CFX_BaseMassArrayImp::~CFX_BaseMassArrayImp() {
154 RemoveAll();
155 delete m_pData;
156 }
AddSpaceTo(int32_t index)157 uint8_t* CFX_BaseMassArrayImp::AddSpaceTo(int32_t index) {
158 FXSYS_assert(index > -1);
159 uint8_t* pChunk;
160 if (index < m_iBlockCount) {
161 pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize);
162 } else {
163 int32_t iMemSize = m_iChunkSize * m_iBlockSize;
164 while (TRUE) {
165 if (index < m_iChunkCount * m_iChunkSize) {
166 pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize);
167 break;
168 } else {
169 pChunk = FX_Alloc(uint8_t, iMemSize);
170 if (m_iChunkCount < m_pData->GetSize()) {
171 m_pData->SetAt(m_iChunkCount, pChunk);
172 } else {
173 m_pData->Add(pChunk);
174 }
175 m_iChunkCount++;
176 }
177 }
178 }
179 FXSYS_assert(pChunk != NULL);
180 m_iBlockCount = index + 1;
181 return pChunk + (index % m_iChunkSize) * m_iBlockSize;
182 }
GetAt(int32_t index) const183 uint8_t* CFX_BaseMassArrayImp::GetAt(int32_t index) const {
184 FXSYS_assert(index > -1 && index < m_iBlockCount);
185 uint8_t* pChunk = (uint8_t*)m_pData->GetAt(index / m_iChunkSize);
186 FXSYS_assert(pChunk != NULL);
187 return pChunk + (index % m_iChunkSize) * m_iBlockSize;
188 }
Append(const CFX_BaseMassArrayImp & src,int32_t iStart,int32_t iCount)189 int32_t CFX_BaseMassArrayImp::Append(const CFX_BaseMassArrayImp& src,
190 int32_t iStart,
191 int32_t iCount) {
192 FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
193 int32_t iAdded = src.m_iBlockCount;
194 FXSYS_assert(iStart > -1 && iStart < iAdded);
195 if (iCount < 0) {
196 iCount = iAdded;
197 }
198 if (iStart + iCount > iAdded) {
199 iCount = iAdded - iStart;
200 }
201 if (iCount < 1) {
202 return m_iBlockCount;
203 }
204 int32_t iBlockCount = m_iBlockCount;
205 int32_t iTotal = m_iBlockCount + iCount;
206 AddSpaceTo(iTotal - 1);
207 Append(iBlockCount, src, iStart, iCount);
208 return m_iBlockCount;
209 }
Copy(const CFX_BaseMassArrayImp & src,int32_t iStart,int32_t iCount)210 int32_t CFX_BaseMassArrayImp::Copy(const CFX_BaseMassArrayImp& src,
211 int32_t iStart,
212 int32_t iCount) {
213 FXSYS_assert(m_iBlockSize == src.m_iBlockSize);
214 int32_t iCopied = src.m_iBlockCount;
215 FXSYS_assert(iStart > -1);
216 if (iStart >= iCopied) {
217 return 0;
218 }
219 RemoveAll(TRUE);
220 if (iCount < 0) {
221 iCount = iCopied;
222 }
223 if (iStart + iCount > iCopied) {
224 iCount = iCopied - iStart;
225 }
226 if (iCount < 1) {
227 return 0;
228 }
229 if (m_iBlockCount < iCount) {
230 AddSpaceTo(iCount - 1);
231 }
232 Append(0, src, iStart, iCount);
233 return m_iBlockCount;
234 }
Append(int32_t iDstStart,const CFX_BaseMassArrayImp & src,int32_t iSrcStart,int32_t iSrcCount)235 void CFX_BaseMassArrayImp::Append(int32_t iDstStart,
236 const CFX_BaseMassArrayImp& src,
237 int32_t iSrcStart,
238 int32_t iSrcCount) {
239 FXSYS_assert(iDstStart > -1 && m_iBlockSize == src.m_iBlockSize);
240 int32_t iSrcTotal = src.m_iBlockCount;
241 FXSYS_assert(iSrcTotal > 0 && m_iBlockCount >= iDstStart + iSrcCount);
242 FXSYS_assert(iSrcStart > -1 && iSrcStart < iSrcTotal && iSrcCount > 0 &&
243 iSrcStart + iSrcCount <= iSrcTotal);
244 int32_t iDstChunkIndex = iDstStart / m_iChunkSize;
245 int32_t iSrcChunkIndex = iSrcStart / src.m_iChunkSize;
246 uint8_t* pDstChunk = (uint8_t*)GetAt(iDstStart);
247 uint8_t* pSrcChunk = (uint8_t*)src.GetAt(iSrcStart);
248 int32_t iDstChunkSize = m_iChunkSize - (iDstStart % m_iChunkSize);
249 int32_t iSrcChunkSize = src.m_iChunkSize - (iSrcStart % src.m_iChunkSize);
250 int32_t iCopySize =
251 std::min(iSrcCount, std::min(iSrcChunkSize, iDstChunkSize));
252 int32_t iCopyBytes = iCopySize * m_iBlockSize;
253 while (iSrcCount > 0) {
254 FXSYS_assert(pDstChunk != NULL && pSrcChunk != NULL);
255 FXSYS_memcpy(pDstChunk, pSrcChunk, iCopyBytes);
256 iSrcCount -= iCopySize;
257 iSrcChunkSize -= iCopySize;
258 if (iSrcChunkSize < 1) {
259 iSrcChunkSize = src.m_iChunkSize;
260 iSrcChunkIndex++;
261 pSrcChunk = (uint8_t*)src.m_pData->GetAt(iSrcChunkIndex);
262 } else {
263 pSrcChunk += iCopyBytes;
264 }
265 iDstChunkSize -= iCopySize;
266 if (iDstChunkSize < 1) {
267 iDstChunkSize = m_iChunkSize;
268 iDstChunkIndex++;
269 pDstChunk = (uint8_t*)m_pData->GetAt(iDstChunkIndex);
270 } else {
271 pDstChunk += iCopyBytes;
272 }
273 iCopySize = std::min(iSrcCount, std::min(iSrcChunkSize, iDstChunkSize));
274 iCopyBytes = iCopySize * m_iBlockSize;
275 }
276 }
RemoveLast(int32_t iCount)277 int32_t CFX_BaseMassArrayImp::RemoveLast(int32_t iCount) {
278 if (iCount < 0 || iCount >= m_iBlockCount) {
279 m_iBlockCount = 0;
280 } else {
281 m_iBlockCount -= iCount;
282 }
283 return m_iBlockCount;
284 }
RemoveAll(FX_BOOL bLeaveMemory)285 void CFX_BaseMassArrayImp::RemoveAll(FX_BOOL bLeaveMemory) {
286 if (bLeaveMemory) {
287 m_iBlockCount = 0;
288 return;
289 }
290 for (int32_t i = 0; i < m_iChunkCount; i++) {
291 void* p = m_pData->GetAt(i);
292 if (p == NULL) {
293 continue;
294 }
295 FX_Free(p);
296 }
297 m_pData->RemoveAll();
298 m_iChunkCount = 0;
299 m_iBlockCount = 0;
300 }
CFX_BaseMassArray(int32_t iChunkSize,int32_t iBlockSize)301 CFX_BaseMassArray::CFX_BaseMassArray(int32_t iChunkSize, int32_t iBlockSize) {
302 m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize);
303 }
~CFX_BaseMassArray()304 CFX_BaseMassArray::~CFX_BaseMassArray() {
305 delete m_pData;
306 }
GetSize() const307 int32_t CFX_BaseMassArray::GetSize() const {
308 return m_pData->m_iBlockCount;
309 }
AddSpaceTo(int32_t index)310 uint8_t* CFX_BaseMassArray::AddSpaceTo(int32_t index) {
311 return m_pData->AddSpaceTo(index);
312 }
GetAt(int32_t index) const313 uint8_t* CFX_BaseMassArray::GetAt(int32_t index) const {
314 return m_pData->GetAt(index);
315 }
Append(const CFX_BaseMassArray & src,int32_t iStart,int32_t iCount)316 int32_t CFX_BaseMassArray::Append(const CFX_BaseMassArray& src,
317 int32_t iStart,
318 int32_t iCount) {
319 return m_pData->Append(*(CFX_BaseMassArrayImp*)src.m_pData, iStart, iCount);
320 }
Copy(const CFX_BaseMassArray & src,int32_t iStart,int32_t iCount)321 int32_t CFX_BaseMassArray::Copy(const CFX_BaseMassArray& src,
322 int32_t iStart,
323 int32_t iCount) {
324 return m_pData->Copy(*(CFX_BaseMassArrayImp*)src.m_pData, iStart, iCount);
325 }
RemoveLast(int32_t iCount)326 int32_t CFX_BaseMassArray::RemoveLast(int32_t iCount) {
327 return m_pData->RemoveLast(iCount);
328 }
RemoveAll(FX_BOOL bLeaveMemory)329 void CFX_BaseMassArray::RemoveAll(FX_BOOL bLeaveMemory) {
330 m_pData->RemoveAll(bLeaveMemory);
331 }
332 typedef struct _FX_BASEDISCRETEARRAYDATA {
333 int32_t iBlockSize;
334 int32_t iChunkSize;
335 int32_t iChunkCount;
336 CFX_PtrArray ChunkBuffer;
337 } FX_BASEDISCRETEARRAYDATA, *FX_LPBASEDISCRETEARRAYDATA;
338 typedef FX_BASEDISCRETEARRAYDATA const* FX_LPCBASEDISCRETEARRAYDATA;
CFX_BaseDiscreteArray(int32_t iChunkSize,int32_t iBlockSize)339 CFX_BaseDiscreteArray::CFX_BaseDiscreteArray(int32_t iChunkSize,
340 int32_t iBlockSize) {
341 FXSYS_assert(iChunkSize > 0 && iBlockSize > 0);
342 FX_LPBASEDISCRETEARRAYDATA pData;
343 m_pData = pData = new FX_BASEDISCRETEARRAYDATA;
344 pData->ChunkBuffer.SetSize(16);
345 pData->iChunkCount = 0;
346 pData->iChunkSize = iChunkSize;
347 pData->iBlockSize = iBlockSize;
348 }
~CFX_BaseDiscreteArray()349 CFX_BaseDiscreteArray::~CFX_BaseDiscreteArray() {
350 RemoveAll();
351 delete (FX_LPBASEDISCRETEARRAYDATA) m_pData;
352 }
AddSpaceTo(int32_t index)353 uint8_t* CFX_BaseDiscreteArray::AddSpaceTo(int32_t index) {
354 FXSYS_assert(index > -1);
355 FX_LPBASEDISCRETEARRAYDATA pData = (FX_LPBASEDISCRETEARRAYDATA)m_pData;
356 int32_t& iChunkCount = pData->iChunkCount;
357 int32_t iChunkSize = pData->iChunkSize;
358 uint8_t* pChunk = NULL;
359 int32_t iChunk = index / iChunkSize;
360 if (iChunk < iChunkCount) {
361 pChunk = (uint8_t*)pData->ChunkBuffer.GetAt(iChunk);
362 }
363 if (!pChunk) {
364 pChunk = FX_Alloc2D(uint8_t, iChunkSize, pData->iBlockSize);
365 FXSYS_memset(pChunk, 0, iChunkSize * pData->iBlockSize);
366 pData->ChunkBuffer.SetAtGrow(iChunk, pChunk);
367 if (iChunkCount <= iChunk) {
368 iChunkCount = iChunk + 1;
369 }
370 }
371 return pChunk + (index % iChunkSize) * pData->iBlockSize;
372 }
GetAt(int32_t index) const373 uint8_t* CFX_BaseDiscreteArray::GetAt(int32_t index) const {
374 FXSYS_assert(index > -1);
375 FX_LPBASEDISCRETEARRAYDATA pData = (FX_LPBASEDISCRETEARRAYDATA)m_pData;
376 int32_t iChunkSize = pData->iChunkSize;
377 int32_t iChunk = index / iChunkSize;
378 if (iChunk >= pData->iChunkCount) {
379 return NULL;
380 }
381 uint8_t* pChunk = (uint8_t*)pData->ChunkBuffer.GetAt(iChunk);
382 if (pChunk == NULL) {
383 return NULL;
384 }
385 return pChunk + (index % iChunkSize) * pData->iBlockSize;
386 }
RemoveAll()387 void CFX_BaseDiscreteArray::RemoveAll() {
388 FX_LPBASEDISCRETEARRAYDATA pData = (FX_LPBASEDISCRETEARRAYDATA)m_pData;
389 CFX_PtrArray& ChunkBuffer = pData->ChunkBuffer;
390 int32_t& iChunkCount = pData->iChunkCount;
391 for (int32_t i = 0; i < iChunkCount; i++) {
392 void* p = ChunkBuffer.GetAt(i);
393 if (p == NULL) {
394 continue;
395 }
396 FX_Free(p);
397 }
398 ChunkBuffer.RemoveAll();
399 iChunkCount = 0;
400 }
CFX_BaseStack(int32_t iChunkSize,int32_t iBlockSize)401 CFX_BaseStack::CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize) {
402 m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize);
403 }
~CFX_BaseStack()404 CFX_BaseStack::~CFX_BaseStack() {
405 delete (CFX_BaseMassArrayImp*)m_pData;
406 }
Push()407 uint8_t* CFX_BaseStack::Push() {
408 return m_pData->AddSpace();
409 }
Pop()410 void CFX_BaseStack::Pop() {
411 int32_t& iBlockCount = m_pData->m_iBlockCount;
412 if (iBlockCount < 1) {
413 return;
414 }
415 iBlockCount--;
416 }
GetTopElement() const417 uint8_t* CFX_BaseStack::GetTopElement() const {
418 int32_t iSize = m_pData->m_iBlockCount;
419 if (iSize < 1) {
420 return NULL;
421 }
422 return m_pData->GetAt(iSize - 1);
423 }
GetSize() const424 int32_t CFX_BaseStack::GetSize() const {
425 return m_pData->m_iBlockCount;
426 }
GetAt(int32_t index) const427 uint8_t* CFX_BaseStack::GetAt(int32_t index) const {
428 return m_pData->GetAt(index);
429 }
RemoveAll(FX_BOOL bLeaveMemory)430 void CFX_BaseStack::RemoveAll(FX_BOOL bLeaveMemory) {
431 m_pData->RemoveAll(bLeaveMemory);
432 }
433