source: trunk/Common/alax.info/roatlcollections.h @ 553

Last change on this file since 553 was 553, checked in by roman, 8 years ago
  • Property svn:keywords set to Id
File size: 38.3 KB
Line 
1////////////////////////////////////////////////////////////
2// Template class library; extends Widnows SDK, ATL, WTL
3//
4// Copyright (C) Roman Ryltsov, 2006-2015
5// Created by Roman Ryltsov roman@alax.info
6//
7// A permission to re-use this source code is granted as long as copyright notice and
8// reference to source website http://alax.info is retained.
9
10#pragma once
11
12#include <atlcoll.h>
13
14////////////////////////////////////////////////////////////
15// CRoIterativeTraitsBase
16
17class CRoIterativeTraitsBase
18{
19public:
20
21        ////////////////////////////////////////////////////////
22        // CAddressT
23
24        template <typename CValue>
25        class CAddressT
26        {
27        public:
28                CValue m_Value;
29
30        public:
31        // CAddressT
32                const CValue* operator & () const
33                {
34                        return reinterpret_cast<const CValue*>(this);
35                }
36                CValue* operator & ()
37                {
38                        return reinterpret_cast<CValue*>(this);
39                }
40        };
41
42public:
43// CRoIterativeTraitsBase
44};
45
46////////////////////////////////////////////////////////////
47// CRoIterativeArrayTraitsT
48
49template <typename CArray>
50class CRoIterativeArrayTraitsT :
51        public CRoIterativeTraitsBase
52{
53protected:
54        typedef SIZE_T KEY;
55
56public:
57
58        ////////////////////////////////////////////////////////
59        // CIterator
60
61        class CIterator
62        {
63        public:
64                const CArray* m_pArray;
65                KEY m_nIndex;
66
67        public:
68        // CIterator
69                CIterator(const CArray* pArray) throw() :
70                        m_pArray(pArray),
71                        m_nIndex(0)
72                {
73                        _A(pArray);
74                }
75                BOOL IsValid() const throw()
76                {
77                        return m_nIndex < m_pArray->GetCount();
78                }
79                VOID Next() throw()
80                {
81                        m_nIndex++;
82                }
83                operator KEY () const throw()
84                {
85                        return m_nIndex;
86                }
87        };
88
89        ////////////////////////////////////////////////////////
90        // CReverseIterator
91
92        class CReverseIterator
93        {
94        public:
95                const CArray* m_pArray;
96                KEY m_nIndex;
97
98        public:
99        // CReverseIterator
100                CReverseIterator(const CArray* pArray) throw() :
101                        m_pArray(pArray),
102                        m_nIndex(pArray->GetCount() - 1)
103                {
104                        _A(pArray);
105                }
106                BOOL IsValid() const throw()
107                {
108                        return (SSIZE_T) m_nIndex >= 0;
109                }
110                VOID Next() throw()
111                {
112                        m_nIndex--;
113                }
114                operator KEY () const throw()
115                {
116                        return m_nIndex;
117                }
118        };
119
120        ////////////////////////////////////////////////////////
121        // CRangeIterator
122
123        class CRangeIterator
124        {
125        public:
126                const CArray& m_Array;
127                SIZE_T m_nIndex;
128
129        public:
130        // CRangeIterator
131                ATL_FORCEINLINE CRangeIterator(const CArray* pArray, SIZE_T nIndex) :
132                        m_Array(*pArray),
133                        m_nIndex(nIndex)
134                {
135                        _A(pArray);
136                }
137                ATL_FORCEINLINE BOOL operator == (const CRangeIterator& Value) const
138                {
139                        _A(&m_Array == &Value.m_Array);
140                        return m_nIndex == Value.m_nIndex;
141                }
142                ATL_FORCEINLINE BOOL operator != (const CRangeIterator& Value) const
143                {
144                        return !(*this == Value);
145                }
146                ATL_FORCEINLINE CRangeIterator& operator ++ ()
147                {
148                        ++m_nIndex;
149                        return *this;
150                }
151                ATL_FORCEINLINE operator const typename CArray::CCollectionElement* () const
152                {
153                        const typename CArray::CCollectionElement& Element = m_Array.GetAt(m_nIndex);
154                        CAddressT<typename CArray::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CArray::CCollectionElement>&>(Element);
155                        return &ElementAddress;
156                }
157                ATL_FORCEINLINE operator typename CArray::CCollectionElement* ()
158                {
159                        typename CArray::CCollectionElement& Element = const_cast<CArray&>(m_Array).GetAt(m_nIndex);
160                        CAddressT<typename CArray::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CArray::CCollectionElement>&>(Element);
161                        return &ElementAddress;
162                }
163                ATL_FORCEINLINE static CRangeIterator begin(const CArray* pArray)
164                {
165                        return CRangeIterator(pArray, 0);
166                }
167                ATL_FORCEINLINE static CRangeIterator end(const CArray* pArray)
168                {
169                        return CRangeIterator(pArray, pArray->GetCount());
170                }
171        };
172
173public:
174// CRoIterativeArrayTraitsT
175};
176
177////////////////////////////////////////////////////////////
178// CRoIterativeListTraitsT
179
180template <typename CList>
181class CRoIterativeListTraitsT :
182        public CRoIterativeTraitsBase
183{
184protected:
185        typedef POSITION KEY;
186
187public:
188
189        ////////////////////////////////////////////////////////
190        // CIterator
191
192        class CIterator
193        {
194        public:
195                const CList* m_pList;
196                KEY m_Position;
197
198        public:
199        // CIterator
200                CIterator(const CList* pList) throw() :
201                        m_pList(pList),
202                        m_Position(pList->GetHeadPosition())
203                {
204                }
205                BOOL IsValid() const throw()
206                {
207                        return m_Position != NULL;
208                }
209                VOID Next() throw()
210                {
211                        m_pList->GetNext(m_Position);
212                }
213                operator KEY () const throw()
214                {
215                        return m_Position;
216                }
217        };
218
219        ////////////////////////////////////////////////////////
220        // CReverseIterator
221
222        class CReverseIterator
223        {
224        public:
225                const CList* m_pList;
226                KEY m_Position;
227
228        public:
229        // CReverseIterator
230                CReverseIterator(const CList* pList) throw() :
231                        m_pList(pList),
232                        m_Position(pList->GetTailPosition())
233                {
234                }
235                BOOL IsValid() const throw()
236                {
237                        return m_Position != NULL;
238                }
239                VOID Next() throw()
240                {
241                        m_pList->GetPrev(m_Position);
242                }
243                operator KEY () const throw()
244                {
245                        return m_Position;
246                }
247        };
248
249        ////////////////////////////////////////////////////////
250        // CRangeIterator
251
252        class CRangeIterator
253        {
254        public:
255                const CList& m_List;
256                POSITION m_Position;
257
258        public:
259        // CRangeIterator
260                ATL_FORCEINLINE CRangeIterator(const CList* pList, POSITION Position) :
261                        m_List(*pList),
262                        m_Position(Position)
263                {
264                        _A(pList);
265                }
266                ATL_FORCEINLINE BOOL operator == (const CRangeIterator& Value) const
267                {
268                        _A(&m_List == &Value.m_List);
269                        return m_Position == Value.m_Position;
270                }
271                ATL_FORCEINLINE BOOL operator != (const CRangeIterator& Value) const
272                {
273                        return !(*this == Value);
274                }
275                ATL_FORCEINLINE CRangeIterator& operator ++ ()
276                {
277                        m_List.GetNext(m_Position);
278                        return *this;
279                }
280                ATL_FORCEINLINE operator const typename CList::CCollectionElement* () const
281                {
282                        _A(m_Position);
283                        const typename CList::CCollectionElement& Element = m_List.GetAt(m_Position);
284                        CAddressT<typename CList::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CList::CCollectionElement>&>(Element);
285                        return &ElementAddress;
286                }
287                ATL_FORCEINLINE operator typename CList::CCollectionElement* ()
288                {
289                        _A(m_Position);
290                        typename CList::CCollectionElement& Element = const_cast<CList&>(m_List).GetAt(m_Position);
291                        CAddressT<typename CList::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CList::CCollectionElement>&>(Element);
292                        return &ElementAddress;
293                }
294                ATL_FORCEINLINE static CRangeIterator begin(const CList* pList)
295                {
296                        return CRangeIterator(pList, pList->GetHeadPosition());
297                }
298                ATL_FORCEINLINE static CRangeIterator end(const CList* pList)
299                {
300                        return CRangeIterator(pList, NULL);
301                }
302        };
303
304public:
305// CRoIterativeListTraitsT
306};
307
308////////////////////////////////////////////////////////////
309// CRoIterativeCollectionT
310
311template <typename T, template <typename _Collection> class CIterativeTraits, typename _Element, typename _ElementTraits = CElementTraits<_Element> >
312class CRoIterativeCollectionT :
313        protected CIterativeTraits<T>
314{
315protected:
316        typedef typename CIterativeTraits<T>::KEY KEY;
317
318public:
319// CRoIterativeCollectionT
320        template <typename _Iterator, typename _Parameter>
321        SIZE_T GetCountThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, typename CElementTraits<_Parameter>::INARGTYPE Parameter), typename CElementTraits<_Parameter>::INARGTYPE Parameter) const throw()
322        {
323                _A(pCompareElement);
324                const T* pT = static_cast<const T*>(this);
325                SIZE_T nCount = 0;
326                for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
327                        if((*pCompareElement)(pT->GetAt(Iterator), Parameter))
328                                nCount++;
329                return nCount;
330        }
331        template <typename _Parameter>
332        SIZE_T GetCountThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, typename CElementTraits<_Parameter>::INARGTYPE Parameter), typename CElementTraits<_Parameter>::INARGTYPE Parameter) const throw()
333        {
334                return GetCountThatT<CIterator, _Parameter>(pCompareElement, Parameter);
335        }
336        template <typename _Iterator>
337        SIZE_T GetCountThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element)) const throw()
338        {
339                _A(pCompareElement);
340                const T* pT = static_cast<const T*>(this);
341                SIZE_T nCount = 0;
342                for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
343                        if((*pCompareElement)(pT->GetAt(Iterator)))
344                                nCount++;
345                return nCount;
346        }
347        SIZE_T GetCountThat(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element)) const throw()
348        {
349                return GetCountThatT<CIterator>(pCompareElement);
350        }
351        //__if_exists(T::Add)
352        //{
353                template <typename _Iterator, typename _Parameter>
354                SIZE_T GetThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, typename CElementTraits<_Parameter>::INARGTYPE Parameter), typename CElementTraits<_Parameter>::INARGTYPE Parameter, T& Collection) const throw()
355                {
356                        _A(pCompareElement);
357                        _A(Collection.IsEmpty());
358                        const T* pT = static_cast<const T*>(this);
359                        Collection.SetCount(0, (INT) pT->GetCount());
360                        SIZE_T nCount = 0;
361                        for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
362                        {
363                                const _Element& Element = pT->GetAt(Iterator);
364                                if((*pCompareElement)(Element, Parameter))
365                                        _W(Collection.Add(Element) >= 0);
366                        }
367                        return Collection.GetCount();
368                }
369                template <typename _Parameter>
370                SIZE_T GetThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, typename CElementTraits<_Parameter>::INARGTYPE Parameter), typename CElementTraits<_Parameter>::INARGTYPE Parameter, T& Collection) const throw()
371                {
372                        return GetThatT<CIterator, _Parameter>(pCompareElement, Parameter, Collection);
373                }
374                template <typename _Iterator>
375                SIZE_T GetThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element), T& Collection) const
376                {
377                        _A(pCompareElement);
378                        _A(Collection.IsEmpty());
379                        const T* pT = static_cast<const T*>(this);
380                        Collection.SetCount(0, (INT) pT->GetCount());
381                        for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
382                        {
383                                const _Element& Element = pT->GetAt(Iterator);
384                                if((*pCompareElement)(Element))
385                                        _W(Collection.Add(Element) >= 0);
386                        }
387                        return Collection.GetCount();
388                }
389                SIZE_T GetThat(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element), T& Collection) const
390                {
391                        return GetThatT<CIterator>(pCompareElement, Collection);
392                }
393        //}
394        //__if_exists(T::RemoveAt)
395        //{
396                template <typename _Iterator, typename _Parameter>
397                SIZE_T RemoveThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, typename CElementTraits<_Parameter>::INARGTYPE Parameter), typename CElementTraits<_Parameter>::INARGTYPE Parameter) throw()
398                {
399                        _A(pCompareElement);
400                        T* pT = static_cast<T*>(this);
401                        SIZE_T nCount = 0;
402                        for(_Iterator Iterator(pT); Iterator.IsValid(); )
403                        {
404                                const KEY CurrentKey = Iterator;
405                                Iterator.Next();
406                                if(!(*pCompareElement)(pT->GetAt(CurrentKey), Parameter))
407                                        continue;
408                                // ASSU: Removed item does not invalidate further items on the loop
409                                pT->RemoveAt(CurrentKey);
410                                nCount++;
411                        }
412                        return nCount;
413                }
414                template <typename _Parameter>
415                SIZE_T RemoveThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, typename CElementTraits<_Parameter>::INARGTYPE Parameter), typename CElementTraits<_Parameter>::INARGTYPE Parameter) throw()
416                {
417                        // ASSU: Elements removed by CReverseIterator leave items to go intact and valid for further iterations
418                        return RemoveThatT<CReverseIterator, _Parameter>(pCompareElement, Parameter);
419                }
420                SIZE_T RemoveThat(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element)) throw()
421                {
422                        return RemoveThatT<CReverseIterator>(pCompareElement);
423                }
424                BOOL RemoveFirst(typename _ElementTraits::INARGTYPE Element)
425                {
426                        T* pT = static_cast<T*>(this);
427                        KEY Key;
428                        if(!pT->FindFirst(Element, &Key))
429                                return FALSE;
430                        pT->RemoveAt(Key);
431                        return TRUE;
432                }
433                BOOL RemoveLast(typename _ElementTraits::INARGTYPE Element)
434                {
435                        T* pT = static_cast<T*>(this);
436                        KEY Key;
437                        if(!pT->FindLast(Element, &Key))
438                                return FALSE;
439                        pT->RemoveAt(Key);
440                        return TRUE;
441                }
442        //}
443        template <typename _Iterator>
444        BOOL FindT(typename _ElementTraits::INARGTYPE Element, KEY* pKey = NULL) const throw()
445        {
446                const T* pT = static_cast<const T*>(this);
447                for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
448                        if(_ElementTraits::CompareElements(pT->GetAt(Iterator), Element))
449                        {
450                                if(pKey)
451                                        *pKey = Iterator;
452                                return TRUE;
453                        }
454                return FALSE;
455        }
456        template <typename _Iterator>
457        BOOL FindThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element), KEY* pKey = NULL) const throw()
458        {
459                _A(pCompareElement);
460                const T* pT = static_cast<const T*>(this);
461                for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
462                        if((*pCompareElement)(pT->GetAt(Iterator)))
463                        {
464                                if(pKey)
465                                        *pKey = Iterator;
466                                return TRUE;
467                        }
468                return FALSE;
469        }
470        template <typename _Iterator, typename _Parameter>
471        BOOL FindThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, _Parameter Parameter), _Parameter Parameter, KEY* pKey = NULL) const throw()
472        {
473                _A(pCompareElement);
474                const T* pT = static_cast<const T*>(this);
475                for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
476                        if((*pCompareElement)(pT->GetAt(Iterator), Parameter))
477                        {
478                                if(pKey)
479                                        *pKey = Iterator;
480                                return TRUE;
481                        }
482                return FALSE;
483        }
484        template <typename _Iterator, typename _Parameter>
485        BOOL FindThatT(BOOL (T::*pCompareElement)(typename _ElementTraits::INARGTYPE Element, _Parameter Parameter), _Parameter Parameter, KEY* pKey = NULL) const throw()
486        {
487                _A(pCompareElement);
488                const T* pT = static_cast<const T*>(this);
489                for(_Iterator Iterator(pT); Iterator.IsValid(); Iterator.Next())
490                        if((pT->*pCompareElement)(pT->GetAt(Iterator), Parameter))
491                        {
492                                if(pKey)
493                                        *pKey = Iterator;
494                                return TRUE;
495                        }
496                return FALSE;
497        }
498        BOOL FindFirst(typename _ElementTraits::INARGTYPE Element, KEY* pKey = NULL) const throw()
499        {
500                return FindT<CIterator>(Element, pKey);
501        }
502        BOOL FindLast(typename _ElementTraits::INARGTYPE Element, KEY* pKey = NULL) const throw()
503        {
504                return FindT<CReverseIterator>(Element, pKey);
505        }
506        BOOL FindFirstThat(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element), KEY* pKey = NULL) const throw()
507        {
508                return FindThatT<CIterator>(pCompareElement, pKey);
509        }
510        BOOL FindLastThat(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element), KEY* pKey = NULL) const throw()
511        {
512                return FindThatT<CReverseIterator>(pCompareElement, pKey);
513        }
514        template <typename _Parameter>
515        BOOL FindFirstThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, _Parameter Parameter), _Parameter Parameter, KEY* pKey = NULL) const throw()
516        {
517                return FindThatT<CIterator, _Parameter>(pCompareElement, Parameter, pKey);
518        }
519        template <typename _Parameter>
520        BOOL FindLastThatT(BOOL (*pCompareElement)(typename _ElementTraits::INARGTYPE Element, _Parameter Parameter), _Parameter Parameter, KEY* pKey = NULL) const throw()
521        {
522                return FindThatT<CReverseIterator, _Parameter>(pCompareElement, Parameter, pKey);
523        }
524        template <typename _Parameter>
525        BOOL FindFirstThatT(BOOL (T::*pCompareElement)(typename _ElementTraits::INARGTYPE Element, _Parameter Parameter) const, _Parameter Parameter, KEY* pKey = NULL) const throw()
526        {
527                return FindThatT<CIterator, _Parameter>(pCompareElement, Parameter, pKey);
528        }
529        template <typename _Parameter>
530        BOOL FindLastThatT(BOOL (T::*pCompareElement)(typename _ElementTraits::INARGTYPE Element, _Parameter Parameter) const, _Parameter Parameter, KEY* pKey = NULL) const throw()
531        {
532                return FindThatT<CReverseIterator, _Parameter>(pCompareElement, Parameter, pKey);
533        }
534        SIZE_T ForEach(BOOL (*pProcessElement)(typename _ElementTraits::INARGTYPE Element)) const
535        {
536                _A(pProcessElement);
537                T* pT = static_cast<T*>(this);
538                SIZE_T nCount = 0;
539                for(CIterator Iterator(pT); Iterator.IsValid(); Iterator.Next(), nCount++)
540                        if(!(*pProcessElement)(pT->GetAt(Iterator)))
541                                break;
542                return nCount;
543        }
544        SIZE_T ForEach(BOOL (*pProcessElement)(_Element& Element))
545        {
546                _A(pProcessElement);
547                T* pT = static_cast<T*>(this);
548                SIZE_T nCount = 0;
549                for(CIterator Iterator(pT); Iterator.IsValid(); Iterator.Next(), nCount++)
550                        if(!(*pProcessElement)(pT->GetAt(Iterator)))
551                                break;
552                return nCount;
553        }
554        // TODO: ForEachThat
555
556// Range Iterator
557        ATL_FORCEINLINE typename CIterativeTraits<T>::CRangeIterator begin() const
558        {
559                return CRangeIterator::begin(static_cast<const T*>(this));
560        }
561        ATL_FORCEINLINE typename CIterativeTraits<T>::CRangeIterator end() const
562        {
563                return CRangeIterator::end(static_cast<const T*>(this));
564        }
565};
566
567////////////////////////////////////////////////////////////
568// CRoArrayT
569
570template <typename _Element, typename _ElementTraits = CElementTraits<_Element> >
571class CRoArrayT :
572        public CAtlArray<_Element, _ElementTraits>,
573        public CRoIterativeCollectionT<CRoArrayT<_Element, _ElementTraits>, CRoIterativeArrayTraitsT, _Element, _ElementTraits>
574{
575public:
576        typedef CAtlArray<_Element, _ElementTraits> CBaseArray;
577        typedef _Element CCollectionElement;
578        typedef CRoArrayT<_Element, _ElementTraits> CRoArray;
579
580private:
581
582        class CBasePrivateMembers
583        {
584        public:
585                _Element* m_pData;
586                SIZE_T m_nSize;
587                SIZE_T m_nMaxSize;
588                INT m_nGrowBy;
589
590        public:
591        // CBasePrivateMembers
592        };
593
594public:
595// CRoArrayT
596        #pragma region Hacks
597        SIZE_T GetCapacity() const throw()
598        {
599                _A(sizeof (CBaseArray) == sizeof (CBasePrivateMembers));
600                const CBasePrivateMembers* pMembers = reinterpret_cast<const CBasePrivateMembers*>(static_cast<const CBaseArray*>(this));
601                _A(pMembers->m_nSize == GetCount());
602                return pMembers->m_nMaxSize; 
603        }
604        BOOL SetCapacity(SIZE_T nCapacity)
605        {
606                __D(nCapacity >= GetCount(), E_UNNAMED);
607                _A(sizeof (CBaseArray) == sizeof (CBasePrivateMembers));
608                CBasePrivateMembers* pMembers = reinterpret_cast<CBasePrivateMembers*>(static_cast<CBaseArray*>(this));
609                _Element* pElements;
610                if(nCapacity)
611                {
612                        pElements = static_cast<_Element*>(calloc(nCapacity, sizeof (_Element)));
613                        if(!pElements)
614                                return FALSE;
615                } else
616                        pElements = NULL;
617                _ElementTraits::RelocateElements(pElements, pMembers->m_pData, pMembers->m_nSize);
618                free(pMembers->m_pData);
619                pMembers->m_pData = pElements;
620                pMembers->m_nMaxSize = nCapacity;
621                return TRUE;
622        }
623        VOID ImmediateSetCount(SIZE_T nCount)
624        {
625                _A(sizeof (CBaseArray) == sizeof (CBasePrivateMembers));
626                CBasePrivateMembers* pMembers = reinterpret_cast<CBasePrivateMembers*>(static_cast<CBaseArray*>(this));
627                _A(pMembers->m_nSize == GetCount());
628                __D(nCount <= pMembers->m_nMaxSize, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
629                pMembers->m_nSize = nCount;
630        }
631        #pragma endregion
632        SIZE_T AddNotFound(INARGTYPE Element)
633        {
634                SIZE_T nIndex;
635                if(!FindFirst(Element, &nIndex))
636                        nIndex = Add(Element);
637                _A(nIndex >= 0);
638                return nIndex;
639        }
640        template <typename CParameter>
641        VOID Sort(SSIZE_T nFirstIndex, SSIZE_T nLastIndex, INT_PTR (*pCompare)(const typename _ElementTraits::INARGTYPE, const typename _ElementTraits::INARGTYPE, CParameter Parameter), CParameter Parameter)
642        {
643                _A(pCompare);
644                if(nLastIndex - nFirstIndex < 1)
645                        return;
646                _Element* pElements = GetData();
647                SSIZE_T nIndex1 = nFirstIndex, nIndex2 = nLastIndex;
648                SSIZE_T nIndex3 = (nIndex1 + nIndex2) / 2;
649                while(nIndex1 <= nIndex2)
650                {
651                        while(pCompare(pElements[nIndex1], pElements[nIndex3], Parameter) < 0)
652                                nIndex1++;
653                        while(pCompare(pElements[nIndex3], pElements[nIndex2], Parameter) < 0)
654                                nIndex2--;
655                        if(nIndex1 <= nIndex2)
656                        {
657                                if(nIndex3 == nIndex1)
658                                        nIndex3 = nIndex2;
659                                else if(nIndex3 == nIndex2)
660                                        nIndex3 = nIndex1;
661                                _Element& ElementA = pElements[nIndex1++];
662                                _Element& ElementB = pElements[nIndex2--];
663                                CTempBufferT<_Element, sizeof (_Element)> pElement(1);
664                                _ElementTraits::RelocateElements(pElement, &ElementA, 1);
665                                _ElementTraits::RelocateElements(&ElementA, &ElementB, 1);
666                                _ElementTraits::RelocateElements(&ElementB, pElement, 1);
667                        }
668                }
669                if(nFirstIndex < nIndex2)
670                        Sort<CParameter>(nFirstIndex, nIndex2, pCompare, Parameter);
671                if(nIndex1 < nLastIndex)
672                        Sort<CParameter>(nIndex1, nLastIndex, pCompare, Parameter);
673        }
674        template <typename CParameter>
675        VOID Sort(INT_PTR (*pCompare)(const typename _ElementTraits::INARGTYPE, const typename _ElementTraits::INARGTYPE, CParameter Parameter), CParameter Parameter)
676        {
677                if(!IsEmpty())
678                        Sort<CParameter>(0, GetCount() - 1, pCompare, Parameter);
679        }
680        static INT_PTR DefaultCompare(const typename _ElementTraits::INARGTYPE Element1, const typename _ElementTraits::INARGTYPE Element2, INT)
681        {
682                return (Element1 < Element2) ? -1 : (Element1 <= Element2) ? 0 : +1;
683        }
684        VOID Sort()
685        {
686                if(!IsEmpty())
687                        Sort<INT>(0, GetCount() - 1, &CRoArray::DefaultCompare, 0);
688        }
689};
690
691////////////////////////////////////////////////////////////
692// CRoListT
693
694template <typename _Element, typename _ElementTraits = CElementTraits<_Element> >
695class CRoListT :
696        public CAtlList<_Element, _ElementTraits>,
697        public CRoIterativeCollectionT<CRoListT<_Element, _ElementTraits>, CRoIterativeListTraitsT, _Element, _ElementTraits>
698{
699public:
700        typedef CRoListT<_Element, _ElementTraits> CRoList;
701        typedef _Element CCollectionElement;
702
703public:
704// CRoListT
705        BOOL FindPositionIndex(POSITION Position, SIZE_T* pnIndex = NULL) const throw()
706        {
707                SIZE_T nIndex = 0;
708                for(CIterator Iterator(this); Iterator.IsValid(); Iterator.Next(), nIndex++)
709                        if(Iterator == Position)
710                        {
711                                if(pnIndex)
712                                        *pnIndex = nIndex;
713                                return TRUE;
714                        }
715                return FALSE;
716        }
717};
718
719////////////////////////////////////////////////////////////
720// CRoAssignableListT
721
722template <typename _Base>
723class CRoAssignableListT :
724        public _Base
725{
726public:
727// CRoAssignableListT
728        CRoAssignableListT() throw()
729        {
730        }
731        CRoAssignableListT(const CRoAssignableListT& Value)
732        {
733                *this = Value;
734        }
735        CRoAssignableListT& operator = (const CRoAssignableListT& Value)
736        {
737                RemoveAll();
738                AddTailList(&Value);
739                return *this;
740        }
741};
742
743////////////////////////////////////////////////////////////
744// CRoAssignableArrayT
745
746template <typename _Base>
747class CRoAssignableArrayT :
748        public _Base
749{
750public:
751// CRoAssignableArrayT
752        CRoAssignableArrayT() throw()
753        {
754        }
755        CRoAssignableArrayT(const CRoAssignableArrayT& Value)
756        {
757                *this = Value;
758        }
759        CRoAssignableArrayT& operator = (const CRoAssignableArrayT& Value)
760        {
761                RemoveAll();
762                Append(Value);
763                return *this;
764        }
765};
766
767////////////////////////////////////////////////////////////
768// CRoFixedArrayT
769
770template <typename _Element, SIZE_T t_nFixedCapacity, typename _ElementTraits = CElementTraits<_Element> >
771class CRoFixedArrayT :
772        public CRoIterativeCollectionT<CRoFixedArrayT<_Element, t_nFixedCapacity, _ElementTraits>, CRoIterativeArrayTraitsT, _Element, _ElementTraits>
773{
774public:
775        typedef typename _ElementTraits::INARGTYPE INARGTYPE;
776        typedef typename _ElementTraits::OUTARGTYPE OUTARGTYPE;
777
778protected:
779        typedef CRoFixedArrayT<_Element, t_nFixedCapacity, _ElementTraits> CRoFixedArray;
780
781private:
782        CTempBuffer<_Element, sizeof (_Element) * t_nFixedCapacity> m_pElements;
783        SIZE_T m_nCapacity;
784        SIZE_T m_nCount;
785
786#pragma push_macro("new")
787#undef new
788        static void CallConstructors(_Element* pElements, SIZE_T nCount)
789        {
790                SIZE_T nIndex = 0;
791                _ATLTRY
792                {
793                        for(; nIndex < nCount; nIndex++)
794                                ::new (pElements + nIndex) _Element;
795                }
796                _ATLCATCHALL()
797                {
798                        for(; nIndex > 0; nIndex--)
799                                pElements[nIndex - 1].~_Element();
800                        _ATLRETHROW;
801                }
802        }
803#pragma pop_macro("new")
804        static void CallDestructors(_Element* pElements, SIZE_T nCount) throw()
805        {
806                for(SIZE_T nIndex = 0; nIndex < nCount; nIndex++)
807                        pElements[nIndex].~_Element();
808        }
809
810public:
811// CRoFixedArrayT
812        static SIZE_T GetFixedCapacity() throw()
813        {
814                return t_nFixedCapacity;
815        }
816        CRoFixedArrayT() throw() :
817                m_pElements(GetFixedCapacity()),
818                m_nCapacity(GetFixedCapacity()),
819                m_nCount(0)
820        {
821        }
822        CRoFixedArrayT(SIZE_T nCapacity) :
823                m_pElements(nCapacity),
824                m_nCapacity(nCapacity),
825                m_nCount(0)
826        {
827        }
828        ~CRoFixedArrayT() throw()
829        {
830                if(m_nCount)
831                        CallDestructors(m_pElements, m_nCount);
832        }
833        SIZE_T GetCount() const throw()
834        {
835                return m_nCount;
836        }
837        BOOL IsEmpty() const throw()
838        {
839                return !m_nCount;
840        }
841        BOOL SetCount(SIZE_T nCount, INT nGrowBy = 0)
842        {
843                nGrowBy;
844                if(nCount == 0)
845                {
846                        // shrink to nothing
847                        if(m_nCount)
848                                CallDestructors(m_pElements, m_nCount);
849                        m_nCount = 0;
850                        return TRUE;
851                }
852                __D(nCount <= m_nCapacity, E_OUTOFMEMORY);
853                if(nCount > m_nCount)
854                        CallConstructors(m_pElements + m_nCount, nCount - m_nCount);
855                else if(m_nCount > nCount)
856                        CallDestructors(m_pElements + nCount, m_nCount - nCount);
857                m_nCount = nCount;
858                return TRUE;
859        }
860        const _Element* GetData() const throw()
861        {
862                return m_pElements;
863        }
864        _Element* GetData() throw()
865        {
866                return m_pElements;
867        }
868        const _Element& GetAt(SIZE_T nIndex) const throw()
869        {
870                _A(nIndex < m_nCount);
871                return m_pElements[nIndex];
872        }
873        _Element& GetAt(SIZE_T nIndex) throw()
874        {
875                _A(nIndex < m_nCount);
876                return m_pElements[nIndex];
877        }
878        //VOID SetAt(SIZE_T nIndex, INARGTYPE Element)
879#pragma push_macro("new")
880#undef new
881        SIZE_T Add()
882        {
883                __D(m_nCount < m_nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
884                const SIZE_T nIndex = m_nCount;
885                ::new (m_pElements + nIndex) _Element;
886                m_nCount++;
887                return nIndex;
888        }
889        SIZE_T Add(INARGTYPE Element)
890        {
891                __D(m_nCount < m_nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
892                const SIZE_T nIndex = m_nCount;
893                ::new (m_pElements + nIndex) _Element(Element);
894                m_nCount++;
895                return nIndex;
896        }
897#pragma pop_macro("new")
898        SIZE_T AddNotFound(INARGTYPE Element)
899        {
900                SIZE_T nIndex;
901                if(!FindFirst(Element, &nIndex))
902                        nIndex = Add(Element);
903                _A(nIndex >= 0);
904                return nIndex;
905        }
906        //VOID InsertAt(SIZE_T nIndex, INARGTYPE Element, SIZE_T nCount = 1)
907        template <typename _Array>
908        VOID Append(const _Array& Array)
909        {
910                // SUGG: Process at once without iterations
911                for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
912                        _W(Add(Array[nIndex]) >= 0);
913        }
914        VOID RemoveAt(SIZE_T nIndex, SIZE_T nCount = 1)
915        {
916                _A((nIndex + nCount) <= m_nCount);
917                const SIZE_T nMoveCount = m_nCount - (nIndex + nCount);
918                CallDestructors(m_pElements + nIndex, nCount);
919                if(nMoveCount > 0)
920                        _ElementTraits::RelocateElements(m_pElements + nIndex, m_pElements + nIndex + nCount, nMoveCount);
921                m_nCount -= nCount;
922        }
923        VOID RemoveAll() throw()
924        {
925                SetCount(0);
926        }
927        const _Element& operator [] (SIZE_T nIndex) const throw()
928        {
929                return GetAt(nIndex);
930        }
931        _Element& operator [] (SIZE_T nIndex) throw()
932        {
933                return GetAt(nIndex);
934        }
935};
936
937////////////////////////////////////////////////////////////
938// CRoMapT
939
940template<typename _KeyElement, typename _Element, class _KeyElementTraits = CElementTraits<_KeyElement>, class _ElementTraits = CElementTraits<_Element> >
941class CRoMapT :
942        public CAtlMap<_KeyElement, _Element, _KeyElementTraits, _ElementTraits>,
943        public CRoIterativeTraitsBase
944{
945public:
946        typedef CAtlMap<_KeyElement, _Element, _KeyElementTraits, _ElementTraits> CBaseMap;
947        typedef CRoMapT<_KeyElement, _Element, _KeyElementTraits, _ElementTraits> CMap;
948        typedef _KeyElement CCollectionKeyElement;
949        typedef _Element CCollectionElement;
950
951        ////////////////////////////////////////////////////////
952        // CPositionRangeIterator
953
954        class CPositionRangeIterator
955        {
956        public:
957                const CMap& m_Map;
958                POSITION m_Position;
959
960        public:
961        // CPositionRangeIterator
962                ATL_FORCEINLINE CPositionRangeIterator(const CMap* pMap, POSITION Position) :
963                        m_Map(*pMap),
964                        m_Position(Position)
965                {
966                        _A(pMap);
967                }
968                ATL_FORCEINLINE BOOL operator == (const CPositionRangeIterator& Position) const
969                {
970                        _A(&m_Map == &Position.m_Map);
971                        return m_Position == Position.m_Position;
972                }
973                ATL_FORCEINLINE BOOL operator != (const CPositionRangeIterator& Position) const
974                {
975                        return !(*this == Position);
976                }
977                ATL_FORCEINLINE CPositionRangeIterator& operator ++ ()
978                {
979                        m_Map.GetNext(m_Position);
980                        return *this;
981                }
982                ATL_FORCEINLINE operator const POSITION* () const
983                {
984                        return &m_Position;
985                }
986                ATL_FORCEINLINE operator typename POSITION* ()
987                {
988                        return &m_Position;
989                }
990                ATL_FORCEINLINE static CPositionRangeIterator begin(const CMap* pMap)
991                {
992                        return CPositionRangeIterator(pMap, pMap->GetStartPosition());
993                }
994                ATL_FORCEINLINE static CPositionRangeIterator end(const CMap* pMap)
995                {
996                        return CPositionRangeIterator(pMap, NULL);
997                }
998        };
999
1000        ////////////////////////////////////////////////////////
1001        // CPositions
1002
1003        class CPositions
1004        {
1005        public:
1006                const CMap* m_pMap;
1007
1008        public:
1009        // CPositions
1010                ATL_FORCEINLINE CPositions(const CMap* pMap) :
1011                        m_pMap(pMap)
1012                {
1013                        _A(pMap);
1014                }
1015
1016        // Range Iterator
1017                ATL_FORCEINLINE CPositionRangeIterator begin() const
1018                {
1019                        return CPositionRangeIterator::begin(m_pMap);
1020                }
1021                ATL_FORCEINLINE CPositionRangeIterator end() const
1022                {
1023                        return CPositionRangeIterator::end(m_pMap);
1024                }
1025        };
1026
1027        ////////////////////////////////////////////////////////
1028        // CKeyRangeIterator
1029
1030        class CKeyRangeIterator
1031        {
1032        public:
1033                const CMap& m_Map;
1034                POSITION m_Position;
1035
1036        public:
1037        // CKeyRangeIterator
1038                ATL_FORCEINLINE CKeyRangeIterator(const CMap* pMap, POSITION Position) :
1039                        m_Map(*pMap),
1040                        m_Position(Position)
1041                {
1042                        _A(pMap);
1043                }
1044                ATL_FORCEINLINE BOOL operator == (const CKeyRangeIterator& Key) const
1045                {
1046                        _A(&m_Map == &Key.m_Map);
1047                        return m_Position == Key.m_Position;
1048                }
1049                ATL_FORCEINLINE BOOL operator != (const CKeyRangeIterator& Key) const
1050                {
1051                        return !(*this == Key);
1052                }
1053                ATL_FORCEINLINE CKeyRangeIterator& operator ++ ()
1054                {
1055                        m_Map.GetNext(m_Position);
1056                        return *this;
1057                }
1058                ATL_FORCEINLINE operator const typename CMap::CCollectionKeyElement* () const
1059                {
1060                        _A(m_Position);
1061                        const typename CMap::CCollectionKeyElement& Element = m_Map.GetKeyAt(m_Position);
1062                        const CAddressT<const typename CMap::CCollectionKeyElement>& ElementAddress = reinterpret_cast<const CAddressT<const typename CMap::CCollectionKeyElement>&>(Element);
1063                        return &ElementAddress;
1064                }
1065                ATL_FORCEINLINE static CKeyRangeIterator begin(const CMap* pMap)
1066                {
1067                        return CKeyRangeIterator(pMap, pMap->GetStartPosition());
1068                }
1069                ATL_FORCEINLINE static CKeyRangeIterator end(const CMap* pMap)
1070                {
1071                        return CKeyRangeIterator(pMap, NULL);
1072                }
1073        };
1074
1075        ////////////////////////////////////////////////////////
1076        // CKeys
1077
1078        class CKeys
1079        {
1080        public:
1081                const CMap* m_pMap;
1082
1083        public:
1084        // CKeys
1085                ATL_FORCEINLINE CKeys(const CMap* pMap) :
1086                        m_pMap(pMap)
1087                {
1088                        _A(pMap);
1089                }
1090
1091        // Range Iterator
1092                ATL_FORCEINLINE CKeyRangeIterator begin() const
1093                {
1094                        return CKeyRangeIterator::begin(m_pMap);
1095                }
1096                ATL_FORCEINLINE CKeyRangeIterator end() const
1097                {
1098                        return CKeyRangeIterator::end(m_pMap);
1099                }
1100        };
1101
1102        ////////////////////////////////////////////////////////
1103        // CValueRangeIterator
1104
1105        class CValueRangeIterator
1106        {
1107        public:
1108                const CMap& m_Map;
1109                POSITION m_Position;
1110
1111        public:
1112        // CValueRangeIterator
1113                ATL_FORCEINLINE CValueRangeIterator(const CMap* pMap, POSITION Position) :
1114                        m_Map(*pMap),
1115                        m_Position(Position)
1116                {
1117                        _A(pMap);
1118                }
1119                ATL_FORCEINLINE BOOL operator == (const CValueRangeIterator& Value) const
1120                {
1121                        _A(&m_Map == &Value.m_Map);
1122                        return m_Position == Value.m_Position;
1123                }
1124                ATL_FORCEINLINE BOOL operator != (const CValueRangeIterator& Value) const
1125                {
1126                        return !(*this == Value);
1127                }
1128                ATL_FORCEINLINE CValueRangeIterator& operator ++ ()
1129                {
1130                        m_Map.GetNext(m_Position);
1131                        return *this;
1132                }
1133                ATL_FORCEINLINE operator const typename CMap::CCollectionElement* () const
1134                {
1135                        _A(m_Position);
1136                        const typename CMap::CCollectionElement& Element = m_Map.GetValueAt(m_Position);
1137                        CAddressT<typename CMap::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CMap::CCollectionElement>&>(Element);
1138                        return &ElementAddress;
1139                }
1140                ATL_FORCEINLINE operator typename CMap::CCollectionElement* ()
1141                {
1142                        _A(m_Position);
1143                        typename CMap::CCollectionElement& Element = const_cast<CMap&>(m_Map).GetValueAt(m_Position);
1144                        CAddressT<typename CMap::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CMap::CCollectionElement>&>(Element);
1145                        return &ElementAddress;
1146                }
1147                ATL_FORCEINLINE static CValueRangeIterator begin(const CMap* pMap)
1148                {
1149                        return CValueRangeIterator(pMap, pMap->GetStartPosition());
1150                }
1151                ATL_FORCEINLINE static CValueRangeIterator end(const CMap* pMap)
1152                {
1153                        return CValueRangeIterator(pMap, NULL);
1154                }
1155        };
1156
1157        ////////////////////////////////////////////////////////
1158        // CValues
1159
1160        class CValues
1161        {
1162        public:
1163                const CMap* m_pMap;
1164
1165        public:
1166        // CValues
1167                ATL_FORCEINLINE CValues(const CMap* pMap) :
1168                        m_pMap(pMap)
1169                {
1170                        _A(pMap);
1171                }
1172
1173        // Range Iterator
1174                ATL_FORCEINLINE CValueRangeIterator begin() const
1175                {
1176                        return CValueRangeIterator::begin(m_pMap);
1177                }
1178                ATL_FORCEINLINE CValueRangeIterator end() const
1179                {
1180                        return CValueRangeIterator::end(m_pMap);
1181                }
1182        };
1183
1184public:
1185// CRoMapT
1186        CPositions GetPositions() const
1187        {
1188                return CPositions(this);
1189        }
1190        CKeys GetKeys() const
1191        {
1192                return CKeys(this);
1193        }
1194        CValues GetValues() const
1195        {
1196                return CValues(this);
1197        }
1198};
1199
1200////////////////////////////////////////////////////////////
1201// CRoMapT
1202
1203template<typename _KeyElement, typename _Element, SIZE_T t_nFixedCapacity, class _KeyElementTraits = CElementTraits<_KeyElement>, class _ElementTraits = CElementTraits<_Element> >
1204class CRoFixedMapT
1205{
1206        typedef CRoFixedArrayT<_KeyElement, t_nFixedCapacity, _KeyElementTraits> CKeyElementArray;
1207        typedef CRoFixedArrayT<_Element, t_nFixedCapacity, _ElementTraits> CElementArray;
1208
1209public:
1210        typedef typename _KeyElementTraits::INARGTYPE KINARGTYPE;
1211        typedef typename _KeyElementTraits::OUTARGTYPE KOUTARGTYPE;
1212        typedef typename _ElementTraits::INARGTYPE VINARGTYPE;
1213        typedef typename _ElementTraits::OUTARGTYPE VOUTARGTYPE;
1214
1215private:
1216        CKeyElementArray m_KeyElementArray;
1217        CElementArray m_ElementArray;
1218
1219        static POSITION PositionFromIndex(SIZE_T nIndex) throw()
1220        {
1221                return (POSITION) (nIndex + 1);
1222        }
1223        static SIZE_T IndexFromPosition(POSITION Position) throw()
1224        {
1225                _A(Position);
1226                return (SIZE_T) Position - 1;
1227        }
1228
1229public:
1230// CRoFixedMapT
1231        static SIZE_T GetFixedCapacity() throw()
1232        {
1233                return t_nFixedCapacity;
1234        }
1235        CRoFixedMapT() throw()
1236        {
1237        }
1238        SIZE_T GetCount() const throw()
1239        {
1240                _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1241                return m_KeyElementArray.GetCount();
1242        }
1243        BOOL IsEmpty() const throw()
1244        {
1245                _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1246                return m_KeyElementArray.IsEmpty();
1247        }
1248        BOOL Lookup(KINARGTYPE Key, VOUTARGTYPE Value) const
1249        {
1250                for(SIZE_T nIndex = 0; nIndex < m_KeyElementArray.GetCount(); nIndex++)
1251                        if(_KeyElementTraits::CompareElements(m_KeyElementArray[nIndex], Key))
1252                        {
1253                                Value = m_ElementArray[nIndex];
1254                                return TRUE;
1255                        }
1256                return FALSE;
1257        }
1258        POSITION Lookup(KINARGTYPE Key) const throw()
1259        {
1260                for(SIZE_T nIndex = 0; nIndex < m_KeyElementArray.GetCount(); nIndex++)
1261                        if(_KeyElementTraits::CompareElements(m_KeyElementArray[nIndex], Key))
1262                                return PositionFromIndex(nIndex);
1263                return NULL;
1264        }
1265        //const CPair* Lookup(KINARGTYPE key) const throw()
1266        //CPair* Lookup(KINARGTYPE key) throw()
1267        _Element& operator[] (KINARGTYPE Key)
1268        {
1269                const POSITION Position = Lookup(Key);
1270                if(Position)
1271                        return GetValueAt(Position);
1272                const SIZE_T nIndex = m_KeyElementArray.Add(Key);
1273                _A((SSIZE_T) nIndex >= 0);
1274                _W(m_ElementArray.Add() == nIndex);
1275                _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1276                return m_ElementArray[nIndex];
1277        }
1278        POSITION SetAt(KINARGTYPE Key, VINARGTYPE Value)
1279        {
1280                POSITION Position = Lookup(Key);
1281                if(!Position)
1282                {
1283                        const SIZE_T nIndex = m_KeyElementArray.Add(Key);
1284                        _A((SSIZE_T) nIndex >= 0);
1285                        _W(m_ElementArray.Add(Value) == nIndex);
1286                        _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1287                        Position = PositionFromIndex(nIndex);
1288                } else
1289                        GetValueAt(Position) = Value;
1290                return Position;
1291        }
1292        //VOID SetValueAt(POSITION Position, VINARGTYPE Value)
1293        BOOL RemoveKey(KINARGTYPE Key) throw()
1294        {
1295                const POSITION Position = Lookup(Key);
1296                if(!Position)
1297                        return FALSE;
1298                RemoveAtPos(Position);
1299                return TRUE;
1300        }
1301        VOID RemoveAll() throw()
1302        {
1303                m_KeyElementArray.RemoveAll();
1304                m_ElementArray.RemoveAll();
1305        }
1306        VOID RemoveAtPos(POSITION Position) throw()
1307        {
1308                const SIZE_T nIndex = IndexFromPosition(Position);
1309                m_KeyElementArray.RemoveAt(nIndex);
1310                m_ElementArray.RemoveAt(nIndex);
1311        }
1312        POSITION GetStartPosition() const throw()
1313        {
1314                if(!IsEmpty())
1315                        return PositionFromIndex(0);
1316                return NULL;
1317        }
1318        //VOID GetNextAssoc(POSITION& Position, KOUTARGTYPE Key, VOUTARGTYPE Value) const
1319        POSITION GetNext(POSITION& Position) const throw()
1320        {
1321                _A(Position);
1322                reinterpret_cast<BYTE*&>(Position)++;
1323                if(IndexFromPosition(Position) >= m_KeyElementArray.GetCount())
1324                        Position = NULL;
1325                return Position;
1326        }
1327        //CPair* GetNext(POSITION& Position) throw()
1328        //const _KeyElement& GetNextKey(POSITION& Position) const
1329        //const _Element& GetNextValue(POSITION& Position) const
1330        //_Element& GetNextValue(POSITION& Position)
1331        //VOID GetAt(POSITION Position, KOUTARGTYPE Key, VOUTARGTYPE Value) const
1332        //CPair* GetAt(POSITION Position) throw()
1333        //const CPair* GetAt(POSITION Position) const throw()
1334        const _KeyElement& GetKeyAt(POSITION Position) const
1335        {
1336                _A(Position);
1337                const SIZE_T nIndex = IndexFromPosition(Position);
1338                return m_KeyElementArray[nIndex];
1339        }
1340        const _Element& GetValueAt(POSITION Position) const
1341        {
1342                _A(Position);
1343                const SIZE_T nIndex = IndexFromPosition(Position);
1344                return m_ElementArray[nIndex];
1345        }
1346        _Element& GetValueAt(POSITION Position)
1347        {
1348                _A(Position);
1349                const SIZE_T nIndex = IndexFromPosition(Position);
1350                return m_ElementArray[nIndex];
1351        }
1352};
1353
1354////////////////////////////////////////////////////////////
1355// CRoAssignableMapT
1356
1357template <typename _Base>
1358class CRoAssignableMapT :
1359        public _Base
1360{
1361public:
1362// CRoAssignableMapT
1363        CRoAssignableMapT() throw()
1364        {
1365        }
1366        CRoAssignableMapT(const CRoAssignableMapT& Value)
1367        {
1368                *this = Value;
1369        }
1370        CRoAssignableMapT& operator = (const CRoAssignableMapT& Value)
1371        {
1372                RemoveAll();
1373                for(POSITION Position = Value.GetStartPosition(); Position; Value.GetNext(Position))
1374                        _W(SetAt(Value.GetKeyAt(Position), Value.GetValueAt(Position)));
1375                return *this;
1376        }
1377};
1378
Note: See TracBrowser for help on using the repository browser.