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 
AppendString(const CFX_ByteStringC & str)47   void AppendString(const CFX_ByteStringC& str) {
48     AppendBlock(str.GetPtr(), str.GetLength());
49   }
50 
AppendByte(uint8_t byte)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 
GetBuffer()68   uint8_t* GetBuffer() const { return m_pBuffer; }
69 
GetSize()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 
AppendChar(int ch)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 
GetLength()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 
GetLength()124   FX_STRSIZE GetLength() const { return m_DataSize / sizeof(FX_WCHAR); }
125 
GetBuffer()126   FX_WCHAR* GetBuffer() const { return (FX_WCHAR*)m_pBuffer; }
127 
Delete(int start_index,int count)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:
CFX_ArchiveSaver()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 
GetLength()158   intptr_t GetLength() { return m_SavingBuf.GetSize(); }
159 
GetBuffer()160   const uint8_t* GetBuffer() { return m_SavingBuf.GetBuffer(); }
161 
SetStream(IFX_FileStream * pStream)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);
~IFX_BufferArchive()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:
CFX_UTF8Decoder()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 
ClearStatus()263   void ClearStatus() { m_PendingBytes = 0; }
264 
GetResult()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:
CFX_UTF8Encoder()277   CFX_UTF8Encoder() {}
278 
279   void Input(FX_WCHAR unicode);
AppendStr(const CFX_ByteStringC & str)280   void AppendStr(const CFX_ByteStringC& str) { m_Buffer << str; }
GetResult()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:
CFX_ArrayTemplate()319   CFX_ArrayTemplate() : CFX_BasicArray(sizeof(TYPE)) {}
320 
GetSize()321   int GetSize() const { return m_nSize; }
322 
GetUpperBound()323   int GetUpperBound() const { return m_nSize - 1; }
324 
SetSize(int nNewSize)325   FX_BOOL SetSize(int nNewSize) { return CFX_BasicArray::SetSize(nNewSize); }
326 
RemoveAll()327   void RemoveAll() { SetSize(0); }
328 
GetAt(int nIndex)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 
SetAt(int nIndex,TYPE newElement)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 
ElementAt(int nIndex)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 
GetData()351   const TYPE* GetData() const { return (const TYPE*)m_pData; }
352 
GetData()353   TYPE* GetData() { return (TYPE*)m_pData; }
354 
SetAtGrow(int nIndex,TYPE newElement)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 
Add(TYPE newElement)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 
Append(const CFX_ArrayTemplate & src)377   FX_BOOL Append(const CFX_ArrayTemplate& src) {
378     return CFX_BasicArray::Append(src);
379   }
380 
Copy(const CFX_ArrayTemplate & src)381   FX_BOOL Copy(const CFX_ArrayTemplate& src) {
382     return CFX_BasicArray::Copy(src);
383   }
384 
GetDataPtr(int index)385   TYPE* GetDataPtr(int index) {
386     return (TYPE*)CFX_BasicArray::GetDataPtr(index);
387   }
388 
AddSpace()389   TYPE* AddSpace() { return (TYPE*)CFX_BasicArray::InsertSpaceAt(m_nSize, 1); }
390 
InsertSpaceAt(int nIndex,int nCount)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 
InsertAt(int nStartIndex,const CFX_BasicArray * pNewArray)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:
CFX_ObjectArray()451   CFX_ObjectArray() : CFX_BasicArray(sizeof(ObjectClass)) {}
452 
~CFX_ObjectArray()453   ~CFX_ObjectArray() { RemoveAll(); }
454 
Add(const ObjectClass & data)455   void Add(const ObjectClass& data) {
456     new ((void*)InsertSpaceAt(m_nSize, 1)) ObjectClass(data);
457   }
458 
Add()459   ObjectClass& Add() {
460     return *(ObjectClass*)new ((void*)InsertSpaceAt(m_nSize, 1)) ObjectClass();
461   }
462 
AddSpace()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 
GetSize()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 
GetDataPtr(int index)532   ObjectClass* GetDataPtr(int index) {
533     return (ObjectClass*)CFX_BasicArray::GetDataPtr(index);
534   }
535 
RemoveAt(int index)536   void RemoveAt(int index) {
537     FXSYS_assert(index < m_nSize);
538     ((ObjectClass*)GetDataPtr(index))->~ObjectClass();
539     CFX_BasicArray::RemoveAt(index, 1);
540   }
541 
RemoveAll()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 
GetSize()569   int GetSize() const { return m_DataSize; }
570 
GetSegmentSize()571   int GetSegmentSize() const { return m_SegmentSize; }
572 
GetUnitSize()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)
CFX_BaseSegmentedArray(sizeof (ElementType),segment_units,index_size)605       : CFX_BaseSegmentedArray(sizeof(ElementType), segment_units, index_size) {
606   }
607 
Add(ElementType data)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:
CFX_FixedBufGrow()619   CFX_FixedBufGrow() : m_pData(NULL) {}
CFX_FixedBufGrow(int data_size)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   }
SetDataSize(int data_size)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   }
~CFX_FixedBufGrow()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 
GetCount()658   int GetCount() const { return m_nCount; }
659 
IsEmpty()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 
SetAt(void * key,void * newValue)668   void SetAt(void* key, void* newValue) { (*this)[key] = newValue; }
669 
670   FX_BOOL RemoveKey(void* key);
671 
672   void RemoveAll();
673 
GetStartPosition()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 
GetHashTableSize()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:
CFX_MapPtrTemplate()711   CFX_MapPtrTemplate() : CFX_MapPtrToPtr(10) {}
712 
Lookup(KeyType key,ValueType & rValue)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 
SetAt(KeyType key,ValueType newValue)726   void SetAt(KeyType key, ValueType newValue) {
727     CFX_MapPtrToPtr::SetAt((void*)(uintptr_t)key, (void*)(uintptr_t)newValue);
728   }
729 
RemoveKey(KeyType key)730   FX_BOOL RemoveKey(KeyType key) {
731     return CFX_MapPtrToPtr::RemoveKey((void*)(uintptr_t)key);
732   }
733 
GetNextAssoc(FX_POSITION & rNextPosition,KeyType & rKey,ValueType & rValue)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 
GetHeadPosition()787   FX_POSITION GetHeadPosition() const { return (FX_POSITION)m_pNodeHead; }
788 
GetTailPosition()789   FX_POSITION GetTailPosition() const { return (FX_POSITION)m_pNodeTail; }
790 
GetNext(FX_POSITION & rPosition)791   void* GetNext(FX_POSITION& rPosition) const {
792     CNode* pNode = (CNode*)rPosition;
793     rPosition = (FX_POSITION)pNode->pNext;
794     return pNode->data;
795   }
796 
GetPrev(FX_POSITION & rPosition)797   void* GetPrev(FX_POSITION& rPosition) const {
798     CNode* pNode = (CNode*)rPosition;
799     rPosition = (FX_POSITION)pNode->pPrev;
800     return pNode->data;
801   }
802 
GetNextPosition(FX_POSITION pos)803   FX_POSITION GetNextPosition(FX_POSITION pos) const {
804     return ((CNode*)pos)->pNext;
805   }
806 
GetPrevPosition(FX_POSITION pos)807   FX_POSITION GetPrevPosition(FX_POSITION pos) const {
808     return ((CNode*)pos)->pPrev;
809   }
810 
GetAt(FX_POSITION rPosition)811   void* GetAt(FX_POSITION rPosition) const {
812     CNode* pNode = (CNode*)rPosition;
813     return pNode->data;
814   }
815 
GetCount()816   int GetCount() const { return m_nCount; }
817 
818   FX_POSITION AddTail(void* newElement);
819 
820   FX_POSITION AddHead(void* newElement);
821 
SetAt(FX_POSITION pos,void * newElement)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 
LookupPrivateData(void * module_id,void * & pData)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 
IsEOF()915   FX_BOOL IsEOF() { return m_BitPos >= m_BitSize; }
916 
SkipBits(FX_DWORD nBits)917   void SkipBits(FX_DWORD nBits) { m_BitPos += nBits; }
918 
Rewind()919   void Rewind() { m_BitPos = 0; }
920 
GetPos()921   FX_DWORD GetPos() const { return m_BitPos; }
922 
BitsRemaining()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:
CountedObj()941     CountedObj() {}
942 
CountedObj(const CountedObj & src)943     CountedObj(const CountedObj& src) : ObjClass(src) {}
944 
945     int m_RefCount;
946   };
947 
CFX_CountRef()948   CFX_CountRef() { m_pObject = NULL; }
949 
CFX_CountRef(const Ref & ref)950   CFX_CountRef(const Ref& ref) {
951     m_pObject = ref.m_pObject;
952     if (m_pObject) {
953       m_pObject->m_RefCount++;
954     }
955   }
956 
~CFX_CountRef()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 
New()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 
GetObject()1004   const ObjClass* GetObject() const { return m_pObject; }
1005 
1006   operator const ObjClass*() const { return m_pObject; }
1007 
IsNull()1008   FX_BOOL IsNull() const { return !m_pObject; }
1009 
NotNull()1010   FX_BOOL NotNull() const { return !IsNull(); }
1011 
GetModify()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 
SetNull()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:
~IFX_Pause()1045   virtual ~IFX_Pause() {}
1046   virtual FX_BOOL NeedToPauseNow() = 0;
1047 };
1048 
1049 template <typename T>
1050 class CFX_AutoRestorer {
1051  public:
CFX_AutoRestorer(T * location)1052   explicit CFX_AutoRestorer(T* location)
1053       : m_Location(location), m_OldValue(*location) {}
~CFX_AutoRestorer()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 {
operatorFxFreeDeleter1062   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 {
operatorReleaseDeleter1068   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:
CFX_SortListArray()1083   CFX_SortListArray() : m_CurList(0) {}
1084 
~CFX_SortListArray()1085   ~CFX_SortListArray() { Clear(); }
1086 
Clear()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 
Append(int32_t nStart,int32_t nCount)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 
GetAt(int32_t nIndex)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:
Append(const DataList & list)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:
Clear()1175   void Clear() { m_Data.Clear(); }
1176 
Add(int32_t nStart,int32_t nCount)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 
GetPtrAt(int32_t nIndex)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:
~IFX_Unknown()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:
CFX_Vector_3by1()1214   CFX_Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {}
1215 
CFX_Vector_3by1(FX_FLOAT a1,FX_FLOAT b1,FX_FLOAT c1)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:
CFX_Matrix_3by3()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 
CFX_Matrix_3by3(FX_FLOAT a1,FX_FLOAT b1,FX_FLOAT c1,FX_FLOAT d1,FX_FLOAT e1,FX_FLOAT f1,FX_FLOAT g1,FX_FLOAT h1,FX_FLOAT i1)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