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