//--------------------------------------------------------------------------- // // Module: clist.h // // Description: list classes // // //@@BEGIN_MSINTERNAL // Development Team: // Mike McLaughlin // // History: Date Author Comment // //@@END_MSINTERNAL //--------------------------------------------------------------------------- // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved. // //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Macros //--------------------------------------------------------------------------- #define FOR_EACH_LIST_ITEM(pl, p) { \ PCLIST_ITEM pli; \ for(pli = (pl)->GetListFirst(); \ !(pl)->IsListEnd(pli); \ pli = (pl)->GetListNext(pli)) { \ p = (pl)->GetListData(pli); \ (pl)->AssertList(p); #define FOR_EACH_LIST_ITEM_DELETE(pl, p) { \ PCLIST_ITEM pli, pliNext; \ for(pli = (pl)->GetListFirst(); !(pl)->IsListEnd(pli); pli = pliNext) { \ pliNext = (pl)->GetListNext(pli); \ p = (pl)->GetListData(pli); \ (pl)->AssertList(p); #define DELETE_LIST_ITEM(pl) \ pliNext = (pl)->GetListFirst(); #define FOR_EACH_LIST_ITEM_BACKWARD(pl, p) { \ PCLIST_ITEM pli; \ for(pli = (pl)->GetListLast(); \ !(pl)->IsListEnd(pli); \ pli = (pl)->GetListPrevious(pli)) { \ p = (pl)->GetListData(pli); \ (pl)->AssertList(p); #define END_EACH_LIST_ITEM } } //--------------------------------------------------------------------------- #define FOR_EACH_CLIST_ITEM(pl, p) { \ for(p = (pl)->GetListFirst(); \ !(pl)->IsListEnd(p); \ p = (pl)->GetListNext(p)) { \ Assert(p); #define FOR_EACH_CLIST_ITEM_DELETE(pl, p, type) { \ type *pNext; \ for(p = (pl)->GetListFirst(); !(pl)->IsListEnd(p); p = pNext) { \ Assert(p); \ pNext = (pl)->GetListNext(p); #define END_EACH_CLIST_ITEM } } //--------------------------------------------------------------------------- // Abstract List Classes //--------------------------------------------------------------------------- typedef class CList : public CObj { public: } CLIST, *PCLIST; typedef class CListItem : public CObj { public: } CLIST_ITEM, *PCLIST_ITEM; //--------------------------------------------------------------------------- // Singlely Linked List //--------------------------------------------------------------------------- typedef class CListSingle : public CList { friend class CListSingleItem; public: CListSingle() { m_plsiHead = NULL; }; VOID DestroyList() { m_plsiHead = NULL; }; BOOL IsLstEmpty() { Assert(this); return(m_plsiHead == NULL); }; CListSingleItem *GetListFirst() { Assert(this); return(m_plsiHead); }; BOOL IsListEnd(CListSingleItem *plsi) { Assert(this); return(plsi == NULL); }; CListSingleItem *GetListData(CListSingleItem *plsi) { return plsi; } CListSingleItem *GetListNext(CListSingleItem *plsi); CListSingleItem **GetListEnd(); ENUMFUNC EnumerateList( IN ENUMFUNC (CListSingleItem::*pfn)( ) ); ENUMFUNC EnumerateList( IN ENUMFUNC (CListSingleItem::*pfn)( PVOID pReference ), PVOID pReference ); void ReverseList(); protected: CListSingleItem *m_plsiHead; public: DefineSignature(0x2048534C); // LSH } CLIST_SINGLE, *PCLIST_SINGLE; //--------------------------------------------------------------------------- typedef class CListSingleItem : public CListItem { friend class CListData; friend class CListSingle; public: CListSingleItem() { m_plsiNext = NULL; }; VOID AddList(CListSingle *pls) { Assert(pls); Assert(this); ASSERT(m_plsiNext == NULL); m_plsiNext = pls->m_plsiHead; pls->m_plsiHead = this; }; VOID AddListEnd(CListSingle *pls) { Assert(pls); Assert(this); ASSERT(m_plsiNext == NULL); *(pls->GetListEnd()) = this; }; VOID RemoveList(CListSingle *pls); private: CListSingleItem *m_plsiNext; public: DefineSignature(0x2049534C); // LSI } CLIST_SINGLE_ITEM, *PCLIST_SINGLE_ITEM; inline CListSingleItem * CListSingle::GetListNext(CListSingleItem *plsi) { Assert(this); return plsi->m_plsiNext; } //--------------------------------------------------------------------------- // Doublely Linked List //--------------------------------------------------------------------------- typedef class CListDouble : public CList { friend class CListDoubleItem; public: CListDouble() { InitializeListHead(&m_leHead); }; VOID DestroyList() { }; BOOL IsLstEmpty() { Assert(this); return IsListEmpty(&m_leHead); }; ULONG CountList(); CListDoubleItem *GetListFirst(); CListDoubleItem *GetListLast(); BOOL IsListEnd(CListDoubleItem *pldi); CListDoubleItem *GetListNext(CListDoubleItem *pldi); CListDoubleItem *GetListPrevious(CListDoubleItem *pldi); CListDoubleItem *GetListData(CListDoubleItem *pldi) { return pldi; }; ENUMFUNC EnumerateList( IN ENUMFUNC (CListDoubleItem::*pfn)( ) ); ENUMFUNC EnumerateList( IN ENUMFUNC (CListDoubleItem::*pfn)( PVOID pReference ), PVOID pReference ); protected: LIST_ENTRY m_leHead; public: DefineSignature(0x2048424C); // LBH } CLIST_DOUBLE, *PCLIST_DOUBLE; //--------------------------------------------------------------------------- typedef class CListDoubleItem : public CListItem { friend class CListDouble; public: VOID AddList(CListDouble *plb) { Assert(plb); Assert(this); ASSERT(m_le.Flink == NULL); ASSERT(m_le.Blink == NULL); InsertHeadList(&plb->m_leHead, &m_le); }; VOID AddListEnd(CListDouble *plb) { Assert(plb); Assert(this); ASSERT(m_le.Flink == NULL); ASSERT(m_le.Blink == NULL); InsertTailList(&plb->m_leHead, &m_le); }; VOID RemoveList() { Assert(this); ASSERT(m_le.Flink != NULL); ASSERT(m_le.Blink != NULL); RemoveEntryList(&m_le); m_le.Flink = NULL; m_le.Blink = NULL; }; VOID RemoveListCheck() { Assert(this); if(m_le.Flink != NULL) { RemoveList(); } }; protected: LIST_ENTRY m_le; public: DefineSignature(0x2049424C); // LBI } CLIST_DOUBLE_ITEM, *PCLIST_DOUBLE_ITEM; inline CListDoubleItem * CListDouble::GetListFirst() { Assert(this); ASSERT(m_leHead.Flink != NULL); return CONTAINING_RECORD(m_leHead.Flink, CListDoubleItem, m_le); } inline CListDoubleItem * CListDouble::GetListLast() { Assert(this); ASSERT(m_leHead.Blink != NULL); return CONTAINING_RECORD(m_leHead.Blink, CListDoubleItem, m_le); } inline BOOL CListDouble::IsListEnd(CListDoubleItem *pldi) { Assert(this); return(&pldi->m_le == &m_leHead); } inline CListDoubleItem * CListDouble::GetListNext(CListDoubleItem *pldi) { Assert(this); ASSERT(pldi->m_le.Flink != NULL); return CONTAINING_RECORD(pldi->m_le.Flink, CListDoubleItem, m_le); } inline CListDoubleItem * CListDouble::GetListPrevious(CListDoubleItem *pldi) { Assert(this); ASSERT(pldi->m_le.Blink != NULL); return CONTAINING_RECORD(pldi->m_le.Blink, CListDoubleItem, m_le); } //--------------------------------------------------------------------------- // Linked List of Data Pointers //--------------------------------------------------------------------------- class CListDataItem; typedef class CListDataData : public CListSingleItem { friend class CListData; public: CListDataData( CListDataItem *pldi ) { m_pldiData = pldi; }; CListDataData( PVOID p ) { m_pldiData = (CListDataItem *)p; }; private: CListDataItem *m_pldiData; public: DefineSignature(0x2044444C); // LDD } CLIST_DATA_DATA, *PCLIST_DATA_DATA; //--------------------------------------------------------------------------- typedef class CListData : public CListSingle { public: ~CListData() { CListData::DestroyList(); }; VOID DestroyList(); ULONG CountList(); CListDataData *GetListFirst() { Assert(this); return (CListDataData *)CListSingle::GetListFirst(); }; CListDataData *GetListNext(CListDataData *pldd) { Assert(this); return (CListDataData *)CListSingle::GetListNext(pldd); }; CListDataItem *GetListData(CListDataData *pldd) { Assert(this); return pldd->m_pldiData; }; CListDataItem *GetListFirstData() { Assert(this); return GetListData(GetListFirst()); }; ENUMFUNC EnumerateList( IN ENUMFUNC (CListDataItem::*pfn)( ) ); ENUMFUNC EnumerateList( IN ENUMFUNC (CListDataItem::*pfn)( PVOID pReference ), PVOID pReference ); NTSTATUS CreateUniqueList( OUT CListData *pldOut, IN PVOID (*GetFunction)( IN PVOID pData ), IN BOOL (*CompareFunction)( IN PVOID pIn, IN PVOID pOut ) ); BOOL CheckDupList( PVOID p ); NTSTATUS AddList( PVOID p ); NTSTATUS AddListDup( PVOID p ); NTSTATUS AddListEnd( PVOID p ); NTSTATUS AddListOrdered( PVOID p, LONG lFieldOffset ); VOID RemoveList( PVOID p ); VOID JoinList( CListData *pld ); private: CListDataData **GetListEnd() { return((CListDataData **)CListSingle::GetListEnd()); }; public: DefineSignature(0x2048444C); // LDH } CLIST_DATA, *PCLIST_DATA; //--------------------------------------------------------------------------- typedef class CListDataItem : public CListItem { public: ENUMFUNC Destroy() { delete this; return(STATUS_CONTINUE); }; BOOL CheckDupList( PCLIST_DATA pld ) { Assert(this); return(pld->CheckDupList((PVOID)this)); }; NTSTATUS AddList( PCLIST_DATA pld ) { Assert(this); return(pld->AddList((PVOID)this)); }; NTSTATUS AddListDup( PCLIST_DATA pld ) { Assert(this); return(pld->AddListDup((PVOID)this)); }; NTSTATUS AddListEnd( PCLIST_DATA pld ) { Assert(this); return(pld->AddListEnd((PVOID)this)); }; VOID RemoveList( PCLIST_DATA pld ) { Assert(this); pld->RemoveList((PVOID)this); }; DefineSignature(0x2049444C); // LDI } CLIST_DATA_ITEM, *PCLIST_DATA_ITEM; typedef PVOID (*UNIQUE_LIST_PFN)(PVOID); typedef BOOL (*UNIQUE_LIST_PFN2)(PVOID, PVOID); //--------------------------------------------------------------------------- // Multi-Headed Linked List //--------------------------------------------------------------------------- typedef class CListMultiData : public CListDoubleItem { friend class CListMulti; friend class CListMultiItem; public: CListMultiData( PVOID p ) { m_plmiData = (CListMultiItem *)p; }; ~CListMultiData() { CListMultiData::RemoveList(); }; VOID RemoveList() { Assert(this); CListDoubleItem::RemoveList(); m_ldiItem.RemoveList(); }; private: CListDoubleItem m_ldiItem; CListMultiItem *m_plmiData; public: DefineSignature(0x20444d4C); // LMD } CLIST_MULTI_DATA, *PCLIST_MULTI_DATA; //--------------------------------------------------------------------------- typedef class CListMulti : public CListDouble { friend class CListMultiItem; public: ~CListMulti() { CListMulti::DestroyList(); }; VOID DestroyList(); ENUMFUNC EnumerateList( ENUMFUNC (CListMultiItem::*pfn)( ) ); ENUMFUNC EnumerateList( ENUMFUNC (CListMultiItem::*pfn)( PVOID pReference ), PVOID pReference ); CListMultiData *GetListFirst() { Assert(this); return (CListMultiData *)CListDouble::GetListFirst(); }; CListMultiData *GetListLast() { Assert(this); return (CListMultiData *)CListDouble::GetListLast(); }; BOOL IsListEnd(CListMultiData *plmd) { Assert(this); return CListDouble::IsListEnd(plmd); }; CListMultiData *GetListNext(CListMultiData *plmd) { Assert(this); return (CListMultiData *)CListDouble::GetListNext(plmd); }; CListMultiData *GetListPrevious(CListMultiData *plmd) { Assert(this); return (CListMultiData *)CListDouble::GetListPrevious(plmd); }; CListMultiItem *GetListData(CListMultiData *plmd) { Assert(this); return plmd->m_plmiData; }; CListMultiItem *GetListFirstData() { Assert(this); return GetListData(GetListFirst()); }; BOOL CheckDupList( PVOID p ); NTSTATUS AddList( PVOID p, CListMultiItem *plmi ); NTSTATUS AddList( CListMultiItem *plmi ) { Assert(this); return(AddList((PVOID)plmi, plmi)); }; NTSTATUS AddListEnd( PVOID p, CListMultiItem *plmi ); NTSTATUS AddListEnd( CListMultiItem *plmi ) { Assert(this); return(AddListEnd((PVOID)plmi, plmi)); }; NTSTATUS AddListOrdered( PVOID p, CListMultiItem *plmi, LONG lFieldOffset ); NTSTATUS AddListOrdered( CListMultiItem *plmi, LONG lFieldOffset ) { Assert(this); return(AddListOrdered((PVOID)plmi, plmi, lFieldOffset)); }; VOID RemoveList( PVOID p ); VOID JoinList( CListMulti *plm ); DefineSignature(0x20484D4C); // LMH } CLIST_MULTI, *PCLIST_MULTI; //--------------------------------------------------------------------------- typedef class CListMultiItem : public CListDouble { public: ~CListMultiItem(); BOOL CheckDupList( PCLIST_MULTI plm ) { return(plm->CheckDupList((PVOID)this)); }; NTSTATUS AddList( PCLIST_MULTI plm ) { Assert(plm); Assert(this); return(plm->AddList(this)); }; NTSTATUS AddListEnd( PCLIST_MULTI plm ) { Assert(plm); Assert(this); return(plm->AddListEnd(this)); }; NTSTATUS AddListOrdered( PCLIST_MULTI plm, LONG lFieldOffset ) { Assert(plm); Assert(this); return(plm->AddListOrdered(this, lFieldOffset)); }; VOID RemoveList( PCLIST_MULTI plm ) { Assert(this); plm->RemoveList((PVOID)this); }; DefineSignature(0x20494d4C); // LMI } CLIST_MULTI_ITEM, *PCLIST_MULTI_ITEM; //--------------------------------------------------------------------------- // Templates //--------------------------------------------------------------------------- template class ListSingleDestroy : public CListSingle { public: ~ListSingleDestroy() { ListSingleDestroy::DestroyList(); }; VOID DestroyList() { ListSingleDestroy::EnumerateList(TYPE::Destroy); CListSingle::DestroyList(); }; VOID AssertList(TYPE *p) { Assert(p); }; ENUMFUNC EnumerateList( IN ENUMFUNC (TYPE::*pfn)( ) ) { return CListSingle::EnumerateList( (ENUMFUNC (CListSingleItem::*)())pfn); }; ENUMFUNC EnumerateList( IN ENUMFUNC (TYPE::*pfn)( PVOID pReference ), PVOID pReference ) { return CListSingle::EnumerateList( (ENUMFUNC (CListSingleItem::*)(PVOID))pfn, pReference); }; PCLIST_ITEM GetListFirst() { return CListSingle::GetListFirst(); }; BOOL IsListEnd(PCLIST_ITEM pli) { return CListSingle::IsListEnd((CListSingleItem *)pli); }; PCLIST_ITEM GetListNext(PCLIST_ITEM pli) { return CListSingle::GetListNext((CListSingleItem *)pli); }; TYPE *GetListData(PCLIST_ITEM pli) { return (TYPE *)CListSingle::GetListData((CListSingleItem *)pli); }; TYPE *GetListFirstData() { return (TYPE *)CListSingle::GetListData(CListSingle::GetListFirst()); }; }; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- template class ListDouble : public CListDouble { public: VOID AssertList(TYPE *p) { Assert(p); }; ENUMFUNC EnumerateList( IN ENUMFUNC (TYPE::*pfn)() ) { return CListDouble::EnumerateList( (ENUMFUNC (CListDoubleItem::*)())pfn); }; ENUMFUNC EnumerateList( IN ENUMFUNC (TYPE::*pfn)( PVOID pReference ), PVOID pReference ) { return CListDouble::EnumerateList( (ENUMFUNC (CListDoubleItem::*)(PVOID))pfn, pReference); }; PCLIST_ITEM GetListFirst() { return CListDouble::GetListFirst(); }; PCLIST_ITEM GetListLast() { return CListDouble::GetListLast(); }; BOOL IsListEnd(PCLIST_ITEM pli) { return CListDouble::IsListEnd((CListDoubleItem *)pli); }; PCLIST_ITEM GetListNext(PCLIST_ITEM pli) { return CListDouble::GetListNext((CListDoubleItem *)pli); }; PCLIST_ITEM GetListPrevious(PCLIST_ITEM pli) { return CListDouble::GetListPrevious((CListDoubleItem *)pli); }; TYPE *GetListData(PCLIST_ITEM pli) { return (TYPE *)CListDouble::GetListData((CListDoubleItem *)pli); }; }; //--------------------------------------------------------------------------- template class ListDoubleDestroy : public ListDouble { public: ~ListDoubleDestroy() { ListDoubleDestroy::DestroyList(); }; VOID DestroyList() { ListDoubleDestroy::EnumerateList(TYPE::Destroy); CListDouble::DestroyList(); }; }; //--------------------------------------------------------------------------- template class ListDoubleField : public CListDouble { public: VOID AssertList(TYPE *p) { Assert(p); }; CListItem *GetListFirst() { return (CListItem *)CONTAINING_RECORD( CListDouble::GetListFirst(), TYPE, ldiNext); }; BOOL IsListEnd(CListItem *pli) { return CListDouble::IsListEnd(&((TYPE *)pli)->ldiNext); }; CListItem *GetListNext(CListItem *pli) { return (CListItem *)CONTAINING_RECORD( CListDouble::GetListNext(&((TYPE *)pli)->ldiNext), TYPE, ldiNext); }; TYPE *GetListData(CListItem *pli) { return CONTAINING_RECORD( CListDouble::GetListData(&((TYPE *)pli)->ldiNext), TYPE, ldiNext); }; }; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- template class ListDataAssertLess : public CListData { public: VOID AssertList(TYPE *p) { }; PCLIST_ITEM GetListFirst() { return CListData::GetListFirst(); }; BOOL IsListEnd(PCLIST_ITEM pli) { return CListData::IsListEnd((CListDataData *)pli); }; PCLIST_ITEM GetListNext(PCLIST_ITEM pli) { return CListData::GetListNext((CListDataData *)pli); }; TYPE *GetListData(PCLIST_ITEM pli) { return (TYPE *)CListData::GetListData((CListDataData *)pli); }; TYPE *GetListFirstData() { return (TYPE *)CListData::GetListFirstData(); }; NTSTATUS AddList( TYPE *p ) { return CListData::AddList((PVOID)p); }; NTSTATUS AddListDup( TYPE *p ) { return CListData::AddListDup((PVOID)p); }; NTSTATUS AddListEnd( TYPE *p ) { return CListData::AddListEnd((PVOID)p); }; NTSTATUS AddListOrdered( TYPE *p, LONG lFieldOffset ) { return CListData::AddListOrdered((PVOID)p, lFieldOffset); }; VOID RemoveList( TYPE *p ) { CListData::RemoveList((PVOID)p); }; }; //--------------------------------------------------------------------------- template class ListData : public ListDataAssertLess { public: VOID AssertList(TYPE *p) { Assert(p); }; ENUMFUNC EnumerateList( ENUMFUNC (TYPE::*pfn)() ) { return CListData::EnumerateList((ENUMFUNC (CListDataItem::*)())pfn); }; ENUMFUNC EnumerateList( ENUMFUNC (TYPE::*pfn)( PVOID pReference ), PVOID pReference ) { return CListData::EnumerateList( (ENUMFUNC (CListDataItem::*)(PVOID))pfn, pReference); }; }; //--------------------------------------------------------------------------- template class ListDataDestroy : public ListData { public: ~ListDataDestroy() { ListDataDestroy::DestroyList(); }; VOID DestroyList() { ListDataDestroy::EnumerateList(TYPE::Destroy); CListData::DestroyList(); }; }; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- template class ListMulti : public CListMulti { public: VOID AssertList(TYPE *p) { Assert(p); }; PCLIST_ITEM GetListFirst() { return CListMulti::GetListFirst(); }; PCLIST_ITEM GetListLast() { return CListMulti::GetListLast(); }; BOOL IsListEnd(PCLIST_ITEM pli) { return CListMulti::IsListEnd((CListMultiData *)pli); }; PCLIST_ITEM GetListNext(PCLIST_ITEM pli) { return CListMulti::GetListNext((CListMultiData *)pli); }; PCLIST_ITEM GetListPrevious(PCLIST_ITEM pli) { return CListMulti::GetListPrevious((CListMultiData *)pli); }; TYPE *GetListData(PCLIST_ITEM pli) { return (TYPE *)CListMulti::GetListData((CListMultiData *)pli); }; TYPE *GetListFirstData() { return (TYPE *)CListMulti::GetListFirstData(); }; ENUMFUNC EnumerateList( ENUMFUNC (TYPE::*pfn)() ) { return CListMulti::EnumerateList((ENUMFUNC (CListMultiItem::*)())pfn); }; ENUMFUNC EnumerateList( ENUMFUNC (TYPE::*pfn)( PVOID pReference ), PVOID pReference ) { return CListMulti::EnumerateList( (ENUMFUNC (CListMultiItem::*)(PVOID))pfn, pReference); }; }; //--------------------------------------------------------------------------- template class ListMultiDestroy : public ListMulti { public: ~ListMultiDestroy() { ListMultiDestroy::DestroyList(); }; VOID DestroyList() { ListMultiDestroy::EnumerateList(TYPE::Destroy); CListMulti::DestroyList(); }; }; //--------------------------------------------------------------------------- // End of File: clist.h //---------------------------------------------------------------------------