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