amd64: fix multithread, fix vgui, fix physmodels

This commit is contained in:
nillerusr
2022-06-05 01:44:42 +03:00
parent 01413fdd71
commit 9ee21ecf90
63 changed files with 5679 additions and 2468 deletions
+2 -2
View File
@@ -1425,7 +1425,7 @@ const char *KeyValues::GetString( const char *keyName, const char *defaultValue
SetString( keyName, buf );
break;
case TYPE_PTR:
Q_snprintf( buf, sizeof( buf ), "%lld", (int64)(size_t)dat->m_pValue );
Q_snprintf( buf, sizeof( buf ), "%lld", (int64)dat->m_pValue );
SetString( keyName, buf );
break;
case TYPE_INT:
@@ -1478,7 +1478,7 @@ const wchar_t *KeyValues::GetWString( const char *keyName, const wchar_t *defaul
SetWString( keyName, wbuf);
break;
case TYPE_PTR:
swprintf( wbuf, Q_ARRAYSIZE(wbuf), L"%lld", (int64)(size_t)dat->m_pValue );
swprintf( wbuf, Q_ARRAYSIZE(wbuf), L"%lld", (int64)dat->m_pValue );
SetWString( keyName, wbuf );
break;
case TYPE_INT:
+10 -218
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
@@ -18,16 +18,21 @@
// Purpose: Comparison function for string sorted associative data structures
//-----------------------------------------------------------------------------
bool StrLess( const char * const &pszLeft, const char * const &pszRight )
bool StrLessInsensitive( const char * const &pszLeft, const char * const &pszRight )
{
return ( Q_stricmp( pszLeft, pszRight) < 0 );
}
bool StrLessSensitive( const char * const &pszLeft, const char * const &pszRight )
{
return ( Q_strcmp( pszLeft, pszRight) < 0 );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CStringPool::CStringPool()
: m_Strings( 32, 256, StrLess )
CStringPool::CStringPool( StringPoolCase_t caseSensitivity )
: m_Strings( 32, 256, caseSensitivity == StringPoolCaseInsensitive ? StrLessInsensitive : StrLessSensitive )
{
}
@@ -69,9 +74,7 @@ const char * CStringPool::Allocate( const char *pszValue )
return m_Strings[i];
pszNew = strdup( pszValue );
if ( bNew )
m_Strings.Insert( pszNew );
m_Strings.Insert( pszNew );
return pszNew;
}
@@ -94,217 +97,6 @@ void CStringPool::FreeAll()
//-----------------------------------------------------------------------------
CCountedStringPool::CCountedStringPool()
{
MEM_ALLOC_CREDIT();
m_HashTable.EnsureCount(HASH_TABLE_SIZE);
for( int i = 0; i < m_HashTable.Count(); i++ )
{
m_HashTable[i] = INVALID_ELEMENT;
}
m_FreeListStart = INVALID_ELEMENT;
m_Elements.AddToTail();
m_Elements[0].pString = NULL;
m_Elements[0].nReferenceCount = 0;
m_Elements[0].nNextElement = INVALID_ELEMENT;
}
CCountedStringPool::~CCountedStringPool()
{
FreeAll();
}
void CCountedStringPool::FreeAll()
{
int i;
// Reset the hash table:
for( i = 0; i < m_HashTable.Count(); i++ )
{
m_HashTable[i] = INVALID_ELEMENT;
}
// Blow away the free list:
m_FreeListStart = INVALID_ELEMENT;
for( i = 0; i < m_Elements.Count(); i++ )
{
if( m_Elements[i].pString )
{
delete [] m_Elements[i].pString;
m_Elements[i].pString = NULL;
m_Elements[i].nReferenceCount = 0;
m_Elements[i].nNextElement = INVALID_ELEMENT;
}
}
// Remove all but the invalid element:
m_Elements.RemoveAll();
m_Elements.AddToTail();
m_Elements[0].pString = NULL;
m_Elements[0].nReferenceCount = 0;
m_Elements[0].nNextElement = INVALID_ELEMENT;
}
unsigned short CCountedStringPool::FindStringHandle( const char* pIntrinsic )
{
if( pIntrinsic == NULL )
return INVALID_ELEMENT;
unsigned short nHashBucketIndex = (HashStringCaseless(pIntrinsic ) %HASH_TABLE_SIZE);
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
// Does the bucket already exist?
if( nCurrentBucket != INVALID_ELEMENT )
{
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
{
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
{
return nCurrentBucket;
}
}
}
return 0;
}
char* CCountedStringPool::FindString( const char* pIntrinsic )
{
if( pIntrinsic == NULL )
return NULL;
// Yes, this will be NULL on failure.
return m_Elements[FindStringHandle(pIntrinsic)].pString;
}
unsigned short CCountedStringPool::ReferenceStringHandle( const char* pIntrinsic )
{
if( pIntrinsic == NULL )
return INVALID_ELEMENT;
unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % HASH_TABLE_SIZE);
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
// Does the bucket already exist?
if( nCurrentBucket != INVALID_ELEMENT )
{
for( ; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
{
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
{
// Anyone who hits 65k references is permanant
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
{
m_Elements[nCurrentBucket].nReferenceCount ++ ;
}
return nCurrentBucket;
}
}
}
if( m_FreeListStart != INVALID_ELEMENT )
{
nCurrentBucket = m_FreeListStart;
m_FreeListStart = m_Elements[nCurrentBucket].nNextElement;
}
else
{
nCurrentBucket = m_Elements.AddToTail();
}
m_Elements[nCurrentBucket].nReferenceCount = 1;
// Insert at the beginning of the bucket:
m_Elements[nCurrentBucket].nNextElement = m_HashTable[ nHashBucketIndex ];
m_HashTable[ nHashBucketIndex ] = nCurrentBucket;
m_Elements[nCurrentBucket].pString = new char[Q_strlen( pIntrinsic ) + 1];
Q_strcpy( m_Elements[nCurrentBucket].pString, pIntrinsic );
return nCurrentBucket;
}
char* CCountedStringPool::ReferenceString( const char* pIntrinsic )
{
if(!pIntrinsic)
return NULL;
return m_Elements[ReferenceStringHandle( pIntrinsic)].pString;
}
void CCountedStringPool::DereferenceString( const char* pIntrinsic )
{
// If we get a NULL pointer, just return
if (!pIntrinsic)
return;
unsigned short nHashBucketIndex = (HashStringCaseless( pIntrinsic ) % m_HashTable.Count());
unsigned short nCurrentBucket = m_HashTable[ nHashBucketIndex ];
// If there isn't anything in the bucket, just return.
if ( nCurrentBucket == INVALID_ELEMENT )
return;
for( unsigned short previous = INVALID_ELEMENT; nCurrentBucket != INVALID_ELEMENT ; nCurrentBucket = m_Elements[nCurrentBucket].nNextElement )
{
if( !Q_stricmp( pIntrinsic, m_Elements[nCurrentBucket].pString ) )
{
// Anyone who hits 65k references is permanant
if( m_Elements[nCurrentBucket].nReferenceCount < MAX_REFERENCE )
{
m_Elements[nCurrentBucket].nReferenceCount --;
}
if( m_Elements[nCurrentBucket].nReferenceCount == 0 )
{
if( previous == INVALID_ELEMENT )
{
m_HashTable[nHashBucketIndex] = m_Elements[nCurrentBucket].nNextElement;
}
else
{
m_Elements[previous].nNextElement = m_Elements[nCurrentBucket].nNextElement;
}
delete [] m_Elements[nCurrentBucket].pString;
m_Elements[nCurrentBucket].pString = NULL;
m_Elements[nCurrentBucket].nReferenceCount = 0;
m_Elements[nCurrentBucket].nNextElement = m_FreeListStart;
m_FreeListStart = nCurrentBucket;
break;
}
}
previous = nCurrentBucket;
}
}
char* CCountedStringPool::HandleToString( unsigned short handle )
{
return m_Elements[handle].pString;
}
void CCountedStringPool::SpewStrings()
{
int i;
for ( i = 0; i < m_Elements.Count(); i++ )
{
char* string = m_Elements[i].pString;
Msg("String %d: ref:%d %s", i, m_Elements[i].nReferenceCount, string == NULL? "EMPTY - ok for slot zero only!" : string);
}
Msg("\n%d total counted strings.", m_Elements.Count());
}
#ifdef _DEBUG
CON_COMMAND( test_stringpool, "Tests the class CStringPool" )
{
+311 -170
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// $Header: $
// $NoKeywords: $
@@ -92,14 +92,14 @@ CUtlCStringConversion::CUtlCStringConversion( char nEscapeChar, const char *pDel
memset( m_pConversion, 0x0, sizeof(m_pConversion) );
for ( int i = 0; i < nCount; ++i )
{
m_pConversion[ (unsigned char) pArray[i].m_pReplacementString[0] ] = pArray[i].m_nActualChar;
m_pConversion[ (unsigned char)(pArray[i].m_pReplacementString[0]) ] = pArray[i].m_nActualChar;
}
}
// Finds a conversion for the passed-in string, returns length
char CUtlCStringConversion::FindConversion( const char *pString, int *pLength )
{
char c = m_pConversion[ (unsigned char) pString[0] ];
char c = m_pConversion[ (unsigned char)( pString[0] ) ];
*pLength = (c != '\0') ? 1 : 0;
return c;
}
@@ -114,7 +114,7 @@ CUtlCharConversion::CUtlCharConversion( char nEscapeChar, const char *pDelimiter
m_nEscapeChar = nEscapeChar;
m_pDelimiter = pDelimiter;
m_nCount = nCount;
m_nDelimiterLength = Q_strlen( pDelimiter );
m_nDelimiterLength = V_strlen( pDelimiter );
m_nMaxConversionLength = 0;
memset( m_pReplacements, 0, sizeof(m_pReplacements) );
@@ -122,10 +122,10 @@ CUtlCharConversion::CUtlCharConversion( char nEscapeChar, const char *pDelimiter
for ( int i = 0; i < nCount; ++i )
{
m_pList[i] = pArray[i].m_nActualChar;
ConversionInfo_t &info = m_pReplacements[ (unsigned char) m_pList[i] ];
ConversionInfo_t &info = m_pReplacements[ (unsigned char)( m_pList[i] ) ];
Assert( info.m_pReplacementString == 0 );
info.m_pReplacementString = pArray[i].m_pReplacementString;
info.m_nLength = Q_strlen( info.m_pReplacementString );
info.m_nLength = V_strlen( info.m_pReplacementString );
if ( info.m_nLength > m_nMaxConversionLength )
{
m_nMaxConversionLength = info.m_nLength;
@@ -158,12 +158,12 @@ int CUtlCharConversion::GetDelimiterLength() const
//-----------------------------------------------------------------------------
const char *CUtlCharConversion::GetConversionString( char c ) const
{
return m_pReplacements[ (unsigned char) c ].m_pReplacementString;
return m_pReplacements[ (unsigned char)c ].m_pReplacementString;
}
int CUtlCharConversion::GetConversionLength( char c ) const
{
return m_pReplacements[ (unsigned char) c ].m_nLength;
return m_pReplacements[ (unsigned char)c ].m_nLength;
}
int CUtlCharConversion::MaxConversionLength() const
@@ -179,9 +179,9 @@ char CUtlCharConversion::FindConversion( const char *pString, int *pLength )
{
for ( int i = 0; i < m_nCount; ++i )
{
if ( !Q_strcmp( pString, m_pReplacements[ (unsigned char) m_pList[i] ].m_pReplacementString ) )
if ( !V_strcmp( pString, m_pReplacements[ (unsigned char)( m_pList[i] ) ].m_pReplacementString ) )
{
*pLength = m_pReplacements[ (unsigned char) m_pList[i] ].m_nLength;
*pLength = m_pReplacements[ (unsigned char)( m_pList[i] ) ].m_nLength;
return m_pList[i];
}
}
@@ -207,7 +207,7 @@ CUtlBuffer::CUtlBuffer( int growSize, int initSize, int nFlags ) :
if ( (initSize != 0) && !IsReadOnly() )
{
m_nMaxPut = -1;
AddNullTermination();
AddNullTermination( m_Put );
}
else
{
@@ -228,17 +228,115 @@ CUtlBuffer::CUtlBuffer( const void *pBuffer, int nSize, int nFlags ) :
m_Flags = nFlags;
if ( IsReadOnly() )
{
m_nMaxPut = nSize;
m_nMaxPut = m_Put = nSize;
}
else
{
m_nMaxPut = -1;
AddNullTermination();
AddNullTermination( m_Put );
}
SetOverflowFuncs( &CUtlBuffer::GetOverflow, &CUtlBuffer::PutOverflow );
}
CUtlBuffer::CUtlBuffer( const CUtlBuffer& copyFrom )
: m_Get( copyFrom.m_Get )
, m_Put( copyFrom.m_Put )
, m_Error( copyFrom.m_Error )
, m_Flags( copyFrom.m_Flags )
, m_Reserved( copyFrom.m_Reserved )
#if defined( _GAMECONSOLE )
, pad( copyFrom.pad )
#endif
, m_nTab( copyFrom.m_nTab )
, m_nMaxPut( copyFrom.m_nMaxPut )
, m_nOffset( copyFrom.m_nOffset )
, m_GetOverflowFunc( copyFrom.m_GetOverflowFunc )
, m_PutOverflowFunc( copyFrom.m_PutOverflowFunc )
, m_Byteswap( copyFrom.m_Byteswap )
{
if(copyFrom.m_Memory.Count() > 0)
{
Assert( false ); // This is a slow path, don't do this.
// copy memory
m_Memory.EnsureCapacity( copyFrom.m_Memory.Count() );
memcpy( m_Memory.Base(), copyFrom.m_Memory.Base(), copyFrom.m_Memory.Count() );
}
}
CUtlBuffer& CUtlBuffer::operator=( const CUtlBuffer& copyFrom )
{
if ( copyFrom.m_Memory.Count() > 0 )
{
Assert( false ); // This is a slow path, don't do this.
if(this != &copyFrom)
{
m_Memory.Purge();
m_Memory.EnsureCapacity( copyFrom.m_Memory.Count() );
memcpy( m_Memory.Base(), copyFrom.m_Memory.Base(), copyFrom.m_Memory.Count() );
}
}
m_Get = copyFrom.m_Get;
m_Put = copyFrom.m_Put;
m_Error = copyFrom.m_Error;
m_Flags = copyFrom.m_Flags;
m_Reserved = copyFrom.m_Reserved;
#if defined( _GAMECONSOLE )
pad = copyFrom.pad;
#endif
m_nTab = copyFrom.m_nTab;
m_nMaxPut = copyFrom.m_nMaxPut;
m_nOffset = copyFrom.m_nOffset;
m_GetOverflowFunc = copyFrom.m_GetOverflowFunc;
m_PutOverflowFunc = copyFrom.m_PutOverflowFunc;
m_Byteswap = copyFrom.m_Byteswap;
return *this;
}
#if VALVE_CPP11
CUtlBuffer::CUtlBuffer( CUtlBuffer&& moveFrom ) // = default
: m_Memory( Move( moveFrom.m_Memory ) )
, m_Get( Move( moveFrom.m_Get ) )
, m_Put( Move( moveFrom.m_Put ) )
, m_Error( Move( moveFrom.m_Error ) )
, m_Flags( Move( moveFrom.m_Flags ) )
, m_Reserved( Move( moveFrom.m_Reserved ) )
#if defined( _GAMECONSOLE )
, pad( Move( moveFrom.pad ) )
#endif
, m_nTab( Move( moveFrom.m_nTab ) )
, m_nMaxPut( Move( moveFrom.m_nMaxPut ) )
, m_nOffset( Move( moveFrom.m_nOffset ) )
, m_GetOverflowFunc( Move( moveFrom.m_GetOverflowFunc ) )
, m_PutOverflowFunc( Move( moveFrom.m_PutOverflowFunc ) )
, m_Byteswap( Move( moveFrom.m_Byteswap ) )
{}
CUtlBuffer& CUtlBuffer::operator=( CUtlBuffer&& moveFrom ) // = default
{
m_Memory = Move( moveFrom.m_Memory );
m_Get = Move( moveFrom.m_Get );
m_Put = Move( moveFrom.m_Put );
m_Error = Move( moveFrom.m_Error );
m_Flags = Move( moveFrom.m_Flags );
m_Reserved = Move( moveFrom.m_Reserved );
#if defined( _GAMECONSOLE )
pad = Move( moveFrom.pad );
#endif
m_nTab = Move( moveFrom.m_nTab );
m_nMaxPut = Move( moveFrom.m_nMaxPut );
m_nOffset = Move( moveFrom.m_nOffset );
m_GetOverflowFunc = Move( moveFrom.m_GetOverflowFunc );
m_PutOverflowFunc = Move( moveFrom.m_PutOverflowFunc );
m_Byteswap = Move( moveFrom.m_Byteswap );
return *this;
}
#endif
//-----------------------------------------------------------------------------
// Modifies the buffer to be binary or text; Blows away the buffer and the CONTAINS_CRLF value.
//-----------------------------------------------------------------------------
@@ -303,7 +401,7 @@ void CUtlBuffer::SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, i
m_nOffset = 0;
m_Flags = nFlags;
m_nMaxPut = -1;
AddNullTermination();
AddNullTermination( m_Put );
}
//-----------------------------------------------------------------------------
@@ -321,9 +419,25 @@ void CUtlBuffer::AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nF
m_nOffset = 0;
m_Flags = nFlags;
m_nMaxPut = -1;
AddNullTermination();
AddNullTermination( m_Put );
}
//-----------------------------------------------------------------------------
// Allows the caller to control memory
//-----------------------------------------------------------------------------
void* CUtlBuffer::DetachMemory()
{
// Reset all indices; we just changed memory
m_Get = 0;
m_Put = 0;
m_nTab = 0;
m_Error = 0;
m_nOffset = 0;
return m_Memory.DetachMemory( );
}
//-----------------------------------------------------------------------------
// Makes sure we've got at least this much memory
//-----------------------------------------------------------------------------
@@ -351,16 +465,15 @@ void CUtlBuffer::EnsureCapacity( int num )
//-----------------------------------------------------------------------------
// Base get method from which all others derive
//-----------------------------------------------------------------------------
void CUtlBuffer::Get( void* pMem, int size )
bool CUtlBuffer::Get( void* pMem, int size )
{
if ( size > 0 && CheckGet( size ) )
{
int Index = m_Get - m_nOffset;
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + size - 1 ) );
memcpy( pMem, &m_Memory[ Index ], size );
memcpy( pMem, &m_Memory[m_Get - m_nOffset], size );
m_Get += size;
return true;
}
return false;
}
@@ -372,10 +485,7 @@ int CUtlBuffer::GetUpTo( void *pMem, int nSize )
{
if ( CheckArbitraryPeekGet( 0, nSize ) )
{
int Index = m_Get - m_nOffset;
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + nSize - 1 ) );
memcpy( pMem, &m_Memory[ Index ], nSize );
memcpy( pMem, &m_Memory[m_Get - m_nOffset], nSize );
m_Get += nSize;
return nSize;
}
@@ -392,7 +502,7 @@ void CUtlBuffer::EatWhiteSpace()
{
while ( CheckGet( sizeof(char) ) )
{
if ( !isspace( *(const unsigned char*)PeekGet() ) )
if ( !V_isspace( *(const unsigned char*)PeekGet() ) )
break;
m_Get += sizeof(char);
}
@@ -437,7 +547,7 @@ int CUtlBuffer::PeekWhiteSpace( int nOffset )
while ( CheckPeekGet( nOffset, sizeof(char) ) )
{
if ( !isspace( *(unsigned char*)PeekGet( nOffset ) ) )
if ( !V_isspace( *(unsigned char*)PeekGet( nOffset ) ) )
break;
nOffset += sizeof(char);
}
@@ -491,7 +601,7 @@ int CUtlBuffer::PeekStringLength()
for ( int i = 0; i < nPeekAmount; ++i )
{
// The +1 here is so we eat the terminating 0
if ( isspace((unsigned char)pTest[i]) || (pTest[i] == 0) )
if ( V_isspace((unsigned char)pTest[i]) || (pTest[i] == 0) )
return (i + nOffset - nStartingOffset + 1);
}
}
@@ -550,7 +660,7 @@ bool CUtlBuffer::PeekStringMatch( int nOffset, const char *pString, int nLen )
{
if ( !CheckPeekGet( nOffset, nLen ) )
return false;
return !Q_strncmp( (const char*)PeekGet(nOffset), pString, nLen );
return !V_strncmp( (const char*)PeekGet(nOffset), pString, nLen );
}
@@ -607,19 +717,16 @@ int CUtlBuffer::PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActu
//-----------------------------------------------------------------------------
// Reads a null-terminated string
//-----------------------------------------------------------------------------
void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars )
void CUtlBuffer::GetString( char* pString, int nMaxChars )
{
if ( !IsValid() )
if (!IsValid())
{
*pString = 0;
return;
}
// This can legitimately be zero if we were told that the buffer is zero length, and
// we're asking to duplicate the buffer, so let that pass, too.
Assert( maxLenInChars != 0 || PeekStringLength() == 0 );
if ( maxLenInChars == 0 )
Assert( nMaxChars > 0 );
if ( nMaxChars <= 0 )
{
return;
}
@@ -640,14 +747,14 @@ void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars )
return;
}
const size_t nCharsToRead = min( (size_t)nLen, maxLenInChars ) - 1;
const int nCharsToRead = Min( nLen, nMaxChars ) - 1;
Get( pString, nCharsToRead );
pString[nCharsToRead] = 0;
pString[ nCharsToRead ] = 0;
if ( (size_t)nLen > (nCharsToRead + 1) )
if ( nLen > ( nCharsToRead + 1 ) )
{
SeekGet( SEEK_CURRENT, nLen - (nCharsToRead + 1) );
SeekGet( SEEK_CURRENT, nLen - ( nCharsToRead + 1 ) );
}
// Read the terminating NULL in binary formats
@@ -663,7 +770,7 @@ void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars )
//-----------------------------------------------------------------------------
void CUtlBuffer::GetLine( char* pLine, int nMaxChars )
{
Assert( IsText() && !ContainsCRLF() );
//Assert( IsText() && !ContainsCRLF() );
if ( !IsValid() )
{
@@ -732,7 +839,7 @@ void CUtlBuffer::GetDelimitedString( CUtlCharConversion *pConv, char *pString, i
{
if ( !IsText() || !pConv )
{
GetStringInternal( pString, nMaxChars );
GetString( pString, nMaxChars );
return;
}
@@ -858,11 +965,7 @@ const void* CUtlBuffer::PeekGet( int nMaxSize, int nOffset )
{
if ( !CheckPeekGet( nOffset, nMaxSize ) )
return NULL;
int Index = m_Get + nOffset - m_nOffset;
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + nMaxSize - 1 ) );
return &m_Memory[ Index ];
return &m_Memory[ m_Get + nOffset - m_nOffset ];
}
@@ -914,10 +1017,8 @@ int CUtlBuffer::VaScanf( const char* pFmt, va_list list )
return 0;
int numScanned = 0;
int nLength;
char c;
char* pEnd;
while ( (c = *pFmt++) )
while ( c = *pFmt++ )
{
// Stop if we hit the end of the buffer
if ( m_Get >= TellMaxPut() )
@@ -956,93 +1057,105 @@ int CUtlBuffer::VaScanf( const char* pFmt, va_list list )
return numScanned;
}
}
break;
break;
case 'h':
{
if ( *pFmt == 'd' || *pFmt == 'i' )
{
if ( !GetTypeText( *va_arg( list, int16 * ) ) )
return numScanned; // only support short ints, don't bother with hex
}
else if ( *pFmt == 'u' )
{
if ( !GetTypeText( *va_arg( list, uint16 * ) ) )
return numScanned;
}
else
return numScanned;
++pFmt;
}
break;
case 'I':
{
if ( *pFmt++ != '6' || *pFmt++ != '4' )
return numScanned; // only support "I64d" and "I64u"
if ( *pFmt == 'd' )
{
if ( !GetTypeText( *va_arg( list, int64 * ) ) )
return numScanned;
}
else if ( *pFmt == 'u' )
{
if ( !GetTypeText( *va_arg( list, uint64 * ) ) )
return numScanned;
}
else
{
return numScanned;
}
++pFmt;
}
break;
case 'i':
case 'd':
{
int* i = va_arg( list, int * );
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
nLength = 128;
if ( !CheckArbitraryPeekGet( 0, nLength ) )
{
*i = 0;
int32 *pArg = va_arg( list, int32 * );
if ( !GetTypeText( *pArg ) )
return numScanned;
}
*i = strtol( (char*)PeekGet(), &pEnd, 10 );
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
if ( nBytesRead == 0 )
return numScanned;
m_Get += nBytesRead;
}
break;
case 'x':
{
int* i = va_arg( list, int * );
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
nLength = 128;
if ( !CheckArbitraryPeekGet( 0, nLength ) )
{
*i = 0;
uint32 *pArg = va_arg( list, uint32 * );
if ( !GetTypeText( *pArg, 16 ) )
return numScanned;
}
*i = strtol( (char*)PeekGet(), &pEnd, 16 );
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
if ( nBytesRead == 0 )
return numScanned;
m_Get += nBytesRead;
}
break;
case 'u':
{
unsigned int* u = va_arg( list, unsigned int *);
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
nLength = 128;
if ( !CheckArbitraryPeekGet( 0, nLength ) )
{
*u = 0;
uint32 *pArg = va_arg( list, uint32 * );
if ( !GetTypeText( *pArg ) )
return numScanned;
}
*u = strtoul( (char*)PeekGet(), &pEnd, 10 );
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
if ( nBytesRead == 0 )
return numScanned;
m_Get += nBytesRead;
}
break;
case 'l':
{
// we currently support %lf and %lld
if ( *pFmt == 'f' )
{
if ( !GetTypeText( *va_arg( list, double * ) ) )
return numScanned;
}
else if ( *pFmt == 'l' && *++pFmt == 'd' )
{
if ( !GetTypeText( *va_arg( list, int64 * ) ) )
return numScanned;
}
else
return numScanned;
}
break;
case 'f':
{
float* f = va_arg( list, float *);
// NOTE: This is not bullet-proof; it assumes numbers are < 128 characters
nLength = 128;
if ( !CheckArbitraryPeekGet( 0, nLength ) )
{
*f = 0.0f;
float *pArg = va_arg( list, float * );
if ( !GetTypeText( *pArg ) )
return numScanned;
}
*f = (float)strtod( (char*)PeekGet(), &pEnd );
int nBytesRead = (int)( pEnd - (char*)PeekGet() );
if ( nBytesRead == 0 )
return numScanned;
m_Get += nBytesRead;
}
break;
case 's':
{
char* s = va_arg( list, char * );
GetStringInternal( s, 256 );
GetString( s, 64 ); // [SECURITY EXPLOIT: Scanf %s should be deprecated as malicious data can overrun stack buffers! Here we'd assume that at least 64 bytes are available on the stack, and even if not this shouldn't give attracker much room for code execution]
}
break;
@@ -1099,38 +1212,55 @@ bool CUtlBuffer::GetToken( const char *pToken )
Assert( pToken );
// Look for the token
int nLen = Q_strlen( pToken );
int nLen = V_strlen( pToken );
int nSizeToCheck = Size() - TellGet() - m_nOffset;
// First time through on streaming, check what we already have loaded
// if we have enough loaded to do the check
int nMaxSize = Size() - ( TellGet() - m_nOffset );
if ( nMaxSize <= nLen )
{
nMaxSize = Size();
}
int nSizeRemaining = TellMaxPut() - TellGet();
int nGet = TellGet();
do
while ( nSizeRemaining >= nLen )
{
int nMaxSize = TellMaxPut() - TellGet();
if ( nMaxSize < nSizeToCheck )
{
nSizeToCheck = nMaxSize;
}
if ( nLen > nSizeToCheck )
break;
bool bOverFlow = ( nSizeRemaining > nMaxSize );
int nSizeToCheck = bOverFlow ? nMaxSize : nSizeRemaining;
if ( !CheckPeekGet( 0, nSizeToCheck ) )
break;
const char *pBufStart = (const char*)PeekGet();
const char *pFoundEnd = Q_strnistr( pBufStart, pToken, nSizeToCheck );
if ( pFoundEnd )
const char *pFoundEnd = V_strnistr( pBufStart, pToken, nSizeToCheck );
// Time to be careful: if we are in a state of overflow
// (namely, there's more of the buffer beyond the current window)
// we could be looking for 'foo' for example, and find 'foobar'
// if 'foo' happens to be the last 3 characters of the current window
size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart;
bool bPotentialMismatch = ( bOverFlow && ( (int)nOffset == Size() - nLen ) );
if ( !pFoundEnd || bPotentialMismatch )
{
size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart;
SeekGet( CUtlBuffer::SEEK_CURRENT, nOffset + nLen );
return true;
nSizeRemaining -= nSizeToCheck;
if ( !pFoundEnd && ( nSizeRemaining < nLen ) )
break;
// Second time through, stream as much in as possible
// But keep the last portion of the current buffer
// since we couldn't check it against stuff outside the window
nSizeRemaining += nLen;
nMaxSize = Size();
SeekGet( CUtlBuffer::SEEK_CURRENT, nSizeToCheck - nLen );
continue;
}
SeekGet( CUtlBuffer::SEEK_CURRENT, nSizeToCheck - nLen - 1 );
nSizeToCheck = Size() - (nLen-1);
} while ( true );
// Seek past the end of the found string
SeekGet( CUtlBuffer::SEEK_CURRENT, (int)( nOffset + nLen ) );
return true;
}
// Didn't find a match, leave the get index where it was to start with
SeekGet( CUtlBuffer::SEEK_HEAD, nGet );
return false;
}
@@ -1161,7 +1291,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
// Ending delimiter is not
Assert( pEndingDelim && pEndingDelim[0] );
nEndingDelimLen = Q_strlen( pEndingDelim );
nEndingDelimLen = V_strlen( pEndingDelim );
int nStartGet = TellGet();
char nCurrChar;
@@ -1170,7 +1300,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
while ( *pStartingDelim )
{
nCurrChar = *pStartingDelim++;
if ( !isspace((unsigned char)nCurrChar) )
if ( !V_isspace((unsigned char)nCurrChar) )
{
if ( tolower( GetChar() ) != tolower( nCurrChar ) )
goto parseFailed;
@@ -1187,7 +1317,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
goto parseFailed;
nCurrentGet = TellGet();
nCharsToCopy = (nCurrentGet - nEndingDelimLen) - nTokenStart;
nCharsToCopy = (int)( (nCurrentGet - nEndingDelimLen) - nTokenStart );
if ( nCharsToCopy >= nMaxLen )
{
nCharsToCopy = nMaxLen - 1;
@@ -1203,7 +1333,7 @@ bool CUtlBuffer::ParseToken( const char *pStartingDelim, const char *pEndingDeli
// Eat trailing whitespace
for ( ; nCharsToCopy > 0; --nCharsToCopy )
{
if ( !isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) )
if ( !V_isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) )
break;
}
}
@@ -1319,15 +1449,10 @@ void CUtlBuffer::Put( const void *pMem, int size )
{
if ( size && CheckPut( size ) )
{
int Index = m_Put - m_nOffset;
Assert( m_Memory.IsIdxValid( Index ) && m_Memory.IsIdxValid( Index + size - 1 ) );
if( Index >= 0 )
{
memcpy( &m_Memory[ Index ], pMem, size );
m_Put += size;
memcpy( &m_Memory[m_Put - m_nOffset], pMem, size );
m_Put += size;
AddNullTermination();
}
AddNullTermination( m_Put );
}
}
@@ -1342,7 +1467,7 @@ void CUtlBuffer::PutString( const char* pString )
if ( pString )
{
// Not text? append a null at the end.
size_t nLen = Q_strlen( pString ) + 1;
int nLen = (int)V_strlen( pString ) + 1;
Put( pString, nLen * sizeof(char) );
return;
}
@@ -1365,7 +1490,7 @@ void CUtlBuffer::PutString( const char* pString )
while ( pEndl )
{
size_t nSize = (size_t)pEndl - (size_t)pString + sizeof(char);
Put( pString, nSize );
Put( pString, (int)nSize );
pString = pEndl + 1;
if ( *pString )
{
@@ -1378,7 +1503,7 @@ void CUtlBuffer::PutString( const char* pString )
}
}
}
size_t nLen = Q_strlen( pString );
int nLen = (int)V_strlen( pString );
if ( nLen )
{
Put( pString, nLen * sizeof(char) );
@@ -1430,7 +1555,7 @@ void CUtlBuffer::PutDelimitedString( CUtlCharConversion *pConv, const char *pStr
}
Put( pConv->GetDelimiter(), pConv->GetDelimiterLength() );
int nLen = pString ? Q_strlen( pString ) : 0;
int nLen = pString ? V_strlen( pString ) : 0;
for ( int i = 0; i < nLen; ++i )
{
PutDelimitedCharInternal( pConv, pString[i] );
@@ -1446,12 +1571,9 @@ void CUtlBuffer::PutDelimitedString( CUtlCharConversion *pConv, const char *pStr
void CUtlBuffer::VaPrintf( const char* pFmt, va_list list )
{
char temp[2048];
#ifdef DBGFLAG_ASSERT
int nLen =
#endif
Q_vsnprintf( temp, sizeof( temp ), pFmt, list );
Assert( nLen < 2048 );
char temp[8192];
int nLen = V_vsnprintf( temp, sizeof( temp ), pFmt, list );
ErrorIfNot( nLen < sizeof( temp ), ( "CUtlBuffer::VaPrintf: String overflowed buffer [%d]\n", sizeof( temp ) ) );
PutString( temp );
}
@@ -1563,7 +1685,7 @@ void CUtlBuffer::SeekPut( SeekType_t type, int offset )
OnPutOverflow( -nNextPut-1 );
m_Put = nNextPut;
AddNullTermination();
AddNullTermination( m_Put );
}
@@ -1585,8 +1707,10 @@ bool CUtlBuffer::IsBigEndian( void )
//-----------------------------------------------------------------------------
// null terminate the buffer
// NOTE: Pass in nPut here even though it is just a copy of m_Put. This is almost always called immediately
// after modifying m_Put and this lets it stay in a register and avoid LHS on PPC.
//-----------------------------------------------------------------------------
void CUtlBuffer::AddNullTermination( void )
void CUtlBuffer::AddNullTermination( )
{
if ( m_Put > m_nMaxPut )
{
@@ -1595,12 +1719,7 @@ void CUtlBuffer::AddNullTermination( void )
// Add null termination value
if ( CheckPut( 1 ) )
{
int Index = m_Put - m_nOffset;
Assert( m_Memory.IsIdxValid( Index ) );
if( Index >= 0 )
{
m_Memory[ Index ] = 0;
}
m_Memory[m_Put - m_nOffset] = 0;
}
else
{
@@ -1613,6 +1732,29 @@ void CUtlBuffer::AddNullTermination( void )
}
void CUtlBuffer::AddNullTermination( int nPut )
{
if ( nPut > m_nMaxPut )
{
if ( !IsReadOnly() && ((m_Error & PUT_OVERFLOW) == 0) )
{
// Add null termination value
if ( CheckPut( 1 ) )
{
m_Memory[nPut - m_nOffset] = 0;
}
else
{
// Restore the overflow state, it was valid before...
m_Error &= ~PUT_OVERFLOW;
}
}
m_nMaxPut = nPut;
}
}
//-----------------------------------------------------------------------------
// Converts a buffer from a CRLF buffer to a CR buffer (and back)
// Returns false if no conversion was necessary (and outBuf is left untouched)
@@ -1640,21 +1782,21 @@ bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf )
int nPutDelta = 0;
const char *pBase = (const char*)Base();
int nCurrGet = 0;
intp nCurrGet = 0;
while ( nCurrGet < nInCount )
{
const char *pCurr = &pBase[nCurrGet];
if ( bFromCRLF )
{
const char *pNext = Q_strnistr( pCurr, "\r\n", nInCount - nCurrGet );
const char *pNext = V_strnistr( pCurr, "\r\n", nInCount - nCurrGet );
if ( !pNext )
{
outBuf.Put( pCurr, nInCount - nCurrGet );
break;
}
int nBytes = (size_t)pNext - (size_t)pCurr;
outBuf.Put( pCurr, nBytes );
intp nBytes = (intp)pNext - (intp)pCurr;
outBuf.Put( pCurr, (int)nBytes );
outBuf.PutChar( '\n' );
nCurrGet += nBytes + 2;
if ( nGet >= nCurrGet - 1 )
@@ -1668,15 +1810,15 @@ bool CUtlBuffer::ConvertCRLF( CUtlBuffer &outBuf )
}
else
{
const char *pNext = Q_strnchr( pCurr, '\n', nInCount - nCurrGet );
const char *pNext = V_strnchr( pCurr, '\n', nInCount - nCurrGet );
if ( !pNext )
{
outBuf.Put( pCurr, nInCount - nCurrGet );
break;
}
int nBytes = (size_t)pNext - (size_t)pCurr;
outBuf.Put( pCurr, nBytes );
intp nBytes = (intp)pNext - (intp)pCurr;
outBuf.Put( pCurr, (int)nBytes );
outBuf.PutChar( '\r' );
outBuf.PutChar( '\n' );
nCurrGet += nBytes + 1;
@@ -1793,4 +1935,3 @@ char * CUtlInplaceBuffer::InplaceGetLinePtr( void )
return pszLine;
}
+170 -83
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a symbol table
//
@@ -9,29 +9,11 @@
#pragma warning (disable:4514)
#include "utlsymbol.h"
#include "KeyValues.h"
#include "tier0/threadtools.h"
#include "tier0/memdbgon.h"
#include "stringpool.h"
#include "utlhashtable.h"
#include "utlstring.h"
// Ensure that everybody has the right compiler version installed. The version
// number can be obtained by looking at the compiler output when you type 'cl'
// and removing the last two digits and the periods: 16.00.40219.01 becomes 160040219
#ifdef _MSC_FULL_VER
#if _MSC_FULL_VER > 160000000
// VS 2010
#if _MSC_FULL_VER < 160040219
#error You must install VS 2010 SP1
#endif
#else
// VS 2005
#if _MSC_FULL_VER < 140050727
#error You must install VS 2005 SP1
#endif
#endif
#endif
#include "generichash.h"
#include "tier0/vprof.h"
#include <stddef.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@@ -68,6 +50,17 @@ void CUtlSymbol::Initialize()
}
}
void CUtlSymbol::LockTableForRead()
{
Initialize();
s_pSymbolTable->LockForRead();
}
void CUtlSymbol::UnlockTableForRead()
{
s_pSymbolTable->UnlockForRead();
}
//-----------------------------------------------------------------------------
// Purpose: Singleton to delete table on exit from module
//-----------------------------------------------------------------------------
@@ -104,6 +97,11 @@ const char* CUtlSymbol::String( ) const
return CurrTable()->String(m_Id);
}
const char* CUtlSymbol::StringNoLock( ) const
{
return CurrTable()->StringNoLock(m_Id);
}
void CUtlSymbol::DisableStaticSymbolTable()
{
s_bAllowStaticSymbolTable = false;
@@ -125,16 +123,25 @@ bool CUtlSymbol::operator==( const char* pStr ) const
//-----------------------------------------------------------------------------
// symbol table stuff
//-----------------------------------------------------------------------------
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
inline const char* CUtlSymbolTable::DecoratedStringFromIndex( const CStringPoolIndex &index ) const
{
Assert( index.m_iPool < m_StringPools.Count() );
Assert( index.m_iOffset < m_StringPools[index.m_iPool]->m_TotalLen );
return &m_StringPools[index.m_iPool]->m_Data[index.m_iOffset];
// step over the hash decorating the beginning of the string
return (&m_StringPools[index.m_iPool]->m_Data[index.m_iOffset]);
}
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
{
// step over the hash decorating the beginning of the string
return DecoratedStringFromIndex(index)+sizeof(hashDecoration_t);
}
// The first two bytes of each string in the pool are actually the hash for that string.
// Thus we compare hashes rather than entire strings for a significant perf benefit.
// However since there is a high rate of hash collision we must still compare strings
// if the hashes match.
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
{
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
@@ -142,21 +149,79 @@ bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStri
// right now at least, because m_LessFunc is the first member of CUtlRBTree, and m_Lookup
// is the first member of CUtlSymbolTabke, this == pTable
CUtlSymbolTable *pTable = (CUtlSymbolTable *)( (byte *)this - offsetof(CUtlSymbolTable::CTree, m_LessFunc) ) - offsetof(CUtlSymbolTable, m_Lookup );
#if 1 // using the hashes
const char *str1, *str2;
hashDecoration_t hash1, hash2;
if (i1 == INVALID_STRING_INDEX)
{
str1 = pTable->m_pUserSearchString;
hash1 = pTable->m_nUserSearchStringHash;
}
else
{
str1 = pTable->DecoratedStringFromIndex( i1 );
hashDecoration_t storedHash = *reinterpret_cast<const hashDecoration_t *>(str1);
str1 += sizeof(hashDecoration_t);
AssertMsg2( storedHash == ( !pTable->m_bInsensitive ? HashString(str1) : HashStringCaseless(str1) ),
"The stored hash (%d) for symbol %s is not correct.", storedHash, str1 );
hash1 = storedHash;
}
if (i2 == INVALID_STRING_INDEX)
{
str2 = pTable->m_pUserSearchString;
hash2 = pTable->m_nUserSearchStringHash;
}
else
{
str2 = pTable->DecoratedStringFromIndex( i2 );
hashDecoration_t storedHash = *reinterpret_cast<const hashDecoration_t *>(str2);
str2 += sizeof(hashDecoration_t);
AssertMsg2( storedHash == ( !pTable->m_bInsensitive ? HashString(str2) : HashStringCaseless(str2) ),
"The stored hash (%d) for symbol '%s' is not correct.", storedHash, str2 );
hash2 = storedHash;
}
// compare the hashes
if ( hash1 == hash2 )
{
if ( !str1 && str2 )
return 1;
if ( !str2 && str1 )
return -1;
if ( !str1 && !str2 )
return 0;
// if the hashes match compare the strings
if ( !pTable->m_bInsensitive )
return strcmp( str1, str2 ) < 0;
else
return V_stricmp( str1, str2 ) < 0;
}
else
{
return hash1 < hash2;
}
#else // not using the hashes, just comparing strings
const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i1 );
pTable->StringFromIndex( i1 );
const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i2 );
pTable->StringFromIndex( i2 );
if ( !str1 && str2 )
return false;
return 1;
if ( !str2 && str1 )
return true;
return -1;
if ( !str1 && !str2 )
return false;
return 0;
if ( !pTable->m_bInsensitive )
return V_strcmp( str1, str2 ) < 0;
return strcmp( str1, str2 ) < 0;
else
return V_stricmp( str1, str2 ) < 0;
return strcmpi( str1, str2 ) < 0;
#endif
}
@@ -177,11 +242,13 @@ CUtlSymbolTable::~CUtlSymbolTable()
CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
{
VPROF( "CUtlSymbol::Find" );
if (!pString)
return CUtlSymbol();
// Store a special context used to help with insertion
m_pUserSearchString = pString;
m_nUserSearchStringHash = m_bInsensitive ? HashStringCaseless(pString) : HashString(pString) ;
// Passing this special invalid symbol makes the comparison function
// use the string passed in the context
@@ -189,6 +256,7 @@ CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
#ifdef _DEBUG
m_pUserSearchString = NULL;
m_nUserSearchStringHash = 0;
#endif
return CUtlSymbol( idx );
@@ -217,6 +285,7 @@ int CUtlSymbolTable::FindPoolWithSpace( int len ) const
CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
{
VPROF("CUtlSymbol::AddString");
if (!pString)
return CUtlSymbol( UTL_INVAL_SYMBOL );
@@ -225,35 +294,47 @@ CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
if (id.IsValid())
return id;
int len = V_strlen(pString) + 1;
int lenString = strlen(pString) + 1; // length of just the string
int lenDecorated = lenString + sizeof(hashDecoration_t); // and with its hash decoration
// make sure that all strings are aligned on 2-byte boundaries so the hashes will read correctly
COMPILE_TIME_ASSERT(sizeof(hashDecoration_t) == 2);
lenDecorated = (lenDecorated + 1) & (~0x01); // round up to nearest multiple of 2
// Find a pool with space for this string, or allocate a new one.
int iPool = FindPoolWithSpace( len );
int iPool = FindPoolWithSpace( lenDecorated );
if ( iPool == -1 )
{
// Add a new pool.
int newPoolSize = max( len, MIN_STRING_POOL_SIZE );
StringPool_t *pPool = (StringPool_t*)malloc( sizeof( StringPool_t ) + newPoolSize - 1 );
pPool->m_TotalLen = newPoolSize;
int newPoolSize = MAX( lenDecorated + sizeof( StringPool_t ), MIN_STRING_POOL_SIZE );
StringPool_t *pPool = (StringPool_t*)malloc( newPoolSize );
pPool->m_TotalLen = newPoolSize - sizeof( StringPool_t );
pPool->m_SpaceUsed = 0;
iPool = m_StringPools.AddToTail( pPool );
}
// Compute a hash
hashDecoration_t hash = m_bInsensitive ? HashStringCaseless(pString) : HashString(pString) ;
// Copy the string in.
StringPool_t *pPool = m_StringPools[iPool];
Assert( pPool->m_SpaceUsed < 0xFFFF ); // This should never happen, because if we had a string > 64k, it
// would have been given its entire own pool.
unsigned short iStringOffset = pPool->m_SpaceUsed;
const char *startingAddr = &pPool->m_Data[pPool->m_SpaceUsed];
memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
pPool->m_SpaceUsed += len;
// store the hash at the head of the string
*((hashDecoration_t *)(startingAddr)) = hash;
// and then the string's data
memcpy( (void *)(startingAddr + sizeof(hashDecoration_t)), pString, lenString );
pPool->m_SpaceUsed += lenDecorated;
// didn't find, insert the string into the vector.
// insert the string into the vector.
CStringPoolIndex index;
index.m_iPool = iPool;
index.m_iOffset = iStringOffset;
MEM_ALLOC_CREDIT();
UtlSymId_t idx = m_Lookup.Insert( index );
return CUtlSymbol( idx );
}
@@ -288,22 +369,6 @@ void CUtlSymbolTable::RemoveAll()
}
class CUtlFilenameSymbolTable::HashTable : public CUtlStableHashtable<CUtlConstString>
{
};
CUtlFilenameSymbolTable::CUtlFilenameSymbolTable()
{
m_Strings = new HashTable;
}
CUtlFilenameSymbolTable::~CUtlFilenameSymbolTable()
{
delete m_Strings;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pFileName -
@@ -328,7 +393,7 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileNa
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
strlwr( fn );
#endif
// Split the filename into constituent parts
@@ -340,20 +405,18 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileNa
// not found, lock and look again
FileNameHandleInternal_t handle;
m_lock.LockForWrite();
handle.path = m_Strings->Insert( basepath ) + 1;
handle.file = m_Strings->Insert( filename ) + 1;
//handle.path = m_StringPool.FindStringHandle( basepath );
//handle.file = m_StringPool.FindStringHandle( filename );
//if ( handle.path != m_Strings.InvalidHandle() && handle.file )
//{
handle.SetPath( m_PathStringPool.FindStringHandle( basepath ) );
handle.SetFile( m_FileStringPool.FindStringHandle( filename ) );
if ( handle.GetPath() && handle.GetFile() )
{
// found
// m_lock.UnlockWrite();
// return *( FileNameHandle_t * )( &handle );
//}
m_lock.UnlockWrite();
return *( FileNameHandle_t * )( &handle );
}
// safely add it
//handle.path = m_StringPool.ReferenceStringHandle( basepath );
//handle.file = m_StringPool.ReferenceStringHandle( filename );
handle.SetPath( m_PathStringPool.ReferenceStringHandle( basepath ) );
handle.SetFile( m_FileStringPool.ReferenceStringHandle( filename ) );
m_lock.UnlockWrite();
return *( FileNameHandle_t * )( &handle );
@@ -371,7 +434,7 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
strlwr( fn );
#endif
// Split the filename into constituent parts
@@ -382,16 +445,13 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
FileNameHandleInternal_t handle;
Assert( (uint16)(m_Strings->InvalidHandle() + 1) == 0 );
m_lock.LockForRead();
handle.path = m_Strings->Find(basepath) + 1;
handle.file = m_Strings->Find(filename) + 1;
//handle.path = m_StringPool.FindStringHandle(basepath);
//handle.file = m_StringPool.FindStringHandle(filename);
handle.SetPath( m_PathStringPool.FindStringHandle( basepath ) );
handle.SetFile( m_FileStringPool.FindStringHandle( filename ) );
m_lock.UnlockRead();
if ( handle.path == 0 || handle.file == 0 )
if ( ( handle.GetPath() == 0 ) || ( handle.GetFile() == 0 ) )
return NULL;
return *( FileNameHandle_t * )( &handle );
@@ -406,17 +466,15 @@ bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf,
{
buf[ 0 ] = 0;
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
if ( !internal || !internal->file || !internal->path )
FileNameHandleInternal_t *internalFileHandle = ( FileNameHandleInternal_t * )&handle;
if ( !internalFileHandle )
{
return false;
}
m_lock.LockForRead();
//const char *path = m_StringPool.HandleToString(internal->path);
//const char *fn = m_StringPool.HandleToString(internal->file);
const char *path = (*m_Strings)[ internal->path - 1 ].Get();
const char *fn = (*m_Strings)[ internal->file - 1].Get();
const char *path = m_PathStringPool.HandleToString( internalFileHandle->GetPath() );
const char *fn = m_FileStringPool.HandleToString( internalFileHandle->GetFile() );
m_lock.UnlockRead();
if ( !path || !fn )
@@ -432,5 +490,34 @@ bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf,
void CUtlFilenameSymbolTable::RemoveAll()
{
m_Strings->Purge();
m_PathStringPool.FreeAll();
m_FileStringPool.FreeAll();
}
void CUtlFilenameSymbolTable::SpewStrings()
{
m_lock.LockForRead();
m_PathStringPool.SpewStrings();
m_FileStringPool.SpewStrings();
m_lock.UnlockRead();
}
bool CUtlFilenameSymbolTable::SaveToBuffer( CUtlBuffer &buffer )
{
m_lock.LockForRead();
bool bResult = m_PathStringPool.SaveToBuffer( buffer );
bResult = bResult && m_FileStringPool.SaveToBuffer( buffer );
m_lock.UnlockRead();
return bResult;
}
bool CUtlFilenameSymbolTable::RestoreFromBuffer( CUtlBuffer &buffer )
{
m_lock.LockForWrite();
bool bResult = m_PathStringPool.RestoreFromBuffer( buffer );
bResult = bResult && m_FileStringPool.RestoreFromBuffer( buffer );
m_lock.UnlockWrite();
return bResult;
}