conversions.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
1// Copyright 2006-2008 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include <stdarg.h> 29#include <limits.h> 30 31#include "v8.h" 32 33#include "conversions-inl.h" 34#include "dtoa.h" 35#include "factory.h" 36#include "scanner-base.h" 37#include "strtod.h" 38 39namespace v8 { 40namespace internal { 41 42namespace { 43 44// C++-style iterator adaptor for StringInputBuffer 45// (unlike C++ iterators the end-marker has different type). 46class StringInputBufferIterator { 47 public: 48 class EndMarker {}; 49 50 explicit StringInputBufferIterator(StringInputBuffer* buffer); 51 52 int operator*() const; 53 void operator++(); 54 bool operator==(EndMarker const&) const { return end_; } 55 bool operator!=(EndMarker const& m) const { return !end_; } 56 57 private: 58 StringInputBuffer* const buffer_; 59 int current_; 60 bool end_; 61}; 62 63 64StringInputBufferIterator::StringInputBufferIterator( 65 StringInputBuffer* buffer) : buffer_(buffer) { 66 ++(*this); 67} 68 69int StringInputBufferIterator::operator*() const { 70 return current_; 71} 72 73 74void StringInputBufferIterator::operator++() { 75 end_ = !buffer_->has_more(); 76 if (!end_) { 77 current_ = buffer_->GetNext(); 78 } 79} 80} 81 82 83template <class Iterator, class EndMark> 84static bool SubStringEquals(Iterator* current, 85 EndMark end, 86 const char* substring) { 87 ASSERT(**current == *substring); 88 for (substring++; *substring != '\0'; substring++) { 89 ++*current; 90 if (*current == end || **current != *substring) return false; 91 } 92 ++*current; 93 return true; 94} 95 96 97// Maximum number of significant digits in decimal representation. 98// The longest possible double in decimal representation is 99// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 100// (768 digits). If we parse a number whose first digits are equal to a 101// mean of 2 adjacent doubles (that could have up to 769 digits) the result 102// must be rounded to the bigger one unless the tail consists of zeros, so 103// we don't need to preserve all the digits. 104const int kMaxSignificantDigits = 772; 105 106 107static const double JUNK_STRING_VALUE = OS::nan_value(); 108 109 110// Returns true if a nonspace found and false if the end has reached. 111template <class Iterator, class EndMark> 112static inline bool AdvanceToNonspace(ScannerConstants* scanner_constants, 113 Iterator* current, 114 EndMark end) { 115 while (*current != end) { 116 if (!scanner_constants->IsWhiteSpace(**current)) return true; 117 ++*current; 118 } 119 return false; 120} 121 122 123static bool isDigit(int x, int radix) { 124 return (x >= '0' && x <= '9' && x < '0' + radix) 125 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) 126 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); 127} 128 129 130static double SignedZero(bool negative) { 131 return negative ? -0.0 : 0.0; 132} 133 134 135// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. 136template <int radix_log_2, class Iterator, class EndMark> 137static double InternalStringToIntDouble(ScannerConstants* scanner_constants, 138 Iterator current, 139 EndMark end, 140 bool negative, 141 bool allow_trailing_junk) { 142 ASSERT(current != end); 143 144 // Skip leading 0s. 145 while (*current == '0') { 146 ++current; 147 if (current == end) return SignedZero(negative); 148 } 149 150 int64_t number = 0; 151 int exponent = 0; 152 const int radix = (1 << radix_log_2); 153 154 do { 155 int digit; 156 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { 157 digit = static_cast<char>(*current) - '0'; 158 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { 159 digit = static_cast<char>(*current) - 'a' + 10; 160 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { 161 digit = static_cast<char>(*current) - 'A' + 10; 162 } else { 163 if (allow_trailing_junk || 164 !AdvanceToNonspace(scanner_constants, ¤t, end)) { 165 break; 166 } else { 167 return JUNK_STRING_VALUE; 168 } 169 } 170 171 number = number * radix + digit; 172 int overflow = static_cast<int>(number >> 53); 173 if (overflow != 0) { 174 // Overflow occurred. Need to determine which direction to round the 175 // result. 176 int overflow_bits_count = 1; 177 while (overflow > 1) { 178 overflow_bits_count++; 179 overflow >>= 1; 180 } 181 182 int dropped_bits_mask = ((1 << overflow_bits_count) - 1); 183 int dropped_bits = static_cast<int>(number) & dropped_bits_mask; 184 number >>= overflow_bits_count; 185 exponent = overflow_bits_count; 186 187 bool zero_tail = true; 188 while (true) { 189 ++current; 190 if (current == end || !isDigit(*current, radix)) break; 191 zero_tail = zero_tail && *current == '0'; 192 exponent += radix_log_2; 193 } 194 195 if (!allow_trailing_junk && 196 AdvanceToNonspace(scanner_constants, ¤t, end)) { 197 return JUNK_STRING_VALUE; 198 } 199 200 int middle_value = (1 << (overflow_bits_count - 1)); 201 if (dropped_bits > middle_value) { 202 number++; // Rounding up. 203 } else if (dropped_bits == middle_value) { 204 // Rounding to even to consistency with decimals: half-way case rounds 205 // up if significant part is odd and down otherwise. 206 if ((number & 1) != 0 || !zero_tail) { 207 number++; // Rounding up. 208 } 209 } 210 211 // Rounding up may cause overflow. 212 if ((number & ((int64_t)1 << 53)) != 0) { 213 exponent++; 214 number >>= 1; 215 } 216 break; 217 } 218 ++current; 219 } while (current != end); 220 221 ASSERT(number < ((int64_t)1 << 53)); 222 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); 223 224 if (exponent == 0) { 225 if (negative) { 226 if (number == 0) return -0.0; 227 number = -number; 228 } 229 return static_cast<double>(number); 230 } 231 232 ASSERT(number != 0); 233 // The double could be constructed faster from number (mantissa), exponent 234 // and sign. Assuming it's a rare case more simple code is used. 235 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent); 236} 237 238 239template <class Iterator, class EndMark> 240static double InternalStringToInt(ScannerConstants* scanner_constants, 241 Iterator current, 242 EndMark end, 243 int radix) { 244 const bool allow_trailing_junk = true; 245 const double empty_string_val = JUNK_STRING_VALUE; 246 247 if (!AdvanceToNonspace(scanner_constants, ¤t, end)) { 248 return empty_string_val; 249 } 250 251 bool negative = false; 252 bool leading_zero = false; 253 254 if (*current == '+') { 255 // Ignore leading sign; skip following spaces. 256 ++current; 257 if (!AdvanceToNonspace(scanner_constants, ¤t, end)) { 258 return JUNK_STRING_VALUE; 259 } 260 } else if (*current == '-') { 261 ++current; 262 if (!AdvanceToNonspace(scanner_constants, ¤t, end)) { 263 return JUNK_STRING_VALUE; 264 } 265 negative = true; 266 } 267 268 if (radix == 0) { 269 // Radix detection. 270 if (*current == '0') { 271 ++current; 272 if (current == end) return SignedZero(negative); 273 if (*current == 'x' || *current == 'X') { 274 radix = 16; 275 ++current; 276 if (current == end) return JUNK_STRING_VALUE; 277 } else { 278 radix = 8; 279 leading_zero = true; 280 } 281 } else { 282 radix = 10; 283 } 284 } else if (radix == 16) { 285 if (*current == '0') { 286 // Allow "0x" prefix. 287 ++current; 288 if (current == end) return SignedZero(negative); 289 if (*current == 'x' || *current == 'X') { 290 ++current; 291 if (current == end) return JUNK_STRING_VALUE; 292 } else { 293 leading_zero = true; 294 } 295 } 296 } 297 298 if (radix < 2 || radix > 36) return JUNK_STRING_VALUE; 299 300 // Skip leading zeros. 301 while (*current == '0') { 302 leading_zero = true; 303 ++current; 304 if (current == end) return SignedZero(negative); 305 } 306 307 if (!leading_zero && !isDigit(*current, radix)) { 308 return JUNK_STRING_VALUE; 309 } 310 311 if (IsPowerOf2(radix)) { 312 switch (radix) { 313 case 2: 314 return InternalStringToIntDouble<1>( 315 scanner_constants, current, end, negative, allow_trailing_junk); 316 case 4: 317 return InternalStringToIntDouble<2>( 318 scanner_constants, current, end, negative, allow_trailing_junk); 319 case 8: 320 return InternalStringToIntDouble<3>( 321 scanner_constants, current, end, negative, allow_trailing_junk); 322 323 case 16: 324 return InternalStringToIntDouble<4>( 325 scanner_constants, current, end, negative, allow_trailing_junk); 326 327 case 32: 328 return InternalStringToIntDouble<5>( 329 scanner_constants, current, end, negative, allow_trailing_junk); 330 default: 331 UNREACHABLE(); 332 } 333 } 334 335 if (radix == 10) { 336 // Parsing with strtod. 337 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308. 338 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero 339 // end. 340 const int kBufferSize = kMaxSignificantDigits + 2; 341 char buffer[kBufferSize]; 342 int buffer_pos = 0; 343 while (*current >= '0' && *current <= '9') { 344 if (buffer_pos <= kMaxSignificantDigits) { 345 // If the number has more than kMaxSignificantDigits it will be parsed 346 // as infinity. 347 ASSERT(buffer_pos < kBufferSize); 348 buffer[buffer_pos++] = static_cast<char>(*current); 349 } 350 ++current; 351 if (current == end) break; 352 } 353 354 if (!allow_trailing_junk && 355 AdvanceToNonspace(scanner_constants, ¤t, end)) { 356 return JUNK_STRING_VALUE; 357 } 358 359 ASSERT(buffer_pos < kBufferSize); 360 buffer[buffer_pos] = '\0'; 361 Vector<const char> buffer_vector(buffer, buffer_pos); 362 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0); 363 } 364 365 // The following code causes accumulating rounding error for numbers greater 366 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10, 367 // 16, or 32, then mathInt may be an implementation-dependent approximation to 368 // the mathematical integer value" (15.1.2.2). 369 370 int lim_0 = '0' + (radix < 10 ? radix : 10); 371 int lim_a = 'a' + (radix - 10); 372 int lim_A = 'A' + (radix - 10); 373 374 // NOTE: The code for computing the value may seem a bit complex at 375 // first glance. It is structured to use 32-bit multiply-and-add 376 // loops as long as possible to avoid loosing precision. 377 378 double v = 0.0; 379 bool done = false; 380 do { 381 // Parse the longest part of the string starting at index j 382 // possible while keeping the multiplier, and thus the part 383 // itself, within 32 bits. 384 unsigned int part = 0, multiplier = 1; 385 while (true) { 386 int d; 387 if (*current >= '0' && *current < lim_0) { 388 d = *current - '0'; 389 } else if (*current >= 'a' && *current < lim_a) { 390 d = *current - 'a' + 10; 391 } else if (*current >= 'A' && *current < lim_A) { 392 d = *current - 'A' + 10; 393 } else { 394 done = true; 395 break; 396 } 397 398 // Update the value of the part as long as the multiplier fits 399 // in 32 bits. When we can't guarantee that the next iteration 400 // will not overflow the multiplier, we stop parsing the part 401 // by leaving the loop. 402 const unsigned int kMaximumMultiplier = 0xffffffffU / 36; 403 uint32_t m = multiplier * radix; 404 if (m > kMaximumMultiplier) break; 405 part = part * radix + d; 406 multiplier = m; 407 ASSERT(multiplier > part); 408 409 ++current; 410 if (current == end) { 411 done = true; 412 break; 413 } 414 } 415 416 // Update the value and skip the part in the string. 417 v = v * multiplier + part; 418 } while (!done); 419 420 if (!allow_trailing_junk && 421 AdvanceToNonspace(scanner_constants, ¤t, end)) { 422 return JUNK_STRING_VALUE; 423 } 424 425 return negative ? -v : v; 426} 427 428 429// Converts a string to a double value. Assumes the Iterator supports 430// the following operations: 431// 1. current == end (other ops are not allowed), current != end. 432// 2. *current - gets the current character in the sequence. 433// 3. ++current (advances the position). 434template <class Iterator, class EndMark> 435static double InternalStringToDouble(ScannerConstants* scanner_constants, 436 Iterator current, 437 EndMark end, 438 int flags, 439 double empty_string_val) { 440 // To make sure that iterator dereferencing is valid the following 441 // convention is used: 442 // 1. Each '++current' statement is followed by check for equality to 'end'. 443 // 2. If AdvanceToNonspace returned false then current == end. 444 // 3. If 'current' becomes be equal to 'end' the function returns or goes to 445 // 'parsing_done'. 446 // 4. 'current' is not dereferenced after the 'parsing_done' label. 447 // 5. Code before 'parsing_done' may rely on 'current != end'. 448 if (!AdvanceToNonspace(scanner_constants, ¤t, end)) { 449 return empty_string_val; 450 } 451 452 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0; 453 454 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0". 455 const int kBufferSize = kMaxSignificantDigits + 10; 456 char buffer[kBufferSize]; // NOLINT: size is known at compile time. 457 int buffer_pos = 0; 458 459 // Exponent will be adjusted if insignificant digits of the integer part 460 // or insignificant leading zeros of the fractional part are dropped. 461 int exponent = 0; 462 int significant_digits = 0; 463 int insignificant_digits = 0; 464 bool nonzero_digit_dropped = false; 465 bool fractional_part = false; 466 467 bool negative = false; 468 469 if (*current == '+') { 470 // Ignore leading sign. 471 ++current; 472 if (current == end) return JUNK_STRING_VALUE; 473 } else if (*current == '-') { 474 ++current; 475 if (current == end) return JUNK_STRING_VALUE; 476 negative = true; 477 } 478 479 static const char kInfinitySymbol[] = "Infinity"; 480 if (*current == kInfinitySymbol[0]) { 481 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { 482 return JUNK_STRING_VALUE; 483 } 484 485 if (!allow_trailing_junk && 486 AdvanceToNonspace(scanner_constants, ¤t, end)) { 487 return JUNK_STRING_VALUE; 488 } 489 490 ASSERT(buffer_pos == 0); 491 return negative ? -V8_INFINITY : V8_INFINITY; 492 } 493 494 bool leading_zero = false; 495 if (*current == '0') { 496 ++current; 497 if (current == end) return SignedZero(negative); 498 499 leading_zero = true; 500 501 // It could be hexadecimal value. 502 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { 503 ++current; 504 if (current == end || !isDigit(*current, 16)) { 505 return JUNK_STRING_VALUE; // "0x". 506 } 507 508 return InternalStringToIntDouble<4>(scanner_constants, 509 current, 510 end, 511 negative, 512 allow_trailing_junk); 513 } 514 515 // Ignore leading zeros in the integer part. 516 while (*current == '0') { 517 ++current; 518 if (current == end) return SignedZero(negative); 519 } 520 } 521 522 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0; 523 524 // Copy significant digits of the integer part (if any) to the buffer. 525 while (*current >= '0' && *current <= '9') { 526 if (significant_digits < kMaxSignificantDigits) { 527 ASSERT(buffer_pos < kBufferSize); 528 buffer[buffer_pos++] = static_cast<char>(*current); 529 significant_digits++; 530 // Will later check if it's an octal in the buffer. 531 } else { 532 insignificant_digits++; // Move the digit into the exponential part. 533 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; 534 } 535 octal = octal && *current < '8'; 536 ++current; 537 if (current == end) goto parsing_done; 538 } 539 540 if (significant_digits == 0) { 541 octal = false; 542 } 543 544 if (*current == '.') { 545 if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE; 546 if (octal) goto parsing_done; 547 548 ++current; 549 if (current == end) { 550 if (significant_digits == 0 && !leading_zero) { 551 return JUNK_STRING_VALUE; 552 } else { 553 goto parsing_done; 554 } 555 } 556 557 if (significant_digits == 0) { 558 // octal = false; 559 // Integer part consists of 0 or is absent. Significant digits start after 560 // leading zeros (if any). 561 while (*current == '0') { 562 ++current; 563 if (current == end) return SignedZero(negative); 564 exponent--; // Move this 0 into the exponent. 565 } 566 } 567 568 // We don't emit a '.', but adjust the exponent instead. 569 fractional_part = true; 570 571 // There is a fractional part. 572 while (*current >= '0' && *current <= '9') { 573 if (significant_digits < kMaxSignificantDigits) { 574 ASSERT(buffer_pos < kBufferSize); 575 buffer[buffer_pos++] = static_cast<char>(*current); 576 significant_digits++; 577 exponent--; 578 } else { 579 // Ignore insignificant digits in the fractional part. 580 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; 581 } 582 ++current; 583 if (current == end) goto parsing_done; 584 } 585 } 586 587 if (!leading_zero && exponent == 0 && significant_digits == 0) { 588 // If leading_zeros is true then the string contains zeros. 589 // If exponent < 0 then string was [+-]\.0*... 590 // If significant_digits != 0 the string is not equal to 0. 591 // Otherwise there are no digits in the string. 592 return JUNK_STRING_VALUE; 593 } 594 595 // Parse exponential part. 596 if (*current == 'e' || *current == 'E') { 597 if (octal) return JUNK_STRING_VALUE; 598 ++current; 599 if (current == end) { 600 if (allow_trailing_junk) { 601 goto parsing_done; 602 } else { 603 return JUNK_STRING_VALUE; 604 } 605 } 606 char sign = '+'; 607 if (*current == '+' || *current == '-') { 608 sign = static_cast<char>(*current); 609 ++current; 610 if (current == end) { 611 if (allow_trailing_junk) { 612 goto parsing_done; 613 } else { 614 return JUNK_STRING_VALUE; 615 } 616 } 617 } 618 619 if (current == end || *current < '0' || *current > '9') { 620 if (allow_trailing_junk) { 621 goto parsing_done; 622 } else { 623 return JUNK_STRING_VALUE; 624 } 625 } 626 627 const int max_exponent = INT_MAX / 2; 628 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); 629 int num = 0; 630 do { 631 // Check overflow. 632 int digit = *current - '0'; 633 if (num >= max_exponent / 10 634 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { 635 num = max_exponent; 636 } else { 637 num = num * 10 + digit; 638 } 639 ++current; 640 } while (current != end && *current >= '0' && *current <= '9'); 641 642 exponent += (sign == '-' ? -num : num); 643 } 644 645 if (!allow_trailing_junk && 646 AdvanceToNonspace(scanner_constants, ¤t, end)) { 647 return JUNK_STRING_VALUE; 648 } 649 650 parsing_done: 651 exponent += insignificant_digits; 652 653 if (octal) { 654 return InternalStringToIntDouble<3>(scanner_constants, 655 buffer, 656 buffer + buffer_pos, 657 negative, 658 allow_trailing_junk); 659 } 660 661 if (nonzero_digit_dropped) { 662 buffer[buffer_pos++] = '1'; 663 exponent--; 664 } 665 666 ASSERT(buffer_pos < kBufferSize); 667 buffer[buffer_pos] = '\0'; 668 669 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); 670 return negative ? -converted : converted; 671} 672 673 674double StringToDouble(String* str, int flags, double empty_string_val) { 675 ScannerConstants* scanner_constants = 676 Isolate::Current()->scanner_constants(); 677 StringShape shape(str); 678 if (shape.IsSequentialAscii()) { 679 const char* begin = SeqAsciiString::cast(str)->GetChars(); 680 const char* end = begin + str->length(); 681 return InternalStringToDouble(scanner_constants, begin, end, flags, 682 empty_string_val); 683 } else if (shape.IsSequentialTwoByte()) { 684 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); 685 const uc16* end = begin + str->length(); 686 return InternalStringToDouble(scanner_constants, begin, end, flags, 687 empty_string_val); 688 } else { 689 StringInputBuffer buffer(str); 690 return InternalStringToDouble(scanner_constants, 691 StringInputBufferIterator(&buffer), 692 StringInputBufferIterator::EndMarker(), 693 flags, 694 empty_string_val); 695 } 696} 697 698 699double StringToInt(String* str, int radix) { 700 ScannerConstants* scanner_constants = 701 Isolate::Current()->scanner_constants(); 702 StringShape shape(str); 703 if (shape.IsSequentialAscii()) { 704 const char* begin = SeqAsciiString::cast(str)->GetChars(); 705 const char* end = begin + str->length(); 706 return InternalStringToInt(scanner_constants, begin, end, radix); 707 } else if (shape.IsSequentialTwoByte()) { 708 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); 709 const uc16* end = begin + str->length(); 710 return InternalStringToInt(scanner_constants, begin, end, radix); 711 } else { 712 StringInputBuffer buffer(str); 713 return InternalStringToInt(scanner_constants, 714 StringInputBufferIterator(&buffer), 715 StringInputBufferIterator::EndMarker(), 716 radix); 717 } 718} 719 720 721double StringToDouble(const char* str, int flags, double empty_string_val) { 722 ScannerConstants* scanner_constants = 723 Isolate::Current()->scanner_constants(); 724 const char* end = str + StrLength(str); 725 return InternalStringToDouble(scanner_constants, str, end, flags, 726 empty_string_val); 727} 728 729 730double StringToDouble(Vector<const char> str, 731 int flags, 732 double empty_string_val) { 733 ScannerConstants* scanner_constants = 734 Isolate::Current()->scanner_constants(); 735 const char* end = str.start() + str.length(); 736 return InternalStringToDouble(scanner_constants, str.start(), end, flags, 737 empty_string_val); 738} 739 740 741const char* DoubleToCString(double v, Vector<char> buffer) { 742 switch (fpclassify(v)) { 743 case FP_NAN: return "NaN"; 744 case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity"); 745 case FP_ZERO: return "0"; 746 default: { 747 StringBuilder builder(buffer.start(), buffer.length()); 748 int decimal_point; 749 int sign; 750 const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1; 751 char decimal_rep[kV8DtoaBufferCapacity]; 752 int length; 753 754 DoubleToAscii(v, DTOA_SHORTEST, 0, 755 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 756 &sign, &length, &decimal_point); 757 758 if (sign) builder.AddCharacter('-'); 759 760 if (length <= decimal_point && decimal_point <= 21) { 761 // ECMA-262 section 9.8.1 step 6. 762 builder.AddString(decimal_rep); 763 builder.AddPadding('0', decimal_point - length); 764 765 } else if (0 < decimal_point && decimal_point <= 21) { 766 // ECMA-262 section 9.8.1 step 7. 767 builder.AddSubstring(decimal_rep, decimal_point); 768 builder.AddCharacter('.'); 769 builder.AddString(decimal_rep + decimal_point); 770 771 } else if (decimal_point <= 0 && decimal_point > -6) { 772 // ECMA-262 section 9.8.1 step 8. 773 builder.AddString("0."); 774 builder.AddPadding('0', -decimal_point); 775 builder.AddString(decimal_rep); 776 777 } else { 778 // ECMA-262 section 9.8.1 step 9 and 10 combined. 779 builder.AddCharacter(decimal_rep[0]); 780 if (length != 1) { 781 builder.AddCharacter('.'); 782 builder.AddString(decimal_rep + 1); 783 } 784 builder.AddCharacter('e'); 785 builder.AddCharacter((decimal_point >= 0) ? '+' : '-'); 786 int exponent = decimal_point - 1; 787 if (exponent < 0) exponent = -exponent; 788 builder.AddFormatted("%d", exponent); 789 } 790 return builder.Finalize(); 791 } 792 } 793} 794 795 796const char* IntToCString(int n, Vector<char> buffer) { 797 bool negative = false; 798 if (n < 0) { 799 // We must not negate the most negative int. 800 if (n == kMinInt) return DoubleToCString(n, buffer); 801 negative = true; 802 n = -n; 803 } 804 // Build the string backwards from the least significant digit. 805 int i = buffer.length(); 806 buffer[--i] = '\0'; 807 do { 808 buffer[--i] = '0' + (n % 10); 809 n /= 10; 810 } while (n); 811 if (negative) buffer[--i] = '-'; 812 return buffer.start() + i; 813} 814 815 816char* DoubleToFixedCString(double value, int f) { 817 const int kMaxDigitsBeforePoint = 21; 818 const double kFirstNonFixed = 1e21; 819 const int kMaxDigitsAfterPoint = 20; 820 ASSERT(f >= 0); 821 ASSERT(f <= kMaxDigitsAfterPoint); 822 823 bool negative = false; 824 double abs_value = value; 825 if (value < 0) { 826 abs_value = -value; 827 negative = true; 828 } 829 830 // If abs_value has more than kMaxDigitsBeforePoint digits before the point 831 // use the non-fixed conversion routine. 832 if (abs_value >= kFirstNonFixed) { 833 char arr[100]; 834 Vector<char> buffer(arr, ARRAY_SIZE(arr)); 835 return StrDup(DoubleToCString(value, buffer)); 836 } 837 838 // Find a sufficiently precise decimal representation of n. 839 int decimal_point; 840 int sign; 841 // Add space for the '\0' byte. 842 const int kDecimalRepCapacity = 843 kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1; 844 char decimal_rep[kDecimalRepCapacity]; 845 int decimal_rep_length; 846 DoubleToAscii(value, DTOA_FIXED, f, 847 Vector<char>(decimal_rep, kDecimalRepCapacity), 848 &sign, &decimal_rep_length, &decimal_point); 849 850 // Create a representation that is padded with zeros if needed. 851 int zero_prefix_length = 0; 852 int zero_postfix_length = 0; 853 854 if (decimal_point <= 0) { 855 zero_prefix_length = -decimal_point + 1; 856 decimal_point = 1; 857 } 858 859 if (zero_prefix_length + decimal_rep_length < decimal_point + f) { 860 zero_postfix_length = decimal_point + f - decimal_rep_length - 861 zero_prefix_length; 862 } 863 864 unsigned rep_length = 865 zero_prefix_length + decimal_rep_length + zero_postfix_length; 866 StringBuilder rep_builder(rep_length + 1); 867 rep_builder.AddPadding('0', zero_prefix_length); 868 rep_builder.AddString(decimal_rep); 869 rep_builder.AddPadding('0', zero_postfix_length); 870 char* rep = rep_builder.Finalize(); 871 872 // Create the result string by appending a minus and putting in a 873 // decimal point if needed. 874 unsigned result_size = decimal_point + f + 2; 875 StringBuilder builder(result_size + 1); 876 if (negative) builder.AddCharacter('-'); 877 builder.AddSubstring(rep, decimal_point); 878 if (f > 0) { 879 builder.AddCharacter('.'); 880 builder.AddSubstring(rep + decimal_point, f); 881 } 882 DeleteArray(rep); 883 return builder.Finalize(); 884} 885 886 887static char* CreateExponentialRepresentation(char* decimal_rep, 888 int exponent, 889 bool negative, 890 int significant_digits) { 891 bool negative_exponent = false; 892 if (exponent < 0) { 893 negative_exponent = true; 894 exponent = -exponent; 895 } 896 897 // Leave room in the result for appending a minus, for a period, the 898 // letter 'e', a minus or a plus depending on the exponent, and a 899 // three digit exponent. 900 unsigned result_size = significant_digits + 7; 901 StringBuilder builder(result_size + 1); 902 903 if (negative) builder.AddCharacter('-'); 904 builder.AddCharacter(decimal_rep[0]); 905 if (significant_digits != 1) { 906 builder.AddCharacter('.'); 907 builder.AddString(decimal_rep + 1); 908 int rep_length = StrLength(decimal_rep); 909 builder.AddPadding('0', significant_digits - rep_length); 910 } 911 912 builder.AddCharacter('e'); 913 builder.AddCharacter(negative_exponent ? '-' : '+'); 914 builder.AddFormatted("%d", exponent); 915 return builder.Finalize(); 916} 917 918 919 920char* DoubleToExponentialCString(double value, int f) { 921 const int kMaxDigitsAfterPoint = 20; 922 // f might be -1 to signal that f was undefined in JavaScript. 923 ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint); 924 925 bool negative = false; 926 if (value < 0) { 927 value = -value; 928 negative = true; 929 } 930 931 // Find a sufficiently precise decimal representation of n. 932 int decimal_point; 933 int sign; 934 // f corresponds to the digits after the point. There is always one digit 935 // before the point. The number of requested_digits equals hence f + 1. 936 // And we have to add one character for the null-terminator. 937 const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1; 938 // Make sure that the buffer is big enough, even if we fall back to the 939 // shortest representation (which happens when f equals -1). 940 ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1); 941 char decimal_rep[kV8DtoaBufferCapacity]; 942 int decimal_rep_length; 943 944 if (f == -1) { 945 DoubleToAscii(value, DTOA_SHORTEST, 0, 946 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 947 &sign, &decimal_rep_length, &decimal_point); 948 f = decimal_rep_length - 1; 949 } else { 950 DoubleToAscii(value, DTOA_PRECISION, f + 1, 951 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 952 &sign, &decimal_rep_length, &decimal_point); 953 } 954 ASSERT(decimal_rep_length > 0); 955 ASSERT(decimal_rep_length <= f + 1); 956 957 int exponent = decimal_point - 1; 958 char* result = 959 CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1); 960 961 return result; 962} 963 964 965char* DoubleToPrecisionCString(double value, int p) { 966 const int kMinimalDigits = 1; 967 const int kMaximalDigits = 21; 968 ASSERT(p >= kMinimalDigits && p <= kMaximalDigits); 969 USE(kMinimalDigits); 970 971 bool negative = false; 972 if (value < 0) { 973 value = -value; 974 negative = true; 975 } 976 977 // Find a sufficiently precise decimal representation of n. 978 int decimal_point; 979 int sign; 980 // Add one for the terminating null character. 981 const int kV8DtoaBufferCapacity = kMaximalDigits + 1; 982 char decimal_rep[kV8DtoaBufferCapacity]; 983 int decimal_rep_length; 984 985 DoubleToAscii(value, DTOA_PRECISION, p, 986 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 987 &sign, &decimal_rep_length, &decimal_point); 988 ASSERT(decimal_rep_length <= p); 989 990 int exponent = decimal_point - 1; 991 992 char* result = NULL; 993 994 if (exponent < -6 || exponent >= p) { 995 result = 996 CreateExponentialRepresentation(decimal_rep, exponent, negative, p); 997 } else { 998 // Use fixed notation. 999 // 1000 // Leave room in the result for appending a minus, a period and in 1001 // the case where decimal_point is not positive for a zero in 1002 // front of the period. 1003 unsigned result_size = (decimal_point <= 0) 1004 ? -decimal_point + p + 3 1005 : p + 2; 1006 StringBuilder builder(result_size + 1); 1007 if (negative) builder.AddCharacter('-'); 1008 if (decimal_point <= 0) { 1009 builder.AddString("0."); 1010 builder.AddPadding('0', -decimal_point); 1011 builder.AddString(decimal_rep); 1012 builder.AddPadding('0', p - decimal_rep_length); 1013 } else { 1014 const int m = Min(decimal_rep_length, decimal_point); 1015 builder.AddSubstring(decimal_rep, m); 1016 builder.AddPadding('0', decimal_point - decimal_rep_length); 1017 if (decimal_point < p) { 1018 builder.AddCharacter('.'); 1019 const int extra = negative ? 2 : 1; 1020 if (decimal_rep_length > decimal_point) { 1021 const int len = StrLength(decimal_rep + decimal_point); 1022 const int n = Min(len, p - (builder.position() - extra)); 1023 builder.AddSubstring(decimal_rep + decimal_point, n); 1024 } 1025 builder.AddPadding('0', extra + (p - builder.position())); 1026 } 1027 } 1028 result = builder.Finalize(); 1029 } 1030 1031 return result; 1032} 1033 1034 1035char* DoubleToRadixCString(double value, int radix) { 1036 ASSERT(radix >= 2 && radix <= 36); 1037 1038 // Character array used for conversion. 1039 static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 1040 1041 // Buffer for the integer part of the result. 1024 chars is enough 1042 // for max integer value in radix 2. We need room for a sign too. 1043 static const int kBufferSize = 1100; 1044 char integer_buffer[kBufferSize]; 1045 integer_buffer[kBufferSize - 1] = '\0'; 1046 1047 // Buffer for the decimal part of the result. We only generate up 1048 // to kBufferSize - 1 chars for the decimal part. 1049 char decimal_buffer[kBufferSize]; 1050 decimal_buffer[kBufferSize - 1] = '\0'; 1051 1052 // Make sure the value is positive. 1053 bool is_negative = value < 0.0; 1054 if (is_negative) value = -value; 1055 1056 // Get the integer part and the decimal part. 1057 double integer_part = floor(value); 1058 double decimal_part = value - integer_part; 1059 1060 // Convert the integer part starting from the back. Always generate 1061 // at least one digit. 1062 int integer_pos = kBufferSize - 2; 1063 do { 1064 integer_buffer[integer_pos--] = 1065 chars[static_cast<int>(modulo(integer_part, radix))]; 1066 integer_part /= radix; 1067 } while (integer_part >= 1.0); 1068 // Sanity check. 1069 ASSERT(integer_pos > 0); 1070 // Add sign if needed. 1071 if (is_negative) integer_buffer[integer_pos--] = '-'; 1072 1073 // Convert the decimal part. Repeatedly multiply by the radix to 1074 // generate the next char. Never generate more than kBufferSize - 1 1075 // chars. 1076 // 1077 // TODO(1093998): We will often generate a full decimal_buffer of 1078 // chars because hitting zero will often not happen. The right 1079 // solution would be to continue until the string representation can 1080 // be read back and yield the original value. To implement this 1081 // efficiently, we probably have to modify dtoa. 1082 int decimal_pos = 0; 1083 while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) { 1084 decimal_part *= radix; 1085 decimal_buffer[decimal_pos++] = 1086 chars[static_cast<int>(floor(decimal_part))]; 1087 decimal_part -= floor(decimal_part); 1088 } 1089 decimal_buffer[decimal_pos] = '\0'; 1090 1091 // Compute the result size. 1092 int integer_part_size = kBufferSize - 2 - integer_pos; 1093 // Make room for zero termination. 1094 unsigned result_size = integer_part_size + decimal_pos; 1095 // If the number has a decimal part, leave room for the period. 1096 if (decimal_pos > 0) result_size++; 1097 // Allocate result and fill in the parts. 1098 StringBuilder builder(result_size + 1); 1099 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); 1100 if (decimal_pos > 0) builder.AddCharacter('.'); 1101 builder.AddSubstring(decimal_buffer, decimal_pos); 1102 return builder.Finalize(); 1103} 1104 1105 1106static Mutex* dtoa_lock_one = OS::CreateMutex(); 1107static Mutex* dtoa_lock_zero = OS::CreateMutex(); 1108 1109 1110} } // namespace v8::internal 1111 1112 1113extern "C" { 1114void ACQUIRE_DTOA_LOCK(int n) { 1115 ASSERT(n == 0 || n == 1); 1116 (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->Lock(); 1117} 1118 1119 1120void FREE_DTOA_LOCK(int n) { 1121 ASSERT(n == 0 || n == 1); 1122 (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)-> 1123 Unlock(); 1124} 1125} 1126