diff options
author | Robin Burchell <robin+git@viroteck.net> | 2019-05-26 20:36:16 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-05-28 00:17:39 +0200 |
commit | 9947ee9566ac1ba6a5bb9f3ea31879154d9b42fc (patch) | |
tree | 07f740418e542f90e653b987ae66bfce1c3dc45c /AK/String.cpp | |
parent | 4040c6137d58a6ed7fa83c5d45617070fd001215 (diff) | |
download | serenity-9947ee9566ac1ba6a5bb9f3ea31879154d9b42fc.zip |
Shell: Allow * and ? wildcard expansion in arguments
Should also presumably allow for escaping and such, but this is a start.
Fixes #112.
Diffstat (limited to 'AK/String.cpp')
-rw-r--r-- | AK/String.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/AK/String.cpp b/AK/String.cpp index 3298e833aa..8544e4c98a 100644 --- a/AK/String.cpp +++ b/AK/String.cpp @@ -196,4 +196,58 @@ String String::repeated(char ch, int count) return *impl; } +bool String::matches(const String& mask, CaseSensitivity case_sensitivity) const +{ + if (case_sensitivity == CaseSensitivity::CaseInsensitive) { + String this_lower = this->to_lowercase(); + String mask_lower = mask.to_lowercase(); + return this_lower.match_helper(mask_lower); + } + + return match_helper(mask); +} + +bool String::match_helper(const String& mask) const +{ + if (is_null() || mask.is_null()) + return false; + + const char* string_ptr = characters(); + const char* mask_ptr = mask.characters(); + + // Match string against mask directly unless we hit a * + while ((*string_ptr) && (*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) { + if (*mask_ptr == '*') { + // If we have only a * left, there is no way to not match. + if (!*++mask_ptr) + return true; + mp = mask_ptr; + cp = string_ptr+1; + } else if ((*mask_ptr == *string_ptr) || (*mask_ptr == '?')) { + mask_ptr++; + string_ptr++; + } else { + mask_ptr = mp; + string_ptr = cp++; + } + } + + // Handle any trailing mask + while (*mask_ptr == '*') + mask_ptr++; + + // If we 'ate' all of the mask then we match. + return !*mask_ptr; +} + } |