Fix line endings. WHAMMY.

This commit is contained in:
Jørgen P. Tjernø
2013-12-02 19:31:46 -08:00
parent c47ad60970
commit f56bb35301
6719 changed files with 2805089 additions and 2805089 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,326 +1,326 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// NetAdr.cpp: implementation of the CNetAdr class.
//
//===========================================================================//
#if defined( _WIN32 ) && !defined( _X360 )
#include <windows.h>
#endif
#include "tier0/dbg.h"
#include "netadr.h"
#include "tier1/strtools.h"
#if defined( _WIN32 ) && !defined( _X360 )
#define WIN32_LEAN_AND_MEAN
#include <winsock.h>
typedef int socklen_t;
#elif !defined( _X360 )
#include <netinet/in.h> // ntohs()
#include <netdb.h> // gethostbyname()
#include <sys/socket.h> // getsockname()
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
bool netadr_t::CompareAdr (const netadr_t &a, bool onlyBase) const
{
if ( a.type != type )
return false;
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_BROADCAST )
return true;
if ( type == NA_IP )
{
if ( !onlyBase && (port != a.port) )
return false;
if ( a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3] )
return true;
}
return false;
}
bool netadr_t::CompareClassBAdr (const netadr_t &a) const
{
if ( a.type != type )
return false;
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_IP )
{
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] )
return true;
}
return false;
}
bool netadr_t::CompareClassCAdr (const netadr_t &a) const
{
if ( a.type != type )
return false;
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_IP )
{
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] )
return true;
}
return false;
}
// reserved addresses are not routeable, so they can all be used in a LAN game
bool netadr_t::IsReservedAdr () const
{
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_IP )
{
if ( (ip[0] == 10) || // 10.x.x.x is reserved
(ip[0] == 127) || // 127.x.x.x
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x
(ip[0] == 192 && ip[1] >= 168) ) // 192.168.x.x
return true;
}
return false;
}
const char * netadr_t::ToString(bool baseOnly) const
{
static char s[64];
Q_strncpy (s, "unknown", sizeof( s ) );
if (type == NA_LOOPBACK)
{
Q_strncpy (s, "loopback", sizeof( s ) );
}
else if (type == NA_BROADCAST)
{
Q_strncpy (s, "broadcast", sizeof( s ) );
}
else if (type == NA_IP)
{
if ( baseOnly)
{
Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]);
}
else
{
Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port));
}
}
return s;
}
bool netadr_t::IsLocalhost() const
{
// are we 127.0.0.1 ?
return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1);
}
bool netadr_t::IsLoopback() const
{
// are we useding engine loopback buffers
return type == NA_LOOPBACK;
}
void netadr_t::Clear()
{
ip[0] = ip[1] = ip[2] = ip[3] = 0;
port = 0;
type = NA_NULL;
}
void netadr_t::SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4)
{
ip[0] = b1;
ip[1] = b2;
ip[2] = b3;
ip[3] = b4;
}
void netadr_t::SetIP(uint unIP)
{
*((uint*)ip) = BigLong( unIP );
}
void netadr_t::SetType(netadrtype_t newtype)
{
type = newtype;
}
netadrtype_t netadr_t::GetType() const
{
return type;
}
unsigned short netadr_t::GetPort() const
{
return BigShort( port );
}
unsigned int netadr_t::GetIPNetworkByteOrder() const
{
return *(unsigned int *)&ip;
}
unsigned int netadr_t::GetIPHostByteOrder() const
{
return ntohl( GetIPNetworkByteOrder() );
}
void netadr_t::ToSockadr (struct sockaddr * s) const
{
Q_memset ( s, 0, sizeof(struct sockaddr));
if (type == NA_BROADCAST)
{
((struct sockaddr_in*)s)->sin_family = AF_INET;
((struct sockaddr_in*)s)->sin_port = port;
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST;
}
else if (type == NA_IP)
{
((struct sockaddr_in*)s)->sin_family = AF_INET;
((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&ip;
((struct sockaddr_in*)s)->sin_port = port;
}
else if (type == NA_LOOPBACK )
{
((struct sockaddr_in*)s)->sin_family = AF_INET;
((struct sockaddr_in*)s)->sin_port = port;
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK ;
}
}
bool netadr_t::SetFromSockadr(const struct sockaddr * s)
{
if (s->sa_family == AF_INET)
{
type = NA_IP;
*(int *)&ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
port = ((struct sockaddr_in *)s)->sin_port;
return true;
}
else
{
Clear();
return false;
}
}
bool netadr_t::IsValid() const
{
return ( (port !=0 ) && (type != NA_NULL) &&
( ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0 ) );
}
#ifdef _WIN32
#undef SetPort // get around stupid WINSPOOL.H macro
#endif
void netadr_t::SetPort(unsigned short newport)
{
port = BigShort( newport );
}
void netadr_t::SetFromString( const char *pch, bool bUseDNS )
{
Clear();
type = NA_IP;
Assert( pch ); // invalid to call this with NULL pointer; fix your code bug!
if ( !pch ) // but let's not crash
return;
if ( pch[0] >= '0' && pch[0] <= '9' && strchr( pch, '.' ) )
{
int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0;
int nRes = sscanf( pch, "%d.%d.%d.%d:%d", &n1, &n2, &n3, &n4, &n5 );
if ( nRes >= 4 )
{
SetIP( n1, n2, n3, n4 );
}
if ( nRes == 5 )
{
SetPort( ( uint16 ) n5 );
}
}
else if ( bUseDNS )
{
// X360TBD:
#if !defined( _X360 )
char szHostName[ 256 ];
Q_strncpy( szHostName, pch, sizeof(szHostName) );
char *pchColon = strchr( szHostName, ':' );
if ( pchColon )
{
*pchColon = 0;
}
// DNS it
struct hostent *h = gethostbyname( szHostName );
if ( !h )
return;
SetIP( ntohl( *(int *)h->h_addr_list[0] ) );
if ( pchColon )
{
SetPort( atoi( ++pchColon ) );
}
#else
Assert( 0 );
#endif
}
}
bool netadr_t::operator<(const netadr_t &netadr) const
{
if ( *((uint *)netadr.ip) < *((uint *)ip) )
return true;
else if ( *((uint *)netadr.ip) > *((uint *)ip) )
return false;
return ( netadr.port < port );
}
void netadr_t::SetFromSocket( int hSocket )
{
#if !defined(_X360)
Clear();
type = NA_IP;
struct sockaddr address;
int namelen = sizeof(address);
if ( getsockname( hSocket, (struct sockaddr *)&address, (socklen_t *)&namelen) == 0 )
{
SetFromSockadr( &address );
}
#else
Assert(0);
#endif
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// NetAdr.cpp: implementation of the CNetAdr class.
//
//===========================================================================//
#if defined( _WIN32 ) && !defined( _X360 )
#include <windows.h>
#endif
#include "tier0/dbg.h"
#include "netadr.h"
#include "tier1/strtools.h"
#if defined( _WIN32 ) && !defined( _X360 )
#define WIN32_LEAN_AND_MEAN
#include <winsock.h>
typedef int socklen_t;
#elif !defined( _X360 )
#include <netinet/in.h> // ntohs()
#include <netdb.h> // gethostbyname()
#include <sys/socket.h> // getsockname()
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
bool netadr_t::CompareAdr (const netadr_t &a, bool onlyBase) const
{
if ( a.type != type )
return false;
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_BROADCAST )
return true;
if ( type == NA_IP )
{
if ( !onlyBase && (port != a.port) )
return false;
if ( a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3] )
return true;
}
return false;
}
bool netadr_t::CompareClassBAdr (const netadr_t &a) const
{
if ( a.type != type )
return false;
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_IP )
{
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] )
return true;
}
return false;
}
bool netadr_t::CompareClassCAdr (const netadr_t &a) const
{
if ( a.type != type )
return false;
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_IP )
{
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] )
return true;
}
return false;
}
// reserved addresses are not routeable, so they can all be used in a LAN game
bool netadr_t::IsReservedAdr () const
{
if ( type == NA_LOOPBACK )
return true;
if ( type == NA_IP )
{
if ( (ip[0] == 10) || // 10.x.x.x is reserved
(ip[0] == 127) || // 127.x.x.x
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x
(ip[0] == 192 && ip[1] >= 168) ) // 192.168.x.x
return true;
}
return false;
}
const char * netadr_t::ToString(bool baseOnly) const
{
static char s[64];
Q_strncpy (s, "unknown", sizeof( s ) );
if (type == NA_LOOPBACK)
{
Q_strncpy (s, "loopback", sizeof( s ) );
}
else if (type == NA_BROADCAST)
{
Q_strncpy (s, "broadcast", sizeof( s ) );
}
else if (type == NA_IP)
{
if ( baseOnly)
{
Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]);
}
else
{
Q_snprintf (s, sizeof( s ), "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port));
}
}
return s;
}
bool netadr_t::IsLocalhost() const
{
// are we 127.0.0.1 ?
return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1);
}
bool netadr_t::IsLoopback() const
{
// are we useding engine loopback buffers
return type == NA_LOOPBACK;
}
void netadr_t::Clear()
{
ip[0] = ip[1] = ip[2] = ip[3] = 0;
port = 0;
type = NA_NULL;
}
void netadr_t::SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4)
{
ip[0] = b1;
ip[1] = b2;
ip[2] = b3;
ip[3] = b4;
}
void netadr_t::SetIP(uint unIP)
{
*((uint*)ip) = BigLong( unIP );
}
void netadr_t::SetType(netadrtype_t newtype)
{
type = newtype;
}
netadrtype_t netadr_t::GetType() const
{
return type;
}
unsigned short netadr_t::GetPort() const
{
return BigShort( port );
}
unsigned int netadr_t::GetIPNetworkByteOrder() const
{
return *(unsigned int *)&ip;
}
unsigned int netadr_t::GetIPHostByteOrder() const
{
return ntohl( GetIPNetworkByteOrder() );
}
void netadr_t::ToSockadr (struct sockaddr * s) const
{
Q_memset ( s, 0, sizeof(struct sockaddr));
if (type == NA_BROADCAST)
{
((struct sockaddr_in*)s)->sin_family = AF_INET;
((struct sockaddr_in*)s)->sin_port = port;
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST;
}
else if (type == NA_IP)
{
((struct sockaddr_in*)s)->sin_family = AF_INET;
((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&ip;
((struct sockaddr_in*)s)->sin_port = port;
}
else if (type == NA_LOOPBACK )
{
((struct sockaddr_in*)s)->sin_family = AF_INET;
((struct sockaddr_in*)s)->sin_port = port;
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK ;
}
}
bool netadr_t::SetFromSockadr(const struct sockaddr * s)
{
if (s->sa_family == AF_INET)
{
type = NA_IP;
*(int *)&ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
port = ((struct sockaddr_in *)s)->sin_port;
return true;
}
else
{
Clear();
return false;
}
}
bool netadr_t::IsValid() const
{
return ( (port !=0 ) && (type != NA_NULL) &&
( ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0 ) );
}
#ifdef _WIN32
#undef SetPort // get around stupid WINSPOOL.H macro
#endif
void netadr_t::SetPort(unsigned short newport)
{
port = BigShort( newport );
}
void netadr_t::SetFromString( const char *pch, bool bUseDNS )
{
Clear();
type = NA_IP;
Assert( pch ); // invalid to call this with NULL pointer; fix your code bug!
if ( !pch ) // but let's not crash
return;
if ( pch[0] >= '0' && pch[0] <= '9' && strchr( pch, '.' ) )
{
int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0;
int nRes = sscanf( pch, "%d.%d.%d.%d:%d", &n1, &n2, &n3, &n4, &n5 );
if ( nRes >= 4 )
{
SetIP( n1, n2, n3, n4 );
}
if ( nRes == 5 )
{
SetPort( ( uint16 ) n5 );
}
}
else if ( bUseDNS )
{
// X360TBD:
#if !defined( _X360 )
char szHostName[ 256 ];
Q_strncpy( szHostName, pch, sizeof(szHostName) );
char *pchColon = strchr( szHostName, ':' );
if ( pchColon )
{
*pchColon = 0;
}
// DNS it
struct hostent *h = gethostbyname( szHostName );
if ( !h )
return;
SetIP( ntohl( *(int *)h->h_addr_list[0] ) );
if ( pchColon )
{
SetPort( atoi( ++pchColon ) );
}
#else
Assert( 0 );
#endif
}
}
bool netadr_t::operator<(const netadr_t &netadr) const
{
if ( *((uint *)netadr.ip) < *((uint *)ip) )
return true;
else if ( *((uint *)netadr.ip) > *((uint *)ip) )
return false;
return ( netadr.port < port );
}
void netadr_t::SetFromSocket( int hSocket )
{
#if !defined(_X360)
Clear();
type = NA_IP;
struct sockaddr address;
int namelen = sizeof(address);
if ( getsockname( hSocket, (struct sockaddr *)&address, (socklen_t *)&namelen) == 0 )
{
SetFromSockadr( &address );
}
#else
Assert(0);
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,90 +1,90 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Low level byte swapping routines.
//
// $NoKeywords: $
//=============================================================================
#include "byteswap.h"
//-----------------------------------------------------------------------------
// Copy a single field from the input buffer to the output buffer, swapping the bytes if necessary
//-----------------------------------------------------------------------------
void CByteswap::SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField )
{
switch ( pField->fieldType )
{
case FIELD_CHARACTER:
SwapBufferToTargetEndian<char>( (char*)pOutputBuffer, (char*)pData, pField->fieldSize );
break;
case FIELD_BOOLEAN:
SwapBufferToTargetEndian<bool>( (bool*)pOutputBuffer, (bool*)pData, pField->fieldSize );
break;
case FIELD_SHORT:
SwapBufferToTargetEndian<short>( (short*)pOutputBuffer, (short*)pData, pField->fieldSize );
break;
case FIELD_FLOAT:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize );
break;
case FIELD_INTEGER:
SwapBufferToTargetEndian<int>( (int*)pOutputBuffer, (int*)pData, pField->fieldSize );
break;
case FIELD_VECTOR:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 3 );
break;
case FIELD_VECTOR2D:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 2 );
break;
case FIELD_QUATERNION:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 4 );
break;
case FIELD_EMBEDDED:
{
typedescription_t *pEmbed = pField->td->dataDesc;
for ( int i = 0; i < pField->fieldSize; ++i )
{
SwapFieldsToTargetEndian( (byte*)pOutputBuffer + pEmbed->fieldOffset[ TD_OFFSET_NORMAL ],
(byte*)pData + pEmbed->fieldOffset[ TD_OFFSET_NORMAL ],
pField->td );
pOutputBuffer = (byte*)pOutputBuffer + pField->fieldSizeInBytes;
pData = (byte*)pData + pField->fieldSizeInBytes;
}
}
break;
default:
assert(0);
}
}
//-----------------------------------------------------------------------------
// Write a block of fields. Works a bit like the saverestore code.
//-----------------------------------------------------------------------------
void CByteswap::SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap )
{
// deal with base class first
if ( pDataMap->baseMap )
{
SwapFieldsToTargetEndian( pOutputBuffer, pBaseData, pDataMap->baseMap );
}
typedescription_t *pFields = pDataMap->dataDesc;
int fieldCount = pDataMap->dataNumFields;
for ( int i = 0; i < fieldCount; ++i )
{
typedescription_t *pField = &pFields[i];
SwapFieldToTargetEndian( (BYTE*)pOutputBuffer + pField->fieldOffset[ TD_OFFSET_NORMAL ],
(BYTE*)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ],
pField );
}
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Low level byte swapping routines.
//
// $NoKeywords: $
//=============================================================================
#include "byteswap.h"
//-----------------------------------------------------------------------------
// Copy a single field from the input buffer to the output buffer, swapping the bytes if necessary
//-----------------------------------------------------------------------------
void CByteswap::SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField )
{
switch ( pField->fieldType )
{
case FIELD_CHARACTER:
SwapBufferToTargetEndian<char>( (char*)pOutputBuffer, (char*)pData, pField->fieldSize );
break;
case FIELD_BOOLEAN:
SwapBufferToTargetEndian<bool>( (bool*)pOutputBuffer, (bool*)pData, pField->fieldSize );
break;
case FIELD_SHORT:
SwapBufferToTargetEndian<short>( (short*)pOutputBuffer, (short*)pData, pField->fieldSize );
break;
case FIELD_FLOAT:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize );
break;
case FIELD_INTEGER:
SwapBufferToTargetEndian<int>( (int*)pOutputBuffer, (int*)pData, pField->fieldSize );
break;
case FIELD_VECTOR:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 3 );
break;
case FIELD_VECTOR2D:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 2 );
break;
case FIELD_QUATERNION:
SwapBufferToTargetEndian<uint>( (uint*)pOutputBuffer, (uint*)pData, pField->fieldSize * 4 );
break;
case FIELD_EMBEDDED:
{
typedescription_t *pEmbed = pField->td->dataDesc;
for ( int i = 0; i < pField->fieldSize; ++i )
{
SwapFieldsToTargetEndian( (byte*)pOutputBuffer + pEmbed->fieldOffset[ TD_OFFSET_NORMAL ],
(byte*)pData + pEmbed->fieldOffset[ TD_OFFSET_NORMAL ],
pField->td );
pOutputBuffer = (byte*)pOutputBuffer + pField->fieldSizeInBytes;
pData = (byte*)pData + pField->fieldSizeInBytes;
}
}
break;
default:
assert(0);
}
}
//-----------------------------------------------------------------------------
// Write a block of fields. Works a bit like the saverestore code.
//-----------------------------------------------------------------------------
void CByteswap::SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap )
{
// deal with base class first
if ( pDataMap->baseMap )
{
SwapFieldsToTargetEndian( pOutputBuffer, pBaseData, pDataMap->baseMap );
}
typedescription_t *pFields = pDataMap->dataDesc;
int fieldCount = pDataMap->dataNumFields;
for ( int i = 0; i < fieldCount; ++i )
{
typedescription_t *pField = &pFields[i];
SwapFieldToTargetEndian( (BYTE*)pOutputBuffer + pField->fieldOffset[ TD_OFFSET_NORMAL ],
(BYTE*)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ],
pField );
}
}

View File

@@ -1,41 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include <string.h>
#include "characterset.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: builds a simple lookup table of a group of important characters
// Input : *pParseGroup - pointer to the buffer for the group
// *pGroupString - null terminated list of characters to flag
//-----------------------------------------------------------------------------
void CharacterSetBuild( characterset_t *pSetBuffer, const char *pszSetString )
{
int i = 0;
// Test our pointers
if ( !pSetBuffer || !pszSetString )
return;
memset( pSetBuffer->set, 0, sizeof(pSetBuffer->set) );
while ( pszSetString[i] )
{
pSetBuffer->set[ pszSetString[i] ] = 1;
i++;
}
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include <string.h>
#include "characterset.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: builds a simple lookup table of a group of important characters
// Input : *pParseGroup - pointer to the buffer for the group
// *pGroupString - null terminated list of characters to flag
//-----------------------------------------------------------------------------
void CharacterSetBuild( characterset_t *pSetBuffer, const char *pszSetString )
{
int i = 0;
// Test our pointers
if ( !pSetBuffer || !pszSetString )
return;
memset( pSetBuffer->set, 0, sizeof(pSetBuffer->set) );
while ( pszSetString[i] )
{
pSetBuffer->set[ pszSetString[i] ] = 1;
i++;
}
}

View File

@@ -1,180 +1,180 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Generic CRC functions
//
//=============================================================================//
#include "basetypes.h"
#include "commonmacros.h"
#include "checksum_crc.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define CRC32_INIT_VALUE 0xFFFFFFFFUL
#define CRC32_XOR_VALUE 0xFFFFFFFFUL
#define NUM_BYTES 256
static const CRC32_t pulCRCTable[NUM_BYTES] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
void CRC32_Init(CRC32_t *pulCRC)
{
*pulCRC = CRC32_INIT_VALUE;
}
void CRC32_Final(CRC32_t *pulCRC)
{
*pulCRC ^= CRC32_XOR_VALUE;
}
CRC32_t CRC32_GetTableEntry( unsigned int slot )
{
return pulCRCTable[(unsigned char)slot];
}
void CRC32_ProcessBuffer(CRC32_t *pulCRC, const void *pBuffer, int nBuffer)
{
CRC32_t ulCrc = *pulCRC;
unsigned char *pb = (unsigned char *)pBuffer;
unsigned int nFront;
int nMain;
JustAfew:
switch (nBuffer)
{
case 7:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 6:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 5:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 4:
ulCrc ^= LittleLong( *(CRC32_t *)pb );
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
*pulCRC = ulCrc;
return;
case 3:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 2:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 1:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 0:
*pulCRC = ulCrc;
return;
}
// We may need to do some alignment work up front, and at the end, so that
// the main loop is aligned and only has to worry about 8 byte at a time.
//
// The low-order two bits of pb and nBuffer in total control the
// upfront work.
//
nFront = ((unsigned int)pb) & 3;
nBuffer -= nFront;
switch (nFront)
{
case 3:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 2:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 1:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
}
nMain = nBuffer >> 3;
while (nMain--)
{
ulCrc ^= LittleLong( *(CRC32_t *)pb );
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc ^= LittleLong( *(CRC32_t *)(pb + 4) );
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
pb += 8;
}
nBuffer &= 7;
goto JustAfew;
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Generic CRC functions
//
//=============================================================================//
#include "basetypes.h"
#include "commonmacros.h"
#include "checksum_crc.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define CRC32_INIT_VALUE 0xFFFFFFFFUL
#define CRC32_XOR_VALUE 0xFFFFFFFFUL
#define NUM_BYTES 256
static const CRC32_t pulCRCTable[NUM_BYTES] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
void CRC32_Init(CRC32_t *pulCRC)
{
*pulCRC = CRC32_INIT_VALUE;
}
void CRC32_Final(CRC32_t *pulCRC)
{
*pulCRC ^= CRC32_XOR_VALUE;
}
CRC32_t CRC32_GetTableEntry( unsigned int slot )
{
return pulCRCTable[(unsigned char)slot];
}
void CRC32_ProcessBuffer(CRC32_t *pulCRC, const void *pBuffer, int nBuffer)
{
CRC32_t ulCrc = *pulCRC;
unsigned char *pb = (unsigned char *)pBuffer;
unsigned int nFront;
int nMain;
JustAfew:
switch (nBuffer)
{
case 7:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 6:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 5:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 4:
ulCrc ^= LittleLong( *(CRC32_t *)pb );
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
*pulCRC = ulCrc;
return;
case 3:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 2:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 1:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 0:
*pulCRC = ulCrc;
return;
}
// We may need to do some alignment work up front, and at the end, so that
// the main loop is aligned and only has to worry about 8 byte at a time.
//
// The low-order two bits of pb and nBuffer in total control the
// upfront work.
//
nFront = ((unsigned int)pb) & 3;
nBuffer -= nFront;
switch (nFront)
{
case 3:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 2:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
case 1:
ulCrc = pulCRCTable[*pb++ ^ (unsigned char)ulCrc] ^ (ulCrc >> 8);
}
nMain = nBuffer >> 3;
while (nMain--)
{
ulCrc ^= LittleLong( *(CRC32_t *)pb );
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc ^= LittleLong( *(CRC32_t *)(pb + 4) );
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
ulCrc = pulCRCTable[(unsigned char)ulCrc] ^ (ulCrc >> 8);
pb += 8;
}
nBuffer &= 7;
goto JustAfew;
}

View File

@@ -1,305 +1,305 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "basetypes.h"
#include "commonmacros.h"
#include "checksum_md5.h"
#include <string.h>
#include <stdio.h>
#include "tier1/strtools.h"
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// The four core functions - F1 is optimized somewhat
// #define F1(x, y, z) (x & y | ~x & z)
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
// This is the central step in the MD5 algorithm.
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
//-----------------------------------------------------------------------------
// Purpose: The core of the MD5 algorithm, this alters an existing MD5 hash to
// reflect the addition of 16 longwords of new data. MD5Update blocks
// the data and converts bytes into longwords for this routine.
// Input : buf[4] -
// in[16] -
// Output : static void
//-----------------------------------------------------------------------------
static void MD5Transform(unsigned int buf[4], unsigned int const in[16])
{
register unsigned int a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
//-----------------------------------------------------------------------------
// Purpose: Start MD5 accumulation. Set bit count to 0 and buffer to mysterious initialization constants.
// Input : *ctx -
//-----------------------------------------------------------------------------
void MD5Init(MD5Context_t *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Update context to reflect the concatenation of another buffer full of bytes.
// Input : *ctx -
// *buf -
// len -
//-----------------------------------------------------------------------------
void MD5Update(MD5Context_t *ctx, unsigned char const *buf, unsigned int len)
{
unsigned int t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((unsigned int) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t)
{
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t)
{
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
//byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64)
{
memcpy(ctx->in, buf, 64);
//byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
//-----------------------------------------------------------------------------
// Purpose: Final wrapup - pad to 64-byte boundary with the bit pattern
// 1 0* (64-bit count of bits processed, MSB-first)
// Input : digest[MD5_DIGEST_LENGTH] -
// *ctx -
//-----------------------------------------------------------------------------
void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5Context_t *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8)
{
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
//byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
}
else
{
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
//byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((unsigned int *) ctx->in)[14] = ctx->bits[0];
((unsigned int *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
//byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, MD5_DIGEST_LENGTH);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *hash -
// hashlen -
// Output : char
//-----------------------------------------------------------------------------
char *MD5_Print( unsigned char *hash, int hashlen )
{
static char szReturn[64];
Assert( hashlen <= 32 );
Q_binarytohex( hash, hashlen, szReturn, sizeof( szReturn ) );
return szReturn;
}
//-----------------------------------------------------------------------------
// Purpose: generate pseudo random number from a seed number
// Input : seed number
// Output : pseudo random number
//-----------------------------------------------------------------------------
unsigned int MD5_PseudoRandom(unsigned int nSeed)
{
MD5Context_t ctx;
unsigned char digest[MD5_DIGEST_LENGTH]; // The MD5 Hash
memset( &ctx, 0, sizeof( ctx ) );
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char*)&nSeed, sizeof(nSeed) );
MD5Final(digest, &ctx);
return *(unsigned int*)(digest+6); // use 4 middle bytes for random value
}
//-----------------------------------------------------------------------------
bool MD5_Compare( const MD5Value_t &data, const MD5Value_t &compare )
{
return V_memcmp( data.bits, compare.bits, MD5_DIGEST_LENGTH ) == 0;
}
//-----------------------------------------------------------------------------
void MD5Value_t::Zero()
{
V_memset( bits, 0, sizeof( bits ) );
}
//-----------------------------------------------------------------------------
bool MD5Value_t::IsZero() const
{
for ( int i = 0 ; i < Q_ARRAYSIZE( bits ) ; ++i )
{
if ( bits[i] != 0 )
return false;
}
return true;
}
//-----------------------------------------------------------------------------
void MD5_ProcessSingleBuffer( const void *p, int len, MD5Value_t &md5Result )
{
Assert( len >= 0 );
MD5Context_t ctx;
MD5Init( &ctx );
MD5Update( &ctx, (unsigned char const *)p, len );
MD5Final( md5Result.bits, &ctx );
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "basetypes.h"
#include "commonmacros.h"
#include "checksum_md5.h"
#include <string.h>
#include <stdio.h>
#include "tier1/strtools.h"
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// The four core functions - F1 is optimized somewhat
// #define F1(x, y, z) (x & y | ~x & z)
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
// This is the central step in the MD5 algorithm.
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
//-----------------------------------------------------------------------------
// Purpose: The core of the MD5 algorithm, this alters an existing MD5 hash to
// reflect the addition of 16 longwords of new data. MD5Update blocks
// the data and converts bytes into longwords for this routine.
// Input : buf[4] -
// in[16] -
// Output : static void
//-----------------------------------------------------------------------------
static void MD5Transform(unsigned int buf[4], unsigned int const in[16])
{
register unsigned int a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
//-----------------------------------------------------------------------------
// Purpose: Start MD5 accumulation. Set bit count to 0 and buffer to mysterious initialization constants.
// Input : *ctx -
//-----------------------------------------------------------------------------
void MD5Init(MD5Context_t *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Update context to reflect the concatenation of another buffer full of bytes.
// Input : *ctx -
// *buf -
// len -
//-----------------------------------------------------------------------------
void MD5Update(MD5Context_t *ctx, unsigned char const *buf, unsigned int len)
{
unsigned int t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((unsigned int) len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t)
{
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t)
{
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
//byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64)
{
memcpy(ctx->in, buf, 64);
//byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
//-----------------------------------------------------------------------------
// Purpose: Final wrapup - pad to 64-byte boundary with the bit pattern
// 1 0* (64-bit count of bits processed, MSB-first)
// Input : digest[MD5_DIGEST_LENGTH] -
// *ctx -
//-----------------------------------------------------------------------------
void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5Context_t *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8)
{
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
//byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
}
else
{
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
//byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((unsigned int *) ctx->in)[14] = ctx->bits[0];
((unsigned int *) ctx->in)[15] = ctx->bits[1];
MD5Transform(ctx->buf, (unsigned int *) ctx->in);
//byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, MD5_DIGEST_LENGTH);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *hash -
// hashlen -
// Output : char
//-----------------------------------------------------------------------------
char *MD5_Print( unsigned char *hash, int hashlen )
{
static char szReturn[64];
Assert( hashlen <= 32 );
Q_binarytohex( hash, hashlen, szReturn, sizeof( szReturn ) );
return szReturn;
}
//-----------------------------------------------------------------------------
// Purpose: generate pseudo random number from a seed number
// Input : seed number
// Output : pseudo random number
//-----------------------------------------------------------------------------
unsigned int MD5_PseudoRandom(unsigned int nSeed)
{
MD5Context_t ctx;
unsigned char digest[MD5_DIGEST_LENGTH]; // The MD5 Hash
memset( &ctx, 0, sizeof( ctx ) );
MD5Init(&ctx);
MD5Update(&ctx, (unsigned char*)&nSeed, sizeof(nSeed) );
MD5Final(digest, &ctx);
return *(unsigned int*)(digest+6); // use 4 middle bytes for random value
}
//-----------------------------------------------------------------------------
bool MD5_Compare( const MD5Value_t &data, const MD5Value_t &compare )
{
return V_memcmp( data.bits, compare.bits, MD5_DIGEST_LENGTH ) == 0;
}
//-----------------------------------------------------------------------------
void MD5Value_t::Zero()
{
V_memset( bits, 0, sizeof( bits ) );
}
//-----------------------------------------------------------------------------
bool MD5Value_t::IsZero() const
{
for ( int i = 0 ; i < Q_ARRAYSIZE( bits ) ; ++i )
{
if ( bits[i] != 0 )
return false;
}
return true;
}
//-----------------------------------------------------------------------------
void MD5_ProcessSingleBuffer( const void *p, int len, MD5Value_t &md5Result )
{
Assert( len >= 0 );
MD5Context_t ctx;
MD5Init( &ctx );
MD5Update( &ctx, (unsigned char const *)p, len );
MD5Final( md5Result.bits, &ctx );
}

View File

@@ -1,299 +1,299 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of SHA-1
//
//=============================================================================
/*
100% free public domain implementation of the SHA-1
algorithm by Dominik Reichl <dominik.reichl@t-online.de>
=== Test Vectors (from FIPS PUB 180-1) ===
SHA1("abc") =
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
SHA1(A million repetitions of "a") =
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#if !defined(_MINIMUM_BUILD_)
#include "checksum_sha1.h"
#else
//
// This path is build in the CEG/DRM projects where we require that no CRT references are made !
//
#include <intrin.h> // memcpy, memset etc... will be inlined.
#include "tier1/checksum_sha1.h"
#endif
#define MAX_FILE_READ_BUFFER 8000
// Rotate x bits to the left
#ifndef ROL32
#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits))))
#endif
#ifdef SHA1_LITTLE_ENDIAN
#define SHABLK0(i) (m_block->l[i] = \
(ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF))
#else
#define SHABLK0(i) (m_block->l[i])
#endif
#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \
^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1))
// SHA-1 rounds
#define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); }
#define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); }
#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); }
#ifdef _MINIMUM_BUILD_
Minimum_CSHA1::Minimum_CSHA1()
#else
CSHA1::CSHA1()
#endif
{
m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;
Reset();
}
#ifdef _MINIMUM_BUILD_
Minimum_CSHA1::~Minimum_CSHA1()
#else
CSHA1::~CSHA1()
#endif
{
// Reset();
}
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Reset()
#else
void CSHA1::Reset()
#endif
{
// SHA1 initialization constants
m_state[0] = 0x67452301;
m_state[1] = 0xEFCDAB89;
m_state[2] = 0x98BADCFE;
m_state[3] = 0x10325476;
m_state[4] = 0xC3D2E1F0;
m_count[0] = 0;
m_count[1] = 0;
}
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Transform(unsigned long state[5], unsigned char buffer[64])
#else
void CSHA1::Transform(unsigned long state[5], unsigned char buffer[64])
#endif
{
unsigned long a = 0, b = 0, c = 0, d = 0, e = 0;
memcpy(m_block, buffer, 64);
// Copy state[] to working vars
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
// 4 rounds of 20 operations each. Loop unrolled.
_R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3);
_R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7);
_R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11);
_R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15);
_R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19);
_R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23);
_R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27);
_R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31);
_R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35);
_R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39);
_R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43);
_R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47);
_R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51);
_R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55);
_R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59);
_R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63);
_R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67);
_R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71);
_R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75);
_R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79);
// Add the working vars back into state[]
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
// Wipe variables
a = b = c = d = e = 0;
}
// Use this function to hash in binary data and strings
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Update(unsigned char *data, unsigned int len)
#else
void CSHA1::Update(unsigned char *data, unsigned int len)
#endif
{
unsigned long i = 0, j;
j = (m_count[0] >> 3) & 63;
if((m_count[0] += len << 3) < (len << 3)) m_count[1]++;
m_count[1] += (len >> 29);
if((j + len) > 63)
{
memcpy(&m_buffer[j], data, (i = 64 - j));
Transform(m_state, m_buffer);
for (; i+63 < len; i += 64)
Transform(m_state, &data[i]);
j = 0;
}
else i = 0;
memcpy(&m_buffer[j], &data[i], len - i);
}
#if !defined(_MINIMUM_BUILD_)
// Hash in file contents
bool CSHA1::HashFile(char *szFileName)
{
unsigned long ulFileSize = 0, ulRest = 0, ulBlocks = 0;
unsigned long i = 0;
unsigned char uData[MAX_FILE_READ_BUFFER];
FILE *fIn = NULL;
if(szFileName == NULL) return(false);
if((fIn = fopen(szFileName, "rb")) == NULL) return(false);
fseek(fIn, 0, SEEK_END);
ulFileSize = ftell(fIn);
fseek(fIn, 0, SEEK_SET);
ulRest = ulFileSize % MAX_FILE_READ_BUFFER;
ulBlocks = ulFileSize / MAX_FILE_READ_BUFFER;
for(i = 0; i < ulBlocks; i++)
{
fread(uData, 1, MAX_FILE_READ_BUFFER, fIn);
Update(uData, MAX_FILE_READ_BUFFER);
}
if(ulRest != 0)
{
fread(uData, 1, ulRest, fIn);
Update(uData, ulRest);
}
fclose(fIn);
fIn = NULL;
return(true);
}
#endif
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Final()
#else
void CSHA1::Final()
#endif
{
unsigned long i = 0;
unsigned char finalcount[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
for (i = 0; i < 8; i++)
finalcount[i] = (unsigned char)((m_count[(i >= 4 ? 0 : 1)]
>> ((3 - (i & 3)) * 8) ) & 255); // Endian independent
Update((unsigned char *)"\200", 1);
while ((m_count[0] & 504) != 448)
Update((unsigned char *)"\0", 1);
Update(finalcount, 8); // Cause a SHA1Transform()
for (i = 0; i < k_cubHash; i++)
{
m_digest[i] = (unsigned char)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255);
}
// Wipe variables for security reasons
i = 0;
memset(m_buffer, 0, sizeof(m_buffer) );
memset(m_state, 0, sizeof(m_state) );
memset(m_count, 0, sizeof(m_count) );
memset(finalcount, 0, sizeof( finalcount) );
Transform(m_state, m_buffer);
}
#if !defined(_MINIMUM_BUILD_)
// Get the final hash as a pre-formatted string
void CSHA1::ReportHash(char *szReport, unsigned char uReportType)
{
unsigned char i = 0;
char szTemp[12];
if(szReport == NULL) return;
if(uReportType == REPORT_HEX)
{
sprintf(szTemp, "%02X", m_digest[0]);
strcat(szReport, szTemp);
for(i = 1; i < k_cubHash; i++)
{
sprintf(szTemp, " %02X", m_digest[i]);
strcat(szReport, szTemp);
}
}
else if(uReportType == REPORT_DIGIT)
{
sprintf(szTemp, "%u", m_digest[0]);
strcat(szReport, szTemp);
for(i = 1; i < k_cubHash; i++)
{
sprintf(szTemp, " %u", m_digest[i]);
strcat(szReport, szTemp);
}
}
else strcpy(szReport, "Error: Unknown report type!");
}
#endif // _MINIMUM_BUILD_
// Get the raw message digest
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::GetHash(unsigned char *uDest)
#else
void CSHA1::GetHash(unsigned char *uDest)
#endif
{
memcpy(uDest, m_digest, k_cubHash);
}
#ifndef _MINIMUM_BUILD_
// utility hash comparison function
bool HashLessFunc( SHADigest_t const &lhs, SHADigest_t const &rhs )
{
int iRes = memcmp( &lhs, &rhs, sizeof( SHADigest_t ) );
return ( iRes < 0 );
}
#endif
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Implementation of SHA-1
//
//=============================================================================
/*
100% free public domain implementation of the SHA-1
algorithm by Dominik Reichl <dominik.reichl@t-online.de>
=== Test Vectors (from FIPS PUB 180-1) ===
SHA1("abc") =
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
SHA1(A million repetitions of "a") =
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#if !defined(_MINIMUM_BUILD_)
#include "checksum_sha1.h"
#else
//
// This path is build in the CEG/DRM projects where we require that no CRT references are made !
//
#include <intrin.h> // memcpy, memset etc... will be inlined.
#include "tier1/checksum_sha1.h"
#endif
#define MAX_FILE_READ_BUFFER 8000
// Rotate x bits to the left
#ifndef ROL32
#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits))))
#endif
#ifdef SHA1_LITTLE_ENDIAN
#define SHABLK0(i) (m_block->l[i] = \
(ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF))
#else
#define SHABLK0(i) (m_block->l[i])
#endif
#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \
^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1))
// SHA-1 rounds
#define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); }
#define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); }
#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); }
#ifdef _MINIMUM_BUILD_
Minimum_CSHA1::Minimum_CSHA1()
#else
CSHA1::CSHA1()
#endif
{
m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;
Reset();
}
#ifdef _MINIMUM_BUILD_
Minimum_CSHA1::~Minimum_CSHA1()
#else
CSHA1::~CSHA1()
#endif
{
// Reset();
}
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Reset()
#else
void CSHA1::Reset()
#endif
{
// SHA1 initialization constants
m_state[0] = 0x67452301;
m_state[1] = 0xEFCDAB89;
m_state[2] = 0x98BADCFE;
m_state[3] = 0x10325476;
m_state[4] = 0xC3D2E1F0;
m_count[0] = 0;
m_count[1] = 0;
}
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Transform(unsigned long state[5], unsigned char buffer[64])
#else
void CSHA1::Transform(unsigned long state[5], unsigned char buffer[64])
#endif
{
unsigned long a = 0, b = 0, c = 0, d = 0, e = 0;
memcpy(m_block, buffer, 64);
// Copy state[] to working vars
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
// 4 rounds of 20 operations each. Loop unrolled.
_R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3);
_R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7);
_R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11);
_R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15);
_R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19);
_R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23);
_R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27);
_R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31);
_R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35);
_R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39);
_R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43);
_R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47);
_R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51);
_R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55);
_R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59);
_R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63);
_R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67);
_R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71);
_R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75);
_R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79);
// Add the working vars back into state[]
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
// Wipe variables
a = b = c = d = e = 0;
}
// Use this function to hash in binary data and strings
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Update(unsigned char *data, unsigned int len)
#else
void CSHA1::Update(unsigned char *data, unsigned int len)
#endif
{
unsigned long i = 0, j;
j = (m_count[0] >> 3) & 63;
if((m_count[0] += len << 3) < (len << 3)) m_count[1]++;
m_count[1] += (len >> 29);
if((j + len) > 63)
{
memcpy(&m_buffer[j], data, (i = 64 - j));
Transform(m_state, m_buffer);
for (; i+63 < len; i += 64)
Transform(m_state, &data[i]);
j = 0;
}
else i = 0;
memcpy(&m_buffer[j], &data[i], len - i);
}
#if !defined(_MINIMUM_BUILD_)
// Hash in file contents
bool CSHA1::HashFile(char *szFileName)
{
unsigned long ulFileSize = 0, ulRest = 0, ulBlocks = 0;
unsigned long i = 0;
unsigned char uData[MAX_FILE_READ_BUFFER];
FILE *fIn = NULL;
if(szFileName == NULL) return(false);
if((fIn = fopen(szFileName, "rb")) == NULL) return(false);
fseek(fIn, 0, SEEK_END);
ulFileSize = ftell(fIn);
fseek(fIn, 0, SEEK_SET);
ulRest = ulFileSize % MAX_FILE_READ_BUFFER;
ulBlocks = ulFileSize / MAX_FILE_READ_BUFFER;
for(i = 0; i < ulBlocks; i++)
{
fread(uData, 1, MAX_FILE_READ_BUFFER, fIn);
Update(uData, MAX_FILE_READ_BUFFER);
}
if(ulRest != 0)
{
fread(uData, 1, ulRest, fIn);
Update(uData, ulRest);
}
fclose(fIn);
fIn = NULL;
return(true);
}
#endif
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::Final()
#else
void CSHA1::Final()
#endif
{
unsigned long i = 0;
unsigned char finalcount[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
for (i = 0; i < 8; i++)
finalcount[i] = (unsigned char)((m_count[(i >= 4 ? 0 : 1)]
>> ((3 - (i & 3)) * 8) ) & 255); // Endian independent
Update((unsigned char *)"\200", 1);
while ((m_count[0] & 504) != 448)
Update((unsigned char *)"\0", 1);
Update(finalcount, 8); // Cause a SHA1Transform()
for (i = 0; i < k_cubHash; i++)
{
m_digest[i] = (unsigned char)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255);
}
// Wipe variables for security reasons
i = 0;
memset(m_buffer, 0, sizeof(m_buffer) );
memset(m_state, 0, sizeof(m_state) );
memset(m_count, 0, sizeof(m_count) );
memset(finalcount, 0, sizeof( finalcount) );
Transform(m_state, m_buffer);
}
#if !defined(_MINIMUM_BUILD_)
// Get the final hash as a pre-formatted string
void CSHA1::ReportHash(char *szReport, unsigned char uReportType)
{
unsigned char i = 0;
char szTemp[12];
if(szReport == NULL) return;
if(uReportType == REPORT_HEX)
{
sprintf(szTemp, "%02X", m_digest[0]);
strcat(szReport, szTemp);
for(i = 1; i < k_cubHash; i++)
{
sprintf(szTemp, " %02X", m_digest[i]);
strcat(szReport, szTemp);
}
}
else if(uReportType == REPORT_DIGIT)
{
sprintf(szTemp, "%u", m_digest[0]);
strcat(szReport, szTemp);
for(i = 1; i < k_cubHash; i++)
{
sprintf(szTemp, " %u", m_digest[i]);
strcat(szReport, szTemp);
}
}
else strcpy(szReport, "Error: Unknown report type!");
}
#endif // _MINIMUM_BUILD_
// Get the raw message digest
#ifdef _MINIMUM_BUILD_
void Minimum_CSHA1::GetHash(unsigned char *uDest)
#else
void CSHA1::GetHash(unsigned char *uDest)
#endif
{
memcpy(uDest, m_digest, k_cubHash);
}
#ifndef _MINIMUM_BUILD_
// utility hash comparison function
bool HashLessFunc( SHADigest_t const &lhs, SHADigest_t const &rhs )
{
int iRes = memcmp( &lhs, &rhs, sizeof( SHADigest_t ) );
return ( iRes < 0 );
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,411 +1,411 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "basetypes.h"
#include "datamanager.h"
DECLARE_POINTER_HANDLE( memhandle_t );
#define AUTO_LOCK_DM() AUTO_LOCK_( CDataManagerBase, *this )
CDataManagerBase::CDataManagerBase( unsigned int maxSize )
{
m_targetMemorySize = maxSize;
m_memUsed = 0;
m_lruList = m_memoryLists.CreateList();
m_lockList = m_memoryLists.CreateList();
m_freeList = m_memoryLists.CreateList();
m_listsAreFreed = 0;
}
CDataManagerBase::~CDataManagerBase()
{
Assert( m_listsAreFreed );
}
void CDataManagerBase::NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize )
{
Lock();
m_memUsed += (int)newSize - (int)oldSize;
Unlock();
}
void CDataManagerBase::SetTargetSize( unsigned int targetSize )
{
m_targetMemorySize = targetSize;
}
unsigned int CDataManagerBase::FlushAllUnlocked()
{
Lock();
int nFlush = m_memoryLists.Count( m_lruList );
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
CUtlVector<void *> destroyList( pScratch, nFlush );
unsigned nBytesInitial = MemUsed_Inline();
int node = m_memoryLists.Head(m_lruList);
while ( node != m_memoryLists.InvalidIndex() )
{
int next = m_memoryLists.Next(node);
m_memoryLists.Unlink( m_lruList, node );
destroyList.AddToTail( GetForFreeByIndex( node ) );
node = next;
}
Unlock();
for ( int i = 0; i < nFlush; i++ )
{
DestroyResourceStorage( destroyList[i] );
}
return ( nBytesInitial - MemUsed_Inline() );
}
unsigned int CDataManagerBase::FlushToTargetSize()
{
return EnsureCapacity(0);
}
// Frees everything! The LRU AND the LOCKED items. This is only used to forcibly free the resources,
// not to make space.
unsigned int CDataManagerBase::FlushAll()
{
Lock();
int nFlush = m_memoryLists.Count( m_lruList ) + m_memoryLists.Count( m_lockList );
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
CUtlVector<void *> destroyList( pScratch, nFlush );
unsigned result = MemUsed_Inline();
int node;
int nextNode;
node = m_memoryLists.Head(m_lruList);
while ( node != m_memoryLists.InvalidIndex() )
{
nextNode = m_memoryLists.Next(node);
m_memoryLists.Unlink( m_lruList, node );
destroyList.AddToTail( GetForFreeByIndex( node ) );
node = nextNode;
}
node = m_memoryLists.Head(m_lockList);
while ( node != m_memoryLists.InvalidIndex() )
{
nextNode = m_memoryLists.Next(node);
m_memoryLists.Unlink( m_lockList, node );
m_memoryLists[node].lockCount = 0;
destroyList.AddToTail( GetForFreeByIndex( node ) );
node = nextNode;
}
m_listsAreFreed = false;
Unlock();
for ( int i = 0; i < nFlush; i++ )
{
DestroyResourceStorage( destroyList[i] );
}
return result;
}
unsigned int CDataManagerBase::Purge( unsigned int nBytesToPurge )
{
unsigned int nTargetSize = MemUsed_Inline() - nBytesToPurge;
// Check for underflow
if ( MemUsed_Inline() < nBytesToPurge )
nTargetSize = 0;
unsigned int nImpliedCapacity = MemTotal_Inline() - nTargetSize;
return EnsureCapacity( nImpliedCapacity );
}
void CDataManagerBase::DestroyResource( memhandle_t handle )
{
Lock();
unsigned short index = FromHandle( handle );
if ( !m_memoryLists.IsValidIndex(index) )
{
Unlock();
return;
}
Assert( m_memoryLists[index].lockCount == 0 );
if ( m_memoryLists[index].lockCount )
BreakLock( handle );
m_memoryLists.Unlink( m_lruList, index );
void *p = GetForFreeByIndex( index );
Unlock();
DestroyResourceStorage( p );
}
void *CDataManagerBase::LockResource( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lruList, memoryIndex );
m_memoryLists.LinkToTail( m_lockList, memoryIndex );
}
Assert(m_memoryLists[memoryIndex].lockCount != (unsigned short)-1);
m_memoryLists[memoryIndex].lockCount++;
return m_memoryLists[memoryIndex].pStore;
}
return NULL;
}
int CDataManagerBase::UnlockResource( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
Assert( m_memoryLists[memoryIndex].lockCount > 0 );
if ( m_memoryLists[memoryIndex].lockCount > 0 )
{
m_memoryLists[memoryIndex].lockCount--;
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lockList, memoryIndex );
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
}
}
return m_memoryLists[memoryIndex].lockCount;
}
return 0;
}
void *CDataManagerBase::GetResource_NoLockNoLRUTouch( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
return m_memoryLists[memoryIndex].pStore;
}
return NULL;
}
void *CDataManagerBase::GetResource_NoLock( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
TouchByIndex( memoryIndex );
return m_memoryLists[memoryIndex].pStore;
}
return NULL;
}
void CDataManagerBase::TouchResource( memhandle_t handle )
{
AUTO_LOCK_DM();
TouchByIndex( FromHandle(handle) );
}
void CDataManagerBase::MarkAsStale( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lruList, memoryIndex );
m_memoryLists.LinkToHead( m_lruList, memoryIndex );
}
}
}
int CDataManagerBase::BreakLock( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() && m_memoryLists[memoryIndex].lockCount )
{
int nBroken = m_memoryLists[memoryIndex].lockCount;
m_memoryLists[memoryIndex].lockCount = 0;
m_memoryLists.Unlink( m_lockList, memoryIndex );
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
return nBroken;
}
return 0;
}
int CDataManagerBase::BreakAllLocks()
{
AUTO_LOCK_DM();
int nBroken = 0;
int node;
int nextNode;
node = m_memoryLists.Head(m_lockList);
while ( node != m_memoryLists.InvalidIndex() )
{
nBroken++;
nextNode = m_memoryLists.Next(node);
m_memoryLists[node].lockCount = 0;
m_memoryLists.Unlink( m_lockList, node );
m_memoryLists.LinkToTail( m_lruList, node );
node = nextNode;
}
return nBroken;
}
unsigned short CDataManagerBase::CreateHandle( bool bCreateLocked )
{
AUTO_LOCK_DM();
int memoryIndex = m_memoryLists.Head(m_freeList);
unsigned short list = ( bCreateLocked ) ? m_lockList : m_lruList;
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
m_memoryLists.Unlink( m_freeList, memoryIndex );
m_memoryLists.LinkToTail( list, memoryIndex );
}
else
{
memoryIndex = m_memoryLists.AddToTail( list );
}
if ( bCreateLocked )
{
m_memoryLists[memoryIndex].lockCount++;
}
return memoryIndex;
}
memhandle_t CDataManagerBase::StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize )
{
AUTO_LOCK_DM();
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
mem.pStore = pStore;
m_memUsed += realSize;
return ToHandle(memoryIndex);
}
void CDataManagerBase::TouchByIndex( unsigned short memoryIndex )
{
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lruList, memoryIndex );
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
}
}
}
memhandle_t CDataManagerBase::ToHandle( unsigned short index )
{
unsigned int hiword = m_memoryLists.Element(index).serial;
hiword <<= 16;
index++;
return (memhandle_t)( hiword|index );
}
unsigned int CDataManagerBase::TargetSize()
{
return MemTotal_Inline();
}
unsigned int CDataManagerBase::AvailableSize()
{
return MemAvailable_Inline();
}
unsigned int CDataManagerBase::UsedSize()
{
return MemUsed_Inline();
}
// free resources until there is enough space to hold "size"
unsigned int CDataManagerBase::EnsureCapacity( unsigned int size )
{
unsigned nBytesInitial = MemUsed_Inline();
while ( MemUsed_Inline() > MemTotal_Inline() || MemAvailable_Inline() < size )
{
Lock();
int lruIndex = m_memoryLists.Head( m_lruList );
if ( lruIndex == m_memoryLists.InvalidIndex() )
{
Unlock();
break;
}
m_memoryLists.Unlink( m_lruList, lruIndex );
void *p = GetForFreeByIndex( lruIndex );
Unlock();
DestroyResourceStorage( p );
}
return ( nBytesInitial - MemUsed_Inline() );
}
// free this resource and move the handle to the free list
void *CDataManagerBase::GetForFreeByIndex( unsigned short memoryIndex )
{
void *p = NULL;
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
Assert( m_memoryLists[memoryIndex].lockCount == 0 );
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
unsigned size = GetRealSize( mem.pStore );
if ( size > m_memUsed )
{
ExecuteOnce( Warning( "Data manager 'used' memory incorrect\n" ) );
size = m_memUsed;
}
m_memUsed -= size;
p = mem.pStore;
mem.pStore = NULL;
mem.serial++;
m_memoryLists.LinkToTail( m_freeList, memoryIndex );
}
return p;
}
// get a list of everything in the LRU
void CDataManagerBase::GetLRUHandleList( CUtlVector< memhandle_t >& list )
{
for ( int node = m_memoryLists.Tail(m_lruList);
node != m_memoryLists.InvalidIndex();
node = m_memoryLists.Previous(node) )
{
list.AddToTail( ToHandle( node ) );
}
}
// get a list of everything locked
void CDataManagerBase::GetLockHandleList( CUtlVector< memhandle_t >& list )
{
for ( int node = m_memoryLists.Head(m_lockList);
node != m_memoryLists.InvalidIndex();
node = m_memoryLists.Next(node) )
{
list.AddToTail( ToHandle( node ) );
}
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "basetypes.h"
#include "datamanager.h"
DECLARE_POINTER_HANDLE( memhandle_t );
#define AUTO_LOCK_DM() AUTO_LOCK_( CDataManagerBase, *this )
CDataManagerBase::CDataManagerBase( unsigned int maxSize )
{
m_targetMemorySize = maxSize;
m_memUsed = 0;
m_lruList = m_memoryLists.CreateList();
m_lockList = m_memoryLists.CreateList();
m_freeList = m_memoryLists.CreateList();
m_listsAreFreed = 0;
}
CDataManagerBase::~CDataManagerBase()
{
Assert( m_listsAreFreed );
}
void CDataManagerBase::NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize )
{
Lock();
m_memUsed += (int)newSize - (int)oldSize;
Unlock();
}
void CDataManagerBase::SetTargetSize( unsigned int targetSize )
{
m_targetMemorySize = targetSize;
}
unsigned int CDataManagerBase::FlushAllUnlocked()
{
Lock();
int nFlush = m_memoryLists.Count( m_lruList );
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
CUtlVector<void *> destroyList( pScratch, nFlush );
unsigned nBytesInitial = MemUsed_Inline();
int node = m_memoryLists.Head(m_lruList);
while ( node != m_memoryLists.InvalidIndex() )
{
int next = m_memoryLists.Next(node);
m_memoryLists.Unlink( m_lruList, node );
destroyList.AddToTail( GetForFreeByIndex( node ) );
node = next;
}
Unlock();
for ( int i = 0; i < nFlush; i++ )
{
DestroyResourceStorage( destroyList[i] );
}
return ( nBytesInitial - MemUsed_Inline() );
}
unsigned int CDataManagerBase::FlushToTargetSize()
{
return EnsureCapacity(0);
}
// Frees everything! The LRU AND the LOCKED items. This is only used to forcibly free the resources,
// not to make space.
unsigned int CDataManagerBase::FlushAll()
{
Lock();
int nFlush = m_memoryLists.Count( m_lruList ) + m_memoryLists.Count( m_lockList );
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
CUtlVector<void *> destroyList( pScratch, nFlush );
unsigned result = MemUsed_Inline();
int node;
int nextNode;
node = m_memoryLists.Head(m_lruList);
while ( node != m_memoryLists.InvalidIndex() )
{
nextNode = m_memoryLists.Next(node);
m_memoryLists.Unlink( m_lruList, node );
destroyList.AddToTail( GetForFreeByIndex( node ) );
node = nextNode;
}
node = m_memoryLists.Head(m_lockList);
while ( node != m_memoryLists.InvalidIndex() )
{
nextNode = m_memoryLists.Next(node);
m_memoryLists.Unlink( m_lockList, node );
m_memoryLists[node].lockCount = 0;
destroyList.AddToTail( GetForFreeByIndex( node ) );
node = nextNode;
}
m_listsAreFreed = false;
Unlock();
for ( int i = 0; i < nFlush; i++ )
{
DestroyResourceStorage( destroyList[i] );
}
return result;
}
unsigned int CDataManagerBase::Purge( unsigned int nBytesToPurge )
{
unsigned int nTargetSize = MemUsed_Inline() - nBytesToPurge;
// Check for underflow
if ( MemUsed_Inline() < nBytesToPurge )
nTargetSize = 0;
unsigned int nImpliedCapacity = MemTotal_Inline() - nTargetSize;
return EnsureCapacity( nImpliedCapacity );
}
void CDataManagerBase::DestroyResource( memhandle_t handle )
{
Lock();
unsigned short index = FromHandle( handle );
if ( !m_memoryLists.IsValidIndex(index) )
{
Unlock();
return;
}
Assert( m_memoryLists[index].lockCount == 0 );
if ( m_memoryLists[index].lockCount )
BreakLock( handle );
m_memoryLists.Unlink( m_lruList, index );
void *p = GetForFreeByIndex( index );
Unlock();
DestroyResourceStorage( p );
}
void *CDataManagerBase::LockResource( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lruList, memoryIndex );
m_memoryLists.LinkToTail( m_lockList, memoryIndex );
}
Assert(m_memoryLists[memoryIndex].lockCount != (unsigned short)-1);
m_memoryLists[memoryIndex].lockCount++;
return m_memoryLists[memoryIndex].pStore;
}
return NULL;
}
int CDataManagerBase::UnlockResource( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
Assert( m_memoryLists[memoryIndex].lockCount > 0 );
if ( m_memoryLists[memoryIndex].lockCount > 0 )
{
m_memoryLists[memoryIndex].lockCount--;
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lockList, memoryIndex );
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
}
}
return m_memoryLists[memoryIndex].lockCount;
}
return 0;
}
void *CDataManagerBase::GetResource_NoLockNoLRUTouch( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
return m_memoryLists[memoryIndex].pStore;
}
return NULL;
}
void *CDataManagerBase::GetResource_NoLock( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
TouchByIndex( memoryIndex );
return m_memoryLists[memoryIndex].pStore;
}
return NULL;
}
void CDataManagerBase::TouchResource( memhandle_t handle )
{
AUTO_LOCK_DM();
TouchByIndex( FromHandle(handle) );
}
void CDataManagerBase::MarkAsStale( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lruList, memoryIndex );
m_memoryLists.LinkToHead( m_lruList, memoryIndex );
}
}
}
int CDataManagerBase::BreakLock( memhandle_t handle )
{
AUTO_LOCK_DM();
unsigned short memoryIndex = FromHandle(handle);
if ( memoryIndex != m_memoryLists.InvalidIndex() && m_memoryLists[memoryIndex].lockCount )
{
int nBroken = m_memoryLists[memoryIndex].lockCount;
m_memoryLists[memoryIndex].lockCount = 0;
m_memoryLists.Unlink( m_lockList, memoryIndex );
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
return nBroken;
}
return 0;
}
int CDataManagerBase::BreakAllLocks()
{
AUTO_LOCK_DM();
int nBroken = 0;
int node;
int nextNode;
node = m_memoryLists.Head(m_lockList);
while ( node != m_memoryLists.InvalidIndex() )
{
nBroken++;
nextNode = m_memoryLists.Next(node);
m_memoryLists[node].lockCount = 0;
m_memoryLists.Unlink( m_lockList, node );
m_memoryLists.LinkToTail( m_lruList, node );
node = nextNode;
}
return nBroken;
}
unsigned short CDataManagerBase::CreateHandle( bool bCreateLocked )
{
AUTO_LOCK_DM();
int memoryIndex = m_memoryLists.Head(m_freeList);
unsigned short list = ( bCreateLocked ) ? m_lockList : m_lruList;
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
m_memoryLists.Unlink( m_freeList, memoryIndex );
m_memoryLists.LinkToTail( list, memoryIndex );
}
else
{
memoryIndex = m_memoryLists.AddToTail( list );
}
if ( bCreateLocked )
{
m_memoryLists[memoryIndex].lockCount++;
}
return memoryIndex;
}
memhandle_t CDataManagerBase::StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize )
{
AUTO_LOCK_DM();
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
mem.pStore = pStore;
m_memUsed += realSize;
return ToHandle(memoryIndex);
}
void CDataManagerBase::TouchByIndex( unsigned short memoryIndex )
{
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
if ( m_memoryLists[memoryIndex].lockCount == 0 )
{
m_memoryLists.Unlink( m_lruList, memoryIndex );
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
}
}
}
memhandle_t CDataManagerBase::ToHandle( unsigned short index )
{
unsigned int hiword = m_memoryLists.Element(index).serial;
hiword <<= 16;
index++;
return (memhandle_t)( hiword|index );
}
unsigned int CDataManagerBase::TargetSize()
{
return MemTotal_Inline();
}
unsigned int CDataManagerBase::AvailableSize()
{
return MemAvailable_Inline();
}
unsigned int CDataManagerBase::UsedSize()
{
return MemUsed_Inline();
}
// free resources until there is enough space to hold "size"
unsigned int CDataManagerBase::EnsureCapacity( unsigned int size )
{
unsigned nBytesInitial = MemUsed_Inline();
while ( MemUsed_Inline() > MemTotal_Inline() || MemAvailable_Inline() < size )
{
Lock();
int lruIndex = m_memoryLists.Head( m_lruList );
if ( lruIndex == m_memoryLists.InvalidIndex() )
{
Unlock();
break;
}
m_memoryLists.Unlink( m_lruList, lruIndex );
void *p = GetForFreeByIndex( lruIndex );
Unlock();
DestroyResourceStorage( p );
}
return ( nBytesInitial - MemUsed_Inline() );
}
// free this resource and move the handle to the free list
void *CDataManagerBase::GetForFreeByIndex( unsigned short memoryIndex )
{
void *p = NULL;
if ( memoryIndex != m_memoryLists.InvalidIndex() )
{
Assert( m_memoryLists[memoryIndex].lockCount == 0 );
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
unsigned size = GetRealSize( mem.pStore );
if ( size > m_memUsed )
{
ExecuteOnce( Warning( "Data manager 'used' memory incorrect\n" ) );
size = m_memUsed;
}
m_memUsed -= size;
p = mem.pStore;
mem.pStore = NULL;
mem.serial++;
m_memoryLists.LinkToTail( m_freeList, memoryIndex );
}
return p;
}
// get a list of everything in the LRU
void CDataManagerBase::GetLRUHandleList( CUtlVector< memhandle_t >& list )
{
for ( int node = m_memoryLists.Tail(m_lruList);
node != m_memoryLists.InvalidIndex();
node = m_memoryLists.Previous(node) )
{
list.AddToTail( ToHandle( node ) );
}
}
// get a list of everything locked
void CDataManagerBase::GetLockHandleList( CUtlVector< memhandle_t >& list )
{
for ( int node = m_memoryLists.Head(m_lockList);
node != m_memoryLists.InvalidIndex();
node = m_memoryLists.Next(node) )
{
list.AddToTail( ToHandle( node ) );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,497 +1,497 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A collection of utility classes to simplify file I/O, and
// as much as possible contain portability problems. Here avoiding
// including windows.h.
//
//=============================================================================
#if defined(_WIN32)
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0502 // ReadDirectoryChangesW
#endif
#if defined(OSX)
#include <CoreServices/CoreServices.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/time.h>
#endif
#define ASYNC_FILEIO
#if defined( LINUX )
// Linux hasn't got a good AIO library that we have found yet, so lets punt for now
#undef ASYNC_FILEIO
#endif
#if defined(_WIN32)
//#include <direct.h>
#include <io.h>
// unset to force to use stdio implementation
#define WIN32_FILEIO
#if defined(ASYNC_FILEIO)
#if defined(_WIN32) && !defined(WIN32_FILEIO)
#error "trying to use async io without win32 filesystem API usage, that isn't doable"
#endif
#endif
#else /* not defined (_WIN32) */
#include <utime.h>
#include <dirent.h>
#include <unistd.h> // for unlink
#include <limits.h> // defines PATH_MAX
#include <alloca.h> // 'cause we like smashing the stack
#if defined( _PS3 )
#include <fcntl.h>
#else
#include <sys/fcntl.h>
#include <sys/statvfs.h>
#endif
#include <sched.h>
#define int64 int64_t
#define _A_SUBDIR S_IFDIR
// FUTURE map _A_HIDDEN via checking filename against .*
#define _A_HIDDEN 0
// FUTURE check 'read only' by checking mode against S_IRUSR
#define _A_RDONLY 0
// no files under posix are 'system' or 'archive'
#define _A_SYSTEM 0
#define _A_ARCH 0
#endif
#include "tier1/fileio.h"
#include "tier1/utlbuffer.h"
#include "tier1/strtools.h"
#include <errno.h>
#if defined( WIN32_FILEIO )
#include "winlite.h"
#endif
#if defined( ASYNC_FILEIO )
#ifdef _WIN32
#include "winlite.h"
#elif defined(_PS3)
// bugbug ps3 - see some aio files under libfs.. skipping for the moment
#elif defined(POSIX)
#include <aio.h>
#else
#error "aio please"
#endif
#endif
//-----------------------------------------------------------------------------
// Purpose: Constructor from UTF8
//-----------------------------------------------------------------------------
CPathString::CPathString( const char *pchUTF8Path )
{
// Need to first turn into an absolute path, so \\?\ pre-pended paths will be ok
m_pchUTF8Path = new char[ MAX_UNICODE_PATH_IN_UTF8 ];
m_pwchWideCharPathPrepended = NULL;
// First, convert to absolute path, which also does Q_FixSlashes for us.
Q_MakeAbsolutePath( m_pchUTF8Path, MAX_UNICODE_PATH * 4, pchUTF8Path );
// Second, fix any double slashes
V_FixDoubleSlashes( m_pchUTF8Path );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CPathString::~CPathString()
{
if ( m_pwchWideCharPathPrepended )
{
delete[] m_pwchWideCharPathPrepended;
m_pwchWideCharPathPrepended = NULL;
}
if ( m_pchUTF8Path )
{
delete[] m_pchUTF8Path;
m_pchUTF8Path = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Access UTF8 path
//-----------------------------------------------------------------------------
const char * CPathString::GetUTF8Path()
{
return m_pchUTF8Path;
}
//-----------------------------------------------------------------------------
// Purpose: Gets wchar_t based path, with \\?\ pre-pended (allowing long paths
// on Win32, should only be used with unicode extended path aware filesystem calls)
//-----------------------------------------------------------------------------
const wchar_t *CPathString::GetWCharPathPrePended()
{
PopulateWCharPath();
return m_pwchWideCharPathPrepended;
}
//-----------------------------------------------------------------------------
// Purpose: Builds wchar path string
//-----------------------------------------------------------------------------
void CPathString::PopulateWCharPath()
{
if ( m_pwchWideCharPathPrepended )
return;
// Check if the UTF8 path starts with \\, which on Win32 means it's a UNC path, and then needs a different prefix
if ( m_pchUTF8Path[0] == '\\' && m_pchUTF8Path[1] == '\\' )
{
m_pwchWideCharPathPrepended = new wchar_t[MAX_UNICODE_PATH+8];
Q_memcpy( m_pwchWideCharPathPrepended, L"\\\\?\\UNC\\", 8*sizeof(wchar_t) );
#ifdef DBGFLAG_ASSERT
int cchResult =
#endif
Q_UTF8ToUnicode( m_pchUTF8Path+2, m_pwchWideCharPathPrepended+8, MAX_UNICODE_PATH*sizeof(wchar_t) );
Assert( cchResult );
// Be sure we NULL terminate within our allocated region incase Q_UTF8ToUnicode failed, though we're already in bad shape then.
m_pwchWideCharPathPrepended[MAX_UNICODE_PATH+7] = 0;
}
else
{
m_pwchWideCharPathPrepended = new wchar_t[MAX_UNICODE_PATH+4];
Q_memcpy( m_pwchWideCharPathPrepended, L"\\\\?\\", 4*sizeof(wchar_t) );
#ifdef DBGFLAG_ASSERT
int cchResult =
#endif
Q_UTF8ToUnicode( m_pchUTF8Path, m_pwchWideCharPathPrepended+4, MAX_UNICODE_PATH*sizeof(wchar_t) );
Assert( cchResult );
// Be sure we NULL terminate within our allocated region incase Q_UTF8ToUnicode failed, though we're already in bad shape then.
m_pwchWideCharPathPrepended[MAX_UNICODE_PATH+3] = 0;
}
}
#ifdef WIN32
struct DirWatcherOverlapped : public OVERLAPPED
{
CDirWatcher *m_pDirWatcher;
};
#endif
#if !defined(_PS3) && !defined(_X360)
// a buffer full of file names
static const int k_cubDirWatchBufferSize = 8 * 1024;
//-----------------------------------------------------------------------------
// Purpose: directory watching
//-----------------------------------------------------------------------------
CDirWatcher::CDirWatcher()
{
m_hFile = NULL;
m_pOverlapped = NULL;
m_pFileInfo = NULL;
#ifdef OSX
m_WatcherStream = 0;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: directory watching
//-----------------------------------------------------------------------------
CDirWatcher::~CDirWatcher()
{
#ifdef WIN32
if ( m_pOverlapped )
{
// mark the overlapped structure as gone
DirWatcherOverlapped *pDirWatcherOverlapped = (DirWatcherOverlapped *)m_pOverlapped;
pDirWatcherOverlapped->m_pDirWatcher = NULL;
}
if ( m_hFile )
{
// make sure we flush any pending I/O's on the handle
::CancelIo( m_hFile );
::SleepEx( 0, TRUE );
// close the handle
::CloseHandle( m_hFile );
}
#elif defined(OSX)
if ( m_WatcherStream )
{
FSEventStreamStop( (FSEventStreamRef)m_WatcherStream );
FSEventStreamInvalidate( (FSEventStreamRef)m_WatcherStream );
FSEventStreamRelease( (FSEventStreamRef)m_WatcherStream );
m_WatcherStream = 0;
}
#endif
if ( m_pFileInfo )
{
free( m_pFileInfo );
}
if ( m_pOverlapped )
{
free( m_pOverlapped );
}
}
#ifdef WIN32
//-----------------------------------------------------------------------------
// Purpose: callback watch
// gets called on the same thread whenever a SleepEx() occurs
//-----------------------------------------------------------------------------
class CDirWatcherFriend
{
public:
static void WINAPI DirWatchCallback( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, OVERLAPPED *pOverlapped )
{
DirWatcherOverlapped *pDirWatcherOverlapped = (DirWatcherOverlapped *)pOverlapped;
// see if we've been cancelled
if ( !pDirWatcherOverlapped->m_pDirWatcher )
return;
// parse and pass back
if ( dwNumberOfBytesTransfered > sizeof(FILE_NOTIFY_INFORMATION) )
{
FILE_NOTIFY_INFORMATION *pFileNotifyInformation = (FILE_NOTIFY_INFORMATION *)pDirWatcherOverlapped->m_pDirWatcher->m_pFileInfo;
do
{
// null terminate the string and turn it to UTF-8
int cNumWChars = pFileNotifyInformation->FileNameLength / sizeof(wchar_t);
wchar_t *pwchT = new wchar_t[cNumWChars + 1];
memcpy( pwchT, pFileNotifyInformation->FileName, pFileNotifyInformation->FileNameLength );
pwchT[cNumWChars] = 0;
CStrAutoEncode strAutoEncode( pwchT );
// add it to our list
pDirWatcherOverlapped->m_pDirWatcher->AddFileToChangeList( strAutoEncode.ToString() );
delete[] pwchT;
if ( pFileNotifyInformation->NextEntryOffset == 0 )
break;
// move to the next file
pFileNotifyInformation = (FILE_NOTIFY_INFORMATION *)(((byte*)pFileNotifyInformation) + pFileNotifyInformation->NextEntryOffset);
} while ( 1 );
}
// watch again
pDirWatcherOverlapped->m_pDirWatcher->PostDirWatch();
}
};
#elif defined(OSX)
void CheckDirectoryForChanges( const char *path_buff, CDirWatcher *pDirWatch, bool bRecurse )
{
DIR *dir = opendir(path_buff);
char fullpath[MAX_PATH];
struct dirent *dirent;
struct timespec ts = { 0, 0 };
bool bTimeSet = false;
while ( (dirent = readdir(dir)) != NULL )
{
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
continue;
snprintf( fullpath, PATH_MAX, "%s/%s", path_buff, dirent->d_name );
struct stat st;
if (lstat(fullpath, &st) != 0)
continue;
if ( S_ISDIR(st.st_mode) && bRecurse )
{
CheckDirectoryForChanges( fullpath, pDirWatch, bRecurse );
}
else if ( st.st_mtimespec.tv_sec > pDirWatch->m_modTime.tv_sec ||
( st.st_mtimespec.tv_sec == pDirWatch->m_modTime.tv_sec && st.st_mtimespec.tv_nsec > pDirWatch->m_modTime.tv_nsec ) )
{
ts = st.st_mtimespec;
bTimeSet = true;
// the win32 size only sends up the dir relative to the watching dir, so replicate that here
pDirWatch->AddFileToChangeList( fullpath + pDirWatch->m_BaseDir.Length() + 1 );
}
}
if ( bTimeSet )
pDirWatch->m_modTime = ts;
closedir(dir);
}
static void fsevents_callback( ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents,void *eventPaths,
const FSEventStreamEventFlags eventMasks[], const FSEventStreamEventId eventIDs[] )
{
char path_buff[PATH_MAX];
for (int i=0; i < numEvents; i++)
{
char **paths = (char **)eventPaths;
strcpy(path_buff, paths[i]);
int len = strlen(path_buff);
if (path_buff[len-1] == '/')
{
// chop off a trailing slash
path_buff[--len] = '\0';
}
bool bRecurse = false;
if (eventMasks[i] & kFSEventStreamEventFlagMustScanSubDirs
|| eventMasks[i] & kFSEventStreamEventFlagUserDropped
|| eventMasks[i] & kFSEventStreamEventFlagKernelDropped)
{
bRecurse = true;
}
CDirWatcher *pDirWatch = (CDirWatcher *)clientCallBackInfo;
// make sure its in our subdir
if ( !V_strnicmp( path_buff, pDirWatch->m_BaseDir.String(), pDirWatch->m_BaseDir.Length() ) )
CheckDirectoryForChanges( path_buff, pDirWatch, bRecurse );
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose: only one directory can be watched at a time
//-----------------------------------------------------------------------------
void CDirWatcher::SetDirToWatch( const char *pchDir )
{
if ( !pchDir || !*pchDir )
return;
CPathString strPath( pchDir );
#ifdef WIN32
// open the directory
m_hFile = ::CreateFileW( strPath.GetWCharPathPrePended(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_BACKUP_SEMANTICS, NULL );
// create our buffers
m_pFileInfo = malloc( k_cubDirWatchBufferSize );
m_pOverlapped = malloc( sizeof( DirWatcherOverlapped ) );
// post a watch
PostDirWatch();
#elif defined(OSX)
CFStringRef mypath = CFStringCreateWithCString( NULL, strPath.GetUTF8Path(), kCFStringEncodingMacRoman );
if ( !mypath )
{
Assert( !"Failed to CFStringCreateWithCString watcher path" );
return;
}
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
FSEventStreamContext callbackInfo = {0, this, NULL, NULL, NULL};
CFAbsoluteTime latency = 1.0; // Latency in seconds
m_WatcherStream = (void *)FSEventStreamCreate(NULL,
&fsevents_callback,
&callbackInfo,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
latency,
kFSEventStreamCreateFlagNoDefer
);
FSEventStreamScheduleWithRunLoop( (FSEventStreamRef)m_WatcherStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(pathsToWatch );
CFRelease( mypath );
FSEventStreamStart( (FSEventStreamRef)m_WatcherStream );
char szFullPath[MAX_PATH];
Q_MakeAbsolutePath( szFullPath, sizeof(szFullPath), pchDir );
m_BaseDir = szFullPath;
struct timeval tv;
gettimeofday( &tv, NULL );
TIMEVAL_TO_TIMESPEC( &tv, &m_modTime );
#else
Assert( !"Impl me" );
#endif
}
#ifdef WIN32
//-----------------------------------------------------------------------------
// Purpose: used by callback functions to push a file onto the list
//-----------------------------------------------------------------------------
void CDirWatcher::PostDirWatch()
{
memset( m_pOverlapped, 0, sizeof(DirWatcherOverlapped) );
DirWatcherOverlapped *pDirWatcherOverlapped = (DirWatcherOverlapped *)m_pOverlapped;
pDirWatcherOverlapped->m_pDirWatcher = this;
DWORD dwBytes;
::ReadDirectoryChangesW( m_hFile, m_pFileInfo, k_cubDirWatchBufferSize, TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME, &dwBytes, (OVERLAPPED *)m_pOverlapped, &CDirWatcherFriend::DirWatchCallback );
}
#endif
//-----------------------------------------------------------------------------
// Purpose: used by callback functions to push a file onto the list
//-----------------------------------------------------------------------------
void CDirWatcher::AddFileToChangeList( const char *pchFile )
{
// make sure it isn't already in the list
FOR_EACH_LL( m_listChangedFiles, i )
{
if ( !Q_stricmp( m_listChangedFiles[i], pchFile ) )
return;
}
m_listChangedFiles.AddToTail( pchFile );
}
//-----------------------------------------------------------------------------
// Purpose: retrieve any changes
//-----------------------------------------------------------------------------
bool CDirWatcher::GetChangedFile( CUtlString *psFile )
{
#ifdef WIN32
// this will trigger any pending directory reads
// this does get hit other places in the code; so the callback can happen at any time
::SleepEx( 0, TRUE );
#endif
if ( !m_listChangedFiles.Count() )
return false;
*psFile = m_listChangedFiles[m_listChangedFiles.Head()];
m_listChangedFiles.Remove( m_listChangedFiles.Head() );
return true;
}
#ifdef DBGFLAG_VALIDATE
void CDirWatcher::Validate( CValidator &validator, const char *pchName )
{
VALIDATE_SCOPE();
validator.ClaimMemory( m_pOverlapped );
validator.ClaimMemory( m_pFileInfo );
ValidateObj( m_listChangedFiles );
FOR_EACH_LL( m_listChangedFiles, i )
{
ValidateObj( m_listChangedFiles[i] );
}
}
#endif
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A collection of utility classes to simplify file I/O, and
// as much as possible contain portability problems. Here avoiding
// including windows.h.
//
//=============================================================================
#if defined(_WIN32)
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0502 // ReadDirectoryChangesW
#endif
#if defined(OSX)
#include <CoreServices/CoreServices.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/time.h>
#endif
#define ASYNC_FILEIO
#if defined( LINUX )
// Linux hasn't got a good AIO library that we have found yet, so lets punt for now
#undef ASYNC_FILEIO
#endif
#if defined(_WIN32)
//#include <direct.h>
#include <io.h>
// unset to force to use stdio implementation
#define WIN32_FILEIO
#if defined(ASYNC_FILEIO)
#if defined(_WIN32) && !defined(WIN32_FILEIO)
#error "trying to use async io without win32 filesystem API usage, that isn't doable"
#endif
#endif
#else /* not defined (_WIN32) */
#include <utime.h>
#include <dirent.h>
#include <unistd.h> // for unlink
#include <limits.h> // defines PATH_MAX
#include <alloca.h> // 'cause we like smashing the stack
#if defined( _PS3 )
#include <fcntl.h>
#else
#include <sys/fcntl.h>
#include <sys/statvfs.h>
#endif
#include <sched.h>
#define int64 int64_t
#define _A_SUBDIR S_IFDIR
// FUTURE map _A_HIDDEN via checking filename against .*
#define _A_HIDDEN 0
// FUTURE check 'read only' by checking mode against S_IRUSR
#define _A_RDONLY 0
// no files under posix are 'system' or 'archive'
#define _A_SYSTEM 0
#define _A_ARCH 0
#endif
#include "tier1/fileio.h"
#include "tier1/utlbuffer.h"
#include "tier1/strtools.h"
#include <errno.h>
#if defined( WIN32_FILEIO )
#include "winlite.h"
#endif
#if defined( ASYNC_FILEIO )
#ifdef _WIN32
#include "winlite.h"
#elif defined(_PS3)
// bugbug ps3 - see some aio files under libfs.. skipping for the moment
#elif defined(POSIX)
#include <aio.h>
#else
#error "aio please"
#endif
#endif
//-----------------------------------------------------------------------------
// Purpose: Constructor from UTF8
//-----------------------------------------------------------------------------
CPathString::CPathString( const char *pchUTF8Path )
{
// Need to first turn into an absolute path, so \\?\ pre-pended paths will be ok
m_pchUTF8Path = new char[ MAX_UNICODE_PATH_IN_UTF8 ];
m_pwchWideCharPathPrepended = NULL;
// First, convert to absolute path, which also does Q_FixSlashes for us.
Q_MakeAbsolutePath( m_pchUTF8Path, MAX_UNICODE_PATH * 4, pchUTF8Path );
// Second, fix any double slashes
V_FixDoubleSlashes( m_pchUTF8Path );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CPathString::~CPathString()
{
if ( m_pwchWideCharPathPrepended )
{
delete[] m_pwchWideCharPathPrepended;
m_pwchWideCharPathPrepended = NULL;
}
if ( m_pchUTF8Path )
{
delete[] m_pchUTF8Path;
m_pchUTF8Path = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: Access UTF8 path
//-----------------------------------------------------------------------------
const char * CPathString::GetUTF8Path()
{
return m_pchUTF8Path;
}
//-----------------------------------------------------------------------------
// Purpose: Gets wchar_t based path, with \\?\ pre-pended (allowing long paths
// on Win32, should only be used with unicode extended path aware filesystem calls)
//-----------------------------------------------------------------------------
const wchar_t *CPathString::GetWCharPathPrePended()
{
PopulateWCharPath();
return m_pwchWideCharPathPrepended;
}
//-----------------------------------------------------------------------------
// Purpose: Builds wchar path string
//-----------------------------------------------------------------------------
void CPathString::PopulateWCharPath()
{
if ( m_pwchWideCharPathPrepended )
return;
// Check if the UTF8 path starts with \\, which on Win32 means it's a UNC path, and then needs a different prefix
if ( m_pchUTF8Path[0] == '\\' && m_pchUTF8Path[1] == '\\' )
{
m_pwchWideCharPathPrepended = new wchar_t[MAX_UNICODE_PATH+8];
Q_memcpy( m_pwchWideCharPathPrepended, L"\\\\?\\UNC\\", 8*sizeof(wchar_t) );
#ifdef DBGFLAG_ASSERT
int cchResult =
#endif
Q_UTF8ToUnicode( m_pchUTF8Path+2, m_pwchWideCharPathPrepended+8, MAX_UNICODE_PATH*sizeof(wchar_t) );
Assert( cchResult );
// Be sure we NULL terminate within our allocated region incase Q_UTF8ToUnicode failed, though we're already in bad shape then.
m_pwchWideCharPathPrepended[MAX_UNICODE_PATH+7] = 0;
}
else
{
m_pwchWideCharPathPrepended = new wchar_t[MAX_UNICODE_PATH+4];
Q_memcpy( m_pwchWideCharPathPrepended, L"\\\\?\\", 4*sizeof(wchar_t) );
#ifdef DBGFLAG_ASSERT
int cchResult =
#endif
Q_UTF8ToUnicode( m_pchUTF8Path, m_pwchWideCharPathPrepended+4, MAX_UNICODE_PATH*sizeof(wchar_t) );
Assert( cchResult );
// Be sure we NULL terminate within our allocated region incase Q_UTF8ToUnicode failed, though we're already in bad shape then.
m_pwchWideCharPathPrepended[MAX_UNICODE_PATH+3] = 0;
}
}
#ifdef WIN32
struct DirWatcherOverlapped : public OVERLAPPED
{
CDirWatcher *m_pDirWatcher;
};
#endif
#if !defined(_PS3) && !defined(_X360)
// a buffer full of file names
static const int k_cubDirWatchBufferSize = 8 * 1024;
//-----------------------------------------------------------------------------
// Purpose: directory watching
//-----------------------------------------------------------------------------
CDirWatcher::CDirWatcher()
{
m_hFile = NULL;
m_pOverlapped = NULL;
m_pFileInfo = NULL;
#ifdef OSX
m_WatcherStream = 0;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: directory watching
//-----------------------------------------------------------------------------
CDirWatcher::~CDirWatcher()
{
#ifdef WIN32
if ( m_pOverlapped )
{
// mark the overlapped structure as gone
DirWatcherOverlapped *pDirWatcherOverlapped = (DirWatcherOverlapped *)m_pOverlapped;
pDirWatcherOverlapped->m_pDirWatcher = NULL;
}
if ( m_hFile )
{
// make sure we flush any pending I/O's on the handle
::CancelIo( m_hFile );
::SleepEx( 0, TRUE );
// close the handle
::CloseHandle( m_hFile );
}
#elif defined(OSX)
if ( m_WatcherStream )
{
FSEventStreamStop( (FSEventStreamRef)m_WatcherStream );
FSEventStreamInvalidate( (FSEventStreamRef)m_WatcherStream );
FSEventStreamRelease( (FSEventStreamRef)m_WatcherStream );
m_WatcherStream = 0;
}
#endif
if ( m_pFileInfo )
{
free( m_pFileInfo );
}
if ( m_pOverlapped )
{
free( m_pOverlapped );
}
}
#ifdef WIN32
//-----------------------------------------------------------------------------
// Purpose: callback watch
// gets called on the same thread whenever a SleepEx() occurs
//-----------------------------------------------------------------------------
class CDirWatcherFriend
{
public:
static void WINAPI DirWatchCallback( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, OVERLAPPED *pOverlapped )
{
DirWatcherOverlapped *pDirWatcherOverlapped = (DirWatcherOverlapped *)pOverlapped;
// see if we've been cancelled
if ( !pDirWatcherOverlapped->m_pDirWatcher )
return;
// parse and pass back
if ( dwNumberOfBytesTransfered > sizeof(FILE_NOTIFY_INFORMATION) )
{
FILE_NOTIFY_INFORMATION *pFileNotifyInformation = (FILE_NOTIFY_INFORMATION *)pDirWatcherOverlapped->m_pDirWatcher->m_pFileInfo;
do
{
// null terminate the string and turn it to UTF-8
int cNumWChars = pFileNotifyInformation->FileNameLength / sizeof(wchar_t);
wchar_t *pwchT = new wchar_t[cNumWChars + 1];
memcpy( pwchT, pFileNotifyInformation->FileName, pFileNotifyInformation->FileNameLength );
pwchT[cNumWChars] = 0;
CStrAutoEncode strAutoEncode( pwchT );
// add it to our list
pDirWatcherOverlapped->m_pDirWatcher->AddFileToChangeList( strAutoEncode.ToString() );
delete[] pwchT;
if ( pFileNotifyInformation->NextEntryOffset == 0 )
break;
// move to the next file
pFileNotifyInformation = (FILE_NOTIFY_INFORMATION *)(((byte*)pFileNotifyInformation) + pFileNotifyInformation->NextEntryOffset);
} while ( 1 );
}
// watch again
pDirWatcherOverlapped->m_pDirWatcher->PostDirWatch();
}
};
#elif defined(OSX)
void CheckDirectoryForChanges( const char *path_buff, CDirWatcher *pDirWatch, bool bRecurse )
{
DIR *dir = opendir(path_buff);
char fullpath[MAX_PATH];
struct dirent *dirent;
struct timespec ts = { 0, 0 };
bool bTimeSet = false;
while ( (dirent = readdir(dir)) != NULL )
{
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
continue;
snprintf( fullpath, PATH_MAX, "%s/%s", path_buff, dirent->d_name );
struct stat st;
if (lstat(fullpath, &st) != 0)
continue;
if ( S_ISDIR(st.st_mode) && bRecurse )
{
CheckDirectoryForChanges( fullpath, pDirWatch, bRecurse );
}
else if ( st.st_mtimespec.tv_sec > pDirWatch->m_modTime.tv_sec ||
( st.st_mtimespec.tv_sec == pDirWatch->m_modTime.tv_sec && st.st_mtimespec.tv_nsec > pDirWatch->m_modTime.tv_nsec ) )
{
ts = st.st_mtimespec;
bTimeSet = true;
// the win32 size only sends up the dir relative to the watching dir, so replicate that here
pDirWatch->AddFileToChangeList( fullpath + pDirWatch->m_BaseDir.Length() + 1 );
}
}
if ( bTimeSet )
pDirWatch->m_modTime = ts;
closedir(dir);
}
static void fsevents_callback( ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents,void *eventPaths,
const FSEventStreamEventFlags eventMasks[], const FSEventStreamEventId eventIDs[] )
{
char path_buff[PATH_MAX];
for (int i=0; i < numEvents; i++)
{
char **paths = (char **)eventPaths;
strcpy(path_buff, paths[i]);
int len = strlen(path_buff);
if (path_buff[len-1] == '/')
{
// chop off a trailing slash
path_buff[--len] = '\0';
}
bool bRecurse = false;
if (eventMasks[i] & kFSEventStreamEventFlagMustScanSubDirs
|| eventMasks[i] & kFSEventStreamEventFlagUserDropped
|| eventMasks[i] & kFSEventStreamEventFlagKernelDropped)
{
bRecurse = true;
}
CDirWatcher *pDirWatch = (CDirWatcher *)clientCallBackInfo;
// make sure its in our subdir
if ( !V_strnicmp( path_buff, pDirWatch->m_BaseDir.String(), pDirWatch->m_BaseDir.Length() ) )
CheckDirectoryForChanges( path_buff, pDirWatch, bRecurse );
}
}
#endif
//-----------------------------------------------------------------------------
// Purpose: only one directory can be watched at a time
//-----------------------------------------------------------------------------
void CDirWatcher::SetDirToWatch( const char *pchDir )
{
if ( !pchDir || !*pchDir )
return;
CPathString strPath( pchDir );
#ifdef WIN32
// open the directory
m_hFile = ::CreateFileW( strPath.GetWCharPathPrePended(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_BACKUP_SEMANTICS, NULL );
// create our buffers
m_pFileInfo = malloc( k_cubDirWatchBufferSize );
m_pOverlapped = malloc( sizeof( DirWatcherOverlapped ) );
// post a watch
PostDirWatch();
#elif defined(OSX)
CFStringRef mypath = CFStringCreateWithCString( NULL, strPath.GetUTF8Path(), kCFStringEncodingMacRoman );
if ( !mypath )
{
Assert( !"Failed to CFStringCreateWithCString watcher path" );
return;
}
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
FSEventStreamContext callbackInfo = {0, this, NULL, NULL, NULL};
CFAbsoluteTime latency = 1.0; // Latency in seconds
m_WatcherStream = (void *)FSEventStreamCreate(NULL,
&fsevents_callback,
&callbackInfo,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
latency,
kFSEventStreamCreateFlagNoDefer
);
FSEventStreamScheduleWithRunLoop( (FSEventStreamRef)m_WatcherStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(pathsToWatch );
CFRelease( mypath );
FSEventStreamStart( (FSEventStreamRef)m_WatcherStream );
char szFullPath[MAX_PATH];
Q_MakeAbsolutePath( szFullPath, sizeof(szFullPath), pchDir );
m_BaseDir = szFullPath;
struct timeval tv;
gettimeofday( &tv, NULL );
TIMEVAL_TO_TIMESPEC( &tv, &m_modTime );
#else
Assert( !"Impl me" );
#endif
}
#ifdef WIN32
//-----------------------------------------------------------------------------
// Purpose: used by callback functions to push a file onto the list
//-----------------------------------------------------------------------------
void CDirWatcher::PostDirWatch()
{
memset( m_pOverlapped, 0, sizeof(DirWatcherOverlapped) );
DirWatcherOverlapped *pDirWatcherOverlapped = (DirWatcherOverlapped *)m_pOverlapped;
pDirWatcherOverlapped->m_pDirWatcher = this;
DWORD dwBytes;
::ReadDirectoryChangesW( m_hFile, m_pFileInfo, k_cubDirWatchBufferSize, TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME, &dwBytes, (OVERLAPPED *)m_pOverlapped, &CDirWatcherFriend::DirWatchCallback );
}
#endif
//-----------------------------------------------------------------------------
// Purpose: used by callback functions to push a file onto the list
//-----------------------------------------------------------------------------
void CDirWatcher::AddFileToChangeList( const char *pchFile )
{
// make sure it isn't already in the list
FOR_EACH_LL( m_listChangedFiles, i )
{
if ( !Q_stricmp( m_listChangedFiles[i], pchFile ) )
return;
}
m_listChangedFiles.AddToTail( pchFile );
}
//-----------------------------------------------------------------------------
// Purpose: retrieve any changes
//-----------------------------------------------------------------------------
bool CDirWatcher::GetChangedFile( CUtlString *psFile )
{
#ifdef WIN32
// this will trigger any pending directory reads
// this does get hit other places in the code; so the callback can happen at any time
::SleepEx( 0, TRUE );
#endif
if ( !m_listChangedFiles.Count() )
return false;
*psFile = m_listChangedFiles[m_listChangedFiles.Head()];
m_listChangedFiles.Remove( m_listChangedFiles.Head() );
return true;
}
#ifdef DBGFLAG_VALIDATE
void CDirWatcher::Validate( CValidator &validator, const char *pchName )
{
VALIDATE_SCOPE();
validator.ClaimMemory( m_pOverlapped );
validator.ClaimMemory( m_pFileInfo );
ValidateObj( m_listChangedFiles );
FOR_EACH_LL( m_listChangedFiles, i )
{
ValidateObj( m_listChangedFiles[i] );
}
}
#endif
#endif // _PS3 || _X360

View File

@@ -1,437 +1,437 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Variant Pearson Hash general purpose hashing algorithm described
// by Cargill in C++ Report 1994. Generates a 16-bit result.
//
//=============================================================================
#include <stdlib.h>
#include "tier0/basetypes.h"
#include "tier0/platform.h"
#include "generichash.h"
#include <ctype.h>
#include "tier0/dbg.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
// Table of randomly shuffled values from 0-255 generated by:
//
//-----------------------------------------------------------------------------
/*
void MakeRandomValues()
{
int i, j, r;
unsigned t;
srand( 0xdeadbeef );
for ( i = 0; i < 256; i++ )
{
g_nRandomValues[i] = (unsigned )i;
}
for (j = 0; j < 8; j++)
{
for (i = 0; i < 256; i++)
{
r = rand() & 0xff;
t = g_nRandomValues[i];
g_nRandomValues[i] = g_nRandomValues[r];
g_nRandomValues[r] = t;
}
}
printf("static unsigned g_nRandomValues[256] =\n{\n");
for (i = 0; i < 256; i += 16)
{
printf("\t");
for (j = 0; j < 16; j++)
printf(" %3d,", g_nRandomValues[i+j]);
printf("\n");
}
printf("};\n");
}
*/
static unsigned g_nRandomValues[256] =
{
238, 164, 191, 168, 115, 16, 142, 11, 213, 214, 57, 151, 248, 252, 26, 198,
13, 105, 102, 25, 43, 42, 227, 107, 210, 251, 86, 66, 83, 193, 126, 108,
131, 3, 64, 186, 192, 81, 37, 158, 39, 244, 14, 254, 75, 30, 2, 88,
172, 176, 255, 69, 0, 45, 116, 139, 23, 65, 183, 148, 33, 46, 203, 20,
143, 205, 60, 197, 118, 9, 171, 51, 233, 135, 220, 49, 71, 184, 82, 109,
36, 161, 169, 150, 63, 96, 173, 125, 113, 67, 224, 78, 232, 215, 35, 219,
79, 181, 41, 229, 149, 153, 111, 217, 21, 72, 120, 163, 133, 40, 122, 140,
208, 231, 211, 200, 160, 182, 104, 110, 178, 237, 15, 101, 27, 50, 24, 189,
177, 130, 187, 92, 253, 136, 100, 212, 19, 174, 70, 22, 170, 206, 162, 74,
247, 5, 47, 32, 179, 117, 132, 195, 124, 123, 245, 128, 236, 223, 12, 84,
54, 218, 146, 228, 157, 94, 106, 31, 17, 29, 194, 34, 56, 134, 239, 246,
241, 216, 127, 98, 7, 204, 154, 152, 209, 188, 48, 61, 87, 97, 225, 85,
90, 167, 155, 112, 145, 114, 141, 93, 250, 4, 201, 156, 38, 89, 226, 196,
1, 235, 44, 180, 159, 121, 119, 166, 190, 144, 10, 91, 76, 230, 221, 80,
207, 55, 58, 53, 175, 8, 6, 52, 68, 242, 18, 222, 103, 249, 147, 129,
138, 243, 28, 185, 62, 59, 240, 202, 234, 99, 77, 73, 199, 137, 95, 165,
};
//-----------------------------------------------------------------------------
// String
//-----------------------------------------------------------------------------
unsigned FASTCALL HashString( const char *pszKey )
{
const uint8 *k = (const uint8 *)pszKey;
unsigned even = 0,
odd = 0,
n;
while ((n = *k++) != 0)
{
even = g_nRandomValues[odd ^ n];
if ((n = *k++) != 0)
odd = g_nRandomValues[even ^ n];
else
break;
}
return (even << 8) | odd ;
}
//-----------------------------------------------------------------------------
// Case-insensitive string
//-----------------------------------------------------------------------------
unsigned FASTCALL HashStringCaseless( const char *pszKey )
{
const uint8 *k = (const uint8 *) pszKey;
unsigned even = 0,
odd = 0,
n;
while ((n = toupper(*k++)) != 0)
{
even = g_nRandomValues[odd ^ n];
if ((n = toupper(*k++)) != 0)
odd = g_nRandomValues[even ^ n];
else
break;
}
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 32 bit conventional case-insensitive string
//-----------------------------------------------------------------------------
unsigned FASTCALL HashStringCaselessConventional( const char *pszKey )
{
unsigned hash = 0xAAAAAAAA; // Alternating 1's and 0's to maximize the effect of the later multiply and add
for( ; *pszKey ; pszKey++ )
{
hash = ( ( hash << 5 ) + hash ) + (uint8)tolower(*pszKey);
}
return hash;
}
//-----------------------------------------------------------------------------
// int hash
//-----------------------------------------------------------------------------
unsigned FASTCALL HashInt( const int n )
{
register unsigned even, odd;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 4-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash4( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 8-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash8( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+1);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 12-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash12( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+1);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+2);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 16-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash16( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+1);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+2);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+3);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// Arbitrary fixed length hash
//-----------------------------------------------------------------------------
unsigned FASTCALL HashBlock( const void *pKey, unsigned size )
{
const uint8 * k = (const uint8 *) pKey;
unsigned even = 0,
odd = 0,
n;
while (size)
{
--size;
n = *k++;
even = g_nRandomValues[odd ^ n];
if (size)
{
--size;
n = *k++;
odd = g_nRandomValues[even ^ n];
}
else
break;
}
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// Murmur hash
//-----------------------------------------------------------------------------
uint32 MurmurHash2( const void * key, int len, uint32 seed )
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const uint32 m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
uint32 h = seed ^ len;
// Mix 4 bytes at a time into the hash
const unsigned char * data = (const unsigned char *)key;
while(len >= 4)
{
uint32 k = LittleDWord( *(uint32 *)data );
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
#define TOLOWERU( c ) ( ( uint32 ) ( ( ( c >= 'A' ) && ( c <= 'Z' ) )? c + 32 : c ) )
uint32 MurmurHash2LowerCase( char const *pString, uint32 nSeed )
{
int nLen = strlen( pString );
char *p = ( char * ) stackalloc( nLen + 1 );
for( int i = 0; i < nLen ; i++ )
{
p[i] = TOLOWERU( pString[i] );
}
return MurmurHash2( p, nLen, nSeed );
}
//-----------------------------------------------------------------------------
// Murmur hash, 64 bit- endian neutral
//-----------------------------------------------------------------------------
uint64 MurmurHash64( const void * key, int len, uint32 seed )
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const uint32 m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
uint32 h1 = seed ^ len;
uint32 h2 = 0;
// Mix 4 bytes at a time into the hash
const uint32 * data = (const uint32 *)key;
while ( len >= 8 )
{
uint32 k1 = LittleDWord( *data++ );
k1 *= m; k1 ^= k1 >> r; k1 *= m;
h1 *= m; h1 ^= k1;
len -= 4;
uint32 k2 = LittleDWord( *data++ );
k2 *= m; k2 ^= k2 >> r; k2 *= m;
h2 *= m; h2 ^= k2;
len -= 4;
}
if(len >= 4)
{
uint32 k1 = LittleDWord( *data++ );
k1 *= m; k1 ^= k1 >> r; k1 *= m;
h1 *= m; h1 ^= k1;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len)
{
case 3: h2 ^= ((uint8*)data)[2] << 16;
case 2: h2 ^= ((uint8*)data)[1] << 8;
case 1: h2 ^= ((uint8*)data)[0];
h2 *= m;
};
h1 ^= h2 >> 18; h1 *= m;
h2 ^= h1 >> 22; h2 *= m;
h1 ^= h2 >> 17; h1 *= m;
h2 ^= h1 >> 19; h2 *= m;
uint64 h = h1;
h = (h << 32) | h2;
return h;
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Variant Pearson Hash general purpose hashing algorithm described
// by Cargill in C++ Report 1994. Generates a 16-bit result.
//
//=============================================================================
#include <stdlib.h>
#include "tier0/basetypes.h"
#include "tier0/platform.h"
#include "generichash.h"
#include <ctype.h>
#include "tier0/dbg.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
// Table of randomly shuffled values from 0-255 generated by:
//
//-----------------------------------------------------------------------------
/*
void MakeRandomValues()
{
int i, j, r;
unsigned t;
srand( 0xdeadbeef );
for ( i = 0; i < 256; i++ )
{
g_nRandomValues[i] = (unsigned )i;
}
for (j = 0; j < 8; j++)
{
for (i = 0; i < 256; i++)
{
r = rand() & 0xff;
t = g_nRandomValues[i];
g_nRandomValues[i] = g_nRandomValues[r];
g_nRandomValues[r] = t;
}
}
printf("static unsigned g_nRandomValues[256] =\n{\n");
for (i = 0; i < 256; i += 16)
{
printf("\t");
for (j = 0; j < 16; j++)
printf(" %3d,", g_nRandomValues[i+j]);
printf("\n");
}
printf("};\n");
}
*/
static unsigned g_nRandomValues[256] =
{
238, 164, 191, 168, 115, 16, 142, 11, 213, 214, 57, 151, 248, 252, 26, 198,
13, 105, 102, 25, 43, 42, 227, 107, 210, 251, 86, 66, 83, 193, 126, 108,
131, 3, 64, 186, 192, 81, 37, 158, 39, 244, 14, 254, 75, 30, 2, 88,
172, 176, 255, 69, 0, 45, 116, 139, 23, 65, 183, 148, 33, 46, 203, 20,
143, 205, 60, 197, 118, 9, 171, 51, 233, 135, 220, 49, 71, 184, 82, 109,
36, 161, 169, 150, 63, 96, 173, 125, 113, 67, 224, 78, 232, 215, 35, 219,
79, 181, 41, 229, 149, 153, 111, 217, 21, 72, 120, 163, 133, 40, 122, 140,
208, 231, 211, 200, 160, 182, 104, 110, 178, 237, 15, 101, 27, 50, 24, 189,
177, 130, 187, 92, 253, 136, 100, 212, 19, 174, 70, 22, 170, 206, 162, 74,
247, 5, 47, 32, 179, 117, 132, 195, 124, 123, 245, 128, 236, 223, 12, 84,
54, 218, 146, 228, 157, 94, 106, 31, 17, 29, 194, 34, 56, 134, 239, 246,
241, 216, 127, 98, 7, 204, 154, 152, 209, 188, 48, 61, 87, 97, 225, 85,
90, 167, 155, 112, 145, 114, 141, 93, 250, 4, 201, 156, 38, 89, 226, 196,
1, 235, 44, 180, 159, 121, 119, 166, 190, 144, 10, 91, 76, 230, 221, 80,
207, 55, 58, 53, 175, 8, 6, 52, 68, 242, 18, 222, 103, 249, 147, 129,
138, 243, 28, 185, 62, 59, 240, 202, 234, 99, 77, 73, 199, 137, 95, 165,
};
//-----------------------------------------------------------------------------
// String
//-----------------------------------------------------------------------------
unsigned FASTCALL HashString( const char *pszKey )
{
const uint8 *k = (const uint8 *)pszKey;
unsigned even = 0,
odd = 0,
n;
while ((n = *k++) != 0)
{
even = g_nRandomValues[odd ^ n];
if ((n = *k++) != 0)
odd = g_nRandomValues[even ^ n];
else
break;
}
return (even << 8) | odd ;
}
//-----------------------------------------------------------------------------
// Case-insensitive string
//-----------------------------------------------------------------------------
unsigned FASTCALL HashStringCaseless( const char *pszKey )
{
const uint8 *k = (const uint8 *) pszKey;
unsigned even = 0,
odd = 0,
n;
while ((n = toupper(*k++)) != 0)
{
even = g_nRandomValues[odd ^ n];
if ((n = toupper(*k++)) != 0)
odd = g_nRandomValues[even ^ n];
else
break;
}
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 32 bit conventional case-insensitive string
//-----------------------------------------------------------------------------
unsigned FASTCALL HashStringCaselessConventional( const char *pszKey )
{
unsigned hash = 0xAAAAAAAA; // Alternating 1's and 0's to maximize the effect of the later multiply and add
for( ; *pszKey ; pszKey++ )
{
hash = ( ( hash << 5 ) + hash ) + (uint8)tolower(*pszKey);
}
return hash;
}
//-----------------------------------------------------------------------------
// int hash
//-----------------------------------------------------------------------------
unsigned FASTCALL HashInt( const int n )
{
register unsigned even, odd;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 4-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash4( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 8-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash8( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+1);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 12-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash12( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+1);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+2);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// 16-byte hash
//-----------------------------------------------------------------------------
unsigned FASTCALL Hash16( const void *pKey )
{
register const uint32 * p = (const uint32 *) pKey;
register unsigned even,
odd,
n;
n = *p;
even = g_nRandomValues[n & 0xff];
odd = g_nRandomValues[((n >> 8) & 0xff)];
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ (n >> 16) & 0xff];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+1);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+2);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
n = *(p+3);
even = g_nRandomValues[odd ^ (n >> 24)];
odd = g_nRandomValues[even ^ ((n >> 16) & 0xff)];
even = g_nRandomValues[odd ^ ((n >> 8) & 0xff)];
odd = g_nRandomValues[even ^ (n & 0xff)];
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// Arbitrary fixed length hash
//-----------------------------------------------------------------------------
unsigned FASTCALL HashBlock( const void *pKey, unsigned size )
{
const uint8 * k = (const uint8 *) pKey;
unsigned even = 0,
odd = 0,
n;
while (size)
{
--size;
n = *k++;
even = g_nRandomValues[odd ^ n];
if (size)
{
--size;
n = *k++;
odd = g_nRandomValues[even ^ n];
}
else
break;
}
return (even << 8) | odd;
}
//-----------------------------------------------------------------------------
// Murmur hash
//-----------------------------------------------------------------------------
uint32 MurmurHash2( const void * key, int len, uint32 seed )
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const uint32 m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
uint32 h = seed ^ len;
// Mix 4 bytes at a time into the hash
const unsigned char * data = (const unsigned char *)key;
while(len >= 4)
{
uint32 k = LittleDWord( *(uint32 *)data );
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m;
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return h;
}
#define TOLOWERU( c ) ( ( uint32 ) ( ( ( c >= 'A' ) && ( c <= 'Z' ) )? c + 32 : c ) )
uint32 MurmurHash2LowerCase( char const *pString, uint32 nSeed )
{
int nLen = strlen( pString );
char *p = ( char * ) stackalloc( nLen + 1 );
for( int i = 0; i < nLen ; i++ )
{
p[i] = TOLOWERU( pString[i] );
}
return MurmurHash2( p, nLen, nSeed );
}
//-----------------------------------------------------------------------------
// Murmur hash, 64 bit- endian neutral
//-----------------------------------------------------------------------------
uint64 MurmurHash64( const void * key, int len, uint32 seed )
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const uint32 m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
uint32 h1 = seed ^ len;
uint32 h2 = 0;
// Mix 4 bytes at a time into the hash
const uint32 * data = (const uint32 *)key;
while ( len >= 8 )
{
uint32 k1 = LittleDWord( *data++ );
k1 *= m; k1 ^= k1 >> r; k1 *= m;
h1 *= m; h1 ^= k1;
len -= 4;
uint32 k2 = LittleDWord( *data++ );
k2 *= m; k2 ^= k2 >> r; k2 *= m;
h2 *= m; h2 ^= k2;
len -= 4;
}
if(len >= 4)
{
uint32 k1 = LittleDWord( *data++ );
k1 *= m; k1 ^= k1 >> r; k1 *= m;
h1 *= m; h1 ^= k1;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len)
{
case 3: h2 ^= ((uint8*)data)[2] << 16;
case 2: h2 ^= ((uint8*)data)[1] << 8;
case 1: h2 ^= ((uint8*)data)[0];
h2 *= m;
};
h1 ^= h2 >> 18; h1 *= m;
h2 ^= h1 >> 22; h2 *= m;
h1 ^= h2 >> 17; h1 *= m;
h2 ^= h1 >> 19; h2 *= m;
uint64 h = h1;
h = (h << 32) | h2;
return h;
}

View File

@@ -1,259 +1,259 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
#if defined( WIN32 ) && !defined( _X360 )
#include <windows.h>
#elif defined( POSIX )
#include <iconv.h>
#endif
#include "tier1/ilocalize.h"
#include "utlstring.h"
#pragma warning( disable: 4018 ) // '<' : signed/unsigned mismatch
//-----------------------------------------------------------------------------
// Purpose: converts an english string to unicode
//-----------------------------------------------------------------------------
int ILocalize::ConvertANSIToUnicode(const char *ansi, wchar_t *unicode, int unicodeBufferSizeInBytes)
{
#ifdef POSIX
return Q_UTF8ToUnicode(ansi, unicode, unicodeBufferSizeInBytes);
#else
int chars = MultiByteToWideChar(CP_UTF8, 0, ansi, -1, unicode, unicodeBufferSizeInBytes / sizeof(wchar_t));
unicode[(unicodeBufferSizeInBytes / sizeof(wchar_t)) - 1] = 0;
return chars;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: converts an unicode string to an english string
//-----------------------------------------------------------------------------
int ILocalize::ConvertUnicodeToANSI(const wchar_t *unicode, char *ansi, int ansiBufferSize)
{
#ifdef POSIX
return Q_UnicodeToUTF8(unicode, ansi, ansiBufferSize);
#else
int result = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, ansi, ansiBufferSize, NULL, NULL);
ansi[ansiBufferSize - 1] = 0;
return result;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: construct string helper
//-----------------------------------------------------------------------------
template < typename T >
void ConstructStringVArgsInternal_Impl(T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, va_list argList)
{
static const int k_cMaxFormatStringArguments = 9; // We only look one character ahead and start at %s1
Assert( numFormatParameters <= k_cMaxFormatStringArguments );
// Safety check
if ( unicodeOutput == NULL || unicodeBufferSizeInBytes < 1 )
{
return;
}
if ( !formatString || numFormatParameters > k_cMaxFormatStringArguments )
{
unicodeOutput[0] = 0;
return;
}
int unicodeBufferSize = unicodeBufferSizeInBytes / sizeof(T);
const T *searchPos = formatString;
T *outputPos = unicodeOutput;
T *argParams[k_cMaxFormatStringArguments];
for ( int i = 0; i < numFormatParameters; i++ )
{
argParams[i] = va_arg( argList, T* );
}
//assumes we can't have %s10
//assume both are 0 terminated?
int formatLength = StringFuncs<T>::Length( formatString );
while ( searchPos[0] != '\0' && unicodeBufferSize > 1 )
{
if ( formatLength >= 3 && searchPos[0] == '%' && searchPos[1] == 's' )
{
//this is an escape sequence - %s1, %s2 etc, up to %s9
int argindex = ( searchPos[2] ) - '0' - 1; // 0 for %s1, 1 for %s2, etc.
if ( argindex < 0 || argindex > k_cMaxFormatStringArguments )
{
Warning( "Bad format string in CLocalizeStringTable::ConstructString\n" );
*outputPos = '\0';
return;
}
if ( argindex < numFormatParameters )
{
T const *param = argParams[argindex];
if ( param == NULL )
param = StringFuncs<T>::NullDebugString();
int paramSize = StringFuncs<T>::Length(param);
if (paramSize >= unicodeBufferSize)
{
paramSize = unicodeBufferSize - 1;
}
memcpy(outputPos, param, paramSize * sizeof(T));
unicodeBufferSize -= paramSize;
outputPos += paramSize;
searchPos += 3;
formatLength -= 3;
}
else
{
AssertMsg( argindex < numFormatParameters, "ConstructStringVArgsInternal_Impl() - Found a %s# escape sequence whose index was more than the number of args." );
//copy it over, char by char
*outputPos = *searchPos;
outputPos++;
unicodeBufferSize--;
searchPos++;
formatLength--;
}
}
else
{
//copy it over, char by char
*outputPos = *searchPos;
outputPos++;
unicodeBufferSize--;
searchPos++;
formatLength--;
}
}
// ensure null termination
Assert( outputPos - unicodeOutput < unicodeBufferSizeInBytes/sizeof(T) );
*outputPos = L'\0';
}
void ILocalize::ConstructStringVArgsInternal(char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, int numFormatParameters, va_list argList)
{
ConstructStringVArgsInternal_Impl<char>( unicodeOutput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
}
void ILocalize::ConstructStringVArgsInternal(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, int numFormatParameters, va_list argList)
{
ConstructStringVArgsInternal_Impl<wchar_t>( unicodeOutput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
}
//-----------------------------------------------------------------------------
// Purpose: construct string helper
//-----------------------------------------------------------------------------
template < typename T >
const T *GetTypedKeyValuesString( KeyValues *pKeyValues, const char *pKeyName );
template < >
const char *GetTypedKeyValuesString<char>( KeyValues *pKeyValues, const char *pKeyName )
{
return pKeyValues->GetString( pKeyName, "[unknown]" );
}
template < >
const wchar_t *GetTypedKeyValuesString<wchar_t>( KeyValues *pKeyValues, const char *pKeyName )
{
return pKeyValues->GetWString( pKeyName, L"[unknown]" );
}
template < typename T >
void ConstructStringKeyValuesInternal_Impl( T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, KeyValues *localizationVariables )
{
T *outputPos = unicodeOutput;
//assumes we can't have %s10
//assume both are 0 terminated?
int unicodeBufferSize = unicodeBufferSizeInBytes / sizeof(T);
while ( *formatString != '\0' && unicodeBufferSize > 1 )
{
bool shouldAdvance = true;
if ( *formatString == '%' )
{
// this is an escape sequence that specifies a variable name
if ( formatString[1] == 's' && formatString[2] >= '0' && formatString[2] <= '9' )
{
// old style escape sequence, ignore
}
else if ( formatString[1] == '%' )
{
// just a '%' char, just write the second one
formatString++;
}
else if ( localizationVariables )
{
// get out the variable name
const T *varStart = formatString + 1;
const T *varEnd = StringFuncs<T>::FindChar( varStart, '%' );
if ( varEnd && *varEnd == '%' )
{
shouldAdvance = false;
// assume variable names must be ascii, do a quick convert
char variableName[32];
char *vset = variableName;
for ( const T *pws = varStart; pws < varEnd && (vset < variableName + sizeof(variableName) - 1); ++pws, ++vset )
{
*vset = (char)*pws;
}
*vset = 0;
// look up the variable name
const T *value = GetTypedKeyValuesString<T>( localizationVariables, variableName );
int paramSize = StringFuncs<T>::Length( value );
if (paramSize >= unicodeBufferSize)
{
paramSize = MAX( 0, unicodeBufferSize - 1 );
}
StringFuncs<T>::Copy( outputPos, value, paramSize );
unicodeBufferSize -= paramSize;
outputPos += paramSize;
formatString = varEnd + 1;
}
}
}
if (shouldAdvance)
{
//copy it over, char by char
*outputPos = *formatString;
outputPos++;
unicodeBufferSize--;
formatString++;
}
}
// ensure null termination
*outputPos = '\0';
}
void ILocalize::ConstructStringKeyValuesInternal(char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, KeyValues *localizationVariables)
{
ConstructStringKeyValuesInternal_Impl<char>( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
}
void ILocalize::ConstructStringKeyValuesInternal(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, KeyValues *localizationVariables)
{
ConstructStringKeyValuesInternal_Impl<wchar_t>( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
//========= Copyright Valve Corporation, All rights reserved. ============//
#if defined( WIN32 ) && !defined( _X360 )
#include <windows.h>
#elif defined( POSIX )
#include <iconv.h>
#endif
#include "tier1/ilocalize.h"
#include "utlstring.h"
#pragma warning( disable: 4018 ) // '<' : signed/unsigned mismatch
//-----------------------------------------------------------------------------
// Purpose: converts an english string to unicode
//-----------------------------------------------------------------------------
int ILocalize::ConvertANSIToUnicode(const char *ansi, wchar_t *unicode, int unicodeBufferSizeInBytes)
{
#ifdef POSIX
return Q_UTF8ToUnicode(ansi, unicode, unicodeBufferSizeInBytes);
#else
int chars = MultiByteToWideChar(CP_UTF8, 0, ansi, -1, unicode, unicodeBufferSizeInBytes / sizeof(wchar_t));
unicode[(unicodeBufferSizeInBytes / sizeof(wchar_t)) - 1] = 0;
return chars;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: converts an unicode string to an english string
//-----------------------------------------------------------------------------
int ILocalize::ConvertUnicodeToANSI(const wchar_t *unicode, char *ansi, int ansiBufferSize)
{
#ifdef POSIX
return Q_UnicodeToUTF8(unicode, ansi, ansiBufferSize);
#else
int result = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, ansi, ansiBufferSize, NULL, NULL);
ansi[ansiBufferSize - 1] = 0;
return result;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: construct string helper
//-----------------------------------------------------------------------------
template < typename T >
void ConstructStringVArgsInternal_Impl(T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, int numFormatParameters, va_list argList)
{
static const int k_cMaxFormatStringArguments = 9; // We only look one character ahead and start at %s1
Assert( numFormatParameters <= k_cMaxFormatStringArguments );
// Safety check
if ( unicodeOutput == NULL || unicodeBufferSizeInBytes < 1 )
{
return;
}
if ( !formatString || numFormatParameters > k_cMaxFormatStringArguments )
{
unicodeOutput[0] = 0;
return;
}
int unicodeBufferSize = unicodeBufferSizeInBytes / sizeof(T);
const T *searchPos = formatString;
T *outputPos = unicodeOutput;
T *argParams[k_cMaxFormatStringArguments];
for ( int i = 0; i < numFormatParameters; i++ )
{
argParams[i] = va_arg( argList, T* );
}
//assumes we can't have %s10
//assume both are 0 terminated?
int formatLength = StringFuncs<T>::Length( formatString );
while ( searchPos[0] != '\0' && unicodeBufferSize > 1 )
{
if ( formatLength >= 3 && searchPos[0] == '%' && searchPos[1] == 's' )
{
//this is an escape sequence - %s1, %s2 etc, up to %s9
int argindex = ( searchPos[2] ) - '0' - 1; // 0 for %s1, 1 for %s2, etc.
if ( argindex < 0 || argindex > k_cMaxFormatStringArguments )
{
Warning( "Bad format string in CLocalizeStringTable::ConstructString\n" );
*outputPos = '\0';
return;
}
if ( argindex < numFormatParameters )
{
T const *param = argParams[argindex];
if ( param == NULL )
param = StringFuncs<T>::NullDebugString();
int paramSize = StringFuncs<T>::Length(param);
if (paramSize >= unicodeBufferSize)
{
paramSize = unicodeBufferSize - 1;
}
memcpy(outputPos, param, paramSize * sizeof(T));
unicodeBufferSize -= paramSize;
outputPos += paramSize;
searchPos += 3;
formatLength -= 3;
}
else
{
AssertMsg( argindex < numFormatParameters, "ConstructStringVArgsInternal_Impl() - Found a %s# escape sequence whose index was more than the number of args." );
//copy it over, char by char
*outputPos = *searchPos;
outputPos++;
unicodeBufferSize--;
searchPos++;
formatLength--;
}
}
else
{
//copy it over, char by char
*outputPos = *searchPos;
outputPos++;
unicodeBufferSize--;
searchPos++;
formatLength--;
}
}
// ensure null termination
Assert( outputPos - unicodeOutput < unicodeBufferSizeInBytes/sizeof(T) );
*outputPos = L'\0';
}
void ILocalize::ConstructStringVArgsInternal(char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, int numFormatParameters, va_list argList)
{
ConstructStringVArgsInternal_Impl<char>( unicodeOutput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
}
void ILocalize::ConstructStringVArgsInternal(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, int numFormatParameters, va_list argList)
{
ConstructStringVArgsInternal_Impl<wchar_t>( unicodeOutput, unicodeBufferSizeInBytes, formatString, numFormatParameters, argList );
}
//-----------------------------------------------------------------------------
// Purpose: construct string helper
//-----------------------------------------------------------------------------
template < typename T >
const T *GetTypedKeyValuesString( KeyValues *pKeyValues, const char *pKeyName );
template < >
const char *GetTypedKeyValuesString<char>( KeyValues *pKeyValues, const char *pKeyName )
{
return pKeyValues->GetString( pKeyName, "[unknown]" );
}
template < >
const wchar_t *GetTypedKeyValuesString<wchar_t>( KeyValues *pKeyValues, const char *pKeyName )
{
return pKeyValues->GetWString( pKeyName, L"[unknown]" );
}
template < typename T >
void ConstructStringKeyValuesInternal_Impl( T *unicodeOutput, int unicodeBufferSizeInBytes, const T *formatString, KeyValues *localizationVariables )
{
T *outputPos = unicodeOutput;
//assumes we can't have %s10
//assume both are 0 terminated?
int unicodeBufferSize = unicodeBufferSizeInBytes / sizeof(T);
while ( *formatString != '\0' && unicodeBufferSize > 1 )
{
bool shouldAdvance = true;
if ( *formatString == '%' )
{
// this is an escape sequence that specifies a variable name
if ( formatString[1] == 's' && formatString[2] >= '0' && formatString[2] <= '9' )
{
// old style escape sequence, ignore
}
else if ( formatString[1] == '%' )
{
// just a '%' char, just write the second one
formatString++;
}
else if ( localizationVariables )
{
// get out the variable name
const T *varStart = formatString + 1;
const T *varEnd = StringFuncs<T>::FindChar( varStart, '%' );
if ( varEnd && *varEnd == '%' )
{
shouldAdvance = false;
// assume variable names must be ascii, do a quick convert
char variableName[32];
char *vset = variableName;
for ( const T *pws = varStart; pws < varEnd && (vset < variableName + sizeof(variableName) - 1); ++pws, ++vset )
{
*vset = (char)*pws;
}
*vset = 0;
// look up the variable name
const T *value = GetTypedKeyValuesString<T>( localizationVariables, variableName );
int paramSize = StringFuncs<T>::Length( value );
if (paramSize >= unicodeBufferSize)
{
paramSize = MAX( 0, unicodeBufferSize - 1 );
}
StringFuncs<T>::Copy( outputPos, value, paramSize );
unicodeBufferSize -= paramSize;
outputPos += paramSize;
formatString = varEnd + 1;
}
}
}
if (shouldAdvance)
{
//copy it over, char by char
*outputPos = *formatString;
outputPos++;
unicodeBufferSize--;
formatString++;
}
}
// ensure null termination
*outputPos = '\0';
}
void ILocalize::ConstructStringKeyValuesInternal(char *unicodeOutput, int unicodeBufferSizeInBytes, const char *formatString, KeyValues *localizationVariables)
{
ConstructStringKeyValuesInternal_Impl<char>( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
}
void ILocalize::ConstructStringKeyValuesInternal(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, KeyValues *localizationVariables)
{
ConstructStringKeyValuesInternal_Impl<wchar_t>( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables );
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,274 +1,274 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Contains a branch-neutral binary packer for KeyValues trees.
//
// $NoKeywords: $
//
//=============================================================================//
#include <KeyValues.h>
#include "kvpacker.h"
#include "tier0/dbg.h"
#include "utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#define KEYVALUES_TOKEN_SIZE 1024
// writes KeyValue as binary data to buffer
bool KVPacker::WriteAsBinary( KeyValues *pNode, CUtlBuffer &buffer )
{
if ( buffer.IsText() ) // must be a binary buffer
return false;
if ( !buffer.IsValid() ) // must be valid, no overflows etc
return false;
// Write subkeys:
// loop through all our peers
for ( KeyValues *dat = pNode; dat != NULL; dat = dat->GetNextKey() )
{
// write type
switch ( dat->GetDataType() )
{
case KeyValues::TYPE_NONE:
{
buffer.PutUnsignedChar( PACKTYPE_NONE );
break;
}
case KeyValues::TYPE_STRING:
{
buffer.PutUnsignedChar( PACKTYPE_STRING );
break;
}
case KeyValues::TYPE_WSTRING:
{
buffer.PutUnsignedChar( PACKTYPE_WSTRING );
break;
}
case KeyValues::TYPE_INT:
{
buffer.PutUnsignedChar( PACKTYPE_INT );
break;
}
case KeyValues::TYPE_UINT64:
{
buffer.PutUnsignedChar( PACKTYPE_UINT64 );
break;
}
case KeyValues::TYPE_FLOAT:
{
buffer.PutUnsignedChar( PACKTYPE_FLOAT );
break;
}
case KeyValues::TYPE_COLOR:
{
buffer.PutUnsignedChar( PACKTYPE_COLOR );
break;
}
case KeyValues::TYPE_PTR:
{
buffer.PutUnsignedChar( PACKTYPE_PTR );
break;
}
default:
break;
}
// write name
buffer.PutString( dat->GetName() );
// write value
switch ( dat->GetDataType() )
{
case KeyValues::TYPE_NONE:
{
if( !WriteAsBinary( dat->GetFirstSubKey(), buffer ) )
return false;
break;
}
case KeyValues::TYPE_STRING:
{
if (dat->GetString() && *(dat->GetString()))
{
buffer.PutString( dat->GetString() );
}
else
{
buffer.PutString( "" );
}
break;
}
case KeyValues::TYPE_WSTRING:
{
int nLength = dat->GetWString() ? Q_wcslen( dat->GetWString() ) : 0;
buffer.PutShort( nLength );
for( int k = 0; k < nLength; ++ k )
{
buffer.PutShort( ( unsigned short ) dat->GetWString()[k] );
}
break;
}
case KeyValues::TYPE_INT:
{
buffer.PutInt( dat->GetInt() );
break;
}
case KeyValues::TYPE_UINT64:
{
buffer.PutInt64( dat->GetUint64() );
break;
}
case KeyValues::TYPE_FLOAT:
{
buffer.PutFloat( dat->GetFloat() );
break;
}
case KeyValues::TYPE_COLOR:
{
Color color = dat->GetColor();
buffer.PutUnsignedChar( color[0] );
buffer.PutUnsignedChar( color[1] );
buffer.PutUnsignedChar( color[2] );
buffer.PutUnsignedChar( color[3] );
break;
}
case KeyValues::TYPE_PTR:
{
buffer.PutUnsignedInt( (int)dat->GetPtr() );
break;
}
default:
break;
}
}
// write tail, marks end of peers
buffer.PutUnsignedChar( PACKTYPE_NULLMARKER );
return buffer.IsValid();
}
// read KeyValues from binary buffer, returns true if parsing was successful
bool KVPacker::ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer )
{
if ( buffer.IsText() ) // must be a binary buffer
return false;
if ( !buffer.IsValid() ) // must be valid, no overflows etc
return false;
pNode->Clear();
char token[KEYVALUES_TOKEN_SIZE];
KeyValues *dat = pNode;
EPackType ePackType = (EPackType)buffer.GetUnsignedChar();
// loop through all our peers
while ( true )
{
if ( ePackType == PACKTYPE_NULLMARKER )
break; // no more peers
buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 );
token[KEYVALUES_TOKEN_SIZE-1] = 0;
dat->SetName( token );
switch ( ePackType )
{
case PACKTYPE_NONE:
{
KeyValues *pNewNode = new KeyValues("");
dat->AddSubKey( pNewNode );
if( !ReadAsBinary( pNewNode, buffer ) )
return false;
break;
}
case PACKTYPE_STRING:
{
buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 );
token[KEYVALUES_TOKEN_SIZE-1] = 0;
dat->SetStringValue( token );
break;
}
case PACKTYPE_WSTRING:
{
int nLength = buffer.GetShort();
wchar_t *pTemp = (wchar_t *)stackalloc( sizeof(wchar_t) * ( 1 + nLength ) );
for( int k = 0; k < nLength; ++ k )
{
pTemp[k] = buffer.GetShort();
}
pTemp[ nLength ] = 0;
dat->SetWString( NULL, pTemp );
break;
}
case PACKTYPE_INT:
{
dat->SetInt( NULL, buffer.GetInt() );
break;
}
case PACKTYPE_UINT64:
{
dat->SetUint64( NULL, (uint64)buffer.GetInt64() );
break;
}
case PACKTYPE_FLOAT:
{
dat->SetFloat( NULL, buffer.GetFloat() );
break;
}
case PACKTYPE_COLOR:
{
Color color(
buffer.GetUnsignedChar(),
buffer.GetUnsignedChar(),
buffer.GetUnsignedChar(),
buffer.GetUnsignedChar() );
dat->SetColor( NULL, color );
break;
}
case PACKTYPE_PTR:
{
dat->SetPtr( NULL, (void*)buffer.GetUnsignedInt() );
break;
}
default:
break;
}
if ( !buffer.IsValid() ) // error occured
return false;
ePackType = (EPackType)buffer.GetUnsignedChar();
if ( ePackType == PACKTYPE_NULLMARKER )
break;
// new peer follows
KeyValues *pNewPeer = new KeyValues("");
dat->SetNextKey( pNewPeer );
dat = pNewPeer;
}
return buffer.IsValid();
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Contains a branch-neutral binary packer for KeyValues trees.
//
// $NoKeywords: $
//
//=============================================================================//
#include <KeyValues.h>
#include "kvpacker.h"
#include "tier0/dbg.h"
#include "utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
#define KEYVALUES_TOKEN_SIZE 1024
// writes KeyValue as binary data to buffer
bool KVPacker::WriteAsBinary( KeyValues *pNode, CUtlBuffer &buffer )
{
if ( buffer.IsText() ) // must be a binary buffer
return false;
if ( !buffer.IsValid() ) // must be valid, no overflows etc
return false;
// Write subkeys:
// loop through all our peers
for ( KeyValues *dat = pNode; dat != NULL; dat = dat->GetNextKey() )
{
// write type
switch ( dat->GetDataType() )
{
case KeyValues::TYPE_NONE:
{
buffer.PutUnsignedChar( PACKTYPE_NONE );
break;
}
case KeyValues::TYPE_STRING:
{
buffer.PutUnsignedChar( PACKTYPE_STRING );
break;
}
case KeyValues::TYPE_WSTRING:
{
buffer.PutUnsignedChar( PACKTYPE_WSTRING );
break;
}
case KeyValues::TYPE_INT:
{
buffer.PutUnsignedChar( PACKTYPE_INT );
break;
}
case KeyValues::TYPE_UINT64:
{
buffer.PutUnsignedChar( PACKTYPE_UINT64 );
break;
}
case KeyValues::TYPE_FLOAT:
{
buffer.PutUnsignedChar( PACKTYPE_FLOAT );
break;
}
case KeyValues::TYPE_COLOR:
{
buffer.PutUnsignedChar( PACKTYPE_COLOR );
break;
}
case KeyValues::TYPE_PTR:
{
buffer.PutUnsignedChar( PACKTYPE_PTR );
break;
}
default:
break;
}
// write name
buffer.PutString( dat->GetName() );
// write value
switch ( dat->GetDataType() )
{
case KeyValues::TYPE_NONE:
{
if( !WriteAsBinary( dat->GetFirstSubKey(), buffer ) )
return false;
break;
}
case KeyValues::TYPE_STRING:
{
if (dat->GetString() && *(dat->GetString()))
{
buffer.PutString( dat->GetString() );
}
else
{
buffer.PutString( "" );
}
break;
}
case KeyValues::TYPE_WSTRING:
{
int nLength = dat->GetWString() ? Q_wcslen( dat->GetWString() ) : 0;
buffer.PutShort( nLength );
for( int k = 0; k < nLength; ++ k )
{
buffer.PutShort( ( unsigned short ) dat->GetWString()[k] );
}
break;
}
case KeyValues::TYPE_INT:
{
buffer.PutInt( dat->GetInt() );
break;
}
case KeyValues::TYPE_UINT64:
{
buffer.PutInt64( dat->GetUint64() );
break;
}
case KeyValues::TYPE_FLOAT:
{
buffer.PutFloat( dat->GetFloat() );
break;
}
case KeyValues::TYPE_COLOR:
{
Color color = dat->GetColor();
buffer.PutUnsignedChar( color[0] );
buffer.PutUnsignedChar( color[1] );
buffer.PutUnsignedChar( color[2] );
buffer.PutUnsignedChar( color[3] );
break;
}
case KeyValues::TYPE_PTR:
{
buffer.PutUnsignedInt( (int)dat->GetPtr() );
break;
}
default:
break;
}
}
// write tail, marks end of peers
buffer.PutUnsignedChar( PACKTYPE_NULLMARKER );
return buffer.IsValid();
}
// read KeyValues from binary buffer, returns true if parsing was successful
bool KVPacker::ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer )
{
if ( buffer.IsText() ) // must be a binary buffer
return false;
if ( !buffer.IsValid() ) // must be valid, no overflows etc
return false;
pNode->Clear();
char token[KEYVALUES_TOKEN_SIZE];
KeyValues *dat = pNode;
EPackType ePackType = (EPackType)buffer.GetUnsignedChar();
// loop through all our peers
while ( true )
{
if ( ePackType == PACKTYPE_NULLMARKER )
break; // no more peers
buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 );
token[KEYVALUES_TOKEN_SIZE-1] = 0;
dat->SetName( token );
switch ( ePackType )
{
case PACKTYPE_NONE:
{
KeyValues *pNewNode = new KeyValues("");
dat->AddSubKey( pNewNode );
if( !ReadAsBinary( pNewNode, buffer ) )
return false;
break;
}
case PACKTYPE_STRING:
{
buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 );
token[KEYVALUES_TOKEN_SIZE-1] = 0;
dat->SetStringValue( token );
break;
}
case PACKTYPE_WSTRING:
{
int nLength = buffer.GetShort();
wchar_t *pTemp = (wchar_t *)stackalloc( sizeof(wchar_t) * ( 1 + nLength ) );
for( int k = 0; k < nLength; ++ k )
{
pTemp[k] = buffer.GetShort();
}
pTemp[ nLength ] = 0;
dat->SetWString( NULL, pTemp );
break;
}
case PACKTYPE_INT:
{
dat->SetInt( NULL, buffer.GetInt() );
break;
}
case PACKTYPE_UINT64:
{
dat->SetUint64( NULL, (uint64)buffer.GetInt64() );
break;
}
case PACKTYPE_FLOAT:
{
dat->SetFloat( NULL, buffer.GetFloat() );
break;
}
case PACKTYPE_COLOR:
{
Color color(
buffer.GetUnsignedChar(),
buffer.GetUnsignedChar(),
buffer.GetUnsignedChar(),
buffer.GetUnsignedChar() );
dat->SetColor( NULL, color );
break;
}
case PACKTYPE_PTR:
{
dat->SetPtr( NULL, (void*)buffer.GetUnsignedInt() );
break;
}
default:
break;
}
if ( !buffer.IsValid() ) // error occured
return false;
ePackType = (EPackType)buffer.GetUnsignedChar();
if ( ePackType == PACKTYPE_NULLMARKER )
break;
// new peer follows
KeyValues *pNewPeer = new KeyValues("");
dat->SetNextKey( pNewPeer );
dat = pNewPeer;
}
return buffer.IsValid();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,312 +1,312 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "mempool.h"
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include "tier0/dbg.h"
#include <ctype.h>
#include "tier1/strtools.h"
// Should be last include
#include "tier0/memdbgon.h"
MemoryPoolReportFunc_t CUtlMemoryPool::g_ReportFunc = 0;
//-----------------------------------------------------------------------------
// Error reporting... (debug only)
//-----------------------------------------------------------------------------
void CUtlMemoryPool::SetErrorReportFunc( MemoryPoolReportFunc_t func )
{
g_ReportFunc = func;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CUtlMemoryPool::CUtlMemoryPool( int blockSize, int numElements, int growMode, const char *pszAllocOwner, int nAlignment )
{
#ifdef _X360
if( numElements > 0 && growMode != GROW_NONE )
{
numElements = 1;
}
#endif
m_nAlignment = ( nAlignment != 0 ) ? nAlignment : 1;
Assert( IsPowerOfTwo( m_nAlignment ) );
m_BlockSize = blockSize < sizeof(void*) ? sizeof(void*) : blockSize;
m_BlockSize = AlignValue( m_BlockSize, m_nAlignment );
m_BlocksPerBlob = numElements;
m_PeakAlloc = 0;
m_GrowMode = growMode;
if ( !pszAllocOwner )
{
pszAllocOwner = __FILE__;
}
m_pszAllocOwner = pszAllocOwner;
Init();
AddNewBlob();
}
//-----------------------------------------------------------------------------
// Purpose: Frees the memory contained in the mempool, and invalidates it for
// any further use.
// Input : *memPool - the mempool to shutdown
//-----------------------------------------------------------------------------
CUtlMemoryPool::~CUtlMemoryPool()
{
if (m_BlocksAllocated > 0)
{
ReportLeaks();
}
Clear();
}
//-----------------------------------------------------------------------------
// Resets the pool
//-----------------------------------------------------------------------------
void CUtlMemoryPool::Init()
{
m_NumBlobs = 0;
m_BlocksAllocated = 0;
m_pHeadOfFreeList = 0;
m_BlobHead.m_pNext = m_BlobHead.m_pPrev = &m_BlobHead;
}
//-----------------------------------------------------------------------------
// Frees everything
//-----------------------------------------------------------------------------
void CUtlMemoryPool::Clear()
{
// Free everything..
CBlob *pNext;
for( CBlob *pCur = m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur = pNext )
{
pNext = pCur->m_pNext;
free( pCur );
}
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Reports memory leaks
//-----------------------------------------------------------------------------
void CUtlMemoryPool::ReportLeaks()
{
if (!g_ReportFunc)
return;
g_ReportFunc("Memory leak: mempool blocks left in memory: %d\n", m_BlocksAllocated);
#ifdef _DEBUG
// walk and destroy the free list so it doesn't intefere in the scan
while (m_pHeadOfFreeList != NULL)
{
void *next = *((void**)m_pHeadOfFreeList);
memset(m_pHeadOfFreeList, 0, m_BlockSize);
m_pHeadOfFreeList = next;
}
g_ReportFunc("Dumping memory: \'");
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
{
// scan the memory block and dump the leaks
char *scanPoint = (char *)pCur->m_Data;
char *scanEnd = pCur->m_Data + pCur->m_NumBytes;
bool needSpace = false;
while (scanPoint < scanEnd)
{
// search for and dump any strings
if ((unsigned)(*scanPoint + 1) <= 256 && isprint(*scanPoint))
{
g_ReportFunc("%c", *scanPoint);
needSpace = true;
}
else if (needSpace)
{
needSpace = false;
g_ReportFunc(" ");
}
scanPoint++;
}
}
g_ReportFunc("\'\n");
#endif // _DEBUG
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CUtlMemoryPool::AddNewBlob()
{
MEM_ALLOC_CREDIT_(m_pszAllocOwner);
int sizeMultiplier;
if( m_GrowMode == GROW_SLOW )
{
sizeMultiplier = 1;
}
else
{
if ( m_GrowMode == GROW_NONE )
{
// Can only have one allocation when we're in this mode
if( m_NumBlobs != 0 )
{
Assert( !"CUtlMemoryPool::AddNewBlob: mode == GROW_NONE" );
return;
}
}
// GROW_FAST and GROW_NONE use this.
sizeMultiplier = m_NumBlobs + 1;
}
// maybe use something other than malloc?
int nElements = m_BlocksPerBlob * sizeMultiplier;
int blobSize = m_BlockSize * nElements;
CBlob *pBlob = (CBlob*)malloc( sizeof(CBlob) - 1 + blobSize + ( m_nAlignment - 1 ) );
Assert( pBlob );
// Link it in at the end of the blob list.
pBlob->m_NumBytes = blobSize;
pBlob->m_pNext = &m_BlobHead;
pBlob->m_pPrev = pBlob->m_pNext->m_pPrev;
pBlob->m_pNext->m_pPrev = pBlob->m_pPrev->m_pNext = pBlob;
// setup the free list
m_pHeadOfFreeList = AlignValue( pBlob->m_Data, m_nAlignment );
Assert (m_pHeadOfFreeList);
void **newBlob = (void**)m_pHeadOfFreeList;
for (int j = 0; j < nElements-1; j++)
{
newBlob[0] = (char*)newBlob + m_BlockSize;
newBlob = (void**)newBlob[0];
}
// null terminate list
newBlob[0] = NULL;
m_NumBlobs++;
}
void* CUtlMemoryPool::Alloc()
{
return Alloc( m_BlockSize );
}
void* CUtlMemoryPool::AllocZero()
{
return AllocZero( m_BlockSize );
}
//-----------------------------------------------------------------------------
// Purpose: Allocs a single block of memory from the pool.
// Input : amount -
//-----------------------------------------------------------------------------
void *CUtlMemoryPool::Alloc( size_t amount )
{
void *returnBlock;
if ( amount > (unsigned int)m_BlockSize )
return NULL;
if( !m_pHeadOfFreeList )
{
// returning NULL is fine in GROW_NONE
if( m_GrowMode == GROW_NONE )
{
//Assert( !"CUtlMemoryPool::Alloc: tried to make new blob with GROW_NONE" );
return NULL;
}
// overflow
AddNewBlob();
// still failure, error out
if( !m_pHeadOfFreeList )
{
Assert( !"CUtlMemoryPool::Alloc: ran out of memory" );
return NULL;
}
}
m_BlocksAllocated++;
m_PeakAlloc = max(m_PeakAlloc, m_BlocksAllocated);
returnBlock = m_pHeadOfFreeList;
// move the pointer the next block
m_pHeadOfFreeList = *((void**)m_pHeadOfFreeList);
return returnBlock;
}
//-----------------------------------------------------------------------------
// Purpose: Allocs a single block of memory from the pool, zeroes the memory before returning
// Input : amount -
//-----------------------------------------------------------------------------
void *CUtlMemoryPool::AllocZero( size_t amount )
{
void *mem = Alloc( amount );
if ( mem )
{
V_memset( mem, 0x00, amount );
}
return mem;
}
//-----------------------------------------------------------------------------
// Purpose: Frees a block of memory
// Input : *memBlock - the memory to free
//-----------------------------------------------------------------------------
void CUtlMemoryPool::Free( void *memBlock )
{
if ( !memBlock )
return; // trying to delete NULL pointer, ignore
#ifdef _DEBUG
// check to see if the memory is from the allocated range
bool bOK = false;
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
{
if (memBlock >= pCur->m_Data && (char*)memBlock < (pCur->m_Data + pCur->m_NumBytes))
{
bOK = true;
}
}
Assert (bOK);
#endif // _DEBUG
#ifdef _DEBUG
// invalidate the memory
memset( memBlock, 0xDD, m_BlockSize );
#endif
m_BlocksAllocated--;
// make the block point to the first item in the list
*((void**)memBlock) = m_pHeadOfFreeList;
// the list head is now the new block
m_pHeadOfFreeList = memBlock;
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "mempool.h"
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include "tier0/dbg.h"
#include <ctype.h>
#include "tier1/strtools.h"
// Should be last include
#include "tier0/memdbgon.h"
MemoryPoolReportFunc_t CUtlMemoryPool::g_ReportFunc = 0;
//-----------------------------------------------------------------------------
// Error reporting... (debug only)
//-----------------------------------------------------------------------------
void CUtlMemoryPool::SetErrorReportFunc( MemoryPoolReportFunc_t func )
{
g_ReportFunc = func;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CUtlMemoryPool::CUtlMemoryPool( int blockSize, int numElements, int growMode, const char *pszAllocOwner, int nAlignment )
{
#ifdef _X360
if( numElements > 0 && growMode != GROW_NONE )
{
numElements = 1;
}
#endif
m_nAlignment = ( nAlignment != 0 ) ? nAlignment : 1;
Assert( IsPowerOfTwo( m_nAlignment ) );
m_BlockSize = blockSize < sizeof(void*) ? sizeof(void*) : blockSize;
m_BlockSize = AlignValue( m_BlockSize, m_nAlignment );
m_BlocksPerBlob = numElements;
m_PeakAlloc = 0;
m_GrowMode = growMode;
if ( !pszAllocOwner )
{
pszAllocOwner = __FILE__;
}
m_pszAllocOwner = pszAllocOwner;
Init();
AddNewBlob();
}
//-----------------------------------------------------------------------------
// Purpose: Frees the memory contained in the mempool, and invalidates it for
// any further use.
// Input : *memPool - the mempool to shutdown
//-----------------------------------------------------------------------------
CUtlMemoryPool::~CUtlMemoryPool()
{
if (m_BlocksAllocated > 0)
{
ReportLeaks();
}
Clear();
}
//-----------------------------------------------------------------------------
// Resets the pool
//-----------------------------------------------------------------------------
void CUtlMemoryPool::Init()
{
m_NumBlobs = 0;
m_BlocksAllocated = 0;
m_pHeadOfFreeList = 0;
m_BlobHead.m_pNext = m_BlobHead.m_pPrev = &m_BlobHead;
}
//-----------------------------------------------------------------------------
// Frees everything
//-----------------------------------------------------------------------------
void CUtlMemoryPool::Clear()
{
// Free everything..
CBlob *pNext;
for( CBlob *pCur = m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur = pNext )
{
pNext = pCur->m_pNext;
free( pCur );
}
Init();
}
//-----------------------------------------------------------------------------
// Purpose: Reports memory leaks
//-----------------------------------------------------------------------------
void CUtlMemoryPool::ReportLeaks()
{
if (!g_ReportFunc)
return;
g_ReportFunc("Memory leak: mempool blocks left in memory: %d\n", m_BlocksAllocated);
#ifdef _DEBUG
// walk and destroy the free list so it doesn't intefere in the scan
while (m_pHeadOfFreeList != NULL)
{
void *next = *((void**)m_pHeadOfFreeList);
memset(m_pHeadOfFreeList, 0, m_BlockSize);
m_pHeadOfFreeList = next;
}
g_ReportFunc("Dumping memory: \'");
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
{
// scan the memory block and dump the leaks
char *scanPoint = (char *)pCur->m_Data;
char *scanEnd = pCur->m_Data + pCur->m_NumBytes;
bool needSpace = false;
while (scanPoint < scanEnd)
{
// search for and dump any strings
if ((unsigned)(*scanPoint + 1) <= 256 && isprint(*scanPoint))
{
g_ReportFunc("%c", *scanPoint);
needSpace = true;
}
else if (needSpace)
{
needSpace = false;
g_ReportFunc(" ");
}
scanPoint++;
}
}
g_ReportFunc("\'\n");
#endif // _DEBUG
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CUtlMemoryPool::AddNewBlob()
{
MEM_ALLOC_CREDIT_(m_pszAllocOwner);
int sizeMultiplier;
if( m_GrowMode == GROW_SLOW )
{
sizeMultiplier = 1;
}
else
{
if ( m_GrowMode == GROW_NONE )
{
// Can only have one allocation when we're in this mode
if( m_NumBlobs != 0 )
{
Assert( !"CUtlMemoryPool::AddNewBlob: mode == GROW_NONE" );
return;
}
}
// GROW_FAST and GROW_NONE use this.
sizeMultiplier = m_NumBlobs + 1;
}
// maybe use something other than malloc?
int nElements = m_BlocksPerBlob * sizeMultiplier;
int blobSize = m_BlockSize * nElements;
CBlob *pBlob = (CBlob*)malloc( sizeof(CBlob) - 1 + blobSize + ( m_nAlignment - 1 ) );
Assert( pBlob );
// Link it in at the end of the blob list.
pBlob->m_NumBytes = blobSize;
pBlob->m_pNext = &m_BlobHead;
pBlob->m_pPrev = pBlob->m_pNext->m_pPrev;
pBlob->m_pNext->m_pPrev = pBlob->m_pPrev->m_pNext = pBlob;
// setup the free list
m_pHeadOfFreeList = AlignValue( pBlob->m_Data, m_nAlignment );
Assert (m_pHeadOfFreeList);
void **newBlob = (void**)m_pHeadOfFreeList;
for (int j = 0; j < nElements-1; j++)
{
newBlob[0] = (char*)newBlob + m_BlockSize;
newBlob = (void**)newBlob[0];
}
// null terminate list
newBlob[0] = NULL;
m_NumBlobs++;
}
void* CUtlMemoryPool::Alloc()
{
return Alloc( m_BlockSize );
}
void* CUtlMemoryPool::AllocZero()
{
return AllocZero( m_BlockSize );
}
//-----------------------------------------------------------------------------
// Purpose: Allocs a single block of memory from the pool.
// Input : amount -
//-----------------------------------------------------------------------------
void *CUtlMemoryPool::Alloc( size_t amount )
{
void *returnBlock;
if ( amount > (unsigned int)m_BlockSize )
return NULL;
if( !m_pHeadOfFreeList )
{
// returning NULL is fine in GROW_NONE
if( m_GrowMode == GROW_NONE )
{
//Assert( !"CUtlMemoryPool::Alloc: tried to make new blob with GROW_NONE" );
return NULL;
}
// overflow
AddNewBlob();
// still failure, error out
if( !m_pHeadOfFreeList )
{
Assert( !"CUtlMemoryPool::Alloc: ran out of memory" );
return NULL;
}
}
m_BlocksAllocated++;
m_PeakAlloc = max(m_PeakAlloc, m_BlocksAllocated);
returnBlock = m_pHeadOfFreeList;
// move the pointer the next block
m_pHeadOfFreeList = *((void**)m_pHeadOfFreeList);
return returnBlock;
}
//-----------------------------------------------------------------------------
// Purpose: Allocs a single block of memory from the pool, zeroes the memory before returning
// Input : amount -
//-----------------------------------------------------------------------------
void *CUtlMemoryPool::AllocZero( size_t amount )
{
void *mem = Alloc( amount );
if ( mem )
{
V_memset( mem, 0x00, amount );
}
return mem;
}
//-----------------------------------------------------------------------------
// Purpose: Frees a block of memory
// Input : *memBlock - the memory to free
//-----------------------------------------------------------------------------
void CUtlMemoryPool::Free( void *memBlock )
{
if ( !memBlock )
return; // trying to delete NULL pointer, ignore
#ifdef _DEBUG
// check to see if the memory is from the allocated range
bool bOK = false;
for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext )
{
if (memBlock >= pCur->m_Data && (char*)memBlock < (pCur->m_Data + pCur->m_NumBytes))
{
bOK = true;
}
}
Assert (bOK);
#endif // _DEBUG
#ifdef _DEBUG
// invalidate the memory
memset( memBlock, 0xDD, m_BlockSize );
#endif
m_BlocksAllocated--;
// make the block point to the first item in the list
*((void**)memBlock) = m_pHeadOfFreeList;
// the list head is now the new block
m_pHeadOfFreeList = memBlock;
}

View File

@@ -1,297 +1,297 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#if defined( _WIN32 ) && !defined( _X360 )
#define WIN_32_LEAN_AND_MEAN
#include <windows.h>
#define VA_COMMIT_FLAGS MEM_COMMIT
#define VA_RESERVE_FLAGS MEM_RESERVE
#elif defined( _X360 )
#define VA_COMMIT_FLAGS (MEM_COMMIT|MEM_NOZERO|MEM_LARGE_PAGES)
#define VA_RESERVE_FLAGS (MEM_RESERVE|MEM_LARGE_PAGES)
#endif
#include "tier0/dbg.h"
#include "memstack.h"
#include "utlmap.h"
#include "tier0/memdbgon.h"
#ifdef _WIN32
#pragma warning(disable:4073)
#pragma init_seg(lib)
#endif
//-----------------------------------------------------------------------------
MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack);
//-----------------------------------------------------------------------------
CMemoryStack::CMemoryStack()
: m_pBase( NULL ),
m_pNextAlloc( NULL ),
m_pAllocLimit( NULL ),
m_pCommitLimit( NULL ),
m_alignment( 16 ),
#if defined(_WIN32)
m_commitSize( 0 ),
m_minCommit( 0 ),
#endif
m_maxSize( 0 )
{
}
//-------------------------------------
CMemoryStack::~CMemoryStack()
{
if ( m_pBase )
Term();
}
//-------------------------------------
bool CMemoryStack::Init( unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment )
{
Assert( !m_pBase );
#ifdef _X360
m_bPhysical = false;
#endif
m_maxSize = maxSize;
m_alignment = AlignValue( alignment, 4 );
Assert( m_alignment == alignment );
Assert( m_maxSize > 0 );
#if defined(_WIN32)
if ( commitSize != 0 )
{
m_commitSize = commitSize;
}
unsigned pageSize;
#ifndef _X360
SYSTEM_INFO sysInfo;
GetSystemInfo( &sysInfo );
Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) );
pageSize = sysInfo.dwPageSize;
#else
pageSize = 64*1024;
#endif
if ( m_commitSize == 0 )
{
m_commitSize = pageSize;
}
else
{
m_commitSize = AlignValue( m_commitSize, pageSize );
}
m_maxSize = AlignValue( m_maxSize, m_commitSize );
Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize );
m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS );
Assert( m_pBase );
m_pCommitLimit = m_pNextAlloc = m_pBase;
if ( initialCommit )
{
initialCommit = AlignValue( initialCommit, m_commitSize );
Assert( initialCommit < m_maxSize );
if ( !VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
return false;
m_minCommit = initialCommit;
m_pCommitLimit += initialCommit;
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
}
#else
m_pBase = (byte *)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 );
m_pNextAlloc = m_pBase;
m_pCommitLimit = m_pBase + m_maxSize;
#endif
m_pAllocLimit = m_pBase + m_maxSize;
return ( m_pBase != NULL );
}
//-------------------------------------
#ifdef _X360
bool CMemoryStack::InitPhysical( unsigned size, unsigned alignment )
{
m_bPhysical = true;
m_maxSize = m_commitSize = size;
m_alignment = AlignValue( alignment, 4 );
int flags = PAGE_READWRITE;
if ( size >= 16*1024*1024 )
{
flags |= MEM_16MB_PAGES;
}
else
{
flags |= MEM_LARGE_PAGES;
}
m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, 4096, flags );
Assert( m_pBase );
m_pNextAlloc = m_pBase;
m_pCommitLimit = m_pBase + m_maxSize;
m_pAllocLimit = m_pBase + m_maxSize;
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
return ( m_pBase != NULL );
}
#endif
//-------------------------------------
void CMemoryStack::Term()
{
FreeAll();
if ( m_pBase )
{
#if defined(_WIN32)
VirtualFree( m_pBase, 0, MEM_RELEASE );
#else
MemAlloc_FreeAligned( m_pBase );
#endif
m_pBase = NULL;
}
}
//-------------------------------------
int CMemoryStack::GetSize()
{
#ifdef _WIN32
return m_pCommitLimit - m_pBase;
#else
return m_maxSize;
#endif
}
//-------------------------------------
bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT
{
#ifdef _X360
if ( m_bPhysical )
{
return NULL;
}
#endif
#if defined(_WIN32)
unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize );
unsigned commitSize = pNewCommitLimit - m_pCommitLimit;
if ( GetSize() )
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
if( m_pCommitLimit + commitSize > m_pAllocLimit )
{
return false;
}
if ( !VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
{
Assert( 0 );
return false;
}
m_pCommitLimit = pNewCommitLimit;
if ( GetSize() )
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
return true;
#else
Assert( 0 );
return false;
#endif
}
//-------------------------------------
void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit )
{
void *pAllocPoint = m_pBase + mark;
Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc );
if ( pAllocPoint >= m_pBase && pAllocPoint < m_pNextAlloc )
{
if ( bDecommit )
{
#if defined(_WIN32)
unsigned char *pDecommitPoint = AlignValue( (unsigned char *)pAllocPoint, m_commitSize );
if ( pDecommitPoint < m_pBase + m_minCommit )
{
pDecommitPoint = m_pBase + m_minCommit;
}
unsigned decommitSize = m_pCommitLimit - pDecommitPoint;
if ( decommitSize > 0 )
{
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
VirtualFree( pDecommitPoint, decommitSize, MEM_DECOMMIT );
m_pCommitLimit = pDecommitPoint;
if ( mark > 0 )
{
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
}
}
#endif
}
m_pNextAlloc = (unsigned char *)pAllocPoint;
}
}
//-------------------------------------
void CMemoryStack::FreeAll( bool bDecommit )
{
if ( m_pBase && m_pCommitLimit - m_pBase > 0 )
{
if ( bDecommit )
{
#if defined(_WIN32)
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
VirtualFree( m_pBase, m_pCommitLimit - m_pBase, MEM_DECOMMIT );
m_pCommitLimit = m_pBase;
#endif
}
m_pNextAlloc = m_pBase;
}
}
//-------------------------------------
void CMemoryStack::Access( void **ppRegion, unsigned *pBytes )
{
*ppRegion = m_pBase;
*pBytes = ( m_pNextAlloc - m_pBase);
}
//-------------------------------------
void CMemoryStack::PrintContents()
{
Msg( "Total used memory: %d\n", GetUsed() );
Msg( "Total committed memory: %d\n", GetSize() );
}
//-----------------------------------------------------------------------------
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#if defined( _WIN32 ) && !defined( _X360 )
#define WIN_32_LEAN_AND_MEAN
#include <windows.h>
#define VA_COMMIT_FLAGS MEM_COMMIT
#define VA_RESERVE_FLAGS MEM_RESERVE
#elif defined( _X360 )
#define VA_COMMIT_FLAGS (MEM_COMMIT|MEM_NOZERO|MEM_LARGE_PAGES)
#define VA_RESERVE_FLAGS (MEM_RESERVE|MEM_LARGE_PAGES)
#endif
#include "tier0/dbg.h"
#include "memstack.h"
#include "utlmap.h"
#include "tier0/memdbgon.h"
#ifdef _WIN32
#pragma warning(disable:4073)
#pragma init_seg(lib)
#endif
//-----------------------------------------------------------------------------
MEMALLOC_DEFINE_EXTERNAL_TRACKING(CMemoryStack);
//-----------------------------------------------------------------------------
CMemoryStack::CMemoryStack()
: m_pBase( NULL ),
m_pNextAlloc( NULL ),
m_pAllocLimit( NULL ),
m_pCommitLimit( NULL ),
m_alignment( 16 ),
#if defined(_WIN32)
m_commitSize( 0 ),
m_minCommit( 0 ),
#endif
m_maxSize( 0 )
{
}
//-------------------------------------
CMemoryStack::~CMemoryStack()
{
if ( m_pBase )
Term();
}
//-------------------------------------
bool CMemoryStack::Init( unsigned maxSize, unsigned commitSize, unsigned initialCommit, unsigned alignment )
{
Assert( !m_pBase );
#ifdef _X360
m_bPhysical = false;
#endif
m_maxSize = maxSize;
m_alignment = AlignValue( alignment, 4 );
Assert( m_alignment == alignment );
Assert( m_maxSize > 0 );
#if defined(_WIN32)
if ( commitSize != 0 )
{
m_commitSize = commitSize;
}
unsigned pageSize;
#ifndef _X360
SYSTEM_INFO sysInfo;
GetSystemInfo( &sysInfo );
Assert( !( sysInfo.dwPageSize & (sysInfo.dwPageSize-1)) );
pageSize = sysInfo.dwPageSize;
#else
pageSize = 64*1024;
#endif
if ( m_commitSize == 0 )
{
m_commitSize = pageSize;
}
else
{
m_commitSize = AlignValue( m_commitSize, pageSize );
}
m_maxSize = AlignValue( m_maxSize, m_commitSize );
Assert( m_maxSize % pageSize == 0 && m_commitSize % pageSize == 0 && m_commitSize <= m_maxSize );
m_pBase = (unsigned char *)VirtualAlloc( NULL, m_maxSize, VA_RESERVE_FLAGS, PAGE_NOACCESS );
Assert( m_pBase );
m_pCommitLimit = m_pNextAlloc = m_pBase;
if ( initialCommit )
{
initialCommit = AlignValue( initialCommit, m_commitSize );
Assert( initialCommit < m_maxSize );
if ( !VirtualAlloc( m_pCommitLimit, initialCommit, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
return false;
m_minCommit = initialCommit;
m_pCommitLimit += initialCommit;
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
}
#else
m_pBase = (byte *)MemAlloc_AllocAligned( m_maxSize, alignment ? alignment : 1 );
m_pNextAlloc = m_pBase;
m_pCommitLimit = m_pBase + m_maxSize;
#endif
m_pAllocLimit = m_pBase + m_maxSize;
return ( m_pBase != NULL );
}
//-------------------------------------
#ifdef _X360
bool CMemoryStack::InitPhysical( unsigned size, unsigned alignment )
{
m_bPhysical = true;
m_maxSize = m_commitSize = size;
m_alignment = AlignValue( alignment, 4 );
int flags = PAGE_READWRITE;
if ( size >= 16*1024*1024 )
{
flags |= MEM_16MB_PAGES;
}
else
{
flags |= MEM_LARGE_PAGES;
}
m_pBase = (unsigned char *)XPhysicalAlloc( m_maxSize, MAXULONG_PTR, 4096, flags );
Assert( m_pBase );
m_pNextAlloc = m_pBase;
m_pCommitLimit = m_pBase + m_maxSize;
m_pAllocLimit = m_pBase + m_maxSize;
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
return ( m_pBase != NULL );
}
#endif
//-------------------------------------
void CMemoryStack::Term()
{
FreeAll();
if ( m_pBase )
{
#if defined(_WIN32)
VirtualFree( m_pBase, 0, MEM_RELEASE );
#else
MemAlloc_FreeAligned( m_pBase );
#endif
m_pBase = NULL;
}
}
//-------------------------------------
int CMemoryStack::GetSize()
{
#ifdef _WIN32
return m_pCommitLimit - m_pBase;
#else
return m_maxSize;
#endif
}
//-------------------------------------
bool CMemoryStack::CommitTo( byte *pNextAlloc ) RESTRICT
{
#ifdef _X360
if ( m_bPhysical )
{
return NULL;
}
#endif
#if defined(_WIN32)
unsigned char * pNewCommitLimit = AlignValue( pNextAlloc, m_commitSize );
unsigned commitSize = pNewCommitLimit - m_pCommitLimit;
if ( GetSize() )
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
if( m_pCommitLimit + commitSize > m_pAllocLimit )
{
return false;
}
if ( !VirtualAlloc( m_pCommitLimit, commitSize, VA_COMMIT_FLAGS, PAGE_READWRITE ) )
{
Assert( 0 );
return false;
}
m_pCommitLimit = pNewCommitLimit;
if ( GetSize() )
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
return true;
#else
Assert( 0 );
return false;
#endif
}
//-------------------------------------
void CMemoryStack::FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit )
{
void *pAllocPoint = m_pBase + mark;
Assert( pAllocPoint >= m_pBase && pAllocPoint <= m_pNextAlloc );
if ( pAllocPoint >= m_pBase && pAllocPoint < m_pNextAlloc )
{
if ( bDecommit )
{
#if defined(_WIN32)
unsigned char *pDecommitPoint = AlignValue( (unsigned char *)pAllocPoint, m_commitSize );
if ( pDecommitPoint < m_pBase + m_minCommit )
{
pDecommitPoint = m_pBase + m_minCommit;
}
unsigned decommitSize = m_pCommitLimit - pDecommitPoint;
if ( decommitSize > 0 )
{
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
VirtualFree( pDecommitPoint, decommitSize, MEM_DECOMMIT );
m_pCommitLimit = pDecommitPoint;
if ( mark > 0 )
{
MemAlloc_RegisterExternalAllocation( CMemoryStack, GetBase(), GetSize() );
}
}
#endif
}
m_pNextAlloc = (unsigned char *)pAllocPoint;
}
}
//-------------------------------------
void CMemoryStack::FreeAll( bool bDecommit )
{
if ( m_pBase && m_pCommitLimit - m_pBase > 0 )
{
if ( bDecommit )
{
#if defined(_WIN32)
MemAlloc_RegisterExternalDeallocation( CMemoryStack, GetBase(), GetSize() );
VirtualFree( m_pBase, m_pCommitLimit - m_pBase, MEM_DECOMMIT );
m_pCommitLimit = m_pBase;
#endif
}
m_pNextAlloc = m_pBase;
}
}
//-------------------------------------
void CMemoryStack::Access( void **ppRegion, unsigned *pBytes )
{
*ppRegion = m_pBase;
*pBytes = ( m_pNextAlloc - m_pBase);
}
//-------------------------------------
void CMemoryStack::PrintContents()
{
Msg( "Total used memory: %d\n", GetUsed() );
Msg( "Total committed memory: %d\n", GetSize() );
}
//-----------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,274 +1,274 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: win32 dependant ASM code for CPU capability detection
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#if defined( _X360 ) || defined( WIN64 )
bool CheckMMXTechnology(void) { return false; }
bool CheckSSETechnology(void) { return false; }
bool CheckSSE2Technology(void) { return false; }
bool Check3DNowTechnology(void) { return false; }
#elif defined( _WIN32 ) && !defined( _X360 )
#pragma optimize( "", off )
#pragma warning( disable: 4800 ) //'int' : forcing value to bool 'true' or 'false' (performance warning)
// stuff from windows.h
#ifndef EXCEPTION_EXECUTE_HANDLER
#define EXCEPTION_EXECUTE_HANDLER 1
#endif
bool CheckMMXTechnology(void)
{
int retval = true;
unsigned int RegEDX = 0;
#ifdef CPUID
_asm pushad;
#endif
__try
{
_asm
{
#ifdef CPUID
xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 1 // set up CPUID to return processor version and features
// 0 = vendor string, 1 = version info, 2 = cache info
CPUID // code bytes = 0fh, 0a2h
mov RegEDX, edx // features returned in edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then certainly no MMX extensions.
if (retval)
{
if (RegEDX & 0x800000) // bit 23 is set for MMX technology
{
__try
{
// try executing the MMX instruction "emms"
_asm EMMS
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
}
else
retval = false; // processor supports CPUID but does not support MMX technology
// if retval == 0 here, it means the processor has MMX technology but
// floating-point emulation is on; so MMX technology is unavailable
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
bool CheckSSETechnology(void)
{
int retval = true;
unsigned int RegEDX = 0;
#ifdef CPUID
_asm pushad;
#endif
// Do we have support for the CPUID function?
__try
{
_asm
{
#ifdef CPUID
xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 1 // set up CPUID to return processor version and features
// 0 = vendor string, 1 = version info, 2 = cache info
CPUID // code bytes = 0fh, 0a2h
mov RegEDX, edx // features returned in edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then certainly no SSE extensions.
if (retval)
{
// Do we have support for SSE in this processor?
if ( RegEDX & 0x2000000L ) // bit 25 is set for SSE technology
{
// Make sure that SSE is supported by executing an inline SSE instruction
// BUGBUG, FIXME - Visual C Version 6.0 does not support SSE inline code YET (No macros from Intel either)
// Fix this if VC7 supports inline SSE instructinons like "xorps" as shown below.
#if 1
__try
{
_asm
{
// Attempt execution of a SSE instruction to make sure OS supports SSE FPU context switches
xorps xmm0, xmm0
// This will work on Win2k+ (Including masking SSE FPU exception to "normalized" values)
// This will work on Win98+ (But no "masking" of FPU exceptions provided)
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
#endif
{
retval = false;
}
}
else
retval = false;
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
bool CheckSSE2Technology(void)
{
int retval = true;
unsigned int RegEDX = 0;
#ifdef CPUID
_asm pushad;
#endif
// Do we have support for the CPUID function?
__try
{
_asm
{
#ifdef CPUID
xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 1 // set up CPUID to return processor version and features
// 0 = vendor string, 1 = version info, 2 = cache info
CPUID // code bytes = 0fh, 0a2h
mov RegEDX, edx // features returned in edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then certainly no SSE extensions.
if (retval)
{
// Do we have support for SSE in this processor?
if ( RegEDX & 0x04000000 ) // bit 26 is set for SSE2 technology
{
// Make sure that SSE is supported by executing an inline SSE instruction
__try
{
_asm
{
// Attempt execution of a SSE2 instruction to make sure OS supports SSE FPU context switches
xorpd xmm0, xmm0
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
}
else
retval = false;
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
bool Check3DNowTechnology(void)
{
int retval = true;
unsigned int RegEAX = 0;
#ifdef CPUID
_asm pushad;
#endif
// First see if we can execute CPUID at all
__try
{
_asm
{
#ifdef CPUID
// xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 0x80000000 // setup CPUID to return whether AMD >0x80000000 function are supported.
// 0x80000000 = Highest 0x80000000+ function, 0x80000001 = 3DNow support
CPUID // code bytes = 0fh, 0a2h
mov RegEAX, eax // result returned in eax
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then there is definitely no 3DNow support
if (retval)
{
// Are there any "higher" AMD CPUID functions?
if (RegEAX > 0x80000000L )
{
__try
{
_asm
{
mov eax, 0x80000001 // setup to test for CPU features
CPUID // code bytes = 0fh, 0a2h
shr edx, 31 // If bit 31 is set, we have 3DNow support!
mov retval, edx // Save the return value for end of function
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
}
else
{
// processor supports CPUID but does not support AMD CPUID functions
retval = false;
}
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
#pragma optimize( "", on )
#endif // _WIN32
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: win32 dependant ASM code for CPU capability detection
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#if defined( _X360 ) || defined( WIN64 )
bool CheckMMXTechnology(void) { return false; }
bool CheckSSETechnology(void) { return false; }
bool CheckSSE2Technology(void) { return false; }
bool Check3DNowTechnology(void) { return false; }
#elif defined( _WIN32 ) && !defined( _X360 )
#pragma optimize( "", off )
#pragma warning( disable: 4800 ) //'int' : forcing value to bool 'true' or 'false' (performance warning)
// stuff from windows.h
#ifndef EXCEPTION_EXECUTE_HANDLER
#define EXCEPTION_EXECUTE_HANDLER 1
#endif
bool CheckMMXTechnology(void)
{
int retval = true;
unsigned int RegEDX = 0;
#ifdef CPUID
_asm pushad;
#endif
__try
{
_asm
{
#ifdef CPUID
xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 1 // set up CPUID to return processor version and features
// 0 = vendor string, 1 = version info, 2 = cache info
CPUID // code bytes = 0fh, 0a2h
mov RegEDX, edx // features returned in edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then certainly no MMX extensions.
if (retval)
{
if (RegEDX & 0x800000) // bit 23 is set for MMX technology
{
__try
{
// try executing the MMX instruction "emms"
_asm EMMS
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
}
else
retval = false; // processor supports CPUID but does not support MMX technology
// if retval == 0 here, it means the processor has MMX technology but
// floating-point emulation is on; so MMX technology is unavailable
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
bool CheckSSETechnology(void)
{
int retval = true;
unsigned int RegEDX = 0;
#ifdef CPUID
_asm pushad;
#endif
// Do we have support for the CPUID function?
__try
{
_asm
{
#ifdef CPUID
xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 1 // set up CPUID to return processor version and features
// 0 = vendor string, 1 = version info, 2 = cache info
CPUID // code bytes = 0fh, 0a2h
mov RegEDX, edx // features returned in edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then certainly no SSE extensions.
if (retval)
{
// Do we have support for SSE in this processor?
if ( RegEDX & 0x2000000L ) // bit 25 is set for SSE technology
{
// Make sure that SSE is supported by executing an inline SSE instruction
// BUGBUG, FIXME - Visual C Version 6.0 does not support SSE inline code YET (No macros from Intel either)
// Fix this if VC7 supports inline SSE instructinons like "xorps" as shown below.
#if 1
__try
{
_asm
{
// Attempt execution of a SSE instruction to make sure OS supports SSE FPU context switches
xorps xmm0, xmm0
// This will work on Win2k+ (Including masking SSE FPU exception to "normalized" values)
// This will work on Win98+ (But no "masking" of FPU exceptions provided)
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
#endif
{
retval = false;
}
}
else
retval = false;
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
bool CheckSSE2Technology(void)
{
int retval = true;
unsigned int RegEDX = 0;
#ifdef CPUID
_asm pushad;
#endif
// Do we have support for the CPUID function?
__try
{
_asm
{
#ifdef CPUID
xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 1 // set up CPUID to return processor version and features
// 0 = vendor string, 1 = version info, 2 = cache info
CPUID // code bytes = 0fh, 0a2h
mov RegEDX, edx // features returned in edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then certainly no SSE extensions.
if (retval)
{
// Do we have support for SSE in this processor?
if ( RegEDX & 0x04000000 ) // bit 26 is set for SSE2 technology
{
// Make sure that SSE is supported by executing an inline SSE instruction
__try
{
_asm
{
// Attempt execution of a SSE2 instruction to make sure OS supports SSE FPU context switches
xorpd xmm0, xmm0
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
}
else
retval = false;
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
bool Check3DNowTechnology(void)
{
int retval = true;
unsigned int RegEAX = 0;
#ifdef CPUID
_asm pushad;
#endif
// First see if we can execute CPUID at all
__try
{
_asm
{
#ifdef CPUID
// xor edx, edx // Clue the compiler that EDX is about to be used.
#endif
mov eax, 0x80000000 // setup CPUID to return whether AMD >0x80000000 function are supported.
// 0x80000000 = Highest 0x80000000+ function, 0x80000001 = 3DNow support
CPUID // code bytes = 0fh, 0a2h
mov RegEAX, eax // result returned in eax
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
// If CPUID not supported, then there is definitely no 3DNow support
if (retval)
{
// Are there any "higher" AMD CPUID functions?
if (RegEAX > 0x80000000L )
{
__try
{
_asm
{
mov eax, 0x80000001 // setup to test for CPU features
CPUID // code bytes = 0fh, 0a2h
shr edx, 31 // If bit 31 is set, we have 3DNow support!
mov retval, edx // Save the return value for end of function
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = false;
}
}
else
{
// processor supports CPUID but does not support AMD CPUID functions
retval = false;
}
}
#ifdef CPUID
_asm popad;
#endif
return retval;
}
#pragma optimize( "", on )
#endif // _WIN32

View File

@@ -1,47 +1,47 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: linux dependant ASM code for CPU capability detection
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#define cpuid(in,a,b,c,d) \
asm("pushl %%ebx\n\t" "cpuid\n\t" "movl %%ebx,%%esi\n\t" "pop %%ebx": "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (in));
bool CheckMMXTechnology(void)
{
unsigned long eax,ebx,edx,unused;
cpuid(1,eax,ebx,unused,edx);
return edx & 0x800000;
}
bool CheckSSETechnology(void)
{
unsigned long eax,ebx,edx,unused;
cpuid(1,eax,ebx,unused,edx);
return edx & 0x2000000L;
}
bool CheckSSE2Technology(void)
{
unsigned long eax,ebx,edx,unused;
cpuid(1,eax,ebx,unused,edx);
return edx & 0x04000000;
}
bool Check3DNowTechnology(void)
{
unsigned long eax, unused;
cpuid(0x80000000,eax,unused,unused,unused);
if ( eax > 0x80000000L )
{
cpuid(0x80000001,unused,unused,unused,eax);
return ( eax & 1<<31 );
}
return false;
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: linux dependant ASM code for CPU capability detection
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#define cpuid(in,a,b,c,d) \
asm("pushl %%ebx\n\t" "cpuid\n\t" "movl %%ebx,%%esi\n\t" "pop %%ebx": "=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (in));
bool CheckMMXTechnology(void)
{
unsigned long eax,ebx,edx,unused;
cpuid(1,eax,ebx,unused,edx);
return edx & 0x800000;
}
bool CheckSSETechnology(void)
{
unsigned long eax,ebx,edx,unused;
cpuid(1,eax,ebx,unused,edx);
return edx & 0x2000000L;
}
bool CheckSSE2Technology(void)
{
unsigned long eax,ebx,edx,unused;
cpuid(1,eax,ebx,unused,edx);
return edx & 0x04000000;
}
bool Check3DNowTechnology(void)
{
unsigned long eax, unused;
cpuid(0x80000000,eax,unused,unused,unused);
if ( eax > 0x80000000L )
{
cpuid(0x80000001,unused,unused,unused,eax);
return ( eax & 1<<31 );
}
return false;
}

View File

@@ -1,112 +1,112 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
/******************************************************************/
/* qsort.c -- Non-Recursive ANSI Quicksort function */
/* */
/* Public domain by Raymond Gardner, Englewood CO February 1991 */
/* */
/* Usage: */
/* qsort(base, nbr_elements, width_bytes, compare_function); */
/* void *base; */
/* size_t nbr_elements, width_bytes; */
/* int (*compare_function)(const void *, const void *); */
/* */
/* Sorts an array starting at base, of length nbr_elements, each */
/* element of size width_bytes, ordered via compare_function, */
/* which is called as (*compare_function)(ptr_to_element1, */
/* ptr_to_element2) and returns < 0 if element1 < element2, */
/* 0 if element1 = element2, > 0 if element1 > element2. */
/* Most refinements are due to R. Sedgewick. See "Implementing */
/* Quicksort Programs", Comm. ACM, Oct. 1978, and Corrigendum, */
/* Comm. ACM, June 1979. */
/******************************************************************/
// modified to take (and use) a context object, ala Microsoft's qsort_s
// "extension" to the stdlib
#include <stddef.h> /* for size_t definition */
/*
** swap nbytes between a and b
*/
static void swap_bytes(char *a, char *b, size_t nbytes)
{
char tmp;
do {
tmp = *a; *a++ = *b; *b++ = tmp;
} while ( --nbytes );
}
#define SWAP(a, b) (swap_bytes((char *)(a), (char *)(b), size))
#define COMP(ctx, a, b) ((*comp)((void *)ctx, (void *)(a), (void *)(b)))
#define T 7 /* subfiles of T or fewer elements will */
/* be sorted by a simple insertion sort */
/* Note! T must be at least 3 */
extern "C" void qsort_s(void *basep, size_t nelems, size_t size,
int (*comp)(void *, const void *, const void *),
void *ctx)
{
char *stack[40], **sp; /* stack and stack pointer */
char *i, *j, *limit; /* scan and limit pointers */
size_t thresh; /* size of T elements in bytes */
char *base; /* base pointer as char * */
base = (char *)basep; /* set up char * base pointer */
//========= Copyright Valve Corporation, All rights reserved. ============//
/******************************************************************/
/* qsort.c -- Non-Recursive ANSI Quicksort function */
/* */
/* Public domain by Raymond Gardner, Englewood CO February 1991 */
/* */
/* Usage: */
/* qsort(base, nbr_elements, width_bytes, compare_function); */
/* void *base; */
/* size_t nbr_elements, width_bytes; */
/* int (*compare_function)(const void *, const void *); */
/* */
/* Sorts an array starting at base, of length nbr_elements, each */
/* element of size width_bytes, ordered via compare_function, */
/* which is called as (*compare_function)(ptr_to_element1, */
/* ptr_to_element2) and returns < 0 if element1 < element2, */
/* 0 if element1 = element2, > 0 if element1 > element2. */
/* Most refinements are due to R. Sedgewick. See "Implementing */
/* Quicksort Programs", Comm. ACM, Oct. 1978, and Corrigendum, */
/* Comm. ACM, June 1979. */
/******************************************************************/
// modified to take (and use) a context object, ala Microsoft's qsort_s
// "extension" to the stdlib
#include <stddef.h> /* for size_t definition */
/*
** swap nbytes between a and b
*/
static void swap_bytes(char *a, char *b, size_t nbytes)
{
char tmp;
do {
tmp = *a; *a++ = *b; *b++ = tmp;
} while ( --nbytes );
}
#define SWAP(a, b) (swap_bytes((char *)(a), (char *)(b), size))
#define COMP(ctx, a, b) ((*comp)((void *)ctx, (void *)(a), (void *)(b)))
#define T 7 /* subfiles of T or fewer elements will */
/* be sorted by a simple insertion sort */
/* Note! T must be at least 3 */
extern "C" void qsort_s(void *basep, size_t nelems, size_t size,
int (*comp)(void *, const void *, const void *),
void *ctx)
{
char *stack[40], **sp; /* stack and stack pointer */
char *i, *j, *limit; /* scan and limit pointers */
size_t thresh; /* size of T elements in bytes */
char *base; /* base pointer as char * */
base = (char *)basep; /* set up char * base pointer */
thresh = T * size; /* init threshold */
sp = stack; /* init stack pointer */
limit = base + nelems * size;/* pointer past end of array */
for ( ;; ) { /* repeat until break... */
if ( limit - base > thresh ) { /* if more than T elements */
/* swap base with middle */
SWAP((((limit-base)/size)/2)*size+base, base);
i = base + size; /* i scans left to right */
j = limit - size; /* j scans right to left */
if ( COMP(ctx, i, j) > 0 ) /* Sedgewick's */
SWAP(i, j); /* three-element sort */
if ( COMP(ctx, base, j) > 0 )/* sets things up */
SWAP(base, j); /* so that */
if ( COMP(ctx, i, base) > 0 )/* *i <= *base <= *j */
SWAP(i, base); /* *base is pivot element */
for ( ;; ) { /* loop until break */
do /* move i right */
i += size; /* until *i >= pivot */
while ( COMP(ctx, i, base) < 0 );
do /* move j left */
j -= size; /* until *j <= pivot */
while ( COMP(ctx, j, base) > 0 );
if ( i > j ) /* if pointers crossed */
break; /* break loop */
SWAP(i, j); /* else swap elements, keep scanning*/
}
SWAP(base, j); /* move pivot into correct place */
if ( j - base > limit - i ) { /* if left subfile larger */
sp[0] = base; /* stack left subfile base */
sp[1] = j; /* and limit */
base = i; /* sort the right subfile */
} else { /* else right subfile larger*/
sp[0] = i; /* stack right subfile base */
sp[1] = limit; /* and limit */
limit = j; /* sort the left subfile */
}
sp += 2; /* increment stack pointer */
} else { /* else subfile is small, use insertion sort */
for ( j = base, i = j+size; i < limit; j = i, i += size )
for ( ; COMP(ctx, j, j+size) > 0; j -= size ) {
SWAP(j, j+size);
if ( j == base )
break;
}
if ( sp != stack ) { /* if any entries on stack */
sp -= 2; /* pop the base and limit */
base = sp[0];
limit = sp[1];
} else /* else stack empty, done */
break;
}
}
}

View File

@@ -1,41 +1,41 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "rangecheckedvar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
bool g_bDoRangeChecks = true;
static int g_nDisables = 0;
CDisableRangeChecks::CDisableRangeChecks()
{
if ( !ThreadInMainThread() )
return;
g_nDisables++;
g_bDoRangeChecks = false;
}
CDisableRangeChecks::~CDisableRangeChecks()
{
if ( !ThreadInMainThread() )
return;
Assert( g_nDisables > 0 );
--g_nDisables;
if ( g_nDisables == 0 )
{
g_bDoRangeChecks = true;
}
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "rangecheckedvar.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
bool g_bDoRangeChecks = true;
static int g_nDisables = 0;
CDisableRangeChecks::CDisableRangeChecks()
{
if ( !ThreadInMainThread() )
return;
g_nDisables++;
g_bDoRangeChecks = false;
}
CDisableRangeChecks::~CDisableRangeChecks()
{
if ( !ThreadInMainThread() )
return;
Assert( g_nDisables > 0 );
--g_nDisables;
if ( g_nDisables == 0 )
{
g_bDoRangeChecks = true;
}
}

View File

@@ -1,93 +1,93 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "tier1/reliabletimer.h"
int64 CReliableTimer::sm_nPerformanceFrequency = 0;
bool CReliableTimer::sm_bUseQPC = false;
#ifdef _WIN32
#include "winlite.h"
#endif
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CReliableTimer::CReliableTimer()
{
m_nPerformanceCounterStart = 0;
m_nPerformanceCounterEnd = 0;
m_nPerformanceCounterLimit = 0;
#ifdef _WIN32
// calculate performance frequency the first time we use a timer
if ( 0 == sm_nPerformanceFrequency )
{
// Are we on a bad CPU?
sm_bUseQPC = false; // todo
const CPUInformation &cpu = *GetCPUInformation();
sm_bUseQPC = ( ( 0 == Q_stricmp( cpu.m_szProcessorID, "AuthenticAMD" ) )
&& ( cpu.m_nPhysicalProcessors > 1 )
&& !cpu.m_bSSE41 );
if ( sm_bUseQPC )
{
LARGE_INTEGER li;
QueryPerformanceFrequency( &li );
sm_nPerformanceFrequency = li.QuadPart;
}
else
{
sm_nPerformanceFrequency = g_ClockSpeed;
}
}
#elif defined(_PS3)
// On PowerPC, the time base register increment frequency is implementation dependent, and doesn't have to be constant.
// On PS3, measured it to be just shy of 80Mhz on the PPU and doesn't seem to change
if ( sm_nPerformanceFrequency == 0 )
sm_nPerformanceFrequency = sys_time_get_timebase_frequency();
#else
// calculate performance frequency the first time we use a timer
if ( 0 == sm_nPerformanceFrequency )
{
sm_nPerformanceFrequency = g_ClockSpeed;
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Returns current QueryPerformanceCounter value
//-----------------------------------------------------------------------------
int64 CReliableTimer::GetPerformanceCountNow()
{
//VPROF_BUDGET( "CReliableTimer::GetPerformanceCountNow", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
#ifdef _WIN32
if ( sm_bUseQPC )
{
LARGE_INTEGER li = {0};
QueryPerformanceCounter( &li );
return li.QuadPart;
}
else
{
CCycleCount CycleCount;
CycleCount.Sample();
return CycleCount.GetLongCycles();
}
#elif defined( _PS3 )
// use handy macro to grab tb
uint64 ulNow;
SYS_TIMEBASE_GET( ulNow );
return ulNow;
#else
uint64 un64;
__asm__ __volatile__ (
"rdtsc\n\t"
: "=A" (un64) );
return (int64)un64;
#endif
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "tier1/reliabletimer.h"
int64 CReliableTimer::sm_nPerformanceFrequency = 0;
bool CReliableTimer::sm_bUseQPC = false;
#ifdef _WIN32
#include "winlite.h"
#endif
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CReliableTimer::CReliableTimer()
{
m_nPerformanceCounterStart = 0;
m_nPerformanceCounterEnd = 0;
m_nPerformanceCounterLimit = 0;
#ifdef _WIN32
// calculate performance frequency the first time we use a timer
if ( 0 == sm_nPerformanceFrequency )
{
// Are we on a bad CPU?
sm_bUseQPC = false; // todo
const CPUInformation &cpu = *GetCPUInformation();
sm_bUseQPC = ( ( 0 == Q_stricmp( cpu.m_szProcessorID, "AuthenticAMD" ) )
&& ( cpu.m_nPhysicalProcessors > 1 )
&& !cpu.m_bSSE41 );
if ( sm_bUseQPC )
{
LARGE_INTEGER li;
QueryPerformanceFrequency( &li );
sm_nPerformanceFrequency = li.QuadPart;
}
else
{
sm_nPerformanceFrequency = g_ClockSpeed;
}
}
#elif defined(_PS3)
// On PowerPC, the time base register increment frequency is implementation dependent, and doesn't have to be constant.
// On PS3, measured it to be just shy of 80Mhz on the PPU and doesn't seem to change
if ( sm_nPerformanceFrequency == 0 )
sm_nPerformanceFrequency = sys_time_get_timebase_frequency();
#else
// calculate performance frequency the first time we use a timer
if ( 0 == sm_nPerformanceFrequency )
{
sm_nPerformanceFrequency = g_ClockSpeed;
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: Returns current QueryPerformanceCounter value
//-----------------------------------------------------------------------------
int64 CReliableTimer::GetPerformanceCountNow()
{
//VPROF_BUDGET( "CReliableTimer::GetPerformanceCountNow", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
#ifdef _WIN32
if ( sm_bUseQPC )
{
LARGE_INTEGER li = {0};
QueryPerformanceCounter( &li );
return li.QuadPart;
}
else
{
CCycleCount CycleCount;
CycleCount.Sample();
return CycleCount.GetLongCycles();
}
#elif defined( _PS3 )
// use handy macro to grab tb
uint64 ulNow;
SYS_TIMEBASE_GET( ulNow );
return ulNow;
#else
uint64 un64;
__asm__ __volatile__ (
"rdtsc\n\t"
: "=A" (un64) );
return (int64)un64;
#endif
}

View File

@@ -1,150 +1,150 @@
// Copyright 2008 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Internals shared between the Snappy implementation and its unittest.
#ifndef UTIL_SNAPPY_SNAPPY_INTERNAL_H_
#define UTIL_SNAPPY_SNAPPY_INTERNAL_H_
#include "snappy-stubs-internal.h"
namespace snappy {
namespace internal {
class WorkingMemory {
public:
WorkingMemory() : large_table_(NULL) { }
~WorkingMemory() { delete[] large_table_; }
// Allocates and clears a hash table using memory in "*this",
// stores the number of buckets in "*table_size" and returns a pointer to
// the base of the hash table.
uint16* GetHashTable(size_t input_size, int* table_size);
private:
uint16 small_table_[1<<10]; // 2KB
uint16* large_table_; // Allocated only when needed
SNAPPY_DISALLOW_COPY_AND_ASSIGN(WorkingMemory);
};
// Flat array compression that does not emit the "uncompressed length"
// prefix. Compresses "input" string to the "*op" buffer.
//
// REQUIRES: "input_length <= kBlockSize"
// REQUIRES: "op" points to an array of memory that is at least
// "MaxCompressedLength(input_length)" in size.
// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
// REQUIRES: "table_size" is a power of two
//
// Returns an "end" pointer into "op" buffer.
// "end - op" is the compressed size of "input".
char* CompressFragment(const char* input,
size_t input_length,
char* op,
uint16* table,
const int table_size);
// Return the largest n such that
//
// s1[0,n-1] == s2[0,n-1]
// and n <= (s2_limit - s2).
//
// Does not read *s2_limit or beyond.
// Does not read *(s1 + (s2_limit - s2)) or beyond.
// Requires that s2_limit >= s2.
//
// Separate implementation for x86_64, for speed. Uses the fact that
// x86_64 is little endian.
#if defined(ARCH_K8)
static inline int FindMatchLength(const char* s1,
const char* s2,
const char* s2_limit) {
DCHECK_GE(s2_limit, s2);
int matched = 0;
// Find out how long the match is. We loop over the data 64 bits at a
// time until we find a 64-bit block that doesn't match; then we find
// the first non-matching bit and use that to calculate the total
// length of the match.
while (PREDICT_TRUE(s2 <= s2_limit - 8)) {
if (PREDICT_FALSE(UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched))) {
s2 += 8;
matched += 8;
} else {
// On current (mid-2008) Opteron models there is a 3% more
// efficient code sequence to find the first non-matching byte.
// However, what follows is ~10% better on Intel Core 2 and newer,
// and we expect AMD's bsf instruction to improve.
uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);
int matching_bits = Bits::FindLSBSetNonZero64(x);
matched += matching_bits >> 3;
return matched;
}
}
while (PREDICT_TRUE(s2 < s2_limit)) {
if (PREDICT_TRUE(s1[matched] == *s2)) {
++s2;
++matched;
} else {
return matched;
}
}
return matched;
}
#else
static inline int FindMatchLength(const char* s1,
const char* s2,
const char* s2_limit) {
// Implementation based on the x86-64 version, above.
DCHECK_GE(s2_limit, s2);
int matched = 0;
while (s2 <= s2_limit - 4 &&
UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {
s2 += 4;
matched += 4;
}
if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
int matching_bits = Bits::FindLSBSetNonZero(x);
matched += matching_bits >> 3;
} else {
while ((s2 < s2_limit) && (s1[matched] == *s2)) {
++s2;
++matched;
}
}
return matched;
}
#endif
} // end namespace internal
} // end namespace snappy
#endif // UTIL_SNAPPY_SNAPPY_INTERNAL_H_
// Copyright 2008 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Internals shared between the Snappy implementation and its unittest.
#ifndef UTIL_SNAPPY_SNAPPY_INTERNAL_H_
#define UTIL_SNAPPY_SNAPPY_INTERNAL_H_
#include "snappy-stubs-internal.h"
namespace snappy {
namespace internal {
class WorkingMemory {
public:
WorkingMemory() : large_table_(NULL) { }
~WorkingMemory() { delete[] large_table_; }
// Allocates and clears a hash table using memory in "*this",
// stores the number of buckets in "*table_size" and returns a pointer to
// the base of the hash table.
uint16* GetHashTable(size_t input_size, int* table_size);
private:
uint16 small_table_[1<<10]; // 2KB
uint16* large_table_; // Allocated only when needed
SNAPPY_DISALLOW_COPY_AND_ASSIGN(WorkingMemory);
};
// Flat array compression that does not emit the "uncompressed length"
// prefix. Compresses "input" string to the "*op" buffer.
//
// REQUIRES: "input_length <= kBlockSize"
// REQUIRES: "op" points to an array of memory that is at least
// "MaxCompressedLength(input_length)" in size.
// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
// REQUIRES: "table_size" is a power of two
//
// Returns an "end" pointer into "op" buffer.
// "end - op" is the compressed size of "input".
char* CompressFragment(const char* input,
size_t input_length,
char* op,
uint16* table,
const int table_size);
// Return the largest n such that
//
// s1[0,n-1] == s2[0,n-1]
// and n <= (s2_limit - s2).
//
// Does not read *s2_limit or beyond.
// Does not read *(s1 + (s2_limit - s2)) or beyond.
// Requires that s2_limit >= s2.
//
// Separate implementation for x86_64, for speed. Uses the fact that
// x86_64 is little endian.
#if defined(ARCH_K8)
static inline int FindMatchLength(const char* s1,
const char* s2,
const char* s2_limit) {
DCHECK_GE(s2_limit, s2);
int matched = 0;
// Find out how long the match is. We loop over the data 64 bits at a
// time until we find a 64-bit block that doesn't match; then we find
// the first non-matching bit and use that to calculate the total
// length of the match.
while (PREDICT_TRUE(s2 <= s2_limit - 8)) {
if (PREDICT_FALSE(UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched))) {
s2 += 8;
matched += 8;
} else {
// On current (mid-2008) Opteron models there is a 3% more
// efficient code sequence to find the first non-matching byte.
// However, what follows is ~10% better on Intel Core 2 and newer,
// and we expect AMD's bsf instruction to improve.
uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);
int matching_bits = Bits::FindLSBSetNonZero64(x);
matched += matching_bits >> 3;
return matched;
}
}
while (PREDICT_TRUE(s2 < s2_limit)) {
if (PREDICT_TRUE(s1[matched] == *s2)) {
++s2;
++matched;
} else {
return matched;
}
}
return matched;
}
#else
static inline int FindMatchLength(const char* s1,
const char* s2,
const char* s2_limit) {
// Implementation based on the x86-64 version, above.
DCHECK_GE(s2_limit, s2);
int matched = 0;
while (s2 <= s2_limit - 4 &&
UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {
s2 += 4;
matched += 4;
}
if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
int matching_bits = Bits::FindLSBSetNonZero(x);
matched += matching_bits >> 3;
} else {
while ((s2 < s2_limit) && (s1[matched] == *s2)) {
++s2;
++matched;
}
}
return matched;
}
#endif
} // end namespace internal
} // end namespace snappy
#endif // UTIL_SNAPPY_SNAPPY_INTERNAL_H_

View File

@@ -1,72 +1,72 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include "snappy-sinksource.h"
namespace snappy {
Source::~Source() { }
Sink::~Sink() { }
char* Sink::GetAppendBuffer(size_t, char* scratch) {
return scratch;
}
ByteArraySource::~ByteArraySource() { }
size_t ByteArraySource::Available() const { return left_; }
const char* ByteArraySource::Peek(size_t* len) {
*len = left_;
return ptr_;
}
void ByteArraySource::Skip(size_t n) {
left_ -= n;
ptr_ += n;
}
UncheckedByteArraySink::~UncheckedByteArraySink() { }
void UncheckedByteArraySink::Append(const char* data, size_t n) {
// Do no copying if the caller filled in the result of GetAppendBuffer()
if (data != dest_) {
memcpy(dest_, data, n);
}
dest_ += n;
}
char* UncheckedByteArraySink::GetAppendBuffer(size_t, char*) {
return dest_;
}
}
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include "snappy-sinksource.h"
namespace snappy {
Source::~Source() { }
Sink::~Sink() { }
char* Sink::GetAppendBuffer(size_t, char* scratch) {
return scratch;
}
ByteArraySource::~ByteArraySource() { }
size_t ByteArraySource::Available() const { return left_; }
const char* ByteArraySource::Peek(size_t* len) {
*len = left_;
return ptr_;
}
void ByteArraySource::Skip(size_t n) {
left_ -= n;
ptr_ += n;
}
UncheckedByteArraySink::~UncheckedByteArraySink() { }
void UncheckedByteArraySink::Append(const char* data, size_t n) {
// Do no copying if the caller filled in the result of GetAppendBuffer()
if (data != dest_) {
memcpy(dest_, data, n);
}
dest_ += n;
}
char* UncheckedByteArraySink::GetAppendBuffer(size_t, char*) {
return dest_;
}
}

View File

@@ -1,45 +1,45 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#ifdef _WIN32
#pragma warning(disable:4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
#endif //_WIN32
#include <string>
#include "snappy-stubs-internal.h"
namespace snappy {
void Varint::Append32(string* s, uint32 value) {
char buf[Varint::kMax32];
const char* p = Varint::Encode32(buf, value);
s->append(buf, p - buf);
}
} // namespace snappy
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#ifdef _WIN32
#pragma warning(disable:4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
#endif //_WIN32
#include <string>
#include "snappy-stubs-internal.h"
namespace snappy {
void Varint::Append32(string* s, uint32 value) {
char buf[Varint::kMax32];
const char* p = Varint::Encode32(buf, value);
s->append(buf, p - buf);
}
} // namespace snappy

View File

@@ -1,496 +1,496 @@
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Various stubs for the open-source version of Snappy.
#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tier0/platform.h"
// don't use iostream, this make us fail to run under OS X 10.5
//#include <iostream>
#include <string>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_MMAN
#include <sys/mman.h>
#endif
#if defined(__x86_64__)
// Enable 64-bit optimized versions of some routines.
#define ARCH_K8 1
#endif
// Needed by OS X, among others.
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
// Pull in std::min, std::ostream, and the likes. This is safe because this
// header file is never used from any public header files.
using namespace std;
// We only define ARRAYSIZE if it isn't already defined, because this definition
// is not very good.
#ifndef ARRAYSIZE
// The size of an array, if known at compile-time.
// Will give unexpected results if used on a pointer.
#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
#endif
// Static prediction hints.
#ifdef HAVE_BUILTIN_EXPECT
#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define PREDICT_FALSE(x) x
#define PREDICT_TRUE(x) x
#endif
// This is only used for recomputing the tag byte table used during
// decompression; for simplicity we just remove it from the open-source
// version (anyone who wants to regenerate it can just do the call
// themselves within main()).
#define DEFINE_bool(flag_name, default_value, description) \
bool FLAGS_ ## flag_name = default_value;
#define DECLARE_bool(flag_name) \
extern bool FLAGS_ ## flag_name;
#define REGISTER_MODULE_INITIALIZER(name, code)
#define SNAPPY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
namespace snappy {
static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
// Logging.
#define LOG(level) LogMessage()
#define VLOG(level) true ? (void)0 : \
snappy::LogMessageVoidify() & snappy::LogMessage()
class LogMessage {
public:
LogMessage() { }
~LogMessage() {
fprintf( stderr, "\n" );
//cerr << endl;
}
LogMessage& operator<<(const std::string& msg) {
//cerr << msg;
fprintf( stderr, "%s", msg.c_str() );
return *this;
}
LogMessage& operator<<(int x) {
fprintf( stderr, "%d", x );
//cerr << x;
return *this;
}
};
// Asserts, both versions activated in debug mode only,
// and ones that are always active.
#define CRASH_UNLESS(condition) \
PREDICT_TRUE(condition) ? (void)0 : \
snappy::LogMessageVoidify() & snappy::LogMessageCrash()
class LogMessageCrash : public LogMessage {
public:
LogMessageCrash() { }
#if _MSC_VER == 1700
// Bogus warning from VS 2012:
// warning C4722: 'snappy::LogMessageCrash::~LogMessageCrash' : destructor never returns, potential memory leak
#pragma warning(push)
#pragma warning(disable : 4722)
#endif
~LogMessageCrash() {
fprintf( stderr, "\n" );
// cerr << endl;
abort();
}
};
#if _MSC_VER == 1700
#pragma warning(pop)
#endif
// This class is used to explicitly ignore values in the conditional
// logging macros. This avoids compiler warnings like "value computed
// is not used" and "statement has no effect".
class LogMessageVoidify {
public:
LogMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(const LogMessage&) { }
};
#define CHECK(cond) CRASH_UNLESS(cond)
#define CHECK_LE(a, b) CRASH_UNLESS((a) <= (b))
#define CHECK_GE(a, b) CRASH_UNLESS((a) >= (b))
#define CHECK_EQ(a, b) CRASH_UNLESS((a) == (b))
#define CHECK_NE(a, b) CRASH_UNLESS((a) != (b))
#define CHECK_LT(a, b) CRASH_UNLESS((a) < (b))
#define CHECK_GT(a, b) CRASH_UNLESS((a) > (b))
#ifdef NDEBUG
#define DCHECK(cond) CRASH_UNLESS(true)
#define DCHECK_LE(a, b) CRASH_UNLESS(true)
#define DCHECK_GE(a, b) CRASH_UNLESS(true)
#define DCHECK_EQ(a, b) CRASH_UNLESS(true)
#define DCHECK_NE(a, b) CRASH_UNLESS(true)
#define DCHECK_LT(a, b) CRASH_UNLESS(true)
#define DCHECK_GT(a, b) CRASH_UNLESS(true)
#else
#define DCHECK(cond) CHECK(cond)
#define DCHECK_LE(a, b) CHECK_LE(a, b)
#define DCHECK_GE(a, b) CHECK_GE(a, b)
#define DCHECK_EQ(a, b) CHECK_EQ(a, b)
#define DCHECK_NE(a, b) CHECK_NE(a, b)
#define DCHECK_LT(a, b) CHECK_LT(a, b)
#define DCHECK_GT(a, b) CHECK_GT(a, b)
#endif
// Potentially unaligned loads and stores.
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
#define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
#else
// These functions are provided for architectures that don't support
// unaligned loads and stores.
inline uint16 UNALIGNED_LOAD16(const void *p) {
uint16 t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint32 UNALIGNED_LOAD32(const void *p) {
uint32 t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint64 UNALIGNED_LOAD64(const void *p) {
uint64 t;
memcpy(&t, p, sizeof t);
return t;
}
inline void UNALIGNED_STORE16(void *p, uint16 v) {
memcpy(p, &v, sizeof v);
}
inline void UNALIGNED_STORE32(void *p, uint32 v) {
memcpy(p, &v, sizeof v);
}
inline void UNALIGNED_STORE64(void *p, uint64 v) {
memcpy(p, &v, sizeof v);
}
#endif
// The following guarantees declaration of the byte swap functions.
#ifdef WORDS_BIGENDIAN
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_16(x) _byteswap_ushort(x)
#define bswap_32(x) _byteswap_ulong(x)
#define bswap_64(x) _byteswap_uint64(x)
#elif defined(__APPLE__)
// Mac OS X / Darwin features
#include <libkern/OSByteOrder.h>
#define bswap_16(x) OSSwapInt16(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
#else
#include <byteswap.h>
#endif
#endif // WORDS_BIGENDIAN
// Convert to little-endian storage, opposite of network format.
// Convert x from host to little endian: x = LittleEndian.FromHost(x);
// convert x from little endian to host: x = LittleEndian.ToHost(x);
//
// Store values into unaligned memory converting to little endian order:
// LittleEndian.Store16(p, x);
//
// Load unaligned values stored in little endian converting to host order:
// x = LittleEndian.Load16(p);
class LittleEndian {
public:
// Conversion functions.
#ifdef WORDS_BIGENDIAN
static uint16 FromHost16(uint16 x) { return bswap_16(x); }
static uint16 ToHost16(uint16 x) { return bswap_16(x); }
static uint32 FromHost32(uint32 x) { return bswap_32(x); }
static uint32 ToHost32(uint32 x) { return bswap_32(x); }
static bool IsLittleEndian() { return false; }
#else // !defined(WORDS_BIGENDIAN)
static uint16 FromHost16(uint16 x) { return x; }
static uint16 ToHost16(uint16 x) { return x; }
static uint32 FromHost32(uint32 x) { return x; }
static uint32 ToHost32(uint32 x) { return x; }
static bool IsLittleEndian() { return true; }
#endif // !defined(WORDS_BIGENDIAN)
// Functions to do unaligned loads and stores in little-endian order.
static uint16 Load16(const void *p) {
return ToHost16(UNALIGNED_LOAD16(p));
}
static void Store16(void *p, uint16 v) {
UNALIGNED_STORE16(p, FromHost16(v));
}
static uint32 Load32(const void *p) {
return ToHost32(UNALIGNED_LOAD32(p));
}
static void Store32(void *p, uint32 v) {
UNALIGNED_STORE32(p, FromHost32(v));
}
};
// Some bit-manipulation functions.
class Bits {
public:
// Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0.
static int Log2Floor(uint32 n);
// Return the first set least / most significant bit, 0-indexed. Returns an
// undefined value if n == 0. FindLSBSetNonZero() is similar to ffs() except
// that it's 0-indexed.
static int FindLSBSetNonZero(uint32 n);
static int FindLSBSetNonZero64(uint64 n);
private:
SNAPPY_DISALLOW_COPY_AND_ASSIGN(Bits);
};
#ifdef HAVE_BUILTIN_CTZ
inline int Bits::Log2Floor(uint32 n) {
return n == 0 ? -1 : 31 ^ __builtin_clz(n);
}
inline int Bits::FindLSBSetNonZero(uint32 n) {
return __builtin_ctz(n);
}
inline int Bits::FindLSBSetNonZero64(uint64 n) {
return __builtin_ctzll(n);
}
#else // Portable versions.
inline int Bits::Log2Floor(uint32 n) {
if (n == 0)
return -1;
int log = 0;
uint32 value = n;
for (int i = 4; i >= 0; --i) {
int shift = (1 << i);
uint32 x = value >> shift;
if (x != 0) {
value = x;
log += shift;
}
}
assert(value == 1);
return log;
}
inline int Bits::FindLSBSetNonZero(uint32 n) {
int rc = 31;
for (int i = 4, shift = 1 << 4; i >= 0; --i) {
const uint32 x = n << shift;
if (x != 0) {
n = x;
rc -= shift;
}
shift >>= 1;
}
return rc;
}
// FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
inline int Bits::FindLSBSetNonZero64(uint64 n) {
const uint32 bottombits = static_cast<uint32>(n);
if (bottombits == 0) {
// Bottom bits are zero, so scan in top bits
return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
} else {
return FindLSBSetNonZero(bottombits);
}
}
#endif // End portable versions.
// Variable-length integer encoding.
class Varint {
public:
// Maximum lengths of varint encoding of uint32.
static const int kMax32 = 5;
// Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
// Never reads a character at or beyond limit. If a valid/terminated varint32
// was found in the range, stores it in *OUTPUT and returns a pointer just
// past the last byte of the varint32. Else returns NULL. On success,
// "result <= limit".
static const char* Parse32WithLimit(const char* ptr, const char* limit,
uint32* OUTPUT);
// REQUIRES "ptr" points to a buffer of length sufficient to hold "v".
// EFFECTS Encodes "v" into "ptr" and returns a pointer to the
// byte just past the last encoded byte.
static char* Encode32(char* ptr, uint32 v);
// EFFECTS Appends the varint representation of "value" to "*s".
static void Append32(string* s, uint32 value);
};
inline const char* Varint::Parse32WithLimit(const char* p,
const char* l,
uint32* OUTPUT) {
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
uint32 b, result;
if (ptr >= limit) return NULL;
b = *(ptr++); result = b & 127; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 7; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
return NULL; // Value is too long to be a varint32
done:
*OUTPUT = result;
return reinterpret_cast<const char*>(ptr);
}
inline char* Varint::Encode32(char* sptr, uint32 v) {
// Operate on characters as unsigneds
unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
static const int B = 128;
if (v < (1<<7)) {
*(ptr++) = v;
} else if (v < (1<<14)) {
*(ptr++) = v | B;
*(ptr++) = v>>7;
} else if (v < (1<<21)) {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = v>>14;
} else if (v < (1<<28)) {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = (v>>14) | B;
*(ptr++) = v>>21;
} else {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = (v>>14) | B;
*(ptr++) = (v>>21) | B;
*(ptr++) = v>>28;
}
return reinterpret_cast<char*>(ptr);
}
// If you know the internal layout of the std::string in use, you can
// replace this function with one that resizes the string without
// filling the new space with zeros (if applicable) --
// it will be non-portable but faster.
inline void STLStringResizeUninitialized(string* s, size_t new_size) {
s->resize(new_size);
}
// Return a mutable char* pointing to a string's internal buffer,
// which may not be null-terminated. Writing through this pointer will
// modify the string.
//
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
// next call to a string method that invalidates iterators.
//
// As of 2006-04, there is no standard-blessed way of getting a
// mutable reference to a string's internal buffer. However, issue 530
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)
// proposes this as the method. It will officially be part of the standard
// for C++0x. This should already work on all current implementations.
inline char* string_as_array(string* str) {
return str->empty() ? NULL : &*str->begin();
}
} // namespace snappy
#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Various stubs for the open-source version of Snappy.
#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tier0/platform.h"
// don't use iostream, this make us fail to run under OS X 10.5
//#include <iostream>
#include <string>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_MMAN
#include <sys/mman.h>
#endif
#if defined(__x86_64__)
// Enable 64-bit optimized versions of some routines.
#define ARCH_K8 1
#endif
// Needed by OS X, among others.
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
// Pull in std::min, std::ostream, and the likes. This is safe because this
// header file is never used from any public header files.
using namespace std;
// We only define ARRAYSIZE if it isn't already defined, because this definition
// is not very good.
#ifndef ARRAYSIZE
// The size of an array, if known at compile-time.
// Will give unexpected results if used on a pointer.
#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
#endif
// Static prediction hints.
#ifdef HAVE_BUILTIN_EXPECT
#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
#else
#define PREDICT_FALSE(x) x
#define PREDICT_TRUE(x) x
#endif
// This is only used for recomputing the tag byte table used during
// decompression; for simplicity we just remove it from the open-source
// version (anyone who wants to regenerate it can just do the call
// themselves within main()).
#define DEFINE_bool(flag_name, default_value, description) \
bool FLAGS_ ## flag_name = default_value;
#define DECLARE_bool(flag_name) \
extern bool FLAGS_ ## flag_name;
#define REGISTER_MODULE_INITIALIZER(name, code)
#define SNAPPY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
namespace snappy {
static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
// Logging.
#define LOG(level) LogMessage()
#define VLOG(level) true ? (void)0 : \
snappy::LogMessageVoidify() & snappy::LogMessage()
class LogMessage {
public:
LogMessage() { }
~LogMessage() {
fprintf( stderr, "\n" );
//cerr << endl;
}
LogMessage& operator<<(const std::string& msg) {
//cerr << msg;
fprintf( stderr, "%s", msg.c_str() );
return *this;
}
LogMessage& operator<<(int x) {
fprintf( stderr, "%d", x );
//cerr << x;
return *this;
}
};
// Asserts, both versions activated in debug mode only,
// and ones that are always active.
#define CRASH_UNLESS(condition) \
PREDICT_TRUE(condition) ? (void)0 : \
snappy::LogMessageVoidify() & snappy::LogMessageCrash()
class LogMessageCrash : public LogMessage {
public:
LogMessageCrash() { }
#if _MSC_VER == 1700
// Bogus warning from VS 2012:
// warning C4722: 'snappy::LogMessageCrash::~LogMessageCrash' : destructor never returns, potential memory leak
#pragma warning(push)
#pragma warning(disable : 4722)
#endif
~LogMessageCrash() {
fprintf( stderr, "\n" );
// cerr << endl;
abort();
}
};
#if _MSC_VER == 1700
#pragma warning(pop)
#endif
// This class is used to explicitly ignore values in the conditional
// logging macros. This avoids compiler warnings like "value computed
// is not used" and "statement has no effect".
class LogMessageVoidify {
public:
LogMessageVoidify() { }
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(const LogMessage&) { }
};
#define CHECK(cond) CRASH_UNLESS(cond)
#define CHECK_LE(a, b) CRASH_UNLESS((a) <= (b))
#define CHECK_GE(a, b) CRASH_UNLESS((a) >= (b))
#define CHECK_EQ(a, b) CRASH_UNLESS((a) == (b))
#define CHECK_NE(a, b) CRASH_UNLESS((a) != (b))
#define CHECK_LT(a, b) CRASH_UNLESS((a) < (b))
#define CHECK_GT(a, b) CRASH_UNLESS((a) > (b))
#ifdef NDEBUG
#define DCHECK(cond) CRASH_UNLESS(true)
#define DCHECK_LE(a, b) CRASH_UNLESS(true)
#define DCHECK_GE(a, b) CRASH_UNLESS(true)
#define DCHECK_EQ(a, b) CRASH_UNLESS(true)
#define DCHECK_NE(a, b) CRASH_UNLESS(true)
#define DCHECK_LT(a, b) CRASH_UNLESS(true)
#define DCHECK_GT(a, b) CRASH_UNLESS(true)
#else
#define DCHECK(cond) CHECK(cond)
#define DCHECK_LE(a, b) CHECK_LE(a, b)
#define DCHECK_GE(a, b) CHECK_GE(a, b)
#define DCHECK_EQ(a, b) CHECK_EQ(a, b)
#define DCHECK_NE(a, b) CHECK_NE(a, b)
#define DCHECK_LT(a, b) CHECK_LT(a, b)
#define DCHECK_GT(a, b) CHECK_GT(a, b)
#endif
// Potentially unaligned loads and stores.
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
#define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
#else
// These functions are provided for architectures that don't support
// unaligned loads and stores.
inline uint16 UNALIGNED_LOAD16(const void *p) {
uint16 t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint32 UNALIGNED_LOAD32(const void *p) {
uint32 t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint64 UNALIGNED_LOAD64(const void *p) {
uint64 t;
memcpy(&t, p, sizeof t);
return t;
}
inline void UNALIGNED_STORE16(void *p, uint16 v) {
memcpy(p, &v, sizeof v);
}
inline void UNALIGNED_STORE32(void *p, uint32 v) {
memcpy(p, &v, sizeof v);
}
inline void UNALIGNED_STORE64(void *p, uint64 v) {
memcpy(p, &v, sizeof v);
}
#endif
// The following guarantees declaration of the byte swap functions.
#ifdef WORDS_BIGENDIAN
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_16(x) _byteswap_ushort(x)
#define bswap_32(x) _byteswap_ulong(x)
#define bswap_64(x) _byteswap_uint64(x)
#elif defined(__APPLE__)
// Mac OS X / Darwin features
#include <libkern/OSByteOrder.h>
#define bswap_16(x) OSSwapInt16(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
#else
#include <byteswap.h>
#endif
#endif // WORDS_BIGENDIAN
// Convert to little-endian storage, opposite of network format.
// Convert x from host to little endian: x = LittleEndian.FromHost(x);
// convert x from little endian to host: x = LittleEndian.ToHost(x);
//
// Store values into unaligned memory converting to little endian order:
// LittleEndian.Store16(p, x);
//
// Load unaligned values stored in little endian converting to host order:
// x = LittleEndian.Load16(p);
class LittleEndian {
public:
// Conversion functions.
#ifdef WORDS_BIGENDIAN
static uint16 FromHost16(uint16 x) { return bswap_16(x); }
static uint16 ToHost16(uint16 x) { return bswap_16(x); }
static uint32 FromHost32(uint32 x) { return bswap_32(x); }
static uint32 ToHost32(uint32 x) { return bswap_32(x); }
static bool IsLittleEndian() { return false; }
#else // !defined(WORDS_BIGENDIAN)
static uint16 FromHost16(uint16 x) { return x; }
static uint16 ToHost16(uint16 x) { return x; }
static uint32 FromHost32(uint32 x) { return x; }
static uint32 ToHost32(uint32 x) { return x; }
static bool IsLittleEndian() { return true; }
#endif // !defined(WORDS_BIGENDIAN)
// Functions to do unaligned loads and stores in little-endian order.
static uint16 Load16(const void *p) {
return ToHost16(UNALIGNED_LOAD16(p));
}
static void Store16(void *p, uint16 v) {
UNALIGNED_STORE16(p, FromHost16(v));
}
static uint32 Load32(const void *p) {
return ToHost32(UNALIGNED_LOAD32(p));
}
static void Store32(void *p, uint32 v) {
UNALIGNED_STORE32(p, FromHost32(v));
}
};
// Some bit-manipulation functions.
class Bits {
public:
// Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0.
static int Log2Floor(uint32 n);
// Return the first set least / most significant bit, 0-indexed. Returns an
// undefined value if n == 0. FindLSBSetNonZero() is similar to ffs() except
// that it's 0-indexed.
static int FindLSBSetNonZero(uint32 n);
static int FindLSBSetNonZero64(uint64 n);
private:
SNAPPY_DISALLOW_COPY_AND_ASSIGN(Bits);
};
#ifdef HAVE_BUILTIN_CTZ
inline int Bits::Log2Floor(uint32 n) {
return n == 0 ? -1 : 31 ^ __builtin_clz(n);
}
inline int Bits::FindLSBSetNonZero(uint32 n) {
return __builtin_ctz(n);
}
inline int Bits::FindLSBSetNonZero64(uint64 n) {
return __builtin_ctzll(n);
}
#else // Portable versions.
inline int Bits::Log2Floor(uint32 n) {
if (n == 0)
return -1;
int log = 0;
uint32 value = n;
for (int i = 4; i >= 0; --i) {
int shift = (1 << i);
uint32 x = value >> shift;
if (x != 0) {
value = x;
log += shift;
}
}
assert(value == 1);
return log;
}
inline int Bits::FindLSBSetNonZero(uint32 n) {
int rc = 31;
for (int i = 4, shift = 1 << 4; i >= 0; --i) {
const uint32 x = n << shift;
if (x != 0) {
n = x;
rc -= shift;
}
shift >>= 1;
}
return rc;
}
// FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
inline int Bits::FindLSBSetNonZero64(uint64 n) {
const uint32 bottombits = static_cast<uint32>(n);
if (bottombits == 0) {
// Bottom bits are zero, so scan in top bits
return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
} else {
return FindLSBSetNonZero(bottombits);
}
}
#endif // End portable versions.
// Variable-length integer encoding.
class Varint {
public:
// Maximum lengths of varint encoding of uint32.
static const int kMax32 = 5;
// Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
// Never reads a character at or beyond limit. If a valid/terminated varint32
// was found in the range, stores it in *OUTPUT and returns a pointer just
// past the last byte of the varint32. Else returns NULL. On success,
// "result <= limit".
static const char* Parse32WithLimit(const char* ptr, const char* limit,
uint32* OUTPUT);
// REQUIRES "ptr" points to a buffer of length sufficient to hold "v".
// EFFECTS Encodes "v" into "ptr" and returns a pointer to the
// byte just past the last encoded byte.
static char* Encode32(char* ptr, uint32 v);
// EFFECTS Appends the varint representation of "value" to "*s".
static void Append32(string* s, uint32 value);
};
inline const char* Varint::Parse32WithLimit(const char* p,
const char* l,
uint32* OUTPUT) {
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
uint32 b, result;
if (ptr >= limit) return NULL;
b = *(ptr++); result = b & 127; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 7; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
if (ptr >= limit) return NULL;
b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
return NULL; // Value is too long to be a varint32
done:
*OUTPUT = result;
return reinterpret_cast<const char*>(ptr);
}
inline char* Varint::Encode32(char* sptr, uint32 v) {
// Operate on characters as unsigneds
unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
static const int B = 128;
if (v < (1<<7)) {
*(ptr++) = v;
} else if (v < (1<<14)) {
*(ptr++) = v | B;
*(ptr++) = v>>7;
} else if (v < (1<<21)) {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = v>>14;
} else if (v < (1<<28)) {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = (v>>14) | B;
*(ptr++) = v>>21;
} else {
*(ptr++) = v | B;
*(ptr++) = (v>>7) | B;
*(ptr++) = (v>>14) | B;
*(ptr++) = (v>>21) | B;
*(ptr++) = v>>28;
}
return reinterpret_cast<char*>(ptr);
}
// If you know the internal layout of the std::string in use, you can
// replace this function with one that resizes the string without
// filling the new space with zeros (if applicable) --
// it will be non-portable but faster.
inline void STLStringResizeUninitialized(string* s, size_t new_size) {
s->resize(new_size);
}
// Return a mutable char* pointing to a string's internal buffer,
// which may not be null-terminated. Writing through this pointer will
// modify the string.
//
// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
// next call to a string method that invalidates iterators.
//
// As of 2006-04, there is no standard-blessed way of getting a
// mutable reference to a string's internal buffer. However, issue 530
// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)
// proposes this as the method. It will officially be part of the standard
// for C++0x. This should already work on all current implementations.
inline char* string_as_array(string* str) {
return str->empty() ? NULL : &*str->begin();
}
} // namespace snappy
#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_

File diff suppressed because it is too large Load Diff

View File

@@ -1,141 +1,141 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//===========================================================================//
#include "tier1/sparsematrix.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void CSparseMatrix::AdjustAllRowIndicesAfter( int nStartRow, int nDelta )
{
// now, we need to offset the starting position of all subsequent rows by -1 to compensate for the removal of this element
for( int nOtherRow = nStartRow + 1 ; nOtherRow < Height(); nOtherRow++ )
{
m_rowDescriptors[nOtherRow].m_nDataIndex += nDelta;
}
}
void CSparseMatrix::SetDimensions( int nNumRows, int nNumCols )
{
m_nNumRows = nNumRows;
m_nNumCols = nNumCols;
m_entries.SetCount( 0 );
m_rowDescriptors.SetCount( m_nNumRows );
// and set all rows to be empty
for( int i = 0; i < m_nNumRows; i++ )
{
m_rowDescriptors[i].m_nNonZeroCount = 0;
m_rowDescriptors[i].m_nDataIndex = 0;
}
m_nHighestRowAppendedTo = -1;
}
void CSparseMatrix::SetElement( int nRow, int nCol, float flValue )
{
Assert( nCol < m_nNumCols );
int nCount = m_rowDescriptors[nRow].m_nNonZeroCount;
bool bValueIsZero = ( flValue == 0.0 );
int nFirstEntryIndex = m_rowDescriptors[nRow].m_nDataIndex;
if ( nCount )
{
NonZeroValueDescriptor_t *pValue = &( m_entries[nFirstEntryIndex] );
int i;
for( i = 0; i < nCount; i++ )
{
int nIdx = pValue->m_nColumnNumber;
if ( nIdx == nCol ) // we found it!
{
if ( !bValueIsZero )
{
// we want to overwrite the existing value
pValue->m_flValue = flValue;
}
else
{
// there is a non-zero element currently at this position. We need to remove it
// and we need to remove its storage.
m_rowDescriptors[nRow].m_nNonZeroCount--;
m_entries.Remove( nFirstEntryIndex + i );
// now, we need to offset the starting position of all subsequent rows by -1 to compensate for the removal of this element
AdjustAllRowIndicesAfter( nRow, -1 );
}
return;
}
if ( nIdx > nCol )
{
break;
}
pValue++;
}
// we did not find an entry for this cell. If we were writing zero, fine - we are
// done, otherwise insert
if (! bValueIsZero )
{
m_rowDescriptors[nRow].m_nNonZeroCount++;
NonZeroValueDescriptor_t newValue;
newValue.m_nColumnNumber = nCol;
newValue.m_flValue = flValue;
if ( i == nCount ) // need to append
{
m_entries.InsertAfter( nFirstEntryIndex + nCount - 1, newValue );
}
else
{
m_entries.InsertBefore( nFirstEntryIndex + i, newValue );
}
// now, we need to offset the starting position of all subsequent rows by -1 to compensate for the addition of this element
AdjustAllRowIndicesAfter( nRow, +1 );
}
}
else
{
// row is empty. We may need to insert
if ( ! bValueIsZero )
{
m_rowDescriptors[nRow].m_nNonZeroCount++;
NonZeroValueDescriptor_t newValue;
newValue.m_nColumnNumber = nCol;
newValue.m_flValue = flValue;
m_entries.InsertBefore( nFirstEntryIndex, newValue );
AdjustAllRowIndicesAfter( nRow, +1 );
}
}
}
void CSparseMatrix::FinishedAppending( void )
{
// set all pointers to space for subsequent rows to the right value
for( int i = m_nHighestRowAppendedTo + 1 ; i < Height(); i++ )
{
m_rowDescriptors[i].m_nDataIndex = m_entries.Count();
}
}
void CSparseMatrix::AppendElement( int nRow, int nColumn, float flValue )
{
if ( flValue != 0.0 )
{
if ( m_nHighestRowAppendedTo != nRow )
{
Assert( nRow > m_nHighestRowAppendedTo );
for( int i = m_nHighestRowAppendedTo + 1; i <= nRow; i++ )
{
m_rowDescriptors[i].m_nDataIndex = m_entries.Count();
}
}
m_nHighestRowAppendedTo = nRow;
m_rowDescriptors[nRow].m_nNonZeroCount++;
NonZeroValueDescriptor_t newDesc;
newDesc.m_nColumnNumber = nColumn;
newDesc.m_flValue = flValue;
m_entries.AddToTail( newDesc );
}
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//===========================================================================//
#include "tier1/sparsematrix.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void CSparseMatrix::AdjustAllRowIndicesAfter( int nStartRow, int nDelta )
{
// now, we need to offset the starting position of all subsequent rows by -1 to compensate for the removal of this element
for( int nOtherRow = nStartRow + 1 ; nOtherRow < Height(); nOtherRow++ )
{
m_rowDescriptors[nOtherRow].m_nDataIndex += nDelta;
}
}
void CSparseMatrix::SetDimensions( int nNumRows, int nNumCols )
{
m_nNumRows = nNumRows;
m_nNumCols = nNumCols;
m_entries.SetCount( 0 );
m_rowDescriptors.SetCount( m_nNumRows );
// and set all rows to be empty
for( int i = 0; i < m_nNumRows; i++ )
{
m_rowDescriptors[i].m_nNonZeroCount = 0;
m_rowDescriptors[i].m_nDataIndex = 0;
}
m_nHighestRowAppendedTo = -1;
}
void CSparseMatrix::SetElement( int nRow, int nCol, float flValue )
{
Assert( nCol < m_nNumCols );
int nCount = m_rowDescriptors[nRow].m_nNonZeroCount;
bool bValueIsZero = ( flValue == 0.0 );
int nFirstEntryIndex = m_rowDescriptors[nRow].m_nDataIndex;
if ( nCount )
{
NonZeroValueDescriptor_t *pValue = &( m_entries[nFirstEntryIndex] );
int i;
for( i = 0; i < nCount; i++ )
{
int nIdx = pValue->m_nColumnNumber;
if ( nIdx == nCol ) // we found it!
{
if ( !bValueIsZero )
{
// we want to overwrite the existing value
pValue->m_flValue = flValue;
}
else
{
// there is a non-zero element currently at this position. We need to remove it
// and we need to remove its storage.
m_rowDescriptors[nRow].m_nNonZeroCount--;
m_entries.Remove( nFirstEntryIndex + i );
// now, we need to offset the starting position of all subsequent rows by -1 to compensate for the removal of this element
AdjustAllRowIndicesAfter( nRow, -1 );
}
return;
}
if ( nIdx > nCol )
{
break;
}
pValue++;
}
// we did not find an entry for this cell. If we were writing zero, fine - we are
// done, otherwise insert
if (! bValueIsZero )
{
m_rowDescriptors[nRow].m_nNonZeroCount++;
NonZeroValueDescriptor_t newValue;
newValue.m_nColumnNumber = nCol;
newValue.m_flValue = flValue;
if ( i == nCount ) // need to append
{
m_entries.InsertAfter( nFirstEntryIndex + nCount - 1, newValue );
}
else
{
m_entries.InsertBefore( nFirstEntryIndex + i, newValue );
}
// now, we need to offset the starting position of all subsequent rows by -1 to compensate for the addition of this element
AdjustAllRowIndicesAfter( nRow, +1 );
}
}
else
{
// row is empty. We may need to insert
if ( ! bValueIsZero )
{
m_rowDescriptors[nRow].m_nNonZeroCount++;
NonZeroValueDescriptor_t newValue;
newValue.m_nColumnNumber = nCol;
newValue.m_flValue = flValue;
m_entries.InsertBefore( nFirstEntryIndex, newValue );
AdjustAllRowIndicesAfter( nRow, +1 );
}
}
}
void CSparseMatrix::FinishedAppending( void )
{
// set all pointers to space for subsequent rows to the right value
for( int i = m_nHighestRowAppendedTo + 1 ; i < Height(); i++ )
{
m_rowDescriptors[i].m_nDataIndex = m_entries.Count();
}
}
void CSparseMatrix::AppendElement( int nRow, int nColumn, float flValue )
{
if ( flValue != 0.0 )
{
if ( m_nHighestRowAppendedTo != nRow )
{
Assert( nRow > m_nHighestRowAppendedTo );
for( int i = m_nHighestRowAppendedTo + 1; i <= nRow; i++ )
{
m_rowDescriptors[i].m_nDataIndex = m_entries.Count();
}
}
m_nHighestRowAppendedTo = nRow;
m_rowDescriptors[nRow].m_nNonZeroCount++;
NonZeroValueDescriptor_t newDesc;
newDesc.m_nColumnNumber = nColumn;
newDesc.m_flValue = flValue;
m_entries.AddToTail( newDesc );
}
}

View File

@@ -1,91 +1,91 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//==================================================================================================
#include "strtools.h"
#include "utlvector.h"
CSplitString::CSplitString(const char *pString, const char **pSeparators, int nSeparators)
{
Construct(pString, pSeparators, nSeparators);
};
CSplitString::CSplitString( const char *pString, const char *pSeparator)
{
Construct( pString, &pSeparator, 1 );
}
CSplitString::~CSplitString()
{
if(m_szBuffer)
delete [] m_szBuffer;
}
void CSplitString::Construct( const char *pString, const char **pSeparators, int nSeparators )
{
//////////////////////////////////////////////////////////////////////////
// make a duplicate of the original string. We'll use pieces of this duplicate to tokenize the string
// and create NULL-terminated tokens of the original string
//
int nOriginalStringLength = V_strlen(pString);
m_szBuffer = new char[nOriginalStringLength + 1];
memcpy(m_szBuffer, pString, nOriginalStringLength + 1);
this->Purge();
const char *pCurPos = pString;
while ( 1 )
{
int iFirstSeparator = -1;
const char *pFirstSeparator = 0;
for ( int i=0; i < nSeparators; i++ )
{
const char *pTest = V_stristr( pCurPos, pSeparators[i] );
if ( pTest && (!pFirstSeparator || pTest < pFirstSeparator) )
{
iFirstSeparator = i;
pFirstSeparator = pTest;
}
}
if ( pFirstSeparator )
{
// Split on this separator and continue on.
int separatorLen = strlen( pSeparators[iFirstSeparator] );
if ( pFirstSeparator > pCurPos )
{
//////////////////////////////////////////////////////////////////////////
/// Cut the token out of the duplicate string
char *pTokenInDuplicate = m_szBuffer + (pCurPos - pString);
int nTokenLength = pFirstSeparator-pCurPos;
Assert(nTokenLength > 0 && !memcmp(pTokenInDuplicate,pCurPos,nTokenLength));
pTokenInDuplicate[nTokenLength] = '\0';
this->AddToTail( pTokenInDuplicate /*AllocString( pCurPos, pFirstSeparator-pCurPos )*/ );
}
pCurPos = pFirstSeparator + separatorLen;
}
else
{
// Copy the rest of the string
if ( int nTokenLength = strlen( pCurPos ) )
{
//////////////////////////////////////////////////////////////////////////
// There's no need to cut this token, because there's no separator after it.
// just add its copy in the buffer to the tail
char *pTokenInDuplicate = m_szBuffer + (pCurPos - pString);
Assert(!memcmp(pTokenInDuplicate, pCurPos, nTokenLength));
this->AddToTail( pTokenInDuplicate/*AllocString( pCurPos, -1 )*/ );
}
return;
}
}
}
void CSplitString::PurgeAndDeleteElements()
{
Purge();
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//
//==================================================================================================
#include "strtools.h"
#include "utlvector.h"
CSplitString::CSplitString(const char *pString, const char **pSeparators, int nSeparators)
{
Construct(pString, pSeparators, nSeparators);
};
CSplitString::CSplitString( const char *pString, const char *pSeparator)
{
Construct( pString, &pSeparator, 1 );
}
CSplitString::~CSplitString()
{
if(m_szBuffer)
delete [] m_szBuffer;
}
void CSplitString::Construct( const char *pString, const char **pSeparators, int nSeparators )
{
//////////////////////////////////////////////////////////////////////////
// make a duplicate of the original string. We'll use pieces of this duplicate to tokenize the string
// and create NULL-terminated tokens of the original string
//
int nOriginalStringLength = V_strlen(pString);
m_szBuffer = new char[nOriginalStringLength + 1];
memcpy(m_szBuffer, pString, nOriginalStringLength + 1);
this->Purge();
const char *pCurPos = pString;
while ( 1 )
{
int iFirstSeparator = -1;
const char *pFirstSeparator = 0;
for ( int i=0; i < nSeparators; i++ )
{
const char *pTest = V_stristr( pCurPos, pSeparators[i] );
if ( pTest && (!pFirstSeparator || pTest < pFirstSeparator) )
{
iFirstSeparator = i;
pFirstSeparator = pTest;
}
}
if ( pFirstSeparator )
{
// Split on this separator and continue on.
int separatorLen = strlen( pSeparators[iFirstSeparator] );
if ( pFirstSeparator > pCurPos )
{
//////////////////////////////////////////////////////////////////////////
/// Cut the token out of the duplicate string
char *pTokenInDuplicate = m_szBuffer + (pCurPos - pString);
int nTokenLength = pFirstSeparator-pCurPos;
Assert(nTokenLength > 0 && !memcmp(pTokenInDuplicate,pCurPos,nTokenLength));
pTokenInDuplicate[nTokenLength] = '\0';
this->AddToTail( pTokenInDuplicate /*AllocString( pCurPos, pFirstSeparator-pCurPos )*/ );
}
pCurPos = pFirstSeparator + separatorLen;
}
else
{
// Copy the rest of the string
if ( int nTokenLength = strlen( pCurPos ) )
{
//////////////////////////////////////////////////////////////////////////
// There's no need to cut this token, because there's no separator after it.
// just add its copy in the buffer to the tail
char *pTokenInDuplicate = m_szBuffer + (pCurPos - pString);
Assert(!memcmp(pTokenInDuplicate, pCurPos, nTokenLength));
this->AddToTail( pTokenInDuplicate/*AllocString( pCurPos, -1 )*/ );
}
return;
}
}
}
void CSplitString::PurgeAndDeleteElements()
{
Purge();
}

View File

@@ -1,334 +1,334 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "convar.h"
#include "tier0/dbg.h"
#include "stringpool.h"
#include "tier1/strtools.h"
#include "generichash.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Comparison function for string sorted associative data structures
//-----------------------------------------------------------------------------
bool StrLess( const char * const &pszLeft, const char * const &pszRight )
{
return ( Q_stricmp( pszLeft, pszRight) < 0 );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CStringPool::CStringPool()
: m_Strings( 32, 256, StrLess )
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CStringPool::~CStringPool()
{
FreeAll();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
unsigned int CStringPool::Count() const
{
return m_Strings.Count();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
const char * CStringPool::Find( const char *pszValue )
{
unsigned short i = m_Strings.Find(pszValue);
if ( m_Strings.IsValidIndex(i) )
return m_Strings[i];
return NULL;
}
const char * CStringPool::Allocate( const char *pszValue )
{
char *pszNew;
unsigned short i = m_Strings.Find(pszValue);
bool bNew = (i == m_Strings.InvalidIndex());
if ( !bNew )
return m_Strings[i];
pszNew = strdup( pszValue );
if ( bNew )
m_Strings.Insert( pszNew );
return pszNew;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CStringPool::FreeAll()
{
unsigned short i = m_Strings.FirstInorder();
while ( i != m_Strings.InvalidIndex() )
{
free( (void *)m_Strings[i] );
i = m_Strings.NextInorder(i);
}
m_Strings.RemoveAll();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
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" )
{
CStringPool pool;
Assert(pool.Count() == 0);
pool.Allocate("test");
Assert(pool.Count() == 1);
pool.Allocate("test");
Assert(pool.Count() == 1);
pool.Allocate("test2");
Assert(pool.Count() == 2);
Assert( pool.Find("test2") != NULL );
Assert( pool.Find("TEST") != NULL );
Assert( pool.Find("Test2") != NULL );
Assert( pool.Find("test") != NULL );
pool.FreeAll();
Assert(pool.Count() == 0);
Msg("Pass.");
}
#endif
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "convar.h"
#include "tier0/dbg.h"
#include "stringpool.h"
#include "tier1/strtools.h"
#include "generichash.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Purpose: Comparison function for string sorted associative data structures
//-----------------------------------------------------------------------------
bool StrLess( const char * const &pszLeft, const char * const &pszRight )
{
return ( Q_stricmp( pszLeft, pszRight) < 0 );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CStringPool::CStringPool()
: m_Strings( 32, 256, StrLess )
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CStringPool::~CStringPool()
{
FreeAll();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
unsigned int CStringPool::Count() const
{
return m_Strings.Count();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
const char * CStringPool::Find( const char *pszValue )
{
unsigned short i = m_Strings.Find(pszValue);
if ( m_Strings.IsValidIndex(i) )
return m_Strings[i];
return NULL;
}
const char * CStringPool::Allocate( const char *pszValue )
{
char *pszNew;
unsigned short i = m_Strings.Find(pszValue);
bool bNew = (i == m_Strings.InvalidIndex());
if ( !bNew )
return m_Strings[i];
pszNew = strdup( pszValue );
if ( bNew )
m_Strings.Insert( pszNew );
return pszNew;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CStringPool::FreeAll()
{
unsigned short i = m_Strings.FirstInorder();
while ( i != m_Strings.InvalidIndex() )
{
free( (void *)m_Strings[i] );
i = m_Strings.NextInorder(i);
}
m_Strings.RemoveAll();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
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" )
{
CStringPool pool;
Assert(pool.Count() == 0);
pool.Allocate("test");
Assert(pool.Count() == 1);
pool.Allocate("test");
Assert(pool.Count() == 1);
pool.Allocate("test2");
Assert(pool.Count() == 2);
Assert( pool.Find("test2") != NULL );
Assert( pool.Find("TEST") != NULL );
Assert( pool.Find("Test2") != NULL );
Assert( pool.Find("test") != NULL );
pool.FreeAll();
Assert(pool.Count() == 0);
Msg("Pass.");
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +1,63 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A higher level link library for general use in the game and tools.
//
//===========================================================================//
#include <tier1/tier1.h>
#include "tier0/dbg.h"
#include "vstdlib/iprocessutils.h"
#include "icvar.h"
//-----------------------------------------------------------------------------
// These tier1 libraries must be set by any users of this library.
// They can be set by calling ConnectTier1Libraries or InitDefaultFileSystem.
// It is hoped that setting this, and using this library will be the common mechanism for
// allowing link libraries to access tier1 library interfaces
//-----------------------------------------------------------------------------
ICvar *cvar = 0;
ICvar *g_pCVar = 0;
IProcessUtils *g_pProcessUtils = 0;
static bool s_bConnected = false;
// for utlsortvector.h
#ifndef _WIN32
void *g_pUtlSortVectorQSortContext = NULL;
#endif
//-----------------------------------------------------------------------------
// Call this to connect to all tier 1 libraries.
// It's up to the caller to check the globals it cares about to see if ones are missing
//-----------------------------------------------------------------------------
void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount )
{
// Don't connect twice..
if ( s_bConnected )
return;
s_bConnected = true;
for ( int i = 0; i < nFactoryCount; ++i )
{
if ( !g_pCVar )
{
cvar = g_pCVar = ( ICvar * )pFactoryList[i]( CVAR_INTERFACE_VERSION, NULL );
}
if ( !g_pProcessUtils )
{
g_pProcessUtils = ( IProcessUtils * )pFactoryList[i]( PROCESS_UTILS_INTERFACE_VERSION, NULL );
}
}
}
void DisconnectTier1Libraries()
{
if ( !s_bConnected )
return;
g_pCVar = cvar = 0;
g_pProcessUtils = NULL;
s_bConnected = false;
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: A higher level link library for general use in the game and tools.
//
//===========================================================================//
#include <tier1/tier1.h>
#include "tier0/dbg.h"
#include "vstdlib/iprocessutils.h"
#include "icvar.h"
//-----------------------------------------------------------------------------
// These tier1 libraries must be set by any users of this library.
// They can be set by calling ConnectTier1Libraries or InitDefaultFileSystem.
// It is hoped that setting this, and using this library will be the common mechanism for
// allowing link libraries to access tier1 library interfaces
//-----------------------------------------------------------------------------
ICvar *cvar = 0;
ICvar *g_pCVar = 0;
IProcessUtils *g_pProcessUtils = 0;
static bool s_bConnected = false;
// for utlsortvector.h
#ifndef _WIN32
void *g_pUtlSortVectorQSortContext = NULL;
#endif
//-----------------------------------------------------------------------------
// Call this to connect to all tier 1 libraries.
// It's up to the caller to check the globals it cares about to see if ones are missing
//-----------------------------------------------------------------------------
void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount )
{
// Don't connect twice..
if ( s_bConnected )
return;
s_bConnected = true;
for ( int i = 0; i < nFactoryCount; ++i )
{
if ( !g_pCVar )
{
cvar = g_pCVar = ( ICvar * )pFactoryList[i]( CVAR_INTERFACE_VERSION, NULL );
}
if ( !g_pProcessUtils )
{
g_pProcessUtils = ( IProcessUtils * )pFactoryList[i]( PROCESS_UTILS_INTERFACE_VERSION, NULL );
}
}
}
void DisconnectTier1Libraries()
{
if ( !s_bConnected )
return;
g_pCVar = cvar = 0;
g_pProcessUtils = NULL;
s_bConnected = false;
}

View File

@@ -1,152 +1,152 @@
//-----------------------------------------------------------------------------
// TIER1.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$PreprocessorDefinitions "$BASE;TIER1_STATIC_LIB"
}
$Librarian [$WINDOWS]
{
$AdditionalDependencies "$BASE Rpcrt4.lib"
}
}
$Project "tier1"
{
$Folder "Source Files"
{
$File "bitbuf.cpp"
$File "newbitbuf.cpp"
$File "byteswap.cpp"
$File "characterset.cpp"
$File "checksum_crc.cpp"
$File "checksum_md5.cpp"
$File "checksum_sha1.cpp"
$File "commandbuffer.cpp"
$File "convar.cpp"
$File "datamanager.cpp"
$File "diff.cpp"
$File "generichash.cpp"
$File "ilocalize.cpp"
$File "interface.cpp"
$File "KeyValues.cpp"
$File "kvpacker.cpp"
$File "lzmaDecoder.cpp"
$File "lzss.cpp" [!$SOURCESDK]
$File "mempool.cpp"
$File "memstack.cpp"
$File "NetAdr.cpp"
$File "splitstring.cpp"
$File "processor_detect.cpp" [$WINDOWS||$X360]
{
$Configuration
{
$Compiler
{
$EnableC++Exceptions "Yes (/EHsc)" [!$X360]
}
}
}
$File "processor_detect_linux.cpp" [$POSIX]
$File "qsort_s.cpp" [$LINUXALL||$PS3]
$File "rangecheckedvar.cpp"
$File "reliabletimer.cpp"
$File "stringpool.cpp"
$File "strtools.cpp"
$File "tier1.cpp"
$File "tokenreader.cpp"
$File "sparsematrix.cpp"
$File "uniqueid.cpp"
$File "utlbuffer.cpp"
$File "utlbufferutil.cpp"
$File "utlstring.cpp"
$File "utlsymbol.cpp"
$File "pathmatch.cpp" [$LINUXALL]
$File "snappy.cpp"
$File "snappy-sinksource.cpp"
$File "snappy-stubs-internal.cpp"
}
$Folder "Header Files"
{
$Folder "Internal Header Files"
{
$File "snappy-internal.h"
$File "snappy-stubs-internal.h"
}
$File "$SRCDIR\public\tier1\bitbuf.h"
$File "$SRCDIR\public\tier1\byteswap.h"
$File "$SRCDIR\public\tier1\callqueue.h"
$File "$SRCDIR\public\tier1\characterset.h"
$File "$SRCDIR\public\tier1\checksum_crc.h"
$File "$SRCDIR\public\tier1\checksum_md5.h"
$File "$SRCDIR\public\tier1\checksum_sha1.h"
$File "$SRCDIR\public\tier1\CommandBuffer.h"
$File "$SRCDIR\public\tier1\convar.h"
$File "$SRCDIR\public\tier1\datamanager.h"
$File "$SRCDIR\public\datamap.h"
$File "$SRCDIR\public\tier1\delegates.h"
$File "$SRCDIR\public\tier1\diff.h"
$File "$SRCDIR\public\tier1\fmtstr.h"
$File "$SRCDIR\public\tier1\functors.h"
$File "$SRCDIR\public\tier1\generichash.h"
$File "$SRCDIR\public\tier1\iconvar.h"
$File "$SRCDIR\public\tier1\ilocalize.h"
$File "$SRCDIR\public\tier1\interface.h"
$File "$SRCDIR\public\tier1\KeyValues.h"
$File "$SRCDIR\public\tier1\kvpacker.h"
$File "$SRCDIR\public\tier1\lzmaDecoder.h"
$File "$SRCDIR\public\tier1\lzss.h"
$File "$SRCDIR\public\tier1\mempool.h"
$File "$SRCDIR\public\tier1\memstack.h"
$File "$SRCDIR\public\tier1\netadr.h"
$File "$SRCDIR\public\tier1\processor_detect.h"
$File "$SRCDIR\public\tier1\rangecheckedvar.h"
$File "$SRCDIR\public\tier1\refcount.h"
$File "$SRCDIR\public\tier1\smartptr.h"
$File "$SRCDIR\public\tier1\snappy.h"
$File "$SRCDIR\public\tier1\snappy-sinksource.h"
$File "$SRCDIR\public\tier1\stringpool.h"
$File "$SRCDIR\public\tier1\strtools.h"
$File "$SRCDIR\public\tier1\tier1.h"
$File "$SRCDIR\public\tier1\tokenreader.h"
$File "$SRCDIR\public\tier1\uniqueid.h" [$WINDOWS]
$File "$SRCDIR\public\tier1\utlbidirectionalset.h"
$File "$SRCDIR\public\tier1\utlblockmemory.h"
$File "$SRCDIR\public\tier1\utlbuffer.h"
$File "$SRCDIR\public\tier1\utlbufferutil.h"
$File "$SRCDIR\public\tier1\utlcommon.h"
$File "$SRCDIR\public\tier1\utldict.h"
$File "$SRCDIR\public\tier1\utlenvelope.h"
$File "$SRCDIR\public\tier1\utlfixedmemory.h"
$File "$SRCDIR\public\tier1\utlhandletable.h"
$File "$SRCDIR\public\tier1\utlhash.h"
$File "$SRCDIR\public\tier1\utlhashtable.h"
$File "$SRCDIR\public\tier1\utllinkedlist.h"
$File "$SRCDIR\public\tier1\utlmap.h"
$File "$SRCDIR\public\tier1\utlmemory.h"
$File "$SRCDIR\public\tier1\utlmultilist.h"
$File "$SRCDIR\public\tier1\utlpriorityqueue.h"
$File "$SRCDIR\public\tier1\utlqueue.h"
$File "$SRCDIR\public\tier1\utlrbtree.h"
$File "$SRCDIR\public\tier1\UtlSortVector.h"
$File "$SRCDIR\public\tier1\utlstack.h"
$File "$SRCDIR\public\tier1\utlstring.h"
$File "$SRCDIR\public\tier1\UtlStringMap.h"
$File "$SRCDIR\public\tier1\utlsymbol.h"
$File "$SRCDIR\public\tier1\utlsymbollarge.h"
$File "$SRCDIR\public\tier1\utlvector.h"
$File "$SRCDIR\common\xbox\xboxstubs.h" [$WINDOWS]
}
}
//-----------------------------------------------------------------------------
// TIER1.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR ".."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$PreprocessorDefinitions "$BASE;TIER1_STATIC_LIB"
}
$Librarian [$WINDOWS]
{
$AdditionalDependencies "$BASE Rpcrt4.lib"
}
}
$Project "tier1"
{
$Folder "Source Files"
{
$File "bitbuf.cpp"
$File "newbitbuf.cpp"
$File "byteswap.cpp"
$File "characterset.cpp"
$File "checksum_crc.cpp"
$File "checksum_md5.cpp"
$File "checksum_sha1.cpp"
$File "commandbuffer.cpp"
$File "convar.cpp"
$File "datamanager.cpp"
$File "diff.cpp"
$File "generichash.cpp"
$File "ilocalize.cpp"
$File "interface.cpp"
$File "KeyValues.cpp"
$File "kvpacker.cpp"
$File "lzmaDecoder.cpp"
$File "lzss.cpp" [!$SOURCESDK]
$File "mempool.cpp"
$File "memstack.cpp"
$File "NetAdr.cpp"
$File "splitstring.cpp"
$File "processor_detect.cpp" [$WINDOWS||$X360]
{
$Configuration
{
$Compiler
{
$EnableC++Exceptions "Yes (/EHsc)" [!$X360]
}
}
}
$File "processor_detect_linux.cpp" [$POSIX]
$File "qsort_s.cpp" [$LINUXALL||$PS3]
$File "rangecheckedvar.cpp"
$File "reliabletimer.cpp"
$File "stringpool.cpp"
$File "strtools.cpp"
$File "tier1.cpp"
$File "tokenreader.cpp"
$File "sparsematrix.cpp"
$File "uniqueid.cpp"
$File "utlbuffer.cpp"
$File "utlbufferutil.cpp"
$File "utlstring.cpp"
$File "utlsymbol.cpp"
$File "pathmatch.cpp" [$LINUXALL]
$File "snappy.cpp"
$File "snappy-sinksource.cpp"
$File "snappy-stubs-internal.cpp"
}
$Folder "Header Files"
{
$Folder "Internal Header Files"
{
$File "snappy-internal.h"
$File "snappy-stubs-internal.h"
}
$File "$SRCDIR\public\tier1\bitbuf.h"
$File "$SRCDIR\public\tier1\byteswap.h"
$File "$SRCDIR\public\tier1\callqueue.h"
$File "$SRCDIR\public\tier1\characterset.h"
$File "$SRCDIR\public\tier1\checksum_crc.h"
$File "$SRCDIR\public\tier1\checksum_md5.h"
$File "$SRCDIR\public\tier1\checksum_sha1.h"
$File "$SRCDIR\public\tier1\CommandBuffer.h"
$File "$SRCDIR\public\tier1\convar.h"
$File "$SRCDIR\public\tier1\datamanager.h"
$File "$SRCDIR\public\datamap.h"
$File "$SRCDIR\public\tier1\delegates.h"
$File "$SRCDIR\public\tier1\diff.h"
$File "$SRCDIR\public\tier1\fmtstr.h"
$File "$SRCDIR\public\tier1\functors.h"
$File "$SRCDIR\public\tier1\generichash.h"
$File "$SRCDIR\public\tier1\iconvar.h"
$File "$SRCDIR\public\tier1\ilocalize.h"
$File "$SRCDIR\public\tier1\interface.h"
$File "$SRCDIR\public\tier1\KeyValues.h"
$File "$SRCDIR\public\tier1\kvpacker.h"
$File "$SRCDIR\public\tier1\lzmaDecoder.h"
$File "$SRCDIR\public\tier1\lzss.h"
$File "$SRCDIR\public\tier1\mempool.h"
$File "$SRCDIR\public\tier1\memstack.h"
$File "$SRCDIR\public\tier1\netadr.h"
$File "$SRCDIR\public\tier1\processor_detect.h"
$File "$SRCDIR\public\tier1\rangecheckedvar.h"
$File "$SRCDIR\public\tier1\refcount.h"
$File "$SRCDIR\public\tier1\smartptr.h"
$File "$SRCDIR\public\tier1\snappy.h"
$File "$SRCDIR\public\tier1\snappy-sinksource.h"
$File "$SRCDIR\public\tier1\stringpool.h"
$File "$SRCDIR\public\tier1\strtools.h"
$File "$SRCDIR\public\tier1\tier1.h"
$File "$SRCDIR\public\tier1\tokenreader.h"
$File "$SRCDIR\public\tier1\uniqueid.h" [$WINDOWS]
$File "$SRCDIR\public\tier1\utlbidirectionalset.h"
$File "$SRCDIR\public\tier1\utlblockmemory.h"
$File "$SRCDIR\public\tier1\utlbuffer.h"
$File "$SRCDIR\public\tier1\utlbufferutil.h"
$File "$SRCDIR\public\tier1\utlcommon.h"
$File "$SRCDIR\public\tier1\utldict.h"
$File "$SRCDIR\public\tier1\utlenvelope.h"
$File "$SRCDIR\public\tier1\utlfixedmemory.h"
$File "$SRCDIR\public\tier1\utlhandletable.h"
$File "$SRCDIR\public\tier1\utlhash.h"
$File "$SRCDIR\public\tier1\utlhashtable.h"
$File "$SRCDIR\public\tier1\utllinkedlist.h"
$File "$SRCDIR\public\tier1\utlmap.h"
$File "$SRCDIR\public\tier1\utlmemory.h"
$File "$SRCDIR\public\tier1\utlmultilist.h"
$File "$SRCDIR\public\tier1\utlpriorityqueue.h"
$File "$SRCDIR\public\tier1\utlqueue.h"
$File "$SRCDIR\public\tier1\utlrbtree.h"
$File "$SRCDIR\public\tier1\UtlSortVector.h"
$File "$SRCDIR\public\tier1\utlstack.h"
$File "$SRCDIR\public\tier1\utlstring.h"
$File "$SRCDIR\public\tier1\UtlStringMap.h"
$File "$SRCDIR\public\tier1\utlsymbol.h"
$File "$SRCDIR\public\tier1\utlsymbollarge.h"
$File "$SRCDIR\public\tier1\utlvector.h"
$File "$SRCDIR\common\xbox\xboxstubs.h" [$WINDOWS]
}
}

View File

@@ -1,14 +1,14 @@
//-----------------------------------------------------------------------------
// tier1_exclude.vpc
//
// Project Script
//-----------------------------------------------------------------------------
$Project
{
$Folder "Link Libraries"
{
-$File "$SRCDIR\lib\$PLATFORM\tier1$_STATICLIB_EXT" [!$WINDOWS]
-$File "$SRCDIR\lib\public\tier1$_STATICLIB_EXT" [$WINDOWS]
}
}
//-----------------------------------------------------------------------------
// tier1_exclude.vpc
//
// Project Script
//-----------------------------------------------------------------------------
$Project
{
$Folder "Link Libraries"
{
-$File "$SRCDIR\lib\$PLATFORM\tier1$_STATICLIB_EXT" [!$WINDOWS]
-$File "$SRCDIR\lib\public\tier1$_STATICLIB_EXT" [$WINDOWS]
}
}

View File

@@ -1,480 +1,480 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "tokenreader.h"
#include "tier0/platform.h"
#include "tier1/strtools.h"
#include "tier0/dbg.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
TokenReader::TokenReader(void)
{
m_szFilename[0] = '\0';
m_nLine = 1;
m_nErrorCount = 0;
m_bStuffed = false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszFilename -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool TokenReader::Open(const char *pszFilename)
{
open(pszFilename, std::ios::in | std::ios::binary );
Q_strncpy(m_szFilename, pszFilename, sizeof( m_szFilename ) );
m_nLine = 1;
m_nErrorCount = 0;
m_bStuffed = false;
return(is_open() != 0);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TokenReader::Close()
{
close();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *error -
// Output : const char
//-----------------------------------------------------------------------------
const char *TokenReader::Error(char *error, ...)
{
static char szErrorBuf[256];
Q_snprintf(szErrorBuf, sizeof( szErrorBuf ), "File %s, line %d: ", m_szFilename, m_nLine);
Q_strncat(szErrorBuf, error, sizeof( szErrorBuf ), COPY_ALL_CHARACTERS );
m_nErrorCount++;
return(szErrorBuf);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszStore -
// nSize -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
trtoken_t TokenReader::GetString(char *pszStore, int nSize)
{
if (nSize <= 0)
{
return TOKENERROR;
}
char szBuf[1024];
//
// Until we reach the end of this string or run out of room in
// the destination buffer...
//
while (true)
{
//
// Fetch the next batch of text from the file.
//
get(szBuf, sizeof(szBuf), '\"');
if (eof())
{
return TOKENEOF;
}
if (fail())
{
// Just means nothing was read (empty string probably "")
clear();
}
//
// Transfer the text to the destination buffer.
//
char *pszSrc = szBuf;
while ((*pszSrc != '\0') && (nSize > 1))
{
if (*pszSrc == 0x0d)
{
//
// Newline encountered before closing quote -- unterminated string.
//
*pszStore = '\0';
return TOKENSTRINGTOOLONG;
}
else if (*pszSrc != '\\')
{
*pszStore = *pszSrc;
pszSrc++;
}
else
{
//
// Backslash sequence - replace with the appropriate character.
//
pszSrc++;
if (*pszSrc == 'n')
{
*pszStore = '\n';
}
pszSrc++;
}
pszStore++;
nSize--;
}
if (*pszSrc != '\0')
{
//
// Ran out of room in the destination buffer. Skip to the close-quote,
// terminate the string, and exit.
//
ignore(1024, '\"');
*pszStore = '\0';
return TOKENSTRINGTOOLONG;
}
//
// Check for closing quote.
//
if (peek() == '\"')
{
//
// Eat the close quote and any whitespace.
//
get();
bool bCombineStrings = SkipWhiteSpace();
//
// Combine consecutive quoted strings if the combine strings character was
// encountered between the two strings.
//
if (bCombineStrings && (peek() == '\"'))
{
//
// Eat the open quote and keep parsing this string.
//
get();
}
else
{
//
// Done with this string, terminate the string and exit.
//
*pszStore = '\0';
return STRING;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns the next token, allocating enough memory to store the token
// plus a terminating NULL.
// Input : pszStore - Pointer to a string that will be allocated.
// Output : Returns the type of token that was read, or TOKENERROR.
//-----------------------------------------------------------------------------
trtoken_t TokenReader::NextTokenDynamic(char **ppszStore)
{
char szTempBuffer[8192];
trtoken_t eType = NextToken(szTempBuffer, sizeof(szTempBuffer));
int len = Q_strlen(szTempBuffer) + 1;
*ppszStore = new char [len];
Assert( *ppszStore );
Q_strncpy(*ppszStore, szTempBuffer, len );
return(eType);
}
//-----------------------------------------------------------------------------
// Purpose: Returns the next token.
// Input : pszStore - Pointer to a string that will receive the token.
// Output : Returns the type of token that was read, or TOKENERROR.
//-----------------------------------------------------------------------------
trtoken_t TokenReader::NextToken(char *pszStore, int nSize)
{
char *pStart = pszStore;
if (!is_open())
{
return TOKENEOF;
}
//
// If they stuffed a token, return that token.
//
if (m_bStuffed)
{
m_bStuffed = false;
Q_strncpy( pszStore, m_szStuffed, nSize );
return m_eStuffed;
}
SkipWhiteSpace();
if (eof())
{
return TOKENEOF;
}
if (fail())
{
return TOKENEOF;
}
char ch = get();
//
// Look for all the valid operators.
//
switch (ch)
{
case '@':
case ',':
case '!':
case '+':
case '&':
case '*':
case '$':
case '.':
case '=':
case ':':
case '[':
case ']':
case '(':
case ')':
case '{':
case '}':
case '\\':
{
pszStore[0] = ch;
pszStore[1] = 0;
return OPERATOR;
}
}
//
// Look for the start of a quoted string.
//
if (ch == '\"')
{
return GetString(pszStore, nSize);
}
//
// Integers consist of numbers with an optional leading minus sign.
//
if (isdigit(ch) || (ch == '-'))
{
do
{
if ( (pszStore - pStart + 1) < nSize )
{
*pszStore = ch;
pszStore++;
}
ch = get();
if (ch == '-')
{
return TOKENERROR;
}
} while (isdigit(ch));
//
// No identifier characters are allowed contiguous with numbers.
//
if (isalpha(ch) || (ch == '_'))
{
return TOKENERROR;
}
//
// Put back the non-numeric character for the next call.
//
putback(ch);
*pszStore = '\0';
return INTEGER;
}
//
// Identifiers consist of a consecutive string of alphanumeric
// characters and underscores.
//
while ( isalpha(ch) || isdigit(ch) || (ch == '_') )
{
if ( (pszStore - pStart + 1) < nSize )
{
*pszStore = ch;
pszStore++;
}
ch = get();
}
//
// Put back the non-identifier character for the next call.
//
putback(ch);
*pszStore = '\0';
return IDENT;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ttype -
// *pszToken -
//-----------------------------------------------------------------------------
void TokenReader::IgnoreTill(trtoken_t ttype, const char *pszToken)
{
trtoken_t _ttype;
char szBuf[1024];
while(1)
{
_ttype = NextToken(szBuf, sizeof(szBuf));
if(_ttype == TOKENEOF)
return;
if(_ttype == ttype)
{
if(IsToken(pszToken, szBuf))
{
Stuff(ttype, pszToken);
return;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ttype -
// pszToken -
//-----------------------------------------------------------------------------
void TokenReader::Stuff(trtoken_t eType, const char *pszToken)
{
m_eStuffed = eType;
Q_strncpy(m_szStuffed, pszToken, sizeof( m_szStuffed ) );
m_bStuffed = true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ttype -
// pszToken -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool TokenReader::Expecting(trtoken_t ttype, const char *pszToken)
{
char szBuf[1024];
if (NextToken(szBuf, sizeof(szBuf)) != ttype || !IsToken(pszToken, szBuf))
{
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszStore -
// Output :
//-----------------------------------------------------------------------------
trtoken_t TokenReader::PeekTokenType(char *pszStore, int maxlen )
{
if (!m_bStuffed)
{
m_eStuffed = NextToken(m_szStuffed, sizeof(m_szStuffed));
m_bStuffed = true;
}
if (pszStore)
{
Q_strncpy(pszStore, m_szStuffed, maxlen );
}
return(m_eStuffed);
}
//-----------------------------------------------------------------------------
// Purpose: Gets the next non-whitespace character from the file.
// Input : ch - Receives the character.
// Output : Returns true if the whitespace contained the combine strings
// character '\', which is used to merge consecutive quoted strings.
//-----------------------------------------------------------------------------
bool TokenReader::SkipWhiteSpace(void)
{
bool bCombineStrings = false;
while (true)
{
char ch = get();
if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == 0))
{
continue;
}
if (ch == '+')
{
bCombineStrings = true;
continue;
}
if (ch == '\n')
{
m_nLine++;
continue;
}
if (eof())
{
return(bCombineStrings);
}
//
// Check for the start of a comment.
//
if (ch == '/')
{
if (peek() == '/')
{
ignore(1024, '\n');
m_nLine++;
}
}
else
{
//
// It is a worthy character. Put it back.
//
putback(ch);
return(bCombineStrings);
}
}
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "tokenreader.h"
#include "tier0/platform.h"
#include "tier1/strtools.h"
#include "tier0/dbg.h"
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
TokenReader::TokenReader(void)
{
m_szFilename[0] = '\0';
m_nLine = 1;
m_nErrorCount = 0;
m_bStuffed = false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pszFilename -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool TokenReader::Open(const char *pszFilename)
{
open(pszFilename, std::ios::in | std::ios::binary );
Q_strncpy(m_szFilename, pszFilename, sizeof( m_szFilename ) );
m_nLine = 1;
m_nErrorCount = 0;
m_bStuffed = false;
return(is_open() != 0);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void TokenReader::Close()
{
close();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *error -
// Output : const char
//-----------------------------------------------------------------------------
const char *TokenReader::Error(char *error, ...)
{
static char szErrorBuf[256];
Q_snprintf(szErrorBuf, sizeof( szErrorBuf ), "File %s, line %d: ", m_szFilename, m_nLine);
Q_strncat(szErrorBuf, error, sizeof( szErrorBuf ), COPY_ALL_CHARACTERS );
m_nErrorCount++;
return(szErrorBuf);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszStore -
// nSize -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
trtoken_t TokenReader::GetString(char *pszStore, int nSize)
{
if (nSize <= 0)
{
return TOKENERROR;
}
char szBuf[1024];
//
// Until we reach the end of this string or run out of room in
// the destination buffer...
//
while (true)
{
//
// Fetch the next batch of text from the file.
//
get(szBuf, sizeof(szBuf), '\"');
if (eof())
{
return TOKENEOF;
}
if (fail())
{
// Just means nothing was read (empty string probably "")
clear();
}
//
// Transfer the text to the destination buffer.
//
char *pszSrc = szBuf;
while ((*pszSrc != '\0') && (nSize > 1))
{
if (*pszSrc == 0x0d)
{
//
// Newline encountered before closing quote -- unterminated string.
//
*pszStore = '\0';
return TOKENSTRINGTOOLONG;
}
else if (*pszSrc != '\\')
{
*pszStore = *pszSrc;
pszSrc++;
}
else
{
//
// Backslash sequence - replace with the appropriate character.
//
pszSrc++;
if (*pszSrc == 'n')
{
*pszStore = '\n';
}
pszSrc++;
}
pszStore++;
nSize--;
}
if (*pszSrc != '\0')
{
//
// Ran out of room in the destination buffer. Skip to the close-quote,
// terminate the string, and exit.
//
ignore(1024, '\"');
*pszStore = '\0';
return TOKENSTRINGTOOLONG;
}
//
// Check for closing quote.
//
if (peek() == '\"')
{
//
// Eat the close quote and any whitespace.
//
get();
bool bCombineStrings = SkipWhiteSpace();
//
// Combine consecutive quoted strings if the combine strings character was
// encountered between the two strings.
//
if (bCombineStrings && (peek() == '\"'))
{
//
// Eat the open quote and keep parsing this string.
//
get();
}
else
{
//
// Done with this string, terminate the string and exit.
//
*pszStore = '\0';
return STRING;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns the next token, allocating enough memory to store the token
// plus a terminating NULL.
// Input : pszStore - Pointer to a string that will be allocated.
// Output : Returns the type of token that was read, or TOKENERROR.
//-----------------------------------------------------------------------------
trtoken_t TokenReader::NextTokenDynamic(char **ppszStore)
{
char szTempBuffer[8192];
trtoken_t eType = NextToken(szTempBuffer, sizeof(szTempBuffer));
int len = Q_strlen(szTempBuffer) + 1;
*ppszStore = new char [len];
Assert( *ppszStore );
Q_strncpy(*ppszStore, szTempBuffer, len );
return(eType);
}
//-----------------------------------------------------------------------------
// Purpose: Returns the next token.
// Input : pszStore - Pointer to a string that will receive the token.
// Output : Returns the type of token that was read, or TOKENERROR.
//-----------------------------------------------------------------------------
trtoken_t TokenReader::NextToken(char *pszStore, int nSize)
{
char *pStart = pszStore;
if (!is_open())
{
return TOKENEOF;
}
//
// If they stuffed a token, return that token.
//
if (m_bStuffed)
{
m_bStuffed = false;
Q_strncpy( pszStore, m_szStuffed, nSize );
return m_eStuffed;
}
SkipWhiteSpace();
if (eof())
{
return TOKENEOF;
}
if (fail())
{
return TOKENEOF;
}
char ch = get();
//
// Look for all the valid operators.
//
switch (ch)
{
case '@':
case ',':
case '!':
case '+':
case '&':
case '*':
case '$':
case '.':
case '=':
case ':':
case '[':
case ']':
case '(':
case ')':
case '{':
case '}':
case '\\':
{
pszStore[0] = ch;
pszStore[1] = 0;
return OPERATOR;
}
}
//
// Look for the start of a quoted string.
//
if (ch == '\"')
{
return GetString(pszStore, nSize);
}
//
// Integers consist of numbers with an optional leading minus sign.
//
if (isdigit(ch) || (ch == '-'))
{
do
{
if ( (pszStore - pStart + 1) < nSize )
{
*pszStore = ch;
pszStore++;
}
ch = get();
if (ch == '-')
{
return TOKENERROR;
}
} while (isdigit(ch));
//
// No identifier characters are allowed contiguous with numbers.
//
if (isalpha(ch) || (ch == '_'))
{
return TOKENERROR;
}
//
// Put back the non-numeric character for the next call.
//
putback(ch);
*pszStore = '\0';
return INTEGER;
}
//
// Identifiers consist of a consecutive string of alphanumeric
// characters and underscores.
//
while ( isalpha(ch) || isdigit(ch) || (ch == '_') )
{
if ( (pszStore - pStart + 1) < nSize )
{
*pszStore = ch;
pszStore++;
}
ch = get();
}
//
// Put back the non-identifier character for the next call.
//
putback(ch);
*pszStore = '\0';
return IDENT;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ttype -
// *pszToken -
//-----------------------------------------------------------------------------
void TokenReader::IgnoreTill(trtoken_t ttype, const char *pszToken)
{
trtoken_t _ttype;
char szBuf[1024];
while(1)
{
_ttype = NextToken(szBuf, sizeof(szBuf));
if(_ttype == TOKENEOF)
return;
if(_ttype == ttype)
{
if(IsToken(pszToken, szBuf))
{
Stuff(ttype, pszToken);
return;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ttype -
// pszToken -
//-----------------------------------------------------------------------------
void TokenReader::Stuff(trtoken_t eType, const char *pszToken)
{
m_eStuffed = eType;
Q_strncpy(m_szStuffed, pszToken, sizeof( m_szStuffed ) );
m_bStuffed = true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : ttype -
// pszToken -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool TokenReader::Expecting(trtoken_t ttype, const char *pszToken)
{
char szBuf[1024];
if (NextToken(szBuf, sizeof(szBuf)) != ttype || !IsToken(pszToken, szBuf))
{
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszStore -
// Output :
//-----------------------------------------------------------------------------
trtoken_t TokenReader::PeekTokenType(char *pszStore, int maxlen )
{
if (!m_bStuffed)
{
m_eStuffed = NextToken(m_szStuffed, sizeof(m_szStuffed));
m_bStuffed = true;
}
if (pszStore)
{
Q_strncpy(pszStore, m_szStuffed, maxlen );
}
return(m_eStuffed);
}
//-----------------------------------------------------------------------------
// Purpose: Gets the next non-whitespace character from the file.
// Input : ch - Receives the character.
// Output : Returns true if the whitespace contained the combine strings
// character '\', which is used to merge consecutive quoted strings.
//-----------------------------------------------------------------------------
bool TokenReader::SkipWhiteSpace(void)
{
bool bCombineStrings = false;
while (true)
{
char ch = get();
if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == 0))
{
continue;
}
if (ch == '+')
{
bCombineStrings = true;
continue;
}
if (ch == '\n')
{
m_nLine++;
continue;
}
if (eof())
{
return(bCombineStrings);
}
//
// Check for the start of a comment.
//
if (ch == '/')
{
if (peek() == '/')
{
ignore(1024, '\n');
m_nLine++;
}
}
else
{
//
// It is a worthy character. Put it back.
//
putback(ch);
return(bCombineStrings);
}
}
}

View File

@@ -1,94 +1,94 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// UnDiff - Apply difference block
//
//=============================================================================//
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "tier1/diff.h"
#include "mathlib/mathlib.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList,
int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize)
{
uint8 const *copy_src=OldBlock;
uint8 const *end_of_diff_list=DiffList+DiffListSize;
uint8 const *obuf=Output;
while(DiffList<end_of_diff_list)
{
// printf("dptr=%x ",DiffList-d);
uint8 op=*(DiffList++);
if (op==0)
{
uint16 copy_sz=DiffList[0]+256*DiffList[1];
int copy_ofs=DiffList[2]+DiffList[3]*256;
if (copy_ofs>32767)
copy_ofs|=0xffff0000;
// printf("long cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
memcpy(Output,copy_src+copy_ofs,copy_sz);
Output+=copy_sz;
copy_src=copy_src+copy_ofs+copy_sz;
DiffList+=4;
}
else
{
if (op & 0x80)
{
int copy_sz=op & 0x7f;
int copy_ofs;
if (copy_sz==0)
{
copy_sz=DiffList[0];
if (copy_sz==0)
{
// big raw copy
copy_sz=DiffList[1]+256*DiffList[2]+65536*DiffList[3];
memcpy(Output,DiffList+4,copy_sz);
// printf("big rawcopy to %x len=%d\n", Output-obuf,copy_sz);
DiffList+=copy_sz+4;
Output+=copy_sz;
}
else
{
copy_ofs=DiffList[1]+(DiffList[2]*256);
if (copy_ofs>32767)
copy_ofs|=0xffff0000;
// printf("long ofs cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
memcpy(Output,copy_src+copy_ofs,copy_sz);
Output+=copy_sz;
copy_src=copy_src+copy_ofs+copy_sz;
DiffList+=3;
}
}
else
{
copy_ofs=DiffList[0];
if (copy_ofs>127)
copy_ofs|=0xffffff80;
// printf("cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
memcpy(Output,copy_src+copy_ofs,copy_sz);
Output+=copy_sz;
copy_src=copy_src+copy_ofs+copy_sz;
DiffList++;
}
}
else
{
// printf("raw copy %d to %x\n",op & 127,Output-obuf);
memcpy(Output,DiffList,op & 127);
Output+=op & 127;
DiffList+=(op & 127);
}
}
}
ResultListSize=Output-obuf;
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// UnDiff - Apply difference block
//
//=============================================================================//
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "tier1/diff.h"
#include "mathlib/mathlib.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList,
int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize)
{
uint8 const *copy_src=OldBlock;
uint8 const *end_of_diff_list=DiffList+DiffListSize;
uint8 const *obuf=Output;
while(DiffList<end_of_diff_list)
{
// printf("dptr=%x ",DiffList-d);
uint8 op=*(DiffList++);
if (op==0)
{
uint16 copy_sz=DiffList[0]+256*DiffList[1];
int copy_ofs=DiffList[2]+DiffList[3]*256;
if (copy_ofs>32767)
copy_ofs|=0xffff0000;
// printf("long cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
memcpy(Output,copy_src+copy_ofs,copy_sz);
Output+=copy_sz;
copy_src=copy_src+copy_ofs+copy_sz;
DiffList+=4;
}
else
{
if (op & 0x80)
{
int copy_sz=op & 0x7f;
int copy_ofs;
if (copy_sz==0)
{
copy_sz=DiffList[0];
if (copy_sz==0)
{
// big raw copy
copy_sz=DiffList[1]+256*DiffList[2]+65536*DiffList[3];
memcpy(Output,DiffList+4,copy_sz);
// printf("big rawcopy to %x len=%d\n", Output-obuf,copy_sz);
DiffList+=copy_sz+4;
Output+=copy_sz;
}
else
{
copy_ofs=DiffList[1]+(DiffList[2]*256);
if (copy_ofs>32767)
copy_ofs|=0xffff0000;
// printf("long ofs cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
memcpy(Output,copy_src+copy_ofs,copy_sz);
Output+=copy_sz;
copy_src=copy_src+copy_ofs+copy_sz;
DiffList+=3;
}
}
else
{
copy_ofs=DiffList[0];
if (copy_ofs>127)
copy_ofs|=0xffffff80;
// printf("cp from %x to %x len=%d\n", copy_src+copy_ofs-OldBlock,Output-obuf,copy_sz);
memcpy(Output,copy_src+copy_ofs,copy_sz);
Output+=copy_sz;
copy_src=copy_src+copy_ofs+copy_sz;
DiffList++;
}
}
else
{
// printf("raw copy %d to %x\n",op & 127,Output-obuf);
memcpy(Output,DiffList,op & 127);
Output+=op & 127;
DiffList+=(op & 127);
}
}
}
ResultListSize=Output-obuf;
}

View File

@@ -1,177 +1,177 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
// Unique ID generation
//=============================================================================//
#include "tier0/platform.h"
#ifdef IS_WINDOWS_PC
#include <windows.h> // UUIDCreate
#else
#include "checksum_crc.h"
#endif
#include "tier1/uniqueid.h"
#include "tier1/utlbuffer.h"
//-----------------------------------------------------------------------------
// Creates a new unique id
//-----------------------------------------------------------------------------
void CreateUniqueId( UniqueId_t *pDest )
{
#ifdef IS_WINDOWS_PC
Assert( sizeof( UUID ) == sizeof( *pDest ) );
UuidCreate( (UUID *)pDest );
#else
// X360/linux TBD: Need a real UUID Implementation
Q_memset( pDest, 0, sizeof( UniqueId_t ) );
#endif
}
//-----------------------------------------------------------------------------
// Creates a new unique id from a string representation of one
//-----------------------------------------------------------------------------
bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen )
{
if ( nMaxLen == 0 )
{
nMaxLen = Q_strlen( pBuf );
}
char *pTemp = (char*)stackalloc( nMaxLen + 1 );
V_strncpy( pTemp, pBuf, nMaxLen + 1 );
--nMaxLen;
while( (nMaxLen >= 0) && isspace( pTemp[nMaxLen] ) )
{
--nMaxLen;
}
pTemp[ nMaxLen + 1 ] = 0;
while( *pTemp && isspace( *pTemp ) )
{
++pTemp;
}
#ifdef IS_WINDOWS_PC
Assert( sizeof( UUID ) == sizeof( *pDest ) );
if ( RPC_S_OK != UuidFromString( (unsigned char *)pTemp, (UUID *)pDest ) )
{
InvalidateUniqueId( pDest );
return false;
}
#else
// X360TBD: Need a real UUID Implementation
// For now, use crc to generate a unique ID from the UUID string.
Q_memset( pDest, 0, sizeof( UniqueId_t ) );
if ( nMaxLen > 0 )
{
CRC32_t crc;
CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, pBuf, nMaxLen );
CRC32_Final( &crc );
Q_memcpy( pDest, &crc, sizeof( CRC32_t ) );
}
#endif
return true;
}
//-----------------------------------------------------------------------------
// Sets an object ID to be an invalid state
//-----------------------------------------------------------------------------
void InvalidateUniqueId( UniqueId_t *pDest )
{
Assert( pDest );
memset( pDest, 0, sizeof( UniqueId_t ) );
}
bool IsUniqueIdValid( const UniqueId_t &id )
{
UniqueId_t invalidId;
memset( &invalidId, 0, sizeof( UniqueId_t ) );
return !IsUniqueIdEqual( invalidId, id );
}
bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 )
{
return memcmp( &id1, &id2, sizeof( UniqueId_t ) ) == 0;
}
void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen )
{
pBuf[ 0 ] = 0;
// X360TBD: Need a real UUID Implementation
#ifdef IS_WINDOWS_PC
UUID *self = ( UUID * )&id;
unsigned char *outstring = NULL;
UuidToString( self, &outstring );
if ( outstring && *outstring )
{
Q_strncpy( pBuf, (const char *)outstring, nMaxLen );
RpcStringFree( &outstring );
}
#endif
}
void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest )
{
memcpy( pDest, &src, sizeof( UniqueId_t ) );
}
bool Serialize( CUtlBuffer &buf, const UniqueId_t &src )
{
// X360TBD: Need a real UUID Implementation
#ifdef IS_WINDOWS_PC
if ( buf.IsText() )
{
UUID *pId = ( UUID * )&src;
unsigned char *outstring = NULL;
UuidToString( pId, &outstring );
if ( outstring && *outstring )
{
buf.PutString( (const char *)outstring );
RpcStringFree( &outstring );
}
else
{
buf.PutChar( '\0' );
}
}
else
{
buf.Put( &src, sizeof(UniqueId_t) );
}
return buf.IsValid();
#else
return false;
#endif
}
bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest )
{
if ( buf.IsText() )
{
int nTextLen = buf.PeekStringLength();
char *pBuf = (char*)stackalloc( nTextLen );
buf.GetString( pBuf, nTextLen );
UniqueIdFromString( &dest, pBuf, nTextLen );
}
else
{
buf.Get( &dest, sizeof(UniqueId_t) );
}
return buf.IsValid();
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
// Unique ID generation
//=============================================================================//
#include "tier0/platform.h"
#ifdef IS_WINDOWS_PC
#include <windows.h> // UUIDCreate
#else
#include "checksum_crc.h"
#endif
#include "tier1/uniqueid.h"
#include "tier1/utlbuffer.h"
//-----------------------------------------------------------------------------
// Creates a new unique id
//-----------------------------------------------------------------------------
void CreateUniqueId( UniqueId_t *pDest )
{
#ifdef IS_WINDOWS_PC
Assert( sizeof( UUID ) == sizeof( *pDest ) );
UuidCreate( (UUID *)pDest );
#else
// X360/linux TBD: Need a real UUID Implementation
Q_memset( pDest, 0, sizeof( UniqueId_t ) );
#endif
}
//-----------------------------------------------------------------------------
// Creates a new unique id from a string representation of one
//-----------------------------------------------------------------------------
bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen )
{
if ( nMaxLen == 0 )
{
nMaxLen = Q_strlen( pBuf );
}
char *pTemp = (char*)stackalloc( nMaxLen + 1 );
V_strncpy( pTemp, pBuf, nMaxLen + 1 );
--nMaxLen;
while( (nMaxLen >= 0) && isspace( pTemp[nMaxLen] ) )
{
--nMaxLen;
}
pTemp[ nMaxLen + 1 ] = 0;
while( *pTemp && isspace( *pTemp ) )
{
++pTemp;
}
#ifdef IS_WINDOWS_PC
Assert( sizeof( UUID ) == sizeof( *pDest ) );
if ( RPC_S_OK != UuidFromString( (unsigned char *)pTemp, (UUID *)pDest ) )
{
InvalidateUniqueId( pDest );
return false;
}
#else
// X360TBD: Need a real UUID Implementation
// For now, use crc to generate a unique ID from the UUID string.
Q_memset( pDest, 0, sizeof( UniqueId_t ) );
if ( nMaxLen > 0 )
{
CRC32_t crc;
CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, pBuf, nMaxLen );
CRC32_Final( &crc );
Q_memcpy( pDest, &crc, sizeof( CRC32_t ) );
}
#endif
return true;
}
//-----------------------------------------------------------------------------
// Sets an object ID to be an invalid state
//-----------------------------------------------------------------------------
void InvalidateUniqueId( UniqueId_t *pDest )
{
Assert( pDest );
memset( pDest, 0, sizeof( UniqueId_t ) );
}
bool IsUniqueIdValid( const UniqueId_t &id )
{
UniqueId_t invalidId;
memset( &invalidId, 0, sizeof( UniqueId_t ) );
return !IsUniqueIdEqual( invalidId, id );
}
bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 )
{
return memcmp( &id1, &id2, sizeof( UniqueId_t ) ) == 0;
}
void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen )
{
pBuf[ 0 ] = 0;
// X360TBD: Need a real UUID Implementation
#ifdef IS_WINDOWS_PC
UUID *self = ( UUID * )&id;
unsigned char *outstring = NULL;
UuidToString( self, &outstring );
if ( outstring && *outstring )
{
Q_strncpy( pBuf, (const char *)outstring, nMaxLen );
RpcStringFree( &outstring );
}
#endif
}
void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest )
{
memcpy( pDest, &src, sizeof( UniqueId_t ) );
}
bool Serialize( CUtlBuffer &buf, const UniqueId_t &src )
{
// X360TBD: Need a real UUID Implementation
#ifdef IS_WINDOWS_PC
if ( buf.IsText() )
{
UUID *pId = ( UUID * )&src;
unsigned char *outstring = NULL;
UuidToString( pId, &outstring );
if ( outstring && *outstring )
{
buf.PutString( (const char *)outstring );
RpcStringFree( &outstring );
}
else
{
buf.PutChar( '\0' );
}
}
else
{
buf.Put( &src, sizeof(UniqueId_t) );
}
return buf.IsValid();
#else
return false;
#endif
}
bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest )
{
if ( buf.IsText() )
{
int nTextLen = buf.PeekStringLength();
char *pBuf = (char*)stackalloc( nTextLen );
buf.GetString( pBuf, nTextLen );
UniqueIdFromString( &dest, pBuf, nTextLen );
}
else
{
buf.Get( &dest, sizeof(UniqueId_t) );
}
return buf.IsValid();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,436 +1,436 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a symbol table
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#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
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define INVALID_STRING_INDEX CStringPoolIndex( 0xFFFF, 0xFFFF )
#define MIN_STRING_POOL_SIZE 2048
//-----------------------------------------------------------------------------
// globals
//-----------------------------------------------------------------------------
CUtlSymbolTableMT* CUtlSymbol::s_pSymbolTable = 0;
bool CUtlSymbol::s_bAllowStaticSymbolTable = true;
//-----------------------------------------------------------------------------
// symbol methods
//-----------------------------------------------------------------------------
void CUtlSymbol::Initialize()
{
// If this assert fails, then the module that this call is in has chosen to disallow
// use of the static symbol table. Usually, it's to prevent confusion because it's easy
// to accidentally use the global symbol table when you really want to use a specific one.
Assert( s_bAllowStaticSymbolTable );
// necessary to allow us to create global symbols
static bool symbolsInitialized = false;
if (!symbolsInitialized)
{
s_pSymbolTable = new CUtlSymbolTableMT;
symbolsInitialized = true;
}
}
//-----------------------------------------------------------------------------
// Purpose: Singleton to delete table on exit from module
//-----------------------------------------------------------------------------
class CCleanupUtlSymbolTable
{
public:
~CCleanupUtlSymbolTable()
{
delete CUtlSymbol::s_pSymbolTable;
CUtlSymbol::s_pSymbolTable = NULL;
}
};
static CCleanupUtlSymbolTable g_CleanupSymbolTable;
CUtlSymbolTableMT* CUtlSymbol::CurrTable()
{
Initialize();
return s_pSymbolTable;
}
//-----------------------------------------------------------------------------
// string->symbol->string
//-----------------------------------------------------------------------------
CUtlSymbol::CUtlSymbol( const char* pStr )
{
m_Id = CurrTable()->AddString( pStr );
}
const char* CUtlSymbol::String( ) const
{
return CurrTable()->String(m_Id);
}
void CUtlSymbol::DisableStaticSymbolTable()
{
s_bAllowStaticSymbolTable = false;
}
//-----------------------------------------------------------------------------
// checks if the symbol matches a string
//-----------------------------------------------------------------------------
bool CUtlSymbol::operator==( const char* pStr ) const
{
if (m_Id == UTL_INVAL_SYMBOL)
return false;
return strcmp( String(), pStr ) == 0;
}
//-----------------------------------------------------------------------------
// symbol table stuff
//-----------------------------------------------------------------------------
inline const char* CUtlSymbolTable::StringFromIndex( 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];
}
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
{
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
// can be arbitrarily moved in memory on a realloc. Yes, this is portable. In reality,
// 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 );
const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i1 );
const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i2 );
if ( !str1 && str2 )
return false;
if ( !str2 && str1 )
return true;
if ( !str1 && !str2 )
return false;
if ( !pTable->m_bInsensitive )
return V_strcmp( str1, str2 ) < 0;
else
return V_stricmp( str1, str2 ) < 0;
}
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CUtlSymbolTable::CUtlSymbolTable( int growSize, int initSize, bool caseInsensitive ) :
m_Lookup( growSize, initSize ), m_bInsensitive( caseInsensitive ), m_StringPools( 8 )
{
}
CUtlSymbolTable::~CUtlSymbolTable()
{
// Release the stringpool string data
RemoveAll();
}
CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
{
if (!pString)
return CUtlSymbol();
// Store a special context used to help with insertion
m_pUserSearchString = pString;
// Passing this special invalid symbol makes the comparison function
// use the string passed in the context
UtlSymId_t idx = m_Lookup.Find( INVALID_STRING_INDEX );
#ifdef _DEBUG
m_pUserSearchString = NULL;
#endif
return CUtlSymbol( idx );
}
int CUtlSymbolTable::FindPoolWithSpace( int len ) const
{
for ( int i=0; i < m_StringPools.Count(); i++ )
{
StringPool_t *pPool = m_StringPools[i];
if ( (pPool->m_TotalLen - pPool->m_SpaceUsed) >= len )
{
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Finds and/or creates a symbol based on the string
//-----------------------------------------------------------------------------
CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
{
if (!pString)
return CUtlSymbol( UTL_INVAL_SYMBOL );
CUtlSymbol id = Find( pString );
if (id.IsValid())
return id;
int len = strlen(pString) + 1;
// Find a pool with space for this string, or allocate a new one.
int iPool = FindPoolWithSpace( len );
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;
pPool->m_SpaceUsed = 0;
iPool = m_StringPools.AddToTail( pPool );
}
// 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;
memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
pPool->m_SpaceUsed += len;
// didn't find, insert the string into the vector.
CStringPoolIndex index;
index.m_iPool = iPool;
index.m_iOffset = iStringOffset;
UtlSymId_t idx = m_Lookup.Insert( index );
return CUtlSymbol( idx );
}
//-----------------------------------------------------------------------------
// Look up the string associated with a particular symbol
//-----------------------------------------------------------------------------
const char* CUtlSymbolTable::String( CUtlSymbol id ) const
{
if (!id.IsValid())
return "";
Assert( m_Lookup.IsValidIndex((UtlSymId_t)id) );
return StringFromIndex( m_Lookup[id] );
}
//-----------------------------------------------------------------------------
// Remove all symbols in the table.
//-----------------------------------------------------------------------------
void CUtlSymbolTable::RemoveAll()
{
m_Lookup.Purge();
for ( int i=0; i < m_StringPools.Count(); i++ )
free( m_StringPools[i] );
m_StringPools.RemoveAll();
}
class CUtlFilenameSymbolTable::HashTable : public CUtlStableHashtable<CUtlConstString>
{
};
CUtlFilenameSymbolTable::CUtlFilenameSymbolTable()
{
m_Strings = new HashTable;
}
CUtlFilenameSymbolTable::~CUtlFilenameSymbolTable()
{
delete m_Strings;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pFileName -
// Output : FileNameHandle_t
//-----------------------------------------------------------------------------
FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileName )
{
if ( !pFileName )
{
return NULL;
}
// find first
FileNameHandle_t hFileName = FindFileName( pFileName );
if ( hFileName )
{
return hFileName;
}
// Fix slashes+dotslashes and make lower case first..
char fn[ MAX_PATH ];
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
#endif
// Split the filename into constituent parts
char basepath[ MAX_PATH ];
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
char filename[ MAX_PATH ];
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
// 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 )
//{
// found
// m_lock.UnlockWrite();
// return *( FileNameHandle_t * )( &handle );
//}
// safely add it
//handle.path = m_StringPool.ReferenceStringHandle( basepath );
//handle.file = m_StringPool.ReferenceStringHandle( filename );
m_lock.UnlockWrite();
return *( FileNameHandle_t * )( &handle );
}
FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
{
if ( !pFileName )
{
return NULL;
}
// Fix slashes+dotslashes and make lower case first..
char fn[ MAX_PATH ];
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
#endif
// Split the filename into constituent parts
char basepath[ MAX_PATH ];
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
char filename[ MAX_PATH ];
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
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);
m_lock.UnlockRead();
if ( handle.path == 0 || handle.file == 0 )
return NULL;
return *( FileNameHandle_t * )( &handle );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : handle -
// Output : const char
//-----------------------------------------------------------------------------
bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf, int buflen )
{
buf[ 0 ] = 0;
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
if ( !internal || !internal->file || !internal->path )
{
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();
m_lock.UnlockRead();
if ( !path || !fn )
{
return false;
}
Q_strncpy( buf, path, buflen );
Q_strncat( buf, fn, buflen, COPY_ALL_CHARACTERS );
return true;
}
void CUtlFilenameSymbolTable::RemoveAll()
{
m_Strings->Purge();
}
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a symbol table
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#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
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define INVALID_STRING_INDEX CStringPoolIndex( 0xFFFF, 0xFFFF )
#define MIN_STRING_POOL_SIZE 2048
//-----------------------------------------------------------------------------
// globals
//-----------------------------------------------------------------------------
CUtlSymbolTableMT* CUtlSymbol::s_pSymbolTable = 0;
bool CUtlSymbol::s_bAllowStaticSymbolTable = true;
//-----------------------------------------------------------------------------
// symbol methods
//-----------------------------------------------------------------------------
void CUtlSymbol::Initialize()
{
// If this assert fails, then the module that this call is in has chosen to disallow
// use of the static symbol table. Usually, it's to prevent confusion because it's easy
// to accidentally use the global symbol table when you really want to use a specific one.
Assert( s_bAllowStaticSymbolTable );
// necessary to allow us to create global symbols
static bool symbolsInitialized = false;
if (!symbolsInitialized)
{
s_pSymbolTable = new CUtlSymbolTableMT;
symbolsInitialized = true;
}
}
//-----------------------------------------------------------------------------
// Purpose: Singleton to delete table on exit from module
//-----------------------------------------------------------------------------
class CCleanupUtlSymbolTable
{
public:
~CCleanupUtlSymbolTable()
{
delete CUtlSymbol::s_pSymbolTable;
CUtlSymbol::s_pSymbolTable = NULL;
}
};
static CCleanupUtlSymbolTable g_CleanupSymbolTable;
CUtlSymbolTableMT* CUtlSymbol::CurrTable()
{
Initialize();
return s_pSymbolTable;
}
//-----------------------------------------------------------------------------
// string->symbol->string
//-----------------------------------------------------------------------------
CUtlSymbol::CUtlSymbol( const char* pStr )
{
m_Id = CurrTable()->AddString( pStr );
}
const char* CUtlSymbol::String( ) const
{
return CurrTable()->String(m_Id);
}
void CUtlSymbol::DisableStaticSymbolTable()
{
s_bAllowStaticSymbolTable = false;
}
//-----------------------------------------------------------------------------
// checks if the symbol matches a string
//-----------------------------------------------------------------------------
bool CUtlSymbol::operator==( const char* pStr ) const
{
if (m_Id == UTL_INVAL_SYMBOL)
return false;
return strcmp( String(), pStr ) == 0;
}
//-----------------------------------------------------------------------------
// symbol table stuff
//-----------------------------------------------------------------------------
inline const char* CUtlSymbolTable::StringFromIndex( 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];
}
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
{
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
// can be arbitrarily moved in memory on a realloc. Yes, this is portable. In reality,
// 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 );
const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i1 );
const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i2 );
if ( !str1 && str2 )
return false;
if ( !str2 && str1 )
return true;
if ( !str1 && !str2 )
return false;
if ( !pTable->m_bInsensitive )
return V_strcmp( str1, str2 ) < 0;
else
return V_stricmp( str1, str2 ) < 0;
}
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CUtlSymbolTable::CUtlSymbolTable( int growSize, int initSize, bool caseInsensitive ) :
m_Lookup( growSize, initSize ), m_bInsensitive( caseInsensitive ), m_StringPools( 8 )
{
}
CUtlSymbolTable::~CUtlSymbolTable()
{
// Release the stringpool string data
RemoveAll();
}
CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
{
if (!pString)
return CUtlSymbol();
// Store a special context used to help with insertion
m_pUserSearchString = pString;
// Passing this special invalid symbol makes the comparison function
// use the string passed in the context
UtlSymId_t idx = m_Lookup.Find( INVALID_STRING_INDEX );
#ifdef _DEBUG
m_pUserSearchString = NULL;
#endif
return CUtlSymbol( idx );
}
int CUtlSymbolTable::FindPoolWithSpace( int len ) const
{
for ( int i=0; i < m_StringPools.Count(); i++ )
{
StringPool_t *pPool = m_StringPools[i];
if ( (pPool->m_TotalLen - pPool->m_SpaceUsed) >= len )
{
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Finds and/or creates a symbol based on the string
//-----------------------------------------------------------------------------
CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
{
if (!pString)
return CUtlSymbol( UTL_INVAL_SYMBOL );
CUtlSymbol id = Find( pString );
if (id.IsValid())
return id;
int len = strlen(pString) + 1;
// Find a pool with space for this string, or allocate a new one.
int iPool = FindPoolWithSpace( len );
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;
pPool->m_SpaceUsed = 0;
iPool = m_StringPools.AddToTail( pPool );
}
// 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;
memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
pPool->m_SpaceUsed += len;
// didn't find, insert the string into the vector.
CStringPoolIndex index;
index.m_iPool = iPool;
index.m_iOffset = iStringOffset;
UtlSymId_t idx = m_Lookup.Insert( index );
return CUtlSymbol( idx );
}
//-----------------------------------------------------------------------------
// Look up the string associated with a particular symbol
//-----------------------------------------------------------------------------
const char* CUtlSymbolTable::String( CUtlSymbol id ) const
{
if (!id.IsValid())
return "";
Assert( m_Lookup.IsValidIndex((UtlSymId_t)id) );
return StringFromIndex( m_Lookup[id] );
}
//-----------------------------------------------------------------------------
// Remove all symbols in the table.
//-----------------------------------------------------------------------------
void CUtlSymbolTable::RemoveAll()
{
m_Lookup.Purge();
for ( int i=0; i < m_StringPools.Count(); i++ )
free( m_StringPools[i] );
m_StringPools.RemoveAll();
}
class CUtlFilenameSymbolTable::HashTable : public CUtlStableHashtable<CUtlConstString>
{
};
CUtlFilenameSymbolTable::CUtlFilenameSymbolTable()
{
m_Strings = new HashTable;
}
CUtlFilenameSymbolTable::~CUtlFilenameSymbolTable()
{
delete m_Strings;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pFileName -
// Output : FileNameHandle_t
//-----------------------------------------------------------------------------
FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileName )
{
if ( !pFileName )
{
return NULL;
}
// find first
FileNameHandle_t hFileName = FindFileName( pFileName );
if ( hFileName )
{
return hFileName;
}
// Fix slashes+dotslashes and make lower case first..
char fn[ MAX_PATH ];
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
#endif
// Split the filename into constituent parts
char basepath[ MAX_PATH ];
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
char filename[ MAX_PATH ];
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
// 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 )
//{
// found
// m_lock.UnlockWrite();
// return *( FileNameHandle_t * )( &handle );
//}
// safely add it
//handle.path = m_StringPool.ReferenceStringHandle( basepath );
//handle.file = m_StringPool.ReferenceStringHandle( filename );
m_lock.UnlockWrite();
return *( FileNameHandle_t * )( &handle );
}
FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
{
if ( !pFileName )
{
return NULL;
}
// Fix slashes+dotslashes and make lower case first..
char fn[ MAX_PATH ];
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
#endif
// Split the filename into constituent parts
char basepath[ MAX_PATH ];
Q_ExtractFilePath( fn, basepath, sizeof( basepath ) );
char filename[ MAX_PATH ];
Q_strncpy( filename, fn + Q_strlen( basepath ), sizeof( filename ) );
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);
m_lock.UnlockRead();
if ( handle.path == 0 || handle.file == 0 )
return NULL;
return *( FileNameHandle_t * )( &handle );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : handle -
// Output : const char
//-----------------------------------------------------------------------------
bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf, int buflen )
{
buf[ 0 ] = 0;
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
if ( !internal || !internal->file || !internal->path )
{
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();
m_lock.UnlockRead();
if ( !path || !fn )
{
return false;
}
Q_strncpy( buf, path, buflen );
Q_strncat( buf, fn, buflen, COPY_ALL_CHARACTERS );
return true;
}
void CUtlFilenameSymbolTable::RemoveAll()
{
m_Strings->Purge();
}