Home | History | Annotate | Download | only in crt
      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