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