//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// // // Purpose: // // $NoKeywords: $ // // Unique ID generation //=============================================================================// #include "tier0/platform.h" #ifdef IS_WINDOWS_PC #include // uuidcreate #else #include "checksum_crc.h" #endif #include "tier1/uniqueid.h" #include "tier1/utlbuffer.h" // NOTE: This has to be the last file included! #include "tier0/memdbgon.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) && V_isspace( pTemp[nMaxLen] ) ) { --nMaxLen; } pTemp[ nMaxLen + 1 ] = 0; while( *pTemp && V_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(); }