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