Convert all line endings to LF.
[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
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;
78 protected:
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 };
90 class CFX_ByteTextBuf : public CFX_BinaryBuf
91 {
92 public:
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 };
118 class CFX_WideTextBuf : public CFX_BinaryBuf
119 {
120 public:
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 };
159 class CFX_ArchiveSaver : public CFX_Object
160 {
161 public:
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     }
197 protected:
198
199     CFX_BinaryBuf                       m_SavingBuf;
200
201     IFX_FileStream*                     m_pStream;
202 };
203 class CFX_ArchiveLoader : public CFX_Object
204 {
205 public:
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);
226 protected:
227
228     FX_DWORD                            m_LoadingPos;
229
230     FX_LPCBYTE                          m_pLoadingBuf;
231
232     FX_DWORD                            m_LoadingSize;
233 };
234 class IFX_BufferArchive
235 {
236 public:
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
256 protected:
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 };
269 class CFX_FileBufferArchive : public IFX_BufferArchive, public CFX_Object
270 {
271 public:
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);
281 private:
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 };
289 struct 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 };
300 class CFX_UTF8Decoder
301 {
302 public:
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     }
328 protected:
329
330     int                         m_PendingBytes;
331
332     FX_DWORD            m_PendingChar;
333
334     CFX_WideTextBuf     m_Buffer;
335 };
336 class CFX_UTF8Encoder
337 {
338 public:
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     }
361 protected:
362
363     CFX_ByteTextBuf     m_Buffer;
364
365     FX_DWORD            m_UTF16First;
366 };
367 CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl);
368 CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl);
369 CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI);
370 CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI);
371 class CFX_BasicArray : public CFX_Object
372 {
373 public:
374
375     IFX_Allocator*      m_pAllocator;
376 protected:
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;
395 protected:
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 };
407 template<class TYPE>
408 class CFX_ArrayTemplate : public CFX_BasicArray
409 {
410 public:
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 };
567 typedef CFX_ArrayTemplate<FX_BYTE>              CFX_ByteArray;
568 typedef CFX_ArrayTemplate<FX_WORD>              CFX_WordArray;
569 typedef CFX_ArrayTemplate<FX_DWORD>             CFX_DWordArray;
570 typedef CFX_ArrayTemplate<void*>                CFX_PtrArray;
571 typedef CFX_ArrayTemplate<FX_FILESIZE>  CFX_FileSizeArray;
572 typedef CFX_ArrayTemplate<FX_FLOAT>             CFX_FloatArray;
573 typedef CFX_ArrayTemplate<FX_INT32>             CFX_Int32Array;
574 template <class ObjectClass>
575 class CFX_ObjectArray : public CFX_BasicArray
576 {
577 public:
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 };
690 typedef CFX_ObjectArray<CFX_ByteString> CFX_ByteStringArray;
691 typedef CFX_ObjectArray<CFX_WideString> CFX_WideStringArray;
692 class CFX_BaseSegmentedArray : public CFX_Object
693 {
694 public:
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;
728 private:
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 };
745 template <class ElementType>
746 class CFX_SegmentedArray : public CFX_BaseSegmentedArray
747 {
748 public:
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 };
764 template <class DataType, int FixedSize>
765 class CFX_FixedBufGrow : public CFX_Object
766 {
767 public:
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     }
804 private:
805     IFX_Allocator*      m_pAllocator;
806     DataType            m_Data[FixedSize];
807     DataType*           m_pData;
808 };
809 template <class DataType>
810 class CFX_TempBuf
811 {
812 public:
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     }
832 private:
833     IFX_Allocator*      m_pAllocator;
834     DataType*           m_pData;
835 };
836 class CFX_MapPtrToPtr : public CFX_Object
837 {
838 protected:
839
840     struct CAssoc {
841
842         CAssoc* pNext;
843
844         void* key;
845
846         void* value;
847     };
848 public:
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);
892 protected:
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 };
916 template <class KeyType, class ValueType>
917 class CFX_MapPtrTemplate : public CFX_MapPtrToPtr
918 {
919 public:
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 };
957 class CFX_CMapDWordToDWord : public CFX_Object
958 {
959 public:
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;
972 protected:
973
974     CFX_BinaryBuf       m_Buffer;
975 };
976 class CFX_MapByteStringToPtr : public CFX_Object
977 {
978 protected:
979
980     struct CAssoc {
981
982         CAssoc* pNext;
983
984         FX_DWORD nHashValue;
985
986         CFX_ByteString key;
987
988         void* value;
989     };
990 public:
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;
1034 protected:
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;
1055 public:
1056
1057     ~CFX_MapByteStringToPtr();
1058 };
1059 class CFX_CMapByteStringToPtr : public CFX_Object
1060 {
1061 public:
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);
1084 private:
1085
1086     CFX_BaseSegmentedArray                      m_Buffer;
1087 };
1088 class CFX_PtrList : public CFX_Object
1089 {
1090 protected:
1091
1092     struct CNode {
1093
1094         CNode* pNext;
1095
1096         CNode* pPrev;
1097
1098         void* data;
1099     };
1100 public:
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();
1168 protected:
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);
1187 public:
1188
1189     ~CFX_PtrList();
1190 };
1191 typedef void (*PD_CALLBACK_FREEDATA)(FX_LPVOID pData);
1192 struct 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 };
1204 class CFX_PrivateData
1205 {
1206 public:
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);
1236 protected:
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 };
1242 class CFX_BitStream : public CFX_Object
1243 {
1244 public:
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     }
1267 protected:
1268
1269     FX_DWORD                    m_BitPos;
1270
1271     FX_DWORD                    m_BitSize;
1272
1273     FX_LPCBYTE                  m_pData;
1274 };
1275 template <class ObjClass> class CFX_CountRef : public CFX_Object
1276 {
1277 public:
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     }
1415 protected:
1416
1417     CountedObj*                 m_pObject;
1418 };
1419 class IFX_Pause
1420 {
1421 public:
1422
1423     virtual FX_BOOL     NeedToPauseNow() = 0;
1424 };
1425 class CFX_DataFilter : public CFX_Object
1426 {
1427 public:
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);
1446 protected:
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 };
1459 template <class T>
1460 class CFX_SmartPointer
1461 {
1462 public:
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     }
1480 protected:
1481     T *m_pObj;
1482 };
1483 #define FX_DATALIST_LENGTH      1024
1484 template<size_t unit>
1485 class CFX_SortListArray : public CFX_Object
1486 {
1487 protected:
1488
1489     struct DataList {
1490
1491         FX_INT32        start;
1492
1493         FX_INT32        count;
1494         FX_LPBYTE       data;
1495     };
1496 public:
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     }
1571 protected:
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 };
1601 template<typename T1, typename T2>
1602 class CFX_ListArrayTemplate : public CFX_Object
1603 {
1604 public:
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     }
1627 protected:
1628     T1                  m_Data;
1629 };
1630 typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_FILESIZE)>, FX_FILESIZE>      CFX_FileSizeListArray;
1631 typedef CFX_ListArrayTemplate<CFX_SortListArray<sizeof(FX_DWORD)>, FX_DWORD>            CFX_DWordListArray;
1632 typedef 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