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