You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
768 lines
23 KiB
768 lines
23 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#ifndef DMATTRIBUTE_H |
|
#define DMATTRIBUTE_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "datamodel/attributeflags.h" |
|
#include "datamodel/idatamodel.h" |
|
#include "datamodel/dmattributetypes.h" |
|
#include "datamodel/dmelement.h" |
|
#include "datamodel/dmvar.h" |
|
#include "tier1/utlhash.h" |
|
|
|
//----------------------------------------------------------------------------- |
|
// Fast dynamic cast |
|
//----------------------------------------------------------------------------- |
|
template< class E > |
|
inline E *CastElement( CDmElement *pElement ) |
|
{ |
|
if ( pElement && pElement->IsA( E::GetStaticTypeSymbol() ) ) |
|
return static_cast< E* >( pElement ); |
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// type-safe element creation and accessor helpers - infers type name string from actual type |
|
//----------------------------------------------------------------------------- |
|
template< class E > |
|
inline E *GetElement( DmElementHandle_t hElement ) |
|
{ |
|
CDmElement *pElement = g_pDataModel->GetElement( hElement ); |
|
return CastElement< E >( pElement ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Typesafe element creation + destruction |
|
//----------------------------------------------------------------------------- |
|
template< class E > |
|
inline E *CreateElement( const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) |
|
{ |
|
return GetElement< E >( g_pDataModel->CreateElement( E::GetStaticTypeSymbol(), pObjectName, fileid, pObjectID ) ); |
|
} |
|
|
|
template< class E > |
|
inline E *CreateElement( const char *pElementType, const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) |
|
{ |
|
return GetElement< E >( g_pDataModel->CreateElement( pElementType, pObjectName, fileid, pObjectID ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Used for attribute change callbacks |
|
//----------------------------------------------------------------------------- |
|
typedef unsigned short DmMailingList_t; |
|
enum |
|
{ |
|
DMMAILINGLIST_INVALID = (DmMailingList_t)~0 |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: A general purpose pAttribute. Eventually will be extensible to arbitrary user types |
|
//----------------------------------------------------------------------------- |
|
class CDmAttribute |
|
{ |
|
public: |
|
// Returns the type |
|
DmAttributeType_t GetType() const; |
|
const char *GetTypeString() const; |
|
template< class T > bool IsA() const; |
|
|
|
// Returns the name. NOTE: The utlsymbol |
|
// can be turned into a string by using g_pDataModel->String(); |
|
const char *GetName() const; |
|
UtlSymId_t GetNameSymbol() const; |
|
void SetName( const char *newName ); |
|
|
|
// Gets the attribute value |
|
// NOTE: GetValueUntyped is used with GetType() for use w/ SetValue( type, void* ) |
|
template< class T > const T& GetValue() const; |
|
template< class T > const T& GetValue( const T& defaultValue ) const; |
|
const char *GetValueString() const; |
|
template< class E > E *GetValueElement() const; |
|
const void *GetValueUntyped() const; |
|
|
|
// Sets the attribute value |
|
template< class T > void SetValue( const T &value ); |
|
template< class E > void SetValue( E* pValue ); |
|
void SetValue( const void *pValue, size_t nSize ); |
|
|
|
// Copies w/ type conversion (if possible) from another attribute |
|
void SetValue( const CDmAttribute *pAttribute ); |
|
void SetValue( CDmAttribute *pAttribute ); |
|
void SetValue( DmAttributeType_t valueType, const void *pValue ); |
|
|
|
// Sets the attribute to its default value based on its type |
|
void SetToDefaultValue(); |
|
|
|
// Convert to and from string |
|
void SetValueFromString( const char *pValue ); |
|
const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const; |
|
|
|
// Used for element and element array attributes; it specifies which type of |
|
// elements are valid to be referred to by this attribute |
|
void SetElementTypeSymbol( UtlSymId_t typeSymbol ); |
|
UtlSymId_t GetElementTypeSymbol() const; |
|
|
|
// Returns the next attribute |
|
CDmAttribute *NextAttribute(); |
|
const CDmAttribute *NextAttribute() const; |
|
|
|
// Returns the owner |
|
CDmElement *GetOwner(); |
|
|
|
// Methods related to flags |
|
void AddFlag( int flags ); |
|
void RemoveFlag( int flags ); |
|
void ClearFlags(); |
|
int GetFlags() const; |
|
bool IsFlagSet( int flags ) const; |
|
|
|
// Serialization |
|
bool Serialize( CUtlBuffer &buf ) const; |
|
bool Unserialize( CUtlBuffer &buf ); |
|
|
|
// Serialization of a single element. |
|
// First version of UnserializeElement adds to tail if it worked |
|
// Second version overwrites, but does not add, the element at the specified index |
|
bool SerializeElement( int nElement, CUtlBuffer &buf ) const; |
|
bool UnserializeElement( CUtlBuffer &buf ); |
|
bool UnserializeElement( int nElement, CUtlBuffer &buf ); |
|
|
|
// Does this attribute serialize on multiple lines? |
|
bool SerializesOnMultipleLines() const; |
|
|
|
// Get the attribute/create an attribute handle |
|
DmAttributeHandle_t GetHandle( bool bCreate = true ); |
|
|
|
// Notify external elements upon change ( Calls OnAttributeChanged ) |
|
// Pass false here to stop notification |
|
void NotifyWhenChanged( DmElementHandle_t h, bool bNotify ); |
|
|
|
// estimate memory overhead |
|
int EstimateMemoryUsage( TraversalDepth_t depth ) const; |
|
|
|
private: |
|
// Class factory |
|
static CDmAttribute *CreateAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName ); |
|
static CDmAttribute *CreateExternalAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pExternalMemory ); |
|
static void DestroyAttribute( CDmAttribute *pAttribute ); |
|
|
|
// Constructor, destructor |
|
CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName ); |
|
CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pMemory ); |
|
~CDmAttribute(); |
|
|
|
// Used when constructing CDmAttributes |
|
void Init( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName ); |
|
|
|
// Used when shutting down, indicates DmAttributeHandle_t referring to this are invalid |
|
void InvalidateHandle(); |
|
|
|
// Used when shutting down, indicates no more change notifications will be sent to listening elements |
|
void CleanupMailingList(); |
|
|
|
// Called when the attribute changes |
|
void PreChanged(); |
|
void OnChanged( bool bArrayCountChanged = false, bool bIsTopological = false ); |
|
|
|
// Is modification allowed in this phase? |
|
bool ModificationAllowed() const; |
|
|
|
// Mark the attribute as being dirty |
|
bool MarkDirty(); |
|
|
|
// Is the data inline in a containing element class? |
|
bool IsDataInline() const; |
|
|
|
// Allocates, frees internal data storage |
|
void CreateAttributeData(); |
|
void DeleteAttributeData(); |
|
|
|
// Gets at the internal data storage |
|
void* GetAttributeData(); |
|
const void* GetAttributeData() const; |
|
template < class T > typename CDmAttributeInfo< T >::StorageType_t* GetData(); |
|
template < class T > const typename CDmAttributeInfo< T >::StorageType_t* GetData() const; |
|
template < class T > typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData(); |
|
template < class T > const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData() const; |
|
|
|
// Used by CDmElement to manage the list of attributes it owns |
|
CDmAttribute **GetNextAttributeRef(); |
|
|
|
// Implementational function used for memory consumption estimation computation |
|
int EstimateMemoryUsageInternal( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ) const; |
|
|
|
// Called by elements after unserialization of their attributes is complete |
|
void OnUnserializationFinished(); |
|
|
|
template< class T > bool IsTypeConvertable() const; |
|
template< class T > bool ShouldModify( const T& src ); |
|
template< class T > void CopyData( const T& src ); |
|
template< class T > void CopyDataOut( T& dest ) const; |
|
|
|
private: |
|
CDmAttribute *m_pNext; |
|
void *m_pData; |
|
CDmElement *m_pOwner; |
|
int m_nFlags; |
|
DmAttributeHandle_t m_Handle; |
|
CUtlSymbol m_Name; |
|
DmMailingList_t m_hMailingList; |
|
|
|
friend class CDmElement; |
|
friend class CDmAttributeAccessor; |
|
template< class T > friend class CDmrElementArray; |
|
template< class E > friend class CDmrElementArrayConst; |
|
template< class T > friend class CDmaArrayAccessor; |
|
template< class T, class B > friend class CDmrDecorator; |
|
template< class T, class B > friend class CDmrDecoratorConst; |
|
template< class T > friend class CDmArrayAttributeOp; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Inline methods |
|
//----------------------------------------------------------------------------- |
|
inline DmAttributeType_t CDmAttribute::GetType() const |
|
{ |
|
return (DmAttributeType_t)( m_nFlags & FATTRIB_TYPEMASK ); |
|
} |
|
|
|
template< class T > inline bool CDmAttribute::IsA() const |
|
{ |
|
return GetType() == CDmAttributeInfo< T >::AttributeType(); |
|
} |
|
|
|
inline const char *CDmAttribute::GetName() const |
|
{ |
|
return g_pDataModel->GetString( m_Name ); |
|
} |
|
|
|
inline UtlSymId_t CDmAttribute::GetNameSymbol() const |
|
{ |
|
return m_Name; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Iteration |
|
//----------------------------------------------------------------------------- |
|
inline CDmAttribute *CDmAttribute::NextAttribute() |
|
{ |
|
return m_pNext; |
|
} |
|
|
|
inline const CDmAttribute *CDmAttribute::NextAttribute() const |
|
{ |
|
return m_pNext; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns the owner |
|
//----------------------------------------------------------------------------- |
|
inline CDmElement *CDmAttribute::GetOwner() |
|
{ |
|
return m_pOwner; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Value getting methods |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
inline const T& CDmAttribute::GetValue( const T& defaultValue ) const |
|
{ |
|
if ( GetType() == ( DmAttributeType_t )( CDmAttributeInfo< T >::ATTRIBUTE_TYPE ) ) |
|
return *reinterpret_cast< const T* >( m_pData ); |
|
|
|
if ( IsTypeConvertable< T >() ) |
|
{ |
|
static T tempVal; |
|
CopyDataOut( tempVal ); |
|
return tempVal; |
|
} |
|
|
|
Assert( 0 ); |
|
return defaultValue; |
|
} |
|
|
|
template< class T > |
|
inline const T& CDmAttribute::GetValue() const |
|
{ |
|
static CDmaVar< T > defaultVal; |
|
return GetValue( defaultVal.Get() ); |
|
} |
|
|
|
inline const char *CDmAttribute::GetValueString() const |
|
{ |
|
Assert( GetType() == AT_STRING ); |
|
if ( GetType() != AT_STRING ) |
|
return NULL; |
|
|
|
return GetValue< CUtlString >(); |
|
} |
|
|
|
// used with GetType() for use w/ SetValue( type, void* ) |
|
inline const void* CDmAttribute::GetValueUntyped() const |
|
{ |
|
return m_pData; |
|
} |
|
|
|
template< class E > |
|
inline E* CDmAttribute::GetValueElement() const |
|
{ |
|
Assert( GetType() == AT_ELEMENT ); |
|
if ( GetType() == AT_ELEMENT ) |
|
return GetElement<E>( this->GetValue< DmElementHandle_t >() ); |
|
return NULL; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Value setting methods |
|
//----------------------------------------------------------------------------- |
|
template< class E > |
|
inline void CDmAttribute::SetValue( E* pValue ) |
|
{ |
|
Assert( GetType() == AT_ELEMENT ); |
|
if ( GetType() == AT_ELEMENT ) |
|
{ |
|
SetValue( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID ); |
|
} |
|
} |
|
|
|
template<> |
|
inline void CDmAttribute::SetValue( const char *pValue ) |
|
{ |
|
int nLen = pValue ? Q_strlen( pValue ) + 1 : 0; |
|
CUtlString str( pValue, nLen ); |
|
return SetValue( str ); |
|
} |
|
|
|
template<> |
|
inline void CDmAttribute::SetValue( char *pValue ) |
|
{ |
|
return SetValue( (const char *)pValue ); |
|
} |
|
|
|
inline void CDmAttribute::SetValue( const void *pValue, size_t nSize ) |
|
{ |
|
CUtlBinaryBlock buf( pValue, (int)nSize ); |
|
return SetValue( buf ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Methods related to flags |
|
//----------------------------------------------------------------------------- |
|
inline void CDmAttribute::AddFlag( int nFlags ) |
|
{ |
|
m_nFlags |= nFlags; |
|
} |
|
|
|
inline void CDmAttribute::RemoveFlag( int nFlags ) |
|
{ |
|
m_nFlags &= ~nFlags; |
|
} |
|
|
|
inline void CDmAttribute::ClearFlags() |
|
{ |
|
m_nFlags = 0; |
|
} |
|
|
|
inline int CDmAttribute::GetFlags() const |
|
{ |
|
return m_nFlags; |
|
} |
|
|
|
inline bool CDmAttribute::IsFlagSet( int nFlags ) const |
|
{ |
|
return ( nFlags & m_nFlags ) ? true : false; |
|
} |
|
|
|
inline bool CDmAttribute::IsDataInline() const |
|
{ |
|
return !IsFlagSet(FATTRIB_EXTERNAL); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets at the internal data storage |
|
//----------------------------------------------------------------------------- |
|
inline void* CDmAttribute::GetAttributeData() |
|
{ |
|
return m_pData; |
|
} |
|
|
|
inline const void* CDmAttribute::GetAttributeData() const |
|
{ |
|
return m_pData; |
|
} |
|
|
|
template < class T > |
|
inline typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() |
|
{ |
|
return ( typename CDmAttributeInfo< T >::StorageType_t* )m_pData; |
|
} |
|
|
|
template < class T > |
|
inline typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() |
|
{ |
|
return ( typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData; |
|
} |
|
|
|
template < class T > |
|
inline const typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() const |
|
{ |
|
return ( const typename CDmAttributeInfo< T >::StorageType_t* )m_pData; |
|
} |
|
|
|
template < class T > |
|
inline const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() const |
|
{ |
|
return ( const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Used by CDmElement to manage the list of attributes it owns |
|
//----------------------------------------------------------------------------- |
|
inline CDmAttribute **CDmAttribute::GetNextAttributeRef() |
|
{ |
|
return &m_pNext; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// helper function for determining which attributes/elements to traverse during copy/find/save/etc. |
|
//----------------------------------------------------------------------------- |
|
inline bool ShouldTraverse( const CDmAttribute *pAttr, TraversalDepth_t depth ) |
|
{ |
|
switch ( depth ) |
|
{ |
|
case TD_NONE: |
|
return false; |
|
|
|
case TD_SHALLOW: |
|
if ( !pAttr->IsFlagSet( FATTRIB_MUSTCOPY ) ) |
|
return false; |
|
// fall-through intentional |
|
case TD_DEEP: |
|
if ( pAttr->IsFlagSet( FATTRIB_NEVERCOPY ) ) |
|
return false; |
|
// fall-through intentional |
|
case TD_ALL: |
|
return true; |
|
} |
|
|
|
Assert( 0 ); |
|
return false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Gets attributes |
|
//----------------------------------------------------------------------------- |
|
inline CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) |
|
{ |
|
CDmAttribute *pAttribute = FindAttribute( pAttributeName ); |
|
if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) ) |
|
return NULL; |
|
return pAttribute; |
|
} |
|
|
|
inline const CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) const |
|
{ |
|
CDmAttribute *pAttribute = FindAttribute( pAttributeName ); |
|
if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) ) |
|
return NULL; |
|
return pAttribute; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// AddAttribute calls |
|
//----------------------------------------------------------------------------- |
|
inline CDmAttribute *CDmElement::AddAttribute( const char *pAttributeName, DmAttributeType_t type ) |
|
{ |
|
CDmAttribute *pAttribute = FindAttribute( pAttributeName ); |
|
if ( pAttribute ) |
|
return ( pAttribute->GetType() == type ) ? pAttribute : NULL; |
|
pAttribute = CreateAttribute( pAttributeName, type ); |
|
return pAttribute; |
|
} |
|
|
|
template< class E > inline CDmAttribute *CDmElement::AddAttributeElement( const char *pAttributeName ) |
|
{ |
|
CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT ); |
|
if ( !pAttribute ) |
|
return NULL; |
|
|
|
// FIXME: If the attribute exists but has a different element type symbol, should we complain? |
|
pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() ); |
|
return pAttribute; |
|
} |
|
|
|
template< class E > inline CDmAttribute *CDmElement::AddAttributeElementArray( const char *pAttributeName ) |
|
{ |
|
CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT_ARRAY ); |
|
if ( !pAttribute ) |
|
return NULL; |
|
|
|
// FIXME: If the attribute exists but has a different element type symbol, should we complain? |
|
pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() ); |
|
return pAttribute; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// GetValue methods |
|
//----------------------------------------------------------------------------- |
|
|
|
template< class T > |
|
inline const T& CDmElement::GetValue( const char *pAttributeName ) const |
|
{ |
|
static CDmaVar<T> defaultVal; |
|
return GetValue( pAttributeName, defaultVal.Get() ); |
|
} |
|
|
|
inline const char *CDmElement::GetValueString( const char *pAttributeName ) const |
|
{ |
|
return GetValue<CUtlString>( pAttributeName ).Get(); |
|
} |
|
|
|
template< class E > |
|
inline E* CDmElement::GetValueElement( const char *pAttributeName ) const |
|
{ |
|
DmElementHandle_t h = GetValue< DmElementHandle_t >( pAttributeName ); |
|
return GetElement<E>( h ); |
|
} |
|
|
|
|
|
template< class T > |
|
inline const T& CDmElement::GetValue( const char *pAttributeName, const T& defaultVal ) const |
|
{ |
|
const CDmAttribute *pAttribute = FindAttribute( pAttributeName ); |
|
if ( pAttribute != NULL ) |
|
return pAttribute->GetValue<T>(); |
|
return defaultVal; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// SetValue methods |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const T& value ) |
|
{ |
|
CDmAttribute *pAttribute = FindAttribute( pAttributeName ); |
|
if ( !pAttribute ) |
|
{ |
|
pAttribute = CreateAttribute( pAttributeName, CDmAttributeInfo<T>::AttributeType() ); |
|
} |
|
if ( pAttribute ) |
|
{ |
|
pAttribute->SetValue( value ); |
|
return pAttribute; |
|
} |
|
return NULL; |
|
} |
|
|
|
template< class E > |
|
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, E* pElement ) |
|
{ |
|
DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID; |
|
return SetValue( pAttributeName, hElement ); |
|
} |
|
|
|
template<> |
|
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const char *pValue ) |
|
{ |
|
int nLen = pValue ? Q_strlen( pValue ) + 1 : 0; |
|
CUtlString str( pValue, nLen ); |
|
return SetValue( pAttributeName, str ); |
|
} |
|
|
|
template<> |
|
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, char *pValue ) |
|
{ |
|
return SetValue( pAttributeName, (const char *)pValue ); |
|
} |
|
|
|
inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const void *pValue, size_t nSize ) |
|
{ |
|
CUtlBinaryBlock buf( pValue, (int)nSize ); |
|
return SetValue( pAttributeName, buf ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// AddValue methods( set value if not found ) |
|
//----------------------------------------------------------------------------- |
|
template< class T > |
|
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const T& value ) |
|
{ |
|
CDmAttribute *pAttribute = GetAttribute( pAttributeName ); |
|
if ( !pAttribute ) |
|
return SetValue( pAttributeName, value ); |
|
return pAttribute; |
|
} |
|
|
|
template< class E > |
|
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, E* pElement ) |
|
{ |
|
DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID; |
|
return InitValue( pAttributeName, hElement ); |
|
} |
|
|
|
inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const void *pValue, size_t size ) |
|
{ |
|
CDmAttribute *pAttribute = GetAttribute( pAttributeName ); |
|
if ( !pAttribute ) |
|
return SetValue( pAttributeName, pValue, size ); |
|
return pAttribute; |
|
} |
|
|
|
template< class T > |
|
T *FindReferringElement( CDmElement *pElement, UtlSymId_t symAttrName, bool bMustBeInSameFile = true ) |
|
{ |
|
DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pElement->GetHandle() ); |
|
while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID ) |
|
{ |
|
CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i ); |
|
CDmElement *pDmeParent = pAttribute->GetOwner(); |
|
if ( pDmeParent && pAttribute->GetNameSymbol() == symAttrName ) |
|
{ |
|
T *pParent = CastElement< T >( pDmeParent ); |
|
if ( pParent ) |
|
{ |
|
if ( !bMustBeInSameFile || ( pParent->GetFileId() == pElement->GetFileId() ) ) |
|
return pParent; |
|
} |
|
} |
|
i = g_pDataModel->NextAttributeReferencingElement( i ); |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
template< class T > |
|
T *FindAncestorReferencingElement( CDmElement *target ) |
|
{ |
|
if ( !target ) |
|
return NULL; |
|
|
|
for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() ); |
|
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; |
|
it = g_pDataModel->NextAttributeReferencingElement( it ) ) |
|
{ |
|
CDmAttribute *attr = g_pDataModel->GetAttribute( it ); |
|
Assert( attr ); |
|
CDmElement *element = attr->GetOwner(); |
|
Assert( element ); |
|
if ( !element ) |
|
continue; |
|
T *t = CastElement< T >( element ); |
|
if ( !t ) |
|
continue; |
|
|
|
return t; |
|
} |
|
return NULL; |
|
} |
|
|
|
template< class T > |
|
T *FindAncestorReferencingElement_R_Impl( CUtlRBTree< CDmElement * >& visited, CDmElement *check ) |
|
{ |
|
if ( visited.Find( check ) != visited.InvalidIndex() ) |
|
return NULL; |
|
|
|
visited.Insert( check ); |
|
|
|
// Pass one, see if it's in this ancestor list |
|
DmAttributeReferenceIterator_t it; |
|
for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() ); |
|
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; |
|
it = g_pDataModel->NextAttributeReferencingElement( it ) ) |
|
{ |
|
CDmAttribute *attr = g_pDataModel->GetAttribute( it ); |
|
Assert( attr ); |
|
CDmElement *element = attr->GetOwner(); |
|
Assert( element ); |
|
if ( !element ) |
|
continue; |
|
T *t = CastElement< T >( element ); |
|
if ( !t ) |
|
continue; |
|
|
|
return t; |
|
} |
|
|
|
for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() ); |
|
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; |
|
it = g_pDataModel->NextAttributeReferencingElement( it ) ) |
|
{ |
|
CDmAttribute *attr = g_pDataModel->GetAttribute( it ); |
|
Assert( attr ); |
|
CDmElement *element = attr->GetOwner(); |
|
Assert( element ); |
|
if ( !element ) |
|
continue; |
|
|
|
T *found = FindAncestorReferencingElement_R_Impl< T >( visited, element ); |
|
if ( found ) |
|
return found; |
|
} |
|
return NULL; |
|
} |
|
|
|
|
|
template< class T > |
|
void FindAncestorsReferencingElement( CDmElement *target, CUtlVector< T* >& list ) |
|
{ |
|
if ( !target ) |
|
return; |
|
|
|
list.RemoveAll(); |
|
for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() ); |
|
it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; |
|
it = g_pDataModel->NextAttributeReferencingElement( it ) ) |
|
{ |
|
CDmAttribute *attr = g_pDataModel->GetAttribute( it ); |
|
Assert( attr ); |
|
CDmElement *element = attr->GetOwner(); |
|
Assert( element ); |
|
if ( !element ) |
|
continue; |
|
T* t = CastElement< T >( element ); |
|
if ( !t ) |
|
continue; |
|
|
|
if ( list.Find( t ) != list.InvalidIndex() ) |
|
continue; |
|
|
|
list.AddToTail( t ); |
|
} |
|
} |
|
|
|
|
|
template< class T > |
|
T *FindAncestorReferencingElement_R( CDmElement *target ) |
|
{ |
|
if ( !target ) |
|
return NULL; |
|
|
|
CUtlRBTree< CDmElement * > visited( 0, 0, DefLessFunc( CDmElement * ) ); |
|
return FindAncestorReferencingElement_R_Impl< T >( visited, target ); |
|
} |
|
|
|
|
|
#endif // DMATTRIBUTE_H
|
|
|