Skip to content

Commit 14759ac

Browse files
committed
The function WildcardMatch() have a new algorithm which is much faster and simpler to understand.
Modified unit tests to test both `WildcardSolve()` and `WildcardMatch()`. Completed Wildcard.h functions for issue #58.
1 parent b48acb2 commit 14759ac

File tree

3 files changed

+232
-18
lines changed

3 files changed

+232
-18
lines changed

src/Wildcard.cpp

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@ namespace shellanything
4848
return INVALID_WILDCARD_POSITION; //wildcard position not found
4949
}
5050

51-
bool IsWildcard(char c)
52-
{
53-
if (c == '*' || c == '?')
54-
return true;
55-
return false;
56-
}
57-
5851
size_t FindWildcardCharacters(const char * str, size_t * offsets, size_t offsets_size)
5952
{
6053
// Validate str
@@ -326,4 +319,80 @@ namespace shellanything
326319
return solved;
327320
}
328321

322+
bool WildcardMatch(const char * pattern, const char * value)
323+
{
324+
if (pattern == NULL || value == NULL)
325+
return false;
326+
327+
// Move forward in the pattern and the value as long as we have matching characters.
328+
bool matching_characters = true;
329+
while(matching_characters)
330+
{
331+
// If the pattern is empty, the value must also be empty to match.
332+
if (pattern[0] == '\0')
333+
{
334+
if (value[0] == '\0')
335+
return true;
336+
return false;
337+
}
338+
339+
// If the value is empty, the pattern must be '*' (or a '*' sequence) to match
340+
if (value[0] == '\0')
341+
{
342+
if (!IsStarSequence(&pattern[0]))
343+
return false;
344+
345+
// We have a match.
346+
return true;
347+
}
348+
349+
// At this point, both the pattern and the value are not empty.
350+
// Both can be moved forward if we have a match.
351+
352+
// Now check if we have a matching characters
353+
matching_characters = false;
354+
355+
// If we reached a '*' sequence, move forward in the pattern to the last '*' character of the sequence
356+
while(pattern[0] == '*' && pattern[1] == '*')
357+
{
358+
pattern++;
359+
360+
// Even if did not had 'matching characters', set the flag to true so that we run another loop.
361+
// This will allows us to check for special cases like:
362+
// 1) pattern="" and value=""
363+
// 2) pattern="*" and value=""
364+
matching_characters = true;
365+
}
366+
367+
// If the pattern contains '?', if both pattern and value characters are equals, move forward
368+
if (pattern[0] == '?' || pattern[0] == value[0])
369+
{
370+
pattern++;
371+
value++;
372+
373+
matching_characters = true;
374+
}
375+
}
376+
377+
// If we reached a '*' character in the pattern, there is two possibilities:
378+
// 1) The '*' replaces the next value character.
379+
// 2) The '*' does not replaces the next value character.
380+
// Use recursion to resolve the two possibilities.
381+
if (pattern[0] == '*')
382+
{
383+
// 1) The '*' replaces the next value character.
384+
bool match = WildcardMatch(pattern, value+1);
385+
if (match)
386+
return true;
387+
388+
// 2) The '*' does not replaces the next value character.
389+
match = WildcardMatch(pattern+1, value);
390+
if (match)
391+
return true;
392+
}
393+
394+
// No match possible
395+
return false;
396+
}
397+
329398
} //namespace shellanything

src/Wildcard.h

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,17 @@ namespace shellanything
4747
/// </summary>
4848
typedef std::vector<WILDCARD> WildcardList;
4949

50-
//struct WILDCARD_GROUP
51-
//{
52-
// char character;
53-
// IntList indexes;
54-
//};
55-
//typedef std::vector<WILDCARD_GROUP> WildcardGroupList;
56-
5750
/// <summary>
5851
/// Evaluates if the given character is a wildcard character supported by the library.
5952
/// </summary>
6053
/// <param name="c">The character to evaluate.</param>
6154
/// <returns>Returns true if the given character is a wildcard character. Returns false otherwise.</returns>
62-
bool IsWildcard(char c);
55+
inline bool IsWildcard(char c)
56+
{
57+
if (c == '*' || c == '?')
58+
return true;
59+
return false;
60+
}
6361

6462
/// <summary>
6563
/// Simplify a wildcard pattern. Remove sequences of '*' characters.
@@ -86,6 +84,8 @@ namespace shellanything
8684

8785
/// <summary>
8886
/// Returns true if the given pattern with wildcard characters can be expanded to match the given value.
87+
/// The function also returns the expanded value for each wildcard character match.
88+
/// If you do not need to know the value of the wildcard characters, use the function <see cref="WildcardMatch()"/> which is faster.
8989
/// </summary>
9090
/// <param name="pattern">The string with the wildcard pattern.</param>
9191
/// <param name="value">The value to match.</param>
@@ -94,12 +94,13 @@ namespace shellanything
9494
bool WildcardSolve(const char * pattern, const char * value, WildcardList & matches);
9595

9696
/// <summary>
97-
/// RReturns true if the given pattern with wildcard characters can be expanded to match the given value.
97+
/// Returns true if the given pattern with wildcard characters matches the given value.
98+
/// If you need to know the value of the wildcard characters, use the function <see cref="WildcardSolve()"/>.
9899
/// </summary>
99100
/// <param name="pattern">The string with the wildcard pattern.</param>
100101
/// <param name="value">The value to match.</param>
101-
/// <returns>Returns true if the given pattern with wildcard characters can be expanded to match the given value. Returns false otherwise.</returns>
102-
inline bool WildcardMatch(const char * pattern, const char * value) { WildcardList tmp; return WildcardSolve(pattern, value, tmp); }
102+
/// <returns>Returns true if the given pattern with wildcard characters matches the given value. Returns false otherwise.</returns>
103+
bool WildcardMatch(const char * pattern, const char * value);
103104

104105
} //namespace shellanything
105106

0 commit comments

Comments
 (0)