//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "quakedef.h" #include "networkstringtableitem.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CNetworkStringTableItem::CNetworkStringTableItem( void ) { m_pUserData = NULL; m_nUserDataLength = 0; m_nTickChanged = 0; #ifndef SHARED_NET_STRING_TABLES m_nTickCreated = 0; m_pChangeList = NULL; #endif } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CNetworkStringTableItem::~CNetworkStringTableItem( void ) { #ifndef SHARED_NET_STRING_TABLES if ( m_pChangeList ) { // free changelist and elements for ( int i=0; i < m_pChangeList->Count(); i++ ) { itemchange_s item = m_pChangeList->Element( i ); if ( item.data ) delete[] item.data; } delete m_pChangeList; // destructor calls Purge() m_pUserData = NULL; } #endif if ( m_pUserData ) { delete[] m_pUserData; } } #ifndef SHARED_NET_STRING_TABLES void CNetworkStringTableItem::EnableChangeHistory( void ) { if ( m_pChangeList ) return; // already enabled m_pChangeList = new CUtlVector; Assert ( m_pChangeList ); } void CNetworkStringTableItem::UpdateChangeList( int tick, int length, const void *userData ) { int count = m_pChangeList->Count(); itemchange_s item; if ( count > 0 ) { // check if different from last change in list item = m_pChangeList->Element( count-1 ); if ( !item.data && !userData ) return; // both NULL data if ( item.length == length ) { if ( item.data && userData ) { if ( Q_memcmp( (void*)userData, (void*)item.data, length ) == 0 ) { return; // no data or size change } } } if ( item.tick == tick ) { // two changes within same tick frame, remove last change from list if ( item.data ) { delete[] item.data; } m_pChangeList->Remove( count-1 ); } } item.tick = tick; // add new user data and time stamp if ( userData && length ) { item.data = new unsigned char[length]; item.length = length; Q_memcpy( item.data, userData, length ); } else { item.data = NULL; item.length = 0; } m_pChangeList->AddToTail( item ); } int CNetworkStringTableItem::RestoreTick( int tick ) { Assert( m_pChangeList->Count()>0 ); int index = 1; itemchange_s *item = &m_pChangeList->Element( 0 ); while ( index < m_pChangeList->Count() ) { itemchange_s *nextitem = &m_pChangeList->Element( index ); if ( nextitem->tick > tick ) { break; } item = nextitem; index++; } if ( item->tick > tick ) { // this string was created after tick, so ignore it right now m_pUserData = NULL; m_nUserDataLength = 0; m_nTickChanged = 0; } else { // restore user data for this string m_pUserData = item->data; m_nUserDataLength = item->length; m_nTickChanged = item->tick; } return m_nTickChanged; } #endif //----------------------------------------------------------------------------- // Purpose: // Input : *string - //----------------------------------------------------------------------------- bool CNetworkStringTableItem::SetUserData( int tick, int length, const void *userData ) { #ifndef SHARED_NET_STRING_TABLES if ( m_pChangeList ) { UpdateChangeList( tick, length, userData ); return false; } Assert ( m_nTickCreated > 0 && m_nTickCreated <= tick ); #endif Assert ( m_nTickChanged > 0 && m_nTickChanged <= tick ); Assert ( length < CNetworkStringTableItem::MAX_USERDATA_SIZE ); // no old or new data if ( !userData && !m_pUserData ) return false; if ( m_pUserData && length == m_nUserDataLength && !Q_memcmp( m_pUserData, (void*)userData, length ) ) { return false; // old & new data are equal } if ( m_pUserData ) delete[] m_pUserData; m_nUserDataLength = length; if ( length > 0 ) { m_pUserData = new unsigned char[ length ]; Q_memcpy( m_pUserData, userData, length ); } else { m_pUserData = NULL; } m_nTickChanged = tick; return true; } //----------------------------------------------------------------------------- // Purpose: // Input : stringNumber - // Output : const void //----------------------------------------------------------------------------- const void *CNetworkStringTableItem::GetUserData( int *length ) { if ( length ) *length = m_nUserDataLength; return ( const void * )m_pUserData; }