diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /sp/src/tier1/utlstring.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/tier1/utlstring.cpp')
| -rw-r--r-- | sp/src/tier1/utlstring.cpp | 1096 |
1 files changed, 548 insertions, 548 deletions
diff --git a/sp/src/tier1/utlstring.cpp b/sp/src/tier1/utlstring.cpp index 10920db9..85c36a3b 100644 --- a/sp/src/tier1/utlstring.cpp +++ b/sp/src/tier1/utlstring.cpp @@ -1,548 +1,548 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================
-
-#include "tier1/utlstring.h"
-#include "tier1/strtools.h"
-#include <ctype.h>
-
-// NOTE: This has to be the last file included!
-#include "tier0/memdbgon.h"
-
-
-//-----------------------------------------------------------------------------
-// Base class, containing simple memory management
-//-----------------------------------------------------------------------------
-CUtlBinaryBlock::CUtlBinaryBlock( int growSize, int initSize )
-{
- MEM_ALLOC_CREDIT();
- m_Memory.Init( growSize, initSize );
-
- m_nActualLength = 0;
-}
-
-CUtlBinaryBlock::CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Memory( (unsigned char*)pMemory, nSizeInBytes )
-{
- m_nActualLength = nInitialLength;
-}
-
-CUtlBinaryBlock::CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ) : m_Memory( (const unsigned char*)pMemory, nSizeInBytes )
-{
- m_nActualLength = nSizeInBytes;
-}
-
-CUtlBinaryBlock::CUtlBinaryBlock( const CUtlBinaryBlock& src )
-{
- Set( src.Get(), src.Length() );
-}
-
-void CUtlBinaryBlock::Get( void *pValue, int nLen ) const
-{
- Assert( nLen > 0 );
- if ( m_nActualLength < nLen )
- {
- nLen = m_nActualLength;
- }
-
- if ( nLen > 0 )
- {
- memcpy( pValue, m_Memory.Base(), nLen );
- }
-}
-
-void CUtlBinaryBlock::SetLength( int nLength )
-{
- MEM_ALLOC_CREDIT();
- Assert( !m_Memory.IsReadOnly() );
-
- m_nActualLength = nLength;
- if ( nLength > m_Memory.NumAllocated() )
- {
- int nOverFlow = nLength - m_Memory.NumAllocated();
- m_Memory.Grow( nOverFlow );
-
- // If the reallocation failed, clamp length
- if ( nLength > m_Memory.NumAllocated() )
- {
- m_nActualLength = m_Memory.NumAllocated();
- }
- }
-
-#ifdef _DEBUG
- if ( m_Memory.NumAllocated() > m_nActualLength )
- {
- memset( ( ( char * )m_Memory.Base() ) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength );
- }
-#endif
-}
-
-
-void CUtlBinaryBlock::Set( const void *pValue, int nLen )
-{
- Assert( !m_Memory.IsReadOnly() );
-
- if ( !pValue )
- {
- nLen = 0;
- }
-
- SetLength( nLen );
-
- if ( m_nActualLength )
- {
- if ( ( ( const char * )m_Memory.Base() ) >= ( ( const char * )pValue ) + nLen ||
- ( ( const char * )m_Memory.Base() ) + m_nActualLength <= ( ( const char * )pValue ) )
- {
- memcpy( m_Memory.Base(), pValue, m_nActualLength );
- }
- else
- {
- memmove( m_Memory.Base(), pValue, m_nActualLength );
- }
- }
-}
-
-
-CUtlBinaryBlock &CUtlBinaryBlock::operator=( const CUtlBinaryBlock &src )
-{
- Assert( !m_Memory.IsReadOnly() );
- Set( src.Get(), src.Length() );
- return *this;
-}
-
-
-bool CUtlBinaryBlock::operator==( const CUtlBinaryBlock &src ) const
-{
- if ( src.Length() != Length() )
- return false;
-
- return !memcmp( src.Get(), Get(), Length() );
-}
-
-
-//-----------------------------------------------------------------------------
-// Simple string class.
-//-----------------------------------------------------------------------------
-CUtlString::CUtlString()
-{
-}
-
-CUtlString::CUtlString( const char *pString )
-{
- Set( pString );
-}
-
-CUtlString::CUtlString( const CUtlString& string )
-{
- Set( string.Get() );
-}
-
-// Attaches the string to external memory. Useful for avoiding a copy
-CUtlString::CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Storage( pMemory, nSizeInBytes, nInitialLength )
-{
-}
-
-CUtlString::CUtlString( const void* pMemory, int nSizeInBytes ) : m_Storage( pMemory, nSizeInBytes )
-{
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Set directly and don't look for a null terminator in pValue.
-//-----------------------------------------------------------------------------
-void CUtlString::SetDirect( const char *pValue, int nChars )
-{
- Assert( !m_Storage.IsReadOnly() );
- m_Storage.Set( pValue, nChars + 1 );
-
- // Make sure to null terminate the copied string
- *(((char *)m_Storage.Get()) + nChars) = NULL;
-}
-
-
-void CUtlString::Set( const char *pValue )
-{
- Assert( !m_Storage.IsReadOnly() );
- int nLen = pValue ? Q_strlen(pValue) + 1 : 0;
- m_Storage.Set( pValue, nLen );
-}
-
-
-// Returns strlen
-int CUtlString::Length() const
-{
- return m_Storage.Length() ? m_Storage.Length() - 1 : 0;
-}
-
-// Sets the length (used to serialize into the buffer )
-void CUtlString::SetLength( int nLen )
-{
- Assert( !m_Storage.IsReadOnly() );
-
- // Add 1 to account for the NULL
- m_Storage.SetLength( nLen > 0 ? nLen + 1 : 0 );
-}
-
-const char *CUtlString::Get( ) const
-{
- if ( m_Storage.Length() == 0 )
- {
- return "";
- }
-
- return reinterpret_cast< const char* >( m_Storage.Get() );
-}
-
-// Converts to c-strings
-CUtlString::operator const char*() const
-{
- return Get();
-}
-
-char *CUtlString::Get()
-{
- Assert( !m_Storage.IsReadOnly() );
-
- if ( m_Storage.Length() == 0 )
- {
- // In general, we optimise away small mallocs for empty strings
- // but if you ask for the non-const bytes, they must be writable
- // so we can't return "" here, like we do for the const version - jd
- m_Storage.SetLength( 1 );
- m_Storage[ 0 ] = '\0';
- }
-
- return reinterpret_cast< char* >( m_Storage.Get() );
-}
-
-void CUtlString::Purge()
-{
- m_Storage.Purge();
-}
-
-
-void CUtlString::ToLower()
-{
- for( int nLength = Length() - 1; nLength >= 0; nLength-- )
- {
- m_Storage[ nLength ] = tolower( m_Storage[ nLength ] );
- }
-}
-
-
-void CUtlString::ToUpper()
-{
- for( int nLength = Length() - 1; nLength >= 0; nLength-- )
- {
- m_Storage[ nLength ] = toupper( m_Storage[ nLength ] );
- }
-}
-
-
-CUtlString &CUtlString::operator=( const CUtlString &src )
-{
- Assert( !m_Storage.IsReadOnly() );
- m_Storage = src.m_Storage;
- return *this;
-}
-
-CUtlString &CUtlString::operator=( const char *src )
-{
- Assert( !m_Storage.IsReadOnly() );
- Set( src );
- return *this;
-}
-
-bool CUtlString::operator==( const CUtlString &src ) const
-{
- return m_Storage == src.m_Storage;
-}
-
-bool CUtlString::operator==( const char *src ) const
-{
- return ( strcmp( Get(), src ) == 0 );
-}
-
-CUtlString &CUtlString::operator+=( const CUtlString &rhs )
-{
- Assert( !m_Storage.IsReadOnly() );
-
- const int lhsLength( Length() );
- const int rhsLength( rhs.Length() );
- const int requestedLength( lhsLength + rhsLength );
-
- SetLength( requestedLength );
- const int allocatedLength( Length() );
- const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength );
- memcpy( Get() + lhsLength, rhs.Get(), copyLength );
- m_Storage[ allocatedLength ] = '\0';
-
- return *this;
-}
-
-CUtlString &CUtlString::operator+=( const char *rhs )
-{
- Assert( !m_Storage.IsReadOnly() );
-
- const int lhsLength( Length() );
- const int rhsLength( Q_strlen( rhs ) );
- const int requestedLength( lhsLength + rhsLength );
-
- SetLength( requestedLength );
- const int allocatedLength( Length() );
- const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength );
- memcpy( Get() + lhsLength, rhs, copyLength );
- m_Storage[ allocatedLength ] = '\0';
-
- return *this;
-}
-
-CUtlString &CUtlString::operator+=( char c )
-{
- Assert( !m_Storage.IsReadOnly() );
-
- int nLength = Length();
- SetLength( nLength + 1 );
- m_Storage[ nLength ] = c;
- m_Storage[ nLength+1 ] = '\0';
- return *this;
-}
-
-CUtlString &CUtlString::operator+=( int rhs )
-{
- Assert( !m_Storage.IsReadOnly() );
- Assert( sizeof( rhs ) == 4 );
-
- char tmpBuf[ 12 ]; // Sufficient for a signed 32 bit integer [ -2147483648 to +2147483647 ]
- Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%d", rhs );
- tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0';
-
- return operator+=( tmpBuf );
-}
-
-CUtlString &CUtlString::operator+=( double rhs )
-{
- Assert( !m_Storage.IsReadOnly() );
-
- char tmpBuf[ 256 ]; // How big can doubles be??? Dunno.
- Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%lg", rhs );
- tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0';
-
- return operator+=( tmpBuf );
-}
-
-bool CUtlString::MatchesPattern( const CUtlString &Pattern, int nFlags )
-{
- const char *pszSource = String();
- const char *pszPattern = Pattern.String();
- bool bExact = true;
-
- while( 1 )
- {
- if ( ( *pszPattern ) == 0 )
- {
- return ( (*pszSource ) == 0 );
- }
-
- if ( ( *pszPattern ) == '*' )
- {
- pszPattern++;
-
- if ( ( *pszPattern ) == 0 )
- {
- return true;
- }
-
- bExact = false;
- continue;
- }
-
- int nLength = 0;
-
- while( ( *pszPattern ) != '*' && ( *pszPattern ) != 0 )
- {
- nLength++;
- pszPattern++;
- }
-
- while( 1 )
- {
- const char *pszStartPattern = pszPattern - nLength;
- const char *pszSearch = pszSource;
-
- for( int i = 0; i < nLength; i++, pszSearch++, pszStartPattern++ )
- {
- if ( ( *pszSearch ) == 0 )
- {
- return false;
- }
-
- if ( ( *pszSearch ) != ( *pszStartPattern ) )
- {
- break;
- }
- }
-
- if ( pszSearch - pszSource == nLength )
- {
- break;
- }
-
- if ( bExact == true )
- {
- return false;
- }
-
- if ( ( nFlags & PATTERN_DIRECTORY ) != 0 )
- {
- if ( ( *pszPattern ) != '/' && ( *pszSource ) == '/' )
- {
- return false;
- }
- }
-
- pszSource++;
- }
-
- pszSource += nLength;
- }
-}
-
-
-int CUtlString::Format( const char *pFormat, ... )
-{
- Assert( !m_Storage.IsReadOnly() );
-
- char tmpBuf[ 4096 ]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer
-
- va_list marker;
-
- va_start( marker, pFormat );
-#ifdef _WIN32
- int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker );
-#elif POSIX
- int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker );
-#else
-#error "define vsnprintf type."
-#endif
- va_end( marker );
-
- // Len > maxLen represents an overflow on POSIX, < 0 is an overflow on windows
- if( len < 0 || len >= sizeof( tmpBuf ) - 1 )
- {
- len = sizeof( tmpBuf ) - 1;
- tmpBuf[sizeof( tmpBuf ) - 1] = 0;
- }
-
- Set( tmpBuf );
-
- return len;
-}
-
-//-----------------------------------------------------------------------------
-// Strips the trailing slash
-//-----------------------------------------------------------------------------
-void CUtlString::StripTrailingSlash()
-{
- if ( IsEmpty() )
- return;
-
- int nLastChar = Length() - 1;
- char c = m_Storage[ nLastChar ];
- if ( c == '\\' || c == '/' )
- {
- m_Storage[ nLastChar ] = 0;
- m_Storage.SetLength( m_Storage.Length() - 1 );
- }
-}
-
-CUtlString CUtlString::Slice( int32 nStart, int32 nEnd )
-{
- if ( nStart < 0 )
- nStart = Length() - (-nStart % Length());
- else if ( nStart >= Length() )
- nStart = Length();
-
- if ( nEnd == 0x7FFFFFFF )
- nEnd = Length();
- else if ( nEnd < 0 )
- nEnd = Length() - (-nEnd % Length());
- else if ( nEnd >= Length() )
- nEnd = Length();
-
- if ( nStart >= nEnd )
- return CUtlString( "" );
-
- const char *pIn = String();
-
- CUtlString ret;
- ret.m_Storage.SetLength( nEnd - nStart + 1 );
- char *pOut = (char*)ret.m_Storage.Get();
-
- memcpy( ret.m_Storage.Get(), &pIn[nStart], nEnd - nStart );
- pOut[nEnd - nStart] = 0;
-
- return ret;
-}
-
-// Grab a substring starting from the left or the right side.
-CUtlString CUtlString::Left( int32 nChars )
-{
- return Slice( 0, nChars );
-}
-
-CUtlString CUtlString::Right( int32 nChars )
-{
- return Slice( -nChars );
-}
-
-CUtlString CUtlString::Replace( char cFrom, char cTo )
-{
- CUtlString ret = *this;
- int len = ret.Length();
- for ( int i=0; i < len; i++ )
- {
- if ( ret.m_Storage[i] == cFrom )
- ret.m_Storage[i] = cTo;
- }
-
- return ret;
-}
-
-CUtlString CUtlString::AbsPath( const char *pStartingDir )
-{
- char szNew[MAX_PATH];
- V_MakeAbsolutePath( szNew, sizeof( szNew ), this->String(), pStartingDir );
- return CUtlString( szNew );
-}
-
-CUtlString CUtlString::UnqualifiedFilename()
-{
- const char *pFilename = V_UnqualifiedFileName( this->String() );
- return CUtlString( pFilename );
-}
-
-CUtlString CUtlString::DirName()
-{
- CUtlString ret( this->String() );
- V_StripLastDir( (char*)ret.m_Storage.Get(), ret.m_Storage.Length() );
- V_StripTrailingSlash( (char*)ret.m_Storage.Get() );
- return ret;
-}
-
-CUtlString CUtlString::PathJoin( const char *pStr1, const char *pStr2 )
-{
- char szPath[MAX_PATH];
- V_ComposeFileName( pStr1, pStr2, szPath, sizeof( szPath ) );
- return CUtlString( szPath );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: concatenate the provided string to our current content
-//-----------------------------------------------------------------------------
-void CUtlString::Append( const char *pchAddition )
-{
- *this += pchAddition;
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "tier1/utlstring.h" +#include "tier1/strtools.h" +#include <ctype.h> + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Base class, containing simple memory management +//----------------------------------------------------------------------------- +CUtlBinaryBlock::CUtlBinaryBlock( int growSize, int initSize ) +{ + MEM_ALLOC_CREDIT(); + m_Memory.Init( growSize, initSize ); + + m_nActualLength = 0; +} + +CUtlBinaryBlock::CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Memory( (unsigned char*)pMemory, nSizeInBytes ) +{ + m_nActualLength = nInitialLength; +} + +CUtlBinaryBlock::CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ) : m_Memory( (const unsigned char*)pMemory, nSizeInBytes ) +{ + m_nActualLength = nSizeInBytes; +} + +CUtlBinaryBlock::CUtlBinaryBlock( const CUtlBinaryBlock& src ) +{ + Set( src.Get(), src.Length() ); +} + +void CUtlBinaryBlock::Get( void *pValue, int nLen ) const +{ + Assert( nLen > 0 ); + if ( m_nActualLength < nLen ) + { + nLen = m_nActualLength; + } + + if ( nLen > 0 ) + { + memcpy( pValue, m_Memory.Base(), nLen ); + } +} + +void CUtlBinaryBlock::SetLength( int nLength ) +{ + MEM_ALLOC_CREDIT(); + Assert( !m_Memory.IsReadOnly() ); + + m_nActualLength = nLength; + if ( nLength > m_Memory.NumAllocated() ) + { + int nOverFlow = nLength - m_Memory.NumAllocated(); + m_Memory.Grow( nOverFlow ); + + // If the reallocation failed, clamp length + if ( nLength > m_Memory.NumAllocated() ) + { + m_nActualLength = m_Memory.NumAllocated(); + } + } + +#ifdef _DEBUG + if ( m_Memory.NumAllocated() > m_nActualLength ) + { + memset( ( ( char * )m_Memory.Base() ) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength ); + } +#endif +} + + +void CUtlBinaryBlock::Set( const void *pValue, int nLen ) +{ + Assert( !m_Memory.IsReadOnly() ); + + if ( !pValue ) + { + nLen = 0; + } + + SetLength( nLen ); + + if ( m_nActualLength ) + { + if ( ( ( const char * )m_Memory.Base() ) >= ( ( const char * )pValue ) + nLen || + ( ( const char * )m_Memory.Base() ) + m_nActualLength <= ( ( const char * )pValue ) ) + { + memcpy( m_Memory.Base(), pValue, m_nActualLength ); + } + else + { + memmove( m_Memory.Base(), pValue, m_nActualLength ); + } + } +} + + +CUtlBinaryBlock &CUtlBinaryBlock::operator=( const CUtlBinaryBlock &src ) +{ + Assert( !m_Memory.IsReadOnly() ); + Set( src.Get(), src.Length() ); + return *this; +} + + +bool CUtlBinaryBlock::operator==( const CUtlBinaryBlock &src ) const +{ + if ( src.Length() != Length() ) + return false; + + return !memcmp( src.Get(), Get(), Length() ); +} + + +//----------------------------------------------------------------------------- +// Simple string class. +//----------------------------------------------------------------------------- +CUtlString::CUtlString() +{ +} + +CUtlString::CUtlString( const char *pString ) +{ + Set( pString ); +} + +CUtlString::CUtlString( const CUtlString& string ) +{ + Set( string.Get() ); +} + +// Attaches the string to external memory. Useful for avoiding a copy +CUtlString::CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ) : m_Storage( pMemory, nSizeInBytes, nInitialLength ) +{ +} + +CUtlString::CUtlString( const void* pMemory, int nSizeInBytes ) : m_Storage( pMemory, nSizeInBytes ) +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Set directly and don't look for a null terminator in pValue. +//----------------------------------------------------------------------------- +void CUtlString::SetDirect( const char *pValue, int nChars ) +{ + Assert( !m_Storage.IsReadOnly() ); + m_Storage.Set( pValue, nChars + 1 ); + + // Make sure to null terminate the copied string + *(((char *)m_Storage.Get()) + nChars) = NULL; +} + + +void CUtlString::Set( const char *pValue ) +{ + Assert( !m_Storage.IsReadOnly() ); + int nLen = pValue ? Q_strlen(pValue) + 1 : 0; + m_Storage.Set( pValue, nLen ); +} + + +// Returns strlen +int CUtlString::Length() const +{ + return m_Storage.Length() ? m_Storage.Length() - 1 : 0; +} + +// Sets the length (used to serialize into the buffer ) +void CUtlString::SetLength( int nLen ) +{ + Assert( !m_Storage.IsReadOnly() ); + + // Add 1 to account for the NULL + m_Storage.SetLength( nLen > 0 ? nLen + 1 : 0 ); +} + +const char *CUtlString::Get( ) const +{ + if ( m_Storage.Length() == 0 ) + { + return ""; + } + + return reinterpret_cast< const char* >( m_Storage.Get() ); +} + +// Converts to c-strings +CUtlString::operator const char*() const +{ + return Get(); +} + +char *CUtlString::Get() +{ + Assert( !m_Storage.IsReadOnly() ); + + if ( m_Storage.Length() == 0 ) + { + // In general, we optimise away small mallocs for empty strings + // but if you ask for the non-const bytes, they must be writable + // so we can't return "" here, like we do for the const version - jd + m_Storage.SetLength( 1 ); + m_Storage[ 0 ] = '\0'; + } + + return reinterpret_cast< char* >( m_Storage.Get() ); +} + +void CUtlString::Purge() +{ + m_Storage.Purge(); +} + + +void CUtlString::ToLower() +{ + for( int nLength = Length() - 1; nLength >= 0; nLength-- ) + { + m_Storage[ nLength ] = tolower( m_Storage[ nLength ] ); + } +} + + +void CUtlString::ToUpper() +{ + for( int nLength = Length() - 1; nLength >= 0; nLength-- ) + { + m_Storage[ nLength ] = toupper( m_Storage[ nLength ] ); + } +} + + +CUtlString &CUtlString::operator=( const CUtlString &src ) +{ + Assert( !m_Storage.IsReadOnly() ); + m_Storage = src.m_Storage; + return *this; +} + +CUtlString &CUtlString::operator=( const char *src ) +{ + Assert( !m_Storage.IsReadOnly() ); + Set( src ); + return *this; +} + +bool CUtlString::operator==( const CUtlString &src ) const +{ + return m_Storage == src.m_Storage; +} + +bool CUtlString::operator==( const char *src ) const +{ + return ( strcmp( Get(), src ) == 0 ); +} + +CUtlString &CUtlString::operator+=( const CUtlString &rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + + const int lhsLength( Length() ); + const int rhsLength( rhs.Length() ); + const int requestedLength( lhsLength + rhsLength ); + + SetLength( requestedLength ); + const int allocatedLength( Length() ); + const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); + memcpy( Get() + lhsLength, rhs.Get(), copyLength ); + m_Storage[ allocatedLength ] = '\0'; + + return *this; +} + +CUtlString &CUtlString::operator+=( const char *rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + + const int lhsLength( Length() ); + const int rhsLength( Q_strlen( rhs ) ); + const int requestedLength( lhsLength + rhsLength ); + + SetLength( requestedLength ); + const int allocatedLength( Length() ); + const int copyLength( allocatedLength - lhsLength < rhsLength ? allocatedLength - lhsLength : rhsLength ); + memcpy( Get() + lhsLength, rhs, copyLength ); + m_Storage[ allocatedLength ] = '\0'; + + return *this; +} + +CUtlString &CUtlString::operator+=( char c ) +{ + Assert( !m_Storage.IsReadOnly() ); + + int nLength = Length(); + SetLength( nLength + 1 ); + m_Storage[ nLength ] = c; + m_Storage[ nLength+1 ] = '\0'; + return *this; +} + +CUtlString &CUtlString::operator+=( int rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + Assert( sizeof( rhs ) == 4 ); + + char tmpBuf[ 12 ]; // Sufficient for a signed 32 bit integer [ -2147483648 to +2147483647 ] + Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%d", rhs ); + tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0'; + + return operator+=( tmpBuf ); +} + +CUtlString &CUtlString::operator+=( double rhs ) +{ + Assert( !m_Storage.IsReadOnly() ); + + char tmpBuf[ 256 ]; // How big can doubles be??? Dunno. + Q_snprintf( tmpBuf, sizeof( tmpBuf ), "%lg", rhs ); + tmpBuf[ sizeof( tmpBuf ) - 1 ] = '\0'; + + return operator+=( tmpBuf ); +} + +bool CUtlString::MatchesPattern( const CUtlString &Pattern, int nFlags ) +{ + const char *pszSource = String(); + const char *pszPattern = Pattern.String(); + bool bExact = true; + + while( 1 ) + { + if ( ( *pszPattern ) == 0 ) + { + return ( (*pszSource ) == 0 ); + } + + if ( ( *pszPattern ) == '*' ) + { + pszPattern++; + + if ( ( *pszPattern ) == 0 ) + { + return true; + } + + bExact = false; + continue; + } + + int nLength = 0; + + while( ( *pszPattern ) != '*' && ( *pszPattern ) != 0 ) + { + nLength++; + pszPattern++; + } + + while( 1 ) + { + const char *pszStartPattern = pszPattern - nLength; + const char *pszSearch = pszSource; + + for( int i = 0; i < nLength; i++, pszSearch++, pszStartPattern++ ) + { + if ( ( *pszSearch ) == 0 ) + { + return false; + } + + if ( ( *pszSearch ) != ( *pszStartPattern ) ) + { + break; + } + } + + if ( pszSearch - pszSource == nLength ) + { + break; + } + + if ( bExact == true ) + { + return false; + } + + if ( ( nFlags & PATTERN_DIRECTORY ) != 0 ) + { + if ( ( *pszPattern ) != '/' && ( *pszSource ) == '/' ) + { + return false; + } + } + + pszSource++; + } + + pszSource += nLength; + } +} + + +int CUtlString::Format( const char *pFormat, ... ) +{ + Assert( !m_Storage.IsReadOnly() ); + + char tmpBuf[ 4096 ]; //< Nice big 4k buffer, as much memory as my first computer had, a Radio Shack Color Computer + + va_list marker; + + va_start( marker, pFormat ); +#ifdef _WIN32 + int len = _vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); +#elif POSIX + int len = vsnprintf( tmpBuf, sizeof( tmpBuf ) - 1, pFormat, marker ); +#else +#error "define vsnprintf type." +#endif + va_end( marker ); + + // Len > maxLen represents an overflow on POSIX, < 0 is an overflow on windows + if( len < 0 || len >= sizeof( tmpBuf ) - 1 ) + { + len = sizeof( tmpBuf ) - 1; + tmpBuf[sizeof( tmpBuf ) - 1] = 0; + } + + Set( tmpBuf ); + + return len; +} + +//----------------------------------------------------------------------------- +// Strips the trailing slash +//----------------------------------------------------------------------------- +void CUtlString::StripTrailingSlash() +{ + if ( IsEmpty() ) + return; + + int nLastChar = Length() - 1; + char c = m_Storage[ nLastChar ]; + if ( c == '\\' || c == '/' ) + { + m_Storage[ nLastChar ] = 0; + m_Storage.SetLength( m_Storage.Length() - 1 ); + } +} + +CUtlString CUtlString::Slice( int32 nStart, int32 nEnd ) +{ + if ( nStart < 0 ) + nStart = Length() - (-nStart % Length()); + else if ( nStart >= Length() ) + nStart = Length(); + + if ( nEnd == 0x7FFFFFFF ) + nEnd = Length(); + else if ( nEnd < 0 ) + nEnd = Length() - (-nEnd % Length()); + else if ( nEnd >= Length() ) + nEnd = Length(); + + if ( nStart >= nEnd ) + return CUtlString( "" ); + + const char *pIn = String(); + + CUtlString ret; + ret.m_Storage.SetLength( nEnd - nStart + 1 ); + char *pOut = (char*)ret.m_Storage.Get(); + + memcpy( ret.m_Storage.Get(), &pIn[nStart], nEnd - nStart ); + pOut[nEnd - nStart] = 0; + + return ret; +} + +// Grab a substring starting from the left or the right side. +CUtlString CUtlString::Left( int32 nChars ) +{ + return Slice( 0, nChars ); +} + +CUtlString CUtlString::Right( int32 nChars ) +{ + return Slice( -nChars ); +} + +CUtlString CUtlString::Replace( char cFrom, char cTo ) +{ + CUtlString ret = *this; + int len = ret.Length(); + for ( int i=0; i < len; i++ ) + { + if ( ret.m_Storage[i] == cFrom ) + ret.m_Storage[i] = cTo; + } + + return ret; +} + +CUtlString CUtlString::AbsPath( const char *pStartingDir ) +{ + char szNew[MAX_PATH]; + V_MakeAbsolutePath( szNew, sizeof( szNew ), this->String(), pStartingDir ); + return CUtlString( szNew ); +} + +CUtlString CUtlString::UnqualifiedFilename() +{ + const char *pFilename = V_UnqualifiedFileName( this->String() ); + return CUtlString( pFilename ); +} + +CUtlString CUtlString::DirName() +{ + CUtlString ret( this->String() ); + V_StripLastDir( (char*)ret.m_Storage.Get(), ret.m_Storage.Length() ); + V_StripTrailingSlash( (char*)ret.m_Storage.Get() ); + return ret; +} + +CUtlString CUtlString::PathJoin( const char *pStr1, const char *pStr2 ) +{ + char szPath[MAX_PATH]; + V_ComposeFileName( pStr1, pStr2, szPath, sizeof( szPath ) ); + return CUtlString( szPath ); +} + +//----------------------------------------------------------------------------- +// Purpose: concatenate the provided string to our current content +//----------------------------------------------------------------------------- +void CUtlString::Append( const char *pchAddition ) +{ + *this += pchAddition; +} |