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 13 CFX_ThreadLock::CFX_ThreadLock() { 14 } 15 CFX_ThreadLock::~CFX_ThreadLock() {} 16 void CFX_ThreadLock::Lock() {} 17 void CFX_ThreadLock::Unlock() {} 18 class FX_BASEARRAYDATA : public CFX_Target { 19 public: 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 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 }; 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 } 39 CFX_BaseArray::~CFX_BaseArray() { 40 RemoveAll(); 41 delete m_pData; 42 } 43 int32_t CFX_BaseArray::GetSize() const { 44 return m_pData->iBlockCount; 45 } 46 int32_t CFX_BaseArray::GetBlockSize() const { 47 return m_pData->iBlockSize; 48 } 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 } 70 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 } 74 uint8_t* CFX_BaseArray::GetBuffer() const { 75 return m_pData->pBuffer; 76 } 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 } 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 } 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 } 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 } 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 } 153 CFX_BaseMassArrayImp::~CFX_BaseMassArrayImp() { 154 RemoveAll(); 155 delete m_pData; 156 } 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 } 183 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 } 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 } 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 } 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 } 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 } 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 } 301 CFX_BaseMassArray::CFX_BaseMassArray(int32_t iChunkSize, int32_t iBlockSize) { 302 m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize); 303 } 304 CFX_BaseMassArray::~CFX_BaseMassArray() { 305 delete m_pData; 306 } 307 int32_t CFX_BaseMassArray::GetSize() const { 308 return m_pData->m_iBlockCount; 309 } 310 uint8_t* CFX_BaseMassArray::AddSpaceTo(int32_t index) { 311 return m_pData->AddSpaceTo(index); 312 } 313 uint8_t* CFX_BaseMassArray::GetAt(int32_t index) const { 314 return m_pData->GetAt(index); 315 } 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 } 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 } 326 int32_t CFX_BaseMassArray::RemoveLast(int32_t iCount) { 327 return m_pData->RemoveLast(iCount); 328 } 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; 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 } 349 CFX_BaseDiscreteArray::~CFX_BaseDiscreteArray() { 350 RemoveAll(); 351 delete (FX_LPBASEDISCRETEARRAYDATA) m_pData; 352 } 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 } 373 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 } 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 } 401 CFX_BaseStack::CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize) { 402 m_pData = new CFX_BaseMassArrayImp(iChunkSize, iBlockSize); 403 } 404 CFX_BaseStack::~CFX_BaseStack() { 405 delete (CFX_BaseMassArrayImp*)m_pData; 406 } 407 uint8_t* CFX_BaseStack::Push() { 408 return m_pData->AddSpace(); 409 } 410 void CFX_BaseStack::Pop() { 411 int32_t& iBlockCount = m_pData->m_iBlockCount; 412 if (iBlockCount < 1) { 413 return; 414 } 415 iBlockCount--; 416 } 417 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 } 424 int32_t CFX_BaseStack::GetSize() const { 425 return m_pData->m_iBlockCount; 426 } 427 uint8_t* CFX_BaseStack::GetAt(int32_t index) const { 428 return m_pData->GetAt(index); 429 } 430 void CFX_BaseStack::RemoveAll(FX_BOOL bLeaveMemory) { 431 m_pData->RemoveAll(bLeaveMemory); 432 } 433