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

Last change on this file since 463 was 463, checked in by roman, 9 years ago

Update with improved collection classes, esp. with range-for support

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