Home | History | Annotate | Download | only in fxcrt
      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 #ifndef CORE_INCLUDE_FXCRT_FX_BASIC_H_
      8 #define CORE_INCLUDE_FXCRT_FX_BASIC_H_
      9 
     10 #include <algorithm>
     11 
     12 #include "fx_memory.h"
     13 #include "fx_stream.h"
     14 #include "fx_string.h"
     15 #include "fx_system.h"
     16 
     17 // The FX_ArraySize(arr) macro returns the # of elements in an array arr.
     18 // The expression is a compile-time constant, and therefore can be
     19 // used in defining new arrays, for example.  If you use FX_ArraySize on
     20 // a pointer by mistake, you will get a compile-time error.
     21 //
     22 // One caveat is that FX_ArraySize() doesn't accept any array of an
     23 // anonymous type or a type defined inside a function.
     24 #define FX_ArraySize(array) (sizeof(ArraySizeHelper(array)))
     25 
     26 // This template function declaration is used in defining FX_ArraySize.
     27 // Note that the function doesn't need an implementation, as we only
     28 // use its type.
     29 template <typename T, size_t N>
     30 char(&ArraySizeHelper(T(&array)[N]))[N];
     31 
     32 class CFX_BinaryBuf {
     33  public:
     34   CFX_BinaryBuf();
     35   CFX_BinaryBuf(FX_STRSIZE size);
     36 
     37   ~CFX_BinaryBuf();
     38 
     39   void Clear();
     40 
     41   void EstimateSize(FX_STRSIZE size, FX_STRSIZE alloc_step = 0);
     42 
     43   void AppendBlock(const void* pBuf, FX_STRSIZE size);
     44 
     45   void AppendFill(uint8_t byte, FX_STRSIZE count);
     46 
     47   void AppendString(const CFX_ByteStringC& str) {
     48     AppendBlock(str.GetPtr(), str.GetLength());
     49   }
     50 
     51   inline void AppendByte(uint8_t byte) {
     52     if (m_AllocSize <= m_DataSize) {
     53       ExpandBuf(1);
     54     }
     55     m_pBuffer[m_DataSize++] = byte;
     56   }
     57 
     58   void InsertBlock(FX_STRSIZE pos, const void* pBuf, FX_STRSIZE size);
     59 
     60   void AttachData(void* pBuf, FX_STRSIZE size);
     61 
     62   void CopyData(const void* pBuf, FX_STRSIZE size);
     63 
     64   void TakeOver(CFX_BinaryBuf& other);
     65 
     66   void Delete(int start_index, int count);
     67 
     68   uint8_t* GetBuffer() const { return m_pBuffer; }
     69 
     70   FX_STRSIZE GetSize() const { return m_DataSize; }
     71 
     72   CFX_ByteStringC GetByteString() const;
     73 
     74   void DetachBuffer();
     75 
     76  protected:
     77   FX_STRSIZE m_AllocStep;
     78 
     79   uint8_t* m_pBuffer;
     80 
     81   FX_STRSIZE m_DataSize;
     82 
     83   FX_STRSIZE m_AllocSize;
     84 
     85   void ExpandBuf(FX_STRSIZE size);
     86 };
     87 class CFX_ByteTextBuf : public CFX_BinaryBuf {
     88  public:
     89   void operator=(const CFX_ByteStringC& str);
     90 
     91   void AppendChar(int ch) { AppendByte((uint8_t)ch); }
     92 
     93   CFX_ByteTextBuf& operator<<(int i);
     94 
     95   CFX_ByteTextBuf& operator<<(FX_DWORD i);
     96 
     97   CFX_ByteTextBuf& operator<<(double f);
     98 
     99   CFX_ByteTextBuf& operator<<(const CFX_ByteStringC& lpsz);
    100 
    101   CFX_ByteTextBuf& operator<<(const CFX_ByteTextBuf& buf);
    102 
    103   FX_STRSIZE GetLength() const { return m_DataSize; }
    104 };
    105 class CFX_WideTextBuf : public CFX_BinaryBuf {
    106  public:
    107   void operator=(const FX_WCHAR* lpsz);
    108 
    109   void operator=(const CFX_WideStringC& str);
    110 
    111   void AppendChar(FX_WCHAR wch);
    112 
    113   CFX_WideTextBuf& operator<<(int i);
    114 
    115   CFX_WideTextBuf& operator<<(double f);
    116 
    117   CFX_WideTextBuf& operator<<(const FX_WCHAR* lpsz);
    118 
    119   CFX_WideTextBuf& operator<<(const CFX_WideStringC& str);
    120   CFX_WideTextBuf& operator<<(const CFX_WideString& str);
    121 
    122   CFX_WideTextBuf& operator<<(const CFX_WideTextBuf& buf);
    123 
    124   FX_STRSIZE GetLength() const { return m_DataSize / sizeof(FX_WCHAR); }
    125 
    126   FX_WCHAR* GetBuffer() const { return (FX_WCHAR*)m_pBuffer; }
    127 
    128   void Delete(int start_index, int count) {
    129     CFX_BinaryBuf::Delete(start_index * sizeof(FX_WCHAR),
    130                           count * sizeof(FX_WCHAR));
    131   }
    132 
    133   CFX_WideStringC GetWideString() const;
    134 };
    135 #ifdef PDF_ENABLE_XFA
    136 class CFX_ArchiveSaver {
    137  public:
    138   CFX_ArchiveSaver() : m_pStream(NULL) {}
    139 
    140   CFX_ArchiveSaver& operator<<(uint8_t i);
    141 
    142   CFX_ArchiveSaver& operator<<(int i);
    143 
    144   CFX_ArchiveSaver& operator<<(FX_DWORD i);
    145 
    146   CFX_ArchiveSaver& operator<<(FX_FLOAT i);
    147 
    148   CFX_ArchiveSaver& operator<<(double i);
    149 
    150   CFX_ArchiveSaver& operator<<(const CFX_ByteStringC& bstr);
    151 
    152   CFX_ArchiveSaver& operator<<(const FX_WCHAR* bstr);
    153 
    154   CFX_ArchiveSaver& operator<<(const CFX_WideString& wstr);
    155 
    156   void Write(const void* pData, FX_STRSIZE dwSize);
    157 
    158   intptr_t GetLength() { return m_SavingBuf.GetSize(); }
    159 
    160   const uint8_t* GetBuffer() { return m_SavingBuf.GetBuffer(); }
    161 
    162   void SetStream(IFX_FileStream* pStream) { m_pStream = pStream; }
    163 
    164  protected:
    165   CFX_BinaryBuf m_SavingBuf;
    166 
    167   IFX_FileStream* m_pStream;
    168 };
    169 class CFX_ArchiveLoader {
    170  public:
    171   CFX_ArchiveLoader(const uint8_t* pData, FX_DWORD dwSize);
    172 
    173   CFX_ArchiveLoader& operator>>(uint8_t& i);
    174 
    175   CFX_ArchiveLoader& operator>>(int& i);
    176 
    177   CFX_ArchiveLoader& operator>>(FX_DWORD& i);
    178 
    179   CFX_ArchiveLoader& operator>>(FX_FLOAT& i);
    180 
    181   CFX_ArchiveLoader& operator>>(double& i);
    182 
    183   CFX_ArchiveLoader& operator>>(CFX_ByteString& bstr);
    184 
    185   CFX_ArchiveLoader& operator>>(CFX_WideString& wstr);
    186 
    187   FX_BOOL IsEOF();
    188 
    189   FX_BOOL Read(void* pBuf, FX_DWORD dwSize);
    190 
    191  protected:
    192   FX_DWORD m_LoadingPos;
    193 
    194   const uint8_t* m_pLoadingBuf;
    195 
    196   FX_DWORD m_LoadingSize;
    197 };
    198 #endif  // PDF_ENABLE_XFA
    199 
    200 class IFX_BufferArchive {
    201  public:
    202   IFX_BufferArchive(FX_STRSIZE size);
    203   virtual ~IFX_BufferArchive() {}
    204 
    205   virtual void Clear();
    206 
    207   FX_BOOL Flush();
    208 
    209   int32_t AppendBlock(const void* pBuf, size_t size);
    210 
    211   int32_t AppendByte(uint8_t byte);
    212 
    213   int32_t AppendDWord(FX_DWORD i);
    214 
    215   int32_t AppendString(const CFX_ByteStringC& lpsz);
    216 
    217  protected:
    218   virtual FX_BOOL DoWork(const void* pBuf, size_t size) = 0;
    219 
    220   FX_STRSIZE m_BufSize;
    221 
    222   uint8_t* m_pBuffer;
    223 
    224   FX_STRSIZE m_Length;
    225 };
    226 
    227 class CFX_FileBufferArchive : public IFX_BufferArchive {
    228  public:
    229   CFX_FileBufferArchive(FX_STRSIZE size = 32768);
    230   ~CFX_FileBufferArchive() override;
    231 
    232   void Clear() override;
    233   FX_BOOL AttachFile(IFX_StreamWrite* pFile, FX_BOOL bTakeover = FALSE);
    234 
    235  private:
    236   FX_BOOL DoWork(const void* pBuf, size_t size) override;
    237 
    238   IFX_StreamWrite* m_pFile;
    239   FX_BOOL m_bTakeover;
    240 };
    241 
    242 struct CFX_CharMap {
    243   static CFX_CharMap* GetDefaultMapper(int32_t codepage = 0);
    244 
    245   CFX_WideString (*m_GetWideString)(CFX_CharMap* pMap,
    246                                     const CFX_ByteString& bstr);
    247 
    248   CFX_ByteString (*m_GetByteString)(CFX_CharMap* pMap,
    249                                     const CFX_WideString& wstr);
    250 
    251   int32_t (*m_GetCodePage)();
    252 };
    253 class CFX_UTF8Decoder {
    254  public:
    255   CFX_UTF8Decoder() { m_PendingBytes = 0; }
    256 
    257   void Clear();
    258 
    259   void Input(uint8_t byte);
    260 
    261   void AppendChar(FX_DWORD ch);
    262 
    263   void ClearStatus() { m_PendingBytes = 0; }
    264 
    265   CFX_WideStringC GetResult() const { return m_Buffer.GetWideString(); }
    266 
    267  protected:
    268   int m_PendingBytes;
    269 
    270   FX_DWORD m_PendingChar;
    271 
    272   CFX_WideTextBuf m_Buffer;
    273 };
    274 
    275 class CFX_UTF8Encoder {
    276  public:
    277   CFX_UTF8Encoder() {}
    278 
    279   void Input(FX_WCHAR unicode);
    280   void AppendStr(const CFX_ByteStringC& str) { m_Buffer << str; }
    281   CFX_ByteStringC GetResult() const { return m_Buffer.GetByteString(); }
    282 
    283  protected:
    284   CFX_ByteTextBuf m_Buffer;
    285 };
    286 
    287 class CFX_BasicArray {
    288  protected:
    289   CFX_BasicArray(int unit_size);
    290 
    291   ~CFX_BasicArray();
    292 
    293   FX_BOOL SetSize(int nNewSize);
    294 
    295   FX_BOOL Append(const CFX_BasicArray& src);
    296 
    297   FX_BOOL Copy(const CFX_BasicArray& src);
    298 
    299   uint8_t* InsertSpaceAt(int nIndex, int nCount);
    300 
    301   FX_BOOL RemoveAt(int nIndex, int nCount);
    302 
    303   FX_BOOL InsertAt(int nStartIndex, const CFX_BasicArray* pNewArray);
    304 
    305   const void* GetDataPtr(int index) const;
    306 
    307  protected:
    308   uint8_t* m_pData;
    309 
    310   int m_nSize;
    311 
    312   int m_nMaxSize;
    313 
    314   int m_nUnitSize;
    315 };
    316 template <class TYPE>
    317 class CFX_ArrayTemplate : public CFX_BasicArray {
    318  public:
    319   CFX_ArrayTemplate() : CFX_BasicArray(sizeof(TYPE)) {}
    320 
    321   int GetSize() const { return m_nSize; }
    322 
    323   int GetUpperBound() const { return m_nSize - 1; }
    324 
    325   FX_BOOL SetSize(int nNewSize) { return CFX_BasicArray::SetSize(nNewSize); }
    326 
    327   void RemoveAll() { SetSize(0); }
    328 
    329   const TYPE GetAt(int nIndex) const {
    330     if (nIndex < 0 || nIndex >= m_nSize) {
    331       return (const TYPE&)(*(volatile const TYPE*)NULL);
    332     }
    333     return ((const TYPE*)m_pData)[nIndex];
    334   }
    335 
    336   FX_BOOL SetAt(int nIndex, TYPE newElement) {
    337     if (nIndex < 0 || nIndex >= m_nSize) {
    338       return FALSE;
    339     }
    340     ((TYPE*)m_pData)[nIndex] = newElement;
    341     return TRUE;
    342   }
    343 
    344   TYPE& ElementAt(int nIndex) {
    345     if (nIndex < 0 || nIndex >= m_nSize) {
    346       return *(TYPE*)NULL;
    347     }
    348     return ((TYPE*)m_pData)[nIndex];
    349   }
    350 
    351   const TYPE* GetData() const { return (const TYPE*)m_pData; }
    352 
    353   TYPE* GetData() { return (TYPE*)m_pData; }
    354 
    355   FX_BOOL SetAtGrow(int nIndex, TYPE newElement) {
    356     if (nIndex < 0) {
    357       return FALSE;
    358     }
    359     if (nIndex >= m_nSize)
    360       if (!SetSize(nIndex + 1)) {
    361         return FALSE;
    362       }
    363     ((TYPE*)m_pData)[nIndex] = newElement;
    364     return TRUE;
    365   }
    366 
    367   FX_BOOL Add(TYPE newElement) {
    368     if (m_nSize < m_nMaxSize) {
    369       m_nSize++;
    370     } else if (!SetSize(m_nSize + 1)) {
    371       return FALSE;
    372     }
    373     ((TYPE*)m_pData)[m_nSize - 1] = newElement;
    374     return TRUE;
    375   }
    376 
    377   FX_BOOL Append(const CFX_ArrayTemplate& src) {
    378     return CFX_BasicArray::Append(src);
    379   }
    380 
    381   FX_BOOL Copy(const CFX_ArrayTemplate& src) {
    382     return CFX_BasicArray::Copy(src);
    383   }
    384 
    385   TYPE* GetDataPtr(int index) {
    386     return (TYPE*)CFX_BasicArray::GetDataPtr(index);
    387   }
    388 
    389   TYPE* AddSpace() { return (TYPE*)CFX_BasicArray::InsertSpaceAt(m_nSize, 1); }
    390 
    391   TYPE* InsertSpaceAt(int nIndex, int nCount) {
    392     return (TYPE*)CFX_BasicArray::InsertSpaceAt(nIndex, nCount);
    393   }
    394 
    395   const TYPE operator[](int nIndex) const {
    396     if (nIndex < 0 || nIndex >= m_nSize) {
    397       *(volatile char*)0 = '\0';
    398     }
    399     return ((const TYPE*)m_pData)[nIndex];
    400   }
    401 
    402   TYPE& operator[](int nIndex) {
    403     if (nIndex < 0 || nIndex >= m_nSize) {
    404       *(volatile char*)0 = '\0';
    405     }
    406     return ((TYPE*)m_pData)[nIndex];
    407   }
    408 
    409   FX_BOOL InsertAt(int nIndex, TYPE newElement, int nCount = 1) {
    410     if (!InsertSpaceAt(nIndex, nCount)) {
    411       return FALSE;
    412     }
    413     while (nCount--) {
    414       ((TYPE*)m_pData)[nIndex++] = newElement;
    415     }
    416     return TRUE;
    417   }
    418 
    419   FX_BOOL RemoveAt(int nIndex, int nCount = 1) {
    420     return CFX_BasicArray::RemoveAt(nIndex, nCount);
    421   }
    422 
    423   FX_BOOL InsertAt(int nStartIndex, const CFX_BasicArray* pNewArray) {
    424     return CFX_BasicArray::InsertAt(nStartIndex, pNewArray);
    425   }
    426 
    427   int Find(TYPE data, int iStart = 0) const {
    428     if (iStart < 0) {
    429       return -1;
    430     }
    431     for (; iStart < (int)m_nSize; iStart++)
    432       if (((TYPE*)m_pData)[iStart] == data) {
    433         return iStart;
    434       }
    435     return -1;
    436   }
    437 };
    438 typedef CFX_ArrayTemplate<uint8_t> CFX_ByteArray;
    439 typedef CFX_ArrayTemplate<FX_WORD> CFX_WordArray;
    440 typedef CFX_ArrayTemplate<FX_DWORD> CFX_DWordArray;
    441 typedef CFX_ArrayTemplate<void*> CFX_PtrArray;
    442 typedef CFX_ArrayTemplate<FX_FILESIZE> CFX_FileSizeArray;
    443 #ifdef PDF_ENABLE_XFA
    444 typedef CFX_ArrayTemplate<FX_FLOAT> CFX_FloatArray;
    445 typedef CFX_ArrayTemplate<int32_t> CFX_Int32Array;
    446 #endif  // PDF_ENABLE_XFA
    447 
    448 template <class ObjectClass>
    449 class CFX_ObjectArray : public CFX_BasicArray {
    450  public:
    451   CFX_ObjectArray() : CFX_BasicArray(sizeof(ObjectClass)) {}
    452 
    453   ~CFX_ObjectArray() { RemoveAll(); }
    454 
    455   void Add(const ObjectClass& data) {
    456     new ((void*)InsertSpaceAt(m_nSize, 1)) ObjectClass(data);
    457   }
    458 
    459   ObjectClass& Add() {
    460     return *(ObjectClass*)new ((void*)InsertSpaceAt(m_nSize, 1)) ObjectClass();
    461   }
    462 
    463   void* AddSpace() { return InsertSpaceAt(m_nSize, 1); }
    464 
    465   int32_t Append(const CFX_ObjectArray& src,
    466                  int32_t nStart = 0,
    467                  int32_t nCount = -1) {
    468     if (nCount == 0) {
    469       return 0;
    470     }
    471     int32_t nSize = src.GetSize();
    472     if (!nSize) {
    473       return 0;
    474     }
    475     FXSYS_assert(nStart > -1 && nStart < nSize);
    476     if (nCount < 0) {
    477       nCount = nSize;
    478     }
    479     if (nStart + nCount > nSize) {
    480       nCount = nSize - nStart;
    481     }
    482     if (nCount < 1) {
    483       return 0;
    484     }
    485     nSize = m_nSize;
    486     InsertSpaceAt(m_nSize, nCount);
    487     ObjectClass* pStartObj = (ObjectClass*)GetDataPtr(nSize);
    488     nSize = nStart + nCount;
    489     for (int32_t i = nStart; i < nSize; i++, pStartObj++) {
    490       new ((void*)pStartObj) ObjectClass(src[i]);
    491     }
    492     return nCount;
    493   }
    494 
    495   int32_t Copy(const CFX_ObjectArray& src,
    496                int32_t nStart = 0,
    497                int32_t nCount = -1) {
    498     if (nCount == 0) {
    499       return 0;
    500     }
    501     int32_t nSize = src.GetSize();
    502     if (!nSize) {
    503       return 0;
    504     }
    505     FXSYS_assert(nStart > -1 && nStart < nSize);
    506     if (nCount < 0) {
    507       nCount = nSize;
    508     }
    509     if (nStart + nCount > nSize) {
    510       nCount = nSize - nStart;
    511     }
    512     if (nCount < 1) {
    513       return 0;
    514     }
    515     RemoveAll();
    516     SetSize(nCount);
    517     ObjectClass* pStartObj = (ObjectClass*)m_pData;
    518     nSize = nStart + nCount;
    519     for (int32_t i = nStart; i < nSize; i++, pStartObj++) {
    520       new ((void*)pStartObj) ObjectClass(src[i]);
    521     }
    522     return nCount;
    523   }
    524 
    525   int GetSize() const { return m_nSize; }
    526 
    527   ObjectClass& operator[](int index) const {
    528     FXSYS_assert(index < m_nSize);
    529     return *(ObjectClass*)CFX_BasicArray::GetDataPtr(index);
    530   }
    531 
    532   ObjectClass* GetDataPtr(int index) {
    533     return (ObjectClass*)CFX_BasicArray::GetDataPtr(index);
    534   }
    535 
    536   void RemoveAt(int index) {
    537     FXSYS_assert(index < m_nSize);
    538     ((ObjectClass*)GetDataPtr(index))->~ObjectClass();
    539     CFX_BasicArray::RemoveAt(index, 1);
    540   }
    541 
    542   void RemoveAll() {
    543     for (int i = 0; i < m_nSize; i++) {
    544       ((ObjectClass*)GetDataPtr(i))->~ObjectClass();
    545     }
    546     CFX_BasicArray::SetSize(0);
    547   }
    548 };
    549 typedef CFX_ObjectArray<CFX_ByteString> CFX_ByteStringArray;
    550 typedef CFX_ObjectArray<CFX_WideString> CFX_WideStringArray;
    551 class CFX_BaseSegmentedArray {
    552  public:
    553   CFX_BaseSegmentedArray(int unit_size = 1,
    554                          int segment_units = 512,
    555                          int index_size = 8);
    556 
    557   ~CFX_BaseSegmentedArray();
    558 
    559   void SetUnitSize(int unit_size, int segment_units, int index_size = 8);
    560 
    561   void* Add();
    562 
    563   void* GetAt(int index) const;
    564 
    565   void RemoveAll();
    566 
    567   void Delete(int index, int count = 1);
    568 
    569   int GetSize() const { return m_DataSize; }
    570 
    571   int GetSegmentSize() const { return m_SegmentSize; }
    572 
    573   int GetUnitSize() const { return m_UnitSize; }
    574 
    575   void* Iterate(FX_BOOL (*callback)(void* param, void* pData),
    576                 void* param) const;
    577 
    578  private:
    579   int m_UnitSize;
    580 
    581   short m_SegmentSize;
    582 
    583   uint8_t m_IndexSize;
    584 
    585   uint8_t m_IndexDepth;
    586 
    587   int m_DataSize;
    588 
    589   void* m_pIndex;
    590   void** GetIndex(int seg_index) const;
    591   void* IterateIndex(int level,
    592                      int& start,
    593                      void** pIndex,
    594                      FX_BOOL (*callback)(void* param, void* pData),
    595                      void* param) const;
    596   void* IterateSegment(const uint8_t* pSegment,
    597                        int count,
    598                        FX_BOOL (*callback)(void* param, void* pData),
    599                        void* param) const;
    600 };
    601 template <class ElementType>
    602 class CFX_SegmentedArray : public CFX_BaseSegmentedArray {
    603  public:
    604   CFX_SegmentedArray(int segment_units, int index_size = 8)
    605       : CFX_BaseSegmentedArray(sizeof(ElementType), segment_units, index_size) {
    606   }
    607 
    608   void Add(ElementType data) {
    609     *(ElementType*)CFX_BaseSegmentedArray::Add() = data;
    610   }
    611 
    612   ElementType& operator[](int index) {
    613     return *(ElementType*)CFX_BaseSegmentedArray::GetAt(index);
    614   }
    615 };
    616 template <class DataType, int FixedSize>
    617 class CFX_FixedBufGrow {
    618  public:
    619   CFX_FixedBufGrow() : m_pData(NULL) {}
    620   CFX_FixedBufGrow(int data_size) : m_pData(NULL) {
    621     if (data_size > FixedSize) {
    622       m_pData = FX_Alloc(DataType, data_size);
    623     } else {
    624       FXSYS_memset(m_Data, 0, sizeof(DataType) * FixedSize);
    625     }
    626   }
    627   void SetDataSize(int data_size) {
    628     FX_Free(m_pData);
    629     m_pData = NULL;
    630     if (data_size > FixedSize) {
    631       m_pData = FX_Alloc(DataType, data_size);
    632     } else {
    633       FXSYS_memset(m_Data, 0, sizeof(DataType) * FixedSize);
    634     }
    635   }
    636   ~CFX_FixedBufGrow() { FX_Free(m_pData); }
    637   operator DataType*() { return m_pData ? m_pData : m_Data; }
    638 
    639  private:
    640   DataType m_Data[FixedSize];
    641   DataType* m_pData;
    642 };
    643 class CFX_MapPtrToPtr {
    644  protected:
    645   struct CAssoc {
    646     CAssoc* pNext;
    647 
    648     void* key;
    649 
    650     void* value;
    651   };
    652 
    653  public:
    654   CFX_MapPtrToPtr(int nBlockSize = 10);
    655 
    656   ~CFX_MapPtrToPtr();
    657 
    658   int GetCount() const { return m_nCount; }
    659 
    660   FX_BOOL IsEmpty() const { return m_nCount == 0; }
    661 
    662   FX_BOOL Lookup(void* key, void*& rValue) const;
    663 
    664   void* GetValueAt(void* key) const;
    665 
    666   void*& operator[](void* key);
    667 
    668   void SetAt(void* key, void* newValue) { (*this)[key] = newValue; }
    669 
    670   FX_BOOL RemoveKey(void* key);
    671 
    672   void RemoveAll();
    673 
    674   FX_POSITION GetStartPosition() const {
    675     return (m_nCount == 0) ? NULL : (FX_POSITION)-1;
    676   }
    677 
    678   void GetNextAssoc(FX_POSITION& rNextPosition,
    679                     void*& rKey,
    680                     void*& rValue) const;
    681 
    682   FX_DWORD GetHashTableSize() const { return m_nHashTableSize; }
    683 
    684   void InitHashTable(FX_DWORD hashSize, FX_BOOL bAllocNow = TRUE);
    685 
    686  protected:
    687   CAssoc** m_pHashTable;
    688 
    689   FX_DWORD m_nHashTableSize;
    690 
    691   int m_nCount;
    692 
    693   CAssoc* m_pFreeList;
    694 
    695   struct CFX_Plex* m_pBlocks;
    696 
    697   int m_nBlockSize;
    698 
    699   FX_DWORD HashKey(void* key) const;
    700 
    701   CAssoc* NewAssoc();
    702 
    703   void FreeAssoc(CAssoc* pAssoc);
    704 
    705   CAssoc* GetAssocAt(void* key, FX_DWORD& hash) const;
    706 };
    707 #ifdef PDF_ENABLE_XFA
    708 template <class KeyType, class ValueType>
    709 class CFX_MapPtrTemplate : public CFX_MapPtrToPtr {
    710  public:
    711   CFX_MapPtrTemplate() : CFX_MapPtrToPtr(10) {}
    712 
    713   FX_BOOL Lookup(KeyType key, ValueType& rValue) const {
    714     void* pValue = NULL;
    715     if (!CFX_MapPtrToPtr::Lookup((void*)(uintptr_t)key, pValue)) {
    716       return FALSE;
    717     }
    718     rValue = (ValueType)(uintptr_t)pValue;
    719     return TRUE;
    720   }
    721 
    722   ValueType& operator[](KeyType key) {
    723     return (ValueType&)CFX_MapPtrToPtr::operator[]((void*)(uintptr_t)key);
    724   }
    725 
    726   void SetAt(KeyType key, ValueType newValue) {
    727     CFX_MapPtrToPtr::SetAt((void*)(uintptr_t)key, (void*)(uintptr_t)newValue);
    728   }
    729 
    730   FX_BOOL RemoveKey(KeyType key) {
    731     return CFX_MapPtrToPtr::RemoveKey((void*)(uintptr_t)key);
    732   }
    733 
    734   void GetNextAssoc(FX_POSITION& rNextPosition,
    735                     KeyType& rKey,
    736                     ValueType& rValue) const {
    737     void* pKey = NULL;
    738     void* pValue = NULL;
    739     CFX_MapPtrToPtr::GetNextAssoc(rNextPosition, pKey, pValue);
    740     rKey = (KeyType)(uintptr_t)pKey;
    741     rValue = (ValueType)(uintptr_t)pValue;
    742   }
    743 };
    744 #endif  // PDF_ENABLE_XFA
    745 class CFX_CMapByteStringToPtr {
    746  public:
    747   CFX_CMapByteStringToPtr();
    748 
    749   ~CFX_CMapByteStringToPtr();
    750 
    751   void RemoveAll();
    752 
    753   FX_POSITION GetStartPosition() const;
    754 
    755   void GetNextAssoc(FX_POSITION& rNextPosition,
    756                     CFX_ByteString& rKey,
    757                     void*& rValue) const;
    758 
    759   void* GetNextValue(FX_POSITION& rNextPosition) const;
    760 
    761   FX_BOOL Lookup(const CFX_ByteStringC& key, void*& rValue) const;
    762 
    763   void SetAt(const CFX_ByteStringC& key, void* value);
    764 
    765   void RemoveKey(const CFX_ByteStringC& key);
    766 
    767   int GetCount() const;
    768 
    769   void AddValue(const CFX_ByteStringC& key, void* pValue);
    770 
    771  private:
    772   CFX_BaseSegmentedArray m_Buffer;
    773 };
    774 class CFX_PtrList {
    775  protected:
    776   struct CNode {
    777     CNode* pNext;
    778 
    779     CNode* pPrev;
    780 
    781     void* data;
    782   };
    783 
    784  public:
    785   CFX_PtrList(int nBlockSize = 10);
    786 
    787   FX_POSITION GetHeadPosition() const { return (FX_POSITION)m_pNodeHead; }
    788 
    789   FX_POSITION GetTailPosition() const { return (FX_POSITION)m_pNodeTail; }
    790 
    791   void* GetNext(FX_POSITION& rPosition) const {
    792     CNode* pNode = (CNode*)rPosition;
    793     rPosition = (FX_POSITION)pNode->pNext;
    794     return pNode->data;
    795   }
    796 
    797   void* GetPrev(FX_POSITION& rPosition) const {
    798     CNode* pNode = (CNode*)rPosition;
    799     rPosition = (FX_POSITION)pNode->pPrev;
    800     return pNode->data;
    801   }
    802 
    803   FX_POSITION GetNextPosition(FX_POSITION pos) const {
    804     return ((CNode*)pos)->pNext;
    805   }
    806 
    807   FX_POSITION GetPrevPosition(FX_POSITION pos) const {
    808     return ((CNode*)pos)->pPrev;
    809   }
    810 
    811   void* GetAt(FX_POSITION rPosition) const {
    812     CNode* pNode = (CNode*)rPosition;
    813     return pNode->data;
    814   }
    815 
    816   int GetCount() const { return m_nCount; }
    817 
    818   FX_POSITION AddTail(void* newElement);
    819 
    820   FX_POSITION AddHead(void* newElement);
    821 
    822   void SetAt(FX_POSITION pos, void* newElement) {
    823     CNode* pNode = (CNode*)pos;
    824     pNode->data = newElement;
    825   }
    826 
    827   FX_POSITION InsertAfter(FX_POSITION pos, void* newElement);
    828 
    829   FX_POSITION Find(void* searchValue, FX_POSITION startAfter = NULL) const;
    830 
    831   FX_POSITION FindIndex(int index) const;
    832 
    833   void RemoveAt(FX_POSITION pos);
    834 
    835   void RemoveAll();
    836 
    837  protected:
    838   CNode* m_pNodeHead;
    839 
    840   CNode* m_pNodeTail;
    841 
    842   int m_nCount;
    843 
    844   CNode* m_pNodeFree;
    845 
    846   struct CFX_Plex* m_pBlocks;
    847 
    848   int m_nBlockSize;
    849 
    850   CNode* NewNode(CNode* pPrev, CNode* pNext);
    851 
    852   void FreeNode(CNode* pNode);
    853 
    854  public:
    855   ~CFX_PtrList();
    856 };
    857 typedef void (*PD_CALLBACK_FREEDATA)(void* pData);
    858 struct FX_PRIVATEDATA {
    859   void FreeData();
    860 
    861   void* m_pModuleId;
    862 
    863   void* m_pData;
    864 
    865   PD_CALLBACK_FREEDATA m_pCallback;
    866 
    867   FX_BOOL m_bSelfDestruct;
    868 };
    869 class CFX_PrivateData {
    870  public:
    871   ~CFX_PrivateData();
    872 
    873   void ClearAll();
    874 
    875   void SetPrivateData(void* module_id,
    876                       void* pData,
    877                       PD_CALLBACK_FREEDATA callback);
    878 
    879   void SetPrivateObj(void* module_id, CFX_DestructObject* pObj);
    880 
    881   void* GetPrivateData(void* module_id);
    882 
    883   FX_BOOL LookupPrivateData(void* module_id, void*& pData) const {
    884     if (!module_id) {
    885       return FALSE;
    886     }
    887     FX_DWORD nCount = m_DataList.GetSize();
    888     for (FX_DWORD n = 0; n < nCount; n++) {
    889       if (m_DataList[n].m_pModuleId == module_id) {
    890         pData = m_DataList[n].m_pData;
    891         return TRUE;
    892       }
    893     }
    894     return FALSE;
    895   }
    896 
    897   FX_BOOL RemovePrivateData(void* module_id);
    898 
    899  protected:
    900   CFX_ArrayTemplate<FX_PRIVATEDATA> m_DataList;
    901 
    902   void AddData(void* module_id,
    903                void* pData,
    904                PD_CALLBACK_FREEDATA callback,
    905                FX_BOOL bSelfDestruct);
    906 };
    907 class CFX_BitStream {
    908  public:
    909   void Init(const uint8_t* pData, FX_DWORD dwSize);
    910 
    911   FX_DWORD GetBits(FX_DWORD nBits);
    912 
    913   void ByteAlign();
    914 
    915   FX_BOOL IsEOF() { return m_BitPos >= m_BitSize; }
    916 
    917   void SkipBits(FX_DWORD nBits) { m_BitPos += nBits; }
    918 
    919   void Rewind() { m_BitPos = 0; }
    920 
    921   FX_DWORD GetPos() const { return m_BitPos; }
    922 
    923   FX_DWORD BitsRemaining() const {
    924     return m_BitSize >= m_BitPos ? m_BitSize - m_BitPos : 0;
    925   }
    926 
    927  protected:
    928   FX_DWORD m_BitPos;
    929 
    930   FX_DWORD m_BitSize;
    931 
    932   const uint8_t* m_pData;
    933 };
    934 template <class ObjClass>
    935 class CFX_CountRef {
    936  public:
    937   typedef CFX_CountRef<ObjClass> Ref;
    938 
    939   class CountedObj : public ObjClass {
    940    public:
    941     CountedObj() {}
    942 
    943     CountedObj(const CountedObj& src) : ObjClass(src) {}
    944 
    945     int m_RefCount;
    946   };
    947 
    948   CFX_CountRef() { m_pObject = NULL; }
    949 
    950   CFX_CountRef(const Ref& ref) {
    951     m_pObject = ref.m_pObject;
    952     if (m_pObject) {
    953       m_pObject->m_RefCount++;
    954     }
    955   }
    956 
    957   ~CFX_CountRef() {
    958     if (!m_pObject) {
    959       return;
    960     }
    961     m_pObject->m_RefCount--;
    962     if (m_pObject->m_RefCount <= 0) {
    963       delete m_pObject;
    964     }
    965   }
    966 
    967   ObjClass* New() {
    968     if (m_pObject) {
    969       m_pObject->m_RefCount--;
    970       if (m_pObject->m_RefCount <= 0) {
    971         delete m_pObject;
    972       }
    973     }
    974     m_pObject = new CountedObj;
    975     m_pObject->m_RefCount = 1;
    976     return m_pObject;
    977   }
    978 
    979   void operator=(const Ref& ref) {
    980     if (ref.m_pObject) {
    981       ref.m_pObject->m_RefCount++;
    982     }
    983     if (m_pObject) {
    984       m_pObject->m_RefCount--;
    985       if (m_pObject->m_RefCount <= 0) {
    986         delete m_pObject;
    987       }
    988     }
    989     m_pObject = ref.m_pObject;
    990   }
    991 
    992   void operator=(void* p) {
    993     FXSYS_assert(p == 0);
    994     if (!m_pObject) {
    995       return;
    996     }
    997     m_pObject->m_RefCount--;
    998     if (m_pObject->m_RefCount <= 0) {
    999       delete m_pObject;
   1000     }
   1001     m_pObject = NULL;
   1002   }
   1003 
   1004   const ObjClass* GetObject() const { return m_pObject; }
   1005 
   1006   operator const ObjClass*() const { return m_pObject; }
   1007 
   1008   FX_BOOL IsNull() const { return !m_pObject; }
   1009 
   1010   FX_BOOL NotNull() const { return !IsNull(); }
   1011 
   1012   ObjClass* GetModify() {
   1013     if (!m_pObject) {
   1014       m_pObject = new CountedObj;
   1015       m_pObject->m_RefCount = 1;
   1016     } else if (m_pObject->m_RefCount > 1) {
   1017       m_pObject->m_RefCount--;
   1018       CountedObj* pOldObject = m_pObject;
   1019       m_pObject = new CountedObj(*pOldObject);
   1020       m_pObject->m_RefCount = 1;
   1021     }
   1022     return m_pObject;
   1023   }
   1024 
   1025   void SetNull() {
   1026     if (!m_pObject) {
   1027       return;
   1028     }
   1029     m_pObject->m_RefCount--;
   1030     if (m_pObject->m_RefCount <= 0) {
   1031       delete m_pObject;
   1032     }
   1033     m_pObject = NULL;
   1034   }
   1035 
   1036   FX_BOOL operator==(const Ref& ref) const {
   1037     return m_pObject == ref.m_pObject;
   1038   }
   1039 
   1040  protected:
   1041   CountedObj* m_pObject;
   1042 };
   1043 class IFX_Pause {
   1044  public:
   1045   virtual ~IFX_Pause() {}
   1046   virtual FX_BOOL NeedToPauseNow() = 0;
   1047 };
   1048 
   1049 template <typename T>
   1050 class CFX_AutoRestorer {
   1051  public:
   1052   explicit CFX_AutoRestorer(T* location)
   1053       : m_Location(location), m_OldValue(*location) {}
   1054   ~CFX_AutoRestorer() { *m_Location = m_OldValue; }
   1055 
   1056  private:
   1057   T* const m_Location;
   1058   const T m_OldValue;
   1059 };
   1060 
   1061 struct FxFreeDeleter {
   1062   inline void operator()(void* ptr) const { FX_Free(ptr); }
   1063 };
   1064 
   1065 // Used with std::unique_ptr to Release() objects that can't be deleted.
   1066 template <class T>
   1067 struct ReleaseDeleter {
   1068   inline void operator()(T* ptr) const { ptr->Release(); }
   1069 };
   1070 
   1071 #define FX_DATALIST_LENGTH 1024
   1072 template <size_t unit>
   1073 class CFX_SortListArray {
   1074  protected:
   1075   struct DataList {
   1076     int32_t start;
   1077 
   1078     int32_t count;
   1079     uint8_t* data;
   1080   };
   1081 
   1082  public:
   1083   CFX_SortListArray() : m_CurList(0) {}
   1084 
   1085   ~CFX_SortListArray() { Clear(); }
   1086 
   1087   void Clear() {
   1088     for (int32_t i = m_DataLists.GetUpperBound(); i >= 0; i--) {
   1089       DataList list = m_DataLists.ElementAt(i);
   1090       FX_Free(list.data);
   1091     }
   1092     m_DataLists.RemoveAll();
   1093     m_CurList = 0;
   1094   }
   1095 
   1096   void Append(int32_t nStart, int32_t nCount) {
   1097     if (nStart < 0) {
   1098       return;
   1099     }
   1100     while (nCount > 0) {
   1101       int32_t temp_count = std::min(nCount, FX_DATALIST_LENGTH);
   1102       DataList list;
   1103       list.data = FX_Alloc2D(uint8_t, temp_count, unit);
   1104       list.start = nStart;
   1105       list.count = temp_count;
   1106       Append(list);
   1107       nCount -= temp_count;
   1108       nStart += temp_count;
   1109     }
   1110   }
   1111 
   1112   uint8_t* GetAt(int32_t nIndex) {
   1113     if (nIndex < 0) {
   1114       return NULL;
   1115     }
   1116     if (m_CurList < 0 || m_CurList >= m_DataLists.GetSize()) {
   1117       return NULL;
   1118     }
   1119     DataList* pCurList = m_DataLists.GetDataPtr(m_CurList);
   1120     if (!pCurList || nIndex < pCurList->start ||
   1121         nIndex >= pCurList->start + pCurList->count) {
   1122       pCurList = NULL;
   1123       int32_t iStart = 0;
   1124       int32_t iEnd = m_DataLists.GetUpperBound();
   1125       int32_t iMid = 0;
   1126       while (iStart <= iEnd) {
   1127         iMid = (iStart + iEnd) / 2;
   1128         DataList* list = m_DataLists.GetDataPtr(iMid);
   1129         if (nIndex < list->start) {
   1130           iEnd = iMid - 1;
   1131         } else if (nIndex >= list->start + list->count) {
   1132           iStart = iMid + 1;
   1133         } else {
   1134           pCurList = list;
   1135           m_CurList = iMid;
   1136           break;
   1137         }
   1138       }
   1139     }
   1140     return pCurList ? pCurList->data + (nIndex - pCurList->start) * unit : NULL;
   1141   }
   1142 
   1143  protected:
   1144   void Append(const DataList& list) {
   1145     int32_t iStart = 0;
   1146     int32_t iEnd = m_DataLists.GetUpperBound();
   1147     int32_t iFind = 0;
   1148     while (iStart <= iEnd) {
   1149       int32_t iMid = (iStart + iEnd) / 2;
   1150       DataList* cur_list = m_DataLists.GetDataPtr(iMid);
   1151       if (list.start < cur_list->start + cur_list->count) {
   1152         iEnd = iMid - 1;
   1153       } else {
   1154         if (iMid == iEnd) {
   1155           iFind = iMid + 1;
   1156           break;
   1157         }
   1158         DataList* next_list = m_DataLists.GetDataPtr(iMid + 1);
   1159         if (list.start < next_list->start) {
   1160           iFind = iMid + 1;
   1161           break;
   1162         } else {
   1163           iStart = iMid + 1;
   1164         }
   1165       }
   1166     }
   1167     m_DataLists.InsertAt(iFind, list);
   1168   }
   1169   int32_t m_CurList;
   1170   CFX_ArrayTemplate<DataList> m_DataLists;
   1171 };
   1172 template <typename T1, typename T2>
   1173 class CFX_ListArrayTemplate {
   1174  public:
   1175   void Clear() { m_Data.Clear(); }
   1176 
   1177   void Add(int32_t nStart, int32_t nCount) { m_Data.Append(nStart, nCount); }
   1178 
   1179   T2& operator[](int32_t nIndex) {
   1180     uint8_t* data = m_Data.GetAt(nIndex);
   1181     FXSYS_assert(data);
   1182     return (T2&)(*(volatile T2*)data);
   1183   }
   1184 
   1185   T2* GetPtrAt(int32_t nIndex) { return (T2*)m_Data.GetAt(nIndex); }
   1186 
   1187  protected:
   1188   T1 m_Data;
   1189 };
   1190 typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_FILESIZE)>,
   1191                               FX_FILESIZE> CFX_FileSizeListArray;
   1192 
   1193 typedef enum {
   1194   Ready,
   1195   ToBeContinued,
   1196   Found,
   1197   NotFound,
   1198   Failed,
   1199   Done
   1200 } FX_ProgressiveStatus;
   1201 #define ProgressiveStatus FX_ProgressiveStatus
   1202 #ifdef PDF_ENABLE_XFA
   1203 class IFX_Unknown {
   1204  public:
   1205   virtual ~IFX_Unknown() {}
   1206   virtual FX_DWORD Release() = 0;
   1207   virtual FX_DWORD AddRef() = 0;
   1208 };
   1209 #define FX_IsOdd(a) ((a)&1)
   1210 #endif  // PDF_ENABLE_XFA
   1211 
   1212 class CFX_Vector_3by1 {
   1213  public:
   1214   CFX_Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {}
   1215 
   1216   CFX_Vector_3by1(FX_FLOAT a1, FX_FLOAT b1, FX_FLOAT c1)
   1217       : a(a1), b(b1), c(c1) {}
   1218 
   1219   FX_FLOAT a;
   1220   FX_FLOAT b;
   1221   FX_FLOAT c;
   1222 };
   1223 class CFX_Matrix_3by3 {
   1224  public:
   1225   CFX_Matrix_3by3()
   1226       : a(0.0f),
   1227         b(0.0f),
   1228         c(0.0f),
   1229         d(0.0f),
   1230         e(0.0f),
   1231         f(0.0f),
   1232         g(0.0f),
   1233         h(0.0f),
   1234         i(0.0f) {}
   1235 
   1236   CFX_Matrix_3by3(FX_FLOAT a1,
   1237                   FX_FLOAT b1,
   1238                   FX_FLOAT c1,
   1239                   FX_FLOAT d1,
   1240                   FX_FLOAT e1,
   1241                   FX_FLOAT f1,
   1242                   FX_FLOAT g1,
   1243                   FX_FLOAT h1,
   1244                   FX_FLOAT i1)
   1245       : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1) {}
   1246 
   1247   CFX_Matrix_3by3 Inverse();
   1248 
   1249   CFX_Matrix_3by3 Multiply(const CFX_Matrix_3by3& m);
   1250 
   1251   CFX_Vector_3by1 TransformVector(const CFX_Vector_3by1& v);
   1252 
   1253   FX_FLOAT a;
   1254   FX_FLOAT b;
   1255   FX_FLOAT c;
   1256   FX_FLOAT d;
   1257   FX_FLOAT e;
   1258   FX_FLOAT f;
   1259   FX_FLOAT g;
   1260   FX_FLOAT h;
   1261   FX_FLOAT i;
   1262 };
   1263 
   1264 #endif  // CORE_INCLUDE_FXCRT_FX_BASIC_H_
   1265