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