xref: /aosp_15_r20/external/angle/third_party/abseil-cpp/absl/log/internal/fnmatch.cc (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 
15 #include "absl/log/internal/fnmatch.h"
16 
17 #include <cstddef>
18 
19 #include "absl/base/config.h"
20 #include "absl/strings/string_view.h"
21 
22 namespace absl {
23 ABSL_NAMESPACE_BEGIN
24 namespace log_internal {
FNMatch(absl::string_view pattern,absl::string_view str)25 bool FNMatch(absl::string_view pattern, absl::string_view str) {
26   bool in_wildcard_match = false;
27   while (true) {
28     if (pattern.empty()) {
29       // `pattern` is exhausted; succeed if all of `str` was consumed matching
30       // it.
31       return in_wildcard_match || str.empty();
32     }
33     if (str.empty()) {
34       // `str` is exhausted; succeed if `pattern` is empty or all '*'s.
35       return pattern.find_first_not_of('*') == pattern.npos;
36     }
37     switch (pattern.front()) {
38       case '*':
39         pattern.remove_prefix(1);
40         in_wildcard_match = true;
41         break;
42       case '?':
43         pattern.remove_prefix(1);
44         str.remove_prefix(1);
45         break;
46       default:
47         if (in_wildcard_match) {
48           absl::string_view fixed_portion = pattern;
49           const size_t end = fixed_portion.find_first_of("*?");
50           if (end != fixed_portion.npos) {
51             fixed_portion = fixed_portion.substr(0, end);
52           }
53           const size_t match = str.find(fixed_portion);
54           if (match == str.npos) {
55             return false;
56           }
57           pattern.remove_prefix(fixed_portion.size());
58           str.remove_prefix(match + fixed_portion.size());
59           in_wildcard_match = false;
60         } else {
61           if (pattern.front() != str.front()) {
62             return false;
63           }
64           pattern.remove_prefix(1);
65           str.remove_prefix(1);
66         }
67         break;
68     }
69   }
70 }
71 }  // namespace log_internal
72 ABSL_NAMESPACE_END
73 }  // namespace absl
74