8 // FIXME: We need to include <new> for placement new, but that would mean everyone using atl
9 // would also need to set the option 'WITH_STL'..
10 // For now we just copy the definition here, under a guard..
12 inline void* operator new (size_t size
, void* ptr
) throw() { return ptr
; }
13 inline void operator delete (void* ptr
, void* voidptr2
) throw() { }
20 typedef __POSITION
* POSITION
;
31 #if (_AFX_PACKING >= 8)
35 static inline CAtlPlex
* Create(
36 _Inout_ CAtlPlex
*& Entry
,
37 _In_
size_t MaxElements
,
38 _In_
size_t ElementSize
43 ATLASSERT(MaxElements
> 0);
44 ATLASSERT(ElementSize
> 0);
46 size_t BufferSize
= sizeof(CAtlPlex
) + (MaxElements
* ElementSize
);
48 void *Buffer
= HeapAlloc(GetProcessHeap(), 0, BufferSize
);
49 if (Buffer
== NULL
) return NULL
;
51 Block
= static_cast< CAtlPlex
* >(Buffer
);
52 Block
->m_Next
= Entry
;
72 HeapFree(GetProcessHeap(), 0, Block
);
80 class CElementTraitsBase
83 typedef const T
& INARGTYPE
;
84 typedef T
& OUTARGTYPE
;
86 static void CopyElements(
87 _Out_writes_all_(NumElements
) T
* Dest
,
88 _In_reads_(NumElements
) const T
* Source
,
89 _In_
size_t NumElements
)
91 for (size_t i
= 0; i
< NumElements
; i
++)
97 static void RelocateElements(
98 _Out_writes_all_(NumElements
) T
* Dest
,
99 _In_reads_(NumElements
) T
* Source
,
100 _In_
size_t NumElements
)
102 // A simple memmove works for most of the types.
103 // You'll have to override this for types that have pointers to their
106 #if defined(__GNUC__) && __GNUC__ >= 8
107 #pragma GCC diagnostic push
108 #pragma GCC diagnostic ignored "-Wclass-memaccess"
110 memmove(Dest
, Source
, NumElements
* sizeof(T
));
111 #if defined(__GNUC__) && __GNUC__ >= 8
112 #pragma GCC diagnostic pop
118 class CDefaultCompareTraits
121 static bool CompareElements(
125 return (Val1
== Val2
);
128 static int CompareElementsOrdered(
136 else if (Val1
> Val2
)
146 class CDefaultElementTraits
:
147 public CElementTraitsBase
<T
>,
148 public CDefaultCompareTraits
<T
>
154 class CElementTraits
:
155 public CDefaultElementTraits
<T
>
160 template<typename E
, class ETraits
= CElementTraits
<E
> >
164 typedef typename
ETraits::INARGTYPE INARGTYPE
;
165 typedef typename
ETraits::OUTARGTYPE OUTARGTYPE
;
170 size_t m_AllocatedSize
;
174 #pragma push_macro("new")
177 void CreateItems(E
* pData
, size_t Size
)
179 for (size_t n
= 0; n
< Size
; ++n
)
185 #pragma pop_macro("new")
187 void DestructItems(E
* pData
, size_t Size
)
189 for (size_t n
= 0; n
< Size
; ++n
)
195 bool GrowAllocatedData(size_t nNewSize
)
199 size_t addSize
= m_GrowBy
> 0 ? m_GrowBy
: m_AllocatedSize
/ 2;
200 size_t allocSize
= m_AllocatedSize
+ addSize
;
201 if (allocSize
< nNewSize
)
202 allocSize
= nNewSize
;
204 E
* pData
= (E
*)malloc(nNewSize
* sizeof(E
));
211 // Copy the objects over (default implementation will just move them without calling anything
212 ETraits::RelocateElements(pData
, m_pData
, m_Size
);
216 m_AllocatedSize
= nNewSize
;
220 // We need to allocate a new buffer
221 size_t allocSize
= m_GrowBy
> nNewSize
? m_GrowBy
: nNewSize
;
222 m_pData
= (E
*)malloc(allocSize
* sizeof(E
));
227 m_AllocatedSize
= allocSize
;
232 /* The CAtlArray class does not support construction by copy */
234 CAtlArray(_In_
const CAtlArray
&);
235 CAtlArray
& operator=(_In_
const CAtlArray
&);
241 size_t Add(INARGTYPE element
);
244 bool SetCount(size_t nNewSize
, int nGrowBy
= - 1);
245 size_t GetCount() const;
247 E
& operator[](size_t ielement
);
248 const E
& operator[](size_t ielement
) const;
250 E
& GetAt(size_t iElement
);
251 const E
& GetAt(size_t iElement
) const;
253 //FIXME: Most of this class is missing!
257 // CAtlArray public methods
260 template<typename E
, class ETraits
>
261 CAtlArray
< E
, ETraits
>::CAtlArray()
269 template<typename E
, class ETraits
>
270 CAtlArray
< E
, ETraits
>::~CAtlArray()
276 #pragma push_macro("new")
279 template<typename E
, class ETraits
>
280 size_t CAtlArray
<E
, ETraits
>::Add(INARGTYPE element
)
282 if (m_Size
>= m_AllocatedSize
)
284 if (!GrowAllocatedData(m_Size
+ 1))
286 AtlThrow(E_OUTOFMEMORY
);
290 ::new (m_pData
+ m_Size
) E(element
);
296 #pragma pop_macro("new")
298 template<typename E
, class ETraits
>
299 size_t CAtlArray
<E
, ETraits
>::Add()
301 if (!SetCount(m_Size
+ 1))
303 AtlThrow(E_OUTOFMEMORY
);
309 template<typename E
, class ETraits
>
310 bool CAtlArray
<E
, ETraits
>::SetCount(size_t nNewSize
, int nGrowBy
/*= -1*/)
315 m_GrowBy
= (size_t)nGrowBy
;
318 if (nNewSize
== m_Size
)
322 else if (nNewSize
== 0)
326 DestructItems(m_pData
, m_Size
);
329 m_Size
= m_AllocatedSize
= NULL
;
331 else if (nNewSize
< m_AllocatedSize
)
333 if (nNewSize
> m_Size
)
335 CreateItems(m_pData
+ m_Size
, nNewSize
- m_Size
);
339 DestructItems(m_pData
+ nNewSize
, m_Size
- nNewSize
);
345 if (!GrowAllocatedData(nNewSize
))
350 CreateItems(m_pData
+ m_Size
, nNewSize
- m_Size
);
357 template<typename E
, class ETraits
>
358 size_t CAtlArray
<E
, ETraits
>::GetCount() const
363 template<typename E
, class ETraits
>
364 E
& CAtlArray
<E
, ETraits
>::operator[](size_t iElement
)
366 ATLASSERT(iElement
< m_Size
);
368 return m_pData
[iElement
];
371 template<typename E
, class ETraits
>
372 const E
& CAtlArray
<E
, ETraits
>::operator[](size_t iElement
) const
374 ATLASSERT(iElement
< m_Size
);
376 return m_pData
[iElement
];
379 template<typename E
, class ETraits
>
380 E
& CAtlArray
<E
, ETraits
>::GetAt(size_t iElement
)
382 ATLASSERT(iElement
< m_Size
);
384 return m_pData
[iElement
];
387 template<typename E
, class ETraits
>
388 const E
& CAtlArray
<E
, ETraits
>::GetAt(size_t iElement
) const
390 ATLASSERT(iElement
< m_Size
);
392 return m_pData
[iElement
];
397 template<typename E
, class ETraits
= CElementTraits
<E
> >
401 typedef typename
ETraits::INARGTYPE INARGTYPE
;
404 class CNode
: public __POSITION
412 CNode(INARGTYPE Element
) :
417 /* The CNode class does not support construction by copy */
419 CNode(_In_
const CNode
&);
420 CNode
& operator=(_In_
const CNode
&);
429 size_t m_NumElements
;
431 /* The CAtlList class does not support construction by copy */
433 CAtlList(_In_
const CAtlList
&);
434 CAtlList
& operator=(_In_
const CAtlList
&);
437 CAtlList(_In_ UINT nBlockSize
= 10);
440 size_t GetCount() const;
441 bool IsEmpty() const;
443 POSITION
GetHeadPosition() const;
444 POSITION
GetTailPosition() const;
446 E
& GetNext(_Inout_ POSITION
& pos
);
447 const E
& GetNext(_Inout_ POSITION
& pos
) const;
448 E
& GetPrev(_Inout_ POSITION
& pos
);
449 const E
& GetPrev(_Inout_ POSITION
& pos
) const;
451 E
& GetAt(_In_ POSITION pos
);
452 const E
& GetAt(_In_ POSITION pos
) const;
454 POSITION
AddHead(INARGTYPE element
);
455 POSITION
AddTail(INARGTYPE element
);
460 POSITION
InsertBefore(_In_ POSITION pos
, INARGTYPE element
);
461 POSITION
InsertAfter(_In_ POSITION pos
, INARGTYPE element
);
464 void RemoveAt(_In_ POSITION pos
);
468 _In_opt_ POSITION posStartAfter
= NULL
) const;
469 POSITION
FindIndex(_In_
size_t iElement
) const;
474 _In_opt_ CNode
* pPrev
,
475 _In_opt_ CNode
* pNext
489 // CAtlist public methods
492 template<typename E
, class ETraits
>
493 CAtlList
< E
, ETraits
>::CAtlList(_In_ UINT nBlockSize
) :
495 m_BlockSize(nBlockSize
),
501 ATLASSERT(nBlockSize
> 0);
504 template<typename E
, class ETraits
>
505 CAtlList
<E
, ETraits
>::~CAtlList(void)
510 template<typename E
, class ETraits
>
511 inline size_t CAtlList
< E
, ETraits
>::GetCount() const
513 return m_NumElements
;
516 template<typename E
, class ETraits
>
517 inline bool CAtlList
< E
, ETraits
>::IsEmpty() const
519 return (m_NumElements
== 0);
522 template<typename E
, class ETraits
>
523 inline POSITION CAtlList
<E
, ETraits
>::GetHeadPosition() const
525 return (POSITION
)m_HeadNode
;
528 template<typename E
, class ETraits
>
529 inline POSITION CAtlList
<E
, ETraits
>::GetTailPosition() const
531 return (POSITION
)m_TailNode
;
534 template<typename E
, class ETraits
>
535 inline E
& CAtlList
< E
, ETraits
>::GetNext(_Inout_ POSITION
& pos
)
537 CNode
* Node
= (CNode
*)pos
;
538 pos
= (POSITION
)Node
->m_Next
;
539 return Node
->m_Element
;
542 template<typename E
, class ETraits
>
543 inline const E
& CAtlList
< E
, ETraits
>::GetNext(_Inout_ POSITION
& pos
) const
545 CNode
* Node
= (CNode
*)pos
;
546 pos
= (POSITION
)Node
->m_Next
;
547 return Node
->m_Element
;
550 template<typename E
, class ETraits
>
551 inline E
& CAtlList
< E
, ETraits
>::GetPrev(_Inout_ POSITION
& pos
)
553 CNode
* Node
= (CNode
*)pos
;
554 pos
= (POSITION
)Node
->m_Prev
;
555 return Node
->m_Element
;
558 template<typename E
, class ETraits
>
559 inline const E
& CAtlList
< E
, ETraits
>::GetPrev(_Inout_ POSITION
& pos
) const
561 CNode
* Node
= (CNode
*)pos
;
562 pos
= (POSITION
)Node
->m_Prev
;
563 return Node
->m_Element
;
566 template<typename E
, class ETraits
>
567 inline E
& CAtlList
< E
, ETraits
>::GetAt(_In_ POSITION pos
)
569 CNode
* Node
= (CNode
*)pos
;
570 return Node
->m_Element
;
573 template<typename E
, class ETraits
>
574 inline const E
& CAtlList
< E
, ETraits
>::GetAt(_In_ POSITION pos
) const
576 CNode
* Node
= (CNode
*)pos
;
577 return Node
->m_Element
;
580 template<typename E
, class ETraits
>
581 POSITION CAtlList
<E
, ETraits
>::AddHead(INARGTYPE element
)
583 CNode
* Node
= CreateNode(element
, NULL
, m_HeadNode
);
586 m_HeadNode
->m_Prev
= Node
;
594 return (POSITION
)Node
;
597 template<typename E
, class ETraits
>
598 POSITION CAtlList
<E
, ETraits
>::AddTail(INARGTYPE element
)
600 CNode
* Node
= CreateNode(element
, m_TailNode
, NULL
);
603 m_TailNode
->m_Next
= Node
;
611 return (POSITION
)Node
;
614 template<typename E
, class ETraits
>
615 E CAtlList
<E
, ETraits
>::RemoveHead()
617 CNode
* Node
= m_HeadNode
;
618 E
Element(Node
->m_Element
);
620 m_HeadNode
= Node
->m_Next
;
623 m_HeadNode
->m_Prev
= NULL
;
634 template<typename E
, class ETraits
>
635 E CAtlList
<E
, ETraits
>::RemoveTail()
637 CNode
* Node
= m_TailNode
;
638 E
Element(Node
->m_Element
);
640 m_TailNode
= Node
->m_Prev
;
643 m_TailNode
->m_Next
= NULL
;
654 template<typename E
, class ETraits
>
655 POSITION CAtlList
<E
, ETraits
>::InsertBefore(_In_ POSITION pos
, _In_ INARGTYPE element
)
658 return AddHead(element
);
660 CNode
* OldNode
= (CNode
*)pos
;
661 CNode
* Node
= CreateNode(element
, OldNode
->m_Prev
, OldNode
);
663 if (OldNode
->m_Prev
!= NULL
)
665 OldNode
->m_Prev
->m_Next
= Node
;
671 OldNode
->m_Prev
= Node
;
673 return (POSITION
)Node
;
676 template<typename E
, class ETraits
>
677 POSITION CAtlList
<E
, ETraits
>::InsertAfter(_In_ POSITION pos
, _In_ INARGTYPE element
)
680 return AddTail(element
);
682 CNode
* OldNode
= (CNode
*)pos
;
683 CNode
* Node
= CreateNode(element
, OldNode
, OldNode
->m_Next
);
685 if (OldNode
->m_Next
!= NULL
)
687 OldNode
->m_Next
->m_Prev
= Node
;
693 OldNode
->m_Next
= Node
;
695 return (POSITION
)Node
;
698 template<typename E
, class ETraits
>
699 void CAtlList
<E
, ETraits
>::RemoveAll()
701 while (m_NumElements
> 0)
703 CNode
* Node
= m_HeadNode
;
704 m_HeadNode
= m_HeadNode
->m_Next
;
719 template<typename E
, class ETraits
>
720 void CAtlList
<E
, ETraits
>::RemoveAt(_In_ POSITION pos
)
722 ATLASSERT(pos
!= NULL
);
724 CNode
* OldNode
= (CNode
*)pos
;
725 if (OldNode
== m_HeadNode
)
727 m_HeadNode
= OldNode
->m_Next
;
731 OldNode
->m_Prev
->m_Next
= OldNode
->m_Next
;
733 if (OldNode
== m_TailNode
)
735 m_TailNode
= OldNode
->m_Prev
;
739 OldNode
->m_Next
->m_Prev
= OldNode
->m_Prev
;
744 template<typename E
, class ETraits
>
745 POSITION CAtlList
< E
, ETraits
>::Find(
747 _In_opt_ POSITION posStartAfter
) const
749 CNode
* Node
= (CNode
*)posStartAfter
;
759 for (; Node
!= NULL
; Node
= Node
->m_Next
)
761 if (ETraits::CompareElements(Node
->m_Element
, element
))
762 return (POSITION
)Node
;
768 template<typename E
, class ETraits
>
769 POSITION CAtlList
< E
, ETraits
>::FindIndex(_In_
size_t iElement
) const
771 if (iElement
>= m_NumElements
)
774 if (m_HeadNode
== NULL
)
777 CNode
* Node
= m_HeadNode
;
778 for (size_t i
= 0; i
< iElement
; i
++)
783 return (POSITION
)Node
;
788 // CAtlist private methods
791 template<typename E
, class ETraits
>
792 typename CAtlList
<E
, ETraits
>::CNode
* CAtlList
<E
, ETraits
>::CreateNode(
794 _In_opt_ CNode
* Prev
,
800 CNode
* NewNode
= m_FreeNode
;
801 CNode
* NextFree
= m_FreeNode
->m_Next
;
803 NewNode
= new CNode(element
);
805 m_FreeNode
= NextFree
;
806 NewNode
->m_Prev
= Prev
;
807 NewNode
->m_Next
= Next
;
813 template<typename E
, class ETraits
>
814 void CAtlList
<E
, ETraits
>::FreeNode(
819 pNode
->m_Next
= m_FreeNode
;
823 if (m_NumElements
== 0)
829 template<typename E
, class ETraits
>
830 typename CAtlList
<E
, ETraits
>::CNode
* CAtlList
< E
, ETraits
>::GetFreeNode()
837 CAtlPlex
* Block
= CAtlPlex::Create(m_Blocks
, m_BlockSize
, sizeof(CNode
));
840 AtlThrowImp(E_OUTOFMEMORY
);
843 CNode
* Node
= (CNode
*)Block
->GetData();
844 Node
+= (m_BlockSize
- 1);
845 for (int i
= m_BlockSize
- 1; i
>= 0; i
--)
847 Node
->m_Next
= m_FreeNode
;