aboutsummaryrefslogtreecommitdiff
path: root/sp/src/public/datamodel/dmattribute.h
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /sp/src/public/datamodel/dmattribute.h
parentMark some more files as text. (diff)
downloadsource-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.h1536
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