YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/redis_util.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) YugaByte, Inc.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
4
// in compliance with the License.  You may obtain a copy of the License at
5
//
6
// http://www.apache.org/licenses/LICENSE-2.0
7
//
8
// Unless required by applicable law or agreed to in writing, software distributed under the License
9
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
10
// or implied.  See the License for the specific language governing permissions and limitations
11
// under the License.
12
//
13
14
#include "yb/util/redis_util.h"
15
16
#include "yb/gutil/macros.h"
17
18
namespace yb {
19
20
using std::string;
21
22
namespace {
23
24
// Returns whether a given string matches a redis pattern. Ported from Redis.
25
bool RedisPatternMatchWithLen(
26
470k
    const char* pattern, size_t pattern_len, const char* string, size_t str_len, bool ignore_case) {
27
1.21M
  while (pattern_len > 0) {
28
1.21M
    switch (pattern[0]) {
29
153k
      case '*':
30
153k
        while (pattern[1] == '*') {
31
0
          pattern++;
32
0
          pattern_len--;
33
0
        }
34
153k
        if (pattern_len == 1) {
35
93.0k
          return true; /* match */
36
93.0k
        }
37
260k
        while (str_len > 0) {
38
230k
          if (RedisPatternMatchWithLen(
39
30.3k
                  pattern + 1, pattern_len - 1, string, str_len, ignore_case)) {
40
30.3k
            return true; /* match */
41
30.3k
          }
42
200k
          string++;
43
200k
          str_len--;
44
200k
        }
45
29.7k
        return false; /* no match */
46
0
        break;
47
63.0k
      case '?':
48
63.0k
        if (str_len == 0) {
49
0
          return 0; /* no match */
50
0
        }
51
63.0k
        string++;
52
63.0k
        str_len--;
53
63.0k
        break;
54
31.2k
      case '[': {
55
31.2k
        bool not_match, match;
56
57
31.2k
        pattern++;
58
31.2k
        pattern_len--;
59
31.2k
        not_match = pattern[0] == '^';
60
31.2k
        if (not_match) {
61
1.20k
          pattern++;
62
1.20k
          pattern_len--;
63
1.20k
        }
64
31.2k
        match = false;
65
152k
        while (true) {
66
152k
          if (pattern[0] == '\\' && pattern_len >= 2) {
67
0
            pattern++;
68
0
            pattern_len--;
69
0
            if (pattern[0] == string[0]) {
70
0
              match = true;
71
0
            }
72
152k
          } else if (pattern[0] == ']') {
73
31.2k
            break;
74
121k
          } else if (pattern_len == 0) {
75
0
            pattern--;
76
0
            pattern_len++;
77
0
            break;
78
121k
          } else if (pattern[1] == '-' && pattern_len >= 3) {
79
0
            int start = pattern[0];
80
0
            int end = pattern[2];
81
0
            int c = string[0];
82
0
            if (start > end) {
83
0
              int t = start;
84
0
              start = end;
85
0
              end = t;
86
0
            }
87
0
            if (ignore_case) {
88
0
              start = tolower(start);
89
0
              end = tolower(end);
90
0
              c = tolower(c);
91
0
            }
92
0
            pattern += 2;
93
0
            pattern_len -= 2;
94
0
            if (c >= start && c <= end) {
95
0
              match = true;
96
0
            }
97
121k
          } else {
98
121k
            if (!ignore_case) {
99
121k
              if (pattern[0] == string[0]) {
100
10.2k
                match = true;
101
10.2k
              }
102
0
            } else {
103
0
              if (tolower(static_cast<int>(pattern[0])) == tolower(static_cast<int>(string[0]))) {
104
0
                match = true;
105
0
              }
106
0
            }
107
121k
          }
108
121k
          pattern++;
109
121k
          pattern_len--;
110
121k
        }
111
31.2k
        if (not_match) {
112
1.20k
          match = !match;
113
1.20k
        }
114
31.2k
        if (!match) {
115
19.8k
          return false; /* no match */
116
19.8k
        }
117
11.3k
        string++;
118
11.3k
        str_len--;
119
11.3k
        break;
120
11.3k
      }
121
30.0k
      case '\\':
122
30.0k
        if (pattern_len >= 2) {
123
30.0k
          pattern++;
124
30.0k
          pattern_len--;
125
30.0k
        }
126
30.0k
        FALLTHROUGH_INTENDED;
127
963k
      default:
128
963k
        if (!ignore_case) {
129
963k
          if (pattern[0] != string[0]) {
130
292k
            return false; /* no match */
131
292k
          }
132
0
        } else {
133
0
          if (tolower(static_cast<int>(pattern[0])) != tolower(static_cast<int>(string[0]))) {
134
0
            return false; /* no match */
135
0
          }
136
670k
        }
137
670k
        string++;
138
670k
        str_len--;
139
670k
        break;
140
745k
    }
141
745k
    pattern++;
142
745k
    pattern_len--;
143
745k
    if (str_len == 0) {
144
1.00k
      while (*pattern == '*') {
145
0
        pattern++;
146
0
        pattern_len--;
147
0
      }
148
1.00k
      break;
149
1.00k
    }
150
745k
  }
151
4.78k
  return pattern_len == 0 && str_len == 0;
152
470k
}
153
154
} // namespace
155
156
240k
bool RedisPatternMatch(const string& pattern, const string& string, bool ignore_case) {
157
240k
  return RedisPatternMatchWithLen(
158
240k
      pattern.c_str(), pattern.length(), string.c_str(), string.length(), ignore_case);
159
240k
}
160
161
} // namespace yb