void GafferSceneTest::testPathMatcherRawIterator() { vector<InternedString> root; vector<InternedString> a = assign::list_of( "a" ); vector<InternedString> ab = assign::list_of( "a" )( "b" ); vector<InternedString> abc = assign::list_of( "a" )( "b" )( "c" ); PathMatcher m; PathMatcher::RawIterator it = m.begin(); GAFFERTEST_ASSERT( it == m.end() ); m.addPath( abc ); it = m.begin(); GAFFERTEST_ASSERT( *it == root ); GAFFERTEST_ASSERT( it.exactMatch() == false ); GAFFERTEST_ASSERT( it != m.end() ); ++it; GAFFERTEST_ASSERT( *it == a ); GAFFERTEST_ASSERT( it.exactMatch() == false ); GAFFERTEST_ASSERT( it != m.end() ); ++it; GAFFERTEST_ASSERT( *it == ab ); GAFFERTEST_ASSERT( it.exactMatch() == false ); GAFFERTEST_ASSERT( it != m.end() ); ++it; GAFFERTEST_ASSERT( *it == abc ); GAFFERTEST_ASSERT( it.exactMatch() == true ); GAFFERTEST_ASSERT( it != m.end() ); ++it; GAFFERTEST_ASSERT( it == m.end() ); }
MurmurHash SharedDataHolder<PathMatcher>::hash() const { IECore::MurmurHash result; HashStack stack; PathMatcher m = readable(); for( PathMatcher::RawIterator it = m.begin(), eIt = m.end(); it != eIt; ++it ) { // The iterator is recursive, so we use a stack to keep // track of where we are. Resize the stack to match our // current depth. The required size has the +1 because // we need a stack entry for the root item. size_t requiredStackSize = it->size() + 1; if( requiredStackSize > stack.size() ) { // Going a level deeper. stack.push( HashNodes() ); assert( stack.size() == requiredStackSize ); } else if( requiredStackSize < stack.size() ) { // Returning from recursion to the child nodes. // Output the hashes for the children we visited // and stored on the stack previously. popHashNodes( stack, requiredStackSize, result ); } stack.top().push_back( HashNode( it->size() ? it->back().c_str() : "", it.exactMatch() ) ); } popHashNodes( stack, 0, result ); return result; }
void PathMatcherData::save( SaveContext *context ) const { Data::save( context ); IndexedIOPtr container = context->container( staticTypeName(), g_ioVersion ); std::vector<InternedString> strings; std::vector<unsigned int> pathLengths; std::vector<unsigned char> exactMatches; for( PathMatcher::RawIterator it = readable().begin(), eIt = readable().end(); it != eIt; ++it ) { pathLengths.push_back( it->size() ); if( it->size() ) { strings.push_back( it->back() ); } exactMatches.push_back( it.exactMatch() ); } container->write( "strings", strings.data(), strings.size() ); container->write( "pathLengths", pathLengths.data(), pathLengths.size() ); container->write( "exactMatches", exactMatches.data(), exactMatches.size() ); }
GafferScene::ConstPathMatcherDataPtr Isolate::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstPathMatcherDataPtr inputSetData = inPlug()->setPlug()->getValue(); const PathMatcher &inputSet = inputSetData->readable(); if( inputSet.isEmpty() ) { return inputSetData; } PathMatcherDataPtr outputSetData = new PathMatcherData; PathMatcher &outputSet = outputSetData->writable(); ContextPtr tmpContext = filterContext( context ); Context::Scope scopedContext( tmpContext.get() ); const std::string fromString = fromPlug()->getValue(); ScenePlug::ScenePath fromPath; ScenePlug::stringToPath( fromString, fromPath ); for( PathMatcher::RawIterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; ) { tmpContext->set( ScenePlug::scenePathContextName, *pIt ); const int m = filterPlug()->getValue(); if( m & ( Filter::ExactMatch | Filter::AncestorMatch ) ) { // We want to keep everything below this point, and // we can speed things up by not checking the filter // for our descendants. PathMatcher::RawIterator next = pIt; next.prune(); ++next; while( pIt != next ) { if( pIt.exactMatch() ) { outputSet.addPath( *pIt ); } ++pIt; } } else if( m & Filter::DescendantMatch ) { // We might be removing things below here, // so just continue our iteration normally // so we can find out. if( pIt.exactMatch() ) { outputSet.addPath( *pIt ); } ++pIt; } else { assert( m == Filter::NoMatch ); if( boost::starts_with( *pIt, fromPath ) ) { // Not going to keep anything below // here, so we can prune traversal // entirely. pIt.prune(); } else if( pIt.exactMatch() ) { outputSet.addPath( *pIt ); } ++pIt; } } return outputSetData; }