Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/3rdparty/masm/yarr/YarrPattern.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* | - | ||||||||||||||||||||||||
2 | * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. | - | ||||||||||||||||||||||||
3 | * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged | - | ||||||||||||||||||||||||
4 | * | - | ||||||||||||||||||||||||
5 | * Redistribution and use in source and binary forms, with or without | - | ||||||||||||||||||||||||
6 | * modification, are permitted provided that the following conditions | - | ||||||||||||||||||||||||
7 | * are met: | - | ||||||||||||||||||||||||
8 | * 1. Redistributions of source code must retain the above copyright | - | ||||||||||||||||||||||||
9 | * notice, this list of conditions and the following disclaimer. | - | ||||||||||||||||||||||||
10 | * 2. Redistributions in binary form must reproduce the above copyright | - | ||||||||||||||||||||||||
11 | * notice, this list of conditions and the following disclaimer in the | - | ||||||||||||||||||||||||
12 | * documentation and/or other materials provided with the distribution. | - | ||||||||||||||||||||||||
13 | * | - | ||||||||||||||||||||||||
14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | - | ||||||||||||||||||||||||
15 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | - | ||||||||||||||||||||||||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | - | ||||||||||||||||||||||||
17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | - | ||||||||||||||||||||||||
18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | - | ||||||||||||||||||||||||
19 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | - | ||||||||||||||||||||||||
20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | - | ||||||||||||||||||||||||
21 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | - | ||||||||||||||||||||||||
22 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | - | ||||||||||||||||||||||||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | - | ||||||||||||||||||||||||
24 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | - | ||||||||||||||||||||||||
25 | */ | - | ||||||||||||||||||||||||
26 | - | |||||||||||||||||||||||||
27 | #include "config.h" | - | ||||||||||||||||||||||||
28 | #include "YarrPattern.h" | - | ||||||||||||||||||||||||
29 | - | |||||||||||||||||||||||||
30 | #include "Yarr.h" | - | ||||||||||||||||||||||||
31 | #include "YarrCanonicalizeUCS2.h" | - | ||||||||||||||||||||||||
32 | #include "YarrParser.h" | - | ||||||||||||||||||||||||
33 | #include <wtf/Vector.h> | - | ||||||||||||||||||||||||
34 | - | |||||||||||||||||||||||||
35 | using namespace WTF; | - | ||||||||||||||||||||||||
36 | - | |||||||||||||||||||||||||
37 | namespace JSC { namespace Yarr { | - | ||||||||||||||||||||||||
38 | - | |||||||||||||||||||||||||
39 | #include "RegExpJitTables.h" | - | ||||||||||||||||||||||||
40 | - | |||||||||||||||||||||||||
41 | class CharacterClassConstructor { | - | ||||||||||||||||||||||||
42 | public: | - | ||||||||||||||||||||||||
43 | CharacterClassConstructor(bool isCaseInsensitive = false) | - | ||||||||||||||||||||||||
44 | : m_isCaseInsensitive(isCaseInsensitive) | - | ||||||||||||||||||||||||
45 | { | - | ||||||||||||||||||||||||
46 | } executed 1149087 times by 153 tests: end of block Executed by:
| 1149087 | ||||||||||||||||||||||||
47 | - | |||||||||||||||||||||||||
48 | void reset() | - | ||||||||||||||||||||||||
49 | { | - | ||||||||||||||||||||||||
50 | m_matches.clear(); | - | ||||||||||||||||||||||||
51 | m_ranges.clear(); | - | ||||||||||||||||||||||||
52 | m_matchesUnicode.clear(); | - | ||||||||||||||||||||||||
53 | m_rangesUnicode.clear(); | - | ||||||||||||||||||||||||
54 | } executed 72 times by 1 test: end of block Executed by:
| 72 | ||||||||||||||||||||||||
55 | - | |||||||||||||||||||||||||
56 | void append(const CharacterClass* other) | - | ||||||||||||||||||||||||
57 | { | - | ||||||||||||||||||||||||
58 | for (size_t i = 0; i < other->m_matches.size(); ++i)
| 1276-2656 | ||||||||||||||||||||||||
59 | addSorted(m_matches, other->m_matches[i]); executed 1276 times by 1 test: addSorted(m_matches, other->m_matches[i]); Executed by:
| 1276 | ||||||||||||||||||||||||
60 | for (size_t i = 0; i < other->m_ranges.size(); ++i)
| 2656-5224 | ||||||||||||||||||||||||
61 | addSortedRange(m_ranges, other->m_ranges[i].begin, other->m_ranges[i].end); executed 5224 times by 1 test: addSortedRange(m_ranges, other->m_ranges[i].begin, other->m_ranges[i].end); Executed by:
| 5224 | ||||||||||||||||||||||||
62 | for (size_t i = 0; i < other->m_matchesUnicode.size(); ++i)
| 2654-11330 | ||||||||||||||||||||||||
63 | addSorted(m_matchesUnicode, other->m_matchesUnicode[i]); executed 11329 times by 1 test: addSorted(m_matchesUnicode, other->m_matchesUnicode[i]); Executed by:
| 11329 | ||||||||||||||||||||||||
64 | for (size_t i = 0; i < other->m_rangesUnicode.size(); ++i)
| 2656-13893 | ||||||||||||||||||||||||
65 | addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end); executed 13895 times by 1 test: addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end); Executed by:
| 13895 | ||||||||||||||||||||||||
66 | } executed 2656 times by 1 test: end of block Executed by:
| 2656 | ||||||||||||||||||||||||
67 | - | |||||||||||||||||||||||||
68 | void putChar(UChar ch) | - | ||||||||||||||||||||||||
69 | { | - | ||||||||||||||||||||||||
70 | // Handle ascii cases. | - | ||||||||||||||||||||||||
71 | if (ch <= 0x7f) {
| 0-3618 | ||||||||||||||||||||||||
72 | if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
| 4-3594 | ||||||||||||||||||||||||
73 | addSorted(m_matches, toASCIIUpper(ch)); | - | ||||||||||||||||||||||||
74 | addSorted(m_matches, toASCIILower(ch)); | - | ||||||||||||||||||||||||
75 | } else executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||||||||||||||
76 | addSorted(m_matches, ch); executed 3614 times by 3 tests: addSorted(m_matches, ch); Executed by:
| 3614 | ||||||||||||||||||||||||
77 | return; executed 3620 times by 3 tests: return; Executed by:
| 3620 | ||||||||||||||||||||||||
78 | } | - | ||||||||||||||||||||||||
79 | - | |||||||||||||||||||||||||
80 | // Simple case, not a case-insensitive match. | - | ||||||||||||||||||||||||
81 | if (!m_isCaseInsensitive) {
| 0 | ||||||||||||||||||||||||
82 | addSorted(m_matchesUnicode, ch); | - | ||||||||||||||||||||||||
83 | return; never executed: return; | 0 | ||||||||||||||||||||||||
84 | } | - | ||||||||||||||||||||||||
85 | - | |||||||||||||||||||||||||
86 | // Add multiple matches, if necessary. | - | ||||||||||||||||||||||||
87 | UCS2CanonicalizationRange* info = rangeInfoFor(ch); | - | ||||||||||||||||||||||||
88 | if (info->type == CanonicalizeUnique)
| 0 | ||||||||||||||||||||||||
89 | addSorted(m_matchesUnicode, ch); never executed: addSorted(m_matchesUnicode, ch); | 0 | ||||||||||||||||||||||||
90 | else | - | ||||||||||||||||||||||||
91 | putUnicodeIgnoreCase(ch, info); never executed: putUnicodeIgnoreCase(ch, info); | 0 | ||||||||||||||||||||||||
92 | } | - | ||||||||||||||||||||||||
93 | - | |||||||||||||||||||||||||
94 | void putUnicodeIgnoreCase(UChar ch, UCS2CanonicalizationRange* info) | - | ||||||||||||||||||||||||
95 | { | - | ||||||||||||||||||||||||
96 | ASSERT(m_isCaseInsensitive); | - | ||||||||||||||||||||||||
97 | ASSERT(ch > 0x7f); | - | ||||||||||||||||||||||||
98 | ASSERT(ch >= info->begin && ch <= info->end); | - | ||||||||||||||||||||||||
99 | ASSERT(info->type != CanonicalizeUnique); | - | ||||||||||||||||||||||||
100 | if (info->type == CanonicalizeSet) {
| 0 | ||||||||||||||||||||||||
101 | for (uint16_t* set = characterSetInfo[info->value]; (ch = *set); ++set)
| 0 | ||||||||||||||||||||||||
102 | addSorted(m_matchesUnicode, ch); never executed: addSorted(m_matchesUnicode, ch); | 0 | ||||||||||||||||||||||||
103 | } else { never executed: end of block | 0 | ||||||||||||||||||||||||
104 | addSorted(m_matchesUnicode, ch); | - | ||||||||||||||||||||||||
105 | addSorted(m_matchesUnicode, getCanonicalPair(info, ch)); | - | ||||||||||||||||||||||||
106 | } never executed: end of block | 0 | ||||||||||||||||||||||||
107 | } | - | ||||||||||||||||||||||||
108 | - | |||||||||||||||||||||||||
109 | void putRange(UChar lo, UChar hi) | - | ||||||||||||||||||||||||
110 | { | - | ||||||||||||||||||||||||
111 | if (lo <= 0x7f) {
| 4-1354 | ||||||||||||||||||||||||
112 | char asciiLo = lo; | - | ||||||||||||||||||||||||
113 | char asciiHi = std::min(hi, (UChar)0x7f); | - | ||||||||||||||||||||||||
114 | addSortedRange(m_ranges, lo, asciiHi); | - | ||||||||||||||||||||||||
115 | - | |||||||||||||||||||||||||
116 | if (m_isCaseInsensitive) {
| 32-1324 | ||||||||||||||||||||||||
117 | if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
| 0-24 | ||||||||||||||||||||||||
118 | addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A')); never executed: addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A')); | 0 | ||||||||||||||||||||||||
119 | if ((asciiLo <= 'z') && (asciiHi >= 'a'))
| 0-32 | ||||||||||||||||||||||||
120 | addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a')); executed 24 times by 1 test: addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a')); Executed by:
| 24 | ||||||||||||||||||||||||
121 | } executed 32 times by 1 test: end of block Executed by:
| 32 | ||||||||||||||||||||||||
122 | } executed 1354 times by 5 tests: end of block Executed by:
| 1354 | ||||||||||||||||||||||||
123 | if (hi <= 0x7f)
| 4-1356 | ||||||||||||||||||||||||
124 | return; executed 1356 times by 5 tests: return; Executed by:
| 1356 | ||||||||||||||||||||||||
125 | - | |||||||||||||||||||||||||
126 | lo = std::max(lo, (UChar)0x80); | - | ||||||||||||||||||||||||
127 | addSortedRange(m_rangesUnicode, lo, hi); | - | ||||||||||||||||||||||||
128 | - | |||||||||||||||||||||||||
129 | if (!m_isCaseInsensitive)
| 0-4 | ||||||||||||||||||||||||
130 | return; never executed: return; | 0 | ||||||||||||||||||||||||
131 | - | |||||||||||||||||||||||||
132 | UCS2CanonicalizationRange* info = rangeInfoFor(lo); | - | ||||||||||||||||||||||||
133 | while (true) { | - | ||||||||||||||||||||||||
134 | // Handle the range [lo .. end] | - | ||||||||||||||||||||||||
135 | UChar end = std::min<UChar>(info->end, hi); | - | ||||||||||||||||||||||||
136 | - | |||||||||||||||||||||||||
137 | switch (info->type) { | - | ||||||||||||||||||||||||
138 | case CanonicalizeUnique: executed 20 times by 1 test: case CanonicalizeUnique: Executed by:
| 20 | ||||||||||||||||||||||||
139 | // Nothing to do - no canonical equivalents. | - | ||||||||||||||||||||||||
140 | break; executed 20 times by 1 test: break; Executed by:
| 20 | ||||||||||||||||||||||||
141 | case CanonicalizeSet: { executed 4 times by 1 test: case CanonicalizeSet: Executed by:
| 4 | ||||||||||||||||||||||||
142 | UChar ch; | - | ||||||||||||||||||||||||
143 | for (uint16_t* set = characterSetInfo[info->value]; (ch = *set); ++set)
| 4-12 | ||||||||||||||||||||||||
144 | addSorted(m_matchesUnicode, ch); executed 12 times by 1 test: addSorted(m_matchesUnicode, ch); Executed by:
| 12 | ||||||||||||||||||||||||
145 | break; executed 4 times by 1 test: break; Executed by:
| 4 | ||||||||||||||||||||||||
146 | } | - | ||||||||||||||||||||||||
147 | case CanonicalizeRangeLo: executed 12 times by 1 test: case CanonicalizeRangeLo: Executed by:
| 12 | ||||||||||||||||||||||||
148 | addSortedRange(m_rangesUnicode, lo + info->value, end + info->value); | - | ||||||||||||||||||||||||
149 | break; executed 12 times by 1 test: break; Executed by:
| 12 | ||||||||||||||||||||||||
150 | case CanonicalizeRangeHi: executed 8 times by 1 test: case CanonicalizeRangeHi: Executed by:
| 8 | ||||||||||||||||||||||||
151 | addSortedRange(m_rangesUnicode, lo - info->value, end - info->value); | - | ||||||||||||||||||||||||
152 | break; executed 8 times by 1 test: break; Executed by:
| 8 | ||||||||||||||||||||||||
153 | case CanonicalizeAlternatingAligned: never executed: case CanonicalizeAlternatingAligned: | 0 | ||||||||||||||||||||||||
154 | // Use addSortedRange since there is likely an abutting range to combine with. | - | ||||||||||||||||||||||||
155 | if (lo & 1)
| 0 | ||||||||||||||||||||||||
156 | addSortedRange(m_rangesUnicode, lo - 1, lo - 1); never executed: addSortedRange(m_rangesUnicode, lo - 1, lo - 1); | 0 | ||||||||||||||||||||||||
157 | if (!(end & 1))
| 0 | ||||||||||||||||||||||||
158 | addSortedRange(m_rangesUnicode, end + 1, end + 1); never executed: addSortedRange(m_rangesUnicode, end + 1, end + 1); | 0 | ||||||||||||||||||||||||
159 | break; never executed: break; | 0 | ||||||||||||||||||||||||
160 | case CanonicalizeAlternatingUnaligned: never executed: case CanonicalizeAlternatingUnaligned: | 0 | ||||||||||||||||||||||||
161 | // Use addSortedRange since there is likely an abutting range to combine with. | - | ||||||||||||||||||||||||
162 | if (!(lo & 1))
| 0 | ||||||||||||||||||||||||
163 | addSortedRange(m_rangesUnicode, lo - 1, lo - 1); never executed: addSortedRange(m_rangesUnicode, lo - 1, lo - 1); | 0 | ||||||||||||||||||||||||
164 | if (end & 1)
| 0 | ||||||||||||||||||||||||
165 | addSortedRange(m_rangesUnicode, end + 1, end + 1); never executed: addSortedRange(m_rangesUnicode, end + 1, end + 1); | 0 | ||||||||||||||||||||||||
166 | break; never executed: break; | 0 | ||||||||||||||||||||||||
167 | } | - | ||||||||||||||||||||||||
168 | - | |||||||||||||||||||||||||
169 | if (hi == end)
| 4-40 | ||||||||||||||||||||||||
170 | return; executed 4 times by 1 test: return; Executed by:
| 4 | ||||||||||||||||||||||||
171 | - | |||||||||||||||||||||||||
172 | ++info; | - | ||||||||||||||||||||||||
173 | lo = info->begin; | - | ||||||||||||||||||||||||
174 | }; executed 40 times by 1 test: end of block Executed by:
| 40 | ||||||||||||||||||||||||
175 | - | |||||||||||||||||||||||||
176 | } never executed: end of block | 0 | ||||||||||||||||||||||||
177 | - | |||||||||||||||||||||||||
178 | PassOwnPtr<CharacterClass> charClass() | - | ||||||||||||||||||||||||
179 | { | - | ||||||||||||||||||||||||
180 | OwnPtr<CharacterClass> characterClass = adoptPtr(new CharacterClass); | - | ||||||||||||||||||||||||
181 | - | |||||||||||||||||||||||||
182 | characterClass->m_matches.swap(m_matches); | - | ||||||||||||||||||||||||
183 | characterClass->m_ranges.swap(m_ranges); | - | ||||||||||||||||||||||||
184 | characterClass->m_matchesUnicode.swap(m_matchesUnicode); | - | ||||||||||||||||||||||||
185 | characterClass->m_rangesUnicode.swap(m_rangesUnicode); | - | ||||||||||||||||||||||||
186 | - | |||||||||||||||||||||||||
187 | return characterClass.release(); executed 3382 times by 6 tests: return characterClass.release(); Executed by:
| 3382 | ||||||||||||||||||||||||
188 | } | - | ||||||||||||||||||||||||
189 | - | |||||||||||||||||||||||||
190 | private: | - | ||||||||||||||||||||||||
191 | void addSorted(Vector<UChar>& matches, UChar ch) | - | ||||||||||||||||||||||||
192 | { | - | ||||||||||||||||||||||||
193 | unsigned pos = 0; | - | ||||||||||||||||||||||||
194 | ASSERT(matches.size() <= UINT_MAX); | - | ||||||||||||||||||||||||
195 | unsigned range = static_cast<unsigned>(matches.size()); | - | ||||||||||||||||||||||||
196 | - | |||||||||||||||||||||||||
197 | // binary chop, find position to insert char. | - | ||||||||||||||||||||||||
198 | while (range) {
| 15994-23907 | ||||||||||||||||||||||||
199 | unsigned index = range >> 1; | - | ||||||||||||||||||||||||
200 | - | |||||||||||||||||||||||||
201 | int val = matches[pos+index] - ch; | - | ||||||||||||||||||||||||
202 | if (!val)
| 228-23679 | ||||||||||||||||||||||||
203 | return; executed 228 times by 1 test: return; Executed by:
| 228 | ||||||||||||||||||||||||
204 | else if (val > 0)
| 2424-21254 | ||||||||||||||||||||||||
205 | range = index; executed 2424 times by 3 tests: range = index; Executed by:
| 2424 | ||||||||||||||||||||||||
206 | else { | - | ||||||||||||||||||||||||
207 | pos += (index+1); | - | ||||||||||||||||||||||||
208 | range -= (index+1); | - | ||||||||||||||||||||||||
209 | } executed 21257 times by 3 tests: end of block Executed by:
| 21257 | ||||||||||||||||||||||||
210 | } | - | ||||||||||||||||||||||||
211 | - | |||||||||||||||||||||||||
212 | if (pos == matches.size())
| 1608-14383 | ||||||||||||||||||||||||
213 | matches.append(ch); executed 14382 times by 3 tests: matches.append(ch); Executed by:
| 14382 | ||||||||||||||||||||||||
214 | else | - | ||||||||||||||||||||||||
215 | matches.insert(pos, ch); executed 1608 times by 3 tests: matches.insert(pos, ch); Executed by:
| 1608 | ||||||||||||||||||||||||
216 | } | - | ||||||||||||||||||||||||
217 | - | |||||||||||||||||||||||||
218 | void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi) | - | ||||||||||||||||||||||||
219 | { | - | ||||||||||||||||||||||||
220 | ASSERT(ranges.size() <= UINT_MAX); | - | ||||||||||||||||||||||||
221 | unsigned end = static_cast<unsigned>(ranges.size()); | - | ||||||||||||||||||||||||
222 | - | |||||||||||||||||||||||||
223 | // Simple linear scan - I doubt there are that many ranges anyway... | - | ||||||||||||||||||||||||
224 | // feel free to fix this with something faster (eg binary chop). | - | ||||||||||||||||||||||||
225 | for (unsigned i = 0; i < end; ++i) {
| 11592-59762 | ||||||||||||||||||||||||
226 | // does the new range fall before the current position in the array | - | ||||||||||||||||||||||||
227 | if (hi < ranges[i].begin) {
| 6397-53380 | ||||||||||||||||||||||||
228 | // optional optimization: concatenate appending ranges? - may not be worthwhile. | - | ||||||||||||||||||||||||
229 | if (hi == (ranges[i].begin - 1)) {
| 2495-3907 | ||||||||||||||||||||||||
230 | ranges[i].begin = lo; | - | ||||||||||||||||||||||||
231 | return; executed 2495 times by 1 test: return; Executed by:
| 2495 | ||||||||||||||||||||||||
232 | } | - | ||||||||||||||||||||||||
233 | ranges.insert(i, CharacterRange(lo, hi)); | - | ||||||||||||||||||||||||
234 | return; executed 3907 times by 1 test: return; Executed by:
| 3907 | ||||||||||||||||||||||||
235 | } | - | ||||||||||||||||||||||||
236 | // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the beginning | - | ||||||||||||||||||||||||
237 | // If the new range start at or before the end of the last range, then the overlap (if it starts one after the | - | ||||||||||||||||||||||||
238 | // end of the last range they concatenate, which is just as good. | - | ||||||||||||||||||||||||
239 | if (lo <= (ranges[i].end + 1)) {
| 2516-50880 | ||||||||||||||||||||||||
240 | // found an intersect! we'll replace this entry in the array. | - | ||||||||||||||||||||||||
241 | ranges[i].begin = std::min(ranges[i].begin, lo); | - | ||||||||||||||||||||||||
242 | ranges[i].end = std::max(ranges[i].end, hi); | - | ||||||||||||||||||||||||
243 | - | |||||||||||||||||||||||||
244 | // now check if the new range can subsume any subsequent ranges. | - | ||||||||||||||||||||||||
245 | unsigned next = i+1; | - | ||||||||||||||||||||||||
246 | // each iteration of the loop we will either remove something from the list, or break the loop. | - | ||||||||||||||||||||||||
247 | while (next < ranges.size()) {
| 0-2516 | ||||||||||||||||||||||||
248 | if (ranges[next].begin <= (ranges[i].end + 1)) {
| 0 | ||||||||||||||||||||||||
249 | // the next entry now overlaps / concatenates this one. | - | ||||||||||||||||||||||||
250 | ranges[i].end = std::max(ranges[i].end, ranges[next].end); | - | ||||||||||||||||||||||||
251 | ranges.remove(next); | - | ||||||||||||||||||||||||
252 | } else never executed: end of block | 0 | ||||||||||||||||||||||||
253 | break; never executed: break; | 0 | ||||||||||||||||||||||||
254 | } | - | ||||||||||||||||||||||||
255 | - | |||||||||||||||||||||||||
256 | return; executed 2516 times by 3 tests: return; Executed by:
| 2516 | ||||||||||||||||||||||||
257 | } | - | ||||||||||||||||||||||||
258 | } executed 50878 times by 3 tests: end of block Executed by:
| 50878 | ||||||||||||||||||||||||
259 | - | |||||||||||||||||||||||||
260 | // CharacterRange comes after all existing ranges. | - | ||||||||||||||||||||||||
261 | ranges.append(CharacterRange(lo, hi)); | - | ||||||||||||||||||||||||
262 | } executed 11606 times by 5 tests: end of block Executed by:
| 11606 | ||||||||||||||||||||||||
263 | - | |||||||||||||||||||||||||
264 | bool m_isCaseInsensitive; | - | ||||||||||||||||||||||||
265 | - | |||||||||||||||||||||||||
266 | Vector<UChar> m_matches; | - | ||||||||||||||||||||||||
267 | Vector<CharacterRange> m_ranges; | - | ||||||||||||||||||||||||
268 | Vector<UChar> m_matchesUnicode; | - | ||||||||||||||||||||||||
269 | Vector<CharacterRange> m_rangesUnicode; | - | ||||||||||||||||||||||||
270 | }; | - | ||||||||||||||||||||||||
271 | - | |||||||||||||||||||||||||
272 | class YarrPatternConstructor { | - | ||||||||||||||||||||||||
273 | public: | - | ||||||||||||||||||||||||
274 | YarrPatternConstructor(YarrPattern& pattern) | - | ||||||||||||||||||||||||
275 | : m_pattern(pattern) | - | ||||||||||||||||||||||||
276 | , m_characterClassConstructor(pattern.m_ignoreCase) | - | ||||||||||||||||||||||||
277 | , m_invertParentheticalAssertion(false) | - | ||||||||||||||||||||||||
278 | { | - | ||||||||||||||||||||||||
279 | OwnPtr<PatternDisjunction> body = adoptPtr(new PatternDisjunction); | - | ||||||||||||||||||||||||
280 | m_pattern.m_body = body.get(); | - | ||||||||||||||||||||||||
281 | m_alternative = body->addNewAlternative(); | - | ||||||||||||||||||||||||
282 | m_pattern.m_disjunctions.append(body.release()); | - | ||||||||||||||||||||||||
283 | } executed 1149602 times by 153 tests: end of block Executed by:
| 1149602 | ||||||||||||||||||||||||
284 | - | |||||||||||||||||||||||||
285 | ~YarrPatternConstructor() | - | ||||||||||||||||||||||||
286 | { | - | ||||||||||||||||||||||||
287 | } | - | ||||||||||||||||||||||||
288 | - | |||||||||||||||||||||||||
289 | void reset() | - | ||||||||||||||||||||||||
290 | { | - | ||||||||||||||||||||||||
291 | m_pattern.reset(); | - | ||||||||||||||||||||||||
292 | m_characterClassConstructor.reset(); | - | ||||||||||||||||||||||||
293 | - | |||||||||||||||||||||||||
294 | OwnPtr<PatternDisjunction> body = adoptPtr(new PatternDisjunction); | - | ||||||||||||||||||||||||
295 | m_pattern.m_body = body.get(); | - | ||||||||||||||||||||||||
296 | m_alternative = body->addNewAlternative(); | - | ||||||||||||||||||||||||
297 | m_pattern.m_disjunctions.append(body.release()); | - | ||||||||||||||||||||||||
298 | } executed 72 times by 1 test: end of block Executed by:
| 72 | ||||||||||||||||||||||||
299 | - | |||||||||||||||||||||||||
300 | void assertionBOL() | - | ||||||||||||||||||||||||
301 | { | - | ||||||||||||||||||||||||
302 | if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) {
| 32-148 | ||||||||||||||||||||||||
303 | m_alternative->m_startsWithBOL = true; | - | ||||||||||||||||||||||||
304 | m_alternative->m_containsBOL = true; | - | ||||||||||||||||||||||||
305 | m_pattern.m_containsBOL = true; | - | ||||||||||||||||||||||||
306 | } executed 148 times by 5 tests: end of block Executed by:
| 148 | ||||||||||||||||||||||||
307 | m_alternative->m_terms.append(PatternTerm::BOL()); | - | ||||||||||||||||||||||||
308 | } executed 181 times by 5 tests: end of block Executed by:
| 181 | ||||||||||||||||||||||||
309 | void assertionEOL() | - | ||||||||||||||||||||||||
310 | { | - | ||||||||||||||||||||||||
311 | m_alternative->m_terms.append(PatternTerm::EOL()); | - | ||||||||||||||||||||||||
312 | } executed 178 times by 5 tests: end of block Executed by:
| 178 | ||||||||||||||||||||||||
313 | void assertionWordBoundary(bool invert) | - | ||||||||||||||||||||||||
314 | { | - | ||||||||||||||||||||||||
315 | m_alternative->m_terms.append(PatternTerm::WordBoundary(invert)); | - | ||||||||||||||||||||||||
316 | } executed 1136 times by 1 test: end of block Executed by:
| 1136 | ||||||||||||||||||||||||
317 | - | |||||||||||||||||||||||||
318 | void atomPatternCharacter(UChar ch) | - | ||||||||||||||||||||||||
319 | { | - | ||||||||||||||||||||||||
320 | // We handle case-insensitive checking of unicode characters which do have both | - | ||||||||||||||||||||||||
321 | // cases by handling them as if they were defined using a CharacterClass. | - | ||||||||||||||||||||||||
322 | if (!m_pattern.m_ignoreCase || isASCII(ch)) {
| 0-2368942 | ||||||||||||||||||||||||
323 | m_alternative->m_terms.append(PatternTerm(ch)); | - | ||||||||||||||||||||||||
324 | return; executed 2369244 times by 6 tests: return; Executed by:
| 2369244 | ||||||||||||||||||||||||
325 | } | - | ||||||||||||||||||||||||
326 | - | |||||||||||||||||||||||||
327 | UCS2CanonicalizationRange* info = rangeInfoFor(ch); | - | ||||||||||||||||||||||||
328 | if (info->type == CanonicalizeUnique) {
| 0 | ||||||||||||||||||||||||
329 | m_alternative->m_terms.append(PatternTerm(ch)); | - | ||||||||||||||||||||||||
330 | return; never executed: return; | 0 | ||||||||||||||||||||||||
331 | } | - | ||||||||||||||||||||||||
332 | - | |||||||||||||||||||||||||
333 | m_characterClassConstructor.putUnicodeIgnoreCase(ch, info); | - | ||||||||||||||||||||||||
334 | OwnPtr<CharacterClass> newCharacterClass = m_characterClassConstructor.charClass(); | - | ||||||||||||||||||||||||
335 | m_alternative->m_terms.append(PatternTerm(newCharacterClass.get(), false)); | - | ||||||||||||||||||||||||
336 | m_pattern.m_userCharacterClasses.append(newCharacterClass.release()); | - | ||||||||||||||||||||||||
337 | } never executed: end of block | 0 | ||||||||||||||||||||||||
338 | - | |||||||||||||||||||||||||
339 | void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert) | - | ||||||||||||||||||||||||
340 | { | - | ||||||||||||||||||||||||
341 | switch (classID) { | - | ||||||||||||||||||||||||
342 | case DigitClassID: executed 289 times by 3 tests: case DigitClassID: Executed by:
| 289 | ||||||||||||||||||||||||
343 | m_alternative->m_terms.append(PatternTerm(m_pattern.digitsCharacterClass(), invert)); | - | ||||||||||||||||||||||||
344 | break; executed 289 times by 3 tests: break; Executed by:
| 289 | ||||||||||||||||||||||||
345 | case SpaceClassID: executed 170 times by 3 tests: case SpaceClassID: Executed by:
| 170 | ||||||||||||||||||||||||
346 | m_alternative->m_terms.append(PatternTerm(m_pattern.spacesCharacterClass(), invert)); | - | ||||||||||||||||||||||||
347 | break; executed 170 times by 3 tests: break; Executed by:
| 170 | ||||||||||||||||||||||||
348 | case WordClassID: executed 124 times by 1 test: case WordClassID: Executed by:
| 124 | ||||||||||||||||||||||||
349 | m_alternative->m_terms.append(PatternTerm(m_pattern.wordcharCharacterClass(), invert)); | - | ||||||||||||||||||||||||
350 | break; executed 124 times by 1 test: break; Executed by:
| 124 | ||||||||||||||||||||||||
351 | case NewlineClassID: executed 626 times by 3 tests: case NewlineClassID: Executed by:
| 626 | ||||||||||||||||||||||||
352 | m_alternative->m_terms.append(PatternTerm(m_pattern.newlineCharacterClass(), invert)); | - | ||||||||||||||||||||||||
353 | break; executed 626 times by 3 tests: break; Executed by:
| 626 | ||||||||||||||||||||||||
354 | } | - | ||||||||||||||||||||||||
355 | } executed 1209 times by 6 tests: end of block Executed by:
| 1209 | ||||||||||||||||||||||||
356 | - | |||||||||||||||||||||||||
357 | void atomCharacterClassBegin(bool invert = false) | - | ||||||||||||||||||||||||
358 | { | - | ||||||||||||||||||||||||
359 | m_invertCharacterClass = invert; | - | ||||||||||||||||||||||||
360 | } executed 3557 times by 6 tests: end of block Executed by:
| 3557 | ||||||||||||||||||||||||
361 | - | |||||||||||||||||||||||||
362 | void atomCharacterClassAtom(UChar ch) | - | ||||||||||||||||||||||||
363 | { | - | ||||||||||||||||||||||||
364 | m_characterClassConstructor.putChar(ch); | - | ||||||||||||||||||||||||
365 | } executed 3618 times by 3 tests: end of block Executed by:
| 3618 | ||||||||||||||||||||||||
366 | - | |||||||||||||||||||||||||
367 | void atomCharacterClassRange(UChar begin, UChar end) | - | ||||||||||||||||||||||||
368 | { | - | ||||||||||||||||||||||||
369 | m_characterClassConstructor.putRange(begin, end); | - | ||||||||||||||||||||||||
370 | } executed 1359 times by 5 tests: end of block Executed by:
| 1359 | ||||||||||||||||||||||||
371 | - | |||||||||||||||||||||||||
372 | void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert) | - | ||||||||||||||||||||||||
373 | { | - | ||||||||||||||||||||||||
374 | ASSERT(classID != NewlineClassID); | - | ||||||||||||||||||||||||
375 | - | |||||||||||||||||||||||||
376 | switch (classID) { | - | ||||||||||||||||||||||||
377 | case DigitClassID: executed 116 times by 1 test: case DigitClassID: Executed by:
| 116 | ||||||||||||||||||||||||
378 | m_characterClassConstructor.append(invert ? m_pattern.nondigitsCharacterClass() : m_pattern.digitsCharacterClass()); | - | ||||||||||||||||||||||||
379 | break; executed 116 times by 1 test: break; Executed by:
| 116 | ||||||||||||||||||||||||
380 | - | |||||||||||||||||||||||||
381 | case SpaceClassID: executed 2523 times by 1 test: case SpaceClassID: Executed by:
| 2523 | ||||||||||||||||||||||||
382 | m_characterClassConstructor.append(invert ? m_pattern.nonspacesCharacterClass() : m_pattern.spacesCharacterClass()); | - | ||||||||||||||||||||||||
383 | break; executed 2524 times by 1 test: break; Executed by:
| 2524 | ||||||||||||||||||||||||
384 | - | |||||||||||||||||||||||||
385 | case WordClassID: executed 16 times by 1 test: case WordClassID: Executed by:
| 16 | ||||||||||||||||||||||||
386 | m_characterClassConstructor.append(invert ? m_pattern.nonwordcharCharacterClass() : m_pattern.wordcharCharacterClass()); | - | ||||||||||||||||||||||||
387 | break; executed 16 times by 1 test: break; Executed by:
| 16 | ||||||||||||||||||||||||
388 | - | |||||||||||||||||||||||||
389 | default: never executed: default: | 0 | ||||||||||||||||||||||||
390 | RELEASE_ASSERT_NOT_REACHED(); | - | ||||||||||||||||||||||||
391 | } never executed: end of block | 0 | ||||||||||||||||||||||||
392 | } | - | ||||||||||||||||||||||||
393 | - | |||||||||||||||||||||||||
394 | void atomCharacterClassEnd() | - | ||||||||||||||||||||||||
395 | { | - | ||||||||||||||||||||||||
396 | OwnPtr<CharacterClass> newCharacterClass = m_characterClassConstructor.charClass(); | - | ||||||||||||||||||||||||
397 | m_alternative->m_terms.append(PatternTerm(newCharacterClass.get(), m_invertCharacterClass)); | - | ||||||||||||||||||||||||
398 | m_pattern.m_userCharacterClasses.append(newCharacterClass.release()); | - | ||||||||||||||||||||||||
399 | } executed 3384 times by 6 tests: end of block Executed by:
| 3384 | ||||||||||||||||||||||||
400 | - | |||||||||||||||||||||||||
401 | void atomParenthesesSubpatternBegin(bool capture = true) | - | ||||||||||||||||||||||||
402 | { | - | ||||||||||||||||||||||||
403 | unsigned subpatternId = m_pattern.m_numSubpatterns + 1; | - | ||||||||||||||||||||||||
404 | if (capture)
| 951-2548 | ||||||||||||||||||||||||
405 | m_pattern.m_numSubpatterns++; executed 2548 times by 3 tests: m_pattern.m_numSubpatterns++; Executed by:
| 2548 | ||||||||||||||||||||||||
406 | - | |||||||||||||||||||||||||
407 | OwnPtr<PatternDisjunction> parenthesesDisjunction = adoptPtr(new PatternDisjunction(m_alternative)); | - | ||||||||||||||||||||||||
408 | m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction.get(), capture, false)); | - | ||||||||||||||||||||||||
409 | m_alternative = parenthesesDisjunction->addNewAlternative(); | - | ||||||||||||||||||||||||
410 | m_pattern.m_disjunctions.append(parenthesesDisjunction.release()); | - | ||||||||||||||||||||||||
411 | } executed 3501 times by 3 tests: end of block Executed by:
| 3501 | ||||||||||||||||||||||||
412 | - | |||||||||||||||||||||||||
413 | void atomParentheticalAssertionBegin(bool invert = false) | - | ||||||||||||||||||||||||
414 | { | - | ||||||||||||||||||||||||
415 | OwnPtr<PatternDisjunction> parenthesesDisjunction = adoptPtr(new PatternDisjunction(m_alternative)); | - | ||||||||||||||||||||||||
416 | m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction.get(), false, invert)); | - | ||||||||||||||||||||||||
417 | m_alternative = parenthesesDisjunction->addNewAlternative(); | - | ||||||||||||||||||||||||
418 | m_invertParentheticalAssertion = invert; | - | ||||||||||||||||||||||||
419 | m_pattern.m_disjunctions.append(parenthesesDisjunction.release()); | - | ||||||||||||||||||||||||
420 | } executed 76 times by 1 test: end of block Executed by:
| 76 | ||||||||||||||||||||||||
421 | - | |||||||||||||||||||||||||
422 | void atomParenthesesEnd() | - | ||||||||||||||||||||||||
423 | { | - | ||||||||||||||||||||||||
424 | ASSERT(m_alternative->m_parent); | - | ||||||||||||||||||||||||
425 | ASSERT(m_alternative->m_parent->m_parent); | - | ||||||||||||||||||||||||
426 | - | |||||||||||||||||||||||||
427 | PatternDisjunction* parenthesesDisjunction = m_alternative->m_parent; | - | ||||||||||||||||||||||||
428 | m_alternative = m_alternative->m_parent->m_parent; | - | ||||||||||||||||||||||||
429 | - | |||||||||||||||||||||||||
430 | PatternTerm& lastTerm = m_alternative->lastTerm(); | - | ||||||||||||||||||||||||
431 | - | |||||||||||||||||||||||||
432 | ASSERT(parenthesesDisjunction->m_alternatives.size() <= UINT_MAX); | - | ||||||||||||||||||||||||
433 | unsigned numParenAlternatives = static_cast<unsigned>(parenthesesDisjunction->m_alternatives.size()); | - | ||||||||||||||||||||||||
434 | unsigned numBOLAnchoredAlts = 0; | - | ||||||||||||||||||||||||
435 | - | |||||||||||||||||||||||||
436 | for (unsigned i = 0; i < numParenAlternatives; i++) {
| 3576-4509 | ||||||||||||||||||||||||
437 | // Bubble up BOL flags | - | ||||||||||||||||||||||||
438 | if (parenthesesDisjunction->m_alternatives[i]->m_startsWithBOL)
| 0-4508 | ||||||||||||||||||||||||
439 | numBOLAnchoredAlts++; never executed: numBOLAnchoredAlts++; | 0 | ||||||||||||||||||||||||
440 | } executed 4508 times by 3 tests: end of block Executed by:
| 4508 | ||||||||||||||||||||||||
441 | - | |||||||||||||||||||||||||
442 | if (numBOLAnchoredAlts) {
| 0-3575 | ||||||||||||||||||||||||
443 | m_alternative->m_containsBOL = true; | - | ||||||||||||||||||||||||
444 | // If all the alternatives in parens start with BOL, then so does this one | - | ||||||||||||||||||||||||
445 | if (numBOLAnchoredAlts == numParenAlternatives)
| 0 | ||||||||||||||||||||||||
446 | m_alternative->m_startsWithBOL = true; never executed: m_alternative->m_startsWithBOL = true; | 0 | ||||||||||||||||||||||||
447 | } never executed: end of block | 0 | ||||||||||||||||||||||||
448 | - | |||||||||||||||||||||||||
449 | lastTerm.parentheses.lastSubpatternId = m_pattern.m_numSubpatterns; | - | ||||||||||||||||||||||||
450 | m_invertParentheticalAssertion = false; | - | ||||||||||||||||||||||||
451 | } executed 3574 times by 3 tests: end of block Executed by:
| 3574 | ||||||||||||||||||||||||
452 | - | |||||||||||||||||||||||||
453 | void atomBackReference(unsigned subpatternId) | - | ||||||||||||||||||||||||
454 | { | - | ||||||||||||||||||||||||
455 | ASSERT(subpatternId); | - | ||||||||||||||||||||||||
456 | m_pattern.m_containsBackreferences = true; | - | ||||||||||||||||||||||||
457 | m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, subpatternId); | - | ||||||||||||||||||||||||
458 | - | |||||||||||||||||||||||||
459 | if (subpatternId > m_pattern.m_numSubpatterns) {
| 80-180 | ||||||||||||||||||||||||
460 | m_alternative->m_terms.append(PatternTerm::ForwardReference()); | - | ||||||||||||||||||||||||
461 | return; executed 80 times by 1 test: return; Executed by:
| 80 | ||||||||||||||||||||||||
462 | } | - | ||||||||||||||||||||||||
463 | - | |||||||||||||||||||||||||
464 | PatternAlternative* currentAlternative = m_alternative; | - | ||||||||||||||||||||||||
465 | ASSERT(currentAlternative); | - | ||||||||||||||||||||||||
466 | - | |||||||||||||||||||||||||
467 | // Note to self: if we waited until the AST was baked, we could also remove forwards refs | - | ||||||||||||||||||||||||
468 | while ((currentAlternative = currentAlternative->m_parent->m_parent)) {
| 4-180 | ||||||||||||||||||||||||
469 | PatternTerm& term = currentAlternative->lastTerm(); | - | ||||||||||||||||||||||||
470 | ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion)); | - | ||||||||||||||||||||||||
471 | - | |||||||||||||||||||||||||
472 | if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.capture() && (subpatternId == term.parentheses.subpatternId)) {
| 0-4 | ||||||||||||||||||||||||
473 | m_alternative->m_terms.append(PatternTerm::ForwardReference()); | - | ||||||||||||||||||||||||
474 | return; never executed: return; | 0 | ||||||||||||||||||||||||
475 | } | - | ||||||||||||||||||||||||
476 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||||||||||||||
477 | - | |||||||||||||||||||||||||
478 | m_alternative->m_terms.append(PatternTerm(subpatternId)); | - | ||||||||||||||||||||||||
479 | } executed 180 times by 1 test: end of block Executed by:
| 180 | ||||||||||||||||||||||||
480 | - | |||||||||||||||||||||||||
481 | // deep copy the argument disjunction. If filterStartsWithBOL is true, | - | ||||||||||||||||||||||||
482 | // skip alternatives with m_startsWithBOL set true. | - | ||||||||||||||||||||||||
483 | PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool filterStartsWithBOL = false) | - | ||||||||||||||||||||||||
484 | { | - | ||||||||||||||||||||||||
485 | OwnPtr<PatternDisjunction> newDisjunction; | - | ||||||||||||||||||||||||
486 | for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
| 162-183 | ||||||||||||||||||||||||
487 | PatternAlternative* alternative = disjunction->m_alternatives[alt].get(); | - | ||||||||||||||||||||||||
488 | if (!filterStartsWithBOL || !alternative->m_startsWithBOL) {
| 6-131 | ||||||||||||||||||||||||
489 | if (!newDisjunction) {
| 12-45 | ||||||||||||||||||||||||
490 | newDisjunction = adoptPtr(new PatternDisjunction()); | - | ||||||||||||||||||||||||
491 | newDisjunction->m_parent = disjunction->m_parent; | - | ||||||||||||||||||||||||
492 | } executed 46 times by 2 tests: end of block Executed by:
| 46 | ||||||||||||||||||||||||
493 | PatternAlternative* newAlternative = newDisjunction->addNewAlternative(); | - | ||||||||||||||||||||||||
494 | newAlternative->m_terms.reserveInitialCapacity(alternative->m_terms.size()); | - | ||||||||||||||||||||||||
495 | for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
| 58-124 | ||||||||||||||||||||||||
496 | newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], filterStartsWithBOL)); executed 124 times by 2 tests: newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], filterStartsWithBOL)); Executed by:
| 124 | ||||||||||||||||||||||||
497 | } executed 58 times by 2 tests: end of block Executed by:
| 58 | ||||||||||||||||||||||||
498 | } executed 184 times by 5 tests: end of block Executed by:
| 184 | ||||||||||||||||||||||||
499 | - | |||||||||||||||||||||||||
500 | if (!newDisjunction)
| 46-115 | ||||||||||||||||||||||||
501 | return 0; executed 115 times by 4 tests: return 0; Executed by:
| 115 | ||||||||||||||||||||||||
502 | - | |||||||||||||||||||||||||
503 | PatternDisjunction* copiedDisjunction = newDisjunction.get(); | - | ||||||||||||||||||||||||
504 | m_pattern.m_disjunctions.append(newDisjunction.release()); | - | ||||||||||||||||||||||||
505 | return copiedDisjunction; executed 46 times by 2 tests: return copiedDisjunction; Executed by:
| 46 | ||||||||||||||||||||||||
506 | } | - | ||||||||||||||||||||||||
507 | - | |||||||||||||||||||||||||
508 | PatternTerm copyTerm(PatternTerm& term, bool filterStartsWithBOL = false) | - | ||||||||||||||||||||||||
509 | { | - | ||||||||||||||||||||||||
510 | if ((term.type != PatternTerm::TypeParenthesesSubpattern) && (term.type != PatternTerm::TypeParentheticalAssertion))
| 0-1151 | ||||||||||||||||||||||||
511 | return PatternTerm(term); executed 1152 times by 6 tests: return PatternTerm(term); Executed by:
| 1152 | ||||||||||||||||||||||||
512 | - | |||||||||||||||||||||||||
513 | PatternTerm termCopy = term; | - | ||||||||||||||||||||||||
514 | termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction, filterStartsWithBOL); | - | ||||||||||||||||||||||||
515 | return termCopy; executed 39 times by 1 test: return termCopy; Executed by:
| 39 | ||||||||||||||||||||||||
516 | } | - | ||||||||||||||||||||||||
517 | - | |||||||||||||||||||||||||
518 | void quantifyAtom(unsigned min, unsigned max, bool greedy) | - | ||||||||||||||||||||||||
519 | { | - | ||||||||||||||||||||||||
520 | ASSERT(min <= max); | - | ||||||||||||||||||||||||
521 | ASSERT(m_alternative->m_terms.size()); | - | ||||||||||||||||||||||||
522 | - | |||||||||||||||||||||||||
523 | if (!max) {
| 0-4142 | ||||||||||||||||||||||||
524 | m_alternative->removeLastTerm(); | - | ||||||||||||||||||||||||
525 | return; never executed: return; | 0 | ||||||||||||||||||||||||
526 | } | - | ||||||||||||||||||||||||
527 | - | |||||||||||||||||||||||||
528 | PatternTerm& term = m_alternative->lastTerm(); | - | ||||||||||||||||||||||||
529 | ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary); | - | ||||||||||||||||||||||||
530 | ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount)); | - | ||||||||||||||||||||||||
531 | - | |||||||||||||||||||||||||
532 | if (term.type == PatternTerm::TypeParentheticalAssertion) {
| 0-4139 | ||||||||||||||||||||||||
533 | // If an assertion is quantified with a minimum count of zero, it can simply be removed. | - | ||||||||||||||||||||||||
534 | // This arises from the RepeatMatcher behaviour in the spec. Matching an assertion never | - | ||||||||||||||||||||||||
535 | // results in any input being consumed, however the continuation passed to the assertion | - | ||||||||||||||||||||||||
536 | // (called in steps, 8c and 9 of the RepeatMatcher definition, ES5.1 15.10.2.5) will | - | ||||||||||||||||||||||||
537 | // reject all zero length matches (see step 2.1). A match from the continuation of the | - | ||||||||||||||||||||||||
538 | // expression will still be accepted regardless (via steps 8a and 11) - the upshot of all | - | ||||||||||||||||||||||||
539 | // this is that matches from the assertion are not required, and won't be accepted anyway, | - | ||||||||||||||||||||||||
540 | // so no need to ever run it. | - | ||||||||||||||||||||||||
541 | if (!min)
| 0 | ||||||||||||||||||||||||
542 | m_alternative->removeLastTerm(); never executed: m_alternative->removeLastTerm(); | 0 | ||||||||||||||||||||||||
543 | // We never need to run an assertion more than once. Subsequent interations will be run | - | ||||||||||||||||||||||||
544 | // with the same start index (since assertions are non-capturing) and the same captures | - | ||||||||||||||||||||||||
545 | // (per step 4 of RepeatMatcher in ES5.1 15.10.2.5), and as such will always produce the | - | ||||||||||||||||||||||||
546 | // same result and captures. If the first match succeeds then the subsequent (min - 1) | - | ||||||||||||||||||||||||
547 | // matches will too. Any additional optional matches will fail (on the same basis as the | - | ||||||||||||||||||||||||
548 | // minimum zero quantified assertions, above), but this will still result in a match. | - | ||||||||||||||||||||||||
549 | return; never executed: return; | 0 | ||||||||||||||||||||||||
550 | } | - | ||||||||||||||||||||||||
551 | - | |||||||||||||||||||||||||
552 | if (min == 0)
| 1356-2788 | ||||||||||||||||||||||||
553 | term.quantify(max, greedy ? QuantifierGreedy : QuantifierNonGreedy); executed 2788 times by 5 tests: term.quantify(max, greedy ? QuantifierGreedy : QuantifierNonGreedy); Executed by:
| 2788 | ||||||||||||||||||||||||
554 | else if (min == max)
| 288-1064 | ||||||||||||||||||||||||
555 | term.quantify(min, QuantifierFixedCount); executed 288 times by 1 test: term.quantify(min, QuantifierFixedCount); Executed by:
| 288 | ||||||||||||||||||||||||
556 | else { | - | ||||||||||||||||||||||||
557 | term.quantify(min, QuantifierFixedCount); | - | ||||||||||||||||||||||||
558 | m_alternative->m_terms.append(copyTerm(term)); | - | ||||||||||||||||||||||||
559 | // NOTE: this term is interesting from an analysis perspective, in that it can be ignored..... | - | ||||||||||||||||||||||||
560 | m_alternative->lastTerm().quantify((max == quantifyInfinite) ? max : max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy); | - | ||||||||||||||||||||||||
561 | if (m_alternative->lastTerm().type == PatternTerm::TypeParenthesesSubpattern)
| 28-1041 | ||||||||||||||||||||||||
562 | m_alternative->lastTerm().parentheses.isCopy = true; executed 28 times by 1 test: m_alternative->lastTerm().parentheses.isCopy = true; Executed by:
| 28 | ||||||||||||||||||||||||
563 | } executed 1068 times by 6 tests: end of block Executed by:
| 1068 | ||||||||||||||||||||||||
564 | } | - | ||||||||||||||||||||||||
565 | - | |||||||||||||||||||||||||
566 | void disjunction() | - | ||||||||||||||||||||||||
567 | { | - | ||||||||||||||||||||||||
568 | m_alternative = m_alternative->m_parent->addNewAlternative(); | - | ||||||||||||||||||||||||
569 | } executed 1164 times by 4 tests: end of block Executed by:
| 1164 | ||||||||||||||||||||||||
570 | - | |||||||||||||||||||||||||
571 | unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition) | - | ||||||||||||||||||||||||
572 | { | - | ||||||||||||||||||||||||
573 | alternative->m_hasFixedSize = true; | - | ||||||||||||||||||||||||
574 | Checked<unsigned> currentInputPosition = initialInputPosition; | - | ||||||||||||||||||||||||
575 | - | |||||||||||||||||||||||||
576 | for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
| 1155336-2380650 | ||||||||||||||||||||||||
577 | PatternTerm& term = alternative->m_terms[i]; | - | ||||||||||||||||||||||||
578 | - | |||||||||||||||||||||||||
579 | switch (term.type) { | - | ||||||||||||||||||||||||
580 | case PatternTerm::TypeAssertionBOL: executed 178 times by 5 tests: case PatternTerm::TypeAssertionBOL: Executed by:
| 178 | ||||||||||||||||||||||||
581 | case PatternTerm::TypeAssertionEOL: executed 180 times by 5 tests: case PatternTerm::TypeAssertionEOL: Executed by:
| 180 | ||||||||||||||||||||||||
582 | case PatternTerm::TypeAssertionWordBoundary: executed 1136 times by 1 test: case PatternTerm::TypeAssertionWordBoundary: Executed by:
| 1136 | ||||||||||||||||||||||||
583 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
584 | break; executed 1494 times by 5 tests: break; Executed by:
| 1494 | ||||||||||||||||||||||||
585 | - | |||||||||||||||||||||||||
586 | case PatternTerm::TypeBackReference: executed 192 times by 1 test: case PatternTerm::TypeBackReference: Executed by:
| 192 | ||||||||||||||||||||||||
587 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
588 | term.frameLocation = currentCallFrameSize; | - | ||||||||||||||||||||||||
589 | currentCallFrameSize += YarrStackSpaceForBackTrackInfoBackReference; | - | ||||||||||||||||||||||||
590 | alternative->m_hasFixedSize = false; | - | ||||||||||||||||||||||||
591 | break; executed 192 times by 1 test: break; Executed by:
| 192 | ||||||||||||||||||||||||
592 | - | |||||||||||||||||||||||||
593 | case PatternTerm::TypeForwardReference: executed 8 times by 1 test: case PatternTerm::TypeForwardReference: Executed by:
| 8 | ||||||||||||||||||||||||
594 | break; executed 8 times by 1 test: break; Executed by:
| 8 | ||||||||||||||||||||||||
595 | - | |||||||||||||||||||||||||
596 | case PatternTerm::TypePatternCharacter: executed 2370024 times by 6 tests: case PatternTerm::TypePatternCharacter: Executed by:
| 2370024 | ||||||||||||||||||||||||
597 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
598 | if (term.quantityType != QuantifierFixedCount) {
| 472-2368880 | ||||||||||||||||||||||||
599 | term.frameLocation = currentCallFrameSize; | - | ||||||||||||||||||||||||
600 | currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter; | - | ||||||||||||||||||||||||
601 | alternative->m_hasFixedSize = false; | - | ||||||||||||||||||||||||
602 | } else executed 472 times by 2 tests: end of block Executed by:
| 472 | ||||||||||||||||||||||||
603 | currentInputPosition += term.quantityCount; executed 2368661 times by 6 tests: currentInputPosition += term.quantityCount; Executed by:
| 2368661 | ||||||||||||||||||||||||
604 | break; executed 2369300 times by 6 tests: break; Executed by:
| 2369300 | ||||||||||||||||||||||||
605 | - | |||||||||||||||||||||||||
606 | case PatternTerm::TypeCharacterClass: executed 5373 times by 9 tests: case PatternTerm::TypeCharacterClass: Executed by:
| 5373 | ||||||||||||||||||||||||
607 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
608 | if (term.quantityType != QuantifierFixedCount) {
| 2566-2808 | ||||||||||||||||||||||||
609 | term.frameLocation = currentCallFrameSize; | - | ||||||||||||||||||||||||
610 | currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass; | - | ||||||||||||||||||||||||
611 | alternative->m_hasFixedSize = false; | - | ||||||||||||||||||||||||
612 | } else executed 2566 times by 8 tests: end of block Executed by:
| 2566 | ||||||||||||||||||||||||
613 | currentInputPosition += term.quantityCount; executed 2809 times by 8 tests: currentInputPosition += term.quantityCount; Executed by:
| 2809 | ||||||||||||||||||||||||
614 | break; executed 5368 times by 9 tests: break; Executed by:
| 5368 | ||||||||||||||||||||||||
615 | - | |||||||||||||||||||||||||
616 | case PatternTerm::TypeParenthesesSubpattern: executed 3541 times by 3 tests: case PatternTerm::TypeParenthesesSubpattern: Executed by:
| 3541 | ||||||||||||||||||||||||
617 | // Note: for fixed once parentheses we will ensure at least the minimum is available; others are on their own. | - | ||||||||||||||||||||||||
618 | term.frameLocation = currentCallFrameSize; | - | ||||||||||||||||||||||||
619 | if (term.quantityCount == 1 && !term.parentheses.isCopy) {
| 0-3118 | ||||||||||||||||||||||||
620 | if (term.quantityType != QuantifierFixedCount)
| 338-2778 | ||||||||||||||||||||||||
621 | currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce; executed 338 times by 2 tests: currentCallFrameSize += 1; Executed by:
| 338 | ||||||||||||||||||||||||
622 | currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet()); | - | ||||||||||||||||||||||||
623 | // If quantity is fixed, then pre-check its minimum size. | - | ||||||||||||||||||||||||
624 | if (term.quantityType == QuantifierFixedCount)
| 338-2778 | ||||||||||||||||||||||||
625 | currentInputPosition += term.parentheses.disjunction->m_minimumSize; executed 2778 times by 3 tests: currentInputPosition += term.parentheses.disjunction->m_minimumSize; Executed by:
| 2778 | ||||||||||||||||||||||||
626 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
627 | } else if (term.parentheses.isTerminal) { executed 3118 times by 3 tests: end of block Executed by:
| 11-3118 | ||||||||||||||||||||||||
628 | currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal; | - | ||||||||||||||||||||||||
629 | currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet()); | - | ||||||||||||||||||||||||
630 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
631 | } else { executed 12 times by 1 test: end of block Executed by:
| 12 | ||||||||||||||||||||||||
632 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
633 | setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition.unsafeGet()); | - | ||||||||||||||||||||||||
634 | currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses; | - | ||||||||||||||||||||||||
635 | } executed 412 times by 1 test: end of block Executed by:
| 412 | ||||||||||||||||||||||||
636 | // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length. | - | ||||||||||||||||||||||||
637 | alternative->m_hasFixedSize = false; | - | ||||||||||||||||||||||||
638 | break; executed 3540 times by 3 tests: break; Executed by:
| 3540 | ||||||||||||||||||||||||
639 | - | |||||||||||||||||||||||||
640 | case PatternTerm::TypeParentheticalAssertion: executed 76 times by 1 test: case PatternTerm::TypeParentheticalAssertion: Executed by:
| 76 | ||||||||||||||||||||||||
641 | term.inputPosition = currentInputPosition.unsafeGet(); | - | ||||||||||||||||||||||||
642 | term.frameLocation = currentCallFrameSize; | - | ||||||||||||||||||||||||
643 | currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition.unsafeGet()); | - | ||||||||||||||||||||||||
644 | break; executed 76 times by 1 test: break; Executed by:
| 76 | ||||||||||||||||||||||||
645 | - | |||||||||||||||||||||||||
646 | case PatternTerm::TypeDotStarEnclosure: executed 8 times by 1 test: case PatternTerm::TypeDotStarEnclosure: Executed by:
| 8 | ||||||||||||||||||||||||
647 | alternative->m_hasFixedSize = false; | - | ||||||||||||||||||||||||
648 | term.inputPosition = initialInputPosition; | - | ||||||||||||||||||||||||
649 | break; executed 8 times by 1 test: break; Executed by:
| 8 | ||||||||||||||||||||||||
650 | } | - | ||||||||||||||||||||||||
651 | } executed 2379996 times by 9 tests: end of block Executed by:
| 2379996 | ||||||||||||||||||||||||
652 | - | |||||||||||||||||||||||||
653 | alternative->m_minimumSize = (currentInputPosition - initialInputPosition).unsafeGet(); | - | ||||||||||||||||||||||||
654 | return currentCallFrameSize; executed 1154549 times by 153 tests: return currentCallFrameSize; Executed by:
| 1154549 | ||||||||||||||||||||||||
655 | } | - | ||||||||||||||||||||||||
656 | - | |||||||||||||||||||||||||
657 | unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition) | - | ||||||||||||||||||||||||
658 | { | - | ||||||||||||||||||||||||
659 | if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
| 641-1149465 | ||||||||||||||||||||||||
660 | initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative; executed 642 times by 3 tests: initialCallFrameSize += 1; Executed by:
| 642 | ||||||||||||||||||||||||
661 | - | |||||||||||||||||||||||||
662 | unsigned minimumInputSize = UINT_MAX; | - | ||||||||||||||||||||||||
663 | unsigned maximumCallFrameSize = 0; | - | ||||||||||||||||||||||||
664 | bool hasFixedSize = true; | - | ||||||||||||||||||||||||
665 | - | |||||||||||||||||||||||||
666 | for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
| 1154390-1156077 | ||||||||||||||||||||||||
667 | PatternAlternative* alternative = disjunction->m_alternatives[alt].get(); | - | ||||||||||||||||||||||||
668 | unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition); | - | ||||||||||||||||||||||||
669 | minimumInputSize = std::min(minimumInputSize, alternative->m_minimumSize); | - | ||||||||||||||||||||||||
670 | maximumCallFrameSize = std::max(maximumCallFrameSize, currentAlternativeCallFrameSize); | - | ||||||||||||||||||||||||
671 | hasFixedSize &= alternative->m_hasFixedSize; | - | ||||||||||||||||||||||||
672 | } executed 1155127 times by 153 tests: end of block Executed by:
| 1155127 | ||||||||||||||||||||||||
673 | - | |||||||||||||||||||||||||
674 | ASSERT(minimumInputSize != UINT_MAX); | - | ||||||||||||||||||||||||
675 | ASSERT(maximumCallFrameSize >= initialCallFrameSize); | - | ||||||||||||||||||||||||
676 | - | |||||||||||||||||||||||||
677 | disjunction->m_hasFixedSize = hasFixedSize; | - | ||||||||||||||||||||||||
678 | disjunction->m_minimumSize = minimumInputSize; | - | ||||||||||||||||||||||||
679 | disjunction->m_callFrameSize = maximumCallFrameSize; | - | ||||||||||||||||||||||||
680 | return maximumCallFrameSize; executed 1154201 times by 153 tests: return maximumCallFrameSize; Executed by:
| 1154201 | ||||||||||||||||||||||||
681 | } | - | ||||||||||||||||||||||||
682 | - | |||||||||||||||||||||||||
683 | void setupOffsets() | - | ||||||||||||||||||||||||
684 | { | - | ||||||||||||||||||||||||
685 | setupDisjunctionOffsets(m_pattern.m_body, 0, 0); | - | ||||||||||||||||||||||||
686 | } executed 1150138 times by 153 tests: end of block Executed by:
| 1150138 | ||||||||||||||||||||||||
687 | - | |||||||||||||||||||||||||
688 | // This optimization identifies sets of parentheses that we will never need to backtrack. | - | ||||||||||||||||||||||||
689 | // In these cases we do not need to store state from prior iterations. | - | ||||||||||||||||||||||||
690 | // We can presently avoid backtracking for: | - | ||||||||||||||||||||||||
691 | // * where the parens are at the end of the regular expression (last term in any of the | - | ||||||||||||||||||||||||
692 | // alternatives of the main body disjunction). | - | ||||||||||||||||||||||||
693 | // * where the parens are non-capturing, and quantified unbounded greedy (*). | - | ||||||||||||||||||||||||
694 | // * where the parens do not contain any capturing subpatterns. | - | ||||||||||||||||||||||||
695 | void checkForTerminalParentheses() | - | ||||||||||||||||||||||||
696 | { | - | ||||||||||||||||||||||||
697 | // This check is much too crude; should be just checking whether the candidate | - | ||||||||||||||||||||||||
698 | // node contains nested capturing subpatterns, not the whole expression! | - | ||||||||||||||||||||||||
699 | if (m_pattern.m_numSubpatterns)
| 560-1149855 | ||||||||||||||||||||||||
700 | return; executed 560 times by 3 tests: return; Executed by:
| 560 | ||||||||||||||||||||||||
701 | - | |||||||||||||||||||||||||
702 | Vector<OwnPtr<PatternAlternative> >& alternatives = m_pattern.m_body->m_alternatives; | - | ||||||||||||||||||||||||
703 | for (size_t i = 0; i < alternatives.size(); ++i) {
| 1149644-1149923 | ||||||||||||||||||||||||
704 | Vector<PatternTerm>& terms = alternatives[i]->m_terms; | - | ||||||||||||||||||||||||
705 | if (terms.size()) {
| 98066-1051678 | ||||||||||||||||||||||||
706 | PatternTerm& term = terms.last(); | - | ||||||||||||||||||||||||
707 | if (term.type == PatternTerm::TypeParenthesesSubpattern
| 87-1051460 | ||||||||||||||||||||||||
708 | && term.quantityType == QuantifierGreedy
| 12-76 | ||||||||||||||||||||||||
709 | && term.quantityCount == quantifyInfinite
| 0-11 | ||||||||||||||||||||||||
710 | && !term.capture())
| 0-11 | ||||||||||||||||||||||||
711 | term.parentheses.isTerminal = true; executed 11 times by 1 test: term.parentheses.isTerminal = true; Executed by:
| 11 | ||||||||||||||||||||||||
712 | } executed 1051487 times by 9 tests: end of block Executed by:
| 1051487 | ||||||||||||||||||||||||
713 | } executed 1149807 times by 153 tests: end of block Executed by:
| 1149807 | ||||||||||||||||||||||||
714 | } executed 1149590 times by 153 tests: end of block Executed by:
| 1149590 | ||||||||||||||||||||||||
715 | - | |||||||||||||||||||||||||
716 | void optimizeBOL() | - | ||||||||||||||||||||||||
717 | { | - | ||||||||||||||||||||||||
718 | // Look for expressions containing beginning of line (^) anchoring and unroll them. | - | ||||||||||||||||||||||||
719 | // e.g. /^a|^b|c/ becomes /^a|^b|c/ which is executed once followed by /c/ which loops | - | ||||||||||||||||||||||||
720 | // This code relies on the parsing code tagging alternatives with m_containsBOL and | - | ||||||||||||||||||||||||
721 | // m_startsWithBOL and rolling those up to containing alternatives. | - | ||||||||||||||||||||||||
722 | // At this point, this is only valid for non-multiline expressions. | - | ||||||||||||||||||||||||
723 | PatternDisjunction* disjunction = m_pattern.m_body; | - | ||||||||||||||||||||||||
724 | - | |||||||||||||||||||||||||
725 | if (!m_pattern.m_containsBOL || m_pattern.m_multiline)
| 20-1149777 | ||||||||||||||||||||||||
726 | return; executed 1149681 times by 153 tests: return; Executed by:
| 1149681 | ||||||||||||||||||||||||
727 | - | |||||||||||||||||||||||||
728 | PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true); | - | ||||||||||||||||||||||||
729 | - | |||||||||||||||||||||||||
730 | // Set alternatives in disjunction to "onceThrough" | - | ||||||||||||||||||||||||
731 | for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt)
| 121-132 | ||||||||||||||||||||||||
732 | disjunction->m_alternatives[alt]->setOnceThrough(); executed 132 times by 5 tests: disjunction->m_alternatives[alt]->setOnceThrough(); Executed by:
| 132 | ||||||||||||||||||||||||
733 | - | |||||||||||||||||||||||||
734 | if (loopDisjunction) {
| 6-115 | ||||||||||||||||||||||||
735 | // Move alternatives from loopDisjunction to disjunction | - | ||||||||||||||||||||||||
736 | for (unsigned alt = 0; alt < loopDisjunction->m_alternatives.size(); ++alt)
| 6 | ||||||||||||||||||||||||
737 | disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt].release()); executed 6 times by 2 tests: disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt].release()); Executed by:
| 6 | ||||||||||||||||||||||||
738 | - | |||||||||||||||||||||||||
739 | loopDisjunction->m_alternatives.clear(); | - | ||||||||||||||||||||||||
740 | } executed 6 times by 2 tests: end of block Executed by:
| 6 | ||||||||||||||||||||||||
741 | } executed 121 times by 5 tests: end of block Executed by:
| 121 | ||||||||||||||||||||||||
742 | - | |||||||||||||||||||||||||
743 | bool containsCapturingTerms(PatternAlternative* alternative, size_t firstTermIndex, size_t lastTermIndex) | - | ||||||||||||||||||||||||
744 | { | - | ||||||||||||||||||||||||
745 | Vector<PatternTerm>& terms = alternative->m_terms; | - | ||||||||||||||||||||||||
746 | - | |||||||||||||||||||||||||
747 | for (size_t termIndex = firstTermIndex; termIndex <= lastTermIndex; ++termIndex) {
| 8-24 | ||||||||||||||||||||||||
748 | PatternTerm& term = terms[termIndex]; | - | ||||||||||||||||||||||||
749 | - | |||||||||||||||||||||||||
750 | if (term.m_capture)
| 0-24 | ||||||||||||||||||||||||
751 | return true; never executed: return true; | 0 | ||||||||||||||||||||||||
752 | - | |||||||||||||||||||||||||
753 | if (term.type == PatternTerm::TypeParenthesesSubpattern) {
| 0-24 | ||||||||||||||||||||||||
754 | PatternDisjunction* nestedDisjunction = term.parentheses.disjunction; | - | ||||||||||||||||||||||||
755 | for (unsigned alt = 0; alt < nestedDisjunction->m_alternatives.size(); ++alt) {
| 0 | ||||||||||||||||||||||||
756 | if (containsCapturingTerms(nestedDisjunction->m_alternatives[alt].get(), 0, nestedDisjunction->m_alternatives[alt]->m_terms.size() - 1))
| 0 | ||||||||||||||||||||||||
757 | return true; never executed: return true; | 0 | ||||||||||||||||||||||||
758 | } never executed: end of block | 0 | ||||||||||||||||||||||||
759 | } never executed: end of block | 0 | ||||||||||||||||||||||||
760 | } executed 24 times by 1 test: end of block Executed by:
| 24 | ||||||||||||||||||||||||
761 | - | |||||||||||||||||||||||||
762 | return false; executed 8 times by 1 test: return false; Executed by:
| 8 | ||||||||||||||||||||||||
763 | } | - | ||||||||||||||||||||||||
764 | - | |||||||||||||||||||||||||
765 | // This optimization identifies alternatives in the form of | - | ||||||||||||||||||||||||
766 | // [^].*[?]<expression>.*[$] for expressions that don't have any | - | ||||||||||||||||||||||||
767 | // capturing terms. The alternative is changed to <expression> | - | ||||||||||||||||||||||||
768 | // followed by processing of the dot stars to find and adjust the | - | ||||||||||||||||||||||||
769 | // beginning and the end of the match. | - | ||||||||||||||||||||||||
770 | void optimizeDotStarWrappedExpressions() | - | ||||||||||||||||||||||||
771 | { | - | ||||||||||||||||||||||||
772 | Vector<OwnPtr<PatternAlternative> >& alternatives = m_pattern.m_body->m_alternatives; | - | ||||||||||||||||||||||||
773 | if (alternatives.size() != 1)
| 197-1149634 | ||||||||||||||||||||||||
774 | return; executed 197 times by 2 tests: return; Executed by:
| 197 | ||||||||||||||||||||||||
775 | - | |||||||||||||||||||||||||
776 | PatternAlternative* alternative = alternatives[0].get(); | - | ||||||||||||||||||||||||
777 | Vector<PatternTerm>& terms = alternative->m_terms; | - | ||||||||||||||||||||||||
778 | if (terms.size() >= 3) {
| 263139-886621 | ||||||||||||||||||||||||
779 | bool startsWithBOL = false; | - | ||||||||||||||||||||||||
780 | bool endsWithEOL = false; | - | ||||||||||||||||||||||||
781 | size_t termIndex, firstExpressionTerm, lastExpressionTerm; | - | ||||||||||||||||||||||||
782 | - | |||||||||||||||||||||||||
783 | termIndex = 0; | - | ||||||||||||||||||||||||
784 | if (terms[termIndex].type == PatternTerm::TypeAssertionBOL) {
| 112-263027 | ||||||||||||||||||||||||
785 | startsWithBOL = true; | - | ||||||||||||||||||||||||
786 | ++termIndex; | - | ||||||||||||||||||||||||
787 | } executed 112 times by 4 tests: end of block Executed by:
| 112 | ||||||||||||||||||||||||
788 | - | |||||||||||||||||||||||||
789 | PatternTerm& firstNonAnchorTerm = terms[termIndex]; | - | ||||||||||||||||||||||||
790 | if ((firstNonAnchorTerm.type != PatternTerm::TypeCharacterClass) || (firstNonAnchorTerm.characterClass != m_pattern.newlineCharacterClass()) || !((firstNonAnchorTerm.quantityType == QuantifierGreedy) || (firstNonAnchorTerm.quantityType == QuantifierNonGreedy)))
| 10-262953 | ||||||||||||||||||||||||
791 | return; executed 263115 times by 7 tests: return; Executed by:
| 263115 | ||||||||||||||||||||||||
792 | - | |||||||||||||||||||||||||
793 | firstExpressionTerm = termIndex + 1; | - | ||||||||||||||||||||||||
794 | - | |||||||||||||||||||||||||
795 | termIndex = terms.size() - 1; | - | ||||||||||||||||||||||||
796 | if (terms[termIndex].type == PatternTerm::TypeAssertionEOL) {
| 4-20 | ||||||||||||||||||||||||
797 | endsWithEOL = true; | - | ||||||||||||||||||||||||
798 | --termIndex; | - | ||||||||||||||||||||||||
799 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||||||||||||||
800 | - | |||||||||||||||||||||||||
801 | PatternTerm& lastNonAnchorTerm = terms[termIndex]; | - | ||||||||||||||||||||||||
802 | if ((lastNonAnchorTerm.type != PatternTerm::TypeCharacterClass) || (lastNonAnchorTerm.characterClass != m_pattern.newlineCharacterClass()) || (lastNonAnchorTerm.quantityType != QuantifierGreedy))
| 2-14 | ||||||||||||||||||||||||
803 | return; executed 16 times by 2 tests: return; Executed by:
| 16 | ||||||||||||||||||||||||
804 | - | |||||||||||||||||||||||||
805 | lastExpressionTerm = termIndex - 1; | - | ||||||||||||||||||||||||
806 | - | |||||||||||||||||||||||||
807 | if (firstExpressionTerm > lastExpressionTerm)
| 0-8 | ||||||||||||||||||||||||
808 | return; never executed: return; | 0 | ||||||||||||||||||||||||
809 | - | |||||||||||||||||||||||||
810 | if (!containsCapturingTerms(alternative, firstExpressionTerm, lastExpressionTerm)) {
| 0-8 | ||||||||||||||||||||||||
811 | for (termIndex = terms.size() - 1; termIndex > lastExpressionTerm; --termIndex)
| 8 | ||||||||||||||||||||||||
812 | terms.remove(termIndex); executed 8 times by 1 test: terms.remove(termIndex); Executed by:
| 8 | ||||||||||||||||||||||||
813 | - | |||||||||||||||||||||||||
814 | for (termIndex = firstExpressionTerm; termIndex > 0; --termIndex)
| 8 | ||||||||||||||||||||||||
815 | terms.remove(termIndex - 1); executed 8 times by 1 test: terms.remove(termIndex - 1); Executed by:
| 8 | ||||||||||||||||||||||||
816 | - | |||||||||||||||||||||||||
817 | terms.append(PatternTerm(startsWithBOL, endsWithEOL)); | - | ||||||||||||||||||||||||
818 | - | |||||||||||||||||||||||||
819 | m_pattern.m_containsBOL = false; | - | ||||||||||||||||||||||||
820 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
821 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
822 | } executed 887320 times by 153 tests: end of block Executed by:
| 887320 | ||||||||||||||||||||||||
823 | - | |||||||||||||||||||||||||
824 | private: | - | ||||||||||||||||||||||||
825 | YarrPattern& m_pattern; | - | ||||||||||||||||||||||||
826 | PatternAlternative* m_alternative; | - | ||||||||||||||||||||||||
827 | CharacterClassConstructor m_characterClassConstructor; | - | ||||||||||||||||||||||||
828 | bool m_invertCharacterClass; | - | ||||||||||||||||||||||||
829 | bool m_invertParentheticalAssertion; | - | ||||||||||||||||||||||||
830 | }; | - | ||||||||||||||||||||||||
831 | - | |||||||||||||||||||||||||
832 | const char* YarrPattern::compile(const String& patternString) | - | ||||||||||||||||||||||||
833 | { | - | ||||||||||||||||||||||||
834 | YarrPatternConstructor constructor(*this); | - | ||||||||||||||||||||||||
835 | - | |||||||||||||||||||||||||
836 | if (const char* error = parse(constructor, patternString))
| 249-1150587 | ||||||||||||||||||||||||
837 | return error; executed 250 times by 1 test: return error; Executed by:
| 250 | ||||||||||||||||||||||||
838 | - | |||||||||||||||||||||||||
839 | // If the pattern contains illegal backreferences reset & reparse. | - | ||||||||||||||||||||||||
840 | // Quoting Netscape's "What's new in JavaScript 1.2", | - | ||||||||||||||||||||||||
841 | // "Note: if the number of left parentheses is less than the number specified | - | ||||||||||||||||||||||||
842 | // in \#, the \# is taken as an octal escape as described in the next row." | - | ||||||||||||||||||||||||
843 | if (containsIllegalBackReference()) {
| 72-1150410 | ||||||||||||||||||||||||
844 | unsigned numSubpatterns = m_numSubpatterns; | - | ||||||||||||||||||||||||
845 | - | |||||||||||||||||||||||||
846 | constructor.reset(); | - | ||||||||||||||||||||||||
847 | #if !ASSERT_DISABLED | - | ||||||||||||||||||||||||
848 | const char* error = | - | ||||||||||||||||||||||||
849 | #endif | - | ||||||||||||||||||||||||
850 | parse(constructor, patternString, numSubpatterns); | - | ||||||||||||||||||||||||
851 | - | |||||||||||||||||||||||||
852 | ASSERT(!error); | - | ||||||||||||||||||||||||
853 | ASSERT(numSubpatterns == m_numSubpatterns); | - | ||||||||||||||||||||||||
854 | } executed 72 times by 1 test: end of block Executed by:
| 72 | ||||||||||||||||||||||||
855 | - | |||||||||||||||||||||||||
856 | constructor.checkForTerminalParentheses(); | - | ||||||||||||||||||||||||
857 | constructor.optimizeDotStarWrappedExpressions(); | - | ||||||||||||||||||||||||
858 | constructor.optimizeBOL(); | - | ||||||||||||||||||||||||
859 | - | |||||||||||||||||||||||||
860 | constructor.setupOffsets(); | - | ||||||||||||||||||||||||
861 | - | |||||||||||||||||||||||||
862 | return 0; executed 1149806 times by 153 tests: return 0; Executed by:
| 1149806 | ||||||||||||||||||||||||
863 | } | - | ||||||||||||||||||||||||
864 | - | |||||||||||||||||||||||||
865 | YarrPattern::YarrPattern(const String& pattern, bool ignoreCase, bool multiline, const char** error) | - | ||||||||||||||||||||||||
866 | : m_ignoreCase(ignoreCase) | - | ||||||||||||||||||||||||
867 | , m_multiline(multiline) | - | ||||||||||||||||||||||||
868 | , m_containsBackreferences(false) | - | ||||||||||||||||||||||||
869 | , m_containsBOL(false) | - | ||||||||||||||||||||||||
870 | , m_numSubpatterns(0) | - | ||||||||||||||||||||||||
871 | , m_maxBackReference(0) | - | ||||||||||||||||||||||||
872 | , newlineCached(0) | - | ||||||||||||||||||||||||
873 | , digitsCached(0) | - | ||||||||||||||||||||||||
874 | , spacesCached(0) | - | ||||||||||||||||||||||||
875 | , wordcharCached(0) | - | ||||||||||||||||||||||||
876 | , nondigitsCached(0) | - | ||||||||||||||||||||||||
877 | , nonspacesCached(0) | - | ||||||||||||||||||||||||
878 | , nonwordcharCached(0) | - | ||||||||||||||||||||||||
879 | { | - | ||||||||||||||||||||||||
880 | *error = compile(pattern); | - | ||||||||||||||||||||||||
881 | } executed 1151010 times by 153 tests: end of block Executed by:
| 1151010 | ||||||||||||||||||||||||
882 | - | |||||||||||||||||||||||||
883 | } } | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |