diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /sp/src/public/datamodel/dmattribute.h | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/public/datamodel/dmattribute.h')
| -rw-r--r-- | sp/src/public/datamodel/dmattribute.h | 1536 |
1 files changed, 768 insertions, 768 deletions
diff --git a/sp/src/public/datamodel/dmattribute.h b/sp/src/public/datamodel/dmattribute.h index 5bf016f0..e4441ff9 100644 --- a/sp/src/public/datamodel/dmattribute.h +++ b/sp/src/public/datamodel/dmattribute.h @@ -1,768 +1,768 @@ -//========= 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, 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, 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
+//========= 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, 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, 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 |