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