| 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 32 | ||||||||||||||||||||||||
| 122 | } executed 1354 times by 5 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 148 | ||||||||||||||||||||||||
| 307 | m_alternative->m_terms.append(PatternTerm::BOL()); | - | ||||||||||||||||||||||||
| 308 | } executed 181 times by 5 tests: end of blockExecuted by:
| 181 | ||||||||||||||||||||||||
| 309 | void assertionEOL() | - | ||||||||||||||||||||||||
| 310 | { | - | ||||||||||||||||||||||||
| 311 | m_alternative->m_terms.append(PatternTerm::EOL()); | - | ||||||||||||||||||||||||
| 312 | } executed 178 times by 5 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted by:
| 1209 | ||||||||||||||||||||||||
| 356 | - | |||||||||||||||||||||||||
| 357 | void atomCharacterClassBegin(bool invert = false) | - | ||||||||||||||||||||||||
| 358 | { | - | ||||||||||||||||||||||||
| 359 | m_invertCharacterClass = invert; | - | ||||||||||||||||||||||||
| 360 | } executed 3557 times by 6 tests: end of blockExecuted by:
| 3557 | ||||||||||||||||||||||||
| 361 | - | |||||||||||||||||||||||||
| 362 | void atomCharacterClassAtom(UChar ch) | - | ||||||||||||||||||||||||
| 363 | { | - | ||||||||||||||||||||||||
| 364 | m_characterClassConstructor.putChar(ch); | - | ||||||||||||||||||||||||
| 365 | } executed 3618 times by 3 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 4 | ||||||||||||||||||||||||
| 477 | - | |||||||||||||||||||||||||
| 478 | m_alternative->m_terms.append(PatternTerm(subpatternId)); | - | ||||||||||||||||||||||||
| 479 | } executed 180 times by 1 test: end of blockExecuted 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 blockExecuted 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 blockExecuted by:
| 58 | ||||||||||||||||||||||||
| 498 | } executed 184 times by 5 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 1051487 | ||||||||||||||||||||||||
| 713 | } executed 1149807 times by 153 tests: end of blockExecuted by:
| 1149807 | ||||||||||||||||||||||||
| 714 | } executed 1149590 times by 153 tests: end of blockExecuted 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 blockExecuted by:
| 6 | ||||||||||||||||||||||||
| 741 | } executed 121 times by 5 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 821 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 822 | } executed 887320 times by 153 tests: end of blockExecuted 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 blockExecuted 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 blockExecuted by:
| 1151010 | ||||||||||||||||||||||||
| 882 | - | |||||||||||||||||||||||||
| 883 | } } | - | ||||||||||||||||||||||||
| Source code | Switch to Preprocessed file |