OLD | NEW |
1 // Copyright 2003-2009 Google Inc. All rights reserved. | 1 // Copyright 2003-2009 Google Inc. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // This is a variant of PCRE's pcrecpp.cc, originally written at Google. | 5 // This is a variant of PCRE's pcrecpp.cc, originally written at Google. |
6 // The main changes are the addition of the HitLimit method and | 6 // The main changes are the addition of the HitLimit method and |
7 // compilation as PCRE in namespace re2. | 7 // compilation as PCRE in namespace re2. |
8 | 8 |
9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <limits> |
10 #include "util/util.h" | 11 #include "util/util.h" |
11 #include "util/flags.h" | 12 #include "util/flags.h" |
12 #include "util/pcre.h" | 13 #include "util/pcre.h" |
13 | 14 |
14 #ifdef WIN32 | |
15 #define strtoll _strtoi64 | |
16 #define strtoull _strtoui64 | |
17 #endif | |
18 | |
19 #define PCREPORT(level) LOG(level) | 15 #define PCREPORT(level) LOG(level) |
20 | 16 |
21 // Default PCRE limits. | 17 // Default PCRE limits. |
22 // Defaults chosen to allow a plausible amount of CPU and | 18 // Defaults chosen to allow a plausible amount of CPU and |
23 // not exceed main thread stacks. Note that other threads | 19 // not exceed main thread stacks. Note that other threads |
24 // often have smaller stacks, and therefore tightening | 20 // often have smaller stacks, and therefore tightening |
25 // regexp_stack_limit may frequently be necessary. | 21 // regexp_stack_limit may frequently be necessary. |
26 DEFINE_int32(regexp_stack_limit, 256<<10, "default PCRE stack limit (bytes)"); | 22 DEFINE_int32(regexp_stack_limit, 256<<10, "default PCRE stack limit (bytes)"); |
27 DEFINE_int32(regexp_match_limit, 1000000, | 23 DEFINE_int32(regexp_match_limit, 1000000, |
28 "default PCRE match limit (function calls)"); | 24 "default PCRE match limit (function calls)"); |
29 | 25 |
| 26 #ifndef USEPCRE |
| 27 |
| 28 // Fake just enough of the PCRE API to allow this file to build. :) |
| 29 |
| 30 struct pcre_extra { |
| 31 int flags; |
| 32 int match_limit; |
| 33 int match_limit_recursion; |
| 34 }; |
| 35 |
| 36 #define PCRE_EXTRA_MATCH_LIMIT 0 |
| 37 #define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0 |
| 38 #define PCRE_ANCHORED 0 |
| 39 #define PCRE_NOTEMPTY 0 |
| 40 #define PCRE_ERROR_NOMATCH 1 |
| 41 #define PCRE_ERROR_MATCHLIMIT 2 |
| 42 #define PCRE_ERROR_RECURSIONLIMIT 3 |
| 43 #define PCRE_INFO_CAPTURECOUNT 0 |
| 44 |
| 45 void pcre_free(void*) { |
| 46 } |
| 47 |
| 48 pcre* pcre_compile(const char*, int, const char**, int*, const unsigned char*) { |
| 49 return NULL; |
| 50 } |
| 51 |
| 52 int pcre_exec(const pcre*, const pcre_extra*, const char*, int, int, int, int*,
int) { |
| 53 return 0; |
| 54 } |
| 55 |
| 56 int pcre_fullinfo(const pcre*, const pcre_extra*, int, void*) { |
| 57 return 0; |
| 58 } |
| 59 |
| 60 #endif |
| 61 |
30 namespace re2 { | 62 namespace re2 { |
31 | 63 |
32 // Maximum number of args we can set | 64 // Maximum number of args we can set |
33 static const int kMaxArgs = 16; | 65 static const int kMaxArgs = 16; |
34 static const int kVecSize = (1 + kMaxArgs) * 3; // results + PCRE workspace | 66 static const int kVecSize = (1 + kMaxArgs) * 3; // results + PCRE workspace |
35 | 67 |
36 // Approximate size of a recursive invocation of PCRE's | 68 // Approximate size of a recursive invocation of PCRE's |
37 // internal "match()" frame. This varies depending on the | 69 // internal "match()" frame. This varies depending on the |
38 // compiler and architecture, of course, so the constant is | 70 // compiler and architecture, of course, so the constant is |
39 // just a conservative estimate. To find the exact number, | 71 // just a conservative estimate. To find the exact number, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 // beginning of a string. | 143 // beginning of a string. |
112 // | 144 // |
113 // There are three types of anchoring we want: | 145 // There are three types of anchoring we want: |
114 // UNANCHORED Compile the original pattern, and use | 146 // UNANCHORED Compile the original pattern, and use |
115 // a pcre unanchored match. | 147 // a pcre unanchored match. |
116 // ANCHOR_START Compile the original pattern, and use | 148 // ANCHOR_START Compile the original pattern, and use |
117 // a pcre anchored match. | 149 // a pcre anchored match. |
118 // ANCHOR_BOTH Tack a "\z" to the end of the original pattern | 150 // ANCHOR_BOTH Tack a "\z" to the end of the original pattern |
119 // and use a pcre anchored match. | 151 // and use a pcre anchored match. |
120 | 152 |
121 const char* error; | 153 const char* error = ""; |
122 int eoffset; | 154 int eoffset; |
123 pcre* re; | 155 pcre* re; |
124 if (anchor != ANCHOR_BOTH) { | 156 if (anchor != ANCHOR_BOTH) { |
125 re = pcre_compile(pattern_.c_str(), | 157 re = pcre_compile(pattern_.c_str(), |
126 (options_ & EnabledCompileOptions), | 158 (options_ & EnabledCompileOptions), |
127 &error, &eoffset, NULL); | 159 &error, &eoffset, NULL); |
128 } else { | 160 } else { |
129 // Tack a '\z' at the end of PCRE. Parenthesize it first so that | 161 // Tack a '\z' at the end of PCRE. Parenthesize it first so that |
130 // the '\z' applies to all top-level alternatives in the regexp. | 162 // the '\z' applies to all top-level alternatives in the regexp. |
131 string wrapped = "(?:"; // A non-counting grouping operator | 163 string wrapped = "(?:"; // A non-counting grouping operator |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 if (&a9 == &no_more_args) goto done; args[n++] = &a9; | 208 if (&a9 == &no_more_args) goto done; args[n++] = &a9; |
177 if (&a10 == &no_more_args) goto done; args[n++] = &a10; | 209 if (&a10 == &no_more_args) goto done; args[n++] = &a10; |
178 if (&a11 == &no_more_args) goto done; args[n++] = &a11; | 210 if (&a11 == &no_more_args) goto done; args[n++] = &a11; |
179 if (&a12 == &no_more_args) goto done; args[n++] = &a12; | 211 if (&a12 == &no_more_args) goto done; args[n++] = &a12; |
180 if (&a13 == &no_more_args) goto done; args[n++] = &a13; | 212 if (&a13 == &no_more_args) goto done; args[n++] = &a13; |
181 if (&a14 == &no_more_args) goto done; args[n++] = &a14; | 213 if (&a14 == &no_more_args) goto done; args[n++] = &a14; |
182 if (&a15 == &no_more_args) goto done; args[n++] = &a15; | 214 if (&a15 == &no_more_args) goto done; args[n++] = &a15; |
183 done: | 215 done: |
184 | 216 |
185 int consumed; | 217 int consumed; |
186 int vec[kVecSize]; | 218 int vec[kVecSize] = {}; |
187 return re.DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize); | 219 return re.DoMatchImpl(text, ANCHOR_BOTH, &consumed, args, n, vec, kVecSize); |
188 } | 220 } |
189 | 221 |
190 bool PCRE::PartialMatchFunctor::operator ()(const StringPiece& text, | 222 bool PCRE::PartialMatchFunctor::operator ()(const StringPiece& text, |
191 const PCRE& re, | 223 const PCRE& re, |
192 const Arg& a0, | 224 const Arg& a0, |
193 const Arg& a1, | 225 const Arg& a1, |
194 const Arg& a2, | 226 const Arg& a2, |
195 const Arg& a3, | 227 const Arg& a3, |
196 const Arg& a4, | 228 const Arg& a4, |
(...skipping 22 matching lines...) Expand all Loading... |
219 if (&a9 == &no_more_args) goto done; args[n++] = &a9; | 251 if (&a9 == &no_more_args) goto done; args[n++] = &a9; |
220 if (&a10 == &no_more_args) goto done; args[n++] = &a10; | 252 if (&a10 == &no_more_args) goto done; args[n++] = &a10; |
221 if (&a11 == &no_more_args) goto done; args[n++] = &a11; | 253 if (&a11 == &no_more_args) goto done; args[n++] = &a11; |
222 if (&a12 == &no_more_args) goto done; args[n++] = &a12; | 254 if (&a12 == &no_more_args) goto done; args[n++] = &a12; |
223 if (&a13 == &no_more_args) goto done; args[n++] = &a13; | 255 if (&a13 == &no_more_args) goto done; args[n++] = &a13; |
224 if (&a14 == &no_more_args) goto done; args[n++] = &a14; | 256 if (&a14 == &no_more_args) goto done; args[n++] = &a14; |
225 if (&a15 == &no_more_args) goto done; args[n++] = &a15; | 257 if (&a15 == &no_more_args) goto done; args[n++] = &a15; |
226 done: | 258 done: |
227 | 259 |
228 int consumed; | 260 int consumed; |
229 int vec[kVecSize]; | 261 int vec[kVecSize] = {}; |
230 return re.DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize); | 262 return re.DoMatchImpl(text, UNANCHORED, &consumed, args, n, vec, kVecSize); |
231 } | 263 } |
232 | 264 |
233 bool PCRE::ConsumeFunctor::operator ()(StringPiece* input, | 265 bool PCRE::ConsumeFunctor::operator ()(StringPiece* input, |
234 const PCRE& pattern, | 266 const PCRE& pattern, |
235 const Arg& a0, | 267 const Arg& a0, |
236 const Arg& a1, | 268 const Arg& a1, |
237 const Arg& a2, | 269 const Arg& a2, |
238 const Arg& a3, | 270 const Arg& a3, |
239 const Arg& a4, | 271 const Arg& a4, |
(...skipping 22 matching lines...) Expand all Loading... |
262 if (&a9 == &no_more_args) goto done; args[n++] = &a9; | 294 if (&a9 == &no_more_args) goto done; args[n++] = &a9; |
263 if (&a10 == &no_more_args) goto done; args[n++] = &a10; | 295 if (&a10 == &no_more_args) goto done; args[n++] = &a10; |
264 if (&a11 == &no_more_args) goto done; args[n++] = &a11; | 296 if (&a11 == &no_more_args) goto done; args[n++] = &a11; |
265 if (&a12 == &no_more_args) goto done; args[n++] = &a12; | 297 if (&a12 == &no_more_args) goto done; args[n++] = &a12; |
266 if (&a13 == &no_more_args) goto done; args[n++] = &a13; | 298 if (&a13 == &no_more_args) goto done; args[n++] = &a13; |
267 if (&a14 == &no_more_args) goto done; args[n++] = &a14; | 299 if (&a14 == &no_more_args) goto done; args[n++] = &a14; |
268 if (&a15 == &no_more_args) goto done; args[n++] = &a15; | 300 if (&a15 == &no_more_args) goto done; args[n++] = &a15; |
269 done: | 301 done: |
270 | 302 |
271 int consumed; | 303 int consumed; |
272 int vec[kVecSize]; | 304 int vec[kVecSize] = {}; |
273 if (pattern.DoMatchImpl(*input, ANCHOR_START, &consumed, | 305 if (pattern.DoMatchImpl(*input, ANCHOR_START, &consumed, |
274 args, n, vec, kVecSize)) { | 306 args, n, vec, kVecSize)) { |
275 input->remove_prefix(consumed); | 307 input->remove_prefix(consumed); |
276 return true; | 308 return true; |
277 } else { | 309 } else { |
278 return false; | 310 return false; |
279 } | 311 } |
280 } | 312 } |
281 | 313 |
282 bool PCRE::FindAndConsumeFunctor::operator ()(StringPiece* input, | 314 bool PCRE::FindAndConsumeFunctor::operator ()(StringPiece* input, |
(...skipping 28 matching lines...) Expand all Loading... |
311 if (&a9 == &no_more_args) goto done; args[n++] = &a9; | 343 if (&a9 == &no_more_args) goto done; args[n++] = &a9; |
312 if (&a10 == &no_more_args) goto done; args[n++] = &a10; | 344 if (&a10 == &no_more_args) goto done; args[n++] = &a10; |
313 if (&a11 == &no_more_args) goto done; args[n++] = &a11; | 345 if (&a11 == &no_more_args) goto done; args[n++] = &a11; |
314 if (&a12 == &no_more_args) goto done; args[n++] = &a12; | 346 if (&a12 == &no_more_args) goto done; args[n++] = &a12; |
315 if (&a13 == &no_more_args) goto done; args[n++] = &a13; | 347 if (&a13 == &no_more_args) goto done; args[n++] = &a13; |
316 if (&a14 == &no_more_args) goto done; args[n++] = &a14; | 348 if (&a14 == &no_more_args) goto done; args[n++] = &a14; |
317 if (&a15 == &no_more_args) goto done; args[n++] = &a15; | 349 if (&a15 == &no_more_args) goto done; args[n++] = &a15; |
318 done: | 350 done: |
319 | 351 |
320 int consumed; | 352 int consumed; |
321 int vec[kVecSize]; | 353 int vec[kVecSize] = {}; |
322 if (pattern.DoMatchImpl(*input, UNANCHORED, &consumed, | 354 if (pattern.DoMatchImpl(*input, UNANCHORED, &consumed, |
323 args, n, vec, kVecSize)) { | 355 args, n, vec, kVecSize)) { |
324 input->remove_prefix(consumed); | 356 input->remove_prefix(consumed); |
325 return true; | 357 return true; |
326 } else { | 358 } else { |
327 return false; | 359 return false; |
328 } | 360 } |
329 } | 361 } |
330 | 362 |
331 bool PCRE::Replace(string *str, | 363 bool PCRE::Replace(string *str, |
332 const PCRE& pattern, | 364 const PCRE& pattern, |
333 const StringPiece& rewrite) { | 365 const StringPiece& rewrite) { |
334 int vec[kVecSize]; | 366 int vec[kVecSize] = {}; |
335 int matches = pattern.TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize); | 367 int matches = pattern.TryMatch(*str, 0, UNANCHORED, true, vec, kVecSize); |
336 if (matches == 0) | 368 if (matches == 0) |
337 return false; | 369 return false; |
338 | 370 |
339 string s; | 371 string s; |
340 if (!pattern.Rewrite(&s, rewrite, *str, vec, matches)) | 372 if (!pattern.Rewrite(&s, rewrite, *str, vec, matches)) |
341 return false; | 373 return false; |
342 | 374 |
343 assert(vec[0] >= 0); | 375 assert(vec[0] >= 0); |
344 assert(vec[1] >= 0); | 376 assert(vec[1] >= 0); |
345 str->replace(vec[0], vec[1] - vec[0], s); | 377 str->replace(vec[0], vec[1] - vec[0], s); |
346 return true; | 378 return true; |
347 } | 379 } |
348 | 380 |
349 int PCRE::GlobalReplace(string *str, | 381 int PCRE::GlobalReplace(string *str, |
350 const PCRE& pattern, | 382 const PCRE& pattern, |
351 const StringPiece& rewrite) { | 383 const StringPiece& rewrite) { |
352 int count = 0; | 384 int count = 0; |
353 int vec[kVecSize]; | 385 int vec[kVecSize] = {}; |
354 string out; | 386 string out; |
355 int start = 0; | 387 int start = 0; |
356 bool last_match_was_empty_string = false; | 388 bool last_match_was_empty_string = false; |
357 | 389 |
358 for (; start <= str->length();) { | 390 while (start <= static_cast<int>(str->size())) { |
359 // If the previous match was for the empty string, we shouldn't | 391 // If the previous match was for the empty string, we shouldn't |
360 // just match again: we'll match in the same way and get an | 392 // just match again: we'll match in the same way and get an |
361 // infinite loop. Instead, we do the match in a special way: | 393 // infinite loop. Instead, we do the match in a special way: |
362 // anchored -- to force another try at the same position -- | 394 // anchored -- to force another try at the same position -- |
363 // and with a flag saying that this time, ignore empty matches. | 395 // and with a flag saying that this time, ignore empty matches. |
364 // If this special match returns, that means there's a non-empty | 396 // If this special match returns, that means there's a non-empty |
365 // match at this position as well, and we can continue. If not, | 397 // match at this position as well, and we can continue. If not, |
366 // we do what perl does, and just advance by one. | 398 // we do what perl does, and just advance by one. |
367 // Notice that perl prints '@@@' for this; | 399 // Notice that perl prints '@@@' for this; |
368 // perl -le '$_ = "aa"; s/b*|aa/@/g; print' | 400 // perl -le '$_ = "aa"; s/b*|aa/@/g; print' |
369 int matches; | 401 int matches; |
370 if (last_match_was_empty_string) { | 402 if (last_match_was_empty_string) { |
371 matches = pattern.TryMatch(*str, start, ANCHOR_START, false, | 403 matches = pattern.TryMatch(*str, start, ANCHOR_START, false, |
372 vec, kVecSize); | 404 vec, kVecSize); |
373 if (matches <= 0) { | 405 if (matches <= 0) { |
374 if (start < str->length()) | 406 if (start < static_cast<int>(str->size())) |
375 out.push_back((*str)[start]); | 407 out.push_back((*str)[start]); |
376 start++; | 408 start++; |
377 last_match_was_empty_string = false; | 409 last_match_was_empty_string = false; |
378 continue; | 410 continue; |
379 } | 411 } |
380 } else { | 412 } else { |
381 matches = pattern.TryMatch(*str, start, UNANCHORED, true, vec, kVecSize); | 413 matches = pattern.TryMatch(*str, start, UNANCHORED, true, |
| 414 vec, kVecSize); |
382 if (matches <= 0) | 415 if (matches <= 0) |
383 break; | 416 break; |
384 } | 417 } |
385 int matchstart = vec[0], matchend = vec[1]; | 418 int matchstart = vec[0], matchend = vec[1]; |
386 assert(matchstart >= start); | 419 assert(matchstart >= start); |
387 assert(matchend >= matchstart); | 420 assert(matchend >= matchstart); |
388 | 421 |
389 out.append(*str, start, matchstart - start); | 422 out.append(*str, start, matchstart - start); |
390 pattern.Rewrite(&out, rewrite, *str, vec, matches); | 423 pattern.Rewrite(&out, rewrite, *str, vec, matches); |
391 start = matchend; | 424 start = matchend; |
392 count++; | 425 count++; |
393 last_match_was_empty_string = (matchstart == matchend); | 426 last_match_was_empty_string = (matchstart == matchend); |
394 } | 427 } |
395 | 428 |
396 if (count == 0) | 429 if (count == 0) |
397 return 0; | 430 return 0; |
398 | 431 |
399 if (start < str->length()) | 432 if (start < static_cast<int>(str->size())) |
400 out.append(*str, start, str->length() - start); | 433 out.append(*str, start, static_cast<int>(str->size()) - start); |
401 swap(out, *str); | 434 swap(out, *str); |
402 return count; | 435 return count; |
403 } | 436 } |
404 | 437 |
405 bool PCRE::Extract(const StringPiece &text, | 438 bool PCRE::Extract(const StringPiece &text, |
406 const PCRE& pattern, | 439 const PCRE& pattern, |
407 const StringPiece &rewrite, | 440 const StringPiece &rewrite, |
408 string *out) { | 441 string *out) { |
409 int vec[kVecSize]; | 442 int vec[kVecSize] = {}; |
410 int matches = pattern.TryMatch(text, 0, UNANCHORED, true, vec, kVecSize); | 443 int matches = pattern.TryMatch(text, 0, UNANCHORED, true, vec, kVecSize); |
411 if (matches == 0) | 444 if (matches == 0) |
412 return false; | 445 return false; |
413 out->clear(); | 446 out->clear(); |
414 return pattern.Rewrite(out, rewrite, text, vec, matches); | 447 return pattern.Rewrite(out, rewrite, text, vec, matches); |
415 } | 448 } |
416 | 449 |
417 string PCRE::QuoteMeta(const StringPiece& unquoted) { | 450 string PCRE::QuoteMeta(const StringPiece& unquoted) { |
418 string result; | 451 string result; |
419 result.reserve(unquoted.size() << 1); | 452 result.reserve(unquoted.size() << 1); |
(...skipping 25 matching lines...) Expand all Loading... |
445 } | 478 } |
446 result += unquoted[ii]; | 479 result += unquoted[ii]; |
447 } | 480 } |
448 | 481 |
449 return result; | 482 return result; |
450 } | 483 } |
451 | 484 |
452 /***** Actual matching and rewriting code *****/ | 485 /***** Actual matching and rewriting code *****/ |
453 | 486 |
454 bool PCRE::HitLimit() { | 487 bool PCRE::HitLimit() { |
455 return hit_limit_; | 488 return hit_limit_ != 0; |
456 } | 489 } |
457 | 490 |
458 void PCRE::ClearHitLimit() { | 491 void PCRE::ClearHitLimit() { |
459 hit_limit_ = 0; | 492 hit_limit_ = 0; |
460 } | 493 } |
461 | 494 |
462 int PCRE::TryMatch(const StringPiece& text, | 495 int PCRE::TryMatch(const StringPiece& text, |
463 int startpos, | 496 int startpos, |
464 Anchor anchor, | 497 Anchor anchor, |
465 bool empty_ok, | 498 bool empty_ok, |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 | 626 |
594 return true; | 627 return true; |
595 } | 628 } |
596 | 629 |
597 bool PCRE::DoMatch(const StringPiece& text, | 630 bool PCRE::DoMatch(const StringPiece& text, |
598 Anchor anchor, | 631 Anchor anchor, |
599 int* consumed, | 632 int* consumed, |
600 const Arg* const args[], | 633 const Arg* const args[], |
601 int n) const { | 634 int n) const { |
602 assert(n >= 0); | 635 assert(n >= 0); |
603 size_t const vecsize = (1 + n) * 3; // results + PCRE workspace | 636 const int vecsize = (1 + n) * 3; // results + PCRE workspace |
604 // (as for kVecSize) | 637 // (as for kVecSize) |
605 int *vec = new int[vecsize]; | 638 int* vec = new int[vecsize]; |
606 bool b = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize); | 639 bool b = DoMatchImpl(text, anchor, consumed, args, n, vec, vecsize); |
607 delete[] vec; | 640 delete[] vec; |
608 return b; | 641 return b; |
609 } | 642 } |
610 | 643 |
611 bool PCRE::Rewrite(string *out, const StringPiece &rewrite, | 644 bool PCRE::Rewrite(string *out, const StringPiece &rewrite, |
612 const StringPiece &text, int *vec, int veclen) const { | 645 const StringPiece &text, int *vec, int veclen) const { |
613 int number_of_capturing_groups = NumberOfCapturingGroups(); | 646 int number_of_capturing_groups = NumberOfCapturingGroups(); |
614 for (const char *s = rewrite.data(), *end = s + rewrite.size(); | 647 for (const char *s = rewrite.data(), *end = s + rewrite.size(); |
615 s < end; s++) { | 648 s < end; s++) { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 } | 834 } |
802 | 835 |
803 bool PCRE::Arg::parse_short_radix(const char* str, | 836 bool PCRE::Arg::parse_short_radix(const char* str, |
804 int n, | 837 int n, |
805 void* dest, | 838 void* dest, |
806 int radix) { | 839 int radix) { |
807 long r; | 840 long r; |
808 if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse | 841 if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse |
809 if ((short)r != r) return false; // Out of range | 842 if ((short)r != r) return false; // Out of range |
810 if (dest == NULL) return true; | 843 if (dest == NULL) return true; |
811 *(reinterpret_cast<short*>(dest)) = r; | 844 *(reinterpret_cast<short*>(dest)) = (short)r; |
812 return true; | 845 return true; |
813 } | 846 } |
814 | 847 |
815 bool PCRE::Arg::parse_ushort_radix(const char* str, | 848 bool PCRE::Arg::parse_ushort_radix(const char* str, |
816 int n, | 849 int n, |
817 void* dest, | 850 void* dest, |
818 int radix) { | 851 int radix) { |
819 unsigned long r; | 852 unsigned long r; |
820 if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse | 853 if (!parse_ulong_radix(str, n, &r, radix)) return false; // Could not parse |
821 if ((ushort)r != r) return false; // Out of range | 854 if ((ushort)r != r) return false; // Out of range |
822 if (dest == NULL) return true; | 855 if (dest == NULL) return true; |
823 *(reinterpret_cast<unsigned short*>(dest)) = r; | 856 *(reinterpret_cast<unsigned short*>(dest)) = (ushort)r; |
824 return true; | 857 return true; |
825 } | 858 } |
826 | 859 |
827 bool PCRE::Arg::parse_int_radix(const char* str, | 860 bool PCRE::Arg::parse_int_radix(const char* str, |
828 int n, | 861 int n, |
829 void* dest, | 862 void* dest, |
830 int radix) { | 863 int radix) { |
831 long r; | 864 long r; |
832 if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse | 865 if (!parse_long_radix(str, n, &r, radix)) return false; // Could not parse |
833 if ((int)r != r) return false; // Out of range | 866 if ((int)r != r) return false; // Out of range |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 if (n == 0) return false; | 924 if (n == 0) return false; |
892 static const int kMaxLength = 200; | 925 static const int kMaxLength = 200; |
893 char buf[kMaxLength]; | 926 char buf[kMaxLength]; |
894 if (n >= kMaxLength) return false; | 927 if (n >= kMaxLength) return false; |
895 memcpy(buf, str, n); | 928 memcpy(buf, str, n); |
896 buf[n] = '\0'; | 929 buf[n] = '\0'; |
897 errno = 0; | 930 errno = 0; |
898 char* end; | 931 char* end; |
899 double r = strtod(buf, &end); | 932 double r = strtod(buf, &end); |
900 if (end != buf + n) { | 933 if (end != buf + n) { |
901 #ifdef COMPILER_MSVC | 934 #ifdef _WIN32 |
902 // Microsoft's strtod() doesn't handle inf and nan, so we have to | 935 // Microsoft's strtod() doesn't handle inf and nan, so we have to |
903 // handle it explicitly. Speed is not important here because this | 936 // handle it explicitly. Speed is not important here because this |
904 // code is only called in unit tests. | 937 // code is only called in unit tests. |
905 bool pos = true; | 938 bool pos = true; |
906 const char* i = buf; | 939 const char* i = buf; |
907 if ('-' == *i) { | 940 if ('-' == *i) { |
908 pos = false; | 941 pos = false; |
909 ++i; | 942 ++i; |
910 } else if ('+' == *i) { | 943 } else if ('+' == *i) { |
911 ++i; | 944 ++i; |
912 } | 945 } |
913 if (0 == stricmp(i, "inf") || 0 == stricmp(i, "infinity")) { | 946 if (0 == stricmp(i, "inf") || 0 == stricmp(i, "infinity")) { |
914 r = numeric_limits<double>::infinity(); | 947 r = std::numeric_limits<double>::infinity(); |
915 if (!pos) | 948 if (!pos) |
916 r = -r; | 949 r = -r; |
917 } else if (0 == stricmp(i, "nan")) { | 950 } else if (0 == stricmp(i, "nan")) { |
918 r = numeric_limits<double>::quiet_NaN(); | 951 r = std::numeric_limits<double>::quiet_NaN(); |
919 } else { | 952 } else { |
920 return false; | 953 return false; |
921 } | 954 } |
922 #else | 955 #else |
923 return false; // Leftover junk | 956 return false; // Leftover junk |
924 #endif | 957 #endif |
925 } | 958 } |
926 if (errno) return false; | 959 if (errno) return false; |
927 if (dest == NULL) return true; | 960 if (dest == NULL) return true; |
928 *(reinterpret_cast<double*>(dest)) = r; | 961 *(reinterpret_cast<double*>(dest)) = r; |
(...skipping 28 matching lines...) Expand all Loading... |
957 DEFINE_INTEGER_PARSERS(int); | 990 DEFINE_INTEGER_PARSERS(int); |
958 DEFINE_INTEGER_PARSERS(uint); | 991 DEFINE_INTEGER_PARSERS(uint); |
959 DEFINE_INTEGER_PARSERS(long); | 992 DEFINE_INTEGER_PARSERS(long); |
960 DEFINE_INTEGER_PARSERS(ulong); | 993 DEFINE_INTEGER_PARSERS(ulong); |
961 DEFINE_INTEGER_PARSERS(longlong); | 994 DEFINE_INTEGER_PARSERS(longlong); |
962 DEFINE_INTEGER_PARSERS(ulonglong); | 995 DEFINE_INTEGER_PARSERS(ulonglong); |
963 | 996 |
964 #undef DEFINE_INTEGER_PARSERS | 997 #undef DEFINE_INTEGER_PARSERS |
965 | 998 |
966 } // namespace re2 | 999 } // namespace re2 |
OLD | NEW |