1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 03:56:10 +08:00

First version of the SOurce SDK 2013

This commit is contained in:
Joe Ludwig
2013-06-26 15:22:04 -07:00
commit e7d6f4c174
3682 changed files with 1624327 additions and 0 deletions

3030
tier1/KeyValues.cpp Normal file

File diff suppressed because it is too large Load Diff

326
tier1/NetAdr.cpp Normal file
View File

@ -0,0 +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
}

1490
tier1/bitbuf.cpp Normal file

File diff suppressed because it is too large Load Diff

90
tier1/byteswap.cpp Normal file
View File

@ -0,0 +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 );
}
}

41
tier1/characterset.cpp Normal file
View File

@ -0,0 +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++;
}
}

180
tier1/checksum_crc.cpp Normal file
View File

@ -0,0 +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;
}

305
tier1/checksum_md5.cpp Normal file
View File

@ -0,0 +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 );
}

299
tier1/checksum_sha1.cpp Normal file
View File

@ -0,0 +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

636
tier1/commandbuffer.cpp Normal file
View File

@ -0,0 +1,636 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#include "tier1/CommandBuffer.h"
#include "tier1/utlbuffer.h"
#include "tier1/strtools.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define MAX_ALIAS_NAME 32
#define MAX_COMMAND_LENGTH 1024
struct cmdalias_t
{
cmdalias_t *next;
char name[ MAX_ALIAS_NAME ];
char *value;
};
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CCommandBuffer::CCommandBuffer( ) : m_Commands( 32, 32 )
{
m_hNextCommand = m_Commands.InvalidIndex();
m_nWaitDelayTicks = 1;
m_nCurrentTick = 0;
m_nLastTickToProcess = -1;
m_nArgSBufferSize = 0;
m_bIsProcessingCommands = false;
m_nMaxArgSBufferLength = ARGS_BUFFER_LENGTH;
}
CCommandBuffer::~CCommandBuffer()
{
}
//-----------------------------------------------------------------------------
// Indicates how long to delay when encoutering a 'wait' command
//-----------------------------------------------------------------------------
void CCommandBuffer::SetWaitDelayTime( int nTickDelay )
{
Assert( nTickDelay >= 0 );
m_nWaitDelayTicks = nTickDelay;
}
//-----------------------------------------------------------------------------
// Specifies a max limit of the args buffer. For unittesting. Size == 0 means use default
//-----------------------------------------------------------------------------
void CCommandBuffer::LimitArgumentBufferSize( int nSize )
{
if ( nSize > ARGS_BUFFER_LENGTH )
{
nSize = ARGS_BUFFER_LENGTH;
}
m_nMaxArgSBufferLength = ( nSize == 0 ) ? ARGS_BUFFER_LENGTH : nSize;
}
//-----------------------------------------------------------------------------
// Parses argv0 out of the buffer
//-----------------------------------------------------------------------------
bool CCommandBuffer::ParseArgV0( CUtlBuffer &buf, char *pArgV0, int nMaxLen, const char **pArgS )
{
pArgV0[0] = 0;
*pArgS = NULL;
if ( !buf.IsValid() )
return false;
int nSize = buf.ParseToken( CCommand::DefaultBreakSet(), pArgV0, nMaxLen );
if ( ( nSize <= 0 ) || ( nMaxLen == nSize ) )
return false;
int nArgSLen = buf.TellMaxPut() - buf.TellGet();
*pArgS = (nArgSLen > 0) ? (const char*)buf.PeekGet() : NULL;
return true;
}
//-----------------------------------------------------------------------------
// Insert a command into the command queue
//-----------------------------------------------------------------------------
void CCommandBuffer::InsertCommandAtAppropriateTime( int hCommand )
{
int i;
Command_t &command = m_Commands[hCommand];
for ( i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) )
{
if ( m_Commands[i].m_nTick > command.m_nTick )
break;
}
m_Commands.LinkBefore( i, hCommand );
}
//-----------------------------------------------------------------------------
// Insert a command into the command queue at the appropriate time
//-----------------------------------------------------------------------------
void CCommandBuffer::InsertImmediateCommand( int hCommand )
{
m_Commands.LinkBefore( m_hNextCommand, hCommand );
}
//-----------------------------------------------------------------------------
// Insert a command into the command queue
//-----------------------------------------------------------------------------
bool CCommandBuffer::InsertCommand( const char *pArgS, int nCommandSize, int nTick )
{
if ( nCommandSize >= CCommand::MaxCommandLength() )
{
Warning( "WARNING: Command too long... ignoring!\n%s\n", pArgS );
return false;
}
// Add one for null termination
if ( m_nArgSBufferSize + nCommandSize + 1 > m_nMaxArgSBufferLength )
{
Compact();
if ( m_nArgSBufferSize + nCommandSize + 1 > m_nMaxArgSBufferLength )
return false;
}
memcpy( &m_pArgSBuffer[m_nArgSBufferSize], pArgS, nCommandSize );
m_pArgSBuffer[m_nArgSBufferSize + nCommandSize] = 0;
++nCommandSize;
int hCommand = m_Commands.Alloc();
Command_t &command = m_Commands[hCommand];
command.m_nTick = nTick;
command.m_nFirstArgS = m_nArgSBufferSize;
command.m_nBufferSize = nCommandSize;
m_nArgSBufferSize += nCommandSize;
if ( !m_bIsProcessingCommands || ( nTick > m_nCurrentTick ) )
{
InsertCommandAtAppropriateTime( hCommand );
}
else
{
InsertImmediateCommand( hCommand );
}
return true;
}
//-----------------------------------------------------------------------------
// Returns the length of the next command
//-----------------------------------------------------------------------------
void CCommandBuffer::GetNextCommandLength( const char *pText, int nMaxLen, int *pCommandLength, int *pNextCommandOffset )
{
int nCommandLength = 0;
int nNextCommandOffset;
bool bIsQuoted = false;
bool bIsCommented = false;
for ( nNextCommandOffset=0; nNextCommandOffset < nMaxLen; ++nNextCommandOffset, nCommandLength += bIsCommented ? 0 : 1 )
{
char c = pText[nNextCommandOffset];
if ( !bIsCommented )
{
if ( c == '"' )
{
bIsQuoted = !bIsQuoted;
continue;
}
// don't break if inside a C++ style comment
if ( !bIsQuoted && c == '/' )
{
bIsCommented = ( nNextCommandOffset < nMaxLen-1 ) && pText[nNextCommandOffset+1] == '/';
if ( bIsCommented )
{
++nNextCommandOffset;
continue;
}
}
// don't break if inside a quoted string
if ( !bIsQuoted && c == ';' )
break;
}
// FIXME: This is legacy behavior; should we not break if a \n is inside a quoted string?
if ( c == '\n' )
break;
}
*pCommandLength = nCommandLength;
*pNextCommandOffset = nNextCommandOffset;
}
//-----------------------------------------------------------------------------
// Add text to command buffer, return false if it couldn't owing to overflow
//-----------------------------------------------------------------------------
bool CCommandBuffer::AddText( const char *pText, int nTickDelay )
{
Assert( nTickDelay >= 0 );
int nLen = Q_strlen( pText );
int nTick = m_nCurrentTick + nTickDelay;
// Parse the text into distinct commands
const char *pCurrentCommand = pText;
int nOffsetToNextCommand;
for( ; nLen > 0; nLen -= nOffsetToNextCommand+1, pCurrentCommand += nOffsetToNextCommand+1 )
{
// find a \n or ; line break
int nCommandLength;
GetNextCommandLength( pCurrentCommand, nLen, &nCommandLength, &nOffsetToNextCommand );
if ( nCommandLength <= 0 )
continue;
const char *pArgS;
char *pArgV0 = (char*)_alloca( nCommandLength+1 );
CUtlBuffer bufParse( pCurrentCommand, nCommandLength, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY );
ParseArgV0( bufParse, pArgV0, nCommandLength+1, &pArgS );
if ( pArgV0[0] == 0 )
continue;
// Deal with the special 'wait' command
if ( !Q_stricmp( pArgV0, "wait" ) && IsWaitEnabled() )
{
int nDelay = pArgS ? atoi( pArgS ) : m_nWaitDelayTicks;
nTick += nDelay;
continue;
}
if ( !InsertCommand( pCurrentCommand, nCommandLength, nTick ) )
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Are we in the middle of processing commands?
//-----------------------------------------------------------------------------
bool CCommandBuffer::IsProcessingCommands()
{
return m_bIsProcessingCommands;
}
//-----------------------------------------------------------------------------
// Delays all queued commands to execute at a later time
//-----------------------------------------------------------------------------
void CCommandBuffer::DelayAllQueuedCommands( int nDelay )
{
if ( nDelay <= 0 )
return;
for ( int i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) )
{
m_Commands[i].m_nTick += nDelay;
}
}
//-----------------------------------------------------------------------------
// Call this to begin iterating over all commands up to flCurrentTime
//-----------------------------------------------------------------------------
void CCommandBuffer::BeginProcessingCommands( int nDeltaTicks )
{
if ( nDeltaTicks == 0 )
return;
Assert( !m_bIsProcessingCommands );
m_bIsProcessingCommands = true;
m_nLastTickToProcess = m_nCurrentTick + nDeltaTicks - 1;
// Necessary to insert commands while commands are being processed
m_hNextCommand = m_Commands.Head();
}
//-----------------------------------------------------------------------------
// Returns the next command
//-----------------------------------------------------------------------------
bool CCommandBuffer::DequeueNextCommand( )
{
m_CurrentCommand.Reset();
Assert( m_bIsProcessingCommands );
if ( m_Commands.Count() == 0 )
return false;
int nHead = m_Commands.Head();
Command_t &command = m_Commands[ nHead ];
if ( command.m_nTick > m_nLastTickToProcess )
return false;
m_nCurrentTick = command.m_nTick;
// Copy the current command into a temp buffer
// NOTE: This is here to avoid the pointers returned by DequeueNextCommand
// to become invalid by calling AddText. Is there a way we can avoid the memcpy?
if ( command.m_nBufferSize > 0 )
{
m_CurrentCommand.Tokenize( &m_pArgSBuffer[command.m_nFirstArgS] );
}
m_Commands.Remove( nHead );
// Necessary to insert commands while commands are being processed
m_hNextCommand = m_Commands.Head();
// Msg("Dequeue : ");
// for ( int i = 0; i < nArgc; ++i )
// {
// Msg("%s ", m_pCurrentArgv[i] );
// }
// Msg("\n");
return true;
}
//-----------------------------------------------------------------------------
// Returns the next command
//-----------------------------------------------------------------------------
int CCommandBuffer::DequeueNextCommand( const char **& ppArgv )
{
DequeueNextCommand();
ppArgv = ArgV();
return ArgC();
}
//-----------------------------------------------------------------------------
// Compacts the command buffer
//-----------------------------------------------------------------------------
void CCommandBuffer::Compact()
{
// Compress argvbuffer + argv
// NOTE: I'm using this choice instead of calling malloc + free
// per command to allocate arguments because I expect to post a
// bunch of commands but not have many delayed commands;
// avoiding the allocation cost seems more important that the memcpy
// cost here since I expect to not have much to copy.
m_nArgSBufferSize = 0;
char pTempBuffer[ ARGS_BUFFER_LENGTH ];
for ( int i = m_Commands.Head(); i != m_Commands.InvalidIndex(); i = m_Commands.Next(i) )
{
Command_t &command = m_Commands[ i ];
memcpy( &pTempBuffer[m_nArgSBufferSize], &m_pArgSBuffer[command.m_nFirstArgS], command.m_nBufferSize );
command.m_nFirstArgS = m_nArgSBufferSize;
m_nArgSBufferSize += command.m_nBufferSize;
}
// NOTE: We could also store 2 buffers in the command buffer and switch
// between the two to avoid the 2nd memcpy; but again I'm guessing the memory
// tradeoff isn't worth it
memcpy( m_pArgSBuffer, pTempBuffer, m_nArgSBufferSize );
}
//-----------------------------------------------------------------------------
// Call this to finish iterating over all commands
//-----------------------------------------------------------------------------
void CCommandBuffer::EndProcessingCommands()
{
Assert( m_bIsProcessingCommands );
m_bIsProcessingCommands = false;
m_nCurrentTick = m_nLastTickToProcess + 1;
m_hNextCommand = m_Commands.InvalidIndex();
// Extract commands that are before the end time
// NOTE: This is a bug for this to
int i = m_Commands.Head();
if ( i == m_Commands.InvalidIndex() )
{
m_nArgSBufferSize = 0;
return;
}
while ( i != m_Commands.InvalidIndex() )
{
if ( m_Commands[i].m_nTick >= m_nCurrentTick )
break;
AssertMsgOnce( false, "CCommandBuffer::EndProcessingCommands() called before all appropriate commands were dequeued.\n" );
int nNext = i;
Msg( "Warning: Skipping command %s\n", &m_pArgSBuffer[ m_Commands[i].m_nFirstArgS ] );
m_Commands.Remove( i );
i = nNext;
}
Compact();
}
//-----------------------------------------------------------------------------
// Returns a handle to the next command to process
//-----------------------------------------------------------------------------
CommandHandle_t CCommandBuffer::GetNextCommandHandle()
{
Assert( m_bIsProcessingCommands );
return m_Commands.Head();
}
#if 0
/*
===============
Cmd_Alias_f
Creates a new command that executes a command string (possibly ; seperated)
===============
*/
void Cmd_Alias_f (void)
{
cmdalias_t *a;
char cmd[MAX_COMMAND_LENGTH];
int i, c;
char *s;
if (Cmd_Argc() == 1)
{
Con_Printf ("Current alias commands:\n");
for (a = cmd_alias ; a ; a=a->next)
Con_Printf ("%s : %s\n", a->name, a->value);
return;
}
s = Cmd_Argv(1);
if (strlen(s) >= MAX_ALIAS_NAME)
{
Con_Printf ("Alias name is too long\n");
return;
}
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
c = Cmd_Argc();
for (i=2 ; i< c ; i++)
{
Q_strncat(cmd, Cmd_Argv(i), sizeof( cmd ), COPY_ALL_CHARACTERS);
if (i != c)
{
Q_strncat (cmd, " ", sizeof( cmd ), COPY_ALL_CHARACTERS );
}
}
Q_strncat (cmd, "\n", sizeof( cmd ), COPY_ALL_CHARACTERS);
// if the alias already exists, reuse it
for (a = cmd_alias ; a ; a=a->next)
{
if (!strcmp(s, a->name))
{
if ( !strcmp( a->value, cmd ) ) // Re-alias the same thing
return;
delete[] a->value;
break;
}
}
if (!a)
{
a = (cmdalias_t *)new cmdalias_t;
a->next = cmd_alias;
cmd_alias = a;
}
Q_strncpy (a->name, s, sizeof( a->name ) );
a->value = COM_StringCopy(cmd);
}
/*
=============================================================================
COMMAND EXECUTION
=============================================================================
*/
#define MAX_ARGS 80
static int cmd_argc;
static char *cmd_argv[MAX_ARGS];
static char *cmd_null_string = "";
static const char *cmd_args = NULL;
cmd_source_t cmd_source;
//-----------------------------------------------------------------------------
// Purpose:
// Output : void Cmd_Init
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void Cmd_Shutdown( void )
{
// TODO, cleanup
while ( cmd_alias )
{
cmdalias_t *next = cmd_alias->next;
delete cmd_alias->value; // created by StringCopy()
delete cmd_alias;
cmd_alias = next;
}
}
/*
============
Cmd_ExecuteString
A complete command line has been parsed, so try to execute it
FIXME: lookupnoadd the token to speed search?
============
*/
const ConCommandBase *Cmd_ExecuteString (const char *text, cmd_source_t src)
{
cmdalias_t *a;
cmd_source = src;
Cmd_TokenizeString (text);
// execute the command line
if (!Cmd_Argc())
return NULL; // no tokens
// check alias
for (a=cmd_alias ; a ; a=a->next)
{
if (!Q_strcasecmp (cmd_argv[0], a->name))
{
Cbuf_InsertText (a->value);
return NULL;
}
}
// check ConCommands
ConCommandBase const *pCommand = ConCommandBase::FindCommand( cmd_argv[ 0 ] );
if ( pCommand && pCommand->IsCommand() )
{
bool isServerCommand = ( pCommand->IsBitSet( FCVAR_GAMEDLL ) &&
// Typed at console
cmd_source == src_command &&
// Not HLDS
!sv.IsDedicated() );
// Hook to allow game .dll to figure out who type the message on a listen server
if ( serverGameClients )
{
// We're actually the server, so set it up locally
if ( sv.IsActive() )
{
g_pServerPluginHandler->SetCommandClient( -1 );
#ifndef SWDS
// Special processing for listen server player
if ( isServerCommand )
{
g_pServerPluginHandler->SetCommandClient( cl.m_nPlayerSlot );
}
#endif
}
// We're not the server, but we've been a listen server (game .dll loaded)
// forward this command tot he server instead of running it locally if we're still
// connected
// Otherwise, things like "say" won't work unless you quit and restart
else if ( isServerCommand )
{
if ( cl.IsConnected() )
{
Cmd_ForwardToServer();
return NULL;
}
else
{
// It's a server command, but we're not connected to a server. Don't try to execute it.
return NULL;
}
}
}
// Allow cheat commands in singleplayer, debug, or multiplayer with sv_cheats on
#ifndef _DEBUG
if ( pCommand->IsBitSet( FCVAR_CHEAT ) )
{
if ( !Host_IsSinglePlayerGame() && sv_cheats.GetInt() == 0 )
{
Msg( "Can't use cheat command %s in multiplayer, unless the server has sv_cheats set to 1.\n", pCommand->GetName() );
return NULL;
}
}
#endif
(( ConCommand * )pCommand )->Dispatch();
return pCommand;
}
// check cvars
if ( cv->IsCommand() )
{
return pCommand;
}
// forward the command line to the server, so the entity DLL can parse it
if ( cmd_source == src_command )
{
if ( cl.IsConnected() )
{
Cmd_ForwardToServer();
return NULL;
}
}
Msg("Unknown command \"%s\"\n", Cmd_Argv(0));
return NULL;
}
#endif

1283
tier1/convar.cpp Normal file

File diff suppressed because it is too large Load Diff

411
tier1/datamanager.cpp Normal file
View File

@ -0,0 +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 ) );
}
}

547
tier1/diff.cpp Normal file
View File

@ -0,0 +1,547 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#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"
// format of diff output:
// 0NN (N=1..127) copy next N literaly
//
// 1NN (N=1..127) ofs (-128..127) copy next N bytes from original, changin offset by N bytes from
// last copy end
// 100 N ofs(-32768..32767) copy next N, with larger delta offset
// 00 NNNN(1..65535) ofs(-32768..32767) big copy from old
// 80 00 NN NN NN big raw copy
//
// available codes (could be used for additonal compression ops)
// long offset form whose offset could have fit in short offset
// note - this algorithm uses storage equal to 8* the old buffer size. 64k=.5mb
#define MIN_MATCH_LEN 8
#define ACCEPTABLE_MATCH_LEN 4096
struct BlockPtr
{
BlockPtr *Next;
uint8 const *dataptr;
};
template<class T,class V> static inline void AddToHead(T * & head, V * node)
{
node->Next=head;
head=node;
}
void Fail(char const *msg)
{
Assert(0);
}
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;
}
static void CopyPending(int len, uint8 const *rawbytes,uint8 * &outbuf, uint8 const *limit)
{
// printf("copy raw len=%d\n",len);
if (len<128)
{
if (limit-outbuf < len+1)
Fail("diff buffer overrun");
*(outbuf++)=len;
memcpy(outbuf,rawbytes,len);
outbuf+=len;
}
else
{
if (limit-outbuf < len+5)
Fail("diff buffer overrun");
*(outbuf++)=0x80;
*(outbuf++)=0x00;
*(outbuf++)=(len & 255);
*(outbuf++)=((len>>8) & 255);
*(outbuf++)=((len>>16) & 255);
memcpy(outbuf,rawbytes,len);
outbuf+=len;
}
}
static uint32 hasher(uint8 const *mdata)
{
// attempt to scramble the bits of h1 and h2 together
uint32 ret=0;
for(int i=0;i<MIN_MATCH_LEN;i++)
{
ret=ret<<4;
ret+=(*mdata++);
}
return ret;
}
int FindDiffsForLargeFiles(uint8 const *NewBlock, uint8 const *OldBlock,
int NewSize, int OldSize, int &DiffListSize,uint8 *Output,
uint32 OutSize,
int hashsize)
{
int ret=0;
if (OldSize!=NewSize)
ret=1;
// first, build the hash table
BlockPtr **HashedMatches=new BlockPtr* [hashsize];
memset(HashedMatches,0,sizeof(HashedMatches[0])*hashsize);
BlockPtr *Blocks=0;
if (OldSize)
Blocks=new BlockPtr[OldSize];
BlockPtr *FreeList=Blocks;
// now, build the hash table
uint8 const *walk=OldBlock;
if (OldBlock && OldSize)
while(walk<OldBlock+OldSize-MIN_MATCH_LEN)
{
uint32 hash1=hasher(walk);
hash1 &=(hashsize-1);
BlockPtr *newnode=FreeList;
FreeList++;
newnode->dataptr=walk;
AddToHead(HashedMatches[hash1],newnode);
walk++;
}
else
ret=1;
// now, we have the hash table which may be used to search. begin the output step
int pending_raw_len=0;
walk=NewBlock;
uint8 *outbuf=Output;
uint8 const *lastmatchend=OldBlock;
while(walk<NewBlock+NewSize)
{
int longest=0;
BlockPtr *longest_block=0;
if (walk<NewBlock+NewSize-MIN_MATCH_LEN)
{
// check for a match
uint32 hash1=hasher(walk);
hash1 &= (hashsize-1);
// now, find the longest match in the hash table. If we find one >MIN_MATCH_LEN, take it
for(BlockPtr *b=HashedMatches[hash1];b;b=b->Next)
{
// find the match length
int match_of=b->dataptr-lastmatchend;
if ((match_of>-32768) && (match_of<32767))
{
int max_mlength=min(65535,OldBlock+OldSize-b->dataptr);
max_mlength=min(max_mlength,NewBlock+NewSize-walk);
int i;
for(i=0;i<max_mlength;i++)
if (walk[i]!=b->dataptr[i])
break;
if ((i>MIN_MATCH_LEN) && (i>longest))
{
longest=i;
longest_block=b;
if (longest>ACCEPTABLE_MATCH_LEN)
break;
}
}
}
}
// now, we have a match maybe
if (longest_block)
{
if (pending_raw_len) // must output
{
ret=1;
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
pending_raw_len=0;
}
// now, output copy block
int match_of=longest_block->dataptr-lastmatchend;
int nremaining=OutSize-(outbuf-Output);
if (match_of)
ret=1;
// printf("copy from %x to %x len=%d\n", match_of,outbuf-Output,longest);
if (longest>127)
{
// use really long encoding
if (nremaining<5)
Fail("diff buff needs increase");
*(outbuf++)=00;
*(outbuf++)=(longest & 255);
*(outbuf++)=((longest>>8) & 255);
*(outbuf++)=(match_of & 255);
*(outbuf++)=((match_of>>8) & 255);
}
else
{
if ((match_of>=-128) && (match_of<128))
{
if (nremaining<2)
Fail("diff buff needs increase");
*(outbuf++)=128+longest;
*(outbuf++)=(match_of&255);
}
else
{
// use long encoding
if (nremaining<4)
Fail("diff buff needs increase");
*(outbuf++)=0x80;
*(outbuf++)=longest;
*(outbuf++)=(match_of & 255);
*(outbuf++)=((match_of>>8) & 255);
}
}
lastmatchend=longest_block->dataptr+longest;
walk+=longest;
}
else
{
walk++;
pending_raw_len++;
}
}
// now, flush pending raw copy
if (pending_raw_len) // must output
{
ret=1;
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
pending_raw_len=0;
}
delete[] HashedMatches;
if (Blocks)
delete[] Blocks;
DiffListSize=outbuf-Output;
return ret;
}
int FindDiffs(uint8 const *NewBlock, uint8 const *OldBlock,
int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize)
{
int ret=0;
if (OldSize!=NewSize)
ret=1;
// first, build the hash table
BlockPtr *HashedMatches[65536];
memset(HashedMatches,0,sizeof(HashedMatches));
BlockPtr *Blocks=0;
if (OldSize)
Blocks=new BlockPtr[OldSize];
BlockPtr *FreeList=Blocks;
// now, build the hash table
uint8 const *walk=OldBlock;
if (OldBlock && OldSize)
while(walk<OldBlock+OldSize-MIN_MATCH_LEN)
{
uint16 hash1=*((uint16 const *) walk)+*((uint16 const *) walk+2);
BlockPtr *newnode=FreeList;
FreeList++;
newnode->dataptr=walk;
AddToHead(HashedMatches[hash1],newnode);
walk++;
}
else
ret=1;
// now, we have the hash table which may be used to search. begin the output step
int pending_raw_len=0;
walk=NewBlock;
uint8 *outbuf=Output;
uint8 const *lastmatchend=OldBlock;
while(walk<NewBlock+NewSize)
{
int longest=0;
BlockPtr *longest_block=0;
if (walk<NewBlock+NewSize-MIN_MATCH_LEN)
{
// check for a match
uint16 hash1=*((uint16 const *) walk)+*((uint16 const *) walk+2);
// now, find the longest match in the hash table. If we find one >MIN_MATCH_LEN, take it
for(BlockPtr *b=HashedMatches[hash1];b;b=b->Next)
{
// find the match length
int match_of=b->dataptr-lastmatchend;
if ((match_of>-32768) && (match_of<32767))
{
int max_mlength=min(65535,OldBlock+OldSize-b->dataptr);
max_mlength=min(max_mlength,NewBlock+NewSize-walk);
int i;
for(i=0;i<max_mlength;i++)
if (walk[i]!=b->dataptr[i])
break;
if ((i>MIN_MATCH_LEN) && (i>longest))
{
longest=i;
longest_block=b;
}
}
}
}
// now, we have a match maybe
if (longest_block)
{
if (pending_raw_len) // must output
{
ret=1;
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
pending_raw_len=0;
}
// now, output copy block
int match_of=longest_block->dataptr-lastmatchend;
int nremaining=OutSize-(outbuf-Output);
if (match_of)
ret=1;
if (longest>127)
{
// use really long encoding
if (nremaining<5)
Fail("diff buff needs increase");
*(outbuf++)=00;
*(outbuf++)=(longest & 255);
*(outbuf++)=((longest>>8) & 255);
*(outbuf++)=(match_of & 255);
*(outbuf++)=((match_of>>8) & 255);
}
else
{
if ((match_of>=-128) && (match_of<128))
{
if (nremaining<2)
Fail("diff buff needs increase");
*(outbuf++)=128+longest;
*(outbuf++)=(match_of&255);
}
else
{
// use long encoding
if (nremaining<4)
Fail("diff buff needs increase");
*(outbuf++)=0x80;
*(outbuf++)=longest;
*(outbuf++)=(match_of & 255);
*(outbuf++)=((match_of>>8) & 255);
}
}
lastmatchend=longest_block->dataptr+longest;
walk+=longest;
}
else
{
walk++;
pending_raw_len++;
}
}
// now, flush pending raw copy
if (pending_raw_len) // must output
{
ret=1;
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
pending_raw_len=0;
}
if (Blocks)
delete[] Blocks;
DiffListSize=outbuf-Output;
return ret;
}
int FindDiffsLowMemory(uint8 const *NewBlock, uint8 const *OldBlock,
int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize)
{
int ret=0;
if (OldSize!=NewSize)
ret=1;
uint8 const *old_data_hash[256];
memset(old_data_hash,0,sizeof(old_data_hash));
int pending_raw_len=0;
uint8 const *walk=NewBlock;
uint8 const *oldptr=OldBlock;
uint8 *outbuf=Output;
uint8 const *lastmatchend=OldBlock;
while(walk<NewBlock+NewSize)
{
while( (oldptr-OldBlock<walk-NewBlock+40) && (oldptr-OldBlock<OldSize-MIN_MATCH_LEN))
{
uint16 hash1=(oldptr[0]+oldptr[1]+oldptr[2]+oldptr[3]) & (NELEMS(old_data_hash)-1);
old_data_hash[hash1]=oldptr;
oldptr++;
}
int longest=0;
uint8 const *longest_block=0;
if (walk<NewBlock+NewSize-MIN_MATCH_LEN)
{
// check for a match
uint16 hash1=(walk[0]+walk[1]+walk[2]+walk[3]) & (NELEMS(old_data_hash)-1);
if (old_data_hash[hash1])
{
int max_bytes_to_compare=min(NewBlock+NewSize-walk,OldBlock+OldSize-old_data_hash[hash1]);
int nmatches;
for(nmatches=0;nmatches<max_bytes_to_compare;nmatches++)
if (walk[nmatches]!=old_data_hash[hash1][nmatches])
break;
if (nmatches>MIN_MATCH_LEN)
{
longest_block=old_data_hash[hash1];
longest=nmatches;
}
}
}
// now, we have a match maybe
if (longest_block)
{
if (pending_raw_len) // must output
{
ret=1;
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
pending_raw_len=0;
}
// now, output copy block
int match_of=longest_block-lastmatchend;
int nremaining=OutSize-(outbuf-Output);
if (match_of)
ret=1;
if (longest>127)
{
// use really long encoding
if (nremaining<5)
Fail("diff buff needs increase");
*(outbuf++)=00;
*(outbuf++)=(longest & 255);
*(outbuf++)=((longest>>8) & 255);
*(outbuf++)=(match_of & 255);
*(outbuf++)=((match_of>>8) & 255);
}
else
{
if ((match_of>=-128) && (match_of<128))
{
if (nremaining<2)
Fail("diff buff needs increase");
*(outbuf++)=128+longest;
*(outbuf++)=(match_of&255);
}
else
{
// use long encoding
if (nremaining<4)
Fail("diff buff needs increase");
*(outbuf++)=0x80;
*(outbuf++)=longest;
*(outbuf++)=(match_of & 255);
*(outbuf++)=((match_of>>8) & 255);
}
}
lastmatchend=longest_block+longest;
walk+=longest;
}
else
{
walk++;
pending_raw_len++;
}
}
// now, flush pending raw copy
if (pending_raw_len) // must output
{
ret=1;
CopyPending(pending_raw_len,walk-pending_raw_len,outbuf,Output+OutSize);
pending_raw_len=0;
}
DiffListSize=outbuf-Output;
return ret;
}

497
tier1/fileio.cpp Normal file
View File

@ -0,0 +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
#endif // _PS3 || _X360

437
tier1/generichash.cpp Normal file
View File

@ -0,0 +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;
}

259
tier1/ilocalize.cpp Normal file
View File

@ -0,0 +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 );
}

542
tier1/interface.cpp Normal file
View File

@ -0,0 +1,542 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#if defined( _WIN32 ) && !defined( _X360 )
#include <windows.h>
#endif
#if !defined( DONT_PROTECT_FILEIO_FUNCTIONS )
#define DONT_PROTECT_FILEIO_FUNCTIONS // for protected_things.h
#endif
#if defined( PROTECTED_THINGS_ENABLE )
#undef PROTECTED_THINGS_ENABLE // from protected_things.h
#endif
#include <stdio.h>
#include "interface.h"
#include "basetypes.h"
#include "tier0/dbg.h"
#include <string.h>
#include <stdlib.h>
#include "tier1/strtools.h"
#include "tier0/icommandline.h"
#include "tier0/dbg.h"
#include "tier0/threadtools.h"
#ifdef _WIN32
#include <direct.h> // getcwd
#elif POSIX
#include <dlfcn.h>
#include <unistd.h>
#define _getcwd getcwd
#endif
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// ------------------------------------------------------------------------------------ //
// InterfaceReg.
// ------------------------------------------------------------------------------------ //
InterfaceReg *InterfaceReg::s_pInterfaceRegs = NULL;
InterfaceReg::InterfaceReg( InstantiateInterfaceFn fn, const char *pName ) :
m_pName(pName)
{
m_CreateFn = fn;
m_pNext = s_pInterfaceRegs;
s_pInterfaceRegs = this;
}
// ------------------------------------------------------------------------------------ //
// CreateInterface.
// This is the primary exported function by a dll, referenced by name via dynamic binding
// that exposes an opqaue function pointer to the interface.
//
// We have the Internal variant so Sys_GetFactoryThis() returns the correct internal
// symbol under GCC/Linux/Mac as CreateInterface is DLL_EXPORT so its global so the loaders
// on those OS's pick exactly 1 of the CreateInterface symbols to be the one that is process wide and
// all Sys_GetFactoryThis() calls find that one, which doesn't work. Using the internal walkthrough here
// makes sure Sys_GetFactoryThis() has the dll specific symbol and GetProcAddress() returns the module specific
// function for CreateInterface again getting the dll specific symbol we need.
// ------------------------------------------------------------------------------------ //
void* CreateInterfaceInternal( const char *pName, int *pReturnCode )
{
InterfaceReg *pCur;
for (pCur=InterfaceReg::s_pInterfaceRegs; pCur; pCur=pCur->m_pNext)
{
if (strcmp(pCur->m_pName, pName) == 0)
{
if (pReturnCode)
{
*pReturnCode = IFACE_OK;
}
return pCur->m_CreateFn();
}
}
if (pReturnCode)
{
*pReturnCode = IFACE_FAILED;
}
return NULL;
}
void* CreateInterface( const char *pName, int *pReturnCode )
{
return CreateInterfaceInternal( pName, pReturnCode );
}
#ifdef POSIX
// Linux doesn't have this function so this emulates its functionality
void *GetModuleHandle(const char *name)
{
void *handle;
if( name == NULL )
{
// hmm, how can this be handled under linux....
// is it even needed?
return NULL;
}
if( (handle=dlopen(name, RTLD_NOW))==NULL)
{
printf("DLOPEN Error:%s\n",dlerror());
// couldn't open this file
return NULL;
}
// read "man dlopen" for details
// in short dlopen() inc a ref count
// so dec the ref count by performing the close
dlclose(handle);
return handle;
}
#endif
#if defined( _WIN32 ) && !defined( _X360 )
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to a function, given a module
// Input : pModuleName - module name
// *pName - proc name
//-----------------------------------------------------------------------------
static void *Sys_GetProcAddress( const char *pModuleName, const char *pName )
{
HMODULE hModule = (HMODULE)GetModuleHandle( pModuleName );
#ifdef WIN32
return (void *)GetProcAddress( hModule, pName );
#else
return (void *)dlsym( (void *)hModule, pName );
#endif
}
static void *Sys_GetProcAddress( HMODULE hModule, const char *pName )
{
#ifdef WIN32
return (void *)GetProcAddress( hModule, pName );
#else
return (void *)dlsym( (void *)hModule, pName );
#endif
}
bool Sys_IsDebuggerPresent()
{
return Plat_IsInDebugSession();
}
struct ThreadedLoadLibaryContext_t
{
const char *m_pLibraryName;
HMODULE m_hLibrary;
};
#ifdef _WIN32
// wraps LoadLibraryEx() since 360 doesn't support that
static HMODULE InternalLoadLibrary( const char *pName, Sys_Flags flags )
{
#if defined(_X360)
return LoadLibrary( pName );
#else
if ( flags & SYS_NOLOAD )
return GetModuleHandle( pName );
else
return LoadLibraryEx( pName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
#endif
}
unsigned ThreadedLoadLibraryFunc( void *pParam )
{
ThreadedLoadLibaryContext_t *pContext = (ThreadedLoadLibaryContext_t*)pParam;
pContext->m_hLibrary = InternalLoadLibrary( pContext->m_pLibraryName, SYS_NOFLAGS );
return 0;
}
#endif // _WIN32
HMODULE Sys_LoadLibrary( const char *pLibraryName, Sys_Flags flags )
{
char str[ 1024 ];
// Note: DLL_EXT_STRING can be "_srv.so" or "_360.dll". So be careful
// when using the V_*Extension* routines...
const char *pDllStringExtension = V_GetFileExtension( DLL_EXT_STRING );
const char *pModuleExtension = pDllStringExtension ? ( pDllStringExtension - 1 ) : DLL_EXT_STRING;
Q_strncpy( str, pLibraryName, sizeof(str) );
if ( IsX360() )
{
// old, probably busted, behavior for xbox
if ( !Q_stristr( str, pModuleExtension ) )
{
V_SetExtension( str, pModuleExtension, sizeof(str) );
}
}
else
{
// always force the final extension to be .dll
V_SetExtension( str, pModuleExtension, sizeof(str) );
}
Q_FixSlashes( str );
#ifdef _WIN32
ThreadedLoadLibraryFunc_t threadFunc = GetThreadedLoadLibraryFunc();
if ( !threadFunc )
return InternalLoadLibrary( str, flags );
// We shouldn't be passing noload while threaded.
Assert( !( flags & SYS_NOLOAD ) );
ThreadedLoadLibaryContext_t context;
context.m_pLibraryName = str;
context.m_hLibrary = 0;
ThreadHandle_t h = CreateSimpleThread( ThreadedLoadLibraryFunc, &context );
#ifdef _X360
ThreadSetAffinity( h, XBOX_PROCESSOR_3 );
#endif
unsigned int nTimeout = 0;
while( ThreadWaitForObject( h, true, nTimeout ) == TW_TIMEOUT )
{
nTimeout = threadFunc();
}
ReleaseThreadHandle( h );
return context.m_hLibrary;
#elif POSIX
int dlopen_mode = RTLD_NOW;
if ( flags & SYS_NOLOAD )
dlopen_mode |= RTLD_NOLOAD;
HMODULE ret = ( HMODULE )dlopen( str, dlopen_mode );
if ( !ret && !( flags & SYS_NOLOAD ) )
{
const char *pError = dlerror();
if ( pError && ( strstr( pError, "No such file" ) == 0 ) && ( strstr( pError, "image not found" ) == 0 ) )
{
Msg( " failed to dlopen %s error=%s\n", str, pError );
}
}
return ret;
#endif
}
static bool s_bRunningWithDebugModules = false;
//-----------------------------------------------------------------------------
// Purpose: Loads a DLL/component from disk and returns a handle to it
// Input : *pModuleName - filename of the component
// Output : opaque handle to the module (hides system dependency)
//-----------------------------------------------------------------------------
CSysModule *Sys_LoadModule( const char *pModuleName, Sys_Flags flags /* = SYS_NOFLAGS (0) */ )
{
// If using the Steam filesystem, either the DLL must be a minimum footprint
// file in the depot (MFP) or a filesystem GetLocalCopy() call must be made
// prior to the call to this routine.
char szCwd[1024];
HMODULE hDLL = NULL;
if ( !Q_IsAbsolutePath( pModuleName ) )
{
// full path wasn't passed in, using the current working dir
_getcwd( szCwd, sizeof( szCwd ) );
if ( IsX360() )
{
int i = CommandLine()->FindParm( "-basedir" );
if ( i )
{
strcpy( szCwd, CommandLine()->GetParm( i+1 ) );
}
}
if (szCwd[strlen(szCwd) - 1] == '/' || szCwd[strlen(szCwd) - 1] == '\\' )
{
szCwd[strlen(szCwd) - 1] = 0;
}
char szAbsoluteModuleName[1024];
size_t cCwd = strlen( szCwd );
if ( strstr( pModuleName, "bin/") == pModuleName || ( szCwd[ cCwd - 1 ] == 'n' && szCwd[ cCwd - 2 ] == 'i' && szCwd[ cCwd - 3 ] == 'b' ) )
{
// don't make bin/bin path
Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/%s", szCwd, pModuleName );
}
else
{
Q_snprintf( szAbsoluteModuleName, sizeof(szAbsoluteModuleName), "%s/bin/%s", szCwd, pModuleName );
}
hDLL = Sys_LoadLibrary( szAbsoluteModuleName, flags );
}
if ( !hDLL )
{
// full path failed, let LoadLibrary() try to search the PATH now
hDLL = Sys_LoadLibrary( pModuleName, flags );
#if defined( _DEBUG )
if ( !hDLL )
{
// So you can see what the error is in the debugger...
#if defined( _WIN32 ) && !defined( _X360 )
char *lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
LocalFree( (HLOCAL)lpMsgBuf );
#elif defined( _X360 )
DWORD error = GetLastError();
Msg( "Error(%d) - Failed to load %s:\n", error, pModuleName );
#else
Msg( "Failed to load %s: %s\n", pModuleName, dlerror() );
#endif // _WIN32
}
#endif // DEBUG
}
#if !defined(LINUX)
// If running in the debugger, assume debug binaries are okay, otherwise they must run with -allowdebug
if ( Sys_GetProcAddress( hDLL, "BuiltDebug" ) )
{
if ( !IsX360() && hDLL &&
!CommandLine()->FindParm( "-allowdebug" ) &&
!Sys_IsDebuggerPresent() )
{
Error( "Module %s is a debug build\n", pModuleName );
}
DevWarning( "Module %s is a debug build\n", pModuleName );
if ( !s_bRunningWithDebugModules )
{
s_bRunningWithDebugModules = true;
#if 0 //def IS_WINDOWS_PC
char chMemoryName[ MAX_PATH ];
DebugKernelMemoryObjectName( chMemoryName );
(void) CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, chMemoryName );
// Created a shared memory kernel object specific to process id
// Existence of this object indicates that we have debug modules loaded
#endif
}
}
#endif
return reinterpret_cast<CSysModule *>(hDLL);
}
//-----------------------------------------------------------------------------
// Purpose: Determine if any debug modules were loaded
//-----------------------------------------------------------------------------
bool Sys_RunningWithDebugModules()
{
if ( !s_bRunningWithDebugModules )
{
#if 0 //def IS_WINDOWS_PC
char chMemoryName[ MAX_PATH ];
DebugKernelMemoryObjectName( chMemoryName );
HANDLE hObject = OpenFileMapping( FILE_MAP_READ, FALSE, chMemoryName );
if ( hObject && hObject != INVALID_HANDLE_VALUE )
{
CloseHandle( hObject );
s_bRunningWithDebugModules = true;
}
#endif
}
return s_bRunningWithDebugModules;
}
//-----------------------------------------------------------------------------
// Purpose: Unloads a DLL/component from
// Input : *pModuleName - filename of the component
// Output : opaque handle to the module (hides system dependency)
//-----------------------------------------------------------------------------
void Sys_UnloadModule( CSysModule *pModule )
{
if ( !pModule )
return;
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
#ifdef _WIN32
FreeLibrary( hDLL );
#elif defined(POSIX)
dlclose((void *)hDLL);
#endif
}
//-----------------------------------------------------------------------------
// Purpose: returns a pointer to a function, given a module
// Input : module - windows HMODULE from Sys_LoadModule()
// *pName - proc name
// Output : factory for this module
//-----------------------------------------------------------------------------
CreateInterfaceFn Sys_GetFactory( CSysModule *pModule )
{
if ( !pModule )
return NULL;
HMODULE hDLL = reinterpret_cast<HMODULE>(pModule);
#ifdef _WIN32
return reinterpret_cast<CreateInterfaceFn>(GetProcAddress( hDLL, CREATEINTERFACE_PROCNAME ));
#elif defined(POSIX)
// Linux gives this error:
//../public/interface.cpp: In function `IBaseInterface *(*Sys_GetFactory
//(CSysModule *)) (const char *, int *)':
//../public/interface.cpp:154: ISO C++ forbids casting between
//pointer-to-function and pointer-to-object
//
// so lets get around it :)
return (CreateInterfaceFn)(GetProcAddress( (void *)hDLL, CREATEINTERFACE_PROCNAME ));
#endif
}
//-----------------------------------------------------------------------------
// Purpose: returns the instance of this module
// Output : interface_instance_t
//-----------------------------------------------------------------------------
CreateInterfaceFn Sys_GetFactoryThis( void )
{
return &CreateInterfaceInternal;
}
//-----------------------------------------------------------------------------
// Purpose: returns the instance of the named module
// Input : *pModuleName - name of the module
// Output : interface_instance_t - instance of that module
//-----------------------------------------------------------------------------
CreateInterfaceFn Sys_GetFactory( const char *pModuleName )
{
#ifdef _WIN32
return static_cast<CreateInterfaceFn>( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
#elif defined(POSIX)
// see Sys_GetFactory( CSysModule *pModule ) for an explanation
return (CreateInterfaceFn)( Sys_GetProcAddress( pModuleName, CREATEINTERFACE_PROCNAME ) );
#endif
}
//-----------------------------------------------------------------------------
// Purpose: get the interface for the specified module and version
// Input :
// Output :
//-----------------------------------------------------------------------------
bool Sys_LoadInterface(
const char *pModuleName,
const char *pInterfaceVersionName,
CSysModule **pOutModule,
void **pOutInterface )
{
CSysModule *pMod = Sys_LoadModule( pModuleName );
if ( !pMod )
return false;
CreateInterfaceFn fn = Sys_GetFactory( pMod );
if ( !fn )
{
Sys_UnloadModule( pMod );
return false;
}
*pOutInterface = fn( pInterfaceVersionName, NULL );
if ( !( *pOutInterface ) )
{
Sys_UnloadModule( pMod );
return false;
}
if ( pOutModule )
*pOutModule = pMod;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name.
//
// When the singleton goes out of scope (.dll unload if at module scope),
// then it'll call Sys_UnloadModule on the module so that the refcount is decremented
// and the .dll actually can unload from memory.
//-----------------------------------------------------------------------------
CDllDemandLoader::CDllDemandLoader( char const *pchModuleName ) :
m_pchModuleName( pchModuleName ),
m_hModule( 0 ),
m_bLoadAttempted( false )
{
}
CDllDemandLoader::~CDllDemandLoader()
{
Unload();
}
CreateInterfaceFn CDllDemandLoader::GetFactory()
{
if ( !m_hModule && !m_bLoadAttempted )
{
m_bLoadAttempted = true;
m_hModule = Sys_LoadModule( m_pchModuleName );
}
if ( !m_hModule )
{
return NULL;
}
return Sys_GetFactory( m_hModule );
}
void CDllDemandLoader::Unload()
{
if ( m_hModule )
{
Sys_UnloadModule( m_hModule );
m_hModule = 0;
}
}

274
tier1/kvpacker.cpp Normal file
View File

@ -0,0 +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();
}

312
tier1/mempool.cpp Normal file
View File

@ -0,0 +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;
}

297
tier1/memstack.cpp Normal file
View File

@ -0,0 +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() );
}
//-----------------------------------------------------------------------------

717
tier1/newbitbuf.cpp Normal file
View File

@ -0,0 +1,717 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "bitbuf.h"
#include "coordsize.h"
#include "mathlib/vector.h"
#include "mathlib/mathlib.h"
#include "tier1/strtools.h"
#include "bitvec.h"
// FIXME: Can't use this until we get multithreaded allocations in tier0 working for tools
// This is used by VVIS and fails to link
// NOTE: This must be the last file included!!!
//#include "tier0/memdbgon.h"
#ifdef _X360
// mandatory ... wary of above comment and isolating, tier0 is built as MT though
#include "tier0/memdbgon.h"
#endif
#include "stdio.h"
#if 0
void CBitWrite::StartWriting( void *pData, int nBytes, int iStartBit, int nBits )
{
// Make sure it's dword aligned and padded.
Assert( (nBytes % 4) == 0 );
Assert(((unsigned long)pData & 3) == 0);
Assert( iStartBit == 0 );
m_pData = (uint32 *) pData;
m_pDataOut = m_pData;
m_nDataBytes = nBytes;
if ( nBits == -1 )
{
m_nDataBits = nBytes << 3;
}
else
{
Assert( nBits <= nBytes*8 );
m_nDataBits = nBits;
}
m_bOverflow = false;
m_nOutBufWord = 0;
m_nOutBitsAvail = 32;
m_pBufferEnd = m_pDataOut + ( nBytes >> 2 );
}
const uint32 CBitBuffer::s_nMaskTable[33] = {
0,
( 1 << 1 ) - 1,
( 1 << 2 ) - 1,
( 1 << 3 ) - 1,
( 1 << 4 ) - 1,
( 1 << 5 ) - 1,
( 1 << 6 ) - 1,
( 1 << 7 ) - 1,
( 1 << 8 ) - 1,
( 1 << 9 ) - 1,
( 1 << 10 ) - 1,
( 1 << 11 ) - 1,
( 1 << 12 ) - 1,
( 1 << 13 ) - 1,
( 1 << 14 ) - 1,
( 1 << 15 ) - 1,
( 1 << 16 ) - 1,
( 1 << 17 ) - 1,
( 1 << 18 ) - 1,
( 1 << 19 ) - 1,
( 1 << 20 ) - 1,
( 1 << 21 ) - 1,
( 1 << 22 ) - 1,
( 1 << 23 ) - 1,
( 1 << 24 ) - 1,
( 1 << 25 ) - 1,
( 1 << 26 ) - 1,
( 1 << 27 ) - 1,
( 1 << 28 ) - 1,
( 1 << 29 ) - 1,
( 1 << 30 ) - 1,
0x7fffffff,
0xffffffff,
};
bool CBitWrite::WriteString( const char *pStr )
{
if(pStr)
{
while( *pStr )
{
WriteChar( * ( pStr++ ) );
}
}
WriteChar( 0 );
return !IsOverflowed();
}
void CBitWrite::WriteLongLong(int64 val)
{
uint *pLongs = (uint*)&val;
// Insert the two DWORDS according to network endian
const short endianIndex = 0x0100;
byte *idx = (byte*)&endianIndex;
WriteUBitLong(pLongs[*idx++], sizeof(long) << 3);
WriteUBitLong(pLongs[*idx], sizeof(long) << 3);
}
bool CBitWrite::WriteBits(const void *pInData, int nBits)
{
unsigned char *pOut = (unsigned char*)pInData;
int nBitsLeft = nBits;
// Bounds checking..
if ( ( GetNumBitsWritten() + nBits) > m_nDataBits )
{
SetOverflowFlag();
CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, m_pDebugName );
return false;
}
// !! speed!! need fast paths
// write remaining bytes
while ( nBitsLeft >= 8 )
{
WriteUBitLong( *pOut, 8, false );
++pOut;
nBitsLeft -= 8;
}
// write remaining bits
if ( nBitsLeft )
{
WriteUBitLong( *pOut, nBitsLeft, false );
}
return !IsOverflowed();
}
void CBitWrite::WriteBytes( const void *pBuf, int nBytes )
{
WriteBits(pBuf, nBytes << 3);
}
void CBitWrite::WriteBitCoord (const float f)
{
int signbit = (f <= -COORD_RESOLUTION);
int intval = (int)abs(f);
int fractval = abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1);
// Send the bit flags that indicate whether we have an integer part and/or a fraction part.
WriteOneBit( intval );
WriteOneBit( fractval );
if ( intval || fractval )
{
// Send the sign bit
WriteOneBit( signbit );
// Send the integer if we have one.
if ( intval )
{
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
intval--;
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
}
// Send the fraction if we have one
if ( fractval )
{
WriteUBitLong( (unsigned int)fractval, COORD_FRACTIONAL_BITS );
}
}
}
void CBitWrite::WriteBitCoordMP (const float f, bool bIntegral, bool bLowPrecision )
{
int signbit = (f <= -( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ));
int intval = (int)abs(f);
int fractval = bLowPrecision ?
( abs((int)(f*COORD_DENOMINATOR_LOWPRECISION)) & (COORD_DENOMINATOR_LOWPRECISION-1) ) :
( abs((int)(f*COORD_DENOMINATOR)) & (COORD_DENOMINATOR-1) );
bool bInBounds = intval < (1 << COORD_INTEGER_BITS_MP );
WriteOneBit( bInBounds );
if ( bIntegral )
{
// Send the sign bit
WriteOneBit( intval );
if ( intval )
{
WriteOneBit( signbit );
// Send the integer if we have one.
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
intval--;
if ( bInBounds )
{
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP );
}
else
{
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
}
}
}
else
{
// Send the bit flags that indicate whether we have an integer part and/or a fraction part.
WriteOneBit( intval );
// Send the sign bit
WriteOneBit( signbit );
// Send the integer if we have one.
if ( intval )
{
// Adjust the integers from [1..MAX_COORD_VALUE] to [0..MAX_COORD_VALUE-1]
intval--;
if ( bInBounds )
{
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS_MP );
}
else
{
WriteUBitLong( (unsigned int)intval, COORD_INTEGER_BITS );
}
}
WriteUBitLong( (unsigned int)fractval, bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS );
}
}
void CBitWrite::SeekToBit( int nBit )
{
TempFlush();
m_pDataOut = m_pData + ( nBit / 32 );
m_nOutBufWord = *( m_pDataOut );
m_nOutBitsAvail = 32 - ( nBit & 31 );
}
void CBitWrite::WriteBitVec3Coord( const Vector& fa )
{
int xflag, yflag, zflag;
xflag = (fa[0] >= COORD_RESOLUTION) || (fa[0] <= -COORD_RESOLUTION);
yflag = (fa[1] >= COORD_RESOLUTION) || (fa[1] <= -COORD_RESOLUTION);
zflag = (fa[2] >= COORD_RESOLUTION) || (fa[2] <= -COORD_RESOLUTION);
WriteOneBit( xflag );
WriteOneBit( yflag );
WriteOneBit( zflag );
if ( xflag )
WriteBitCoord( fa[0] );
if ( yflag )
WriteBitCoord( fa[1] );
if ( zflag )
WriteBitCoord( fa[2] );
}
void CBitWrite::WriteBitNormal( float f )
{
int signbit = (f <= -NORMAL_RESOLUTION);
// NOTE: Since +/-1 are valid values for a normal, I'm going to encode that as all ones
unsigned int fractval = abs( (int)(f*NORMAL_DENOMINATOR) );
// clamp..
if (fractval > NORMAL_DENOMINATOR)
fractval = NORMAL_DENOMINATOR;
// Send the sign bit
WriteOneBit( signbit );
// Send the fractional component
WriteUBitLong( fractval, NORMAL_FRACTIONAL_BITS );
}
void CBitWrite::WriteBitVec3Normal( const Vector& fa )
{
int xflag, yflag;
xflag = (fa[0] >= NORMAL_RESOLUTION) || (fa[0] <= -NORMAL_RESOLUTION);
yflag = (fa[1] >= NORMAL_RESOLUTION) || (fa[1] <= -NORMAL_RESOLUTION);
WriteOneBit( xflag );
WriteOneBit( yflag );
if ( xflag )
WriteBitNormal( fa[0] );
if ( yflag )
WriteBitNormal( fa[1] );
// Write z sign bit
int signbit = (fa[2] <= -NORMAL_RESOLUTION);
WriteOneBit( signbit );
}
void CBitWrite::WriteBitAngle( float fAngle, int numbits )
{
unsigned int shift = GetBitForBitnum(numbits);
unsigned int mask = shift - 1;
int d = (int)( (fAngle / 360.0) * shift );
d &= mask;
WriteUBitLong((unsigned int)d, numbits);
}
bool CBitWrite::WriteBitsFromBuffer( bf_read *pIn, int nBits )
{
// This could be optimized a little by
while ( nBits > 32 )
{
WriteUBitLong( pIn->ReadUBitLong( 32 ), 32 );
nBits -= 32;
}
WriteUBitLong( pIn->ReadUBitLong( nBits ), nBits );
return !IsOverflowed() && !pIn->IsOverflowed();
}
void CBitWrite::WriteBitAngles( const QAngle& fa )
{
// FIXME:
Vector tmp( fa.x, fa.y, fa.z );
WriteBitVec3Coord( tmp );
}
bool CBitRead::Seek( int nPosition )
{
bool bSucc = true;
if ( nPosition < 0 || nPosition > m_nDataBits)
{
SetOverflowFlag();
bSucc = false;
nPosition = m_nDataBits;
}
int nHead = m_nDataBytes & 3; // non-multiple-of-4 bytes at head of buffer. We put the "round off"
// at the head to make reading and detecting the end efficient.
int nByteOfs = nPosition / 8;
if ( ( m_nDataBytes < 4 ) || ( nHead && ( nByteOfs < nHead ) ) )
{
// partial first dword
uint8 const *pPartial = ( uint8 const *) m_pData;
if ( m_pData )
{
m_nInBufWord = *( pPartial++ );
if ( nHead > 1 )
m_nInBufWord |= ( *pPartial++ ) << 8;
if ( nHead > 2 )
m_nInBufWord |= ( *pPartial++ ) << 16;
}
m_pDataIn = ( uint32 const * ) pPartial;
m_nInBufWord >>= ( nPosition & 31 );
m_nBitsAvail = ( nHead << 3 ) - ( nPosition & 31 );
}
else
{
int nAdjPosition = nPosition - ( nHead << 3 );
m_pDataIn = reinterpret_cast<uint32 const *> (
reinterpret_cast<uint8 const *>( m_pData ) + ( ( nAdjPosition / 32 ) << 2 ) + nHead );
if ( m_pData )
{
m_nBitsAvail = 32;
GrabNextDWord();
}
else
{
m_nInBufWord = 0;
m_nBitsAvail = 1;
}
m_nInBufWord >>= ( nAdjPosition & 31 );
m_nBitsAvail = min( m_nBitsAvail, 32 - ( nAdjPosition & 31 ) ); // in case grabnextdword overflowed
}
return bSucc;
}
void CBitRead::StartReading( const void *pData, int nBytes, int iStartBit, int nBits )
{
// Make sure it's dword aligned and padded.
Assert(((unsigned long)pData & 3) == 0);
m_pData = (uint32 *) pData;
m_pDataIn = m_pData;
m_nDataBytes = nBytes;
if ( nBits == -1 )
{
m_nDataBits = nBytes << 3;
}
else
{
Assert( nBits <= nBytes*8 );
m_nDataBits = nBits;
}
m_bOverflow = false;
m_pBufferEnd = reinterpret_cast<uint32 const *> ( reinterpret_cast< uint8 const *> (m_pData) + nBytes );
if ( m_pData )
Seek( iStartBit );
}
bool CBitRead::ReadString( char *pStr, int maxLen, bool bLine, int *pOutNumChars )
{
Assert( maxLen != 0 );
bool bTooSmall = false;
int iChar = 0;
while(1)
{
char val = ReadChar();
if ( val == 0 )
break;
else if ( bLine && val == '\n' )
break;
if ( iChar < (maxLen-1) )
{
pStr[iChar] = val;
++iChar;
}
else
{
bTooSmall = true;
}
}
// Make sure it's null-terminated.
Assert( iChar < maxLen );
pStr[iChar] = 0;
if ( pOutNumChars )
*pOutNumChars = iChar;
return !IsOverflowed() && !bTooSmall;
}
char* CBitRead::ReadAndAllocateString( bool *pOverflow )
{
char str[2048];
int nChars;
bool bOverflow = !ReadString( str, sizeof( str ), false, &nChars );
if ( pOverflow )
*pOverflow = bOverflow;
// Now copy into the output and return it;
char *pRet = new char[ nChars + 1 ];
for ( int i=0; i <= nChars; i++ )
pRet[i] = str[i];
return pRet;
}
int64 CBitRead::ReadLongLong( void )
{
int64 retval;
uint *pLongs = (uint*)&retval;
// Read the two DWORDs according to network endian
const short endianIndex = 0x0100;
byte *idx = (byte*)&endianIndex;
pLongs[*idx++] = ReadUBitLong(sizeof(long) << 3);
pLongs[*idx] = ReadUBitLong(sizeof(long) << 3);
return retval;
}
void CBitRead::ReadBits(void *pOutData, int nBits)
{
unsigned char *pOut = (unsigned char*)pOutData;
int nBitsLeft = nBits;
// align output to dword boundary
while( ((unsigned long)pOut & 3) != 0 && nBitsLeft >= 8 )
{
*pOut = (unsigned char)ReadUBitLong(8);
++pOut;
nBitsLeft -= 8;
}
// X360TBD: Can't read dwords in ReadBits because they'll get swapped
if ( IsPC() )
{
// read dwords
while ( nBitsLeft >= 32 )
{
*((unsigned long*)pOut) = ReadUBitLong(32);
pOut += sizeof(unsigned long);
nBitsLeft -= 32;
}
}
// read remaining bytes
while ( nBitsLeft >= 8 )
{
*pOut = ReadUBitLong(8);
++pOut;
nBitsLeft -= 8;
}
// read remaining bits
if ( nBitsLeft )
{
*pOut = ReadUBitLong(nBitsLeft);
}
}
bool CBitRead::ReadBytes(void *pOut, int nBytes)
{
ReadBits(pOut, nBytes << 3);
return !IsOverflowed();
}
float CBitRead::ReadBitAngle( int numbits )
{
float shift = (float)( GetBitForBitnum(numbits) );
int i = ReadUBitLong( numbits );
float fReturn = (float)i * (360.0 / shift);
return fReturn;
}
// Basic Coordinate Routines (these contain bit-field size AND fixed point scaling constants)
float CBitRead::ReadBitCoord (void)
{
int intval=0,fractval=0,signbit=0;
float value = 0.0;
// Read the required integer and fraction flags
intval = ReadOneBit();
fractval = ReadOneBit();
// If we got either parse them, otherwise it's a zero.
if ( intval || fractval )
{
// Read the sign bit
signbit = ReadOneBit();
// If there's an integer, read it in
if ( intval )
{
// Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE]
intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
}
// If there's a fraction, read it in
if ( fractval )
{
fractval = ReadUBitLong( COORD_FRACTIONAL_BITS );
}
// Calculate the correct floating point value
value = intval + ((float)fractval * COORD_RESOLUTION);
// Fixup the sign if negative.
if ( signbit )
value = -value;
}
return value;
}
float CBitRead::ReadBitCoordMP( bool bIntegral, bool bLowPrecision )
{
int intval=0,fractval=0,signbit=0;
float value = 0.0;
bool bInBounds = ReadOneBit() ? true : false;
if ( bIntegral )
{
// Read the required integer and fraction flags
intval = ReadOneBit();
// If we got either parse them, otherwise it's a zero.
if ( intval )
{
// Read the sign bit
signbit = ReadOneBit();
// If there's an integer, read it in
// Adjust the integers from [0..MAX_COORD_VALUE-1] to [1..MAX_COORD_VALUE]
if ( bInBounds )
{
value = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1;
}
else
{
value = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
}
}
}
else
{
// Read the required integer and fraction flags
intval = ReadOneBit();
// Read the sign bit
signbit = ReadOneBit();
// If we got either parse them, otherwise it's a zero.
if ( intval )
{
if ( bInBounds )
{
intval = ReadUBitLong( COORD_INTEGER_BITS_MP ) + 1;
}
else
{
intval = ReadUBitLong( COORD_INTEGER_BITS ) + 1;
}
}
// If there's a fraction, read it in
fractval = ReadUBitLong( bLowPrecision ? COORD_FRACTIONAL_BITS_MP_LOWPRECISION : COORD_FRACTIONAL_BITS );
// Calculate the correct floating point value
value = intval + ((float)fractval * ( bLowPrecision ? COORD_RESOLUTION_LOWPRECISION : COORD_RESOLUTION ) );
}
// Fixup the sign if negative.
if ( signbit )
value = -value;
return value;
}
void CBitRead::ReadBitVec3Coord( Vector& fa )
{
int xflag, yflag, zflag;
// This vector must be initialized! Otherwise, If any of the flags aren't set,
// the corresponding component will not be read and will be stack garbage.
fa.Init( 0, 0, 0 );
xflag = ReadOneBit();
yflag = ReadOneBit();
zflag = ReadOneBit();
if ( xflag )
fa[0] = ReadBitCoord();
if ( yflag )
fa[1] = ReadBitCoord();
if ( zflag )
fa[2] = ReadBitCoord();
}
float CBitRead::ReadBitNormal (void)
{
// Read the sign bit
int signbit = ReadOneBit();
// Read the fractional part
unsigned int fractval = ReadUBitLong( NORMAL_FRACTIONAL_BITS );
// Calculate the correct floating point value
float value = (float)fractval * NORMAL_RESOLUTION;
// Fixup the sign if negative.
if ( signbit )
value = -value;
return value;
}
void CBitRead::ReadBitVec3Normal( Vector& fa )
{
int xflag = ReadOneBit();
int yflag = ReadOneBit();
if (xflag)
fa[0] = ReadBitNormal();
else
fa[0] = 0.0f;
if (yflag)
fa[1] = ReadBitNormal();
else
fa[1] = 0.0f;
// The first two imply the third (but not its sign)
int znegative = ReadOneBit();
float fafafbfb = fa[0] * fa[0] + fa[1] * fa[1];
if (fafafbfb < 1.0f)
fa[2] = sqrt( 1.0f - fafafbfb );
else
fa[2] = 0.0f;
if (znegative)
fa[2] = -fa[2];
}
void CBitRead::ReadBitAngles( QAngle& fa )
{
Vector tmp;
ReadBitVec3Coord( tmp );
fa.Init( tmp.x, tmp.y, tmp.z );
}
#endif

906
tier1/pathmatch.cpp Normal file
View File

@ -0,0 +1,906 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility to interrogate and modify the data in the OSX IPC Server
//
// $NoKeywords: $
//=============================================================================
// README:README
//
// This file implements the --wrap for ld on linux that lets file i/o api's
// behave as if it were running on a case insensitive file system. Unfortunately,
// this is needed by both steam2 and steam3. It was decided to check the source
// into both locations, otherwise someone would find the .o and have no idea
// where to go for the source if it was in the 'other' tree. Also, because this
// needs to be linked into every elf binary, the .o is checked in for Steam3 so that it is
// always available. In Steam2 it sits with the PosixWin32.cpp implementation and gets
// compiled along side of it through the make system. If you are reading this in Steam3,
// you will probably want to actually make your changes in steam2 and do a baseless merge
// to the steam3 copy.
//
// HOWTO: Add a new function. Add the function with _WRAP to the makefiles as noted below.
// Add the implementation to pathmatch.cpp - probably mimicking the existing functions.
// Build steam2 and copy to matching steam3/client. Take the pathmatch.o from steam 2
// and check it in to steam3 (in the location noted below). Full rebuild (re-link really)
// of steam3. Test steam and check in.
//
// If you are looking at updating this file, please update the following as needed:
//
// STEAM2.../Projects/GazelleProto/Client/Engine/obj/RELEASE_NORMAL/libsteam_linux/Common/Misc/pathmatch.o
// This is where steam2 builds the pathmatch.o out to.
//
// STEAM2.../Projects/GazelleProto/Makefile.shlib.base - contains _WRAP references
// STEAM2.../Projects/Common/Misc/pathmatch.cpp - Where the source is checked in, keep in sync with:
// STEAM3.../src/common/pathmatch.cpp - should be identical to previous file, but discoverable in steam3.
// STEAM3.../src/lib/linux32/release/pathmatch.o - steam3 checked in version
// STEAM3.../src/devtools/makefile_base_posix.mak - look for the _WRAP references
#ifdef LINUX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <strings.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mount.h>
#include <fcntl.h>
#include <utime.h>
#include <map>
#include <string>
#include <time.h>
// Enable to do pathmatch caching. Beware: this code isn't threadsafe.
// #define DO_PATHMATCH_CACHE
#ifdef UTF8_PATHMATCH
#define strcasecmp utf8casecmp
#endif
static bool s_bShowDiag;
#define DEBUG_MSG( ... ) if ( s_bShowDiag ) fprintf( stderr, ##__VA_ARGS__ )
#define DEBUG_BREAK() __asm__ __volatile__ ( "int $3" )
#define _COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
#define WRAP( fn, ret, ... ) \
ret __real_##fn(__VA_ARGS__); \
ret __wrap_##fn(__VA_ARGS__)
#define CALL( fn ) __real_##fn
// Needed by pathmatch code
extern "C" int __real_access(const char *pathname, int mode);
extern "C" DIR *__real_opendir(const char *name);
// UTF-8 work from PhysicsFS: http://icculus.org/physfs/
// Even if it wasn't under the zlib license, Ryan wrote all this code originally.
#define UNICODE_BOGUS_CHAR_VALUE 0xFFFFFFFF
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
inline __attribute__ ((always_inline)) static uint32_t utf8codepoint(const char **_str)
{
const char *str = *_str;
uint32_t retval = 0;
uint32_t octet = (uint32_t) ((uint8_t) *str);
uint32_t octet2, octet3, octet4;
if (octet == 0) // null terminator, end of string.
return 0;
else if (octet < 128) // one octet char: 0 to 127
{
(*_str)++; // skip to next possible start of codepoint.
return octet;
}
else if ((octet > 127) && (octet < 192)) // bad (starts with 10xxxxxx).
{
// Apparently each of these is supposed to be flagged as a bogus
// char, instead of just resyncing to the next valid codepoint.
(*_str)++; // skip to next possible start of codepoint.
return UNICODE_BOGUS_CHAR_VALUE;
}
else if (octet < 224) // two octets
{
octet -= (128+64);
octet2 = (uint32_t) ((uint8_t) *(++str));
if ((octet2 & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 2; // skip to next possible start of codepoint.
retval = ((octet << 6) | (octet2 - 128));
if ((retval >= 0x80) && (retval <= 0x7FF))
return retval;
}
else if (octet < 240) // three octets
{
octet -= (128+64+32);
octet2 = (uint32_t) ((uint8_t) *(++str));
if ((octet2 & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet3 = (uint32_t) ((uint8_t) *(++str));
if ((octet3 & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 3; // skip to next possible start of codepoint.
retval = ( ((octet << 12)) | ((octet2-128) << 6) | ((octet3-128)) );
// There are seven "UTF-16 surrogates" that are illegal in UTF-8.
switch (retval)
{
case 0xD800:
case 0xDB7F:
case 0xDB80:
case 0xDBFF:
case 0xDC00:
case 0xDF80:
case 0xDFFF:
return UNICODE_BOGUS_CHAR_VALUE;
}
// 0xFFFE and 0xFFFF are illegal, too, so we check them at the edge.
if ((retval >= 0x800) && (retval <= 0xFFFD))
return retval;
}
else if (octet < 248) // four octets
{
octet -= (128+64+32+16);
octet2 = (uint32_t) ((uint8_t) *(++str));
if ((octet2 & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet3 = (uint32_t) ((uint8_t) *(++str));
if ((octet3 & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet4 = (uint32_t) ((uint8_t) *(++str));
if ((octet4 & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 4; // skip to next possible start of codepoint.
retval = ( ((octet << 18)) | ((octet2 - 128) << 12) |
((octet3 - 128) << 6) | ((octet4 - 128)) );
if ((retval >= 0x10000) && (retval <= 0x10FFFF))
return retval;
}
// Five and six octet sequences became illegal in rfc3629.
// We throw the codepoint away, but parse them to make sure we move
// ahead the right number of bytes and don't overflow the buffer.
else if (octet < 252) // five octets
{
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 5; // skip to next possible start of codepoint.
return UNICODE_BOGUS_CHAR_VALUE;
}
else // six octets
{
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
octet = (uint32_t) ((uint8_t) *(++str));
if ((octet & (128+64)) != 128) // Format isn't 10xxxxxx?
return UNICODE_BOGUS_CHAR_VALUE;
*_str += 6; // skip to next possible start of codepoint.
return UNICODE_BOGUS_CHAR_VALUE;
}
return UNICODE_BOGUS_CHAR_VALUE;
}
typedef struct CaseFoldMapping
{
uint32_t from;
uint32_t to0;
uint32_t to1;
uint32_t to2;
} CaseFoldMapping;
typedef struct CaseFoldHashBucket
{
const uint8_t count;
const CaseFoldMapping *list;
} CaseFoldHashBucket;
#include "pathmatch_casefolding.h"
inline __attribute__ ((always_inline)) static void locate_case_fold_mapping(const uint32_t from, uint32_t *to)
{
const uint8_t hashed = ((from ^ (from >> 8)) & 0xFF);
const CaseFoldHashBucket *bucket = &case_fold_hash[hashed];
const CaseFoldMapping *mapping = bucket->list;
uint32_t i;
for (i = 0; i < bucket->count; i++, mapping++)
{
if (mapping->from == from)
{
to[0] = mapping->to0;
to[1] = mapping->to1;
to[2] = mapping->to2;
return;
}
}
// Not found...there's no remapping for this codepoint.
to[0] = from;
to[1] = 0;
to[2] = 0;
}
inline __attribute__ ((always_inline)) static uint32_t *fold_utf8(const char *str)
{
uint32_t *retval = new uint32_t[(strlen(str) * 3) + 1];
uint32_t *dst = retval;
while (*str)
{
const char ch = *str;
if (ch & 0x80) // high bit set? UTF-8 sequence!
{
uint32_t fold[3];
locate_case_fold_mapping(utf8codepoint(&str), fold);
*(dst++) = fold[0];
if (fold[1])
{
*(dst++) = fold[1];
if (fold[2])
*(dst++) = fold[2];
}
}
else // simple ASCII test.
{
*(dst++) = (uint32_t) (((ch >= 'A') && (ch <= 'Z')) ? ch + 32 : ch);
str++;
}
}
*dst = 0;
return retval;
}
inline __attribute__ ((always_inline)) static int utf8casecmp_loop(const uint32_t *folded1, const uint32_t *folded2)
{
while (true)
{
const uint32_t ch1 = *(folded1++);
const uint32_t ch2 = *(folded2++);
if (ch1 < ch2)
return -1;
else if (ch1 > ch2)
return 1;
else if (ch1 == 0)
return 0; // complete match.
}
}
static int utf8casecmp(const char *str1, const char *str2)
{
uint32_t *folded1 = fold_utf8(str1);
uint32_t *folded2 = fold_utf8(str2);
const int retval = utf8casecmp_loop(folded1, folded2);
delete[] folded1;
delete[] folded2;
return retval;
}
// Simple object to help make sure a DIR* from opendir
// gets closed when it goes out of scope.
class CDirPtr
{
public:
CDirPtr() { m_pDir = NULL; }
CDirPtr( DIR *pDir ) : m_pDir(pDir) {}
~CDirPtr() { Close(); }
void operator=(DIR *pDir) { Close(); m_pDir = pDir; }
operator DIR *() { return m_pDir; }
operator bool() { return m_pDir != NULL; }
private:
void Close() { if ( m_pDir ) closedir( m_pDir ); }
DIR *m_pDir;
};
// Object used to temporarily slice a path into a smaller componentent
// and then repair it when going out of scope. Typically used as an unnamed
// temp object that is a parameter to a function.
class CDirTrimmer
{
public:
CDirTrimmer( char * pPath, size_t nTrimIdx )
{
m_pPath = pPath;
m_idx = nTrimIdx;
m_c = m_pPath[nTrimIdx];
m_pPath[nTrimIdx] = '\0';
}
~CDirTrimmer() { m_pPath[m_idx] = m_c; }
operator const char *() { return m_pPath; }
private:
size_t m_idx;
char *m_pPath;
char m_c;
};
enum PathMod_t
{
kPathUnchanged,
kPathLowered,
kPathChanged,
kPathFailed,
};
static bool Descend( char *pPath, size_t nStartIdx, bool bAllowBasenameMismatch, size_t nLevel = 0 )
{
DEBUG_MSG( "(%zu) Descend: %s, (%s), %s\n", nLevel, pPath, pPath+nStartIdx, bAllowBasenameMismatch ? "true" : "false " );
// We assume up through nStartIdx is valid and matching
size_t nNextSlash = nStartIdx+1;
// path might be a dir
if ( pPath[nNextSlash] == '\0' )
{
return true;
}
bool bIsDir = false; // is the new component a directory for certain?
while ( pPath[nNextSlash] != '\0' && pPath[nNextSlash] != '/' )
{
nNextSlash++;
}
// Modify the pPath string
if ( pPath[nNextSlash] == '/' )
bIsDir = true;
// See if we have an immediate match
if ( __real_access( CDirTrimmer(pPath, nNextSlash), F_OK ) == 0 )
{
if ( !bIsDir )
return true;
bool bRet = Descend( pPath, nNextSlash, bAllowBasenameMismatch, nLevel+1 );
if ( bRet )
return true;
}
// Start enumerating dirents
CDirPtr spDir;
if ( nStartIdx )
{
// we have a path
spDir = __real_opendir( CDirTrimmer( pPath, nStartIdx ) );
nStartIdx++;
}
else
{
// we either start at root or cwd
const char *pRoot = ".";
if ( *pPath == '/' )
{
pRoot = "/";
nStartIdx++;
}
spDir = __real_opendir( pRoot );
}
errno = 0;
struct dirent *pEntry = spDir ? readdir( spDir ) : NULL;
char *pszComponent = pPath + nStartIdx;
size_t cbComponent = nNextSlash - nStartIdx;
while ( pEntry )
{
DEBUG_MSG( "\t(%zu) comparing %s with %s\n", nLevel, pEntry->d_name, (const char *)CDirTrimmer(pszComponent, cbComponent) );
// the candidate must match the target, but not be a case-identical match (we would
// have looked there in the short-circuit code above, so don't look again)
bool bMatches = ( strcasecmp( CDirTrimmer(pszComponent, cbComponent), pEntry->d_name ) == 0 &&
strcmp( CDirTrimmer(pszComponent, cbComponent), pEntry->d_name ) != 0 );
if ( bMatches )
{
char *pSrc = pEntry->d_name;
char *pDst = &pPath[nStartIdx];
// found a match; copy it in.
while ( *pSrc && (*pSrc != '/') )
{
*pDst++ = *pSrc++;
}
if ( !bIsDir )
return true;
if ( Descend( pPath, nNextSlash, bAllowBasenameMismatch, nLevel+1 ) )
return true;
// If descend fails, try more directories
}
pEntry = readdir( spDir );
}
if ( bIsDir )
{
DEBUG_MSG( "(%zu) readdir failed to find '%s' in '%s'\n", nLevel, (const char *)CDirTrimmer(pszComponent, cbComponent), (const char *)CDirTrimmer( pPath, nStartIdx ) );
}
// Sometimes it's ok for the filename portion to not match
// since we might be opening for write. Note that if
// the filename matches case insensitive, that will be
// preferred over preserving the input name
if ( !bIsDir && bAllowBasenameMismatch )
return true;
return false;
}
#ifdef DO_PATHMATCH_CACHE
typedef std::map<std::string, std::pair<std::string, time_t> > resultCache_t;
typedef std::map<std::string, std::pair<std::string, time_t> >::iterator resultCacheItr_t;
static resultCache_t resultCache;
static const int k_cMaxCacheLifetimeSeconds = 2;
#endif // DO_PATHMATCH_CACHE
PathMod_t pathmatch( const char *pszIn, char **ppszOut, bool bAllowBasenameMismatch, char *pszOutBuf, size_t OutBufLen )
{
// Path matching can be very expensive, and the cost is unpredictable because it
// depends on how many files are in directories on a user's machine. Therefore
// it should be disabled whenever possible, and only enabled in environments (such
// as running with loose files such as out of Perforce) where it is needed.
static const char *s_pszPathMatchEnabled = getenv("ENABLE_PATHMATCH");
if ( !s_pszPathMatchEnabled )
return kPathUnchanged;
static const char *s_pszDbgPathMatch = getenv("DBG_PATHMATCH");
s_bShowDiag = ( s_pszDbgPathMatch != NULL );
*ppszOut = NULL;
if ( __real_access( pszIn, F_OK ) == 0 )
return kPathUnchanged;
#ifdef DO_PATHMATCH_CACHE
resultCacheItr_t cachedResult = resultCache.find( pszIn );
if ( cachedResult != resultCache.end() )
{
unsigned int age = time( NULL ) - cachedResult->second.second;
const char *pszResult = cachedResult->second.first.c_str();
if ( pszResult[0] != '\0' || age <= k_cMaxCacheLifetimeSeconds )
{
if ( pszResult[0] != '\0' )
{
*ppszOut = strdup( pszResult );
DEBUG_MSG( "Cached '%s' -> '%s'\n", pszIn, *ppszOut );
return kPathChanged;
}
else
{
DEBUG_MSG( "Cached '%s' -> kPathFailed\n", pszIn );
return kPathFailed;
}
}
else if ( age <= k_cMaxCacheLifetimeSeconds )
{
DEBUG_MSG( "Rechecking '%s' - cache is %u seconds old\n", pszIn, age );
}
}
#endif // DO_PATHMATCH_CACHE
char *pPath;
if( strlen( pszIn ) >= OutBufLen )
{
pPath = strdup( pszIn );
}
else
{
strncpy( pszOutBuf, pszIn, OutBufLen );
pPath = pszOutBuf;
}
if ( pPath )
{
// I believe this code is broken. I'm guessing someone wanted to avoid lowercasing
// the path before the steam directory - but it's actually skipping lowercasing
// whenever steam is found anywhere - including the filename. For example,
// /home/mikesart/valvesrc/console/l4d2/game/left4dead2_dlc1/particles/steam_fx.pcf
// winds up only having the "steam_fx.pcf" portion lowercased.
#ifdef NEVER
// optimization, if the path contained steam somewhere
// assume the path up through the component with 'steam' in
// is valid (because we almost certainly obtained it
// progamatically
char *p = strcasestr( pPath, "steam" );
if ( p )
{
while ( p > pPath )
{
if ( p[-1] == '/' )
break;
p--;
}
if ( ( p == pPath+1 ) && ( *pPath != '/' ) )
p = pPath;
}
else
{
p = pPath;
}
#else
char *p = pPath;
#endif
// Try the lower casing of the remaining path
char *pBasename = p;
while ( *p )
{
if ( *p == '/' )
pBasename = p+1;
*p = tolower(*p);
p++;
}
if ( __real_access( pPath, F_OK ) == 0 )
{
*ppszOut = pPath;
DEBUG_MSG( "Lowered '%s' -> '%s'\n", pszIn, pPath );
return kPathLowered;
}
// path didn't match lowered successfully, restore the basename
// if bAllowBasenameMismatch was true
if ( bAllowBasenameMismatch )
{
const char *pSrc = pszIn + (pBasename - pPath);
while ( *pBasename )
{
*pBasename++ = *pSrc++;
}
}
if ( s_pszDbgPathMatch && strcasestr( s_pszDbgPathMatch, pszIn ) )
{
DEBUG_MSG( "Breaking '%s' in '%s'\n", pszIn, s_pszDbgPathMatch );
DEBUG_BREAK();
}
bool bSuccess = Descend( pPath, 0, bAllowBasenameMismatch );
if ( bSuccess )
{
*ppszOut = pPath;
DEBUG_MSG( "Matched '%s' -> '%s'\n", pszIn, pPath );
}
else
{
DEBUG_MSG( "Unmatched %s\n", pszIn );
}
#ifndef DO_PATHMATCH_CACHE
return bSuccess ? kPathChanged : kPathFailed;
#else
time_t now = time(NULL);
if ( bSuccess )
{
resultCache[ pszIn ] = std::make_pair( *ppszOut, now );
return kPathChanged;
}
else
{
resultCache[ pszIn ] = std::make_pair( "", now );
return kPathFailed;
}
#endif
}
return kPathFailed;
}
// Wrapper object that manages the 'typical' usage cases of pathmatch()
class CWrap
{
public:
CWrap( const char *pSuppliedPath, bool bAllowMismatchedBasename )
: m_pSuppliedPath( pSuppliedPath ), m_pBestMatch( NULL )
{
m_eResult = pathmatch( m_pSuppliedPath, &m_pBestMatch, bAllowMismatchedBasename, m_BestMatchBuf, sizeof( m_BestMatchBuf ) );
if ( m_pBestMatch == NULL )
{
m_pBestMatch = const_cast<char*>( m_pSuppliedPath );
}
}
~CWrap()
{
if ( ( m_pBestMatch != m_pSuppliedPath ) && ( m_pBestMatch != m_BestMatchBuf ) )
free( m_pBestMatch );
}
const char *GetBest() const { return m_pBestMatch; }
const char *GetOriginal() const { return m_pSuppliedPath; }
PathMod_t GetMatchResult() const { return m_eResult; }
operator const char*() { return GetBest(); }
private:
const char *m_pSuppliedPath;
char *m_pBestMatch;
char m_BestMatchBuf[ 512 ];
PathMod_t m_eResult;
};
#ifdef MAIN_TEST
void usage()
{
puts("pathmatch [options] <path>");
//puts("options:");
//puts("\t");
exit(-1);
}
void test( const char *pszFile, bool bAllowBasenameMismatch )
{
char *pNewPath;
char NewPathBuf[ 512 ];
PathMod_t nStat = pathmatch( pszFile, &pNewPath, bAllowBasenameMismatch, NewPathBuf, sizeof( NewPathBuf ) );
printf("AllowMismatchedBasename: %s\n", bAllowBasenameMismatch ? "true" : "false" );
printf("Path Was: ");
switch ( nStat )
{
case kPathUnchanged:
puts("kPathUnchanged");
break;
case kPathLowered:
puts("kPathLowered");
break;
case kPathChanged:
puts("kPathChanged");
break;
case kPathFailed:
puts("kPathFailed");
break;
}
printf(" Path In: %s\n", pszFile );
printf("Path Out: %s\n", nStat == kPathUnchanged ? pszFile : pNewPath );
if ( pNewPath )
free( pNewPath );
}
int
main(int argc, char **argv)
{
if ( argc <= 1 || argc > 2 )
usage();
test( argv[1], false );
test( argv[1], true );
return 0;
}
#endif
extern "C" {
WRAP(freopen, FILE *, const char *path, const char *mode, FILE *stream)
{
// if mode does not have w, a, or +, it's open for read.
bool bAllowBasenameMismatch = strpbrk( mode, "wa+" ) != NULL;
CWrap mpath( path, bAllowBasenameMismatch );
return CALL(freopen)( mpath, mode, stream );
}
WRAP(fopen, FILE *, const char *path, const char *mode)
{
// if mode does not have w, a, or +, it's open for read.
bool bAllowBasenameMismatch = strpbrk( mode, "wa+" ) != NULL;
CWrap mpath( path, bAllowBasenameMismatch );
return CALL(fopen)( mpath, mode );
}
WRAP(fopen64, FILE *, const char *path, const char *mode)
{
// if mode does not have w, a, or +, it's open for read.
bool bAllowBasenameMismatch = strpbrk( mode, "wa+" ) != NULL;
CWrap mpath( path, bAllowBasenameMismatch );
return CALL(fopen64)( mpath, mode );
}
WRAP(open, int, const char *pathname, int flags, mode_t mode)
{
bool bAllowBasenameMismatch = ((flags & (O_WRONLY | O_RDWR)) != 0);
CWrap mpath( pathname, bAllowBasenameMismatch );
return CALL(open)( mpath, flags, mode );
}
WRAP(open64, int, const char *pathname, int flags, mode_t mode)
{
bool bAllowBasenameMismatch = ((flags & (O_WRONLY | O_RDWR)) != 0);
CWrap mpath( pathname, bAllowBasenameMismatch );
return CALL(open64)( mpath, flags, mode );
}
int __wrap_creat(const char *pathname, mode_t mode)
{
return __wrap_open( pathname, O_CREAT|O_WRONLY|O_TRUNC, mode );
}
int __wrap_access(const char *pathname, int mode)
{
return __real_access( CWrap( pathname, false ), mode );
}
WRAP(stat, int, const char *path, struct stat *buf)
{
return CALL(stat)( CWrap( path, false ), buf );
}
WRAP(lstat, int, const char *path, struct stat *buf)
{
return CALL(lstat)( CWrap( path, false ), buf );
}
WRAP(scandir, int, const char *dirp, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
{
return CALL(scandir)( CWrap( dirp, false ), namelist, filter, compar );
}
WRAP(opendir, DIR*, const char *name)
{
return CALL(opendir)( CWrap( name, false ) );
}
WRAP(__xstat, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__xstat)( __ver, CWrap( __filename, false), __stat_buf );
}
WRAP(__lxstat, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__lxstat)( __ver, CWrap( __filename, false), __stat_buf );
}
WRAP(__xstat64, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__xstat64)( __ver, CWrap( __filename, false), __stat_buf );
}
WRAP(__lxstat64, int, int __ver, __const char *__filename, struct stat *__stat_buf)
{
return CALL(__lxstat64)( __ver, CWrap( __filename, false), __stat_buf );
}
WRAP(chmod, int, const char *path, mode_t mode)
{
return CALL(chmod)( CWrap( path, false), mode );
}
WRAP(chown, int, const char *path, uid_t owner, gid_t group)
{
return CALL(chown)( CWrap( path, false), owner, group );
}
WRAP(lchown, int, const char *path, uid_t owner, gid_t group)
{
return CALL(lchown)( CWrap( path, false), owner, group );
}
WRAP(symlink, int, const char *oldpath, const char *newpath)
{
return CALL(symlink)( CWrap( oldpath, false), CWrap( newpath, true ) );
}
WRAP(link, int, const char *oldpath, const char *newpath)
{
return CALL(link)( CWrap( oldpath, false), CWrap( newpath, true ) );
}
WRAP(mknod, int, const char *pathname, mode_t mode, dev_t dev)
{
return CALL(mknod)( CWrap( pathname, true), mode, dev );
}
WRAP(mount, int, const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data)
{
return CALL(mount)( CWrap( source, false ), CWrap( target, false ), filesystemtype, mountflags, data );
}
WRAP(unlink, int, const char *pathname)
{
return CALL(unlink)( CWrap( pathname, false ) );
}
WRAP(mkfifo, int, const char *pathname, mode_t mode)
{
return CALL(mkfifo)( CWrap( pathname, true ), mode );
}
WRAP(rename, int, const char *oldpath, const char *newpath)
{
return CALL(rename)( CWrap( oldpath, false), CWrap( newpath, true ) );
}
WRAP(utime, int, const char *filename, const struct utimbuf *times)
{
return CALL(utime)( CWrap( filename, false), times );
}
WRAP(utimes, int, const char *filename, const struct timeval times[2])
{
return CALL(utimes)( CWrap( filename, false), times );
}
WRAP(realpath, char *, const char *path, char *resolved_path)
{
return CALL(realpath)( CWrap( path, true ), resolved_path );
}
WRAP(mkdir, int, const char *pathname, mode_t mode)
{
return CALL(mkdir)( CWrap( pathname, true ), mode );
}
WRAP(rmdir, char *, const char *pathname)
{
return CALL(rmdir)( CWrap( pathname, false ) );
}
};
#endif

File diff suppressed because it is too large Load Diff

274
tier1/processor_detect.cpp Normal file
View File

@ -0,0 +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

View File

@ -0,0 +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;
}

112
tier1/qsort_s.cpp Normal file
View File

@ -0,0 +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 */

41
tier1/rangecheckedvar.cpp Normal file
View File

@ -0,0 +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;
}
}

93
tier1/reliabletimer.cpp Normal file
View File

@ -0,0 +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
}

150
tier1/snappy-internal.h Normal file
View File

@ -0,0 +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_

View File

@ -0,0 +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_;
}
}

View File

@ -0,0 +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

View File

@ -0,0 +1,487 @@
// 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() { }
~LogMessageCrash() {
fprintf( stderr, "\n" );
// cerr << endl;
abort();
}
};
// 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_

1025
tier1/snappy.cpp Normal file

File diff suppressed because it is too large Load Diff

141
tier1/sparsematrix.cpp Normal file
View File

@ -0,0 +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 );
}
}

91
tier1/splitstring.cpp Normal file
View File

@ -0,0 +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();
}

334
tier1/stringpool.cpp Normal file
View File

@ -0,0 +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

2751
tier1/strtools.cpp Normal file

File diff suppressed because it is too large Load Diff

287
tier1/tier1-2010.vcxproj Normal file
View File

@ -0,0 +1,287 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>tier1</ProjectName>
<ProjectGuid>{EC1C516D-E1D9-BC0A-F79D-E91E954ED8EC}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<TargetName>tier1</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<TargetName>tier1</TargetName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\lib\public\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\win32\</IntDir>
<ExecutablePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\devtools\vstools;$(ExecutablePath);$(Path)</ExecutablePath>
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</PreBuildEventUseInBuild>
<PreLinkEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</PreLinkEventUseInBuild>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</PostBuildEventUseInBuild>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\lib\public\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\win32\</IntDir>
<ExecutablePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\devtools\vstools;$(ExecutablePath);$(Path)</ExecutablePath>
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</PreBuildEventUseInBuild>
<PreLinkEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</PreLinkEventUseInBuild>
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</PostBuildEventUseInBuild>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent>
</PreBuildEvent>
<ClCompile>
<AdditionalOptions> /MP</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\common;..\public;..\public\tier0;..\public\tier1</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_HAS_ITERATOR_DEBUGGING=0;WIN32;_WIN32;_DEBUG;DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;COMPILER_MSVC32;LIBNAME=tier1;RAD_TELEMETRY_DISABLED;BINK_VIDEO;AVI_VIDEO;WMV_VIDEO;TIER1_STATIC_LIB;VPCGAMECAPS=VALVE;PROJECTDIR=D:\dev\games\rel\hl2\src\tier1;_DLL_EXT=.dll;VPCGAME=valve</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<ExpandAttributedSource>false</ExpandAttributedSource>
<AssemblerOutput>NoListing</AssemblerOutput>
<AssemblerListingLocation>$(IntDir)/</AssemblerListingLocation>
<ObjectFileName>$(IntDir)/</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)/</ProgramDataBaseFileName>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<BrowseInformation>false</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsCpp</CompileAs>
<BrowseInformationFile>$(IntDir)/</BrowseInformationFile>
<ErrorReporting>Prompt</ErrorReporting>
</ClCompile>
<PreLinkEvent>
</PreLinkEvent>
<Lib>
<UseUnicodeResponseFiles>false</UseUnicodeResponseFiles>
<AdditionalDependencies>;Rpcrt4.lib</AdditionalDependencies>
<OutputFile>..\lib\public\tier1.lib</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkLibraryDependencies>false</LinkLibraryDependencies>
<AdditionalOptions> /ignore:4221</AdditionalOptions>
</Lib>
<Xdcmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Xdcmake>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)/tier1.bsc</OutputFile>
</Bscmake>
<PostBuildEvent>
</PostBuildEvent>
<CustomBuildStep>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<PreBuildEvent>
</PreBuildEvent>
<ClCompile>
<AdditionalOptions> /MP /d2Zi+</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\common;..\public;..\public\tier0;..\public\tier1</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;COMPILER_MSVC32;LIBNAME=tier1;RAD_TELEMETRY_DISABLED;BINK_VIDEO;AVI_VIDEO;WMV_VIDEO;TIER1_STATIC_LIB;VPCGAMECAPS=VALVE;PROJECTDIR=D:\dev\games\rel\hl2\src\tier1;_DLL_EXT=.dll;VPCGAME=valve</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<ExpandAttributedSource>false</ExpandAttributedSource>
<AssemblerOutput>NoListing</AssemblerOutput>
<AssemblerListingLocation>$(IntDir)/</AssemblerListingLocation>
<ObjectFileName>$(IntDir)/</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)/</ProgramDataBaseFileName>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<BrowseInformation>false</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>OldStyle</DebugInformationFormat>
<CompileAs>CompileAsCpp</CompileAs>
<BrowseInformationFile>$(IntDir)/</BrowseInformationFile>
<ErrorReporting>Prompt</ErrorReporting>
</ClCompile>
<PreLinkEvent>
</PreLinkEvent>
<Lib>
<UseUnicodeResponseFiles>false</UseUnicodeResponseFiles>
<AdditionalDependencies>;Rpcrt4.lib</AdditionalDependencies>
<OutputFile>..\lib\public\tier1.lib</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkLibraryDependencies>false</LinkLibraryDependencies>
<AdditionalOptions> /ignore:4221</AdditionalOptions>
</Lib>
<Xdcmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Xdcmake>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>$(OutDir)/tier1.bsc</OutputFile>
</Bscmake>
<PostBuildEvent>
</PostBuildEvent>
<CustomBuildStep>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\public\tier1\bitbuf.h" />
<ClInclude Include="..\public\tier1\byteswap.h" />
<ClInclude Include="..\public\tier1\callqueue.h" />
<ClInclude Include="..\public\tier1\characterset.h" />
<ClInclude Include="..\public\tier1\checksum_crc.h" />
<ClInclude Include="..\public\tier1\checksum_md5.h" />
<ClInclude Include="..\public\tier1\checksum_sha1.h" />
<ClInclude Include="..\public\tier1\CommandBuffer.h" />
<ClInclude Include="..\public\tier1\convar.h" />
<ClInclude Include="..\public\tier1\datamanager.h" />
<ClInclude Include="..\public\datamap.h" />
<ClInclude Include="..\public\tier1\delegates.h" />
<ClInclude Include="..\public\tier1\diff.h" />
<ClInclude Include="..\public\tier1\fmtstr.h" />
<ClInclude Include="..\public\tier1\functors.h" />
<ClInclude Include="..\public\tier1\generichash.h" />
<ClInclude Include="..\public\tier1\iconvar.h" />
<ClInclude Include="..\public\tier1\ilocalize.h" />
<ClInclude Include="..\public\tier1\interface.h" />
<ClInclude Include="..\public\tier1\KeyValues.h" />
<ClInclude Include="..\public\tier1\kvpacker.h" />
<ClInclude Include="..\public\tier1\lzmaDecoder.h" />
<ClInclude Include="..\public\tier1\lzss.h" />
<ClInclude Include="..\public\tier1\mempool.h" />
<ClInclude Include="..\public\tier1\memstack.h" />
<ClInclude Include="..\public\tier1\netadr.h" />
<ClInclude Include="..\public\tier1\processor_detect.h" />
<ClInclude Include="..\public\tier1\rangecheckedvar.h" />
<ClInclude Include="..\public\tier1\refcount.h" />
<ClInclude Include="..\public\tier1\smartptr.h" />
<ClInclude Include="..\public\tier1\snappy-sinksource.h" />
<ClInclude Include="..\public\tier1\snappy.h" />
<ClInclude Include="..\public\tier1\stringpool.h" />
<ClInclude Include="..\public\tier1\strtools.h" />
<ClInclude Include="..\public\tier1\tier1.h" />
<ClInclude Include="..\public\tier1\tokenreader.h" />
<ClInclude Include="..\public\tier1\uniqueid.h" />
<ClInclude Include="..\public\tier1\utlbidirectionalset.h" />
<ClInclude Include="..\public\tier1\utlblockmemory.h" />
<ClInclude Include="..\public\tier1\utlbuffer.h" />
<ClInclude Include="..\public\tier1\utlbufferutil.h" />
<ClInclude Include="..\public\tier1\utlcommon.h" />
<ClInclude Include="..\public\tier1\utldict.h" />
<ClInclude Include="..\public\tier1\utlenvelope.h" />
<ClInclude Include="..\public\tier1\utlfixedmemory.h" />
<ClInclude Include="..\public\tier1\utlhandletable.h" />
<ClInclude Include="..\public\tier1\utlhash.h" />
<ClInclude Include="..\public\tier1\utlhashtable.h" />
<ClInclude Include="..\public\tier1\utllinkedlist.h" />
<ClInclude Include="..\public\tier1\utlmap.h" />
<ClInclude Include="..\public\tier1\utlmemory.h" />
<ClInclude Include="..\public\tier1\utlmultilist.h" />
<ClInclude Include="..\public\tier1\utlpriorityqueue.h" />
<ClInclude Include="..\public\tier1\utlqueue.h" />
<ClInclude Include="..\public\tier1\utlrbtree.h" />
<ClInclude Include="..\public\tier1\UtlSortVector.h" />
<ClInclude Include="..\public\tier1\utlstack.h" />
<ClInclude Include="..\public\tier1\utlstring.h" />
<ClInclude Include="..\public\tier1\UtlStringMap.h" />
<ClInclude Include="..\public\tier1\utlsymbol.h" />
<ClInclude Include="..\public\tier1\utlsymbollarge.h" />
<ClInclude Include="..\public\tier1\utlvector.h" />
<ClInclude Include="..\common\xbox\xboxstubs.h" />
<ClInclude Include="snappy-internal.h" />
<ClInclude Include="snappy-stubs-internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="bitbuf.cpp" />
<ClCompile Include="byteswap.cpp" />
<ClCompile Include="characterset.cpp" />
<ClCompile Include="checksum_crc.cpp" />
<ClCompile Include="checksum_md5.cpp" />
<ClCompile Include="checksum_sha1.cpp" />
<ClCompile Include="commandbuffer.cpp" />
<ClCompile Include="convar.cpp" />
<ClCompile Include="datamanager.cpp" />
<ClCompile Include="diff.cpp" />
<ClCompile Include="generichash.cpp" />
<ClCompile Include="ilocalize.cpp" />
<ClCompile Include="interface.cpp" />
<ClCompile Include="KeyValues.cpp" />
<ClCompile Include="kvpacker.cpp" />
<ClCompile Include="mempool.cpp" />
<ClCompile Include="memstack.cpp" />
<ClCompile Include="NetAdr.cpp" />
<ClCompile Include="newbitbuf.cpp" />
<ClCompile Include="processor_detect.cpp">
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Sync</ExceptionHandling>
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Sync</ExceptionHandling>
</ClCompile>
<ClCompile Include="rangecheckedvar.cpp" />
<ClCompile Include="reliabletimer.cpp" />
<ClCompile Include="snappy-sinksource.cpp" />
<ClCompile Include="snappy-stubs-internal.cpp" />
<ClCompile Include="snappy.cpp" />
<ClCompile Include="sparsematrix.cpp" />
<ClCompile Include="splitstring.cpp" />
<ClCompile Include="stringpool.cpp" />
<ClCompile Include="strtools.cpp" />
<ClCompile Include="tier1.cpp" />
<ClCompile Include="tokenreader.cpp" />
<ClCompile Include="uniqueid.cpp" />
<ClCompile Include="utlbuffer.cpp" />
<ClCompile Include="utlbufferutil.cpp" />
<ClCompile Include="utlstring.cpp" />
<ClCompile Include="utlsymbol.cpp" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,329 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{1680C80B-FF1E-EA4D-9817-CC12254F2E40}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Internal Header Files">
<UniqueIdentifier>{82D97A15-B2F0-1D81-D6D4-97637C1216E9}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{BA03E055-4FA2-FCE3-8A1C-D348547D379C}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\public\tier1\bitbuf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\byteswap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\callqueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\characterset.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\checksum_crc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\checksum_md5.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\checksum_sha1.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\CommandBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\convar.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\datamanager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\datamap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\delegates.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\diff.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\fmtstr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\functors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\generichash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\iconvar.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\ilocalize.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\interface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\KeyValues.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\kvpacker.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\lzmaDecoder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\lzss.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\mempool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\memstack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\netadr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\processor_detect.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\rangecheckedvar.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\refcount.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\smartptr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\snappy-sinksource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\snappy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\stringpool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\strtools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\tier1.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\tokenreader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\uniqueid.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlbidirectionalset.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlblockmemory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlbuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlbufferutil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlcommon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utldict.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlenvelope.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlfixedmemory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlhandletable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlhash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlhashtable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utllinkedlist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlmap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlmemory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlmultilist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlpriorityqueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlqueue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlrbtree.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\UtlSortVector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlstack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlstring.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\UtlStringMap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlsymbol.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlsymbollarge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\public\tier1\utlvector.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\common\xbox\xboxstubs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="snappy-internal.h">
<Filter>Header Files\Internal Header Files</Filter>
</ClInclude>
<ClInclude Include="snappy-stubs-internal.h">
<Filter>Header Files\Internal Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="bitbuf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="byteswap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="characterset.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="checksum_crc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="checksum_md5.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="checksum_sha1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="commandbuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="convar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="datamanager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="diff.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="generichash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ilocalize.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="interface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="KeyValues.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="kvpacker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mempool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="memstack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NetAdr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="newbitbuf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="processor_detect.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="rangecheckedvar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="reliabletimer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="snappy-sinksource.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="snappy-stubs-internal.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="snappy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sparsematrix.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="splitstring.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stringpool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="strtools.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tier1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tokenreader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="uniqueid.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utlbuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utlbufferutil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utlstring.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utlsymbol.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
</ItemGroup>
</Project>

63
tier1/tier1.cpp Normal file
View File

@ -0,0 +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;
}

408
tier1/tier1_linux32.mak Normal file
View File

@ -0,0 +1,408 @@
NAME=tier1
SRCROOT=..
TARGET_PLATFORM=linux32
TARGET_PLATFORM_EXT=
USE_VALVE_BINDIR=0
PWD := $(shell pwd)
# If no configuration is specified, "release" will be used.
ifeq "$(CFG)" ""
CFG = release
endif
GCC_ExtraCompilerFlags= -U_FORTIFY_SOURCE
GCC_ExtraLinkerFlags =
SymbolVisibility = hidden
OptimizerLevel = -gdwarf-2 -g $(OptimizerLevel_CompilerSpecific)
SystemLibraries =
DLL_EXT = .so
SYM_EXT = .dbg
FORCEINCLUDES=
ifeq "$(CFG)" "debug"
DEFINES += -DDEBUG -D_DEBUG -DPOSIX -DGNUC -DLINUX -D_LINUX -DLIBNAME=tier1 -DRAD_TELEMETRY_DISABLED -DBINK_VIDEO -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -DUSE_SDL -DTIER1_STATIC_LIB -D_EXTERNAL_DLL_EXT=.so -DVPCGAMECAPS=VALVE -DPROJECTDIR=/home/VALVE/joe/p4clients/linuxsdk/hl2/src/tier1 -D_DLL_EXT=.so -DVPCGAME=valve -D_LINUX=1 -D_POSIX=1 -DLINUX=1 -DPOSIX=1
else
DEFINES += -DNDEBUG -DPOSIX -DGNUC -DLINUX -D_LINUX -DLIBNAME=tier1 -DRAD_TELEMETRY_DISABLED -DBINK_VIDEO -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -DUSE_SDL -DTIER1_STATIC_LIB -D_EXTERNAL_DLL_EXT=.so -DVPCGAMECAPS=VALVE -DPROJECTDIR=/home/VALVE/joe/p4clients/linuxsdk/hl2/src/tier1 -D_DLL_EXT=.so -DVPCGAME=valve -D_LINUX=1 -D_POSIX=1 -DLINUX=1 -DPOSIX=1
endif
INCLUDEDIRS += ../common ../public ../public/tier0 ../public/tier1 ../thirdparty/SDL2
CONFTYPE = lib
OUTPUTFILE=../lib/public/linux32/tier1.a
THIS_MAKEFILE = $(PWD)/tier1_linux32.mak
MAKEFILE_BASE = $(SRCROOT)/devtools/makefile_base_posix.mak
POSTBUILDCOMMAND = true
CPPFILES= \
bitbuf.cpp \
byteswap.cpp \
characterset.cpp \
checksum_crc.cpp \
checksum_md5.cpp \
checksum_sha1.cpp \
commandbuffer.cpp \
convar.cpp \
datamanager.cpp \
diff.cpp \
generichash.cpp \
ilocalize.cpp \
interface.cpp \
KeyValues.cpp \
kvpacker.cpp \
mempool.cpp \
memstack.cpp \
NetAdr.cpp \
newbitbuf.cpp \
pathmatch.cpp \
processor_detect_linux.cpp \
qsort_s.cpp \
rangecheckedvar.cpp \
reliabletimer.cpp \
snappy-sinksource.cpp \
snappy-stubs-internal.cpp \
snappy.cpp \
sparsematrix.cpp \
splitstring.cpp \
stringpool.cpp \
strtools.cpp \
tier1.cpp \
tokenreader.cpp \
uniqueid.cpp \
utlbuffer.cpp \
utlbufferutil.cpp \
utlstring.cpp \
utlsymbol.cpp \
LIBFILES = \
LIBFILENAMES = \
# Include the base makefile now.
include $(SRCROOT)/devtools/makefile_base_posix.mak
OTHER_DEPENDENCIES = \
$(OBJ_DIR)/_other_deps.P : $(OTHER_DEPENDENCIES)
$(GEN_OTHER_DEPS)
-include $(OBJ_DIR)/_other_deps.P
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/bitbuf.P
endif
$(OBJ_DIR)/bitbuf.o : $(PWD)/bitbuf.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/byteswap.P
endif
$(OBJ_DIR)/byteswap.o : $(PWD)/byteswap.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/characterset.P
endif
$(OBJ_DIR)/characterset.o : $(PWD)/characterset.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/checksum_crc.P
endif
$(OBJ_DIR)/checksum_crc.o : $(PWD)/checksum_crc.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/checksum_md5.P
endif
$(OBJ_DIR)/checksum_md5.o : $(PWD)/checksum_md5.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/checksum_sha1.P
endif
$(OBJ_DIR)/checksum_sha1.o : $(PWD)/checksum_sha1.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/commandbuffer.P
endif
$(OBJ_DIR)/commandbuffer.o : $(PWD)/commandbuffer.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/convar.P
endif
$(OBJ_DIR)/convar.o : $(PWD)/convar.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/datamanager.P
endif
$(OBJ_DIR)/datamanager.o : $(PWD)/datamanager.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/diff.P
endif
$(OBJ_DIR)/diff.o : $(PWD)/diff.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/generichash.P
endif
$(OBJ_DIR)/generichash.o : $(PWD)/generichash.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/ilocalize.P
endif
$(OBJ_DIR)/ilocalize.o : $(PWD)/ilocalize.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/interface.P
endif
$(OBJ_DIR)/interface.o : $(PWD)/interface.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/KeyValues.P
endif
$(OBJ_DIR)/KeyValues.o : $(PWD)/KeyValues.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/kvpacker.P
endif
$(OBJ_DIR)/kvpacker.o : $(PWD)/kvpacker.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/mempool.P
endif
$(OBJ_DIR)/mempool.o : $(PWD)/mempool.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/memstack.P
endif
$(OBJ_DIR)/memstack.o : $(PWD)/memstack.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/NetAdr.P
endif
$(OBJ_DIR)/NetAdr.o : $(PWD)/NetAdr.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/newbitbuf.P
endif
$(OBJ_DIR)/newbitbuf.o : $(PWD)/newbitbuf.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/pathmatch.P
endif
$(OBJ_DIR)/pathmatch.o : $(PWD)/pathmatch.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/processor_detect_linux.P
endif
$(OBJ_DIR)/processor_detect_linux.o : $(PWD)/processor_detect_linux.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/qsort_s.P
endif
$(OBJ_DIR)/qsort_s.o : $(PWD)/qsort_s.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/rangecheckedvar.P
endif
$(OBJ_DIR)/rangecheckedvar.o : $(PWD)/rangecheckedvar.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/reliabletimer.P
endif
$(OBJ_DIR)/reliabletimer.o : $(PWD)/reliabletimer.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/snappy-sinksource.P
endif
$(OBJ_DIR)/snappy-sinksource.o : $(PWD)/snappy-sinksource.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/snappy-stubs-internal.P
endif
$(OBJ_DIR)/snappy-stubs-internal.o : $(PWD)/snappy-stubs-internal.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/snappy.P
endif
$(OBJ_DIR)/snappy.o : $(PWD)/snappy.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/sparsematrix.P
endif
$(OBJ_DIR)/sparsematrix.o : $(PWD)/sparsematrix.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/splitstring.P
endif
$(OBJ_DIR)/splitstring.o : $(PWD)/splitstring.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/stringpool.P
endif
$(OBJ_DIR)/stringpool.o : $(PWD)/stringpool.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/strtools.P
endif
$(OBJ_DIR)/strtools.o : $(PWD)/strtools.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/tier1.P
endif
$(OBJ_DIR)/tier1.o : $(PWD)/tier1.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/tokenreader.P
endif
$(OBJ_DIR)/tokenreader.o : $(PWD)/tokenreader.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/uniqueid.P
endif
$(OBJ_DIR)/uniqueid.o : $(PWD)/uniqueid.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlbuffer.P
endif
$(OBJ_DIR)/utlbuffer.o : $(PWD)/utlbuffer.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlbufferutil.P
endif
$(OBJ_DIR)/utlbufferutil.o : $(PWD)/utlbufferutil.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlstring.P
endif
$(OBJ_DIR)/utlstring.o : $(PWD)/utlstring.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlsymbol.P
endif
$(OBJ_DIR)/utlsymbol.o : $(PWD)/utlsymbol.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
# Uncomment this, and set FILENAME to file you want built without optimizations enabled.
# $(OBJ_DIR)/FILENAME.o : CFLAGS := $(subst -O2,-O0,$(CFLAGS))
# Uncomment this to disable optimizations for the entire project.
# $(OBJ_DIR)/%.o : CFLAGS := $(subst -O2,-O0,$(CFLAGS))

390
tier1/tier1_osx32.mak Normal file
View File

@ -0,0 +1,390 @@
NAME=tier1
SRCROOT=..
TARGET_PLATFORM=osx32
TARGET_PLATFORM_EXT=
USE_VALVE_BINDIR=0
PWD := $(shell pwd)
# If no configuration is specified, "release" will be used.
ifeq "$(CFG)" ""
CFG = release
endif
GCC_ExtraCompilerFlags=
GCC_ExtraLinkerFlags =
SymbolVisibility = hidden
OptimizerLevel = -gdwarf-2 -g $(OptimizerLevel_CompilerSpecific)
SystemLibraries =
DLL_EXT = .dylib
SYM_EXT = .dSYM
FORCEINCLUDES=
ifeq "$(CFG)" "debug"
DEFINES += -DDEBUG -D_DEBUG -DGNUC -DPOSIX -D_OSX -DOSX -D_DARWIN_UNLIMITED_SELECT -DFD_SETSIZE=10240 -DQUICKTIME_VIDEO -DFORCE_QUICKTIME -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -DTIER1_STATIC_LIB -DVPCGAMECAPS=VALVE -DPROJECTDIR=/Users/joe/p4/ValveGames/rel/hl2/src/tier1 -D_DLL_EXT=.dylib -DVPCGAME=valve -D_POSIX=1
else
DEFINES += -DNDEBUG -DGNUC -DPOSIX -D_OSX -DOSX -D_DARWIN_UNLIMITED_SELECT -DFD_SETSIZE=10240 -DQUICKTIME_VIDEO -DFORCE_QUICKTIME -DGL_GLEXT_PROTOTYPES -DDX_TO_GL_ABSTRACTION -DTIER1_STATIC_LIB -DVPCGAMECAPS=VALVE -DPROJECTDIR=/Users/joe/p4/ValveGames/rel/hl2/src/tier1 -D_DLL_EXT=.dylib -DVPCGAME=valve -D_POSIX=1
endif
INCLUDEDIRS += ../common ../public ../public/tier0 ../public/tier1
CONFTYPE = lib
OUTPUTFILE=../lib/osx32/tier1.a
THIS_MAKEFILE = $(PWD)/tier1_osx32.mak
MAKEFILE_BASE = $(SRCROOT)/devtools/makefile_base_posix.mak
POSTBUILDCOMMAND = true
CPPFILES= \
bitbuf.cpp \
byteswap.cpp \
characterset.cpp \
checksum_crc.cpp \
checksum_md5.cpp \
checksum_sha1.cpp \
commandbuffer.cpp \
convar.cpp \
datamanager.cpp \
diff.cpp \
generichash.cpp \
ilocalize.cpp \
interface.cpp \
KeyValues.cpp \
kvpacker.cpp \
mempool.cpp \
memstack.cpp \
NetAdr.cpp \
newbitbuf.cpp \
processor_detect_linux.cpp \
rangecheckedvar.cpp \
reliabletimer.cpp \
snappy-sinksource.cpp \
snappy-stubs-internal.cpp \
snappy.cpp \
sparsematrix.cpp \
splitstring.cpp \
stringpool.cpp \
strtools.cpp \
tier1.cpp \
tokenreader.cpp \
uniqueid.cpp \
utlbuffer.cpp \
utlbufferutil.cpp \
utlstring.cpp \
utlsymbol.cpp \
LIBFILES = \
LIBFILENAMES = \
# Include the base makefile now.
include $(SRCROOT)/devtools/makefile_base_posix.mak
OTHER_DEPENDENCIES = \
$(OBJ_DIR)/_other_deps.P : $(OTHER_DEPENDENCIES)
$(GEN_OTHER_DEPS)
-include $(OBJ_DIR)/_other_deps.P
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/bitbuf.P
endif
$(OBJ_DIR)/bitbuf.o : $(PWD)/bitbuf.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/byteswap.P
endif
$(OBJ_DIR)/byteswap.o : $(PWD)/byteswap.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/characterset.P
endif
$(OBJ_DIR)/characterset.o : $(PWD)/characterset.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/checksum_crc.P
endif
$(OBJ_DIR)/checksum_crc.o : $(PWD)/checksum_crc.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/checksum_md5.P
endif
$(OBJ_DIR)/checksum_md5.o : $(PWD)/checksum_md5.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/checksum_sha1.P
endif
$(OBJ_DIR)/checksum_sha1.o : $(PWD)/checksum_sha1.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/commandbuffer.P
endif
$(OBJ_DIR)/commandbuffer.o : $(PWD)/commandbuffer.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/convar.P
endif
$(OBJ_DIR)/convar.o : $(PWD)/convar.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/datamanager.P
endif
$(OBJ_DIR)/datamanager.o : $(PWD)/datamanager.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/diff.P
endif
$(OBJ_DIR)/diff.o : $(PWD)/diff.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/generichash.P
endif
$(OBJ_DIR)/generichash.o : $(PWD)/generichash.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/ilocalize.P
endif
$(OBJ_DIR)/ilocalize.o : $(PWD)/ilocalize.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/interface.P
endif
$(OBJ_DIR)/interface.o : $(PWD)/interface.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/KeyValues.P
endif
$(OBJ_DIR)/KeyValues.o : $(PWD)/KeyValues.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/kvpacker.P
endif
$(OBJ_DIR)/kvpacker.o : $(PWD)/kvpacker.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/mempool.P
endif
$(OBJ_DIR)/mempool.o : $(PWD)/mempool.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/memstack.P
endif
$(OBJ_DIR)/memstack.o : $(PWD)/memstack.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/NetAdr.P
endif
$(OBJ_DIR)/NetAdr.o : $(PWD)/NetAdr.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/newbitbuf.P
endif
$(OBJ_DIR)/newbitbuf.o : $(PWD)/newbitbuf.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/processor_detect_linux.P
endif
$(OBJ_DIR)/processor_detect_linux.o : $(PWD)/processor_detect_linux.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/rangecheckedvar.P
endif
$(OBJ_DIR)/rangecheckedvar.o : $(PWD)/rangecheckedvar.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/reliabletimer.P
endif
$(OBJ_DIR)/reliabletimer.o : $(PWD)/reliabletimer.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/snappy-sinksource.P
endif
$(OBJ_DIR)/snappy-sinksource.o : $(PWD)/snappy-sinksource.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/snappy-stubs-internal.P
endif
$(OBJ_DIR)/snappy-stubs-internal.o : $(PWD)/snappy-stubs-internal.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/snappy.P
endif
$(OBJ_DIR)/snappy.o : $(PWD)/snappy.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/sparsematrix.P
endif
$(OBJ_DIR)/sparsematrix.o : $(PWD)/sparsematrix.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/splitstring.P
endif
$(OBJ_DIR)/splitstring.o : $(PWD)/splitstring.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/stringpool.P
endif
$(OBJ_DIR)/stringpool.o : $(PWD)/stringpool.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/strtools.P
endif
$(OBJ_DIR)/strtools.o : $(PWD)/strtools.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/tier1.P
endif
$(OBJ_DIR)/tier1.o : $(PWD)/tier1.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/tokenreader.P
endif
$(OBJ_DIR)/tokenreader.o : $(PWD)/tokenreader.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/uniqueid.P
endif
$(OBJ_DIR)/uniqueid.o : $(PWD)/uniqueid.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlbuffer.P
endif
$(OBJ_DIR)/utlbuffer.o : $(PWD)/utlbuffer.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlbufferutil.P
endif
$(OBJ_DIR)/utlbufferutil.o : $(PWD)/utlbufferutil.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlstring.P
endif
$(OBJ_DIR)/utlstring.o : $(PWD)/utlstring.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
ifneq (clean, $(findstring clean, $(MAKECMDGOALS)))
-include $(OBJ_DIR)/utlsymbol.P
endif
$(OBJ_DIR)/utlsymbol.o : $(PWD)/utlsymbol.cpp $(THIS_MAKEFILE) $(MAKEFILE_BASE)
$(PRE_COMPILE_FILE)
$(COMPILE_FILE) $(POST_COMPILE_FILE)
# Uncomment this, and set FILENAME to file you want built without optimizations enabled.
# $(OBJ_DIR)/FILENAME.o : CFLAGS := $(subst -O2,-O0,$(CFLAGS))
# Uncomment this to disable optimizations for the entire project.
# $(OBJ_DIR)/%.o : CFLAGS := $(subst -O2,-O0,$(CFLAGS))

480
tier1/tokenreader.cpp Normal file
View File

@ -0,0 +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);
}
}
}

94
tier1/undiff.cpp Normal file
View File

@ -0,0 +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;
}

177
tier1/uniqueid.cpp Normal file
View File

@ -0,0 +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();
}

1796
tier1/utlbuffer.cpp Normal file

File diff suppressed because it is too large Load Diff

559
tier1/utlbufferutil.cpp Normal file
View File

@ -0,0 +1,559 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// $Header: $
// $NoKeywords: $
//
// Serialization buffer
//===========================================================================//
#pragma warning (disable : 4514)
#include "tier1/utlbufferutil.h"
#include "tier1/utlbuffer.h"
#include "mathlib/vector.h"
#include "mathlib/vector2d.h"
#include "mathlib/vector4d.h"
#include "mathlib/vmatrix.h"
#include "Color.h"
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
#include "tier1/utlstring.h"
#include "tier1/strtools.h"
#include "tier1/characterset.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// For serialization, set the delimiter rules
//-----------------------------------------------------------------------------
CUtlCharConversion *s_pConv = NULL;
const char *s_pUtlBufferUtilArrayDelim = NULL;
void SetSerializationDelimiter( CUtlCharConversion *pConv )
{
s_pConv = pConv;
}
void SetSerializationArrayDelimiter( const char *pDelimiter )
{
s_pUtlBufferUtilArrayDelim = pDelimiter;
}
//-----------------------------------------------------------------------------
// Serialize a floating point number in text mode in a readably friendly fashion
//-----------------------------------------------------------------------------
static void SerializeFloat( CUtlBuffer &buf, float f )
{
Assert( buf.IsText() );
// FIXME: Print this in a way that we never lose precision
char pTemp[256];
int nLen = Q_snprintf( pTemp, sizeof(pTemp), "%.10f", f );
while ( nLen > 0 && pTemp[nLen-1] == '0' )
{
--nLen;
pTemp[nLen] = 0;
}
if ( nLen > 0 && pTemp[nLen-1] == '.' )
{
--nLen;
pTemp[nLen] = 0;
}
buf.PutString( pTemp );
}
static void SerializeFloats( CUtlBuffer &buf, int nCount, const float *pFloats )
{
for ( int i = 0; i < nCount; ++i )
{
SerializeFloat( buf, pFloats[i] );
if ( i != nCount-1 )
{
buf.PutChar( ' ' );
}
}
}
//-----------------------------------------------------------------------------
// Serialization methods for basic types
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const bool &src )
{
if ( buf.IsText() )
{
buf.Printf( "%d", src );
}
else
{
buf.PutChar( src );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, bool &dest )
{
if ( buf.IsText() )
{
int nValue = 0;
int nRetVal = buf.Scanf( "%d", &nValue );
dest = ( nValue != 0 );
return (nRetVal == 1) && buf.IsValid();
}
dest = ( buf.GetChar( ) != 0 );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const int &src )
{
if ( buf.IsText() )
{
buf.Printf( "%d", src );
}
else
{
buf.PutInt( src );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, int &dest )
{
if ( buf.IsText() )
{
int nRetVal = buf.Scanf( "%d", &dest );
return (nRetVal == 1) && buf.IsValid();
}
dest = buf.GetInt( );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const float &src )
{
if ( buf.IsText() )
{
SerializeFloat( buf, src );
}
else
{
buf.PutFloat( src );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, float &dest )
{
if ( buf.IsText() )
{
// FIXME: Print this in a way that we never lose precision
int nRetVal = buf.Scanf( "%f", &dest );
return (nRetVal == 1) && buf.IsValid();
}
dest = buf.GetFloat( );
return buf.IsValid();
}
//-----------------------------------------------------------------------------
// Attribute types related to vector math
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const Vector2D &src )
{
if ( buf.IsText() )
{
SerializeFloats( buf, 2, src.Base() );
}
else
{
buf.PutFloat( src.x );
buf.PutFloat( src.y );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, Vector2D &dest )
{
if ( buf.IsText() )
{
// FIXME: Print this in a way that we never lose precision
int nRetVal = buf.Scanf( "%f %f", &dest.x, &dest.y );
return (nRetVal == 2) && buf.IsValid();
}
dest.x = buf.GetFloat( );
dest.y = buf.GetFloat( );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const Vector &src )
{
if ( buf.IsText() )
{
SerializeFloats( buf, 3, src.Base() );
}
else
{
buf.PutFloat( src.x );
buf.PutFloat( src.y );
buf.PutFloat( src.z );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, Vector &dest )
{
if ( buf.IsText() )
{
// FIXME: Print this in a way that we never lose precision
int nRetVal = buf.Scanf( "%f %f %f", &dest.x, &dest.y, &dest.z );
return (nRetVal == 3) && buf.IsValid();
}
dest.x = buf.GetFloat( );
dest.y = buf.GetFloat( );
dest.z = buf.GetFloat( );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const Vector4D &src )
{
if ( buf.IsText() )
{
SerializeFloats( buf, 4, src.Base() );
}
else
{
buf.PutFloat( src.x );
buf.PutFloat( src.y );
buf.PutFloat( src.z );
buf.PutFloat( src.w );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, Vector4D &dest )
{
if ( buf.IsText() )
{
// FIXME: Print this in a way that we never lose precision
int nRetVal = buf.Scanf( "%f %f %f %f", &dest.x, &dest.y, &dest.z, &dest.w );
return (nRetVal == 4) && buf.IsValid();
}
dest.x = buf.GetFloat( );
dest.y = buf.GetFloat( );
dest.z = buf.GetFloat( );
dest.w = buf.GetFloat( );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const QAngle &src )
{
if ( buf.IsText() )
{
SerializeFloats( buf, 3, src.Base() );
}
else
{
buf.PutFloat( src.x );
buf.PutFloat( src.y );
buf.PutFloat( src.z );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, QAngle &dest )
{
if ( buf.IsText() )
{
// FIXME: Print this in a way that we never lose precision
int nRetVal = buf.Scanf( "%f %f %f", &dest.x, &dest.y, &dest.z );
return (nRetVal == 3) && buf.IsValid();
}
dest.x = buf.GetFloat( );
dest.y = buf.GetFloat( );
dest.z = buf.GetFloat( );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const Quaternion &src )
{
if ( buf.IsText() )
{
SerializeFloats( buf, 4, &src.x );
}
else
{
buf.PutFloat( src.x );
buf.PutFloat( src.y );
buf.PutFloat( src.z );
buf.PutFloat( src.w );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, Quaternion &dest )
{
if ( buf.IsText() )
{
// FIXME: Print this in a way that we never lose precision
int nRetVal = buf.Scanf( "%f %f %f %f", &dest.x, &dest.y, &dest.z, &dest.w );
return (nRetVal == 4) && buf.IsValid();
}
dest.x = buf.GetFloat( );
dest.y = buf.GetFloat( );
dest.z = buf.GetFloat( );
dest.w = buf.GetFloat( );
return buf.IsValid();
}
bool Serialize( CUtlBuffer &buf, const VMatrix &src )
{
if ( buf.IsText() )
{
buf.Printf( "\n" );
SerializeFloats( buf, 4, src[0] );
buf.Printf( "\n" );
SerializeFloats( buf, 4, src[1] );
buf.Printf( "\n" );
SerializeFloats( buf, 4, src[2] );
buf.Printf( "\n" );
SerializeFloats( buf, 4, src[3] );
buf.Printf( "\n" );
}
else
{
buf.Put( &src, sizeof(VMatrix) );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, VMatrix &dest )
{
if ( !buf.IsValid() )
return false;
if ( buf.IsText() )
{
int nRetVal = buf.Scanf( "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
&dest[ 0 ][ 0 ], &dest[ 0 ][ 1 ], &dest[ 0 ][ 2 ], &dest[ 0 ][ 3 ],
&dest[ 1 ][ 0 ], &dest[ 1 ][ 1 ], &dest[ 1 ][ 2 ], &dest[ 1 ][ 3 ],
&dest[ 2 ][ 0 ], &dest[ 2 ][ 1 ], &dest[ 2 ][ 2 ], &dest[ 2 ][ 3 ],
&dest[ 3 ][ 0 ], &dest[ 3 ][ 1 ], &dest[ 3 ][ 2 ], &dest[ 3 ][ 3 ] );
return (nRetVal == 16);
}
buf.Get( &dest, sizeof(VMatrix) );
return true;
}
//-----------------------------------------------------------------------------
// Color attribute
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const Color &src )
{
if ( buf.IsText() )
{
buf.Printf( "%d %d %d %d", src[0], src[1], src[2], src[3] );
}
else
{
buf.PutUnsignedChar( src[0] );
buf.PutUnsignedChar( src[1] );
buf.PutUnsignedChar( src[2] );
buf.PutUnsignedChar( src[3] );
}
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, Color &dest )
{
if ( buf.IsText() )
{
int r = 0, g = 0, b = 0, a = 255;
int nRetVal = buf.Scanf( "%d %d %d %d", &r, &g, &b, &a );
dest.SetColor( r, g, b, a );
return (nRetVal == 4) && buf.IsValid();
}
dest[0] = buf.GetUnsignedChar( );
dest[1] = buf.GetUnsignedChar( );
dest[2] = buf.GetUnsignedChar( );
dest[3] = buf.GetUnsignedChar( );
return buf.IsValid();
}
/*
//-----------------------------------------------------------------------------
// Object ID attribute
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const DmObjectId_t &src )
{
return g_pDataModel->Serialize( buf, src );
}
bool Unserialize( CUtlBuffer &buf, DmObjectId_t &dest )
{
return g_pDataModel->Unserialize( buf, &dest );
}
*/
//-----------------------------------------------------------------------------
// Binary buffer attribute
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src )
{
int nLength = src.Length();
if ( !buf.IsText() )
{
buf.PutInt( nLength );
if ( nLength != 0 )
{
buf.Put( src.Get(), nLength );
}
return buf.IsValid();
}
// Writes out uuencoded binaries
for ( int i = 0; i < nLength; ++i )
{
if ( (i % 40) == 0 )
{
buf.PutChar( '\n' );
}
char b1 = src[i] & 0xF;
char b2 = src[i] >> 4;
char c1 = ( b1 <= 9 ) ? b1 + '0' : b1 - 10 + 'A';
char c2 = ( b2 <= 9 ) ? b2 + '0' : b2 - 10 + 'A';
buf.PutChar( c2 );
buf.PutChar( c1 );
}
buf.PutChar( '\n' );
return buf.IsValid();
}
static int CountBinaryBytes( CUtlBuffer &buf, int *pEndGet )
{
// This counts the number of bytes in the uuencoded text
int nStartGet = buf.TellGet();
buf.EatWhiteSpace();
*pEndGet = buf.TellGet();
int nByteCount = 0;
while ( buf.IsValid() )
{
char c1 = buf.GetChar();
char c2 = buf.GetChar();
bool bIsNum1 = ( c1 >= '0' ) && ( c1 <= '9' );
bool bIsNum2 = ( c2 >= '0' ) && ( c2 <= '9' );
bool bIsAlpha1 = (( c1 >= 'A' ) && ( c1 <= 'F' )) || (( c1 >= 'a' ) && ( c1 <= 'f' ));
bool bIsAlpha2 = (( c2 >= 'A' ) && ( c2 <= 'F' )) || (( c2 >= 'a' ) && ( c2 <= 'f' ));
if ( !(bIsNum1 || bIsAlpha1) || !(bIsNum2 || bIsAlpha2) )
break;
buf.EatWhiteSpace();
*pEndGet = buf.TellGet();
++nByteCount;
}
buf.SeekGet( CUtlBuffer::SEEK_HEAD, nStartGet );
return nByteCount;
}
inline static unsigned char HexCharToInt( int c1 )
{
if (( c1 >= '0' ) && ( c1 <= '9' ))
return c1 - '0';
if (( c1 >= 'A' ) && ( c1 <= 'F' ))
return 10 + c1 - 'A';
if (( c1 >= 'a' ) && ( c1 <= 'f' ))
return 10 + c1 - 'a';
return 0xFF;
}
bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest )
{
if ( !buf.IsText() )
{
int nLen = buf.GetInt( );
dest.SetLength( nLen );
if ( dest.Length() != 0 )
{
buf.Get( dest.Get(), dest.Length() );
}
if ( nLen != dest.Length() )
{
buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nLen - dest.Length() );
return false;
}
return buf.IsValid();
}
int nEndGet;
int nByteCount = CountBinaryBytes( buf, &nEndGet );
if ( nByteCount < 0 )
return false;
buf.EatWhiteSpace();
int nDest = 0;
dest.SetLength( nByteCount );
while( buf.TellGet() < nEndGet )
{
char c1 = buf.GetChar();
char c2 = buf.GetChar();
unsigned char b1 = HexCharToInt( c1 );
unsigned char b2 = HexCharToInt( c2 );
if ( b1 == 0xFF || b2 == 0xFF )
return false;
dest[ nDest++ ] = b2 | ( b1 << 4 );
buf.EatWhiteSpace();
}
return true;
}
//-----------------------------------------------------------------------------
// String attribute
//-----------------------------------------------------------------------------
bool Serialize( CUtlBuffer &buf, const CUtlString &src )
{
buf.PutDelimitedString( s_pConv, src.Get() );
return buf.IsValid();
}
bool Unserialize( CUtlBuffer &buf, CUtlString &dest )
{
int nLen = buf.PeekDelimitedStringLength( s_pConv );
dest.SetLength( nLen - 1 ); // -1 because the length returned includes space for \0
buf.GetDelimitedString( s_pConv, dest.Get(), nLen );
return buf.IsValid();
}

548
tier1/utlstring.cpp Normal file
View File

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

436
tier1/utlsymbol.cpp Normal file
View File

@ -0,0 +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();
}