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