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