GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/pathspec/pathspec_pattern.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 147 149 98.7%
Branches: 134 182 73.6%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "cvmfs_config.h"
6 #include "pathspec_pattern.h"
7
8 #include <cassert>
9
10 #include "pathspec/pathspec.h"
11
12 363 PathspecElementPattern::PathspecElementPattern(
13 const std::string::const_iterator begin,
14 363 const std::string::const_iterator &end)
15 363 : valid_(true)
16 {
17
1/2
✓ Branch 1 taken 363 times.
✗ Branch 2 not taken.
363 Parse(begin, end);
18 363 }
19
20 1049 PathspecElementPattern::PathspecElementPattern(
21 1049 const PathspecElementPattern& other)
22 1049 : valid_(other.valid_)
23 {
24
1/2
✓ Branch 2 taken 1049 times.
✗ Branch 3 not taken.
1049 subpatterns_.reserve(other.subpatterns_.size());
25 1049 SubPatterns::const_iterator i = other.subpatterns_.begin();
26 1049 SubPatterns::const_iterator iend = other.subpatterns_.end();
27
2/2
✓ Branch 1 taken 1174 times.
✓ Branch 2 taken 1049 times.
2223 for (; i != iend; ++i) {
28
2/4
✓ Branch 2 taken 1174 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1174 times.
✗ Branch 6 not taken.
1174 subpatterns_.push_back((*i)->Clone());
29 }
30 1049 }
31
32 7 PathspecElementPattern& PathspecElementPattern::operator=(
33 const PathspecElementPattern& other)
34 {
35
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (this != &other) {
36 7 valid_ = other.valid_;
37 7 subpatterns_.clear();
38
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 subpatterns_.reserve(other.subpatterns_.size());
39 7 SubPatterns::const_iterator i = other.subpatterns_.begin();
40 7 SubPatterns::const_iterator iend = other.subpatterns_.end();
41
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 7 times.
18 for (; i != iend; ++i) {
42
2/4
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
11 subpatterns_.push_back((*i)->Clone());
43 }
44 }
45
46 7 return *this;
47 }
48
49
50 1412 PathspecElementPattern::~PathspecElementPattern() {
51 1412 SubPatterns::const_iterator i = subpatterns_.begin();
52 1412 SubPatterns::const_iterator iend = subpatterns_.end();
53
2/2
✓ Branch 2 taken 1611 times.
✓ Branch 3 taken 1412 times.
3023 for (; i != iend; ++i) {
54
1/2
✓ Branch 1 taken 1611 times.
✗ Branch 2 not taken.
1611 delete *i;
55 }
56 1412 subpatterns_.clear();
57 1412 }
58
59
60 363 void PathspecElementPattern::Parse(const std::string::const_iterator &begin,
61 const std::string::const_iterator &end) {
62 363 std::string::const_iterator i = begin;
63
2/2
✓ Branch 1 taken 434 times.
✓ Branch 2 taken 363 times.
797 while (i != end) {
64 434 SubPattern* next = (Pathspec::IsSpecialChar(*i))
65
3/4
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 337 times.
✓ Branch 3 taken 97 times.
✗ Branch 4 not taken.
434 ? ParseSpecialChar(end, &i)
66
1/2
✓ Branch 1 taken 337 times.
✗ Branch 2 not taken.
337 : ParsePlaintext(end, &i);
67
3/4
✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 433 times.
434 if (next->IsEmpty()) {
68 1 valid_ = false;
69
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 delete next;
70 } else {
71
1/2
✓ Branch 1 taken 433 times.
✗ Branch 2 not taken.
433 subpatterns_.push_back(next);
72 }
73 }
74 363 }
75
76
77 337 PathspecElementPattern::SubPattern* PathspecElementPattern::ParsePlaintext(
78 const std::string::const_iterator &end,
79 std::string::const_iterator *i
80 ) {
81 337 PlaintextSubPattern *pattern = new PlaintextSubPattern();
82 337 bool next_is_escaped = false;
83
84
2/2
✓ Branch 1 taken 1466 times.
✓ Branch 2 taken 310 times.
1776 while (*i < end) {
85
6/6
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1426 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 27 times.
✓ Branch 7 taken 1439 times.
1466 if (Pathspec::IsSpecialChar(**i) && !next_is_escaped) {
86 27 break;
87 }
88
89
6/6
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 1416 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 19 times.
✓ Branch 6 taken 1420 times.
1439 if (**i == Pathspec::kEscaper && !next_is_escaped) {
90 19 next_is_escaped = true;
91
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1395 times.
1420 } else if (next_is_escaped) {
92
6/6
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 13 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 17 times.
✓ Branch 8 taken 8 times.
25 if (Pathspec::IsSpecialChar(**i) || **i == Pathspec::kEscaper) {
93 17 pattern->AddChar(**i);
94 17 next_is_escaped = false;
95 } else {
96 8 valid_ = false;
97 }
98 } else {
99
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1395 times.
1395 assert(!Pathspec::IsSpecialChar(**i));
100 1395 pattern->AddChar(**i);
101 }
102
103 1439 ++(*i);
104 }
105
106 337 return pattern;
107 }
108
109 97 PathspecElementPattern::SubPattern* PathspecElementPattern::ParseSpecialChar(
110 const std::string::const_iterator &end,
111 std::string::const_iterator *i
112 ) {
113
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 97 times.
97 assert(Pathspec::IsSpecialChar(**i));
114 97 const char chr = **i;
115 97 ++(*i);
116
117
2/3
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
97 switch (chr) {
118 57 case Pathspec::kWildcard:
119 57 return new WildcardSubPattern();
120 40 case Pathspec::kPlaceholder:
121 40 return new PlaceholderSubPattern();
122 default:
123 assert(false && "unrecognized special character");
124 }
125 }
126
127 227 std::string PathspecElementPattern::GenerateRegularExpression(
128 const bool is_relaxed) const {
129 227 std::string result;
130 227 SubPatterns::const_iterator i = subpatterns_.begin();
131 227 const SubPatterns::const_iterator iend = subpatterns_.end();
132
2/2
✓ Branch 1 taken 284 times.
✓ Branch 2 taken 227 times.
511 for (; i != iend; ++i) {
133
2/4
✓ Branch 2 taken 284 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 284 times.
✗ Branch 6 not taken.
284 result += (*i)->GenerateRegularExpression(is_relaxed);
134 }
135 454 return result;
136 }
137
138 34 std::string PathspecElementPattern::GenerateGlobString() const {
139 34 std::string result;
140 34 SubPatterns::const_iterator i = subpatterns_.begin();
141 34 const SubPatterns::const_iterator iend = subpatterns_.end();
142
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 34 times.
74 for (; i != iend; ++i) {
143
2/4
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
40 result += (*i)->GenerateGlobString();
144 }
145 68 return result;
146 }
147
148 102 bool PathspecElementPattern::operator== (
149 const PathspecElementPattern &other) const
150 {
151
5/6
✓ Branch 2 taken 92 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 92 times.
✓ Branch 6 taken 10 times.
✓ Branch 7 taken 92 times.
194 if (subpatterns_.size() != other.subpatterns_.size() ||
152 92 IsValid() != other.IsValid()) {
153 10 return false;
154 }
155
156 92 SubPatterns::const_iterator i = subpatterns_.begin();
157 92 const SubPatterns::const_iterator iend = subpatterns_.end();
158 92 SubPatterns::const_iterator j = other.subpatterns_.begin();
159 92 const SubPatterns::const_iterator jend = other.subpatterns_.end();
160
161
5/6
✓ Branch 3 taken 106 times.
✓ Branch 4 taken 69 times.
✓ Branch 6 taken 106 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 106 times.
✓ Branch 9 taken 69 times.
175 for (; i != iend && j != jend; ++i, ++j) {
162
3/4
✓ Branch 3 taken 106 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 23 times.
✓ Branch 6 taken 83 times.
106 if (!(*i)->Compare(*j)) {
163 23 return false;
164 }
165 }
166
167 69 return true;
168 }
169
170
171 //------------------------------------------------------------------------------
172
173
174 1412 void PathspecElementPattern::PlaintextSubPattern::AddChar(const char chr) {
175 1412 chars_.push_back(chr);
176 1412 }
177
178 std::string
179 222 PathspecElementPattern::PlaintextSubPattern::GenerateRegularExpression(
180 const bool is_relaxed) const
181 {
182 // Note: strict and relaxed regex are the same!
183 222 std::string::const_iterator i = chars_.begin();
184 222 const std::string::const_iterator iend = chars_.end();
185 222 std::string regex;
186
2/2
✓ Branch 2 taken 971 times.
✓ Branch 3 taken 222 times.
1193 for (; i != iend; ++i) {
187
2/2
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 915 times.
971 if (IsSpecialRegexCharacter(*i)) {
188
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
56 regex += "\\";
189 }
190
1/2
✓ Branch 2 taken 971 times.
✗ Branch 3 not taken.
971 regex += *i;
191 }
192 444 return regex;
193 }
194
195
196 std::string
197 36 PathspecElementPattern::PlaintextSubPattern::GenerateGlobString() const
198 {
199 36 std::string::const_iterator i = chars_.begin();
200 36 const std::string::const_iterator iend = chars_.end();
201 36 std::string glob_string;
202
2/2
✓ Branch 2 taken 184 times.
✓ Branch 3 taken 36 times.
220 for (; i != iend; ++i) {
203
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 180 times.
184 if (Pathspec::IsSpecialChar(*i)) {
204
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 glob_string += "\\";
205 }
206
1/2
✓ Branch 2 taken 184 times.
✗ Branch 3 not taken.
184 glob_string += *i;
207 }
208 72 return glob_string;
209 }
210
211 971 bool PathspecElementPattern::PlaintextSubPattern::IsSpecialRegexCharacter(
212 const char chr) const
213 {
214
2/2
✓ Branch 0 taken 934 times.
✓ Branch 1 taken 2 times.
936 return (chr == '.' ||
215
2/2
✓ Branch 0 taken 931 times.
✓ Branch 1 taken 3 times.
934 chr == '\\' ||
216
2/2
✓ Branch 0 taken 927 times.
✓ Branch 1 taken 4 times.
931 chr == '*' ||
217
2/2
✓ Branch 0 taken 925 times.
✓ Branch 1 taken 2 times.
927 chr == '?' ||
218
2/2
✓ Branch 0 taken 923 times.
✓ Branch 1 taken 2 times.
925 chr == '[' ||
219
2/2
✓ Branch 0 taken 922 times.
✓ Branch 1 taken 1 times.
923 chr == ']' ||
220
2/2
✓ Branch 0 taken 921 times.
✓ Branch 1 taken 1 times.
922 chr == '(' ||
221
2/2
✓ Branch 0 taken 920 times.
✓ Branch 1 taken 1 times.
921 chr == ')' ||
222
2/2
✓ Branch 0 taken 919 times.
✓ Branch 1 taken 1 times.
920 chr == '{' ||
223
2/2
✓ Branch 0 taken 918 times.
✓ Branch 1 taken 1 times.
919 chr == '}' ||
224
2/2
✓ Branch 0 taken 917 times.
✓ Branch 1 taken 1 times.
918 chr == '^' ||
225
4/4
✓ Branch 0 taken 936 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 915 times.
1907 chr == '$' ||
226 971 chr == '+');
227 }
228
229 80 bool PathspecElementPattern::PlaintextSubPattern::Compare(
230 const SubPattern *other) const
231 {
232
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 79 times.
80 if (!other->IsPlaintext()) {
233 1 return false;
234 }
235
236 const PlaintextSubPattern *pt_other =
237
1/2
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
79 dynamic_cast<const PlaintextSubPattern*>(other);
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 assert(pt_other != NULL);
239 79 return chars_ == pt_other->chars_;
240 }
241
242
243 std::string
244 41 PathspecElementPattern::WildcardSubPattern::GenerateRegularExpression(
245 const bool is_relaxed) const
246 {
247 return (is_relaxed)
248 ? std::string(".*")
249
14/27
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 27 times.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 27 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 27 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 27 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 27 times.
✓ Branch 17 taken 14 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 27 times.
✓ Branch 20 taken 14 times.
✓ Branch 22 taken 27 times.
✓ Branch 23 taken 14 times.
✓ Branch 25 taken 14 times.
✓ Branch 26 taken 27 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
82 : std::string("[^") + Pathspec::kSeparator + "]*";
250 }
251
252
253 std::string
254 2 PathspecElementPattern::WildcardSubPattern::GenerateGlobString() const
255 {
256
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 return "*";
257 }
258
259
260 14 bool PathspecElementPattern::WildcardSubPattern::Compare(
261 const SubPattern *other) const
262 {
263 14 return other->IsWildcard();
264 }
265
266
267 std::string
268 21 PathspecElementPattern::PlaceholderSubPattern::GenerateRegularExpression(
269 const bool is_relaxed) const
270 {
271 // Note: strict and relaxed regex are the same!
272
3/6
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 21 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21 times.
✗ Branch 9 not taken.
42 return std::string("[^") + Pathspec::kSeparator + "]";
273 }
274
275 std::string
276 2 PathspecElementPattern::PlaceholderSubPattern::GenerateGlobString() const
277 {
278
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 return "?";
279 }
280
281 12 bool PathspecElementPattern::PlaceholderSubPattern::Compare(
282 const SubPattern *other) const
283 {
284 12 return other->IsPlaceholder();
285 }
286