summaryrefslogtreecommitdiff
path: root/AK/String.cpp
diff options
context:
space:
mode:
authorRobin Burchell <robin+git@viroteck.net>2019-05-26 20:36:16 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-28 00:17:39 +0200
commit9947ee9566ac1ba6a5bb9f3ea31879154d9b42fc (patch)
tree07f740418e542f90e653b987ae66bfce1c3dc45c /AK/String.cpp
parent4040c6137d58a6ed7fa83c5d45617070fd001215 (diff)
downloadserenity-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.cpp54
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;
+}
+
}