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