//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //============================================================================= #include "dmxserializationdictionary.h" #include "dmxloader/dmxelement.h" #include "dmxloader/dmxattribute.h" //----------------------------------------------------------------------------- // // Element dictionary used in serialization // //----------------------------------------------------------------------------- CDmxSerializationDictionary::CDmxSerializationDictionary( int nElementsHint /* = 0 */ ) : m_Dict( 0, nElementsHint, CDmxSerializationDictionary::LessFunc ) { } //----------------------------------------------------------------------------- // Used to sort the list of elements //----------------------------------------------------------------------------- bool CDmxSerializationDictionary::LessFunc( const DmxElementInfo_t &lhs, const DmxElementInfo_t &rhs ) { return lhs.m_pElement < rhs.m_pElement; } //----------------------------------------------------------------------------- // Finds the handle of the element //----------------------------------------------------------------------------- DmxSerializationHandle_t CDmxSerializationDictionary::Find( CDmxElement *pElement ) { DmxElementInfo_t find; find.m_pElement = pElement; return m_Dict.Find( find ); } //----------------------------------------------------------------------------- // Creates the list of all things to serialize //----------------------------------------------------------------------------- void CDmxSerializationDictionary::BuildElementList_R( CDmxElement *pElement, bool bFlatMode, bool bIsRoot ) { if ( !pElement ) return; // FIXME: Right here we should ask the element if it's an external // file reference and exit immediately if so. // This means we've already encountered this guy. // Therefore, he can never be a root element DmxSerializationHandle_t h = Find( pElement ); if ( h != m_Dict.InvalidIndex() ) { m_Dict[h].m_bRoot = true; return; } DmxElementInfo_t info; info.m_bRoot = bFlatMode || bIsRoot; info.m_pElement = pElement; m_Dict.Insert( info ); int nCount = pElement->AttributeCount(); for ( int i = 0; i < nCount; ++i ) { CDmxAttribute *pAttribute = pElement->GetAttribute(i); switch( pAttribute->GetType() ) { case AT_ELEMENT: { CDmxElement *pChild = pAttribute->GetValue(); if ( !pChild ) break; BuildElementList_R( pChild, bFlatMode, false ); } break; case AT_ELEMENT_ARRAY: { const CUtlVector &array = pAttribute->GetArray( ); int nCountArray = array.Count(); for ( int j = 0; j < nCountArray; ++j ) { CDmxElement *pChild = array[ j ]; if ( !pChild ) break; BuildElementList_R( pChild, bFlatMode, false ); } } break; } } } void CDmxSerializationDictionary::BuildElementList( CDmxElement *pElement, bool bFlatMode ) { BuildElementList_R( pElement, bFlatMode, true ); } //----------------------------------------------------------------------------- // Should I inline the serialization of this element? //----------------------------------------------------------------------------- bool CDmxSerializationDictionary::ShouldInlineElement( CDmxElement *pElement ) { // This means we've already encountered this guy. // Therefore, he can never be a root element DmxSerializationHandle_t h = Find( pElement ); if ( h != m_Dict.InvalidIndex() ) return !m_Dict[h].m_bRoot; // If we didn't find the element, it means it's a reference to an external // element (or it's NULL), so don't inline ie. return false; } //----------------------------------------------------------------------------- // Clears the dictionary //----------------------------------------------------------------------------- void CDmxSerializationDictionary::Clear() { m_Dict.RemoveAll(); } //----------------------------------------------------------------------------- // How many root elements do we have? //----------------------------------------------------------------------------- int CDmxSerializationDictionary::RootElementCount() const { int nCount = 0; DmxSerializationHandle_t h = m_Dict.FirstInorder(); while( h != m_Dict.InvalidIndex() ) { if ( m_Dict[h].m_bRoot ) { ++nCount; } h = m_Dict.NextInorder( h ); } return nCount; } //----------------------------------------------------------------------------- // Iterates over all root elements to serialize //----------------------------------------------------------------------------- DmxSerializationHandle_t CDmxSerializationDictionary::FirstRootElement() const { // NOTE: I don't have to use First/NextInorder here because there // are guaranteed to be no removals from the dictionary. // Also, using inorder traversal won't get my actual root element to be first in the file int nCount = m_Dict.Count(); for ( DmxSerializationHandle_t h = 0; h < nCount; ++h ) { if ( m_Dict[h].m_bRoot ) return h; } return DMX_SERIALIZATION_HANDLE_INVALID; } DmxSerializationHandle_t CDmxSerializationDictionary::NextRootElement( DmxSerializationHandle_t h ) const { ++h; int nCount = m_Dict.Count(); for ( ; h < nCount; ++h ) { if ( m_Dict[h].m_bRoot ) return h; } return DMX_SERIALIZATION_HANDLE_INVALID; } CDmxElement *CDmxSerializationDictionary::GetRootElement( DmxSerializationHandle_t h ) { Assert( m_Dict[h].m_bRoot ); return m_Dict[h].m_pElement; }