YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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
941k
    const char* pattern, size_t pattern_len, const char* string, size_t str_len, bool ignore_case) {
27
2.42M
  while (pattern_len > 0) {
28
2.42M
    switch (pattern[0]) {
29
306k
      case '*':
30
306k
        while (pattern[1] == '*') {
31
0
          pattern++;
32
0
          pattern_len--;
33
0
        }
34
306k
        if (pattern_len == 1) {
35
186k
          return true; /* match */
36
186k
        }
37
520k
        
while (120k
str_len > 0) {
38
460k
          if (RedisPatternMatchWithLen(
39
460k
                  pattern + 1, pattern_len - 1, string, str_len, ignore_case)) {
40
60.6k
            return true; /* match */
41
60.6k
          }
42
400k
          string++;
43
400k
          str_len--;
44
400k
        }
45
59.4k
        return false; /* no match */
46
0
        break;
47
126k
      case '?':
48
126k
        if (str_len == 0) {
49
0
          return 0; /* no match */
50
0
        }
51
126k
        string++;
52
126k
        str_len--;
53
126k
        break;
54
62.4k
      case '[': {
55
62.4k
        bool not_match, match;
56
57
62.4k
        pattern++;
58
62.4k
        pattern_len--;
59
62.4k
        not_match = pattern[0] == '^';
60
62.4k
        if (not_match) {
61
2.40k
          pattern++;
62
2.40k
          pattern_len--;
63
2.40k
        }
64
62.4k
        match = false;
65
304k
        while (true) {
66
304k
          if (pattern[0] == '\\' && 
pattern_len >= 20
) {
67
0
            pattern++;
68
0
            pattern_len--;
69
0
            if (pattern[0] == string[0]) {
70
0
              match = true;
71
0
            }
72
304k
          } else if (pattern[0] == ']') {
73
62.4k
            break;
74
242k
          } else if (pattern_len == 0) {
75
0
            pattern--;
76
0
            pattern_len++;
77
0
            break;
78
242k
          } else if (pattern[1] == '-' && 
pattern_len >= 30
) {
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
242k
          } else {
98
242k
            if (!ignore_case) {
99
242k
              if (pattern[0] == string[0]) {
100
20.4k
                match = true;
101
20.4k
              }
102
242k
            } 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
242k
          }
108
242k
          pattern++;
109
242k
          pattern_len--;
110
242k
        }
111
62.4k
        if (not_match) {
112
2.40k
          match = !match;
113
2.40k
        }
114
62.4k
        if (!match) {
115
39.6k
          return false; /* no match */
116
39.6k
        }
117
22.7k
        string++;
118
22.7k
        str_len--;
119
22.7k
        break;
120
62.4k
      }
121
60.0k
      case '\\':
122
60.0k
        if (pattern_len >= 2) {
123
60.0k
          pattern++;
124
60.0k
          pattern_len--;
125
60.0k
        }
126
60.0k
        FALLTHROUGH_INTENDED;
127
1.92M
      default:
128
1.92M
        if (!ignore_case) {
129
1.92M
          if (pattern[0] != string[0]) {
130
585k
            return false; /* no match */
131
585k
          }
132
1.92M
        } 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
0
        }
137
1.34M
        string++;
138
1.34M
        str_len--;
139
1.34M
        break;
140
2.42M
    }
141
1.49M
    pattern++;
142
1.49M
    pattern_len--;
143
1.49M
    if (str_len == 0) {
144
2.03k
      while (*pattern == '*') {
145
2
        pattern++;
146
2
        pattern_len--;
147
2
      }
148
2.03k
      break;
149
2.03k
    }
150
1.49M
  }
151
9.59k
  return pattern_len == 0 && 
str_len == 08.98k
;
152
941k
}
153
154
} // namespace
155
156
480k
bool RedisPatternMatch(const string& pattern, const string& string, bool ignore_case) {
157
480k
  return RedisPatternMatchWithLen(
158
480k
      pattern.c_str(), pattern.length(), string.c_str(), string.length(), ignore_case);
159
480k
}
160
161
} // namespace yb