/*++ Copyright (c) 1999 Microsoft Corporation Module Name: vs_list.h Abstract: CVssDLList definition Author: Adi Oltean [aoltean] 11/23/1999 Revision History: Stefan Steiner [ssteiner] 02-21-2000 Removed VolSnapshot specific code to reuse for fsdump. Added the optional compiling of the signature checking code. --*/ #ifndef __VSS_DLLIST_HXX__ #define __VSS_DLLIST_HXX__ #if _MSC_VER > 1000 #pragma once #endif typedef PVOID VS_COOKIE; ///////////////////////////////////////////////////////////////////////////// // Constants const VS_COOKIE VS_NULL_COOKIE = NULL; const DWORD VS_ELEMENT_SIGNATURE = 0x47e347e4; ///////////////////////////////////////////////////////////////////////////// // Forward declarations template class CVssDLList; template class CVssDLListIterator; template class CVssDLListElement; ///////////////////////////////////////////////////////////////////////////// // CVssDLList template class CVssDLList { // Constructors& Destructors private: CVssDLList(const CVssDLList&); public: CVssDLList(): m_pFirst(NULL), m_pLast(NULL), m_dwNumElements( 0 ) {}; ~CVssDLList() { ClearAll(); } // Attributes public: bool IsEmpty() const; DWORD Size() { return m_dwNumElements; } // Operations public: VS_COOKIE Add( IN const T& object ); VS_COOKIE AddTail( IN const T& object ); bool Extract( OUT T& refObject ); bool ExtractTail( OUT T& refObject ); void ExtractByCookie( IN VS_COOKIE cookie, OUT T& refObject ); void ClearAll(); private: bool IsValid() const; // Data members private: CVssDLListElement* m_pFirst; CVssDLListElement* m_pLast; DWORD m_dwNumElements; friend class CVssDLListIterator; }; ///////////////////////////////////////////////////////////////////////////// // CVssDLListIterator template class CVssDLListIterator { private: CVssDLListIterator(); CVssDLListIterator(const CVssDLListIterator&); public: CVssDLListIterator(const CVssDLList& list): m_List(list), m_pNextInEnum(list.m_pFirst) {}; bool GetNext( OUT T& refObject ); VOID Reset() { m_pNextInEnum = m_List.m_pFirst; } private: const CVssDLList& m_List; const CVssDLListElement* m_pNextInEnum; }; ///////////////////////////////////////////////////////////////////////////// // CVssDLListElement template class CVssDLListElement { // Constructors& Destructors private: CVssDLListElement(); CVssDLListElement(const CVssDLListElement&); public: CVssDLListElement( IN const T& object ): m_Object(object), m_pNext(NULL), m_pPrev(NULL) { #ifndef NDEBUG m_dwSignature = VS_ELEMENT_SIGNATURE; #endif }; // Attributes public: bool IsValid() const { #ifndef NDEBUG return (m_dwSignature == VS_ELEMENT_SIGNATURE); #else return ( TRUE ); #endif }; // Data members public: #ifndef NDEBUG DWORD m_dwSignature; #endif CVssDLListElement* m_pPrev; CVssDLListElement* m_pNext; T m_Object; }; ///////////////////////////////////////////////////////////////////////////// // CVssDLList implementation template bool CVssDLList::IsEmpty() const { assert(IsValid()); return (m_pFirst == NULL); } template VS_COOKIE CVssDLList::Add( IN const T& object ) { assert(IsValid()); CVssDLListElement* pElement = new CVssDLListElement(object); if (pElement == NULL) return VS_NULL_COOKIE; // Setting neighbour element links if (m_pFirst) { assert(m_pFirst->m_pPrev == NULL); m_pFirst->m_pPrev = pElement; } // Setting element links assert(pElement->m_pNext == NULL); assert(pElement->m_pPrev == NULL); if (m_pFirst) pElement->m_pNext = m_pFirst; // Setting list head links m_pFirst = pElement; if (m_pLast == NULL) m_pLast = pElement; ++m_dwNumElements; return reinterpret_cast(pElement); } template VS_COOKIE CVssDLList::AddTail( IN const T& object ) { assert(IsValid()); CVssDLListElement* pElement = new CVssDLListElement(object); if (pElement == NULL) return VS_NULL_COOKIE; // Setting neighbour element links if (m_pLast) { assert(m_pLast->m_pNext == NULL); m_pLast->m_pNext = pElement; } // Setting element links assert(pElement->m_pNext == NULL); assert(pElement->m_pPrev == NULL); if (m_pLast) pElement->m_pPrev = m_pLast; // Setting list head links if (m_pFirst == NULL) m_pFirst = pElement; m_pLast = pElement; ++m_dwNumElements; return reinterpret_cast(pElement); } template void CVssDLList::ExtractByCookie( IN VS_COOKIE cookie, OUT T& refObject ) { if (cookie == VS_NULL_COOKIE) return; CVssDLListElement* pElement = reinterpret_cast*>(cookie); assert(pElement); assert(pElement->IsValid()); // Setting neighbours links if (pElement->m_pPrev) pElement->m_pPrev->m_pNext = pElement->m_pNext; if (pElement->m_pNext) pElement->m_pNext->m_pPrev = pElement->m_pPrev; // Setting list head links if (m_pFirst == pElement) m_pFirst = pElement->m_pNext; if (m_pLast == pElement) m_pLast = pElement->m_pPrev; // Destroying the element after getting the original object. refObject = pElement->m_Object; delete pElement; --m_dwNumElements; } template bool CVssDLList::Extract( OUT T& refObject ) { CVssDLListElement* pElement = m_pFirst; if (pElement == NULL) return false; assert(pElement->IsValid()); // Setting neighbours links assert(pElement->m_pPrev == NULL); if (pElement->m_pNext) pElement->m_pNext->m_pPrev = NULL; // Setting list head links m_pFirst = pElement->m_pNext; if (m_pLast == pElement) m_pLast = NULL; // Destroying the element after getting the original object. refObject = pElement->m_Object; delete pElement; --m_dwNumElements; return true; } template bool CVssDLList::ExtractTail( OUT T& refObject ) { CVssDLListElement* pElement = m_pLast; if (pElement == NULL) return false; assert(pElement->IsValid()); // Setting neighbours links assert(pElement->m_pNext == NULL); if (pElement->m_pPrev) pElement->m_pPrev->m_pNext = NULL; // Setting list head links m_pLast = pElement->m_pPrev; if (m_pFirst == pElement) m_pFirst = NULL; // Destroying the element after getting the original object. refObject = pElement->m_Object; delete pElement; --m_dwNumElements; return true; } template void CVssDLList::ClearAll( ) { CVssDLListElement* pElement = m_pFirst; CVssDLListElement* pNextElem; while( pElement != NULL ) { pNextElem = pElement->m_pNext; delete pElement; pElement = pNextElem; } m_pFirst = NULL; m_pLast = NULL; m_dwNumElements = 0; } template bool CVssDLList::IsValid() const { if ((m_pFirst == NULL) && (m_pLast == NULL)) return true; if ((m_pFirst != NULL) && (m_pLast != NULL)) return (m_pFirst->IsValid() && m_pLast->IsValid()); return false; } ///////////////////////////////////////////////////////////////////////////// // CVssDLListIterator implementation template bool CVssDLListIterator::GetNext( OUT T& object ) { if (m_pNextInEnum == NULL) return false; else { object = m_pNextInEnum->m_Object; m_pNextInEnum = m_pNextInEnum->m_pNext; return true; } } #endif // __VSS_DLLIST_HXX__