Merge to XFA: Fix IWYU in fxcrt headers.
[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 _FX_BASIC_H_
8 #define _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 : public CFX_Object
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(FX_BYTE byte, FX_STRSIZE count);
45
46     void                                        AppendString(FX_BSTR str)
47     {
48         AppendBlock(str.GetPtr(), str.GetLength());
49     }
50
51     inline void                         AppendByte(FX_BYTE 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     FX_LPBYTE                           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     FX_LPBYTE                           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 = (FX_BSTR str);
99
100     void                                        AppendChar(int ch)
101     {
102         AppendByte((FX_BYTE)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 << (FX_BSTR 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 = (FX_LPCWSTR lpsz);
125
126     void                                        operator = (FX_WSTR 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 << (FX_LPCWSTR lpsz);
135
136     CFX_WideTextBuf&            operator << (FX_WSTR 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_LPWSTR                           GetBuffer() const
147     {
148         return (FX_LPWSTR)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 : public CFX_Object
159 {
160 public:
161     CFX_ArchiveSaver() : m_pStream(NULL) {}
162
163     CFX_ArchiveSaver&           operator << (FX_BYTE 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 << (FX_BSTR bstr);
174
175     CFX_ArchiveSaver&           operator << (FX_LPCWSTR bstr);
176
177     CFX_ArchiveSaver&           operator << (const CFX_WideString& wstr);
178
179     void                                        Write(const void* pData, FX_STRSIZE dwSize);
180
181     FX_INTPTR                           GetLength()
182     {
183         return m_SavingBuf.GetSize();
184     }
185
186     FX_LPCBYTE                          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 : public CFX_Object
202 {
203 public:
204
205     CFX_ArchiveLoader(FX_LPCBYTE pData, FX_DWORD dwSize);
206
207     CFX_ArchiveLoader&          operator >> (FX_BYTE& 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     FX_LPCBYTE                          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     FX_INT32                            AppendBlock(const void* pBuf, size_t size);
245
246     FX_INT32                            AppendByte(FX_BYTE byte);
247
248     FX_INT32                            AppendDWord(FX_DWORD i);
249
250
251     FX_INT32                            AppendString(FX_BSTR 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     FX_LPBYTE                           m_pBuffer;
260
261     FX_STRSIZE                          m_Length;
262 };
263 class CFX_FileBufferArchive : public IFX_BufferArchive, public CFX_Object
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(FX_LPCWSTR filename);
273
274     FX_BOOL                                     AttachFile(FX_LPCSTR 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(FX_INT32 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     FX_INT32            (*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(FX_BYTE 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(FX_BSTR 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 : public CFX_Object
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     FX_LPBYTE           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     FX_LPBYTE           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<FX_BYTE>              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<FX_INT32>             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     FX_INT32            Append(const CFX_ObjectArray& src, FX_INT32 nStart = 0, FX_INT32 nCount = -1)
578     {
579         if (nCount == 0) {
580             return 0;
581         }
582         FX_INT32 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 (FX_INT32 i = nStart; i < nSize; i ++, pStartObj++) {
601             new ((void*)pStartObj) ObjectClass(src[i]);
602         }
603         return nCount;
604     }
605
606     FX_INT32            Copy(const CFX_ObjectArray& src, FX_INT32 nStart = 0, FX_INT32 nCount = -1)
607     {
608         if (nCount == 0) {
609             return 0;
610         }
611         FX_INT32 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 (FX_INT32 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 : public CFX_Object
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     FX_BYTE                     m_IndexSize;
708
709     FX_BYTE                     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(FX_LPCBYTE 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 : public CFX_Object
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_memset32(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_memset32(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 template <class DataType>
777 class CFX_TempBuf
778 {
779 public:
780     CFX_TempBuf(int size)
781     {
782         m_pData = FX_Alloc(DataType, size);
783     }
784     ~CFX_TempBuf()
785     {
786         if (m_pData) {
787             FX_Free(m_pData);
788         }
789     }
790     DataType&   operator[](int i)
791     {
792         FXSYS_assert(m_pData != NULL);
793         return m_pData[i];
794     }
795     operator DataType*()
796     {
797         return m_pData;
798     }
799 private:
800     DataType*           m_pData;
801 };
802 class CFX_MapPtrToPtr : public CFX_Object
803 {
804 protected:
805
806     struct CAssoc {
807
808         CAssoc* pNext;
809
810         void* key;
811
812         void* value;
813     };
814 public:
815     CFX_MapPtrToPtr(int nBlockSize = 10);
816
817     ~CFX_MapPtrToPtr();
818
819     int GetCount() const
820     {
821         return m_nCount;
822     }
823
824     FX_BOOL IsEmpty() const
825     {
826         return m_nCount == 0;
827     }
828
829     FX_BOOL Lookup(void* key, void*& rValue) const;
830
831     void* GetValueAt(void* key) const;
832
833     void*& operator[](void* key);
834
835     void SetAt(void* key, void* newValue)
836     {
837         (*this)[key] = newValue;
838     }
839
840     FX_BOOL RemoveKey(void* key);
841
842     void RemoveAll();
843
844     FX_POSITION GetStartPosition() const
845     {
846         return (m_nCount == 0) ? NULL : (FX_POSITION) - 1;
847     }
848
849     void GetNextAssoc(FX_POSITION& rNextPosition, void*& rKey, void*& rValue) const;
850
851     FX_DWORD GetHashTableSize() const
852     {
853         return m_nHashTableSize;
854     }
855
856     void InitHashTable(FX_DWORD hashSize, FX_BOOL bAllocNow = TRUE);
857 protected:
858
859     CAssoc** m_pHashTable;
860
861     FX_DWORD m_nHashTableSize;
862
863     int m_nCount;
864
865     CAssoc* m_pFreeList;
866
867     struct CFX_Plex* m_pBlocks;
868
869     int m_nBlockSize;
870
871     FX_DWORD HashKey(void* key) const;
872
873     CAssoc* NewAssoc();
874
875     void FreeAssoc(CAssoc* pAssoc);
876
877     CAssoc* GetAssocAt(void* key, FX_DWORD& hash) const;
878 };
879 template <class KeyType, class ValueType>
880 class CFX_MapPtrTemplate : public CFX_MapPtrToPtr
881 {
882 public:
883     CFX_MapPtrTemplate() : CFX_MapPtrToPtr(10) {}
884
885     FX_BOOL     Lookup(KeyType key, ValueType& rValue) const
886     {
887         FX_LPVOID pValue = NULL;
888         if (!CFX_MapPtrToPtr::Lookup((void*)(FX_UINTPTR)key, pValue)) {
889             return FALSE;
890         }
891         rValue = (ValueType)(FX_UINTPTR)pValue;
892         return TRUE;
893     }
894
895     ValueType& operator[](KeyType key)
896     {
897         return (ValueType&)CFX_MapPtrToPtr::operator []((void*)(FX_UINTPTR)key);
898     }
899
900     void SetAt(KeyType key, ValueType newValue)
901     {
902         CFX_MapPtrToPtr::SetAt((void*)(FX_UINTPTR)key, (void*)(FX_UINTPTR)newValue);
903     }
904
905     FX_BOOL     RemoveKey(KeyType key)
906     {
907         return CFX_MapPtrToPtr::RemoveKey((void*)(FX_UINTPTR)key);
908     }
909
910     void GetNextAssoc(FX_POSITION& rNextPosition, KeyType& rKey, ValueType& rValue) const
911     {
912         void* pKey = NULL;
913         void* pValue = NULL;
914         CFX_MapPtrToPtr::GetNextAssoc(rNextPosition, pKey, pValue);
915         rKey = (KeyType)(FX_UINTPTR)pKey;
916         rValue = (ValueType)(FX_UINTPTR)pValue;
917     }
918 };
919 class CFX_CMapDWordToDWord : public CFX_Object
920 {
921 public:
922
923     FX_BOOL                     Lookup(FX_DWORD key, FX_DWORD& value) const;
924
925     void                        SetAt(FX_DWORD key, FX_DWORD value);
926
927     void                        EstimateSize(FX_DWORD size, FX_DWORD grow_by);
928
929     FX_POSITION         GetStartPosition() const;
930
931     void                        GetNextAssoc(FX_POSITION& pos, FX_DWORD& key, FX_DWORD& value) const;
932 protected:
933
934     CFX_BinaryBuf       m_Buffer;
935 };
936 class CFX_MapByteStringToPtr : public CFX_Object
937 {
938 protected:
939
940     struct CAssoc {
941
942         CAssoc* pNext;
943
944         FX_DWORD nHashValue;
945
946         CFX_ByteString key;
947
948         void* value;
949     };
950 public:
951     CFX_MapByteStringToPtr(int nBlockSize = 10);
952
953     int GetCount() const
954     {
955         return m_nCount;
956     }
957
958     FX_BOOL IsEmpty() const
959     {
960         return m_nCount == 0;
961     }
962
963     FX_BOOL Lookup(FX_BSTR key, void*& rValue) const;
964
965     void*& operator[](FX_BSTR key);
966
967     void SetAt(FX_BSTR key, void* newValue)
968     {
969         (*this)[key] = newValue;
970     }
971
972     FX_BOOL RemoveKey(FX_BSTR key);
973
974     void RemoveAll();
975
976     FX_POSITION GetStartPosition() const
977     {
978         return (m_nCount == 0) ? NULL : (FX_POSITION) - 1;
979     }
980
981     void GetNextAssoc(FX_POSITION& rNextPosition, CFX_ByteString& rKey, void*& rValue) const;
982
983     FX_LPVOID           GetNextValue(FX_POSITION& rNextPosition) const;
984
985     FX_DWORD GetHashTableSize() const
986     {
987         return m_nHashTableSize;
988     }
989
990     void InitHashTable(FX_DWORD hashSize, FX_BOOL bAllocNow = TRUE);
991
992     FX_DWORD HashKey(FX_BSTR key) const;
993 protected:
994
995     CAssoc** m_pHashTable;
996
997     FX_DWORD m_nHashTableSize;
998
999     int m_nCount;
1000
1001     CAssoc* m_pFreeList;
1002
1003     struct CFX_Plex* m_pBlocks;
1004
1005     int m_nBlockSize;
1006
1007     CAssoc* NewAssoc();
1008
1009     void FreeAssoc(CAssoc* pAssoc);
1010
1011     CAssoc* GetAssocAt(FX_BSTR key, FX_DWORD& hash) const;
1012 public:
1013
1014     ~CFX_MapByteStringToPtr();
1015 };
1016 class CFX_CMapByteStringToPtr : public CFX_Object
1017 {
1018 public:
1019     CFX_CMapByteStringToPtr();
1020
1021     ~CFX_CMapByteStringToPtr();
1022
1023     void                        RemoveAll();
1024
1025     FX_POSITION         GetStartPosition() const;
1026
1027     void                        GetNextAssoc(FX_POSITION& rNextPosition, CFX_ByteString& rKey, void*& rValue) const;
1028
1029     FX_LPVOID           GetNextValue(FX_POSITION& rNextPosition) const;
1030
1031     FX_BOOL                     Lookup(FX_BSTR key, void*& rValue) const;
1032
1033     void                        SetAt(FX_BSTR key, void* value);
1034
1035     void                        RemoveKey(FX_BSTR key);
1036
1037     int                         GetCount() const;
1038
1039     void                        AddValue(FX_BSTR key, void* pValue);
1040 private:
1041
1042     CFX_BaseSegmentedArray                      m_Buffer;
1043 };
1044 class CFX_PtrList : public CFX_Object
1045 {
1046 protected:
1047
1048     struct CNode {
1049
1050         CNode* pNext;
1051
1052         CNode* pPrev;
1053
1054         void* data;
1055     };
1056 public:
1057     CFX_PtrList(int nBlockSize = 10);
1058
1059     FX_POSITION GetHeadPosition() const
1060     {
1061         return (FX_POSITION)m_pNodeHead;
1062     }
1063
1064     FX_POSITION GetTailPosition() const
1065     {
1066         return (FX_POSITION)m_pNodeTail;
1067     }
1068
1069     void*       GetNext(FX_POSITION& rPosition) const
1070     {
1071         CNode* pNode = (CNode*) rPosition;
1072         rPosition = (FX_POSITION) pNode->pNext;
1073         return pNode->data;
1074     }
1075
1076     void*       GetPrev(FX_POSITION& rPosition) const
1077     {
1078         CNode* pNode = (CNode*) rPosition;
1079         rPosition = (FX_POSITION) pNode->pPrev;
1080         return pNode->data;
1081     }
1082
1083     FX_POSITION GetNextPosition(FX_POSITION pos) const
1084     {
1085         return ((CNode*)pos)->pNext;
1086     }
1087
1088     FX_POSITION GetPrevPosition(FX_POSITION pos) const
1089     {
1090         return ((CNode*)pos)->pPrev;
1091     }
1092
1093     void*       GetAt(FX_POSITION rPosition) const
1094     {
1095         CNode* pNode = (CNode*) rPosition;
1096         return pNode->data;
1097     }
1098
1099     int         GetCount() const
1100     {
1101         return m_nCount;
1102     }
1103
1104     FX_POSITION AddTail(void* newElement);
1105
1106     FX_POSITION AddHead(void* newElement);
1107
1108     void        SetAt(FX_POSITION pos, void* newElement)
1109     {
1110         CNode* pNode = (CNode*) pos;
1111         pNode->data = newElement;
1112     }
1113
1114     FX_POSITION InsertAfter(FX_POSITION pos, void* newElement);
1115
1116     FX_POSITION Find(void* searchValue, FX_POSITION startAfter = NULL ) const;
1117
1118     FX_POSITION FindIndex(int index) const;
1119
1120     void        RemoveAt(FX_POSITION pos);
1121
1122     void        RemoveAll();
1123 protected:
1124
1125     CNode* m_pNodeHead;
1126
1127     CNode* m_pNodeTail;
1128
1129     int m_nCount;
1130
1131     CNode* m_pNodeFree;
1132
1133     struct CFX_Plex* m_pBlocks;
1134
1135     int m_nBlockSize;
1136
1137     CNode* NewNode(CNode* pPrev, CNode* pNext);
1138
1139     void FreeNode(CNode* pNode);
1140 public:
1141
1142     ~CFX_PtrList();
1143 };
1144 typedef void (*PD_CALLBACK_FREEDATA)(FX_LPVOID pData);
1145 struct FX_PRIVATEDATA {
1146
1147     void                                        FreeData();
1148
1149     FX_LPVOID                           m_pModuleId;
1150
1151     FX_LPVOID                           m_pData;
1152
1153     PD_CALLBACK_FREEDATA        m_pCallback;
1154
1155     FX_BOOL                                     m_bSelfDestruct;
1156 };
1157 class CFX_PrivateData
1158 {
1159 public:
1160
1161     ~CFX_PrivateData();
1162
1163     void                                        ClearAll();
1164
1165     void                                        SetPrivateData(FX_LPVOID module_id, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback);
1166
1167     void                                        SetPrivateObj(FX_LPVOID module_id, CFX_DestructObject* pObj);
1168
1169     FX_LPVOID                           GetPrivateData(FX_LPVOID module_id);
1170
1171     FX_BOOL                                     LookupPrivateData(FX_LPVOID module_id, FX_LPVOID &pData) const
1172     {
1173         if (!module_id) {
1174             return FALSE;
1175         }
1176         FX_DWORD nCount = m_DataList.GetSize();
1177         for (FX_DWORD n = 0; n < nCount; n ++) {
1178             if (m_DataList[n].m_pModuleId == module_id) {
1179                 pData = m_DataList[n].m_pData;
1180                 return TRUE;
1181             }
1182         }
1183         return FALSE;
1184     }
1185
1186     FX_BOOL                                     RemovePrivateData(FX_LPVOID module_id);
1187 protected:
1188
1189     CFX_ArrayTemplate<FX_PRIVATEDATA>   m_DataList;
1190
1191     void                                        AddData(FX_LPVOID module_id, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct);
1192 };
1193 class CFX_BitStream : public CFX_Object
1194 {
1195 public:
1196
1197     void                                Init(FX_LPCBYTE pData, FX_DWORD dwSize);
1198
1199
1200     FX_DWORD                    GetBits(FX_DWORD nBits);
1201
1202     void                                ByteAlign();
1203
1204     FX_BOOL                             IsEOF()
1205     {
1206         return m_BitPos >= m_BitSize;
1207     }
1208
1209     void                                SkipBits(FX_DWORD nBits)
1210     {
1211         m_BitPos += nBits;
1212     }
1213
1214     void                                Rewind()
1215     {
1216         m_BitPos = 0;
1217     }
1218 protected:
1219
1220     FX_DWORD                    m_BitPos;
1221
1222     FX_DWORD                    m_BitSize;
1223
1224     FX_LPCBYTE                  m_pData;
1225 };
1226 template <class ObjClass> class CFX_CountRef : public CFX_Object
1227 {
1228 public:
1229
1230     typedef CFX_CountRef<ObjClass> Ref;
1231
1232     class CountedObj : public ObjClass
1233     {
1234     public:
1235
1236         CountedObj() {}
1237
1238         CountedObj(const CountedObj& src) : ObjClass(src) {}
1239
1240         int                     m_RefCount;
1241     };
1242
1243     CFX_CountRef()
1244     {
1245         m_pObject = NULL;
1246     }
1247
1248     CFX_CountRef(const Ref& ref)
1249     {
1250         m_pObject = ref.m_pObject;
1251         if (m_pObject) {
1252             m_pObject->m_RefCount ++;
1253         }
1254     }
1255
1256     ~CFX_CountRef()
1257     {
1258         if (!m_pObject) {
1259             return;
1260         }
1261         m_pObject->m_RefCount --;
1262         if (m_pObject->m_RefCount <= 0) {
1263             delete m_pObject;
1264         }
1265     }
1266
1267     ObjClass*                   New()
1268     {
1269         if (m_pObject) {
1270             m_pObject->m_RefCount --;
1271             if (m_pObject->m_RefCount <= 0) {
1272                 delete m_pObject;
1273             }
1274             m_pObject = NULL;
1275         }
1276         m_pObject = FX_NEW CountedObj;
1277         if (!m_pObject) {
1278             return NULL;
1279         }
1280         m_pObject->m_RefCount = 1;
1281         return m_pObject;
1282     }
1283
1284     void                                operator = (const Ref& ref)
1285     {
1286         if (ref.m_pObject) {
1287             ref.m_pObject->m_RefCount ++;
1288         }
1289         if (m_pObject) {
1290             m_pObject->m_RefCount --;
1291             if (m_pObject->m_RefCount <= 0) {
1292                 delete m_pObject;
1293             }
1294         }
1295         m_pObject = ref.m_pObject;
1296     }
1297
1298     void                                operator = (void* p)
1299     {
1300         FXSYS_assert(p == 0);
1301         if (m_pObject == NULL) {
1302             return;
1303         }
1304         m_pObject->m_RefCount --;
1305         if (m_pObject->m_RefCount <= 0) {
1306             delete m_pObject;
1307         }
1308         m_pObject = NULL;
1309     }
1310
1311     const ObjClass*             GetObject() const
1312     {
1313         return m_pObject;
1314     }
1315
1316     operator                    const ObjClass*() const
1317     {
1318         return m_pObject;
1319     }
1320
1321     FX_BOOL                             IsNull() const
1322     {
1323         return m_pObject == NULL;
1324     }
1325
1326     FX_BOOL                             NotNull() const
1327     {
1328         return m_pObject != NULL;
1329     }
1330
1331     ObjClass*                   GetModify()
1332     {
1333         if (m_pObject == NULL) {
1334             m_pObject = FX_NEW CountedObj;
1335             if (m_pObject) {
1336                 m_pObject->m_RefCount = 1;
1337             }
1338         } else if (m_pObject->m_RefCount > 1) {
1339             m_pObject->m_RefCount --;
1340             CountedObj* pOldObject = m_pObject;
1341             m_pObject = NULL;
1342             m_pObject = FX_NEW CountedObj(*pOldObject);
1343             if (m_pObject) {
1344                 m_pObject->m_RefCount = 1;
1345             }
1346         }
1347         return m_pObject;
1348     }
1349
1350     void                                SetNull()
1351     {
1352         if (m_pObject == NULL) {
1353             return;
1354         }
1355         m_pObject->m_RefCount --;
1356         if (m_pObject->m_RefCount <= 0) {
1357             delete m_pObject;
1358         }
1359         m_pObject = NULL;
1360     }
1361
1362     FX_BOOL                             operator == (const Ref& ref) const
1363     {
1364         return m_pObject == ref.m_pObject;
1365     }
1366 protected:
1367
1368     CountedObj*                 m_pObject;
1369 };
1370 class IFX_Pause
1371 {
1372 public:
1373     virtual ~IFX_Pause() { }
1374     virtual FX_BOOL     NeedToPauseNow() = 0;
1375 };
1376 class CFX_DataFilter : public CFX_Object
1377 {
1378 public:
1379
1380     virtual ~CFX_DataFilter();
1381
1382     void                        SetDestFilter(CFX_DataFilter* pFilter);
1383
1384     FX_BOOL                     IsEOF() const
1385     {
1386         return m_bEOF;
1387     }
1388
1389     FX_DWORD            GetSrcPos()
1390     {
1391         return m_SrcPos;
1392     }
1393
1394     void                        FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf);
1395
1396     void                        FilterFinish(CFX_BinaryBuf& dest_buf);
1397 protected:
1398
1399     CFX_DataFilter();
1400     virtual void        v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) = 0;
1401     virtual void        v_FilterFinish(CFX_BinaryBuf& dest_buf) = 0;
1402     void                        ReportEOF(FX_DWORD left_input);
1403
1404     FX_BOOL                     m_bEOF;
1405
1406     FX_DWORD            m_SrcPos;
1407
1408     CFX_DataFilter*     m_pDestFilter;
1409 };
1410
1411 template<typename T>
1412 class CFX_AutoRestorer {
1413 public:
1414     explicit CFX_AutoRestorer(T* location) {
1415       m_Location = location;
1416       m_OldValue = *location;
1417     }
1418     ~CFX_AutoRestorer() { *m_Location = m_OldValue; }
1419
1420 private:
1421   T* m_Location;
1422   T m_OldValue;
1423 };
1424
1425 template <class T>
1426 class CFX_SmartPointer
1427 {
1428 public:
1429     CFX_SmartPointer(T *pObj) : m_pObj(pObj) {}
1430     ~CFX_SmartPointer()
1431     {
1432         m_pObj->Release();
1433     }
1434     T* Get(void)
1435     {
1436         return m_pObj;
1437     }
1438     T&          operator *(void)
1439     {
1440         return *m_pObj;
1441     }
1442     T*          operator ->(void)
1443     {
1444         return m_pObj;
1445     }
1446 protected:
1447     T *m_pObj;
1448 };
1449 #define FX_DATALIST_LENGTH      1024
1450 template<size_t unit>
1451 class CFX_SortListArray : public CFX_Object
1452 {
1453 protected:
1454
1455     struct DataList {
1456
1457         FX_INT32        start;
1458
1459         FX_INT32        count;
1460         FX_LPBYTE       data;
1461     };
1462 public:
1463
1464     CFX_SortListArray() : m_CurList(0) {}
1465
1466     ~CFX_SortListArray()
1467     {
1468         Clear();
1469     }
1470
1471
1472     void                        Clear()
1473     {
1474         for (FX_INT32 i = m_DataLists.GetUpperBound(); i >= 0; i--) {
1475             DataList list = m_DataLists.ElementAt(i);
1476             if (list.data) {
1477                 FX_Free(list.data);
1478             }
1479         }
1480         m_DataLists.RemoveAll();
1481         m_CurList = 0;
1482     }
1483
1484     void                        Append(FX_INT32 nStart, FX_INT32 nCount)
1485     {
1486         if (nStart < 0) {
1487             return;
1488         }
1489         while (nCount > 0) {
1490             FX_INT32 temp_count = FX_MIN(nCount, FX_DATALIST_LENGTH);
1491             DataList list;
1492             list.data = FX_Alloc(FX_BYTE, temp_count * unit);
1493             if (!list.data) {
1494                 break;
1495             }
1496             list.start = nStart;
1497             list.count = temp_count;
1498             Append(list);
1499             nCount -= temp_count;
1500             nStart += temp_count;
1501         }
1502     }
1503
1504     FX_LPBYTE           GetAt(FX_INT32 nIndex)
1505     {
1506         if (nIndex < 0) {
1507             return NULL;
1508         }
1509         if (m_CurList < 0 || m_CurList >= m_DataLists.GetSize()) {
1510             return NULL;
1511         }
1512         DataList *pCurList = m_DataLists.GetDataPtr(m_CurList);
1513         if (!pCurList || nIndex < pCurList->start || nIndex >= pCurList->start + pCurList->count) {
1514             pCurList = NULL;
1515             FX_INT32 iStart = 0;
1516             FX_INT32 iEnd = m_DataLists.GetUpperBound();
1517             FX_INT32 iMid = 0;
1518             while (iStart <= iEnd) {
1519                 iMid = (iStart + iEnd) / 2;
1520                 DataList* list = m_DataLists.GetDataPtr(iMid);
1521                 if (nIndex < list->start) {
1522                     iEnd = iMid - 1;
1523                 } else if (nIndex >= list->start + list->count) {
1524                     iStart = iMid + 1;
1525                 } else {
1526                     pCurList = list;
1527                     m_CurList = iMid;
1528                     break;
1529                 }
1530             }
1531         }
1532         return pCurList ? pCurList->data + (nIndex - pCurList->start) * unit : NULL;
1533     }
1534 protected:
1535     void                        Append(const DataList& list)
1536     {
1537         FX_INT32 iStart = 0;
1538         FX_INT32 iEnd = m_DataLists.GetUpperBound();
1539         FX_INT32 iFind = 0;
1540         while (iStart <= iEnd) {
1541             FX_INT32 iMid = (iStart + iEnd) / 2;
1542             DataList* cur_list = m_DataLists.GetDataPtr(iMid);
1543             if (list.start < cur_list->start + cur_list->count) {
1544                 iEnd = iMid - 1;
1545             } else {
1546                 if (iMid == iEnd) {
1547                     iFind = iMid + 1;
1548                     break;
1549                 }
1550                 DataList* next_list = m_DataLists.GetDataPtr(iMid + 1);
1551                 if (list.start < next_list->start) {
1552                     iFind = iMid + 1;
1553                     break;
1554                 } else {
1555                     iStart = iMid + 1;
1556                 }
1557             }
1558         }
1559         m_DataLists.InsertAt(iFind, list);
1560     }
1561     FX_INT32            m_CurList;
1562     CFX_ArrayTemplate<DataList> m_DataLists;
1563 };
1564 template<typename T1, typename T2>
1565 class CFX_ListArrayTemplate : public CFX_Object
1566 {
1567 public:
1568
1569     void                        Clear()
1570     {
1571         m_Data.Clear();
1572     }
1573
1574     void                        Add(FX_INT32 nStart, FX_INT32 nCount)
1575     {
1576         m_Data.Append(nStart, nCount);
1577     }
1578
1579     T2&                         operator [] (FX_INT32 nIndex)
1580     {
1581         FX_LPBYTE data = m_Data.GetAt(nIndex);
1582         FXSYS_assert(data != NULL);
1583         return (T2&)(*(volatile T2*)data);
1584     }
1585
1586     T2*                         GetPtrAt(FX_INT32 nIndex)
1587     {
1588         return (T2*)m_Data.GetAt(nIndex);
1589     }
1590 protected:
1591     T1                  m_Data;
1592 };
1593 typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_FILESIZE)>, FX_FILESIZE>      CFX_FileSizeListArray;
1594 typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_DWORD)>, FX_DWORD>            CFX_DWordListArray;
1595 typedef enum {
1596     Ready,
1597     ToBeContinued,
1598     Found,
1599     NotFound,
1600     Failed,
1601     Done
1602 } FX_ProgressiveStatus;
1603 #define ProgressiveStatus       FX_ProgressiveStatus
1604 #define FX_NAMESPACE_DECLARE(namespace, type)       namespace::type
1605 class IFX_Unknown
1606 {
1607 public:
1608     virtual FX_DWORD    Release() = 0;
1609     virtual FX_DWORD    AddRef() = 0;
1610 };
1611 #define FX_IsOdd(a)     ((a) & 1)
1612
1613 class CFX_Vector_3by1 : public CFX_Object
1614 {
1615 public:
1616
1617     CFX_Vector_3by1() :
1618         a(0.0f), b(0.0f), c(0.0f)
1619     {}
1620
1621     CFX_Vector_3by1(FX_FLOAT a1, FX_FLOAT b1, FX_FLOAT c1):
1622         a(a1), b(b1), c(c1)
1623     {}
1624
1625     FX_FLOAT a;
1626     FX_FLOAT b;
1627     FX_FLOAT c;
1628 };
1629 class CFX_Matrix_3by3 : public CFX_Object
1630 {
1631 public:
1632
1633     CFX_Matrix_3by3():
1634         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)
1635     {}
1636
1637     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) :
1638         a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1)
1639     {}
1640
1641     CFX_Matrix_3by3 Inverse();
1642
1643     CFX_Matrix_3by3 Multiply(const CFX_Matrix_3by3 &m);
1644
1645     CFX_Vector_3by1 TransformVector(const CFX_Vector_3by1 &v);
1646
1647     FX_FLOAT a;
1648     FX_FLOAT b;
1649     FX_FLOAT c;
1650     FX_FLOAT d;
1651     FX_FLOAT e;
1652     FX_FLOAT f;
1653     FX_FLOAT g;
1654     FX_FLOAT h;
1655     FX_FLOAT i;
1656 };
1657
1658 #endif