📄 chxstatistictracker.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: CHXStatisticTracker.cpp,v 1.7.6.4 2004/07/09 01:49:47 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */#include "CHXStatisticTracker.h"#include "HXClientConstants.h"#include "CHXFlatArray.h"#include "CHXClientDebug.h"#include "enter_hx_headers.h"#include "ihxpckts.h"#include "hxcore.h"#include "hxmon.h" // IHXRegistry#include "hxcomm.h" // IHXRegistryID#include "hxsmartptr.h"HX_SMART_POINTER_INLINE( SPIHXRegistry, IHXRegistry );HX_SMART_POINTER_INLINE( SPIHXRegistryID, IHXRegistryID );HX_SMART_POINTER_INLINE( SPIHXBuffer, IHXBuffer );HX_SMART_POINTER_INLINE( SPIHXValues, IHXValues );#include "exit_hx_headers.h"#include "hlxclib/string.h"#include "hlxclib/stdlib.h"static char const kRegistryPropertySeparator = '.';static char const kStatisticKeyWildcard = '#';static UINT32 const kInvalidRegistryPropID = 0;#ifdef LOG_STATISTICS_DEBUG_INFOstatic voidExamineProperty( IHXRegistry* pIRegistry, const UINT32 ulId, const char* pMsg ){ SPIHXBuffer spPropNameBuffer; pIRegistry->GetPropName( ulId, *spPropNameBuffer.AsInOutParam() );#ifdef _MAC_MACHO CFStringRef debugStr = CFStringCreateWithFormat( kCFAllocatorDefault, nil, CFSTR( "%s: ID = %d, Name = %s" ), pMsg, ulId, ( const char* ) spPropNameBuffer->GetBuffer() ); CFShow( debugStr ); CFRelease( debugStr );#endif}#endifclass CHXStatisticProcessor{public: CHXStatisticProcessor( void ) {} virtual ~CHXStatisticProcessor( void ) {} virtual bool operator() ( int valueType, const unsigned char* pValue ) = 0;};static boolProcessStatistic( IHXRegistry* pIRegistry, UINT32 statisticPropID, CHXStatisticProcessor& Processor ){ CHXASSERT( pIRegistry ); if ( statisticPropID != kInvalidRegistryPropID ) { HXPropType propType = pIRegistry->GetTypeById( statisticPropID ); switch ( propType ) { case PT_INTEGER: { INT32 intProperty; if ( SUCCEEDED( pIRegistry->GetIntById( statisticPropID, intProperty ) ) ) { return Processor( kValueType32BitSignedInt, ( const unsigned char* ) &intProperty ); } } break; case PT_STRING: { SPIHXBuffer spPropStringBuffer; if ( SUCCEEDED( pIRegistry->GetStrById( statisticPropID, *spPropStringBuffer.AsInOutParam() ) ) && spPropStringBuffer.IsValid() ) { return Processor( kValueTypeString, spPropStringBuffer->GetBuffer() ); } } break; default: break; } } return false;}static const char*GetPropSubString( const char* pStatisticKey, int propIndex, UINT32* pLength, bool* pIsLeafKey ){ if ( !pStatisticKey ) return NULL; const char* pLocation = pStatisticKey; for ( int index = 0; index < propIndex; ++index ) { pLocation = strchr( pLocation, kRegistryPropertySeparator ); if ( !pLocation ) { return NULL; } ++pLocation; } const char* pNextLocation = strchr( pLocation, kRegistryPropertySeparator ); if ( pNextLocation ) { *pLength = pNextLocation - pLocation; *pIsLeafKey = false; } else { *pLength = strlen( pLocation ); *pIsLeafKey = true; } return pLocation;}static boolShouldObserveProperty( const char* pStatisticKey, const char* pPropName, bool shouldObserveJustMe ){ int propIndex = 0; bool isLeafNode, isLeafKey = ( !pStatisticKey || !*pStatisticKey ); UINT32 nodeLength, keyLength; const char* pNodeSubString; while ( NULL != ( pNodeSubString = GetPropSubString( pPropName, propIndex, &nodeLength, &isLeafNode ) ) ) { const char* pKeySubString = GetPropSubString( pStatisticKey, propIndex, &keyLength, &isLeafKey ); if ( !pKeySubString ) return false; // Wildcard matches all subsequent characters in node prop name. if ( pKeySubString[ keyLength - 1 ] == kStatisticKeyWildcard ) { if ( nodeLength < keyLength ) return false; if ( 0 != strncasecmp( pKeySubString, pNodeSubString, ( keyLength - 1 ) ) ) return false; } else { if ( nodeLength != keyLength ) return false; if ( 0 != strncasecmp( pKeySubString, pNodeSubString, keyLength ) ) return false; } ++propIndex; } return shouldObserveJustMe ? isLeafKey : true;}// ***** CHXStatisticTrackerNode *****CHXStatisticTrackerNode::CHXStatisticTrackerNode( IHXRegistry* pIRegistry, CHXStatisticTracker* pParentTracker, UINT32 propID, const char* pFullPropName ) : m_pRegistry( pIRegistry ) , m_pPropWatch( NULL ) , m_PropName( NULL ) , m_pParentTracker( pParentTracker ) , m_PropID( propID ){ CHXASSERT( m_pRegistry ); m_pRegistry->AddRef(); if ( m_pParentTracker ) { CHXASSERT( pFullPropName ); // Skip the Statistics.Player#. portion. const char* pNodePropName = pFullPropName; int separatorsLeftToSkip = 2; while ( *pNodePropName ) { if ( *pNodePropName == kRegistryPropertySeparator ) { --separatorsLeftToSkip; } pNodePropName++; if ( separatorsLeftToSkip <= 0 ) { break; } } m_PropName = ( char* ) malloc( strlen( pNodePropName ) + 1 ); strcpy( m_PropName, pNodePropName ); }}CHXStatisticTrackerNode::~CHXStatisticTrackerNode( void ){ if ( m_PropName ) { free( m_PropName ); m_PropName = NULL; } if ( m_pPropWatch ) { m_pPropWatch->Release(); m_pPropWatch = NULL; } m_pRegistry->Release();}BEGIN_INTERFACE_LIST_NOCREATE( CHXStatisticTrackerNode ) INTERFACE_LIST_ENTRY_SIMPLE( IHXPropWatchResponse )END_INTERFACE_LISTboolCHXStatisticTrackerNode::IsWatchingMe( void ) const{ return( NULL != m_pPropWatch );}boolCHXStatisticTrackerNode::StartWatchingMe( void ){ if ( m_pPropWatch ) return true; CHXASSERT( m_pRegistry ); HX_RESULT result = m_pRegistry->CreatePropWatch( m_pPropWatch ); if ( SUCCEEDED( result ) ) { result = m_pPropWatch->Init( this ); if ( SUCCEEDED( result ) ) { m_pPropWatch->SetWatchById( m_PropID ); } else { m_pPropWatch->Release(); m_pPropWatch = NULL; } } return( 0 != SUCCEEDED( result ) );}voidCHXStatisticTrackerNode::StopWatchingMe( void ){ if ( !m_pPropWatch ) return; m_pPropWatch->ClearWatchById( m_PropID ); m_pPropWatch->Release(); m_pPropWatch = NULL;}class CopyStatisticProcessor : public CHXStatisticProcessor{private: unsigned char* m_pValueBuffer; UINT32 m_BufferLength; int* m_pValueType; UINT32* m_pUsedBufferLength;public: CopyStatisticProcessor( unsigned char* pValueBuffer, UINT32 bufferLength, int* pValueType, UINT32* pUsedBufferLength ) : m_pValueBuffer( pValueBuffer ) , m_BufferLength( bufferLength ) , m_pValueType( pValueType ) , m_pUsedBufferLength( pUsedBufferLength ) {} virtual ~CopyStatisticProcessor( void ) {} virtual bool operator() ( int valueType, const unsigned char* pValue ) { *m_pValueType = valueType; UINT32 desiredBufferLength = 0; switch ( valueType ) { case kValueType32BitSignedInt: desiredBufferLength = sizeof( INT32 ); break; case kValueTypeString: desiredBufferLength = strlen( ( const char* ) pValue ) + 1; break; } if ( !m_pValueBuffer || ( m_BufferLength == 0 ) ) { if ( m_pUsedBufferLength ) { *m_pUsedBufferLength = desiredBufferLength; } return false; } bool outCopied = false; UINT32 usedBufferLength = 0; if ( desiredBufferLength <= m_BufferLength ) { usedBufferLength = desiredBufferLength; memcpy( m_pValueBuffer, pValue, usedBufferLength ); outCopied = true; } else { switch ( valueType ) { case kValueType32BitSignedInt: break; case kValueTypeString: { usedBufferLength = m_BufferLength; memcpy( m_pValueBuffer, pValue, usedBufferLength ); m_pValueBuffer[ usedBufferLength - 1 ] = '\0'; outCopied = true; } break; } } if ( m_pUsedBufferLength ) { *m_pUsedBufferLength = usedBufferLength; } return outCopied; }};boolCHXStatisticTrackerNode::GetStatisticsFor( const char* pStatisticKey, unsigned char* pValueBuffer, UINT32 bufferLength, int* pValueType, UINT32* pUsedBufferLength ){ bool outGotStatistic = false; CHXStatisticTrackerNode* pPlayerTracker = this; CHXStatisticTracker* pParentTracker = GetParentTracker(); while ( pParentTracker ) { pPlayerTracker = pParentTracker; pParentTracker = pParentTracker->GetParentTracker(); } UINT32 playerId = pPlayerTracker->GetPropID(); SPIHXBuffer spPlayerNameBuffer; m_pRegistry->GetPropName( playerId, *spPlayerNameBuffer.AsInOutParam() ); if ( spPlayerNameBuffer.IsValid() && ( spPlayerNameBuffer->GetSize() > 0 ) ) { UINT32 fullPropNameSize = spPlayerNameBuffer->GetSize() + 1 + strlen( pStatisticKey ) + 1; char* pFullPropName = new char[ fullPropNameSize ]; if ( pFullPropName ) { sprintf( pFullPropName, "%s%c%s", spPlayerNameBuffer->GetBuffer(), kRegistryPropertySeparator, pStatisticKey ); UINT32 propID = m_pRegistry->GetId( pFullPropName ); if ( propID != kInvalidRegistryPropID ) { CopyStatisticProcessor Processor( pValueBuffer, bufferLength, pValueType, pUsedBufferLength ); outGotStatistic = ProcessStatistic( m_pRegistry, propID, Processor ); } delete [] pFullPropName; } } return outGotStatistic;}#ifdef LOG_STATISTICS_DEBUG_INFOvoidCHXStatisticTrackerNode::ExamineProperty( const UINT32 ulId, const char* pMsg ){ ::ExamineProperty( m_pRegistry, ulId, pMsg );}static voidExamineStatisticsByName( IHXRegistry* pIRegistry, const char* pFullEntryName ){ SPIHXValues spRegistryValues; if ( SUCCEEDED( pIRegistry->GetPropListByName( pFullEntryName, *spRegistryValues.AsInOutParam() ) ) ) { const char* pPropertyName = NULL; ULONG32 propertyID; if ( SUCCEEDED( spRegistryValues->GetFirstPropertyULONG32( pPropertyName, propertyID ) ) ) { do { INT32 registryIntValue; SPIHXBuffer spRegistryStrValue; if ( SUCCEEDED( pIRegistry->GetStrByName( pPropertyName, *spRegistryStrValue.AsInOutParam() ) ) ) { const char* pRegistryStrValue = ( const char* ) spRegistryStrValue->GetBuffer();#ifdef _MAC_MACHO CFStringRef debugStr = CFStringCreateWithFormat( kCFAllocatorDefault, nil, CFSTR( "String: %s = %s" ), pPropertyName, pRegistryStrValue ); CFShow( debugStr ); CFRelease( debugStr );#endif } else if ( SUCCEEDED( pIRegistry->GetIntByName( pPropertyName, registryIntValue ) ) ) {#ifdef _MAC_MACHO CFStringRef debugStr = CFStringCreateWithFormat( kCFAllocatorDefault, nil, CFSTR( "Int: %s = %d" ), pPropertyName, registryIntValue ); CFShow( debugStr ); CFRelease( debugStr );#endif } else { ExamineStatisticsByName( pIRegistry, pPropertyName ); } } while ( SUCCEEDED( spRegistryValues->GetNextPropertyULONG32( pPropertyName, propertyID ) ) ); } }}voidCHXStatisticTrackerNode::ExamineStatistics( void ){ CHXASSERT( m_pRegistry ); SPIHXBuffer spFullPropName; m_pRegistry->GetPropName( m_PropID, *spFullPropName.AsInOutParam() ); if ( spFullPropName.IsValid() ) { ExamineStatisticsByName( m_pRegistry, ( const char* ) spFullPropName->GetBuffer() ); CFShow( CFSTR( "*************** End of set ***************" ) ); }}#endif// ***** CHXStatisticTracker *****CHXStatisticTracker*CHXStatisticTracker::CreatePlayerStatisticTracker( IHXPlayer* pIHXPlayer ){ SPIHXRegistry spRegistry = pIHXPlayer; CHXASSERT( spRegistry.IsValid() ); // Client player must support IHXRegistry. SPIHXRegistryID spRegistryID = pIHXPlayer; CHXASSERT( spRegistryID.IsValid() ); // Client player must support IHXRegistryID. UINT32 playerId; SPIHXBuffer spPlayerNameBuffer; spRegistryID->GetID( playerId ); spRegistry->GetPropName( playerId, *spPlayerNameBuffer.AsInOutParam() ); if ( spPlayerNameBuffer.IsValid() && ( spPlayerNameBuffer->GetSize() > 0 ) ) { CHXStatisticTracker* pPlayerStatisticTracker = new CHXStatisticTracker( spRegistry.Ptr(), NULL, playerId, ( const char* ) spPlayerNameBuffer->GetBuffer() ); if ( pPlayerStatisticTracker ) { pPlayerStatisticTracker->AddRef(); if ( pPlayerStatisticTracker->StartWatchingMe() ) { return pPlayerStatisticTracker; } pPlayerStatisticTracker->Release(); pPlayerStatisticTracker = NULL; } } return NULL;}voidCHXStatisticTracker::DestroyPlayerStatisticTracker( CHXStatisticTracker* pPlayerStatisticTracker ){ if ( pPlayerStatisticTracker ) { pPlayerStatisticTracker->StopWatchingMe(); pPlayerStatisticTracker->Release(); pPlayerStatisticTracker = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -