fnmatch.cc 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright 2023 The Abseil Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // https://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "absl/log/internal/fnmatch.h"
  15. #include <cstddef>
  16. #include "absl/base/config.h"
  17. #include "absl/strings/string_view.h"
  18. namespace absl {
  19. ABSL_NAMESPACE_BEGIN
  20. namespace log_internal {
  21. bool FNMatch(absl::string_view pattern, absl::string_view str) {
  22. bool in_wildcard_match = false;
  23. while (true) {
  24. if (pattern.empty()) {
  25. // `pattern` is exhausted; succeed if all of `str` was consumed matching
  26. // it.
  27. return in_wildcard_match || str.empty();
  28. }
  29. if (str.empty()) {
  30. // `str` is exhausted; succeed if `pattern` is empty or all '*'s.
  31. return pattern.find_first_not_of('*') == pattern.npos;
  32. }
  33. switch (pattern.front()) {
  34. case '*':
  35. pattern.remove_prefix(1);
  36. in_wildcard_match = true;
  37. break;
  38. case '?':
  39. pattern.remove_prefix(1);
  40. str.remove_prefix(1);
  41. break;
  42. default:
  43. if (in_wildcard_match) {
  44. absl::string_view fixed_portion = pattern;
  45. const size_t end = fixed_portion.find_first_of("*?");
  46. if (end != fixed_portion.npos) {
  47. fixed_portion = fixed_portion.substr(0, end);
  48. }
  49. const size_t match = str.find(fixed_portion);
  50. if (match == str.npos) {
  51. return false;
  52. }
  53. pattern.remove_prefix(fixed_portion.size());
  54. str.remove_prefix(match + fixed_portion.size());
  55. in_wildcard_match = false;
  56. } else {
  57. if (pattern.front() != str.front()) {
  58. return false;
  59. }
  60. pattern.remove_prefix(1);
  61. str.remove_prefix(1);
  62. }
  63. break;
  64. }
  65. }
  66. }
  67. } // namespace log_internal
  68. ABSL_NAMESPACE_END
  69. } // namespace absl