예제 #1
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() );
}
예제 #2
0
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;
}
예제 #3
0
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() );
}
예제 #4
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;
}