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