StringUtils.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #include <AK/String.h>
  2. #include <AK/StringUtils.h>
  3. #include <AK/StringView.h>
  4. namespace AK {
  5. namespace StringUtils {
  6. bool matches(const StringView& str, const StringView& mask, CaseSensitivity case_sensitivity)
  7. {
  8. if (str.is_null() || mask.is_null())
  9. return str.is_null() && mask.is_null();
  10. if (case_sensitivity == CaseSensitivity::CaseInsensitive) {
  11. const String str_lower = String(str).to_lowercase();
  12. const String mask_lower = String(mask).to_lowercase();
  13. return matches(str_lower, mask_lower, CaseSensitivity::CaseSensitive);
  14. }
  15. const char* string_ptr = str.characters_without_null_termination();
  16. const char* string_end = string_ptr + str.length();
  17. const char* mask_ptr = mask.characters_without_null_termination();
  18. const char* mask_end = mask_ptr + mask.length();
  19. // Match string against mask directly unless we hit a *
  20. while ((string_ptr < string_end) && (mask_ptr < mask_end) && (*mask_ptr != '*')) {
  21. if ((*mask_ptr != *string_ptr) && (*mask_ptr != '?'))
  22. return false;
  23. mask_ptr++;
  24. string_ptr++;
  25. }
  26. const char* cp = nullptr;
  27. const char* mp = nullptr;
  28. while (string_ptr < string_end) {
  29. if ((mask_ptr < mask_end) && (*mask_ptr == '*')) {
  30. // If we have only a * left, there is no way to not match.
  31. if (++mask_ptr == mask_end)
  32. return true;
  33. mp = mask_ptr;
  34. cp = string_ptr + 1;
  35. } else if ((mask_ptr < mask_end) && ((*mask_ptr == *string_ptr) || (*mask_ptr == '?'))) {
  36. mask_ptr++;
  37. string_ptr++;
  38. } else if ((cp != nullptr) && (mp != nullptr)) {
  39. mask_ptr = mp;
  40. string_ptr = cp++;
  41. } else {
  42. break;
  43. }
  44. }
  45. // Handle any trailing mask
  46. while ((mask_ptr < mask_end) && (*mask_ptr == '*'))
  47. mask_ptr++;
  48. // If we 'ate' all of the mask and the string then we match.
  49. return (mask_ptr == mask_end) && string_ptr == string_end;
  50. }
  51. }
  52. }