OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 digit = static_cast<char>(*current) - '0'; | 144 digit = static_cast<char>(*current) - '0'; |
145 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { | 145 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { |
146 digit = static_cast<char>(*current) - 'a' + 10; | 146 digit = static_cast<char>(*current) - 'a' + 10; |
147 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { | 147 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { |
148 digit = static_cast<char>(*current) - 'A' + 10; | 148 digit = static_cast<char>(*current) - 'A' + 10; |
149 } else { | 149 } else { |
150 if (allow_trailing_junk || | 150 if (allow_trailing_junk || |
151 !AdvanceToNonspace(unicode_cache, ¤t, end)) { | 151 !AdvanceToNonspace(unicode_cache, ¤t, end)) { |
152 break; | 152 break; |
153 } else { | 153 } else { |
154 return JUNK_STRING_VALUE; | 154 return JunkStringValue(); |
155 } | 155 } |
156 } | 156 } |
157 | 157 |
158 number = number * radix + digit; | 158 number = number * radix + digit; |
159 int overflow = static_cast<int>(number >> 53); | 159 int overflow = static_cast<int>(number >> 53); |
160 if (overflow != 0) { | 160 if (overflow != 0) { |
161 // Overflow occurred. Need to determine which direction to round the | 161 // Overflow occurred. Need to determine which direction to round the |
162 // result. | 162 // result. |
163 int overflow_bits_count = 1; | 163 int overflow_bits_count = 1; |
164 while (overflow > 1) { | 164 while (overflow > 1) { |
165 overflow_bits_count++; | 165 overflow_bits_count++; |
166 overflow >>= 1; | 166 overflow >>= 1; |
167 } | 167 } |
168 | 168 |
169 int dropped_bits_mask = ((1 << overflow_bits_count) - 1); | 169 int dropped_bits_mask = ((1 << overflow_bits_count) - 1); |
170 int dropped_bits = static_cast<int>(number) & dropped_bits_mask; | 170 int dropped_bits = static_cast<int>(number) & dropped_bits_mask; |
171 number >>= overflow_bits_count; | 171 number >>= overflow_bits_count; |
172 exponent = overflow_bits_count; | 172 exponent = overflow_bits_count; |
173 | 173 |
174 bool zero_tail = true; | 174 bool zero_tail = true; |
175 while (true) { | 175 while (true) { |
176 ++current; | 176 ++current; |
177 if (current == end || !isDigit(*current, radix)) break; | 177 if (current == end || !isDigit(*current, radix)) break; |
178 zero_tail = zero_tail && *current == '0'; | 178 zero_tail = zero_tail && *current == '0'; |
179 exponent += radix_log_2; | 179 exponent += radix_log_2; |
180 } | 180 } |
181 | 181 |
182 if (!allow_trailing_junk && | 182 if (!allow_trailing_junk && |
183 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 183 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
184 return JUNK_STRING_VALUE; | 184 return JunkStringValue(); |
185 } | 185 } |
186 | 186 |
187 int middle_value = (1 << (overflow_bits_count - 1)); | 187 int middle_value = (1 << (overflow_bits_count - 1)); |
188 if (dropped_bits > middle_value) { | 188 if (dropped_bits > middle_value) { |
189 number++; // Rounding up. | 189 number++; // Rounding up. |
190 } else if (dropped_bits == middle_value) { | 190 } else if (dropped_bits == middle_value) { |
191 // Rounding to even to consistency with decimals: half-way case rounds | 191 // Rounding to even to consistency with decimals: half-way case rounds |
192 // up if significant part is odd and down otherwise. | 192 // up if significant part is odd and down otherwise. |
193 if ((number & 1) != 0 || !zero_tail) { | 193 if ((number & 1) != 0 || !zero_tail) { |
194 number++; // Rounding up. | 194 number++; // Rounding up. |
(...skipping 27 matching lines...) Expand all Loading... |
222 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent); | 222 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent); |
223 } | 223 } |
224 | 224 |
225 | 225 |
226 template <class Iterator, class EndMark> | 226 template <class Iterator, class EndMark> |
227 static double InternalStringToInt(UnicodeCache* unicode_cache, | 227 static double InternalStringToInt(UnicodeCache* unicode_cache, |
228 Iterator current, | 228 Iterator current, |
229 EndMark end, | 229 EndMark end, |
230 int radix) { | 230 int radix) { |
231 const bool allow_trailing_junk = true; | 231 const bool allow_trailing_junk = true; |
232 const double empty_string_val = JUNK_STRING_VALUE; | 232 const double empty_string_val = JunkStringValue(); |
233 | 233 |
234 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { | 234 if (!AdvanceToNonspace(unicode_cache, ¤t, end)) { |
235 return empty_string_val; | 235 return empty_string_val; |
236 } | 236 } |
237 | 237 |
238 bool negative = false; | 238 bool negative = false; |
239 bool leading_zero = false; | 239 bool leading_zero = false; |
240 | 240 |
241 if (*current == '+') { | 241 if (*current == '+') { |
242 // Ignore leading sign; skip following spaces. | 242 // Ignore leading sign; skip following spaces. |
243 ++current; | 243 ++current; |
244 if (current == end) { | 244 if (current == end) { |
245 return JUNK_STRING_VALUE; | 245 return JunkStringValue(); |
246 } | 246 } |
247 } else if (*current == '-') { | 247 } else if (*current == '-') { |
248 ++current; | 248 ++current; |
249 if (current == end) { | 249 if (current == end) { |
250 return JUNK_STRING_VALUE; | 250 return JunkStringValue(); |
251 } | 251 } |
252 negative = true; | 252 negative = true; |
253 } | 253 } |
254 | 254 |
255 if (radix == 0) { | 255 if (radix == 0) { |
256 // Radix detection. | 256 // Radix detection. |
257 if (*current == '0') { | 257 if (*current == '0') { |
258 ++current; | 258 ++current; |
259 if (current == end) return SignedZero(negative); | 259 if (current == end) return SignedZero(negative); |
260 if (*current == 'x' || *current == 'X') { | 260 if (*current == 'x' || *current == 'X') { |
261 radix = 16; | 261 radix = 16; |
262 ++current; | 262 ++current; |
263 if (current == end) return JUNK_STRING_VALUE; | 263 if (current == end) return JunkStringValue(); |
264 } else { | 264 } else { |
265 radix = 8; | 265 radix = 8; |
266 leading_zero = true; | 266 leading_zero = true; |
267 } | 267 } |
268 } else { | 268 } else { |
269 radix = 10; | 269 radix = 10; |
270 } | 270 } |
271 } else if (radix == 16) { | 271 } else if (radix == 16) { |
272 if (*current == '0') { | 272 if (*current == '0') { |
273 // Allow "0x" prefix. | 273 // Allow "0x" prefix. |
274 ++current; | 274 ++current; |
275 if (current == end) return SignedZero(negative); | 275 if (current == end) return SignedZero(negative); |
276 if (*current == 'x' || *current == 'X') { | 276 if (*current == 'x' || *current == 'X') { |
277 ++current; | 277 ++current; |
278 if (current == end) return JUNK_STRING_VALUE; | 278 if (current == end) return JunkStringValue(); |
279 } else { | 279 } else { |
280 leading_zero = true; | 280 leading_zero = true; |
281 } | 281 } |
282 } | 282 } |
283 } | 283 } |
284 | 284 |
285 if (radix < 2 || radix > 36) return JUNK_STRING_VALUE; | 285 if (radix < 2 || radix > 36) return JunkStringValue(); |
286 | 286 |
287 // Skip leading zeros. | 287 // Skip leading zeros. |
288 while (*current == '0') { | 288 while (*current == '0') { |
289 leading_zero = true; | 289 leading_zero = true; |
290 ++current; | 290 ++current; |
291 if (current == end) return SignedZero(negative); | 291 if (current == end) return SignedZero(negative); |
292 } | 292 } |
293 | 293 |
294 if (!leading_zero && !isDigit(*current, radix)) { | 294 if (!leading_zero && !isDigit(*current, radix)) { |
295 return JUNK_STRING_VALUE; | 295 return JunkStringValue(); |
296 } | 296 } |
297 | 297 |
298 if (IsPowerOf2(radix)) { | 298 if (IsPowerOf2(radix)) { |
299 switch (radix) { | 299 switch (radix) { |
300 case 2: | 300 case 2: |
301 return InternalStringToIntDouble<1>( | 301 return InternalStringToIntDouble<1>( |
302 unicode_cache, current, end, negative, allow_trailing_junk); | 302 unicode_cache, current, end, negative, allow_trailing_junk); |
303 case 4: | 303 case 4: |
304 return InternalStringToIntDouble<2>( | 304 return InternalStringToIntDouble<2>( |
305 unicode_cache, current, end, negative, allow_trailing_junk); | 305 unicode_cache, current, end, negative, allow_trailing_junk); |
(...skipping 27 matching lines...) Expand all Loading... |
333 // as infinity. | 333 // as infinity. |
334 ASSERT(buffer_pos < kBufferSize); | 334 ASSERT(buffer_pos < kBufferSize); |
335 buffer[buffer_pos++] = static_cast<char>(*current); | 335 buffer[buffer_pos++] = static_cast<char>(*current); |
336 } | 336 } |
337 ++current; | 337 ++current; |
338 if (current == end) break; | 338 if (current == end) break; |
339 } | 339 } |
340 | 340 |
341 if (!allow_trailing_junk && | 341 if (!allow_trailing_junk && |
342 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 342 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
343 return JUNK_STRING_VALUE; | 343 return JunkStringValue(); |
344 } | 344 } |
345 | 345 |
346 ASSERT(buffer_pos < kBufferSize); | 346 ASSERT(buffer_pos < kBufferSize); |
347 buffer[buffer_pos] = '\0'; | 347 buffer[buffer_pos] = '\0'; |
348 Vector<const char> buffer_vector(buffer, buffer_pos); | 348 Vector<const char> buffer_vector(buffer, buffer_pos); |
349 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); | 349 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); |
350 } | 350 } |
351 | 351 |
352 // The following code causes accumulating rounding error for numbers greater | 352 // The following code causes accumulating rounding error for numbers greater |
353 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, | 353 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 break; | 399 break; |
400 } | 400 } |
401 } | 401 } |
402 | 402 |
403 // Update the value and skip the part in the string. | 403 // Update the value and skip the part in the string. |
404 v = v * multiplier + part; | 404 v = v * multiplier + part; |
405 } while (!done); | 405 } while (!done); |
406 | 406 |
407 if (!allow_trailing_junk && | 407 if (!allow_trailing_junk && |
408 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 408 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
409 return JUNK_STRING_VALUE; | 409 return JunkStringValue(); |
410 } | 410 } |
411 | 411 |
412 return negative ? -v : v; | 412 return negative ? -v : v; |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 // Converts a string to a double value. Assumes the Iterator supports | 416 // Converts a string to a double value. Assumes the Iterator supports |
417 // the following operations: | 417 // the following operations: |
418 // 1. current == end (other ops are not allowed), current != end. | 418 // 1. current == end (other ops are not allowed), current != end. |
419 // 2. *current - gets the current character in the sequence. | 419 // 2. *current - gets the current character in the sequence. |
(...skipping 29 matching lines...) Expand all Loading... |
449 int significant_digits = 0; | 449 int significant_digits = 0; |
450 int insignificant_digits = 0; | 450 int insignificant_digits = 0; |
451 bool nonzero_digit_dropped = false; | 451 bool nonzero_digit_dropped = false; |
452 bool fractional_part = false; | 452 bool fractional_part = false; |
453 | 453 |
454 bool negative = false; | 454 bool negative = false; |
455 | 455 |
456 if (*current == '+') { | 456 if (*current == '+') { |
457 // Ignore leading sign. | 457 // Ignore leading sign. |
458 ++current; | 458 ++current; |
459 if (current == end) return JUNK_STRING_VALUE; | 459 if (current == end) return JunkStringValue(); |
460 } else if (*current == '-') { | 460 } else if (*current == '-') { |
461 ++current; | 461 ++current; |
462 if (current == end) return JUNK_STRING_VALUE; | 462 if (current == end) return JunkStringValue(); |
463 negative = true; | 463 negative = true; |
464 } | 464 } |
465 | 465 |
466 static const char kInfinitySymbol[] = "Infinity"; | 466 static const char kInfinitySymbol[] = "Infinity"; |
467 if (*current == kInfinitySymbol[0]) { | 467 if (*current == kInfinitySymbol[0]) { |
468 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { | 468 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { |
469 return JUNK_STRING_VALUE; | 469 return JunkStringValue(); |
470 } | 470 } |
471 | 471 |
472 if (!allow_trailing_junk && | 472 if (!allow_trailing_junk && |
473 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 473 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
474 return JUNK_STRING_VALUE; | 474 return JunkStringValue(); |
475 } | 475 } |
476 | 476 |
477 ASSERT(buffer_pos == 0); | 477 ASSERT(buffer_pos == 0); |
478 return negative ? -V8_INFINITY : V8_INFINITY; | 478 return negative ? -V8_INFINITY : V8_INFINITY; |
479 } | 479 } |
480 | 480 |
481 bool leading_zero = false; | 481 bool leading_zero = false; |
482 if (*current == '0') { | 482 if (*current == '0') { |
483 ++current; | 483 ++current; |
484 if (current == end) return SignedZero(negative); | 484 if (current == end) return SignedZero(negative); |
485 | 485 |
486 leading_zero = true; | 486 leading_zero = true; |
487 | 487 |
488 // It could be hexadecimal value. | 488 // It could be hexadecimal value. |
489 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { | 489 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
490 ++current; | 490 ++current; |
491 if (current == end || !isDigit(*current, 16)) { | 491 if (current == end || !isDigit(*current, 16)) { |
492 return JUNK_STRING_VALUE; // "0x". | 492 return JunkStringValue(); // "0x". |
493 } | 493 } |
494 | 494 |
495 return InternalStringToIntDouble<4>(unicode_cache, | 495 return InternalStringToIntDouble<4>(unicode_cache, |
496 current, | 496 current, |
497 end, | 497 end, |
498 negative, | 498 negative, |
499 allow_trailing_junk); | 499 allow_trailing_junk); |
500 } | 500 } |
501 | 501 |
502 // Ignore leading zeros in the integer part. | 502 // Ignore leading zeros in the integer part. |
(...skipping 19 matching lines...) Expand all Loading... |
522 octal = octal && *current < '8'; | 522 octal = octal && *current < '8'; |
523 ++current; | 523 ++current; |
524 if (current == end) goto parsing_done; | 524 if (current == end) goto parsing_done; |
525 } | 525 } |
526 | 526 |
527 if (significant_digits == 0) { | 527 if (significant_digits == 0) { |
528 octal = false; | 528 octal = false; |
529 } | 529 } |
530 | 530 |
531 if (*current == '.') { | 531 if (*current == '.') { |
532 if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE; | 532 if (octal && !allow_trailing_junk) return JunkStringValue(); |
533 if (octal) goto parsing_done; | 533 if (octal) goto parsing_done; |
534 | 534 |
535 ++current; | 535 ++current; |
536 if (current == end) { | 536 if (current == end) { |
537 if (significant_digits == 0 && !leading_zero) { | 537 if (significant_digits == 0 && !leading_zero) { |
538 return JUNK_STRING_VALUE; | 538 return JunkStringValue(); |
539 } else { | 539 } else { |
540 goto parsing_done; | 540 goto parsing_done; |
541 } | 541 } |
542 } | 542 } |
543 | 543 |
544 if (significant_digits == 0) { | 544 if (significant_digits == 0) { |
545 // octal = false; | 545 // octal = false; |
546 // Integer part consists of 0 or is absent. Significant digits start after | 546 // Integer part consists of 0 or is absent. Significant digits start after |
547 // leading zeros (if any). | 547 // leading zeros (if any). |
548 while (*current == '0') { | 548 while (*current == '0') { |
(...skipping 20 matching lines...) Expand all Loading... |
569 ++current; | 569 ++current; |
570 if (current == end) goto parsing_done; | 570 if (current == end) goto parsing_done; |
571 } | 571 } |
572 } | 572 } |
573 | 573 |
574 if (!leading_zero && exponent == 0 && significant_digits == 0) { | 574 if (!leading_zero && exponent == 0 && significant_digits == 0) { |
575 // If leading_zeros is true then the string contains zeros. | 575 // If leading_zeros is true then the string contains zeros. |
576 // If exponent < 0 then string was [+-]\.0*... | 576 // If exponent < 0 then string was [+-]\.0*... |
577 // If significant_digits != 0 the string is not equal to 0. | 577 // If significant_digits != 0 the string is not equal to 0. |
578 // Otherwise there are no digits in the string. | 578 // Otherwise there are no digits in the string. |
579 return JUNK_STRING_VALUE; | 579 return JunkStringValue(); |
580 } | 580 } |
581 | 581 |
582 // Parse exponential part. | 582 // Parse exponential part. |
583 if (*current == 'e' || *current == 'E') { | 583 if (*current == 'e' || *current == 'E') { |
584 if (octal) return JUNK_STRING_VALUE; | 584 if (octal) return JunkStringValue(); |
585 ++current; | 585 ++current; |
586 if (current == end) { | 586 if (current == end) { |
587 if (allow_trailing_junk) { | 587 if (allow_trailing_junk) { |
588 goto parsing_done; | 588 goto parsing_done; |
589 } else { | 589 } else { |
590 return JUNK_STRING_VALUE; | 590 return JunkStringValue(); |
591 } | 591 } |
592 } | 592 } |
593 char sign = '+'; | 593 char sign = '+'; |
594 if (*current == '+' || *current == '-') { | 594 if (*current == '+' || *current == '-') { |
595 sign = static_cast<char>(*current); | 595 sign = static_cast<char>(*current); |
596 ++current; | 596 ++current; |
597 if (current == end) { | 597 if (current == end) { |
598 if (allow_trailing_junk) { | 598 if (allow_trailing_junk) { |
599 goto parsing_done; | 599 goto parsing_done; |
600 } else { | 600 } else { |
601 return JUNK_STRING_VALUE; | 601 return JunkStringValue(); |
602 } | 602 } |
603 } | 603 } |
604 } | 604 } |
605 | 605 |
606 if (current == end || *current < '0' || *current > '9') { | 606 if (current == end || *current < '0' || *current > '9') { |
607 if (allow_trailing_junk) { | 607 if (allow_trailing_junk) { |
608 goto parsing_done; | 608 goto parsing_done; |
609 } else { | 609 } else { |
610 return JUNK_STRING_VALUE; | 610 return JunkStringValue(); |
611 } | 611 } |
612 } | 612 } |
613 | 613 |
614 const int max_exponent = INT_MAX / 2; | 614 const int max_exponent = INT_MAX / 2; |
615 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); | 615 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); |
616 int num = 0; | 616 int num = 0; |
617 do { | 617 do { |
618 // Check overflow. | 618 // Check overflow. |
619 int digit = *current - '0'; | 619 int digit = *current - '0'; |
620 if (num >= max_exponent / 10 | 620 if (num >= max_exponent / 10 |
621 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { | 621 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { |
622 num = max_exponent; | 622 num = max_exponent; |
623 } else { | 623 } else { |
624 num = num * 10 + digit; | 624 num = num * 10 + digit; |
625 } | 625 } |
626 ++current; | 626 ++current; |
627 } while (current != end && *current >= '0' && *current <= '9'); | 627 } while (current != end && *current >= '0' && *current <= '9'); |
628 | 628 |
629 exponent += (sign == '-' ? -num : num); | 629 exponent += (sign == '-' ? -num : num); |
630 } | 630 } |
631 | 631 |
632 if (!allow_trailing_junk && | 632 if (!allow_trailing_junk && |
633 AdvanceToNonspace(unicode_cache, ¤t, end)) { | 633 AdvanceToNonspace(unicode_cache, ¤t, end)) { |
634 return JUNK_STRING_VALUE; | 634 return JunkStringValue(); |
635 } | 635 } |
636 | 636 |
637 parsing_done: | 637 parsing_done: |
638 exponent += insignificant_digits; | 638 exponent += insignificant_digits; |
639 | 639 |
640 if (octal) { | 640 if (octal) { |
641 return InternalStringToIntDouble<3>(unicode_cache, | 641 return InternalStringToIntDouble<3>(unicode_cache, |
642 buffer, | 642 buffer, |
643 buffer + buffer_pos, | 643 buffer + buffer_pos, |
644 negative, | 644 negative, |
645 allow_trailing_junk); | 645 allow_trailing_junk); |
646 } | 646 } |
647 | 647 |
648 if (nonzero_digit_dropped) { | 648 if (nonzero_digit_dropped) { |
649 buffer[buffer_pos++] = '1'; | 649 buffer[buffer_pos++] = '1'; |
650 exponent--; | 650 exponent--; |
651 } | 651 } |
652 | 652 |
653 ASSERT(buffer_pos < kBufferSize); | 653 ASSERT(buffer_pos < kBufferSize); |
654 buffer[buffer_pos] = '\0'; | 654 buffer[buffer_pos] = '\0'; |
655 | 655 |
656 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); | 656 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); |
657 return negative ? -converted : converted; | 657 return negative ? -converted : converted; |
658 } | 658 } |
659 | 659 |
660 } } // namespace v8::internal | 660 } } // namespace v8::internal |
661 | 661 |
662 #endif // V8_CONVERSIONS_INL_H_ | 662 #endif // V8_CONVERSIONS_INL_H_ |
OLD | NEW |