⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pidbtree.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		{
		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 + -