OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 template <class Iterator, class EndMark> | 267 template <class Iterator, class EndMark> |
268 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) { | 268 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) { |
269 while (*current != end) { | 269 while (*current != end) { |
270 if (!Scanner::kIsWhiteSpace.get(**current)) return true; | 270 if (!Scanner::kIsWhiteSpace.get(**current)) return true; |
271 ++*current; | 271 ++*current; |
272 } | 272 } |
273 return false; | 273 return false; |
274 } | 274 } |
275 | 275 |
276 | 276 |
277 template <class Iterator, class EndMark> | 277 static bool isDigit(int x, int radix) { |
278 static double InternalHexadecimalStringToDouble(Iterator current, | 278 return (x >= '0' && x <= '9' && x < '0' + radix) |
279 EndMark end, | 279 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) |
280 char* buffer, | 280 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); |
281 bool allow_trailing_junk) { | 281 } |
| 282 |
| 283 |
| 284 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
| 285 template <int radix_log_2, class Iterator, class EndMark> |
| 286 static double InternalStringToIntDouble(Iterator current, |
| 287 EndMark end, |
| 288 bool sign, |
| 289 bool allow_trailing_junk) { |
282 ASSERT(current != end); | 290 ASSERT(current != end); |
283 | 291 |
284 const int max_hex_significant_digits = 52 / 4 + 2; | |
285 // We reuse the buffer of InternalStringToDouble. Since hexadecimal | |
286 // numbers may have much less digits than decimal the buffer won't overflow. | |
287 ASSERT(max_hex_significant_digits < kMaxSignificantDigits); | |
288 | |
289 int significant_digits = 0; | |
290 int insignificant_digits = 0; | |
291 bool leading_zero = false; | |
292 // A double has a 53bit significand (once the hidden bit has been added). | |
293 // Halfway cases thus have at most 54bits. Therefore 54/4 + 1 digits are | |
294 // sufficient to represent halfway cases. By adding another digit we can keep | |
295 // track of dropped digits. | |
296 int buffer_pos = 0; | |
297 bool nonzero_digit_dropped = false; | |
298 | |
299 // Skip leading 0s. | 292 // Skip leading 0s. |
300 while (*current == '0') { | 293 while (*current == '0') { |
301 leading_zero = true; | |
302 ++current; | 294 ++current; |
303 if (current == end) return 0; | 295 if (current == end) return sign ? -0.0 : 0.0; |
304 } | 296 } |
305 | 297 |
306 int begin_pos = buffer_pos; | 298 int64_t number = 0; |
307 while ((*current >= '0' && *current <= '9') | 299 int exponent = 0; |
308 || (*current >= 'a' && *current <= 'f') | 300 const int radix = (1 << radix_log_2); |
309 || (*current >= 'A' && *current <= 'F')) { | 301 |
310 if (significant_digits <= max_hex_significant_digits) { | 302 do { |
311 buffer[buffer_pos++] = static_cast<char>(*current); | 303 int digit; |
312 significant_digits++; | 304 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { |
| 305 digit = static_cast<char>(*current) - '0'; |
| 306 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { |
| 307 digit = static_cast<char>(*current) - 'a' + 10; |
| 308 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { |
| 309 digit = static_cast<char>(*current) - 'A' + 10; |
313 } else { | 310 } else { |
314 insignificant_digits++; | 311 if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { |
315 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; | 312 break; |
| 313 } else { |
| 314 return JUNK_STRING_VALUE; |
| 315 } |
| 316 } |
| 317 |
| 318 number = number * radix + digit; |
| 319 int overflow = number >> 53; |
| 320 if (overflow != 0) { |
| 321 // Overflow occurred. Need to determine which direction to round the |
| 322 // result. |
| 323 int overflow_bits_count = 1; |
| 324 while (overflow > 1) { |
| 325 overflow_bits_count++; |
| 326 overflow >>= 1; |
| 327 } |
| 328 |
| 329 int dropped_bits_mask = ((1 << overflow_bits_count) - 1); |
| 330 int dropped_bits = number & dropped_bits_mask; |
| 331 number >>= overflow_bits_count; |
| 332 exponent = overflow_bits_count; |
| 333 |
| 334 bool zero_tail = true; |
| 335 while (true) { |
| 336 ++current; |
| 337 if (current == end || !isDigit(*current, radix)) break; |
| 338 zero_tail = zero_tail && *current == '0'; |
| 339 exponent += radix_log_2; |
| 340 } |
| 341 |
| 342 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
| 343 return JUNK_STRING_VALUE; |
| 344 } |
| 345 |
| 346 int middle_value = (1 << (overflow_bits_count - 1)); |
| 347 if (dropped_bits > middle_value) { |
| 348 number++; // Rounding up. |
| 349 } else if (dropped_bits == middle_value) { |
| 350 // Rounding to even to consistency with decimals: half-way case rounds |
| 351 // up if significant part is odd and down otherwise. |
| 352 if ((number & 1) != 0 || !zero_tail) { |
| 353 number++; // Rounding up. |
| 354 } |
| 355 } |
| 356 |
| 357 // Rounding up may cause overflow. |
| 358 if ((number & ((int64_t)1 << 53)) != 0) { |
| 359 exponent++; |
| 360 number >>= 1; |
| 361 } |
| 362 break; |
316 } | 363 } |
317 ++current; | 364 ++current; |
318 if (current == end) break; | 365 } while (current != end); |
| 366 |
| 367 ASSERT(number < ((int64_t)1 << 53)); |
| 368 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); |
| 369 |
| 370 if (exponent == 0) { |
| 371 if (sign) { |
| 372 if (number == 0) return -0.0; |
| 373 number = -number; |
| 374 } |
| 375 return static_cast<double>(number); |
319 } | 376 } |
320 | 377 |
321 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 378 ASSERT(number != 0); |
322 return JUNK_STRING_VALUE; | 379 // The double could be constructed faster from number (mantissa), exponent |
323 } | 380 // and sign. Assuming it's a rare case more simple code is used. |
324 | 381 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent); |
325 if (significant_digits == 0) { | |
326 return leading_zero ? 0 : JUNK_STRING_VALUE; | |
327 } | |
328 | |
329 if (nonzero_digit_dropped) { | |
330 ASSERT(insignificant_digits > 0); | |
331 insignificant_digits--; | |
332 buffer[buffer_pos++] = '1'; | |
333 } | |
334 | |
335 buffer[buffer_pos] = '\0'; | |
336 | |
337 double result; | |
338 StringToInt(buffer, begin_pos, 16, &result); | |
339 if (insignificant_digits > 0) { | |
340 // Multiplying by a power of 2 doesn't cause a loss of precision. | |
341 result *= pow(16.0, insignificant_digits); | |
342 } | |
343 return result; | |
344 } | 382 } |
345 | 383 |
346 | 384 |
347 // Converts a string to a double value. Assumes the Iterator supports | 385 // Converts a string to a double value. Assumes the Iterator supports |
348 // the following operations: | 386 // the following operations: |
349 // 1. current == end (other ops are not allowed), current != end. | 387 // 1. current == end (other ops are not allowed), current != end. |
350 // 2. *current - gets the current character in the sequence. | 388 // 2. *current - gets the current character in the sequence. |
351 // 3. ++current (advances the position). | 389 // 3. ++current (advances the position). |
352 template <class Iterator, class EndMark> | 390 template <class Iterator, class EndMark> |
353 static double InternalStringToDouble(Iterator current, | 391 static double InternalStringToDouble(Iterator current, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; | 444 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; |
407 } | 445 } |
408 | 446 |
409 bool leading_zero = false; | 447 bool leading_zero = false; |
410 if (*current == '0') { | 448 if (*current == '0') { |
411 ++current; | 449 ++current; |
412 if (current == end) return signed_zero; | 450 if (current == end) return signed_zero; |
413 | 451 |
414 leading_zero = true; | 452 leading_zero = true; |
415 | 453 |
416 // It could be hexadecimal value. | 454 // It could be hexadecimal value. |
417 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { | 455 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
418 ++current; | 456 ++current; |
419 if (current == end) return JUNK_STRING_VALUE; // "0x". | 457 if (current == end) return JUNK_STRING_VALUE; // "0x". |
420 | 458 |
421 double result = InternalHexadecimalStringToDouble(current, | 459 bool sign = (buffer_pos > 0 && buffer[0] == '-'); |
422 end, | 460 return InternalStringToIntDouble<4>(current, |
423 buffer + buffer_pos, | 461 end, |
424 allow_trailing_junk); | 462 sign, |
425 return (buffer_pos > 0 && buffer[0] == '-') ? -result : result; | 463 allow_trailing_junk); |
426 } | 464 } |
427 | 465 |
428 // Ignore leading zeros in the integer part. | 466 // Ignore leading zeros in the integer part. |
429 while (*current == '0') { | 467 while (*current == '0') { |
430 ++current; | 468 ++current; |
431 if (current == end) return signed_zero; | 469 if (current == end) return signed_zero; |
432 } | 470 } |
433 } | 471 } |
434 | 472 |
435 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0; | 473 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 } | 591 } |
554 | 592 |
555 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 593 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
556 return JUNK_STRING_VALUE; | 594 return JUNK_STRING_VALUE; |
557 } | 595 } |
558 | 596 |
559 parsing_done: | 597 parsing_done: |
560 exponent += insignificant_digits; | 598 exponent += insignificant_digits; |
561 | 599 |
562 if (octal) { | 600 if (octal) { |
563 buffer[buffer_pos] = '\0'; | 601 bool sign = buffer[0] == '-'; |
564 // ALLOW_OCTALS is set and there is no '8' or '9' in insignificant | 602 int start_pos = (sign ? 1 : 0); |
565 // digits. Check significant digits now. | |
566 char sign = '+'; | |
567 const char* s = buffer; | |
568 if (*s == '-' || *s == '+') sign = *s++; | |
569 | 603 |
570 double result; | 604 return InternalStringToIntDouble<3>(buffer + start_pos, |
571 s += StringToInt(s, 0, 8, &result); | 605 buffer + buffer_pos, |
572 if (!allow_trailing_junk && *s != '\0') return JUNK_STRING_VALUE; | 606 sign, |
573 | 607 allow_trailing_junk); |
574 if (sign == '-') result = -result; | |
575 if (insignificant_digits > 0) { | |
576 result *= pow(8.0, insignificant_digits); | |
577 } | |
578 return result; | |
579 } | 608 } |
580 | 609 |
581 if (nonzero_digit_dropped) { | 610 if (nonzero_digit_dropped) { |
582 if (insignificant_digits) buffer[buffer_pos++] = '.'; | 611 if (insignificant_digits) buffer[buffer_pos++] = '.'; |
583 buffer[buffer_pos++] = '1'; | 612 buffer[buffer_pos++] = '1'; |
584 } | 613 } |
585 | 614 |
586 // If the number has no more than kMaxDigitsInInt digits and doesn't have | 615 // If the number has no more than kMaxDigitsInInt digits and doesn't have |
587 // fractional part it could be parsed faster (without checks for | 616 // fractional part it could be parsed faster (without checks for |
588 // spaces, overflow, etc.). | 617 // spaces, overflow, etc.). |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 // Allocate result and fill in the parts. | 1035 // Allocate result and fill in the parts. |
1007 StringBuilder builder(result_size + 1); | 1036 StringBuilder builder(result_size + 1); |
1008 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); | 1037 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); |
1009 if (decimal_pos > 0) builder.AddCharacter('.'); | 1038 if (decimal_pos > 0) builder.AddCharacter('.'); |
1010 builder.AddSubstring(decimal_buffer, decimal_pos); | 1039 builder.AddSubstring(decimal_buffer, decimal_pos); |
1011 return builder.Finalize(); | 1040 return builder.Finalize(); |
1012 } | 1041 } |
1013 | 1042 |
1014 | 1043 |
1015 } } // namespace v8::internal | 1044 } } // namespace v8::internal |
OLD | NEW |