Пример #1
0
void PathMatcher::matchWalk( Node *node, const NameIterator &start, const NameIterator &end, unsigned &result ) const
{
	// see if we've matched to the end of the path, and terminate the recursion if we have.
	if( start == end )
	{
		if( node->terminator )
		{
			result |= Filter::ExactMatch;
		}
		if( node->children.size() ) 
		{
			result |= Filter::DescendantMatch;
		}
		if( node->ellipsis )
		{
			result |= Filter::DescendantMatch;
			if( node->ellipsis->terminator )
			{
				result |= Filter::ExactMatch;
			}
		}
		return;
	}
		
	// we haven't matched to the end of the path - there are still path elements
	// to check. if this node is a terminator then we have found an ancestor match
	// though.
	if( node->terminator )
	{
		result |= Filter::AncestorMatch;
	}
	
	// now we can match the remainder of the path against child branches to see
	// if we have any exact or descendant matches.
	Node::ChildMapRange range = node->childRange( *start );
	if( range.first != range.second )
	{
		NameIterator newStart = start; newStart++;
		for( Node::ChildMapIterator it = range.first; it != range.second; it++ )
		{
			if( Gaffer::match( start->c_str(), it->first.c_str() ) )
			{
				matchWalk( it->second, newStart, end, result );
				// if we've found every kind of match then we can terminate early,
				// but otherwise we need to keep going even though we may
				// have found some of the match types already.
				if( result == Filter::EveryMatch )
				{
					return;
				}
			}
		}
	}
	
	if( node->ellipsis )
	{
		result |= Filter::DescendantMatch;
		if( node->ellipsis->terminator )
		{
			result |= Filter::ExactMatch;
		}
		
		NameIterator newStart = start;
		while( newStart != end )
		{
			matchWalk( node->ellipsis, newStart, end, result );
			if( result == Filter::EveryMatch )
			{
				return;
			}
			newStart++;
		}		
	}
}
Пример #2
0
void PathMatcher::matchWalk( const Node *node, const NameIterator &start, const NameIterator &end, unsigned &result ) const
{
	// see if we've matched to the end of the path, and terminate the recursion if we have.
	if( start == end )
	{
		if( node->terminator )
		{
			result |= Filter::ExactMatch;
		}
		if( node->children.size() )
		{
			result |= Filter::DescendantMatch;
		}
		if( const Node *ellipsis = node->child( g_ellipsis ) )
		{
			result |= Filter::DescendantMatch;
			if( ellipsis->terminator )
			{
				result |= Filter::ExactMatch;
			}
		}
		return;
	}

	// we haven't matched to the end of the path - there are still path elements
	// to check. if this node is a terminator then we have found an ancestor match
	// though.
	if( node->terminator )
	{
		result |= Filter::AncestorMatch;
	}

	// now we can match the remainder of the path against child branches to see
	// if we have any exact or descendant matches.
	///////////////////////////////////////////////////////////////////////////

	// first check for a child with the exact name we're looking for.
	// we can use the specialised Name constructor to explicitly say we're
	// not interested in finding a child with wildcards here - this avoids
	// a call to hasWildcards() and gives us a decent little performance boost.

	Node::ConstChildMapIterator childIt = node->children.find( Name( *start, Name::Plain ) );
	const Node::ConstChildMapIterator childItEnd = node->children.end();
	if( childIt != childItEnd )
	{
		NameIterator newStart = start + 1;
		matchWalk( childIt->second, newStart, end, result );
		// if we've found every kind of match then we can terminate early,
		// but otherwise we need to keep going even though we may
		// have found some of the match types already.
		if( result == Filter::EveryMatch )
		{
			return;
		}
	}

	// then check all the wildcarded children to see if they might match.

	const Node *ellipsis = NULL;
	for( childIt = node->wildcardsBegin(); childIt != childItEnd; ++childIt )
	{
		assert( childIt->first.type == Name::Wildcarded );
		if( childIt->first.name == g_ellipsis )
		{
			// store for use in next block.
			ellipsis = childIt->second;
			continue;
		}

		NameIterator newStart = start + 1;
		if( Gaffer::match( start->c_str(), childIt->first.name.c_str() ) )
		{
			matchWalk( childIt->second, newStart, end, result );
			if( result == Filter::EveryMatch )
			{
				return;
			}
		}
	}

	// finally check for ellipsis matches. we do this last, since it
	// is the most expensive.

	if( ellipsis )
	{
		result |= Filter::DescendantMatch;
		if( ellipsis->terminator )
		{
			result |= Filter::ExactMatch;
		}

		NameIterator newStart = start;
		while( newStart != end )
		{
			matchWalk( ellipsis, newStart, end, result );
			if( result == Filter::EveryMatch )
			{
				return;
			}
			newStart++;
		}
	}
}