📄 pidbtree.cpp
字号:
{
iCurrentList++;
AdvanceToValidKey();
};
virtual bool AtValidElement() { return !iIter.BadIndex(); };
virtual void *Current( const char **ppKey )
{
if ( ppKey )
{ *ppKey = ((KeyValuePair *)iIter.Current())->Key(); };
return ((KeyValuePair *)iIter.Current())->Value();
};
/*
Remove and destroy the entry at the current index
*/
virtual void RemoveCurrent()
{
assert( !iIter.BadIndex() );
if ( iIter.BadIndex() ) { return; };
((KeyValuePair *)aLists[iCurrentList].Detach(iIter))
->Delete(tTypeFrame.fnDelete);
};
/*
Detach and return the current element
*/
virtual void *DetachCurrent()
{
assert( !iIter.BadIndex() );
if ( iIter.BadIndex() ) { return 0; };
return ((KeyValuePair *)aLists[iCurrentList].Detach(iIter))->Detach();
};
/*
Replace the current element
*/
virtual void ReplaceCurrent( void *pNew )
{
assert( !iIter.BadIndex() );
if ( iIter.BadIndex() ) { return; };
((KeyValuePair *)iIter.Current())-> Replace( pNew,
tTypeFrame.fnDelete );
};
virtual void Next()
{
iIter++;
AdvanceToValidKey();
};
};
/*____________________________________________________________________________*\
*
Class:
Description:
This Iterator traverses a PIDBTree structure and matches only against
elements with the appropriate keys
\*____________________________________________________________________________*/
class PIDBTreeSpecificKeyIterator : public PIDBTreeAnyKeyIterator
{
private:
const char *pKey;
/*
If the iterator is not currently pointing at a valid key then
advance it to point to the next one
*/
inline void AdvanceToValidKey()
{
for(; !iIter.BadIndex() &&
((KeyValuePair *)iIter.Current())->Key()!=pKey; iIter++ );
};
public:
PIDBTreeSpecificKeyIterator( DblList &tList, const char *pTheKey,
const TypeFrame &tTheTypeFrame )
: PIDBTreeAnyKeyIterator( &tList, 1, tTheTypeFrame ),
pKey( pTheKey )
{
AdvanceToValidKey();
};
virtual void Next()
{
iIter++;
AdvanceToValidKey();
};
};
/*____________________________________________________________________________*\
*
Function:
Synopsis: public, static
Description:
Get the symbol table entry for the key and type. Type RFC822 is
not case sensitive. All the other types are.
\*____________________________________________________________________________*/
const char *PIDBTree::GetFastKey( const char *pKey, int iType )
{
return PISymbolTable_LookupOrInsert(
pKey,
(iType == PIDBTYPE_RFC822 ) ? 0 : 1 );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis: public, static
Description:
Returns -1 on error, else the PIDBTYPE number for name pType
\*____________________________________________________________________________*/
int PIDBTree::PIDBTypeNameToNumber( const char *pType )
{
assert( pType );
if ( !pType )
{ return PIDBTYPE_INVALID; };
/* --- skip leading whitespace --- */
for( ; *pType && (isspace(*pType)); pType++ );
/* --- include only to first whitespace trailing whitespace --- */
int j=0;
for( ; pType[j] && !(isspace(pType[j])); j++ );
/* --- j now contains the length of the first word in pType --- */
/* --- the type --- */
if ( !PIUtil_strncmpi( pType, PIDBTYPE_TEXT_TREE, j ) )
{ return PIDBTYPE_TREE; }
else if ( !PIUtil_strncmpi( pType, PIDBTYPE_TEXT_STRING, j ) )
{ return PIDBTYPE_STRING; }
else if ( !PIUtil_strncmpi( pType, PIDBTYPE_TEXT_RFC822, j ) )
{ return PIDBTYPE_RFC822; }
else if ( !PIUtil_strncmpi( pType, PIDBTYPE_TEXT_OPAQUE, j ) )
{ return PIDBTYPE_OPAQUE; }
else if ( !PIUtil_strncmpi( pType, PIDBTYPE_TEXT_USER, j ) )
{ return PIDBTYPE_USER; }
else
{
};
return PIDBTYPE_INVALID;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis: public, static
Description:
Return numeric flags mask given the bar delimited list pFlags.
\*____________________________________________________________________________*/
int PIDBTree::PIDBFlagsNameToNumber( const char *pFlags )
{
int iFlags = PIDBFLAG_NONE;
if ( pFlags )
{
StringTokenizer tTokens( pFlags, "|" );
for(int i=0; i<tTokens.NumTokens(); i++)
{
const char *pToken = tTokens.GetToken( i );
/* --- skip leading whitespace --- */
for( ; *pToken && (isspace(*pToken)); pToken++ );
/* --- include only to first whitespace trailing whitespace --- */
int j=0;
for( ; pToken[j] && !(isspace(pToken[j])); j++ );
/* --- j now contains the length of the first word in pToken --- */
if ( !PIUtil_strncmpi( pToken, PIDBFLAG_TEXT_PROPAGATEUP, j ) )
{ iFlags |= PIDBFLAG_PROPAGATEUP; }
else if ( !PIUtil_strncmpi( pToken, PIDBFLAG_TEXT_NOCALLBACK, j ) )
{ iFlags |= PIDBFLAG_NOCALLBACK; }
else if ( !PIUtil_strncmpi( pToken, PIDBFLAG_TEXT_FASTKEY, j ) )
{ iFlags |= PIDBFLAG_FASTKEY; }
else
{ assert( 0 ); /* --- catch this at development time --- */ };
};
};
return iFlags;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
int PIDBTree::Add( int iType, const char *pKey, void *pValue,
int iFlags )
{
assert( iType<=iLastType );
if ( iType>iLastType )
{ return PIAPI_EINVAL; };
/* --- get the standard address for this string --- */
const char *pSym =
( iFlags & PIDBFLAG_FASTKEY ) ?
pKey :
( pKey ? PIDBTree::GetFastKey( pKey, iType ) : 0 );
const TypeFrame &tTypeFrame = GetTypeFrame( iType );
void *pNewValue = tTypeFrame.fnAdd ? (tTypeFrame.fnAdd)(pValue) : pValue;
GetList( pTypes, iType, pSym ).Append( (DblList::type)
PI_NEW( KeyValuePair( pSym, pNewValue ) ) );
if ( iType==PIDBTYPE_TREE && pValue )
{
((_PIDB *)pValue)->SetParent( this );
};
return PIAPI_COMPLETED;
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
int PIDBTree::Replace( int iType, const char *pKey, void *pValue,
int iFlags )
{
_PIDBIterator *pIter;
AutoDelete<_PIDBIterator> tA( pIter = GetIterator( iType, pKey, iFlags ) );
(void)tA;
if ( pIter )
{
if ( pIter->AtValidElement() )
{
const TypeFrame &tTypeFrame = GetTypeFrame( iType );
void *pNewValue = tTypeFrame.fnAdd ? (tTypeFrame.fnAdd)(pValue) :
pValue;
pIter->ReplaceCurrent( pNewValue );
return PIAPI_COMPLETED;
};
};
return Add( iType, pKey, pValue, iFlags );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
_PIDBIterator *PIDBTree::GetIterator( int iType, const char *pKey, int iFlags )
{
if ( iType<0 || iType>iLastType ) return 0;
const TypeFrame &tTypeFrame= GetTypeFrame( iType );
const char *pSym =
( iFlags & PIDBFLAG_FASTKEY ) ?
pKey :
( pKey ? PIDBTree::GetFastKey( pKey, iType ) : 0 );
_PIDBIterator *pIter = 0;
pIter = pSym ?
PI_NEW( PIDBTreeSpecificKeyIterator(
GetList( pTypes, iType, pSym ), pSym, tTypeFrame ) ):
PI_NEW( PIDBTreeAnyKeyIterator(
&( pTypes[GetFirstListIndexForType(iType)] ),
HASH_TABLE_SIZE, tTypeFrame ) );
if ( (iFlags & PIDBFLAG_PROPAGATEUP ) && GetParent() )
{
return PI_NEW( PIDBTreePropagatesIterator( GetParent(), iType,
pSym, pIter, iFlags ) );
}
else
{
return pIter;
};
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
void *PIDBTree::Lookup( int iType, const char *pKey, int iFlags )
{
#if 1 /* change this to 0 to disable this optimization */
/*
** Optimization:
** First check if the PROPAGATEUP flag is not set, if not then
** do the lookup here without generating an iterator.
*/
if ( !(iFlags & PIDBFLAG_PROPAGATEUP) )
{
/* --- get fast key --- */
const char *pSym =
( iFlags & PIDBFLAG_FASTKEY ) ?
pKey :
( pKey ? PIDBTree::GetFastKey( pKey, iType ) : 0 );
const char *pTmp = pSym;
for( DblListIterator i( GetList( pTypes, iType, pTmp ) );
!i.BadIndex(); i++ )
{
if ( ((KeyValuePair *)i.Current())->Key()==pSym )
{
return ((KeyValuePair *)i.Current())->Value();
};
};
/* --- not found --- */
return 0;
};
#endif
/* ---
resort to older slower lookup mechanism
--- */
_PIDBIterator *pIter;
AutoDelete<_PIDBIterator> tA( pIter = GetIterator( iType, pKey, iFlags ) );
(void)tA;
if ( !pIter )
{ return 0; };
if ( pIter->AtValidElement() )
{
void *pV = pIter->Current( 0 );
if ( !pV )
{
return 0;
};
return pV;
}
else
{
return 0;
};
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PIDBTree::PIDBTree( _PIDB *pTheParent, const char *pName,
int iNumAdditionalTypes,
TypeFrame *aTheAdditionalTypeFrames )
: _PIDB( pTheParent ),
iLastType( iNumAdditionalTypes + PIDBTYPE_LAST ),
aAdditionalTypeFrames( aTheAdditionalTypeFrames )
{
if ( pTheParent )
{
pTheParent->Add( PIDBTYPE_TREE, pName, this, 0 );
};
assert( iLastType==PIDBTYPE_LAST || aAdditionalTypeFrames );
pTypes = PI_NEW( DblList[ GetNumLists( iLastType ) ] );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
PIDBTree::~PIDBTree()
{
/* --- destruct the builtin and additional types --- */
int j=0;
int i;
for(i=0; j<PIDBTYPE_BUILTINSIZE; i++, j++)
{
InternalDestruct(
&( pTypes[ GetFirstListIndexForType( j ) ] ),
HASH_TABLE_SIZE,
aTypeFrames[i].fnDelete
);
};
assert( j==PIDBTYPE_BUILTINSIZE );
for(i=0; j<=iLastType; i++, j++)
{
InternalDestruct(
&( pTypes[ GetFirstListIndexForType( j ) ] ),
HASH_TABLE_SIZE,
aAdditionalTypeFrames[i].fnDelete );
};
PI_DELETE( [] pTypes );
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
void PIDBTree::InternalDestruct(
DblList *paLists, int iNumLists, void (* fnDelete)(void *) )
{
for( int j=0; j<iNumLists; j++ )
{
DblList &tList = paLists[j];
for(DblListIterator i(tList); !i.BadIndex(); i++)
{
((KeyValuePair *)i.Current())->Delete( fnDelete );
};
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -