/// Find an object based on its path name. /// /// @param[in] path FilePath of the object to locate. /// /// @return Pointer to the object if found, null pointer if not found. Asset* Asset::FindObject( AssetPath path ) { // Make sure the path isn't empty. if( path.IsEmpty() ) { return NULL; } // Assemble a list of object names and instance indices, from the top level on down. size_t pathDepth = 0; size_t packageDepth = 0; for( AssetPath testPath = path; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { ++pathDepth; if( testPath.IsPackage() ) { ++packageDepth; } } StackMemoryHeap<>& rStackHeap = ThreadLocalStackAllocator::GetMemoryHeap(); StackMemoryHeap<>::Marker stackMarker( rStackHeap ); Name* pPathNames = static_cast< Name* >( rStackHeap.Allocate( sizeof( Name ) * pathDepth ) ); HELIUM_ASSERT( pPathNames ); uint32_t* pInstanceIndices = static_cast< uint32_t* >( rStackHeap.Allocate( sizeof( uint32_t ) * pathDepth ) ); HELIUM_ASSERT( pInstanceIndices ); size_t pathIndex = pathDepth; for( AssetPath testPath = path; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { HELIUM_ASSERT( pathIndex != 0 ); --pathIndex; pPathNames[ pathIndex ] = testPath.GetName(); pInstanceIndices[ pathIndex ] = testPath.GetInstanceIndex(); } HELIUM_ASSERT( pathIndex == 0 ); // Search from the root. return FindChildOf( NULL, pPathNames, pInstanceIndices, pathDepth, packageDepth ); }
/// Set this path to the combination of two paths. /// /// @param[in] pRootPath Root portion of the path. /// @param[in] subPath Sub-path component. /// /// @return True if the paths could be joined into a valid path (to which this path was set), false if joining was /// invalid. bool AssetPath::Join( const char* pRootPath, AssetPath subPath ) { if( !pRootPath || pRootPath[ 0 ] == TXT( '\0' ) ) { m_pEntry = subPath.m_pEntry; return true; } // Parse the root path into a series of names. StackMemoryHeap<>& rStackHeap = ThreadLocalStackAllocator::GetMemoryHeap(); StackMemoryHeap<>::Marker stackMarker( rStackHeap ); Name* pRootPathNames; uint32_t* pRootPathIndices; size_t rootPathNameCount; size_t rootPathPackageCount; if( !Parse( pRootPath, rStackHeap, pRootPathNames, pRootPathIndices, rootPathNameCount, rootPathPackageCount ) ) { return false; } if( rootPathNameCount != rootPathPackageCount ) { AssetPath testSubPathComponent = subPath.GetParent(); AssetPath subPathComponent; do { subPathComponent = testSubPathComponent; testSubPathComponent = testSubPathComponent.GetParent(); if( subPathComponent.IsPackage() ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "AssetPath::Join(): Cannot combine \"%s\" and \"%s\" (second path is rooted in a " ) TXT( "package, while the first path ends in an object).\n" ) ), pRootPath, *subPath.ToString() ); return false; } } while( !testSubPathComponent.IsEmpty() ); } // Assemble the list of path names in reverse order for performing the object path lookup/add. size_t nameCount = rootPathNameCount; size_t packageCount = rootPathPackageCount; AssetPath testPath; for( testPath = subPath; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { ++nameCount; if( testPath.IsPackage() ) { ++packageCount; } } Name* pEntryNames = static_cast< Name* >( rStackHeap.Allocate( sizeof( Name ) * nameCount ) ); HELIUM_ASSERT( pEntryNames ); uint32_t* pInstanceIndices = static_cast< uint32_t* >( rStackHeap.Allocate( sizeof( uint32_t ) * nameCount ) ); HELIUM_ASSERT( pInstanceIndices ); Name* pCurrentName = pEntryNames; uint32_t* pCurrentIndex = pInstanceIndices; for( testPath = subPath; !testPath.IsEmpty(); testPath = testPath.GetParent() ) { *pCurrentName = testPath.GetName(); *pCurrentIndex = testPath.GetInstanceIndex(); ++pCurrentName; ++pCurrentIndex; } ArrayCopy( pCurrentName, pRootPathNames, rootPathNameCount ); ArrayCopy( pCurrentIndex, pRootPathIndices, rootPathNameCount ); // Set the path. Set( pEntryNames, pInstanceIndices, nameCount, packageCount ); return true; }