in source/core_mqtt.c [425:526]
static bool matchWildcards( const char * pTopicName,
uint16_t topicNameLength,
const char * pTopicFilter,
uint16_t topicFilterLength,
uint16_t * pNameIndex,
uint16_t * pFilterIndex,
bool * pMatch )
{
bool shouldStopMatching = false;
bool locationIsValidForWildcard;
assert( pTopicName != NULL );
assert( topicNameLength != 0 );
assert( pTopicFilter != NULL );
assert( topicFilterLength != 0 );
assert( pNameIndex != NULL );
assert( pFilterIndex != NULL );
assert( pMatch != NULL );
/* Wild card in a topic filter is only valid either at the starting position
* or when it is preceded by a '/'.*/
locationIsValidForWildcard = ( ( *pFilterIndex == 0u ) ||
( pTopicFilter[ *pFilterIndex - 1U ] == '/' )
) ? true : false;
if( ( pTopicFilter[ *pFilterIndex ] == '+' ) && ( locationIsValidForWildcard == true ) )
{
bool nextLevelExistsInTopicName = false;
bool nextLevelExistsinTopicFilter = false;
/* Move topic name index to the end of the current level. The end of the
* current level is identified by the last character before the next level
* separator '/'. */
while( *pNameIndex < topicNameLength )
{
/* Exit the loop if we hit the level separator. */
if( pTopicName[ *pNameIndex ] == '/' )
{
nextLevelExistsInTopicName = true;
break;
}
( *pNameIndex )++;
}
/* Determine if the topic filter contains a child level after the current level
* represented by the '+' wildcard. */
if( ( *pFilterIndex < ( topicFilterLength - 1U ) ) &&
( pTopicFilter[ *pFilterIndex + 1U ] == '/' ) )
{
nextLevelExistsinTopicFilter = true;
}
/* If the topic name contains a child level but the topic filter ends at
* the current level, then there does not exist a match. */
if( ( nextLevelExistsInTopicName == true ) &&
( nextLevelExistsinTopicFilter == false ) )
{
*pMatch = false;
shouldStopMatching = true;
}
/* If the topic name and topic filter have child levels, then advance the
* filter index to the level separator in the topic filter, so that match
* can be performed in the next level.
* Note: The name index already points to the level separator in the topic
* name. */
else if( nextLevelExistsInTopicName == true )
{
( *pFilterIndex )++;
}
else
{
/* If we have reached here, the the loop terminated on the
* ( *pNameIndex < topicNameLength) condition, which means that have
* reached past the end of the topic name, and thus, we decrement the
* index to the last character in the topic name.*/
( *pNameIndex )--;
}
}
/* '#' matches everything remaining in the topic name. It must be the
* last character in a topic filter. */
else if( ( pTopicFilter[ *pFilterIndex ] == '#' ) &&
( *pFilterIndex == ( topicFilterLength - 1U ) ) &&
( locationIsValidForWildcard == true ) )
{
/* Subsequent characters don't need to be checked for the
* multi-level wildcard. */
*pMatch = true;
shouldStopMatching = true;
}
else
{
/* Any character mismatch other than '+' or '#' means the topic
* name does not match the topic filter. */
*pMatch = false;
shouldStopMatching = true;
}
return shouldStopMatching;
}