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;
}
Exemple #2
0
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() );
}
GafferScene::ConstPathMatcherDataPtr BranchCreator::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->set( setName );

	ConstCompoundDataPtr mapping = boost::static_pointer_cast<const CompoundData>( mappingPlug()->getValue() );
	if( !mapping->readable().size() )
	{
		return inputSetData;
	}

	ScenePlug::ScenePath parentPath = mapping->member<InternedStringVectorData>( g_parentKey )->readable();

	ConstPathMatcherDataPtr branchSetData = computeBranchSet( parentPath, setName, context );
	if( !branchSetData )
	{
		return inputSetData;
	}

	const PathMatcher &branchSet = branchSetData->readable();
	if( branchSet.isEmpty() )
	{
		return inputSetData;
	}

	const CompoundData *forwardMapping = mapping->member<CompoundData>( g_forwardMappingKey );

	PathMatcherDataPtr outputSetData = inputSetData->copy();
	PathMatcher &outputSet = outputSetData->writable();

	vector<InternedString> outputPrefix( parentPath );
	for( PathMatcher::RawIterator pIt = branchSet.begin(), peIt = branchSet.end(); pIt != peIt; ++pIt )
	{
		const ScenePlug::ScenePath &branchPath = *pIt;
		if( !branchPath.size() )
		{
			continue; // Skip root
		}
		assert( branchPath.size() == 1 );

		const InternedStringData *outputName = forwardMapping->member<InternedStringData>( branchPath[0], /* throwExceptions = */ true );

		outputPrefix.resize( parentPath.size() + 1 );
		outputPrefix.back() = outputName->readable();
		outputSet.addPaths( branchSet.subTree( *pIt ), outputPrefix );

		pIt.prune(); // We only want to visit the first level
	}

	return outputSetData;
}
Exemple #4
0
GafferScene::ConstPathMatcherDataPtr Prune::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 = inputSetData->copy();
	PathMatcher &outputSet = outputSetData->writable();

	FilterPlug::SceneScope sceneScope( context, inPlug() );

	for( PathMatcher::RawIterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; )
	{
		sceneScope.set( ScenePlug::scenePathContextName, *pIt );
		const int m = filterPlug()->getValue();
		if( m & ( Filter::ExactMatch | Filter::AncestorMatch ) )
		{
			// This path and all below it are pruned, so we can
			// ignore it and prune the traversal to the descendant
			// paths.
			outputSet.prune( *pIt );
			pIt.prune();
			++pIt;
		}
		else if( m & Filter::DescendantMatch )
		{
			// This path isn't pruned, so we continue our traversal
			// as normal to find out which descendants _are_ pruned.
			++pIt;
		}
		else
		{
			// This path isn't pruned, and neither is anything
			// below it. We can avoid retesting the filter for
			// all descendant paths, since we know they're not
			// pruned.
			assert( m == Filter::NoMatch );
			pIt.prune();
			++pIt;
		}
	}

	return outputSetData;
}
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() );
}
Exemple #6
0
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;
}
Exemple #7
0
GafferScene::ConstPathMatcherDataPtr Isolate::computeSet( const IECore::InternedString &setName, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	ConstPathMatcherDataPtr inputSetData = inPlug()->setPlug()->getValue();
	if(
		( setName == g_lightsSetName && keepLightsPlug()->getValue() ) ||
		( setName == g_camerasSetName && keepCamerasPlug()->getValue() )
	)
	{
		return inputSetData;
	}

	const PathMatcher &inputSet = inputSetData->readable();
	if( inputSet.isEmpty() )
	{
		return inputSetData;
	}

	PathMatcherDataPtr outputSetData = inputSetData->copy();
	PathMatcher &outputSet = outputSetData->writable();

	FilterPlug::SceneScope sceneScope( context, inPlug() );

	const std::string fromString = fromPlug()->getValue();
	ScenePlug::ScenePath fromPath; ScenePlug::stringToPath( fromString, fromPath );

	const SetsToKeep setsToKeep( this );

	for( PathMatcher::RawIterator pIt = inputSet.begin(), peIt = inputSet.end(); pIt != peIt; )
	{
		sceneScope.set( ScenePlug::scenePathContextName, *pIt );
		const int m = filterPlug()->getValue() || setsToKeep.match( *pIt );
		if( m & ( Filter::ExactMatch | Filter::AncestorMatch ) )
		{
			// We want to keep everything below this point, so
			// can just prune our iteration.
			pIt.prune();
			++pIt;
		}
		else if( m & Filter::DescendantMatch )
		{
			// We might be removing things below here,
			// so just continue our iteration normally
			// so we can find out.
			++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.
				outputSet.prune( *pIt );
				pIt.prune();
			}
			++pIt;
		}
	}

	return outputSetData;
}