/*++ Copyright (C) 2000 Microsoft Corporation All rights reserved. Module Name: list.cxx Abstract: List template class. Author: Steve Kiraly (SteveKi) 03-Mar-2000 Revision History: --*/ /******************************************************************** List class, used for intrusive list. ********************************************************************/ template TList:: TList( VOID ) { } template TList:: ~TList( VOID ) { // // Release all the nodes. // TLink *pLink = m_Root.Next(); TLink *pTemp = NULL; while (pLink != &m_Root) { pTemp = pLink; pLink = pLink->Next(); delete pTemp; } } template HRESULT TList:: IsValid( VOID ) const { return S_OK; } template BOOL TList:: IsEmpty( VOID ) { // // If the next pointer is ourself the list is empty. // return &m_Root == m_Root.Next(); } template BOOL TList:: IsLast( IN TLink *pLink ) { // // If the next pointer is ourself the link is the last one. // return pLink->Next() == &m_Root; } template HRESULT TList:: AddAtHead( IN TLink *pLink ) { // // Check if the node is valid. // HRESULT hRetval = pLink ? pLink->IsValid() : E_INVALIDARG; if (SUCCEEDED(hRetval)) { // // Add the node at the head of the list. // hRetval = m_Root.Link(pLink); } return hRetval; } template HRESULT TList:: AddAtTail( IN TLink *pLink ) { // // Check if the node is valid. // HRESULT hRetval = pLink ? pLink->IsValid() : E_INVALIDARG; if (SUCCEEDED(hRetval)) { // // Add the node at the tail of the list. // hRetval = m_Root.Prev()->Link(pLink); } return hRetval; } template HRESULT TList:: Insert( IN TLink *pLink, IN TLink *pHere ) { // // Check if the node is valid. // HRESULT hRetval = pLink ? pLink->IsValid() : E_INVALIDARG; if (SUCCEEDED(hRetval)) { hRetval = pHere ? pHere->IsValid() : E_INVALIDARG; if (SUCCEEDED(hRetval)) { // // Link the specified node just after the apecified node. // hRetval = pHere->Link(pLink); } else { // // Link this node to the head of the list. // hRetval = m_Root.Link(pLink); } } return hRetval; } template T * TList:: RemoveAtHead( VOID ) { TLink *pLink = m_Root.Next(); pLink->UnLink(); return pLink != &m_Root ? reinterpret_cast(pLink) : NULL; } template T * TList:: RemoveAtTail( VOID ) { TLink *pLink = m_Root.Prev(); pLink->UnLink(); return pLink != &m_Root ? reinterpret_cast(pLink) : NULL; } template HRESULT TList:: Remove( IN TLink *pLink ) { // // We only succeed if work was done. // HRESULT hRetval = E_FAIL; if (pLink) { // // Release the node, the caller must delete themselves. // pLink->UnLink(); hRetval = S_OK; } return hRetval; } template T * TList:: Head( VOID ) const { TLink *pLink = m_Root.Next(); return pLink != &m_Root ? reinterpret_cast(pLink) : NULL; } template T * TList:: Tail( VOID ) const { TLink *pLink = m_Root.Prev(); return pLink != &m_Root ? reinterpret_cast(pLink) : NULL; } /******************************************************************** List class, used for non intrusive list. ********************************************************************/ template TLinkNi:: TLinkNi( IN T *pInfo ) : m_pInfo(pInfo) { } template TLinkNi:: ~TLinkNi( VOID ) { m_pInfo = NULL; } template HRESULT TLinkNi:: IsValid( VOID ) const { return S_OK; } template T * TLinkNi:: Get( VOID ) const { return m_pInfo; } template TLinkNi * TLinkNi:: Next( VOID ) const { return static_cast *>(TLink::Next()); } template TLinkNi * TLinkNi:: Prev( VOID ) const { return static_cast *>(TLink::Prev()); } // // Spooler non instrusive list template. // template TListNi:: TListNi( VOID ) : m_Root(NULL) { } template TListNi:: ~TListNi( VOID ) { // // Release all the nodes, the clients must release // their own data. // TLinkNi *pNode = m_Root.Next(); TLinkNi *pTemp = NULL; while (pNode != &m_Root) { pTemp = pNode; pNode = pNode->Next(); delete pTemp; } } template HRESULT TListNi:: IsValid( VOID ) const { return S_OK; } template BOOL TListNi:: IsEmpty( VOID ) const { // // If the next pointer is ourself the list is empty. // return &m_Root == m_Root.Next(); } template HRESULT TListNi:: AddAtHead( IN T *pData ) { return Insert(pData, &m_Root); } template HRESULT TListNi:: AddAtTail( IN T *pData ) { return Insert(pData, m_Root.Prev()); } template HRESULT TListNi:: Insert( IN T *pData, IN TLinkNi *pHere ) { HRESULT hRetval = E_FAIL; if (pData) { // // Create the new node with the data attached. // TLinkNi *pNode = new TLinkNi(pData); // // Check if the node is valid. // hRetval = pNode ? pNode->IsValid() : E_OUTOFMEMORY; if (SUCCEEDED(hRetval)) { hRetval = pHere ? pHere->IsValid() : E_FAIL; if (SUCCEEDED(hRetval)) { // // Link this node to the list. // hRetval = pHere->Link(pNode); } else { // // Link this node to the list. // hRetval = m_Root.Link(pNode); } } // // Something failed release the allocated node. // if (FAILED(hRetval)) { delete pNode; } } return hRetval; } template T * TListNi:: RemoveAtHead( VOID ) { T *pData = NULL; if (!IsEmpty()) { pData = m_Root.Next()->Get(); delete m_Root.Next(); } return pData; } template T * TListNi:: RemoveAtTail( VOID ) { T *pData = NULL; if (!IsEmpty()) { pData = m_Root.Prev()->Get(); delete m_Root.Prev(); } return pData; } template HRESULT TListNi:: Remove( IN TLinkNi *pNode ) { HRESULT hRetval = pNode ? pNode->IsValid() : E_FAIL; if (SUCCEEDED(hRetval)) { // // Release the link, its the callers responsibility to release thier data. // delete pNode; } return bRetval; } template HRESULT TListNi:: Remove( IN T *pData ) { HRESULT hRetval = E_FAIL; if (pData) { // // Locate the data and delete the node, the data // is not deleted, it is the callers responsibility // to delete their own data. // TLinkNi *pNode = m_Root.Next(); for (; pNode != &m_Root; pNode = pNode->Next()) { if (pNode->Get() == pData) { delete pNode; hRetval = S_OK; break; } } } return hRetval; } template T * TListNi:: Head( VOID ) const { TListNi *pLink = m_Root.Next(); return pLink != &m_Root ? reinterpret_cast(pLink->Get()) : NULL; } template T * TListNi:: Tail( VOID ) const { TListNi *pLink = m_Root.Prev(); return pLink != &m_Root ? reinterpret_cast(pLink->Get()) : NULL; }