Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fgas / include / fx_utl.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_UTILS\r
8 #define _FX_UTILS\r
9 class CFX_ThreadLock;\r
10 class CFX_BaseArray;\r
11 template<class baseType> class CFX_BaseArrayTemplate;\r
12 template<class baseType> class CFX_ObjectBaseArrayTemplate;\r
13 class CFX_BaseMassArray;\r
14 class CFX_BaseMassArrayImp;\r
15 template<class baseType> class CFX_MassArrayTemplate;\r
16 template<class baseType> class CFX_ObjectMassArrayTemplate;\r
17 class CFX_BaseDiscreteArray;\r
18 template<class baseType> class CFX_DiscreteArrayTemplate;\r
19 class CFX_BaseStack;\r
20 template<class baseType> class CFX_StackTemplate;\r
21 template<class baseType> class CFX_ObjectStackTemplate;\r
22 template<class baseType> class CFX_CPLTreeNode;\r
23 template<class baseType> class CFX_CPLTree;\r
24 class CFX_ThreadLock\r
25 {\r
26 public:\r
27     CFX_ThreadLock();\r
28     virtual ~CFX_ThreadLock();\r
29     void        Lock();\r
30     void        Unlock();\r
31 private:\r
32     FX_LPVOID   m_pData;\r
33 };\r
34 class CFX_BaseArray : public CFX_Target\r
35 {\r
36 protected:\r
37     CFX_BaseArray(int32_t iGrowSize, int32_t iBlockSize);\r
38     ~CFX_BaseArray();\r
39     int32_t     GetSize() const;\r
40     int32_t     GetBlockSize() const;\r
41     FX_LPBYTE   AddSpaceTo(int32_t index);\r
42     FX_LPBYTE   GetAt(int32_t index) const;\r
43     FX_LPBYTE   GetBuffer() const;\r
44     int32_t     Append(const CFX_BaseArray &src, int32_t iStart = 0, int32_t iCount = -1);\r
45     int32_t     Copy(const CFX_BaseArray &src, int32_t iStart = 0, int32_t iCount = -1);\r
46     int32_t     RemoveLast(int32_t iCount = -1);\r
47     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE);\r
48     FX_LPVOID   m_pData;\r
49 };\r
50 template<class baseType>\r
51 class CFX_BaseArrayTemplate : public CFX_BaseArray\r
52 {\r
53 public:\r
54     CFX_BaseArrayTemplate(int32_t iGrowSize = 100) : CFX_BaseArray(iGrowSize, sizeof(baseType)) {}\r
55     CFX_BaseArrayTemplate(int32_t iGrowSize, int32_t iBlockSize) : CFX_BaseArray(iGrowSize, iBlockSize) {}\r
56     int32_t     GetSize() const\r
57     {\r
58         return CFX_BaseArray::GetSize();\r
59     }\r
60     int32_t     GetBlockSize() const\r
61     {\r
62         return CFX_BaseArray::GetBlockSize();\r
63     }\r
64     baseType*   AddSpace()\r
65     {\r
66         return (baseType*)CFX_BaseArray::AddSpaceTo(CFX_BaseArray::GetSize());\r
67     }\r
68     int32_t     Add(const baseType &element)\r
69     {\r
70         int32_t index = CFX_BaseArray::GetSize();\r
71         *(baseType*)CFX_BaseArray::AddSpaceTo(index) = element;\r
72         return index;\r
73     }\r
74     baseType*   GetBuffer() const\r
75     {\r
76         return (baseType*)CFX_BaseArray::GetBuffer();\r
77     }\r
78     baseType&   GetAt(int32_t index) const\r
79     {\r
80         return *(baseType*)CFX_BaseArray::GetAt(index);\r
81     }\r
82     baseType*   GetPtrAt(int32_t index) const\r
83     {\r
84         return (baseType*)CFX_BaseArray::GetAt(index);\r
85     }\r
86     void                SetAt(int32_t index, const baseType &element)\r
87     {\r
88         *(baseType*)CFX_BaseArray::GetAt(index) = element;\r
89     }\r
90     void                SetAtGrow(int32_t index, const baseType &element)\r
91     {\r
92         *(baseType*)CFX_BaseArray::AddSpaceTo(index) = element;\r
93     }\r
94     int32_t     Append(const CFX_BaseArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
95     {\r
96         return CFX_BaseArray::Append(src, iStart, iCount);\r
97     }\r
98     int32_t     Copy(const CFX_BaseArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
99     {\r
100         return CFX_BaseArray::Copy(src, iStart, iCount);\r
101     }\r
102     int32_t     RemoveLast(int32_t iCount = -1)\r
103     {\r
104         return CFX_BaseArray::RemoveLast(iCount);\r
105     }\r
106     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE)\r
107     {\r
108         CFX_BaseArray::RemoveAll(bLeaveMemory);\r
109     }\r
110 };\r
111 typedef CFX_BaseArrayTemplate<FX_LPVOID>        CFDE_PtrArray;\r
112 typedef CFX_BaseArrayTemplate<FX_DWORD>         CFDE_DWordArray;\r
113 typedef CFX_BaseArrayTemplate<FX_WORD>          CFDE_WordArray;\r
114 template<class baseType>\r
115 class CFX_ObjectBaseArrayTemplate : public CFX_BaseArray\r
116 {\r
117 public:\r
118     CFX_ObjectBaseArrayTemplate(int32_t iGrowSize = 100) : CFX_BaseArray(iGrowSize, sizeof(baseType)) {}\r
119     ~CFX_ObjectBaseArrayTemplate()\r
120     {\r
121         RemoveAll(FALSE);\r
122     }\r
123     int32_t     GetSize() const\r
124     {\r
125         return CFX_BaseArray::GetSize();\r
126     }\r
127     int32_t     GetBlockSize() const\r
128     {\r
129         return CFX_BaseArray::GetBlockSize();\r
130     }\r
131     int32_t     Add(const baseType &element)\r
132     {\r
133         int32_t index = CFX_BaseArray::GetSize();\r
134         baseType *p = (baseType*)CFX_BaseArray::AddSpaceTo(index);\r
135         FXTARGET_New ((void*)p)baseType(element);\r
136         return index;\r
137     }\r
138     baseType&   GetAt(int32_t index) const\r
139     {\r
140         return *(baseType*)CFX_BaseArray::GetAt(index);\r
141     }\r
142     baseType*   GetPtrAt(int32_t index) const\r
143     {\r
144         return (baseType*)CFX_BaseArray::GetAt(index);\r
145     }\r
146     int32_t     Append(const CFX_ObjectBaseArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
147     {\r
148         FXSYS_assert(GetBlockSize() == src.GetBlockSize());\r
149         if (iCount == 0) {\r
150             return 0;\r
151         }\r
152         int32_t iSize = src.GetSize();\r
153         FXSYS_assert(iStart > -1 && iStart < iSize);\r
154         if (iCount < 0) {\r
155             iCount = iSize;\r
156         }\r
157         if (iStart + iCount > iSize) {\r
158             iCount = iSize - iStart;\r
159         }\r
160         if (iCount < 1) {\r
161             return 0;\r
162         }\r
163         iSize = CFX_BaseArray::GetSize();\r
164         CFX_BaseArray::AddSpaceTo(iSize + iCount - 1);\r
165         FX_LPBYTE *pStart = CFX_BaseArray::GetAt(iSize);\r
166         int32_t iBlockSize = CFX_BaseArray::GetBlockSize();\r
167         iSize = iStart + iCount;\r
168         for (int32_t i = iStart; i < iSize; i ++) {\r
169             FXTARGET_NewWith ((void*)pStart)baseType(src.GetAt(i));\r
170             pStart += iBlockSize;\r
171         }\r
172         return iCount;\r
173     }\r
174     int32_t     Copy(const CFX_ObjectBaseArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
175     {\r
176         FXSYS_assert(GetBlockSize() == src.GetBlockSize());\r
177         if (iCount == 0) {\r
178             return 0;\r
179         }\r
180         int32_t iSize = src.GetSize();\r
181         FXSYS_assert(iStart > -1 && iStart < iSize);\r
182         if (iCount < 0) {\r
183             iCount = iSize;\r
184         }\r
185         if (iStart + iCount > iSize) {\r
186             iCount = iSize - iStart;\r
187         }\r
188         if (iCount < 1) {\r
189             return 0;\r
190         }\r
191         RemoveAll(TRUE);\r
192         CFX_BaseArray::AddSpaceTo(iCount - 1);\r
193         FX_LPBYTE *pStart = CFX_BaseArray::GetAt(0);\r
194         int32_t iBlockSize = CFX_BaseArray::GetBlockSize();\r
195         iSize = iStart + iCount;\r
196         for (int32_t i = iStart; i < iSize; i ++) {\r
197             FXTARGET_New ((void*)pStart)baseType(src.GetAt(i));\r
198             pStart += iBlockSize;\r
199         }\r
200         return iCount;\r
201     }\r
202     int32_t     RemoveLast(int32_t iCount = -1)\r
203     {\r
204         int32_t iSize = CFX_BaseArray::GetSize();\r
205         if (iCount < 0 || iCount > iSize) {\r
206             iCount = iSize;\r
207         }\r
208         if (iCount == 0) {\r
209             return iSize;\r
210         }\r
211         for (int32_t i = iSize - iCount; i < iSize; i ++) {\r
212             ((baseType*)GetPtrAt(i))->~baseType();\r
213         }\r
214         return CFX_BaseArray::RemoveLast(iCount);\r
215     }\r
216     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE)\r
217     {\r
218         int32_t iSize = CFX_BaseArray::GetSize();\r
219         for (int32_t i = 0; i < iSize; i ++) {\r
220             ((baseType*)GetPtrAt(i))->~baseType();\r
221         }\r
222         CFX_BaseArray::RemoveAll(bLeaveMemory);\r
223     }\r
224 };\r
225 class CFX_BaseMassArray : public CFX_Target\r
226 {\r
227 protected:\r
228     CFX_BaseMassArray(int32_t iChunkSize, int32_t iBlockSize);\r
229     ~CFX_BaseMassArray();\r
230     int32_t     GetSize() const;\r
231     FX_LPBYTE   AddSpaceTo(int32_t index);\r
232     FX_LPBYTE   GetAt(int32_t index) const;\r
233     int32_t     Append(const CFX_BaseMassArray &src, int32_t iStart = 0, int32_t iCount = -1);\r
234     int32_t     Copy(const CFX_BaseMassArray &src, int32_t iStart = 0, int32_t iCount = -1);\r
235     int32_t     RemoveLast(int32_t iCount = -1);\r
236     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE);\r
237     CFX_BaseMassArrayImp* m_pData;\r
238 };\r
239 template<class baseType>\r
240 class CFX_MassArrayTemplate : public CFX_BaseMassArray\r
241 {\r
242 public:\r
243     CFX_MassArrayTemplate(int32_t iChunkSize = 100) : CFX_BaseMassArray(iChunkSize, sizeof(baseType)) {}\r
244     CFX_MassArrayTemplate(int32_t iChunkSize, int32_t iBlockSize) : CFX_BaseMassArray(iChunkSize, iBlockSize) {}\r
245     int32_t     GetSize() const\r
246     {\r
247         return CFX_BaseMassArray::GetSize();\r
248     }\r
249     baseType*   AddSpace()\r
250     {\r
251         return (baseType*)CFX_BaseMassArray::AddSpaceTo(CFX_BaseMassArray::GetSize());\r
252     }\r
253     int32_t     Add(const baseType &element)\r
254     {\r
255         int32_t index = CFX_BaseMassArray::GetSize();\r
256         *(baseType*)CFX_BaseMassArray::AddSpaceTo(index) = element;\r
257         return index;\r
258     }\r
259     baseType&   GetAt(int32_t index) const\r
260     {\r
261         return *(baseType*)CFX_BaseMassArray::GetAt(index);\r
262     }\r
263     baseType*   GetPtrAt(int32_t index) const\r
264     {\r
265         return (baseType*)CFX_BaseMassArray::GetAt(index);\r
266     }\r
267     void                SetAt(int32_t index, const baseType &element)\r
268     {\r
269         *(baseType*)CFX_BaseMassArray::GetAt(index) = element;\r
270     }\r
271     void                SetAtGrow(int32_t index, const baseType &element)\r
272     {\r
273         *(baseType*)CFX_BaseMassArray::AddSpaceTo(index) = element;\r
274     }\r
275     int32_t     Append(const CFX_MassArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
276     {\r
277         return CFX_BaseMassArray::Append(src, iStart, iCount);\r
278     }\r
279     int32_t     Copy(const CFX_MassArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
280     {\r
281         return CFX_BaseMassArray::Copy(src, iStart, iCount);\r
282     }\r
283     int32_t     RemoveLast(int32_t iCount = -1)\r
284     {\r
285         return CFX_BaseMassArray::RemoveLast(iCount);\r
286     }\r
287     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE)\r
288     {\r
289         CFX_BaseMassArray::RemoveAll(bLeaveMemory);\r
290     }\r
291 };\r
292 typedef CFX_MassArrayTemplate<FX_LPVOID>        CFX_PtrMassArray;\r
293 typedef CFX_MassArrayTemplate<int32_t>          CFX_Int32MassArray;\r
294 typedef CFX_MassArrayTemplate<FX_DWORD>         CFX_DWordMassArray;\r
295 typedef CFX_MassArrayTemplate<FX_WORD>          CFX_WordMassArray;\r
296 typedef CFX_MassArrayTemplate<CFX_Rect>         CFX_RectMassArray;\r
297 typedef CFX_MassArrayTemplate<CFX_RectF>        CFX_RectFMassArray;\r
298 template<class baseType>\r
299 class CFX_ObjectMassArrayTemplate : public CFX_BaseMassArray\r
300 {\r
301 public:\r
302     CFX_ObjectMassArrayTemplate(int32_t iChunkSize = 100) : CFX_BaseMassArray(iChunkSize, sizeof(baseType)) {}\r
303     ~CFX_ObjectMassArrayTemplate()\r
304     {\r
305         RemoveAll(FALSE);\r
306     }\r
307     int32_t     GetSize() const\r
308     {\r
309         return CFX_BaseMassArray::GetSize();\r
310     }\r
311     int32_t     Add(const baseType &element)\r
312     {\r
313         int32_t index = CFX_BaseMassArray::GetSize();\r
314         baseType *p = (baseType*)CFX_BaseMassArray::AddSpaceTo(index);\r
315         FXTARGET_New ((void*)p)baseType(element);\r
316         return index;\r
317     }\r
318     baseType&   GetAt(int32_t index) const\r
319     {\r
320         return *(baseType*)CFX_BaseMassArray::GetAt(index);\r
321     }\r
322     baseType*   GetPtrAt(int32_t index) const\r
323     {\r
324         return (baseType*)CFX_BaseMassArray::GetAt(index);\r
325     }\r
326     int32_t     Append(const CFX_ObjectMassArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
327     {\r
328         if (iCount == 0) {\r
329             return CFX_BaseMassArray::GetSize();\r
330         }\r
331         int32_t iSize = src.GetSize();\r
332         FXSYS_assert(iStart > -1 && iStart < iSize);\r
333         if (iCount < 0) {\r
334             iCount = iSize;\r
335         }\r
336         int32_t iEnd = iStart + iCount;\r
337         if (iEnd > iSize) {\r
338             iEnd = iSize;\r
339         }\r
340         for (int32_t i = iStart; i < iEnd; i ++) {\r
341             Add(src.GetAt(i));\r
342         }\r
343         return CFX_BaseMassArray::GetSize();\r
344     }\r
345     int32_t     Copy(const CFX_ObjectMassArrayTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
346     {\r
347         if (iCount == 0) {\r
348             return CFX_BaseMassArray::GetSize();\r
349         }\r
350         int32_t iSize = src.GetSize();\r
351         FXSYS_assert(iStart > -1 && iStart < iSize);\r
352         if (iCount < 0) {\r
353             iCount = iSize;\r
354         }\r
355         int32_t iEnd = iStart + iCount;\r
356         if (iEnd > iSize) {\r
357             iEnd = iSize;\r
358         }\r
359         RemoveAll(TRUE);\r
360         for (int32_t i = iStart; i < iEnd; i ++) {\r
361             Add(src.GetAt(i));\r
362         }\r
363         return CFX_BaseMassArray::GetSize();\r
364     }\r
365     int32_t     RemoveLast(int32_t iCount = -1)\r
366     {\r
367         int32_t iSize = CFX_BaseMassArray::GetSize();\r
368         if (iCount < 0 || iCount > iSize) {\r
369             iCount = iSize;\r
370         }\r
371         if (iCount == 0) {\r
372             return iSize;\r
373         }\r
374         for (int32_t i = iSize - iCount; i < iSize; i ++) {\r
375             ((baseType*)GetPtrAt(i))->~baseType();\r
376         }\r
377         return CFX_BaseMassArray::RemoveLast(iCount);\r
378     }\r
379     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE)\r
380     {\r
381         int32_t iSize = CFX_BaseMassArray::GetSize();\r
382         for (int32_t i = 0; i < iSize; i ++) {\r
383             ((baseType*)GetPtrAt(i))->~baseType();\r
384         }\r
385         CFX_BaseMassArray::RemoveAll(bLeaveMemory);\r
386     }\r
387 };\r
388 class CFX_BaseDiscreteArray : public CFX_Target\r
389 {\r
390 protected:\r
391     CFX_BaseDiscreteArray(int32_t iChunkSize, int32_t iBlockSize);\r
392     ~CFX_BaseDiscreteArray();\r
393     FX_LPBYTE   AddSpaceTo(int32_t index);\r
394     FX_LPBYTE   GetAt(int32_t index) const;\r
395     void                RemoveAll();\r
396     FX_LPVOID   m_pData;\r
397 };\r
398 template<class baseType>\r
399 class CFX_DiscreteArrayTemplate : public CFX_BaseDiscreteArray\r
400 {\r
401 public:\r
402     CFX_DiscreteArrayTemplate(int32_t iChunkSize = 100) : CFX_BaseDiscreteArray(iChunkSize, sizeof(baseType)) {}\r
403     baseType&   GetAt(int32_t index, const baseType &defValue) const\r
404     {\r
405         baseType *p = (baseType*)CFX_BaseDiscreteArray::GetAt(index);\r
406         return p == NULL ? (baseType&)defValue : *p;\r
407     }\r
408     baseType*   GetPtrAt(int32_t index) const\r
409     {\r
410         return (baseType*)CFX_BaseDiscreteArray::GetAt(index);\r
411     }\r
412     void                SetAtGrow(int32_t index, const baseType &element)\r
413     {\r
414         *(baseType*)CFX_BaseDiscreteArray::AddSpaceTo(index) = element;\r
415     }\r
416     void                RemoveAll()\r
417     {\r
418         CFX_BaseDiscreteArray::RemoveAll();\r
419     }\r
420 };\r
421 typedef CFX_DiscreteArrayTemplate<FX_LPVOID>    CFX_PtrDiscreteArray;\r
422 typedef CFX_DiscreteArrayTemplate<FX_DWORD>             CFX_DWordDiscreteArray;\r
423 typedef CFX_DiscreteArrayTemplate<FX_WORD>              CFX_WordDiscreteArray;\r
424 class CFX_BaseStack : public CFX_Target\r
425 {\r
426 protected:\r
427     CFX_BaseStack(int32_t iChunkSize, int32_t iBlockSize);\r
428     ~CFX_BaseStack();\r
429     FX_LPBYTE   Push();\r
430     void                Pop();\r
431     FX_LPBYTE   GetTopElement() const;\r
432     int32_t     GetSize() const;\r
433     FX_LPBYTE   GetAt(int32_t index) const;\r
434     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE);\r
435     CFX_BaseMassArrayImp* m_pData;\r
436 };\r
437 template<class baseType>\r
438 class CFX_StackTemplate : public CFX_BaseStack\r
439 {\r
440 public:\r
441     CFX_StackTemplate(int32_t iChunkSize = 100) : CFX_BaseStack(iChunkSize, sizeof(baseType)) {}\r
442     int32_t     Push(const baseType &element)\r
443     {\r
444         int32_t index = CFX_BaseStack::GetSize();\r
445         *(baseType*)CFX_BaseStack::Push() = element;\r
446         return index;\r
447     }\r
448     void                Pop()\r
449     {\r
450         CFX_BaseStack::Pop();\r
451     }\r
452     baseType*   GetTopElement() const\r
453     {\r
454         return (baseType*)CFX_BaseStack::GetTopElement();\r
455     }\r
456     int32_t     GetSize() const\r
457     {\r
458         return CFX_BaseStack::GetSize();\r
459     }\r
460     baseType*   GetAt(int32_t index) const\r
461     {\r
462         return (baseType*)CFX_BaseStack::GetAt(index);\r
463     }\r
464     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE)\r
465     {\r
466         CFX_BaseStack::RemoveAll(bLeaveMemory);\r
467     }\r
468 };\r
469 typedef CFX_StackTemplate<FX_LPVOID>    CFX_PtrStack;\r
470 typedef CFX_StackTemplate<FX_DWORD>     CFX_DWordStack;\r
471 typedef CFX_StackTemplate<FX_WORD>              CFX_WordStack;\r
472 typedef CFX_StackTemplate<int32_t>      CFX_Int32Stack;\r
473 template<class baseType>\r
474 class CFX_ObjectStackTemplate : public CFX_BaseStack\r
475 {\r
476 public:\r
477     CFX_ObjectStackTemplate(int32_t iChunkSize = 100) : CFX_BaseStack(iChunkSize, sizeof(baseType)) {}\r
478     ~CFX_ObjectStackTemplate()\r
479     {\r
480         RemoveAll();\r
481     }\r
482     int32_t     Push(const baseType &element)\r
483     {\r
484         int32_t index = CFX_BaseStack::GetSize();\r
485         baseType *p = (baseType*)CFX_BaseStack::Push();\r
486         FXTARGET_New ((void*)p)baseType(element);\r
487         return index;\r
488     }\r
489     void                Pop()\r
490     {\r
491         baseType *p = (baseType*)CFX_BaseStack::GetTopElement();\r
492         if (p != NULL) {\r
493             p->~baseType();\r
494         }\r
495         CFX_BaseStack::Pop();\r
496     }\r
497     baseType*   GetTopElement() const\r
498     {\r
499         return (baseType*)CFX_BaseStack::GetTopElement();\r
500     }\r
501     int32_t     GetSize() const\r
502     {\r
503         return CFX_BaseStack::GetSize();\r
504     }\r
505     baseType*   GetAt(int32_t index) const\r
506     {\r
507         return (baseType*)CFX_BaseStack::GetAt(index);\r
508     }\r
509     void                RemoveAll(FX_BOOL bLeaveMemory = FALSE)\r
510     {\r
511         int32_t iSize = CFX_BaseStack::GetSize();\r
512         for (int32_t i = 0; i < iSize; i ++) {\r
513             ((baseType*)CFX_BaseStack::GetAt(i))->~baseType();\r
514         }\r
515         CFX_BaseStack::RemoveAll(bLeaveMemory);\r
516     }\r
517     int32_t     Copy(const CFX_ObjectStackTemplate &src, int32_t iStart = 0, int32_t iCount = -1)\r
518     {\r
519         if (iCount == 0) {\r
520             return CFX_BaseStack::GetSize();\r
521         }\r
522         int32_t iSize = src.GetSize();\r
523         FXSYS_assert(iStart > -1 && iStart < iSize);\r
524         if (iCount < 0) {\r
525             iCount = iSize;\r
526         }\r
527         int32_t iEnd = iStart + iCount;\r
528         if (iEnd > iSize) {\r
529             iEnd = iSize;\r
530         }\r
531         RemoveAll(TRUE);\r
532         for (int32_t i = iStart; i < iEnd; i ++) {\r
533             Push(*src.GetAt(i));\r
534         }\r
535         return CFX_BaseStack::GetSize();\r
536     }\r
537 };\r
538 template<class baseType>\r
539 class CFX_CPLTreeNode : public CFX_Target\r
540 {\r
541 public:\r
542     typedef CFX_CPLTreeNode<baseType>   CPLTreeNode;\r
543     CFX_CPLTreeNode() : m_pParentNode(NULL)\r
544         , m_pChildNode(NULL)\r
545         , m_pPrevNode(NULL)\r
546         , m_pNextNode(NULL)\r
547         , m_Data()\r
548     {\r
549     }\r
550     enum TreeNode {Root = 0, Parent, FirstSibling, PreviousSibling, NextSibling, LastSibling, FirstNeighbor, PreviousNeighbor, NextNeighbor, LastNeighbor, FirstChild, LastChild};\r
551     CPLTreeNode* GetNode(TreeNode eNode) const\r
552     {\r
553         switch (eNode) {\r
554             case Root: {\r
555                     CPLTreeNode *pParent = (CPLTreeNode*)this;\r
556                     CPLTreeNode *pTemp;\r
557                     while ((pTemp = pParent->m_pParentNode) != NULL) {\r
558                         pParent = pTemp;\r
559                     }\r
560                     return pParent;\r
561                 }\r
562             case Parent:\r
563                 return m_pParentNode;\r
564             case FirstSibling: {\r
565                     CPLTreeNode *pNode = (CPLTreeNode*)this;\r
566                     CPLTreeNode *pTemp;\r
567                     while ((pTemp = pNode->m_pPrevNode) != NULL) {\r
568                         pNode = pTemp;\r
569                     }\r
570                     return pNode == (CPLTreeNode*)this ? NULL : pNode;\r
571                 }\r
572             case PreviousSibling:\r
573                 return m_pPrevNode;\r
574             case NextSibling:\r
575                 return m_pNextNode;\r
576             case LastSibling: {\r
577                     CPLTreeNode *pNode = (CPLTreeNode*)this;\r
578                     CPLTreeNode *pTemp;\r
579                     while ((pTemp = pNode->m_pNextNode) != NULL) {\r
580                         pNode = pTemp;\r
581                     }\r
582                     return pNode == (CPLTreeNode*)this ? NULL : pNode;\r
583                 }\r
584             case FirstNeighbor: {\r
585                     CPLTreeNode *pParent = (CPLTreeNode*)this;\r
586                     CPLTreeNode *pTemp;\r
587                     while ((pTemp = pParent->m_pParentNode) != NULL) {\r
588                         pParent = pTemp;\r
589                     }\r
590                     return pParent == (CPLTreeNode*)this ? NULL : pParent;\r
591                 }\r
592             case PreviousNeighbor: {\r
593                     if (m_pPrevNode == NULL) {\r
594                         return m_pParentNode;\r
595                     }\r
596                     CPLTreeNode *pNode = m_pPrevNode;\r
597                     CPLTreeNode *pTemp;\r
598                     while ((pTemp = pNode->m_pChildNode) != NULL) {\r
599                         pNode = pTemp;\r
600                         while ((pTemp = pNode->m_pNextNode) != NULL) {\r
601                             pNode = pTemp;\r
602                         }\r
603                     }\r
604                     return pNode;\r
605                 }\r
606             case NextNeighbor: {\r
607                     if (m_pChildNode != NULL) {\r
608                         return m_pChildNode;\r
609                     }\r
610                     if (m_pNextNode != NULL) {\r
611                         return m_pNextNode;\r
612                     }\r
613                     CPLTreeNode *pNode = m_pParentNode;\r
614                     while (pNode != NULL) {\r
615                         if (pNode->m_pNextNode != NULL) {\r
616                             return pNode->m_pNextNode;\r
617                         }\r
618                         pNode = pNode->m_pParentNode;\r
619                     }\r
620                     return NULL;\r
621                 }\r
622             case LastNeighbor: {\r
623                     CPLTreeNode *pNode = (CPLTreeNode*)this;\r
624                     CPLTreeNode *pTemp;\r
625                     while ((pTemp = pNode->m_pParentNode) != NULL) {\r
626                         pNode = pTemp;\r
627                     }\r
628                     while (TRUE) {\r
629                         CPLTreeNode *pTemp;\r
630                         while ((pTemp = pNode->m_pNextNode) != NULL) {\r
631                             pNode = pTemp;\r
632                         }\r
633                         if (pNode->m_pChildNode == NULL) {\r
634                             break;\r
635                         }\r
636                         pNode = pNode->m_pChildNode;\r
637                     }\r
638                     return pNode == (CPLTreeNode*)this ? NULL : pNode;\r
639                 }\r
640             case FirstChild:\r
641                 return m_pChildNode;\r
642             case LastChild: {\r
643                     if (m_pChildNode == NULL) {\r
644                         return NULL;\r
645                     }\r
646                     CPLTreeNode *pChild = m_pChildNode;\r
647                     CPLTreeNode *pTemp;\r
648                     while ((pTemp = pChild->m_pNextNode) != NULL) {\r
649                         pChild = pTemp;\r
650                     }\r
651                     return pChild;\r
652                 }\r
653             default:\r
654                 break;\r
655         }\r
656         return NULL;\r
657     }\r
658     void SetParentNode(CPLTreeNode *pNode)\r
659     {\r
660         m_pParentNode = pNode;\r
661     }\r
662     int32_t CountChildNodes() const\r
663     {\r
664         int32_t iCount = 0;\r
665         CPLTreeNode *pNode = m_pChildNode;\r
666         while (pNode) {\r
667             iCount ++;\r
668             pNode = pNode->m_pNextNode;\r
669         }\r
670         return iCount;\r
671     }\r
672     CPLTreeNode* GetChildNode(int32_t iIndex) const\r
673     {\r
674         int32_t iCount = 0;\r
675         CPLTreeNode *pNode = m_pChildNode;\r
676         while (pNode) {\r
677             if (iIndex == iCount) {\r
678                 return pNode;\r
679             }\r
680             iCount ++;\r
681             pNode = pNode->m_pNextNode;\r
682         }\r
683         return NULL;\r
684     }\r
685     int32_t GetNodeIndex() const\r
686     {\r
687         int32_t index = 0;\r
688         CPLTreeNode *pNode = m_pPrevNode;\r
689         while (pNode != NULL) {\r
690             index ++;\r
691             pNode = pNode->m_pPrevNode;\r
692         }\r
693         return index;\r
694     }\r
695     FX_BOOL IsParentNode(const CPLTreeNode *pNode) const\r
696     {\r
697         CPLTreeNode *pParent = m_pParentNode;\r
698         while (pParent != NULL) {\r
699             if (pParent == pNode) {\r
700                 return TRUE;\r
701             }\r
702             pParent = pParent->GetTreeNode(Parent);\r
703         }\r
704         return FALSE;\r
705     }\r
706     FX_BOOL IsChildNode(const CPLTreeNode *pNode) const\r
707     {\r
708         if (pNode == NULL) {\r
709             return FALSE;\r
710         }\r
711         return pNode->IsParentNode((const CPLTreeNode*)this);\r
712     }\r
713     void SetChildNode(CPLTreeNode *pNode)\r
714     {\r
715         m_pChildNode = pNode;\r
716     }\r
717     void SetPrevNode(CPLTreeNode *pNode)\r
718     {\r
719         m_pPrevNode = pNode;\r
720     }\r
721     void SetNextNode(CPLTreeNode *pNode)\r
722     {\r
723         m_pNextNode = pNode;\r
724     }\r
725     int32_t GetNodeLevel() const\r
726     {\r
727         int32_t iLevel = 0;\r
728         CPLTreeNode *pNode = (CPLTreeNode*)this;\r
729         while ((pNode = pNode->m_pParentNode) != NULL) {\r
730             iLevel ++;\r
731         }\r
732         return iLevel;\r
733     }\r
734     FX_BOOL IsRootNode() const\r
735     {\r
736         return m_pParentNode == NULL;\r
737     }\r
738     baseType GetData() const\r
739     {\r
740         return m_Data;\r
741     }\r
742     void SetData(baseType data)\r
743     {\r
744         m_Data = data;\r
745     }\r
746 protected:\r
747     CPLTreeNode         *m_pParentNode;\r
748     CPLTreeNode         *m_pChildNode;\r
749     CPLTreeNode         *m_pPrevNode;\r
750     CPLTreeNode         *m_pNextNode;\r
751     baseType            m_Data;\r
752     friend class CFX_CPLTree<baseType>;\r
753 };\r
754 template<class baseType>\r
755 class CFX_CPLTree\r
756 {\r
757 public:\r
758     typedef CFX_CPLTreeNode<baseType>   CPLTreeNode;\r
759     CFX_CPLTree() : m_Root()\r
760     {\r
761     }\r
762     ~CFX_CPLTree()\r
763     {\r
764         CPLTreeNode *pNode = m_Root.GetNode(CPLTreeNode::LastNeighbor);\r
765         while (pNode != NULL) {\r
766             if (pNode->IsRootNode()) {\r
767                 break;\r
768             }\r
769             CPLTreeNode *pTemp = pNode->GetNode(CPLTreeNode::PreviousNeighbor);\r
770             delete pNode;\r
771             pNode = pTemp;\r
772         }\r
773     }\r
774     CPLTreeNode* GetRoot()\r
775     {\r
776         return &m_Root;\r
777     }\r
778     CPLTreeNode* AddChild(baseType data, CPLTreeNode *pParent = NULL)\r
779     {\r
780         if (pParent == NULL) {\r
781             pParent = &m_Root;\r
782         }\r
783         CPLTreeNode *pChild = FXTARGET_New CPLTreeNode;\r
784         pChild->SetParentNode(pParent);\r
785         pChild->SetData(data);\r
786         if (pParent->m_pChildNode == NULL) {\r
787             pParent->m_pChildNode = pChild;\r
788         } else {\r
789             CPLTreeNode *pLast = pParent->GetNode(CPLTreeNode::LastChild);\r
790             pChild->SetPrevNode(pLast);\r
791             pLast->SetNextNode(pChild);\r
792         }\r
793         return pChild;\r
794     }\r
795 protected:\r
796     CPLTreeNode         m_Root;\r
797 };\r
798 #endif\r