357 lines
17 KiB
C++
357 lines
17 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1994 Microsoft Corporation
|
||
|
All rights reserved.
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
splutil.hxx
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Common utils.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Albert Ting (AlbertT) 29-May-1994
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifndef _SPLUTIL_HXX
|
||
|
#define _SPLUTIL_HXX
|
||
|
|
||
|
//
|
||
|
// Double linked list. DLINK must be the same as DLINKBASE, except
|
||
|
// with differnt constructors.
|
||
|
//
|
||
|
typedef struct DLINK {
|
||
|
|
||
|
DLINK()
|
||
|
{ FLink = NULL; }
|
||
|
|
||
|
DLINK* FLink;
|
||
|
DLINK* BLink;
|
||
|
|
||
|
} *PDLINK;
|
||
|
|
||
|
typedef struct DLINKBASE {
|
||
|
|
||
|
DLINKBASE()
|
||
|
{ FLink = BLink = (PDLINK)this; }
|
||
|
|
||
|
DLINK* FLink;
|
||
|
DLINK* BLink;
|
||
|
|
||
|
} *PDLINKBASE;
|
||
|
|
||
|
class TIter {
|
||
|
public:
|
||
|
PDLINK _pdlink;
|
||
|
PDLINK _pdlBase;
|
||
|
|
||
|
BOOL
|
||
|
bValid()
|
||
|
{ return _pdlink != _pdlBase; }
|
||
|
|
||
|
VOID
|
||
|
vNext()
|
||
|
{ _pdlink = _pdlink->FLink; }
|
||
|
|
||
|
VOID
|
||
|
vPrev()
|
||
|
{ _pdlink = _pdlink->BLink; }
|
||
|
|
||
|
operator PDLINK()
|
||
|
{ return _pdlink; }
|
||
|
};
|
||
|
|
||
|
|
||
|
VOID
|
||
|
LinkListDump(
|
||
|
PDLINK pHead,
|
||
|
DWORD offset,
|
||
|
LPCSTR pcszType,
|
||
|
LPCSTR pcszName
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
/********************************************************************
|
||
|
|
||
|
TBase has two linked lists of TLink.
|
||
|
|
||
|
class TBase {
|
||
|
|
||
|
DLINK_BASE( TLink, Lisk, Link );
|
||
|
DLINK_BASE( TLink, Link2, Link2 );
|
||
|
|
||
|
};
|
||
|
|
||
|
class TLink {
|
||
|
|
||
|
DLINK( TLink, Link );
|
||
|
DLINK( TLink, Link2 );
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Append pLink to the end of the Link2 list.
|
||
|
//
|
||
|
pBase->Link2_vAppend( pLink );
|
||
|
|
||
|
//
|
||
|
// Insert pLinkInsert right after pLinkMiddle.
|
||
|
//
|
||
|
pBase->Link_vInsert( pLinkMiddle, pLinkInsert );
|
||
|
|
||
|
//
|
||
|
// Get to the head.
|
||
|
//
|
||
|
pLinkHead = pBase->Link_pHead();
|
||
|
|
||
|
pLinkHead = pLinkHead->Link_pNext();
|
||
|
|
||
|
//
|
||
|
// Using the iter class.
|
||
|
//
|
||
|
TIter Iter;
|
||
|
|
||
|
for( Link_vIterInit( Iter ), Iter.vNext();
|
||
|
Iter.bValid();
|
||
|
Iter.vNext( )){
|
||
|
|
||
|
//
|
||
|
// Use pLink.
|
||
|
//
|
||
|
vLinkOperation( pLink );
|
||
|
}
|
||
|
|
||
|
********************************************************************/
|
||
|
|
||
|
#define DLINK_BASE( type, name, linkname ) \
|
||
|
VOID name##_vReset() \
|
||
|
{ pdl##name()->FLink = pdl##name()->BLink = pdl##name(); } \
|
||
|
\
|
||
|
PDLINK name##_pdlHead() const \
|
||
|
{ return pdl##name()->FLink; } \
|
||
|
\
|
||
|
PDLINK name##_pdlBase() const \
|
||
|
{ return pdl##name(); } \
|
||
|
\
|
||
|
type* name##_pHead( VOID ) const \
|
||
|
{ \
|
||
|
return name##_bValid( name##_pdlHead() ) ? \
|
||
|
(type*)((PBYTE)name##_pdlHead() - OFFSETOF( type, \
|
||
|
_dl##linkname )) : \
|
||
|
NULL; \
|
||
|
} \
|
||
|
\
|
||
|
BOOL name##_bValid( PDLINK pdlink ) const \
|
||
|
{ return pdlink != pdl##name(); } \
|
||
|
\
|
||
|
VOID name##_vAdd( type* pType ) \
|
||
|
{ name##_vInsert( pdl##name(), pType->pdl##linkname( )); } \
|
||
|
\
|
||
|
VOID name##_vAppend( type* pType ) \
|
||
|
{ name##_vInsert( pdl##name()->BLink, pType->pdl##linkname( )); } \
|
||
|
\
|
||
|
VOID name##_vInsert( PDLINK pdlink1, type* pType2 ) \
|
||
|
{ name##_vInsert( pdlink1, pType2->pdl##linkname() ); } \
|
||
|
\
|
||
|
VOID name##_vInsert( PDLINK pdlink1, PDLINK pdlink2 ) \
|
||
|
{ \
|
||
|
SPLASSERT( !pdlink2->FLink ); \
|
||
|
pdlink1->FLink->BLink = pdlink2; \
|
||
|
\
|
||
|
pdlink2->BLink = pdlink1; \
|
||
|
pdlink2->FLink = pdlink1->FLink; \
|
||
|
\
|
||
|
pdlink1->FLink = pdlink2; \
|
||
|
} \
|
||
|
\
|
||
|
VOID name##_vInsertBefore( PDLINK pdlink1, type* pType2 ) \
|
||
|
{ name##_vInsertBefore( pdlink1, pType2->pdl##linkname() ); } \
|
||
|
\
|
||
|
VOID name##_vInsertBefore( PDLINK pdlink1, PDLINK pdlink2 ) \
|
||
|
{ \
|
||
|
SPLASSERT( !pdlink2->FLink ); \
|
||
|
pdlink1->BLink->FLink = pdlink2; \
|
||
|
\
|
||
|
pdlink2->FLink = pdlink1; \
|
||
|
pdlink2->BLink = pdlink1->BLink; \
|
||
|
\
|
||
|
pdlink1->BLink = pdlink2; \
|
||
|
} \
|
||
|
\
|
||
|
VOID name##_vDelink( type* pType ) \
|
||
|
{ name##_vDelink( pType->pdl##linkname( )); } \
|
||
|
\
|
||
|
VOID name##_vDelink( PDLINK pdlink ) \
|
||
|
{ \
|
||
|
pdlink->FLink->BLink = pdlink->BLink; \
|
||
|
pdlink->BLink->FLink = pdlink->FLink; \
|
||
|
pdlink->FLink = NULL; \
|
||
|
} \
|
||
|
\
|
||
|
type* name##_pFind( type* pType ) const \
|
||
|
{ \
|
||
|
PDLINK pdlinkT; \
|
||
|
PDLINK pdlink = pType->pdl##linkname(); \
|
||
|
\
|
||
|
for( pdlinkT = name##_pdlHead(); \
|
||
|
name##_bValid( pdlinkT ); \
|
||
|
pdlinkT = pdlinkT->FLink ){ \
|
||
|
\
|
||
|
if( pType->pdl##linkname() == pdlinkT ) \
|
||
|
return (type*)((PBYTE)pdlink - OFFSETOF( type, \
|
||
|
_dl##linkname )); \
|
||
|
} \
|
||
|
return NULL; \
|
||
|
} \
|
||
|
\
|
||
|
PDLINK name##_pdlFind( PDLINK pdlink ) const \
|
||
|
{ \
|
||
|
PDLINK pdlinkT; \
|
||
|
for( pdlinkT = name##_pdlHead(); \
|
||
|
name##_bValid( pdlinkT ); \
|
||
|
pdlinkT = pdlinkT->FLink ){ \
|
||
|
\
|
||
|
if( pdlink == pdlinkT ) \
|
||
|
return pdlink; \
|
||
|
} \
|
||
|
return NULL; \
|
||
|
} \
|
||
|
\
|
||
|
PDLINK name##_pdlGetByIndex( UINT uIndex ) const \
|
||
|
{ \
|
||
|
PDLINK pdlink; \
|
||
|
for( pdlink = name##_pdlHead(); \
|
||
|
uIndex; \
|
||
|
uIndex--, pdlink = pdlink->FLink ){ \
|
||
|
\
|
||
|
SPLASSERT( name##_bValid( pdlink )); \
|
||
|
} \
|
||
|
return pdlink; \
|
||
|
} \
|
||
|
\
|
||
|
type* name##_pGetByIndex( UINT uIndex ) const \
|
||
|
{ \
|
||
|
PDLINK pdlink; \
|
||
|
for( pdlink = name##_pdlHead(); \
|
||
|
uIndex; \
|
||
|
uIndex--, pdlink = pdlink->FLink ){ \
|
||
|
\
|
||
|
SPLASSERT( name##_bValid( pdlink )); \
|
||
|
} \
|
||
|
return name##_pConvert( pdlink ); \
|
||
|
} \
|
||
|
\
|
||
|
VOID name##_vDump( VOID ) const \
|
||
|
{ \
|
||
|
LinkListDump( pdl##name(), \
|
||
|
OFFSETOF( type, _dl##linkname ), \
|
||
|
#type, \
|
||
|
#name ); \
|
||
|
} \
|
||
|
\
|
||
|
static PDLINK name##_pdlNext( PDLINK pdlink ) \
|
||
|
{ return pdlink->FLink; } \
|
||
|
\
|
||
|
static type* name##_pConvert( PDLINK pdlink ) \
|
||
|
{ return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##linkname )); } \
|
||
|
\
|
||
|
PDLINK pdl##name( VOID ) const \
|
||
|
{ return (PDLINK)&_dlb##name; } \
|
||
|
\
|
||
|
BOOL name##_bEmpty() const \
|
||
|
{ return pdl##name()->FLink == pdl##name(); } \
|
||
|
\
|
||
|
VOID name##_vIterInit( TIter& Iter ) const \
|
||
|
{ Iter._pdlBase = Iter._pdlink = (PDLINK)&_dlb##name; } \
|
||
|
\
|
||
|
DLINKBASE _dlb##name;
|
||
|
\
|
||
|
#define DLINK( type, name ) \
|
||
|
PDLINK pdl##name() \
|
||
|
{ return &_dl##name; } \
|
||
|
\
|
||
|
VOID name##_vDelinkSelf( VOID ) \
|
||
|
{ \
|
||
|
_dl##name.FLink->BLink = _dl##name.BLink; \
|
||
|
_dl##name.BLink->FLink = _dl##name.FLink; \
|
||
|
_dl##name.FLink = NULL; \
|
||
|
} \
|
||
|
\
|
||
|
BOOL name##_bLinked() const \
|
||
|
{ return _dl##name.FLink != NULL; } \
|
||
|
\
|
||
|
PDLINK name##_pdlNext( VOID ) const \
|
||
|
{ return _dl##name.FLink; } \
|
||
|
\
|
||
|
PDLINK name##_pdlPrev( VOID ) const \
|
||
|
{ return _dl##name.BLink; } \
|
||
|
\
|
||
|
type* name##_pNext( VOID ) const \
|
||
|
{ return name##_pConvert( _dl##name.FLink ); } \
|
||
|
\
|
||
|
type* name##_pPrev( VOID ) const \
|
||
|
{ return name##_pConvert( _dl##name.BLink ); } \
|
||
|
\
|
||
|
static type* name##_pConvert( PDLINK pdlink ) \
|
||
|
{ return (type*)( (PBYTE)pdlink - OFFSETOF( type, _dl##name )); } \
|
||
|
\
|
||
|
DLINK _dl##name
|
||
|
|
||
|
//
|
||
|
// Generic MEntry class that allows objects to be stored on a list
|
||
|
// and searched by name.
|
||
|
//
|
||
|
class MEntry {
|
||
|
|
||
|
SIGNATURE( 'entr' )
|
||
|
|
||
|
public:
|
||
|
|
||
|
DLINK( MEntry, Entry );
|
||
|
TString _strName;
|
||
|
|
||
|
BOOL bValid()
|
||
|
{
|
||
|
return _strName.bValid();
|
||
|
}
|
||
|
|
||
|
static MEntry* pFindEntry( PDLINK pdlink, LPCTSTR pszName );
|
||
|
};
|
||
|
|
||
|
#define ENTRY_BASE( type, name ) \
|
||
|
friend MEntry; \
|
||
|
type* name##_pFindByName( LPCTSTR pszName ) const \
|
||
|
{ \
|
||
|
MEntry* pEntry = MEntry::pFindEntry( name##_pdlBase(), pszName ); \
|
||
|
return pEntry ? (type*)pEntry : NULL; \
|
||
|
} \
|
||
|
static type* name##_pConvertEntry( PDLINK pdlink ) \
|
||
|
{ \
|
||
|
return (type*)name##_pConvert( pdlink ); \
|
||
|
} \
|
||
|
DLINK_BASE( MEntry, name, Entry )
|
||
|
|
||
|
#define DELETE_ENTRY_LIST( type, name ) \
|
||
|
{ \
|
||
|
PDLINK pdlink; \
|
||
|
type* pType; \
|
||
|
\
|
||
|
for( pdlink = name##_pdlHead(); name##_bValid( pdlink ); ){ \
|
||
|
\
|
||
|
pType = name##_pConvertEntry( pdlink ); \
|
||
|
pdlink = name##_pdlNext( pdlink ); \
|
||
|
\
|
||
|
pType->vDelete(); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#endif // ndef _SPLUTIL_HXX
|
||
|
|
||
|
|