Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

768 lines
23 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef DMATTRIBUTE_H
  7. #define DMATTRIBUTE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "datamodel/attributeflags.h"
  12. #include "datamodel/idatamodel.h"
  13. #include "datamodel/dmattributetypes.h"
  14. #include "datamodel/dmelement.h"
  15. #include "datamodel/dmvar.h"
  16. #include "tier1/utlhash.h"
  17. //-----------------------------------------------------------------------------
  18. // Fast dynamic cast
  19. //-----------------------------------------------------------------------------
  20. template< class E >
  21. inline E *CastElement( CDmElement *pElement )
  22. {
  23. if ( pElement && pElement->IsA( E::GetStaticTypeSymbol() ) )
  24. return static_cast< E* >( pElement );
  25. return NULL;
  26. }
  27. //-----------------------------------------------------------------------------
  28. // type-safe element creation and accessor helpers - infers type name string from actual type
  29. //-----------------------------------------------------------------------------
  30. template< class E >
  31. inline E *GetElement( DmElementHandle_t hElement )
  32. {
  33. CDmElement *pElement = g_pDataModel->GetElement( hElement );
  34. return CastElement< E >( pElement );
  35. }
  36. //-----------------------------------------------------------------------------
  37. // Typesafe element creation + destruction
  38. //-----------------------------------------------------------------------------
  39. template< class E >
  40. inline E *CreateElement( const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
  41. {
  42. return GetElement< E >( g_pDataModel->CreateElement( E::GetStaticTypeSymbol(), pObjectName, fileid, pObjectID ) );
  43. }
  44. template< class E >
  45. inline E *CreateElement( const char *pElementType, const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL )
  46. {
  47. return GetElement< E >( g_pDataModel->CreateElement( pElementType, pObjectName, fileid, pObjectID ) );
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Used for attribute change callbacks
  51. //-----------------------------------------------------------------------------
  52. typedef unsigned short DmMailingList_t;
  53. enum
  54. {
  55. DMMAILINGLIST_INVALID = (DmMailingList_t)~0
  56. };
  57. //-----------------------------------------------------------------------------
  58. // Purpose: A general purpose pAttribute. Eventually will be extensible to arbitrary user types
  59. //-----------------------------------------------------------------------------
  60. class CDmAttribute
  61. {
  62. public:
  63. // Returns the type
  64. DmAttributeType_t GetType() const;
  65. const char *GetTypeString() const;
  66. template< class T > bool IsA() const;
  67. // Returns the name. NOTE: The utlsymbol
  68. // can be turned into a string by using g_pDataModel->String();
  69. const char *GetName() const;
  70. UtlSymId_t GetNameSymbol() const;
  71. void SetName( const char *newName );
  72. // Gets the attribute value
  73. // NOTE: GetValueUntyped is used with GetType() for use w/ SetValue( type, void* )
  74. template< class T > const T& GetValue() const;
  75. template< class T > const T& GetValue( const T& defaultValue ) const;
  76. const char *GetValueString() const;
  77. template< class E > E *GetValueElement() const;
  78. const void *GetValueUntyped() const;
  79. // Sets the attribute value
  80. template< class T > void SetValue( const T &value );
  81. template< class E > void SetValue( E* pValue );
  82. void SetValue( const void *pValue, size_t nSize );
  83. // Copies w/ type conversion (if possible) from another attribute
  84. void SetValue( const CDmAttribute *pAttribute );
  85. void SetValue( CDmAttribute *pAttribute );
  86. void SetValue( DmAttributeType_t valueType, const void *pValue );
  87. // Sets the attribute to its default value based on its type
  88. void SetToDefaultValue();
  89. // Convert to and from string
  90. void SetValueFromString( const char *pValue );
  91. const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const;
  92. // Used for element and element array attributes; it specifies which type of
  93. // elements are valid to be referred to by this attribute
  94. void SetElementTypeSymbol( UtlSymId_t typeSymbol );
  95. UtlSymId_t GetElementTypeSymbol() const;
  96. // Returns the next attribute
  97. CDmAttribute *NextAttribute();
  98. const CDmAttribute *NextAttribute() const;
  99. // Returns the owner
  100. CDmElement *GetOwner();
  101. // Methods related to flags
  102. void AddFlag( int flags );
  103. void RemoveFlag( int flags );
  104. void ClearFlags();
  105. int GetFlags() const;
  106. bool IsFlagSet( int flags ) const;
  107. // Serialization
  108. bool Serialize( CUtlBuffer &buf ) const;
  109. bool Unserialize( CUtlBuffer &buf );
  110. // Serialization of a single element.
  111. // First version of UnserializeElement adds to tail if it worked
  112. // Second version overwrites, but does not add, the element at the specified index
  113. bool SerializeElement( int nElement, CUtlBuffer &buf ) const;
  114. bool UnserializeElement( CUtlBuffer &buf );
  115. bool UnserializeElement( int nElement, CUtlBuffer &buf );
  116. // Does this attribute serialize on multiple lines?
  117. bool SerializesOnMultipleLines() const;
  118. // Get the attribute/create an attribute handle
  119. DmAttributeHandle_t GetHandle( bool bCreate = true );
  120. // Notify external elements upon change ( Calls OnAttributeChanged )
  121. // Pass false here to stop notification
  122. void NotifyWhenChanged( DmElementHandle_t h, bool bNotify );
  123. // estimate memory overhead
  124. int EstimateMemoryUsage( TraversalDepth_t depth ) const;
  125. private:
  126. // Class factory
  127. static CDmAttribute *CreateAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
  128. static CDmAttribute *CreateExternalAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pExternalMemory );
  129. static void DestroyAttribute( CDmAttribute *pAttribute );
  130. // Constructor, destructor
  131. CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
  132. CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pMemory );
  133. ~CDmAttribute();
  134. // Used when constructing CDmAttributes
  135. void Init( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName );
  136. // Used when shutting down, indicates DmAttributeHandle_t referring to this are invalid
  137. void InvalidateHandle();
  138. // Used when shutting down, indicates no more change notifications will be sent to listening elements
  139. void CleanupMailingList();
  140. // Called when the attribute changes
  141. void PreChanged();
  142. void OnChanged( bool bArrayCountChanged = false, bool bIsTopological = false );
  143. // Is modification allowed in this phase?
  144. bool ModificationAllowed() const;
  145. // Mark the attribute as being dirty
  146. bool MarkDirty();
  147. // Is the data inline in a containing element class?
  148. bool IsDataInline() const;
  149. // Allocates, frees internal data storage
  150. void CreateAttributeData();
  151. void DeleteAttributeData();
  152. // Gets at the internal data storage
  153. void* GetAttributeData();
  154. const void* GetAttributeData() const;
  155. template < class T > typename CDmAttributeInfo< T >::StorageType_t* GetData();
  156. template < class T > const typename CDmAttributeInfo< T >::StorageType_t* GetData() const;
  157. template < class T > typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData();
  158. template < class T > const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData() const;
  159. // Used by CDmElement to manage the list of attributes it owns
  160. CDmAttribute **GetNextAttributeRef();
  161. // Implementational function used for memory consumption estimation computation
  162. int EstimateMemoryUsageInternal( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ) const;
  163. // Called by elements after unserialization of their attributes is complete
  164. void OnUnserializationFinished();
  165. template< class T > bool IsTypeConvertable() const;
  166. template< class T > bool ShouldModify( const T& src );
  167. template< class T > void CopyData( const T& src );
  168. template< class T > void CopyDataOut( T& dest ) const;
  169. private:
  170. CDmAttribute *m_pNext;
  171. void *m_pData;
  172. CDmElement *m_pOwner;
  173. int m_nFlags;
  174. DmAttributeHandle_t m_Handle;
  175. CUtlSymbol m_Name;
  176. DmMailingList_t m_hMailingList;
  177. friend class CDmElement;
  178. friend class CDmAttributeAccessor;
  179. template< class T > friend class CDmrElementArray;
  180. template< class E > friend class CDmrElementArrayConst;
  181. template< class T > friend class CDmaArrayAccessor;
  182. template< class T, class B > friend class CDmrDecorator;
  183. template< class T, class B > friend class CDmrDecoratorConst;
  184. template< class T > friend class CDmArrayAttributeOp;
  185. };
  186. //-----------------------------------------------------------------------------
  187. // Inline methods
  188. //-----------------------------------------------------------------------------
  189. inline DmAttributeType_t CDmAttribute::GetType() const
  190. {
  191. return (DmAttributeType_t)( m_nFlags & FATTRIB_TYPEMASK );
  192. }
  193. template< class T > inline bool CDmAttribute::IsA() const
  194. {
  195. return GetType() == CDmAttributeInfo< T >::AttributeType();
  196. }
  197. inline const char *CDmAttribute::GetName() const
  198. {
  199. return g_pDataModel->GetString( m_Name );
  200. }
  201. inline UtlSymId_t CDmAttribute::GetNameSymbol() const
  202. {
  203. return m_Name;
  204. }
  205. //-----------------------------------------------------------------------------
  206. // Iteration
  207. //-----------------------------------------------------------------------------
  208. inline CDmAttribute *CDmAttribute::NextAttribute()
  209. {
  210. return m_pNext;
  211. }
  212. inline const CDmAttribute *CDmAttribute::NextAttribute() const
  213. {
  214. return m_pNext;
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Returns the owner
  218. //-----------------------------------------------------------------------------
  219. inline CDmElement *CDmAttribute::GetOwner()
  220. {
  221. return m_pOwner;
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Value getting methods
  225. //-----------------------------------------------------------------------------
  226. template< class T >
  227. inline const T& CDmAttribute::GetValue( const T& defaultValue ) const
  228. {
  229. if ( GetType() == ( DmAttributeType_t )( CDmAttributeInfo< T >::ATTRIBUTE_TYPE ) )
  230. return *reinterpret_cast< const T* >( m_pData );
  231. if ( IsTypeConvertable< T >() )
  232. {
  233. static T tempVal;
  234. CopyDataOut( tempVal );
  235. return tempVal;
  236. }
  237. Assert( 0 );
  238. return defaultValue;
  239. }
  240. template< class T >
  241. inline const T& CDmAttribute::GetValue() const
  242. {
  243. static CDmaVar< T > defaultVal;
  244. return GetValue( defaultVal.Get() );
  245. }
  246. inline const char *CDmAttribute::GetValueString() const
  247. {
  248. Assert( GetType() == AT_STRING );
  249. if ( GetType() != AT_STRING )
  250. return NULL;
  251. return GetValue< CUtlString >();
  252. }
  253. // used with GetType() for use w/ SetValue( type, void* )
  254. inline const void* CDmAttribute::GetValueUntyped() const
  255. {
  256. return m_pData;
  257. }
  258. template< class E >
  259. inline E* CDmAttribute::GetValueElement() const
  260. {
  261. Assert( GetType() == AT_ELEMENT );
  262. if ( GetType() == AT_ELEMENT )
  263. return GetElement<E>( this->GetValue< DmElementHandle_t >() );
  264. return NULL;
  265. }
  266. //-----------------------------------------------------------------------------
  267. // Value setting methods
  268. //-----------------------------------------------------------------------------
  269. template< class E >
  270. inline void CDmAttribute::SetValue( E* pValue )
  271. {
  272. Assert( GetType() == AT_ELEMENT );
  273. if ( GetType() == AT_ELEMENT )
  274. {
  275. SetValue( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID );
  276. }
  277. }
  278. template<>
  279. inline void CDmAttribute::SetValue( const char *pValue )
  280. {
  281. int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
  282. CUtlString str( pValue, nLen );
  283. return SetValue( str );
  284. }
  285. template<>
  286. inline void CDmAttribute::SetValue( char *pValue )
  287. {
  288. return SetValue( (const char *)pValue );
  289. }
  290. inline void CDmAttribute::SetValue( const void *pValue, size_t nSize )
  291. {
  292. CUtlBinaryBlock buf( pValue, (int)nSize );
  293. return SetValue( buf );
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Methods related to flags
  297. //-----------------------------------------------------------------------------
  298. inline void CDmAttribute::AddFlag( int nFlags )
  299. {
  300. m_nFlags |= nFlags;
  301. }
  302. inline void CDmAttribute::RemoveFlag( int nFlags )
  303. {
  304. m_nFlags &= ~nFlags;
  305. }
  306. inline void CDmAttribute::ClearFlags()
  307. {
  308. m_nFlags = 0;
  309. }
  310. inline int CDmAttribute::GetFlags() const
  311. {
  312. return m_nFlags;
  313. }
  314. inline bool CDmAttribute::IsFlagSet( int nFlags ) const
  315. {
  316. return ( nFlags & m_nFlags ) ? true : false;
  317. }
  318. inline bool CDmAttribute::IsDataInline() const
  319. {
  320. return !IsFlagSet(FATTRIB_EXTERNAL);
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Gets at the internal data storage
  324. //-----------------------------------------------------------------------------
  325. inline void* CDmAttribute::GetAttributeData()
  326. {
  327. return m_pData;
  328. }
  329. inline const void* CDmAttribute::GetAttributeData() const
  330. {
  331. return m_pData;
  332. }
  333. template < class T >
  334. inline typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData()
  335. {
  336. return ( typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
  337. }
  338. template < class T >
  339. inline typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData()
  340. {
  341. return ( typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
  342. }
  343. template < class T >
  344. inline const typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() const
  345. {
  346. return ( const typename CDmAttributeInfo< T >::StorageType_t* )m_pData;
  347. }
  348. template < class T >
  349. inline const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() const
  350. {
  351. return ( const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData;
  352. }
  353. //-----------------------------------------------------------------------------
  354. // Used by CDmElement to manage the list of attributes it owns
  355. //-----------------------------------------------------------------------------
  356. inline CDmAttribute **CDmAttribute::GetNextAttributeRef()
  357. {
  358. return &m_pNext;
  359. }
  360. //-----------------------------------------------------------------------------
  361. // helper function for determining which attributes/elements to traverse during copy/find/save/etc.
  362. //-----------------------------------------------------------------------------
  363. inline bool ShouldTraverse( const CDmAttribute *pAttr, TraversalDepth_t depth )
  364. {
  365. switch ( depth )
  366. {
  367. case TD_NONE:
  368. return false;
  369. case TD_SHALLOW:
  370. if ( !pAttr->IsFlagSet( FATTRIB_MUSTCOPY ) )
  371. return false;
  372. // fall-through intentional
  373. case TD_DEEP:
  374. if ( pAttr->IsFlagSet( FATTRIB_NEVERCOPY ) )
  375. return false;
  376. // fall-through intentional
  377. case TD_ALL:
  378. return true;
  379. }
  380. Assert( 0 );
  381. return false;
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Gets attributes
  385. //-----------------------------------------------------------------------------
  386. inline CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type )
  387. {
  388. CDmAttribute *pAttribute = FindAttribute( pAttributeName );
  389. if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
  390. return NULL;
  391. return pAttribute;
  392. }
  393. inline const CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) const
  394. {
  395. CDmAttribute *pAttribute = FindAttribute( pAttributeName );
  396. if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) )
  397. return NULL;
  398. return pAttribute;
  399. }
  400. //-----------------------------------------------------------------------------
  401. // AddAttribute calls
  402. //-----------------------------------------------------------------------------
  403. inline CDmAttribute *CDmElement::AddAttribute( const char *pAttributeName, DmAttributeType_t type )
  404. {
  405. CDmAttribute *pAttribute = FindAttribute( pAttributeName );
  406. if ( pAttribute )
  407. return ( pAttribute->GetType() == type ) ? pAttribute : NULL;
  408. pAttribute = CreateAttribute( pAttributeName, type );
  409. return pAttribute;
  410. }
  411. template< class E > inline CDmAttribute *CDmElement::AddAttributeElement( const char *pAttributeName )
  412. {
  413. CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT );
  414. if ( !pAttribute )
  415. return NULL;
  416. // FIXME: If the attribute exists but has a different element type symbol, should we complain?
  417. pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
  418. return pAttribute;
  419. }
  420. template< class E > inline CDmAttribute *CDmElement::AddAttributeElementArray( const char *pAttributeName )
  421. {
  422. CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT_ARRAY );
  423. if ( !pAttribute )
  424. return NULL;
  425. // FIXME: If the attribute exists but has a different element type symbol, should we complain?
  426. pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() );
  427. return pAttribute;
  428. }
  429. //-----------------------------------------------------------------------------
  430. // GetValue methods
  431. //-----------------------------------------------------------------------------
  432. template< class T >
  433. inline const T& CDmElement::GetValue( const char *pAttributeName ) const
  434. {
  435. static CDmaVar<T> defaultVal;
  436. return GetValue( pAttributeName, defaultVal.Get() );
  437. }
  438. inline const char *CDmElement::GetValueString( const char *pAttributeName ) const
  439. {
  440. return GetValue<CUtlString>( pAttributeName ).Get();
  441. }
  442. template< class E >
  443. inline E* CDmElement::GetValueElement( const char *pAttributeName ) const
  444. {
  445. DmElementHandle_t h = GetValue< DmElementHandle_t >( pAttributeName );
  446. return GetElement<E>( h );
  447. }
  448. template< class T >
  449. inline const T& CDmElement::GetValue( const char *pAttributeName, const T& defaultVal ) const
  450. {
  451. const CDmAttribute *pAttribute = FindAttribute( pAttributeName );
  452. if ( pAttribute != NULL )
  453. return pAttribute->GetValue<T>();
  454. return defaultVal;
  455. }
  456. //-----------------------------------------------------------------------------
  457. // SetValue methods
  458. //-----------------------------------------------------------------------------
  459. template< class T >
  460. inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const T& value )
  461. {
  462. CDmAttribute *pAttribute = FindAttribute( pAttributeName );
  463. if ( !pAttribute )
  464. {
  465. pAttribute = CreateAttribute( pAttributeName, CDmAttributeInfo<T>::AttributeType() );
  466. }
  467. if ( pAttribute )
  468. {
  469. pAttribute->SetValue( value );
  470. return pAttribute;
  471. }
  472. return NULL;
  473. }
  474. template< class E >
  475. inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, E* pElement )
  476. {
  477. DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
  478. return SetValue( pAttributeName, hElement );
  479. }
  480. template<>
  481. inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const char *pValue )
  482. {
  483. int nLen = pValue ? Q_strlen( pValue ) + 1 : 0;
  484. CUtlString str( pValue, nLen );
  485. return SetValue( pAttributeName, str );
  486. }
  487. template<>
  488. inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, char *pValue )
  489. {
  490. return SetValue( pAttributeName, (const char *)pValue );
  491. }
  492. inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const void *pValue, size_t nSize )
  493. {
  494. CUtlBinaryBlock buf( pValue, (int)nSize );
  495. return SetValue( pAttributeName, buf );
  496. }
  497. //-----------------------------------------------------------------------------
  498. // AddValue methods( set value if not found )
  499. //-----------------------------------------------------------------------------
  500. template< class T >
  501. inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const T& value )
  502. {
  503. CDmAttribute *pAttribute = GetAttribute( pAttributeName );
  504. if ( !pAttribute )
  505. return SetValue( pAttributeName, value );
  506. return pAttribute;
  507. }
  508. template< class E >
  509. inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, E* pElement )
  510. {
  511. DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID;
  512. return InitValue( pAttributeName, hElement );
  513. }
  514. inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const void *pValue, size_t size )
  515. {
  516. CDmAttribute *pAttribute = GetAttribute( pAttributeName );
  517. if ( !pAttribute )
  518. return SetValue( pAttributeName, pValue, size );
  519. return pAttribute;
  520. }
  521. template< class T >
  522. T *FindReferringElement( CDmElement *pElement, UtlSymId_t symAttrName, bool bMustBeInSameFile = true )
  523. {
  524. DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pElement->GetHandle() );
  525. while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID )
  526. {
  527. CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i );
  528. CDmElement *pDmeParent = pAttribute->GetOwner();
  529. if ( pDmeParent && pAttribute->GetNameSymbol() == symAttrName )
  530. {
  531. T *pParent = CastElement< T >( pDmeParent );
  532. if ( pParent )
  533. {
  534. if ( !bMustBeInSameFile || ( pParent->GetFileId() == pElement->GetFileId() ) )
  535. return pParent;
  536. }
  537. }
  538. i = g_pDataModel->NextAttributeReferencingElement( i );
  539. }
  540. return NULL;
  541. }
  542. template< class T >
  543. T *FindAncestorReferencingElement( CDmElement *target )
  544. {
  545. if ( !target )
  546. return NULL;
  547. for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
  548. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  549. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  550. {
  551. CDmAttribute *attr = g_pDataModel->GetAttribute( it );
  552. Assert( attr );
  553. CDmElement *element = attr->GetOwner();
  554. Assert( element );
  555. if ( !element )
  556. continue;
  557. T *t = CastElement< T >( element );
  558. if ( !t )
  559. continue;
  560. return t;
  561. }
  562. return NULL;
  563. }
  564. template< class T >
  565. T *FindAncestorReferencingElement_R_Impl( CUtlRBTree< CDmElement * >& visited, CDmElement *check )
  566. {
  567. if ( visited.Find( check ) != visited.InvalidIndex() )
  568. return NULL;
  569. visited.Insert( check );
  570. // Pass one, see if it's in this ancestor list
  571. DmAttributeReferenceIterator_t it;
  572. for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
  573. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  574. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  575. {
  576. CDmAttribute *attr = g_pDataModel->GetAttribute( it );
  577. Assert( attr );
  578. CDmElement *element = attr->GetOwner();
  579. Assert( element );
  580. if ( !element )
  581. continue;
  582. T *t = CastElement< T >( element );
  583. if ( !t )
  584. continue;
  585. return t;
  586. }
  587. for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() );
  588. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  589. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  590. {
  591. CDmAttribute *attr = g_pDataModel->GetAttribute( it );
  592. Assert( attr );
  593. CDmElement *element = attr->GetOwner();
  594. Assert( element );
  595. if ( !element )
  596. continue;
  597. T *found = FindAncestorReferencingElement_R_Impl< T >( visited, element );
  598. if ( found )
  599. return found;
  600. }
  601. return NULL;
  602. }
  603. template< class T >
  604. void FindAncestorsReferencingElement( CDmElement *target, CUtlVector< T* >& list )
  605. {
  606. if ( !target )
  607. return;
  608. list.RemoveAll();
  609. for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() );
  610. it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID;
  611. it = g_pDataModel->NextAttributeReferencingElement( it ) )
  612. {
  613. CDmAttribute *attr = g_pDataModel->GetAttribute( it );
  614. Assert( attr );
  615. CDmElement *element = attr->GetOwner();
  616. Assert( element );
  617. if ( !element )
  618. continue;
  619. T* t = CastElement< T >( element );
  620. if ( !t )
  621. continue;
  622. if ( list.Find( t ) != list.InvalidIndex() )
  623. continue;
  624. list.AddToTail( t );
  625. }
  626. }
  627. template< class T >
  628. T *FindAncestorReferencingElement_R( CDmElement *target )
  629. {
  630. if ( !target )
  631. return NULL;
  632. CUtlRBTree< CDmElement * > visited( 0, 0, DefLessFunc( CDmElement * ) );
  633. return FindAncestorReferencingElement_R_Impl< T >( visited, target );
  634. }
  635. #endif // DMATTRIBUTE_H