windows-nt/Source/XPSP1/NT/printscan/print/spooler/spllib/splutil.hxx
2020-09-26 16:20:57 +08:00

366 lines
18 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
);
/********************************************************************
// Forward reference.
class TLink;
TBase has two linked lists of TLink.
class TBase {
DLINK_BASE( TLink, Link, 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();
//
// To get to the next element in the list.
//
pLink = pLinkHead->Link_pNext();
//
// Remove an element from the list.
//
pLink->pLink_vDelinkSelf();
//
// 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