From: Ged Murphy Date: Thu, 9 Jul 2015 07:51:43 +0000 (+0000) Subject: [ATL] X-Git-Tag: ReactOS-0.4.0~1619 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=d064fe61ec837c973a6333af83678504bf0b8d0c;ds=sidebyside [ATL] - Add basic support for CAtlList, CAtlPlex, CElementTraitsBase, CDefaultCompareTraits. - Implements CAtlList::IsEmpty, ::GetHeadPosition, ::GetNext, ::AddTail, ::RemoveTail, ::RemoveAll - Required in the new devmgr code. svn path=/trunk/; revision=68380 --- diff --git a/reactos/lib/atl/atlcoll.h b/reactos/lib/atl/atlcoll.h new file mode 100644 index 00000000000..b6359ebde50 --- /dev/null +++ b/reactos/lib/atl/atlcoll.h @@ -0,0 +1,383 @@ +#ifndef __ATLCOLL_H__ +#define __ATLCOLL_H__ + +#pragma once +#include + + +struct __POSITION +{ +}; +typedef __POSITION* POSITION; + + +namespace ATL +{ + +class CAtlPlex +{ +public: + CAtlPlex* m_Next; + +#if (_AFX_PACKING >= 8) + DWORD dwReserved[1]; +#endif + + static inline CAtlPlex* Create( + _Inout_ CAtlPlex*& Entry, + _In_ size_t MaxElements, + _In_ size_t ElementSize + ) + { + CAtlPlex* Block; + + ATLASSERT(MaxElements > 0); + ATLASSERT(ElementSize > 0); + + size_t BufferSize = sizeof(CAtlPlex) + (MaxElements * ElementSize); + + void *Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); + if (Buffer == NULL) return NULL; + + Block = static_cast< CAtlPlex* >(Buffer); + Block->m_Next = Entry; + Entry = Block; + + return Block; + } + + void* GetData() + { + return (this + 1); + } + + inline void Destroy() + { + CAtlPlex* Block; + + Block = this; + while (Block != NULL) + { + CAtlPlex* Next; + + Next = Block->m_Next; + HeapFree(GetProcessHeap(), 0, Block); + Block = Next; + } + } +}; + + +template +class CElementTraitsBase +{ +public: + typedef const T& INARGTYPE; + typedef T& OUTARGTYPE; + + static void CopyElements( + _Out_writes_all_(NumElements) T* Dest, + _In_reads_(NumElements) const T* Source, + _In_ size_t NumElements) + { + for (size_t i = 0; i < NumElements; i++) + { + Dest[i] = Source[i]; + } + } + + static void RelocateElements( + _Out_writes_all_(NumElements) T* Dest, + _In_reads_(NumElements) T* Source, + _In_ size_t NumElements) + { + memmove_s(Dest, NumElements * sizeof(T), Source, NumElements * sizeof(T)); + } +}; + +template +class CDefaultCompareTraits +{ +public: + static bool CompareElements( + _In_ const T& Val1, + _In_ const T& Val2) + { + return (Val1 == Val2); + } + + static int CompareElementsOrdered( + _In_ const T& Val1, + _In_ const T& Val2) + { + if (Val1 < Val2) + { + return -1; + } + else if (Val1 > Val2) + { + return 1; + } + + return 0; // equal + } +}; + +template +class CDefaultElementTraits : + public CElementTraitsBase, + public CDefaultCompareTraits +{ +}; + + +template +class CElementTraits : + public CDefaultElementTraits +{ +}; + + +template> +class CAtlList +{ +private: + typedef typename ETraits::INARGTYPE INARGTYPE; + +private: + class CNode : public __POSITION + { + public: + CNode* m_Next; + CNode* m_Prev; + E m_Element; + + public: + CNode(INARGTYPE Element) : + m_Element(Element) + { + } + }; + +private: + CAtlPlex* m_Blocks; + UINT m_BlockSize; + CNode* m_HeadNode; + CNode* m_TailNode; + CNode* m_FreeNode; + size_t m_NumElements; + +public: + CAtlList(_In_ UINT nBlockSize = 10); + ~CAtlList(); + + bool IsEmpty() const; + + POSITION GetHeadPosition() const; + + E& GetNext( + _Inout_ POSITION &Position + ); + + POSITION AddTail( + INARGTYPE element + ); + + E RemoveTail(); + void RemoveAll(); + +private: + CNode* CreateNode( + INARGTYPE element, + _In_opt_ CNode* pPrev, + _In_opt_ CNode* pNext + ); + + void FreeNode( + _Inout_ CNode* pNode + ); + + CNode* GetFreeNode( + ); + +}; + + +// +// CAtlist public methods +// + +template +CAtlList< E, ETraits >::CAtlList(_In_ UINT nBlockSize) : + m_NumElements(0), + m_HeadNode(NULL), + m_TailNode(NULL), + m_FreeNode(NULL), + m_Blocks(NULL), + + m_BlockSize(nBlockSize) +{ + ATLASSERT(nBlockSize > 0); +} + +template +CAtlList::~CAtlList(void) +{ + RemoveAll(); +} + +template +inline bool CAtlList< E, ETraits >::IsEmpty(void) const +{ + return (m_NumElements == 0); +} + +template +inline POSITION CAtlList::GetHeadPosition(void) const +{ + return (POSITION)m_HeadNode; +} + +template +inline E& CAtlList< E, ETraits >::GetNext( + _Inout_ POSITION& Position + ) +{ + CNode* Node = (CNode*)Position; + Position = (POSITION)Node->m_Next; + return Node->m_Element; +} + +template +POSITION CAtlList::AddTail( + INARGTYPE element + ) +{ + CNode* Node = CreateNode(element, m_TailNode, NULL); + if (m_TailNode) + { + m_TailNode->m_Next = Node; + } + else + { + m_HeadNode = Node; + } + m_TailNode = Node; + + return (POSITION)Node; +} + +template +E CAtlList::RemoveTail(void) +{ + CNode* Node = m_TailNode; + + E Element(Node->m_Element); + + m_TailNode = Node->m_Prev; + if (m_TailNode) + { + m_TailNode->m_Next = NULL; + } + else + { + m_HeadNode = NULL; + } + FreeNode(Node); + + return Element; +} + +template +void CAtlList::RemoveAll(void) +{ + while (m_NumElements > 0) + { + CNode* Node = m_HeadNode; + m_HeadNode = m_HeadNode->m_Next; + FreeNode(Node); + } + + m_HeadNode = NULL; + m_TailNode = NULL; + m_FreeNode = NULL; + + if (m_Blocks) + { + m_Blocks->Destroy(); + m_Blocks = NULL; + } +} + + +// +// CAtlist private methods +// + +template +typename CAtlList::CNode* CAtlList::CreateNode( + INARGTYPE element, + _In_opt_ CNode* Prev, + _In_opt_ CNode* Next + ) +{ + GetFreeNode(); + + CNode* NewNode = GetFreeNode(); + CNode* NextFree = m_FreeNode->m_Next; + + NewNode = new CNode(element); + + m_FreeNode = NextFree; + NewNode->m_Prev = Prev; + NewNode->m_Next = Next; + m_NumElements++; + + return NewNode; +} + +template +void CAtlList::FreeNode( + _Inout_ CNode* pNode + ) +{ + pNode->~CNode(); + pNode->m_Next = m_FreeNode; + m_FreeNode = pNode; + + m_NumElements--; + if (m_NumElements == 0) + { + RemoveAll(); + } +} + +template +typename CAtlList::CNode* CAtlList< E, ETraits>::GetFreeNode(void) +{ + if (m_FreeNode) + { + return m_FreeNode; + } + + CAtlPlex* Block = CAtlPlex::Create(m_Blocks, m_BlockSize, sizeof(CNode)); + if (Block == NULL) + { + throw(E_OUTOFMEMORY); + } + + CNode* Node = (CNode*)Block->GetData(); + Node += (m_BlockSize - 1); + for (int i = m_BlockSize - 1; i >= 0; i--) + { + Node->m_Next = m_FreeNode; + m_FreeNode = Node; + Node--; + } + + return m_FreeNode; +} + +} + +#endif \ No newline at end of file