Example #1
0
bool CUtlInplaceBuffer::InplaceGetLinePtr( char **ppszInBufferPtr, int *pnLineLength )
{
	Assert( IsText() && !ContainsCRLF() );

	int nLineLen = PeekLineLength();
	if ( nLineLen <= 1 )
	{
		SeekGet( SEEK_TAIL, 0 );
		return false;
	}

	-- nLineLen; // because it accounts for putting a terminating null-character

	char *pszLine = ( char * ) const_cast< void * >( PeekGet() );
	SeekGet( SEEK_CURRENT, nLineLen );

	// Set the out args
	if ( ppszInBufferPtr )
		*ppszInBufferPtr = pszLine;
	
	if ( pnLineLength )
		*pnLineLength = nLineLen;

	return true;
}
void CUtlBufferEditor::GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars )
{
	if ( !IsText() || !pConv )
	{
		GetString( pString, nMaxChars );
		return;
	}

	if (!IsValid())
	{
		*pString = 0;
		return;
	}

	if ( nMaxChars == 0 )
	{
		nMaxChars = INT_MAX;
	}

	EatWhiteSpace();
	if ( !PeekStringMatch( 0, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) )
		return;

	// Pull off the starting delimiter
	SeekGet( SEEK_CURRENT, pConv->GetDelimiterLength() );

	int nRead = 0;
	while ( IsValid() )
	{
		if ( PeekStringMatch( 0, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) )
		{
			SeekGet( SEEK_CURRENT, pConv->GetDelimiterLength() );
			break;
		}

		char c = GetDelimitedCharInternal( pConv );

		if ( nRead < nMaxChars )
		{
			pString[nRead] = c;
			++nRead;
		}
	}

	if ( nRead >= nMaxChars )
	{
		nRead = nMaxChars - 1;
	}
	pString[nRead] = '\0';
}
//-----------------------------------------------------------------------------
// Advance the get index until after the particular string is found
// Do not eat whitespace before starting. Return false if it failed
//-----------------------------------------------------------------------------
bool CUtlBufferEditor::GetToken( const char *pToken )
{
	Assert( pToken );

	// Look for the token
	int nLen = Q_strlen( pToken );

	int nSizeToCheck = Size() - TellGet() - m_nOffset;

	int nGet = TellGet();
	do
	{
		int nMaxSize = TellMaxPut() - TellGet();
		if ( nMaxSize < nSizeToCheck )
		{
			nSizeToCheck = nMaxSize;
		}
		if ( nLen > nSizeToCheck )
			break;

		if ( !CheckPeekGet( 0, nSizeToCheck ) )
			break;

		const char *pBufStart = (const char*)PeekGet();
		const char *pFoundEnd = Q_strnistr( pBufStart, pToken, nSizeToCheck );
		if ( pFoundEnd )
		{
			size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart;
			SeekGet( CUtlBufferEditor::SEEK_CURRENT, nOffset + nLen );
			return true;
		}

		SeekGet( CUtlBufferEditor::SEEK_CURRENT, nSizeToCheck - nLen - 1 );
		nSizeToCheck = Size() - (nLen-1);

	} while ( true );

	SeekGet( CUtlBufferEditor::SEEK_HEAD, nGet );
	return false;
}
//-----------------------------------------------------------------------------
// This version of GetString converts \ to \\ and " to \", etc.
// It also places " at the beginning and end of the string
//-----------------------------------------------------------------------------
char CUtlBufferEditor::GetDelimitedCharInternal( CUtlCharConversion *pConv )
{
	char c = GetChar();
	if ( c == pConv->GetEscapeChar() )
	{
		int nLength = pConv->MaxConversionLength();
		if ( !CheckArbitraryPeekGet( 0, nLength ) )
			return '\0';

		c = pConv->FindConversion( (const char *)PeekGet(), &nLength );
		SeekGet( SEEK_CURRENT, nLength );
	}

	return c;
}
//-----------------------------------------------------------------------------
// Reads a null-terminated string
//-----------------------------------------------------------------------------
void CUtlBufferEditor::GetString( char* pString, int nMaxChars )
{
	if (!IsValid())
	{
		*pString = 0;
		return;
	}

	if ( nMaxChars == 0 )
	{
		nMaxChars = INT_MAX;
	}

	// Remember, this *includes* the null character
	// It will be 0, however, if the buffer is empty.
	int nLen = PeekStringLength();

	if ( IsText() )
	{
		EatWhiteSpace();
	}

	if ( nLen == 0 )
	{
		*pString = 0;
		m_Error |= GET_OVERFLOW;
		return;
	}
	
	// Strip off the terminating NULL
	if ( nLen <= nMaxChars )
	{
		Get( pString, nLen - 1 );
		pString[ nLen - 1 ] = 0;
	}
	else
	{
		Get( pString, nMaxChars - 1 );
		pString[ nMaxChars - 1 ] = 0;
		SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars );
	}

	// Read the terminating NULL in binary formats
	if ( !IsText() )
	{
		VerifyEquals( GetChar(), 0 );
	}
}
//-----------------------------------------------------------------------------
// Reads up to and including the first \n
//-----------------------------------------------------------------------------
void CUtlBufferEditor::GetLine( char* pLine, int nMaxChars )
{
	Assert( IsText() && !ContainsCRLF() );

	if ( !IsValid() )
	{
		*pLine = 0;
		return;
	}

	if ( nMaxChars == 0 )
	{
		nMaxChars = INT_MAX;
	}

	// Remember, this *includes* the null character
	// It will be 0, however, if the buffer is empty.
	int nLen = PeekLineLength();
	if ( nLen == 0 )
	{
		*pLine = 0;
		m_Error |= GET_OVERFLOW;
		return;
	}
	
	// Strip off the terminating NULL
	if ( nLen <= nMaxChars )
	{
		Get( pLine, nLen - 1 );
		pLine[ nLen - 1 ] = 0;
	}
	else
	{
		Get( pLine, nMaxChars - 1 );
		pLine[ nMaxChars - 1 ] = 0;
		SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars );
	}
}
//-----------------------------------------------------------------------------
// Parses the next token, given a set of character breaks to stop at
//-----------------------------------------------------------------------------
int CUtlBufferEditor::ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments )
{
	Assert( nMaxLen > 0 );
	pTokenBuf[0] = 0;

	// skip whitespace + comments
	while ( true )
	{
		if ( !IsValid() )
			return -1;
		EatWhiteSpace();
		if ( bParseComments )
		{
			if ( !EatCPPComment() )	
				break;
		}
		else
		{
			break;
		}
	}
	
	char c = GetChar();
	
	// End of buffer
	if ( c == 0 )
		return -1;

	// handle quoted strings specially
	if ( c == '\"' )
	{
		int nLen = 0;
		while( IsValid() )
		{
			c = GetChar();
			if ( c == '\"' || !c )
			{
				pTokenBuf[nLen] = 0;
				return nLen;
			}
			pTokenBuf[nLen] = c;
			if ( ++nLen == nMaxLen )
			{
				pTokenBuf[nLen-1] = 0;
				return nMaxLen;
			}
		}

		// In this case, we hit the end of the buffer before hitting the end qoute
		pTokenBuf[nLen] = 0;
		return nLen;
	}

	// parse single characters
	if ( IN_CHARACTERSET( *pBreaks, c ) )
	{
		pTokenBuf[0] = c;
		pTokenBuf[1] = 0;
		return 1;
	}

	// parse a regular word
	int nLen = 0;
	while ( true )
	{
		pTokenBuf[nLen] = c;
		if ( ++nLen == nMaxLen )
		{
			pTokenBuf[nLen-1] = 0;
			return nMaxLen;
		}
		c = GetChar();
		if ( !IsValid() )
			break;

		if ( IN_CHARACTERSET( *pBreaks, c ) || c == '\"' || c <= ' ' )
		{
			SeekGet( SEEK_CURRENT, -1 );
			break;
		}
	}
	
	pTokenBuf[nLen] = 0;
	return nLen;
}
//-----------------------------------------------------------------------------
// (For text buffers only)
// Parse a token from the buffer:
// Grab all text that lies between a starting delimiter + ending delimiter
// (skipping whitespace that leads + trails both delimiters).
// Note the delimiter checks are case-insensitive.
// If successful, the get index is advanced and the function returns true,
// otherwise the index is not advanced and the function returns false.
//-----------------------------------------------------------------------------
bool CUtlBufferEditor::ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen )
{
	int nCharsToCopy = 0;
	int nCurrentGet = 0;

	size_t nEndingDelimLen;

	// Starting delimiter is optional
	char emptyBuf = '\0';
	if ( !pStartingDelim )
	{
		pStartingDelim = &emptyBuf;
	}

	// Ending delimiter is not
	Assert( pEndingDelim && pEndingDelim[0] );
	nEndingDelimLen = Q_strlen( pEndingDelim );

	int nStartGet = TellGet();
	char nCurrChar;
	int nTokenStart = -1;
	EatWhiteSpace( );
	while ( *pStartingDelim )
	{
		nCurrChar = *pStartingDelim++;
		if ( !isspace((unsigned char)nCurrChar) )
		{
			if ( tolower( GetChar() ) != tolower( nCurrChar ) )
				goto parseFailed;
		}
		else
		{
			EatWhiteSpace();
		}
	}

	EatWhiteSpace();
	nTokenStart = TellGet();
	if ( !GetToken( pEndingDelim ) )
		goto parseFailed;

	nCurrentGet = TellGet();
	nCharsToCopy = (nCurrentGet - nEndingDelimLen) - nTokenStart;
	if ( nCharsToCopy >= nMaxLen )
	{
		nCharsToCopy = nMaxLen - 1;
	}

	if ( nCharsToCopy > 0 )
	{
		SeekGet( CUtlBufferEditor::SEEK_HEAD, nTokenStart );
		Get( pString, nCharsToCopy );
		if ( !IsValid() )
			goto parseFailed;

		// Eat trailing whitespace
		for ( ; nCharsToCopy > 0; --nCharsToCopy )
		{
			if ( !isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) )
				break;
		}
	}
	pString[ nCharsToCopy ] = '\0';

	// Advance the Get index
	SeekGet( CUtlBufferEditor::SEEK_HEAD, nCurrentGet );
	return true;

parseFailed:
	// Revert the get index
	SeekGet( SEEK_HEAD, nStartGet );
	pString[0] = '\0';
	return false;
}