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