forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AK: Move the wildcard-matching implementation to StringUtils
Provide wrappers in the String and StringView classes, and add some tests.
- Loading branch information
1 parent
2a30a02
commit 055344f
Showing
16 changed files
with
147 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#include <AK/String.h> | ||
#include <AK/StringUtils.h> | ||
#include <AK/StringView.h> | ||
|
||
namespace AK { | ||
|
||
namespace StringUtils { | ||
|
||
bool matches(const StringView& str, const StringView& mask, CaseSensitivity case_sensitivity) | ||
{ | ||
if (str.is_null() || mask.is_null()) | ||
return str.is_null() && mask.is_null(); | ||
|
||
if (case_sensitivity == CaseSensitivity::CaseInsensitive) { | ||
const String str_lower = String(str).to_lowercase(); | ||
const String mask_lower = String(mask).to_lowercase(); | ||
return matches(str_lower, mask_lower, CaseSensitivity::CaseSensitive); | ||
} | ||
|
||
const char* string_ptr = str.characters_without_null_termination(); | ||
const char* string_end = string_ptr + str.length(); | ||
const char* mask_ptr = mask.characters_without_null_termination(); | ||
const char* mask_end = mask_ptr + mask.length(); | ||
|
||
// Match string against mask directly unless we hit a * | ||
while ((string_ptr < string_end) && (mask_ptr < mask_end) && (*mask_ptr != '*')) { | ||
if ((*mask_ptr != *string_ptr) && (*mask_ptr != '?')) | ||
return false; | ||
mask_ptr++; | ||
string_ptr++; | ||
} | ||
|
||
const char* cp = nullptr; | ||
const char* mp = nullptr; | ||
|
||
while (string_ptr < string_end) { | ||
if ((mask_ptr < mask_end) && (*mask_ptr == '*')) { | ||
// If we have only a * left, there is no way to not match. | ||
if (++mask_ptr == mask_end) | ||
return true; | ||
mp = mask_ptr; | ||
cp = string_ptr + 1; | ||
} else if ((mask_ptr < mask_end) && ((*mask_ptr == *string_ptr) || (*mask_ptr == '?'))) { | ||
mask_ptr++; | ||
string_ptr++; | ||
} else if ((cp != nullptr) && (mp != nullptr)) { | ||
mask_ptr = mp; | ||
string_ptr = cp++; | ||
} else { | ||
break; | ||
} | ||
} | ||
|
||
// Handle any trailing mask | ||
while ((mask_ptr < mask_end) && (*mask_ptr == '*')) | ||
mask_ptr++; | ||
|
||
// If we 'ate' all of the mask and the string then we match. | ||
return (mask_ptr == mask_end) && string_ptr == string_end; | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#pragma once | ||
|
||
#include <AK/Forward.h> | ||
|
||
namespace AK { | ||
|
||
enum class CaseSensitivity { | ||
CaseInsensitive, | ||
CaseSensitive, | ||
}; | ||
|
||
namespace StringUtils { | ||
|
||
bool matches(const StringView& str, const StringView& mask, CaseSensitivity = CaseSensitivity::CaseInsensitive); | ||
|
||
} | ||
|
||
} | ||
|
||
using AK::CaseSensitivity; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#include <AK/StringUtils.h> | ||
#include <AK/TestSuite.h> | ||
|
||
TEST_CASE(matches_null) | ||
{ | ||
EXPECT(AK::StringUtils::matches(StringView(), StringView())); | ||
|
||
EXPECT(!AK::StringUtils::matches(StringView(), "")); | ||
EXPECT(!AK::StringUtils::matches(StringView(), "*")); | ||
EXPECT(!AK::StringUtils::matches(StringView(), "?")); | ||
EXPECT(!AK::StringUtils::matches(StringView(), "a")); | ||
|
||
EXPECT(!AK::StringUtils::matches("", StringView())); | ||
EXPECT(!AK::StringUtils::matches("a", StringView())); | ||
} | ||
|
||
TEST_CASE(matches_empty) | ||
{ | ||
EXPECT(AK::StringUtils::matches("", "")); | ||
|
||
EXPECT(AK::StringUtils::matches("", "*")); | ||
EXPECT(!AK::StringUtils::matches("", "?")); | ||
EXPECT(!AK::StringUtils::matches("", "a")); | ||
|
||
EXPECT(!AK::StringUtils::matches("a", "")); | ||
} | ||
|
||
TEST_CASE(matches_case_sensitive) | ||
{ | ||
EXPECT(AK::StringUtils::matches("a", "a", CaseSensitivity::CaseSensitive)); | ||
EXPECT(!AK::StringUtils::matches("a", "A", CaseSensitivity::CaseSensitive)); | ||
EXPECT(!AK::StringUtils::matches("A", "a", CaseSensitivity::CaseSensitive)); | ||
} | ||
|
||
TEST_CASE(matches_case_insensitive) | ||
{ | ||
EXPECT(!AK::StringUtils::matches("aa", "a")); | ||
EXPECT(AK::StringUtils::matches("aa", "*")); | ||
EXPECT(!AK::StringUtils::matches("cb", "?a")); | ||
EXPECT(AK::StringUtils::matches("adceb", "a*b")); | ||
EXPECT(!AK::StringUtils::matches("acdcb", "a*c?b")); | ||
} | ||
|
||
TEST_MAIN(StringUtils) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters