Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: compiled/filter/RegExpFilter.cpp

Issue 29721753: Issue 6180 - use ABP_TEXT everywhere in order to let String be a UTF-8 string (Closed) Base URL: https://github.com/adblockplus/adblockpluscore.git@adb2678354813ce5b6de095072954c5a784a7bc4
Patch Set: Created March 13, 2018, 6:20 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 TYPE_OBJECT_SUBREQUEST = 0x1000, 45 TYPE_OBJECT_SUBREQUEST = 0x1000,
46 TYPE_MEDIA = 0x4000, 46 TYPE_MEDIA = 0x4000,
47 TYPE_FONT = 0x8000, 47 TYPE_FONT = 0x8000,
48 TYPE_POPUP = 0x8000000, 48 TYPE_POPUP = 0x8000000,
49 TYPE_GENERICBLOCK = 0x10000000, 49 TYPE_GENERICBLOCK = 0x10000000,
50 TYPE_GENERICHIDE = 0x20000000, 50 TYPE_GENERICHIDE = 0x20000000,
51 TYPE_ELEMHIDE = 0x40000000, 51 TYPE_ELEMHIDE = 0x40000000,
52 }; 52 };
53 53
54 const StringMap<int> typeMap { 54 const StringMap<int> typeMap {
55 {u"other"_str, TYPE_OTHER}, 55 {ABP_TEXT("other"_str), TYPE_OTHER},
56 {u"script"_str, TYPE_SCRIPT}, 56 {ABP_TEXT("script"_str), TYPE_SCRIPT},
57 {u"image"_str, TYPE_IMAGE}, 57 {ABP_TEXT("image"_str), TYPE_IMAGE},
58 {u"stylesheet"_str, TYPE_STYLESHEET}, 58 {ABP_TEXT("stylesheet"_str), TYPE_STYLESHEET},
59 {u"object"_str, TYPE_OBJECT}, 59 {ABP_TEXT("object"_str), TYPE_OBJECT},
60 {u"subdocument"_str, TYPE_SUBDOCUMENT}, 60 {ABP_TEXT("subdocument"_str), TYPE_SUBDOCUMENT},
61 {u"document"_str, TYPE_DOCUMENT}, 61 {ABP_TEXT("document"_str), TYPE_DOCUMENT},
62 {u"websocket"_str, TYPE_WEBSOCKET}, 62 {ABP_TEXT("websocket"_str), TYPE_WEBSOCKET},
63 {u"webrtc"_str, TYPE_WEBRTC}, 63 {ABP_TEXT("webrtc"_str), TYPE_WEBRTC},
64 {u"xbl"_str, TYPE_OTHER}, // Backwards compat 64 {ABP_TEXT("xbl"_str), TYPE_OTHER}, // Backwards compat
65 {u"ping"_str, TYPE_PING}, 65 {ABP_TEXT("ping"_str), TYPE_PING},
66 {u"xmlhttprequest"_str, TYPE_XMLHTTPREQUEST}, 66 {ABP_TEXT("xmlhttprequest"_str), TYPE_XMLHTTPREQUEST},
67 {u"object-subrequest"_str, TYPE_OBJECT_SUBREQUEST}, 67 {ABP_TEXT("object-subrequest"_str), TYPE_OBJECT_SUBREQUEST},
68 {u"dtd"_str, TYPE_OTHER}, // Backwards compat 68 {ABP_TEXT("dtd"_str), TYPE_OTHER}, // Backwards compat
69 {u"media"_str, TYPE_MEDIA}, 69 {ABP_TEXT("media"_str), TYPE_MEDIA},
70 {u"font"_str, TYPE_FONT}, 70 {ABP_TEXT("font"_str), TYPE_FONT},
71 {u"background"_str, TYPE_IMAGE}, // Backwards compat 71 {ABP_TEXT("background"_str), TYPE_IMAGE}, // Backwards compat
72 72
73 {u"popup"_str, TYPE_POPUP}, 73 {ABP_TEXT("popup"_str), TYPE_POPUP},
74 {u"genericblock"_str, TYPE_GENERICBLOCK}, 74 {ABP_TEXT("genericblock"_str), TYPE_GENERICBLOCK},
75 {u"generichide"_str, TYPE_GENERICHIDE}, 75 {ABP_TEXT("generichide"_str), TYPE_GENERICHIDE},
76 {u"elemhide"_str, TYPE_ELEMHIDE}, 76 {ABP_TEXT("elemhide"_str), TYPE_ELEMHIDE},
77 }; 77 };
78 78
79 const int defaultTypeMask = INT_MAX & ~(TYPE_DOCUMENT | TYPE_ELEMHIDE | 79 const int defaultTypeMask = INT_MAX & ~(TYPE_DOCUMENT | TYPE_ELEMHIDE |
80 TYPE_POPUP | TYPE_GENERICBLOCK | TYPE_GENERICHIDE); 80 TYPE_POPUP | TYPE_GENERICBLOCK | TYPE_GENERICHIDE);
81 81
82 OwnedString RegExpFromSource(const String& source) 82 OwnedString RegExpFromSource(const String& source)
83 { 83 {
84 /* TODO: this is very inefficient */ 84 /* TODO: this is very inefficient */
85 85
86 // Note: This doesn't remove trailing wildcards, otherwise the result should 86 // Note: This doesn't remove trailing wildcards, otherwise the result should
87 // be identical to Filter.toRegExp(). 87 // be identical to Filter.toRegExp().
88 OwnedString result; 88 OwnedString result;
89 String::value_type prevChar = u'*'; 89 String::value_type prevChar = ABP_TEXT('*');
90 for (String::size_type i = 0; i < source.length(); ++i) 90 for (String::size_type i = 0; i < source.length(); ++i)
91 { 91 {
92 String::value_type currChar = source[i]; 92 String::value_type currChar = source[i];
93 switch (currChar) 93 switch (currChar)
94 { 94 {
95 case u'*': 95 case ABP_TEXT('*'):
96 if (prevChar != u'*') 96 if (prevChar != ABP_TEXT('*'))
97 result.append(u".*"_str); 97 result.append(ABP_TEXT(".*"_str));
98 break; 98 break;
99 case u'^': 99 case ABP_TEXT('^'):
100 result.append(u"(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\ \x60\\x7B-\\x7F]|$)"_str); 100 result.append(ABP_TEXT("(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5 B-\\x5E\\x60\\x7B-\\x7F]|$)"_str));
101 break; 101 break;
102 case u'|': 102 case ABP_TEXT('|'):
103 if (i == 0) 103 if (i == 0)
104 { 104 {
105 // Anchor at expression start, maybe extended anchor? 105 // Anchor at expression start, maybe extended anchor?
106 if (i + 1 < source.length() && source[i + 1] == u'|') 106 if (i + 1 < source.length() && source[i + 1] == ABP_TEXT('|'))
107 { 107 {
108 result.append(u"^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?"_str); 108 result.append(ABP_TEXT("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?"_str ));
109 ++i; 109 ++i;
110 } 110 }
111 else 111 else
112 result.append(u'^'); 112 result.append(ABP_TEXT('^'));
113 } 113 }
114 else if (i == source.length() - 1) 114 else if (i == source.length() - 1)
115 { 115 {
116 // Anchor at expression end, ignore if following separator placehold er 116 // Anchor at expression end, ignore if following separator placehold er
117 if (prevChar != u'^') 117 if (prevChar != ABP_TEXT('^'))
118 result.append(u'$'); 118 result.append(ABP_TEXT('$'));
119 } 119 }
120 else 120 else
121 { 121 {
122 // Not actually an anchor, escape it 122 // Not actually an anchor, escape it
123 result.append(u"\\|"_str); 123 result.append(ABP_TEXT("\\|"_str));
124 } 124 }
125 break; 125 break;
126 default: 126 default:
127 if (!(currChar >= u'a' && currChar <= u'z') && 127 if (!(currChar >= ABP_TEXT('a') && currChar <= ABP_TEXT('z')) &&
128 !(currChar >= u'A' && currChar <= u'Z') && 128 !(currChar >= ABP_TEXT('A') && currChar <= ABP_TEXT('Z')) &&
129 !(currChar >= u'0' && currChar <= u'9') && 129 !(currChar >= ABP_TEXT('0') && currChar <= ABP_TEXT('9')) &&
130 currChar < 128) 130 currChar < 128)
131 { 131 {
132 result.append(u'\\'); 132 result.append(u'\\');
133 } 133 }
134 result.append(currChar); 134 result.append(currChar);
135 } 135 }
136 prevChar = currChar; 136 prevChar = currChar;
137 } 137 }
138 return result; 138 return result;
139 } 139 }
140 140
141 void NormalizeWhitespace(DependentString& text) 141 void NormalizeWhitespace(DependentString& text)
142 { 142 {
143 // We want to remove all spaces but bail out early in the common scenario 143 // We want to remove all spaces but bail out early in the common scenario
144 // that the string contains no spaces. 144 // that the string contains no spaces.
145 145
146 // Look for the first space 146 // Look for the first space
147 String::size_type len = text.length(); 147 String::size_type len = text.length();
148 String::size_type pos; 148 String::size_type pos;
149 for (pos = 0; pos < len; pos++) 149 for (pos = 0; pos < len; pos++)
150 if (text[pos] == ' ') 150 if (text[pos] == ABP_TEXT(' '))
151 break; 151 break;
152 152
153 if (pos >= len) 153 if (pos >= len)
154 return; 154 return;
155 155
156 // Found spaces, move characters to remove them 156 // Found spaces, move characters to remove them
157 String::size_type delta = 1; 157 String::size_type delta = 1;
158 for (pos = pos + 1; pos < len; pos++) 158 for (pos = pos + 1; pos < len; pos++)
159 { 159 {
160 if (text[pos] == ' ') 160 if (text[pos] == ABP_TEXT(' '))
161 delta++; 161 delta++;
162 else 162 else
163 text[pos - delta] = text[pos]; 163 text[pos - delta] = text[pos];
164 } 164 }
165 text.reset(text, 0, len - delta); 165 text.reset(text, 0, len - delta);
166 } 166 }
167 167
168 void ParseOption(String& text, DependentString& error, RegExpFilterData& data, 168 void ParseOption(String& text, DependentString& error, RegExpFilterData& data,
169 int optionStart, int optionEnd, int valueStart, int valueEnd) 169 int optionStart, int optionEnd, int valueStart, int valueEnd)
170 { 170 {
171 if (optionEnd <= optionStart) 171 if (optionEnd <= optionStart)
172 return; 172 return;
173 173
174 bool reverse = false; 174 bool reverse = false;
175 if (text[optionStart] == u'~') 175 if (text[optionStart] == ABP_TEXT('~'))
176 { 176 {
177 reverse = true; 177 reverse = true;
178 optionStart++; 178 optionStart++;
179 } 179 }
180 180
181 DependentString name(text, optionStart, optionEnd - optionStart); 181 DependentString name(text, optionStart, optionEnd - optionStart);
182 for (size_t i = 0; i < name.length(); ++i) 182 for (size_t i = 0; i < name.length(); ++i)
183 { 183 {
184 char16_t currChar = name[i]; 184 char16_t currChar = name[i];
185 if (currChar >= u'A' && currChar <= u'Z') 185 if (currChar >= ABP_TEXT('A') && currChar <= ABP_TEXT('Z'))
186 name[i] = currChar + u'a' - u'A'; 186 name[i] = currChar + ABP_TEXT('a') - ABP_TEXT('A');
187 else if (currChar == u'_') 187 else if (currChar == ABP_TEXT('_'))
188 name[i] = u'-'; 188 name[i] = ABP_TEXT('-');
189 } 189 }
190 190
191 auto it = typeMap.find(name); 191 auto it = typeMap.find(name);
192 if (it) 192 if (it)
193 { 193 {
194 if (data.mContentType < 0) 194 if (data.mContentType < 0)
195 data.mContentType = reverse ? defaultTypeMask : 0; 195 data.mContentType = reverse ? defaultTypeMask : 0;
196 if (reverse) 196 if (reverse)
197 data.mContentType &= ~it->second; 197 data.mContentType &= ~it->second;
198 else 198 else
199 data.mContentType |= it->second; 199 data.mContentType |= it->second;
200 } 200 }
201 else if (name.equals(u"domain"_str)) 201 else if (name.equals(ABP_TEXT("domain"_str)))
202 { 202 {
203 if (valueStart >= 0 && valueEnd > valueStart) 203 if (valueStart >= 0 && valueEnd > valueStart)
204 { 204 {
205 data.mDomainsStart = valueStart; 205 data.mDomainsStart = valueStart;
206 data.mDomainsEnd = valueEnd; 206 data.mDomainsEnd = valueEnd;
207 DependentString(text, valueStart, valueEnd - valueStart).toLower(); 207 DependentString(text, valueStart, valueEnd - valueStart).toLower();
208 } 208 }
209 } 209 }
210 else if (name.equals(u"sitekey"_str)) 210 else if (name.equals(ABP_TEXT("sitekey"_str)))
211 { 211 {
212 if (valueStart >= 0 && valueEnd > valueStart) 212 if (valueStart >= 0 && valueEnd > valueStart)
213 { 213 {
214 data.mSitekeysStart = valueStart; 214 data.mSitekeysStart = valueStart;
215 data.mSitekeysEnd = valueEnd; 215 data.mSitekeysEnd = valueEnd;
216 } 216 }
217 } 217 }
218 else if (name.equals(u"match-case"_str)) 218 else if (name.equals(ABP_TEXT("match-case"_str)))
219 data.mMatchCase = !reverse; 219 data.mMatchCase = !reverse;
220 else if (name.equals(u"third-party"_str)) 220 else if (name.equals(ABP_TEXT("third-party"_str)))
221 data.mThirdParty = reverse ? TrippleState::NO : TrippleState::YES; 221 data.mThirdParty = reverse ? TrippleState::NO : TrippleState::YES;
222 else if (name.equals(u"collapse"_str)) 222 else if (name.equals(ABP_TEXT("collapse"_str)))
223 data.mCollapse = !reverse; 223 data.mCollapse = !reverse;
224 else 224 else
225 error.reset(u"filter_unknown_option"_str); 225 error.reset(ABP_TEXT("filter_unknown_option"_str));
226 } 226 }
227 227
228 void ParseOptions(String& text, DependentString& error, RegExpFilterData& data , 228 void ParseOptions(String& text, DependentString& error, RegExpFilterData& data ,
229 String::size_type optionsStart) 229 String::size_type optionsStart)
230 { 230 {
231 data.mMatchCase = false; 231 data.mMatchCase = false;
232 data.mThirdParty = TrippleState::ANY; 232 data.mThirdParty = TrippleState::ANY;
233 data.mCollapse = true; 233 data.mCollapse = true;
234 data.mDomainsStart = String::npos; 234 data.mDomainsStart = String::npos;
235 data.mSitekeysStart = String::npos; 235 data.mSitekeysStart = String::npos;
236 if (optionsStart >= text.length()) 236 if (optionsStart >= text.length())
237 { 237 {
238 data.mContentType = defaultTypeMask; 238 data.mContentType = defaultTypeMask;
239 return; 239 return;
240 } 240 }
241 241
242 data.mContentType = -1; 242 data.mContentType = -1;
243 243
244 int optionStart = data.mPatternEnd + 1; 244 int optionStart = data.mPatternEnd + 1;
245 int optionEnd = -1; 245 int optionEnd = -1;
246 int valueStart = -1; 246 int valueStart = -1;
247 247
248 StringScanner scanner(text, optionStart, u','); 248 StringScanner scanner(text, optionStart, ABP_TEXT(','));
249 bool done = false; 249 bool done = false;
250 while (!done) 250 while (!done)
251 { 251 {
252 done = scanner.done(); 252 done = scanner.done();
253 switch (scanner.next()) 253 switch (scanner.next())
254 { 254 {
255 case u'=': 255 case ABP_TEXT('='):
256 if (optionEnd < 0) 256 if (optionEnd < 0)
257 { 257 {
258 optionEnd = scanner.position(); 258 optionEnd = scanner.position();
259 valueStart = optionEnd + 1; 259 valueStart = optionEnd + 1;
260 } 260 }
261 break; 261 break;
262 case u',': 262 case ABP_TEXT(','):
263 if (optionEnd < 0) 263 if (optionEnd < 0)
264 optionEnd = scanner.position(); 264 optionEnd = scanner.position();
265 ParseOption(text, error, data, optionStart, optionEnd, valueStart, 265 ParseOption(text, error, data, optionStart, optionEnd, valueStart,
266 scanner.position()); 266 scanner.position());
267 if (!error.empty()) 267 if (!error.empty())
268 return; 268 return;
269 269
270 optionStart = scanner.position() + 1; 270 optionStart = scanner.position() + 1;
271 optionEnd = -1; 271 optionEnd = -1;
272 valueStart = -1; 272 valueStart = -1;
(...skipping 18 matching lines...) Expand all
291 } 291 }
292 292
293 Filter::Type RegExpFilter::Parse(DependentString& text, DependentString& error, 293 Filter::Type RegExpFilter::Parse(DependentString& text, DependentString& error,
294 RegExpFilterData& data) 294 RegExpFilterData& data)
295 { 295 {
296 NormalizeWhitespace(text); 296 NormalizeWhitespace(text);
297 297
298 Filter::Type type = Type::BLOCKING; 298 Filter::Type type = Type::BLOCKING;
299 299
300 data.mPatternStart = 0; 300 data.mPatternStart = 0;
301 if (text.length() >= 2 && text[0] == u'@' && text[1] == u'@') 301 if (text.length() >= 2 && text[0] == ABP_TEXT('@') && text[1] == ABP_TEXT('@') )
302 { 302 {
303 type = Type::WHITELIST; 303 type = Type::WHITELIST;
304 data.mPatternStart = 2; 304 data.mPatternStart = 2;
305 } 305 }
306 306
307 data.mPatternEnd = text.find(u'$', data.mPatternStart); 307 data.mPatternEnd = text.find(ABP_TEXT('$'), data.mPatternStart);
308 if (data.mPatternEnd == text.npos) 308 if (data.mPatternEnd == text.npos)
309 data.mPatternEnd = text.length(); 309 data.mPatternEnd = text.length();
310 310
311 ParseOptions(text, error, data, data.mPatternEnd + 1); 311 ParseOptions(text, error, data, data.mPatternEnd + 1);
312 if (!error.empty()) 312 if (!error.empty())
313 return Type::INVALID; 313 return Type::INVALID;
314 314
315 if (data.mPatternEnd - data.mPatternStart >= 2 && 315 if (data.mPatternEnd - data.mPatternStart >= 2 &&
316 text[data.mPatternStart] == u'/' && 316 text[data.mPatternStart] == ABP_TEXT('/') &&
317 text[data.mPatternEnd - 1] == u'/') 317 text[data.mPatternEnd - 1] == ABP_TEXT('/'))
318 { 318 {
319 data.SetRegExp(GenerateRegExp(DependentString(text, data.mPatternStart + 1, 319 data.SetRegExp(GenerateRegExp(DependentString(text, data.mPatternStart + 1,
320 data.mPatternEnd - data.mPatternStart - 2), data.mMatchCase)); 320 data.mPatternEnd - data.mPatternStart - 2), data.mMatchCase));
321 if (data.mRegexpId == -1) 321 if (data.mRegexpId == -1)
322 { 322 {
323 error.reset(u"filter_invalid_regexp"_str); 323 error.reset(ABP_TEXT("filter_invalid_regexp"_str));
324 return Type::INVALID; 324 return Type::INVALID;
325 } 325 }
326 } 326 }
327 327
328 return type; 328 return type;
329 } 329 }
330 330
331 void RegExpFilter::ParseSitekeys(const String& sitekeys) const 331 void RegExpFilter::ParseSitekeys(const String& sitekeys) const
332 { 332 {
333 StringScanner scanner(sitekeys, 0, u'|'); 333 StringScanner scanner(sitekeys, 0, ABP_TEXT('|'));
334 size_t start = 0; 334 size_t start = 0;
335 bool done = false; 335 bool done = false;
336 while (!done) 336 while (!done)
337 { 337 {
338 done = scanner.done(); 338 done = scanner.done();
339 if (scanner.next() == u'|') 339 if (scanner.next() == ABP_TEXT('|'))
340 { 340 {
341 if (scanner.position() > start) 341 if (scanner.position() > start)
342 AddSitekey(DependentString(sitekeys, start, scanner.position() - start)) ; 342 AddSitekey(DependentString(sitekeys, start, scanner.position() - start)) ;
343 start = scanner.position() + 1; 343 start = scanner.position() + 1;
344 } 344 }
345 } 345 }
346 } 346 }
347 347
348 void RegExpFilter::GenerateCustomBindings() 348 void RegExpFilter::GenerateCustomBindings()
349 { 349 {
350 printf("exports.RegExpFilter.typeMap = {\n"); 350 printf("exports.RegExpFilter.typeMap = {\n");
351 351
352 for (const auto& item : typeMap) 352 for (const auto& item : typeMap)
353 { 353 {
354 std::string type(item.first.length(), '\0'); 354 std::string type(item.first.length(), '\0');
355 for (String::size_type i = 0; i < item.first.length(); i++) 355 for (String::size_type i = 0; i < item.first.length(); i++)
356 type[i] = (item.first[i] == '-' ? '_' : toupper(item.first[i])); 356 type[i] = item.first[i] == ABP_TEXT('-') ? '_' : toupper(item.first[i]);
357 printf(" %s: %i,\n", type.c_str(), item.second); 357 printf(" %s: %i,\n", type.c_str(), item.second);
358 } 358 }
359 printf("};\n"); 359 printf("};\n");
360 } 360 }
361 361
362 RegExpFilter::DomainMap* RegExpFilter::GetDomains() const 362 RegExpFilter::DomainMap* RegExpFilter::GetDomains() const
363 { 363 {
364 if (!mData.DomainsParsingDone()) 364 if (!mData.DomainsParsingDone())
365 { 365 {
366 ParseDomains(mData.GetDomainsSource(mText), u'|'); 366 ParseDomains(mData.GetDomainsSource(mText), ABP_TEXT('|'));
367 mData.SetDomainsParsingDone(); 367 mData.SetDomainsParsingDone();
368 } 368 }
369 return ActiveFilter::GetDomains(); 369 return ActiveFilter::GetDomains();
370 } 370 }
371 371
372 RegExpFilter::SitekeySet* RegExpFilter::GetSitekeys() const 372 RegExpFilter::SitekeySet* RegExpFilter::GetSitekeys() const
373 { 373 {
374 if (!mData.SitekeyParsingDone()) 374 if (!mData.SitekeyParsingDone())
375 { 375 {
376 ParseSitekeys(mData.GetSitekeysSource(mText)); 376 ParseSitekeys(mData.GetSitekeysSource(mText));
(...skipping 13 matching lines...) Expand all
390 return false; 390 return false;
391 } 391 }
392 392
393 if (!mData.RegExpParsingDone()) 393 if (!mData.RegExpParsingDone())
394 { 394 {
395 const OwnedString pattern(mData.GetRegExpSource(mText)); 395 const OwnedString pattern(mData.GetRegExpSource(mText));
396 mData.SetRegExp(GenerateRegExp(RegExpFromSource(pattern), mData.mMatchCase)) ; 396 mData.SetRegExp(GenerateRegExp(RegExpFromSource(pattern), mData.mMatchCase)) ;
397 } 397 }
398 return TestRegExp(mData.mRegexpId, location); 398 return TestRegExp(mData.mRegexpId, location);
399 } 399 }
OLDNEW
« compiled/String.h ('K') | « compiled/filter/Filter.cpp ('k') | compiled/intrusive_ptr.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld