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

Last change on this file since 482 was 482, checked in by roman, 7 years ago

Updated copyright notice

  • Property svn:keywords set to Id
File size: 34.4 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
579private:
580
581        class CBasePrivateMembers
582        {
583        public:
584                _Element* m_pData;
585                SIZE_T m_nSize;
586                SIZE_T m_nMaxSize;
587                INT m_nGrowBy;
588
589        public:
590        // CBasePrivateMembers
591        };
592
593public:
594// CRoArrayT
595        #pragma region Hacks
596        SIZE_T GetCapacity() const throw()
597        {
598                _A(sizeof (CBaseArray) == sizeof (CBasePrivateMembers));
599                const CBasePrivateMembers* pMembers = reinterpret_cast<const CBasePrivateMembers*>(static_cast<const CBaseArray*>(this));
600                _A(pMembers->m_nSize == GetCount());
601                return pMembers->m_nMaxSize; 
602        }
603        BOOL SetCapacity(SIZE_T nCapacity)
604        {
605                __D(nCapacity >= GetCount(), E_UNNAMED);
606                _A(sizeof (CBaseArray) == sizeof (CBasePrivateMembers));
607                CBasePrivateMembers* pMembers = reinterpret_cast<CBasePrivateMembers*>(static_cast<CBaseArray*>(this));
608                _Element* pElements;
609                if(nCapacity)
610                {
611                        pElements = static_cast<_Element*>(calloc(nCapacity, sizeof (_Element)));
612                        if(!pElements)
613                                return FALSE;
614                } else
615                        pElements = NULL;
616                _ElementTraits::RelocateElements(pElements, pMembers->m_pData, pMembers->m_nSize);
617                free(pMembers->m_pData);
618                pMembers->m_pData = pElements;
619                pMembers->m_nMaxSize = nCapacity;
620                return TRUE;
621        }
622        VOID ImmediateSetCount(SIZE_T nCount)
623        {
624                _A(sizeof (CBaseArray) == sizeof (CBasePrivateMembers));
625                CBasePrivateMembers* pMembers = reinterpret_cast<CBasePrivateMembers*>(static_cast<CBaseArray*>(this));
626                _A(pMembers->m_nSize == GetCount());
627                __D(nCount <= pMembers->m_nMaxSize, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
628                pMembers->m_nSize = nCount;
629        }
630        #pragma endregion
631        SIZE_T AddNotFound(INARGTYPE Element)
632        {
633                SIZE_T nIndex;
634                if(!FindFirst(Element, &nIndex))
635                        nIndex = Add(Element);
636                _A(nIndex >= 0);
637                return nIndex;
638        }
639};
640
641////////////////////////////////////////////////////////////
642// CRoListT
643
644template <typename _Element, typename _ElementTraits = CElementTraits<_Element> >
645class CRoListT :
646        public CAtlList<_Element, _ElementTraits>,
647        public CRoIterativeCollectionT<CRoListT<_Element, _ElementTraits>, CRoIterativeListTraitsT, _Element, _ElementTraits>
648{
649public:
650        typedef CRoListT<_Element, _ElementTraits> CRoList;
651        typedef _Element CCollectionElement;
652
653public:
654// CRoListT
655        BOOL FindPositionIndex(POSITION Position, SIZE_T* pnIndex = NULL) const throw()
656        {
657                SIZE_T nIndex = 0;
658                for(CIterator Iterator(this); Iterator.IsValid(); Iterator.Next(), nIndex++)
659                        if(Iterator == Position)
660                        {
661                                if(pnIndex)
662                                        *pnIndex = nIndex;
663                                return TRUE;
664                        }
665                return FALSE;
666        }
667};
668
669////////////////////////////////////////////////////////////
670// CRoAssignableListT
671
672template <typename _Base>
673class CRoAssignableListT :
674        public _Base
675{
676public:
677// CRoAssignableListT
678        CRoAssignableListT() throw()
679        {
680        }
681        CRoAssignableListT(const CRoAssignableListT& Value)
682        {
683                *this = Value;
684        }
685        CRoAssignableListT& operator = (const CRoAssignableListT& Value)
686        {
687                RemoveAll();
688                AddTailList(&Value);
689                return *this;
690        }
691};
692
693////////////////////////////////////////////////////////////
694// CRoAssignableArrayT
695
696template <typename _Base>
697class CRoAssignableArrayT :
698        public _Base
699{
700public:
701// CRoAssignableArrayT
702        CRoAssignableArrayT() throw()
703        {
704        }
705        CRoAssignableArrayT(const CRoAssignableArrayT& Value)
706        {
707                *this = Value;
708        }
709        CRoAssignableArrayT& operator = (const CRoAssignableArrayT& Value)
710        {
711                RemoveAll();
712                Append(Value);
713                return *this;
714        }
715};
716
717////////////////////////////////////////////////////////////
718// CRoFixedArrayT
719
720template <typename _Element, SIZE_T t_nFixedCapacity, typename _ElementTraits = CElementTraits<_Element> >
721class CRoFixedArrayT :
722        public CRoIterativeCollectionT<CRoFixedArrayT<_Element, t_nFixedCapacity, _ElementTraits>, CRoIterativeArrayTraitsT, _Element, _ElementTraits>
723{
724public:
725        typedef typename _ElementTraits::INARGTYPE INARGTYPE;
726        typedef typename _ElementTraits::OUTARGTYPE OUTARGTYPE;
727
728protected:
729        typedef CRoFixedArrayT<_Element, t_nFixedCapacity, _ElementTraits> CRoFixedArray;
730
731private:
732        CTempBuffer<_Element, sizeof (_Element) * t_nFixedCapacity> m_pElements;
733        SIZE_T m_nCapacity;
734        SIZE_T m_nCount;
735
736#pragma push_macro("new")
737#undef new
738        static void CallConstructors(_Element* pElements, SIZE_T nCount)
739        {
740                SIZE_T nIndex = 0;
741                _ATLTRY
742                {
743                        for(; nIndex < nCount; nIndex++)
744                                ::new (pElements + nIndex) _Element;
745                }
746                _ATLCATCHALL()
747                {
748                        for(; nIndex > 0; nIndex--)
749                                pElements[nIndex - 1].~_Element();
750                        _ATLRETHROW;
751                }
752        }
753#pragma pop_macro("new")
754        static void CallDestructors(_Element* pElements, SIZE_T nCount) throw()
755        {
756                for(SIZE_T nIndex = 0; nIndex < nCount; nIndex++)
757                        pElements[nIndex].~_Element();
758        }
759
760public:
761// CRoFixedArrayT
762        static SIZE_T GetFixedCapacity() throw()
763        {
764                return t_nFixedCapacity;
765        }
766        CRoFixedArrayT() throw() :
767                m_pElements(GetFixedCapacity()),
768                m_nCapacity(GetFixedCapacity()),
769                m_nCount(0)
770        {
771        }
772        CRoFixedArrayT(SIZE_T nCapacity) :
773                m_pElements(nCapacity),
774                m_nCapacity(nCapacity),
775                m_nCount(0)
776        {
777        }
778        ~CRoFixedArrayT() throw()
779        {
780                if(m_nCount)
781                        CallDestructors(m_pElements, m_nCount);
782        }
783        SIZE_T GetCount() const throw()
784        {
785                return m_nCount;
786        }
787        BOOL IsEmpty() const throw()
788        {
789                return !m_nCount;
790        }
791        BOOL SetCount(SIZE_T nCount, INT nGrowBy = 0)
792        {
793                nGrowBy;
794                if(nCount == 0)
795                {
796                        // shrink to nothing
797                        if(m_nCount)
798                                CallDestructors(m_pElements, m_nCount);
799                        m_nCount = 0;
800                        return TRUE;
801                }
802                __D(nCount <= m_nCapacity, E_OUTOFMEMORY);
803                if(nCount > m_nCount)
804                        CallConstructors(m_pElements + m_nCount, nCount - m_nCount);
805                else if(m_nCount > nCount)
806                        CallDestructors(m_pElements + nCount, m_nCount - nCount);
807                m_nCount = nCount;
808                return TRUE;
809        }
810        const _Element* GetData() const throw()
811        {
812                return m_pElements;
813        }
814        _Element* GetData() throw()
815        {
816                return m_pElements;
817        }
818        const _Element& GetAt(SIZE_T nIndex) const throw()
819        {
820                _A(nIndex < m_nCount);
821                return m_pElements[nIndex];
822        }
823        _Element& GetAt(SIZE_T nIndex) throw()
824        {
825                _A(nIndex < m_nCount);
826                return m_pElements[nIndex];
827        }
828        //VOID SetAt(SIZE_T nIndex, INARGTYPE Element)
829#pragma push_macro("new")
830#undef new
831        SIZE_T Add()
832        {
833                __D(m_nCount < m_nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
834                const SIZE_T nIndex = m_nCount;
835                ::new (m_pElements + nIndex) _Element;
836                m_nCount++;
837                return nIndex;
838        }
839        SIZE_T Add(INARGTYPE Element)
840        {
841                __D(m_nCount < m_nCapacity, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
842                const SIZE_T nIndex = m_nCount;
843                ::new (m_pElements + nIndex) _Element(Element);
844                m_nCount++;
845                return nIndex;
846        }
847#pragma pop_macro("new")
848        SIZE_T AddNotFound(INARGTYPE Element)
849        {
850                SIZE_T nIndex;
851                if(!FindFirst(Element, &nIndex))
852                        nIndex = Add(Element);
853                _A(nIndex >= 0);
854                return nIndex;
855        }
856        //VOID InsertAt(SIZE_T nIndex, INARGTYPE Element, SIZE_T nCount = 1)
857        template <typename _Array>
858        VOID Append(const _Array& Array)
859        {
860                // SUGG: Process at once without iterations
861                for(SIZE_T nIndex = 0; nIndex < Array.GetCount(); nIndex++)
862                        _W(Add(Array[nIndex]) >= 0);
863        }
864        VOID RemoveAt(SIZE_T nIndex, SIZE_T nCount = 1)
865        {
866                _A((nIndex + nCount) <= m_nCount);
867                const SIZE_T nMoveCount = m_nCount - (nIndex + nCount);
868                CallDestructors(m_pElements + nIndex, nCount);
869                if(nMoveCount > 0)
870                        _ElementTraits::RelocateElements(m_pElements + nIndex, m_pElements + nIndex + nCount, nMoveCount);
871                m_nCount -= nCount;
872        }
873        VOID RemoveAll() throw()
874        {
875                SetCount(0);
876        }
877        const _Element& operator [] (SIZE_T nIndex) const throw()
878        {
879                return GetAt(nIndex);
880        }
881        _Element& operator [] (SIZE_T nIndex) throw()
882        {
883                return GetAt(nIndex);
884        }
885};
886
887////////////////////////////////////////////////////////////
888// CRoMapT
889
890template<typename _KeyElement, typename _Element, class _KeyElementTraits = CElementTraits<_KeyElement>, class _ElementTraits = CElementTraits<_Element> >
891class CRoMapT :
892        public CAtlMap<_KeyElement, _Element, _KeyElementTraits, _ElementTraits>,
893        public CRoIterativeTraitsBase
894{
895public:
896        typedef CAtlMap<_KeyElement, _Element, _KeyElementTraits, _ElementTraits> CBaseMap;
897        typedef CRoMapT<_KeyElement, _Element, _KeyElementTraits, _ElementTraits> CMap;
898        typedef _Element CCollectionElement;
899
900        ////////////////////////////////////////////////////////
901        // CPositionRangeIterator
902
903        class CPositionRangeIterator
904        {
905        public:
906                const CMap& m_Map;
907                POSITION m_Position;
908
909        public:
910        // CPositionRangeIterator
911                ATL_FORCEINLINE CPositionRangeIterator(const CMap* pMap, POSITION Position) :
912                        m_Map(*pMap),
913                        m_Position(Position)
914                {
915                        _A(pMap);
916                }
917                ATL_FORCEINLINE BOOL operator == (const CPositionRangeIterator& Position) const
918                {
919                        _A(&m_Map == &Position.m_Map);
920                        return m_Position == Position.m_Position;
921                }
922                ATL_FORCEINLINE BOOL operator != (const CPositionRangeIterator& Position) const
923                {
924                        return !(*this == Position);
925                }
926                ATL_FORCEINLINE CPositionRangeIterator& operator ++ ()
927                {
928                        m_Map.GetNext(m_Position);
929                        return *this;
930                }
931                ATL_FORCEINLINE operator const POSITION* () const
932                {
933                        return &m_Position;
934                }
935                ATL_FORCEINLINE operator typename POSITION* ()
936                {
937                        return &m_Position;
938                }
939                ATL_FORCEINLINE static CPositionRangeIterator begin(const CMap* pMap)
940                {
941                        return CPositionRangeIterator(pMap, pMap->GetStartPosition());
942                }
943                ATL_FORCEINLINE static CPositionRangeIterator end(const CMap* pMap)
944                {
945                        return CPositionRangeIterator(pMap, NULL);
946                }
947        };
948
949        ////////////////////////////////////////////////////////
950        // CPositions
951
952        class CPositions
953        {
954        public:
955                const CMap* m_pMap;
956
957        public:
958        // CPositions
959                ATL_FORCEINLINE CPositions(const CMap* pMap) :
960                        m_pMap(pMap)
961                {
962                        _A(pMap);
963                }
964
965        // Range Iterator
966                ATL_FORCEINLINE CPositionRangeIterator begin() const
967                {
968                        return CPositionRangeIterator::begin(m_pMap);
969                }
970                ATL_FORCEINLINE CPositionRangeIterator end() const
971                {
972                        return CPositionRangeIterator::end(m_pMap);
973                }
974        };
975
976        ////////////////////////////////////////////////////////
977        // CValueRangeIterator
978
979        class CValueRangeIterator
980        {
981        public:
982                const CMap& m_Map;
983                POSITION m_Position;
984
985        public:
986        // CValueRangeIterator
987                ATL_FORCEINLINE CValueRangeIterator(const CMap* pMap, POSITION Position) :
988                        m_Map(*pMap),
989                        m_Position(Position)
990                {
991                        _A(pMap);
992                }
993                ATL_FORCEINLINE BOOL operator == (const CValueRangeIterator& Value) const
994                {
995                        _A(&m_Map == &Value.m_Map);
996                        return m_Position == Value.m_Position;
997                }
998                ATL_FORCEINLINE BOOL operator != (const CValueRangeIterator& Value) const
999                {
1000                        return !(*this == Value);
1001                }
1002                ATL_FORCEINLINE CValueRangeIterator& operator ++ ()
1003                {
1004                        m_Map.GetNext(m_Position);
1005                        return *this;
1006                }
1007                ATL_FORCEINLINE operator const typename CMap::CCollectionElement* () const
1008                {
1009                        _A(m_Position);
1010                        const typename CMap::CCollectionElement& Element = m_Map.GetValueAt(m_Position);
1011                        CAddressT<typename CMap::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CMap::CCollectionElement>&>(Element);
1012                        return &ElementAddress;
1013                }
1014                ATL_FORCEINLINE operator typename CMap::CCollectionElement* ()
1015                {
1016                        _A(m_Position);
1017                        typename CMap::CCollectionElement& Element = const_cast<CMap&>(m_Map).GetValueAt(m_Position);
1018                        CAddressT<typename CMap::CCollectionElement>& ElementAddress = reinterpret_cast<CAddressT<typename CMap::CCollectionElement>&>(Element);
1019                        return &ElementAddress;
1020                }
1021                ATL_FORCEINLINE static CValueRangeIterator begin(const CMap* pMap)
1022                {
1023                        return CValueRangeIterator(pMap, pMap->GetStartPosition());
1024                }
1025                ATL_FORCEINLINE static CValueRangeIterator end(const CMap* pMap)
1026                {
1027                        return CValueRangeIterator(pMap, NULL);
1028                }
1029        };
1030
1031        ////////////////////////////////////////////////////////
1032        // CValues
1033
1034        class CValues
1035        {
1036        public:
1037                const CMap* m_pMap;
1038
1039        public:
1040        // CValues
1041                ATL_FORCEINLINE CValues(const CMap* pMap) :
1042                        m_pMap(pMap)
1043                {
1044                        _A(pMap);
1045                }
1046
1047        // Range Iterator
1048                ATL_FORCEINLINE CValueRangeIterator begin() const
1049                {
1050                        return CValueRangeIterator::begin(m_pMap);
1051                }
1052                ATL_FORCEINLINE CValueRangeIterator end() const
1053                {
1054                        return CValueRangeIterator::end(m_pMap);
1055                }
1056        };
1057
1058public:
1059// CRoMapT
1060        CPositions GetPositions() const
1061        {
1062                return CPositions(this);
1063        }
1064        CValues GetValues() const
1065        {
1066                return CValues(this);
1067        }
1068};
1069
1070////////////////////////////////////////////////////////////
1071// CRoMapT
1072
1073template<typename _KeyElement, typename _Element, SIZE_T t_nFixedCapacity, class _KeyElementTraits = CElementTraits<_KeyElement>, class _ElementTraits = CElementTraits<_Element> >
1074class CRoFixedMapT
1075{
1076        typedef CRoFixedArrayT<_KeyElement, t_nFixedCapacity, _KeyElementTraits> CKeyElementArray;
1077        typedef CRoFixedArrayT<_Element, t_nFixedCapacity, _ElementTraits> CElementArray;
1078
1079public:
1080        typedef typename _KeyElementTraits::INARGTYPE KINARGTYPE;
1081        typedef typename _KeyElementTraits::OUTARGTYPE KOUTARGTYPE;
1082        typedef typename _ElementTraits::INARGTYPE VINARGTYPE;
1083        typedef typename _ElementTraits::OUTARGTYPE VOUTARGTYPE;
1084
1085private:
1086        CKeyElementArray m_KeyElementArray;
1087        CElementArray m_ElementArray;
1088
1089        static POSITION PositionFromIndex(SIZE_T nIndex) throw()
1090        {
1091                return (POSITION) (nIndex + 1);
1092        }
1093        static SIZE_T IndexFromPosition(POSITION Position) throw()
1094        {
1095                _A(Position);
1096                return (SIZE_T) Position - 1;
1097        }
1098
1099public:
1100// CRoFixedMapT
1101        static SIZE_T GetFixedCapacity() throw()
1102        {
1103                return t_nFixedCapacity;
1104        }
1105        CRoFixedMapT() throw()
1106        {
1107        }
1108        SIZE_T GetCount() const throw()
1109        {
1110                _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1111                return m_KeyElementArray.GetCount();
1112        }
1113        BOOL IsEmpty() const throw()
1114        {
1115                _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1116                return m_KeyElementArray.IsEmpty();
1117        }
1118        BOOL Lookup(KINARGTYPE Key, VOUTARGTYPE Value) const
1119        {
1120                for(SIZE_T nIndex = 0; nIndex < m_KeyElementArray.GetCount(); nIndex++)
1121                        if(_KeyElementTraits::CompareElements(m_KeyElementArray[nIndex], Key))
1122                        {
1123                                Value = m_ElementArray[nIndex];
1124                                return TRUE;
1125                        }
1126                return FALSE;
1127        }
1128        POSITION Lookup(KINARGTYPE Key) const throw()
1129        {
1130                for(SIZE_T nIndex = 0; nIndex < m_KeyElementArray.GetCount(); nIndex++)
1131                        if(_KeyElementTraits::CompareElements(m_KeyElementArray[nIndex], Key))
1132                                return PositionFromIndex(nIndex);
1133                return NULL;
1134        }
1135        //const CPair* Lookup(KINARGTYPE key) const throw()
1136        //CPair* Lookup(KINARGTYPE key) throw()
1137        _Element& operator[] (KINARGTYPE Key)
1138        {
1139                const POSITION Position = Lookup(Key);
1140                if(Position)
1141                        return GetValueAt(Position);
1142                const SIZE_T nIndex = m_KeyElementArray.Add(Key);
1143                _A((SSIZE_T) nIndex >= 0);
1144                _W(m_ElementArray.Add() == nIndex);
1145                _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1146                return m_ElementArray[nIndex];
1147        }
1148        POSITION SetAt(KINARGTYPE Key, VINARGTYPE Value)
1149        {
1150                POSITION Position = Lookup(Key);
1151                if(!Position)
1152                {
1153                        const SIZE_T nIndex = m_KeyElementArray.Add(Key);
1154                        _A((SSIZE_T) nIndex >= 0);
1155                        _W(m_ElementArray.Add(Value) == nIndex);
1156                        _A(m_KeyElementArray.GetCount() == m_ElementArray.GetCount());
1157                        Position = PositionFromIndex(nIndex);
1158                } else
1159                        GetValueAt(Position) = Value;
1160                return Position;
1161        }
1162        //VOID SetValueAt(POSITION Position, VINARGTYPE Value)
1163        BOOL RemoveKey(KINARGTYPE Key) throw()
1164        {
1165                const POSITION Position = Lookup(Key);
1166                if(!Position)
1167                        return FALSE;
1168                RemoveAtPos(Position);
1169                return TRUE;
1170        }
1171        VOID RemoveAll() throw()
1172        {
1173                m_KeyElementArray.RemoveAll();
1174                m_ElementArray.RemoveAll();
1175        }
1176        VOID RemoveAtPos(POSITION Position) throw()
1177        {
1178                const SIZE_T nIndex = IndexFromPosition(Position);
1179                m_KeyElementArray.RemoveAt(nIndex);
1180                m_ElementArray.RemoveAt(nIndex);
1181        }
1182        POSITION GetStartPosition() const throw()
1183        {
1184                if(!IsEmpty())
1185                        return PositionFromIndex(0);
1186                return NULL;
1187        }
1188        //VOID GetNextAssoc(POSITION& Position, KOUTARGTYPE Key, VOUTARGTYPE Value) const
1189        POSITION GetNext(POSITION& Position) const throw()
1190        {
1191                _A(Position);
1192                reinterpret_cast<BYTE*&>(Position)++;
1193                if(IndexFromPosition(Position) >= m_KeyElementArray.GetCount())
1194                        Position = NULL;
1195                return Position;
1196        }
1197        //CPair* GetNext(POSITION& Position) throw()
1198        //const _KeyElement& GetNextKey(POSITION& Position) const
1199        //const _Element& GetNextValue(POSITION& Position) const
1200        //_Element& GetNextValue(POSITION& Position)
1201        //VOID GetAt(POSITION Position, KOUTARGTYPE Key, VOUTARGTYPE Value) const
1202        //CPair* GetAt(POSITION Position) throw()
1203        //const CPair* GetAt(POSITION Position) const throw()
1204        const _KeyElement& GetKeyAt(POSITION Position) const
1205        {
1206                _A(Position);
1207                const SIZE_T nIndex = IndexFromPosition(Position);
1208                return m_KeyElementArray[nIndex];
1209        }
1210        const _Element& GetValueAt(POSITION Position) const
1211        {
1212                _A(Position);
1213                const SIZE_T nIndex = IndexFromPosition(Position);
1214                return m_ElementArray[nIndex];
1215        }
1216        _Element& GetValueAt(POSITION Position)
1217        {
1218                _A(Position);
1219                const SIZE_T nIndex = IndexFromPosition(Position);
1220                return m_ElementArray[nIndex];
1221        }
1222};
1223
1224////////////////////////////////////////////////////////////
1225// CRoAssignableMapT
1226
1227template <typename _Base>
1228class CRoAssignableMapT :
1229        public _Base
1230{
1231public:
1232// CRoAssignableMapT
1233        CRoAssignableMapT() throw()
1234        {
1235        }
1236        CRoAssignableMapT(const CRoAssignableMapT& Value)
1237        {
1238                *this = Value;
1239        }
1240        CRoAssignableMapT& operator = (const CRoAssignableMapT& Value)
1241        {
1242                RemoveAll();
1243                for(POSITION Position = Value.GetStartPosition(); Position; Value.GetNext(Position))
1244                        _W(SetAt(Value.GetKeyAt(Position), Value.GetValueAt(Position)));
1245                return *this;
1246        }
1247};
1248
Note: See TracBrowser for help on using the repository browser.