conversions.cc revision 257744e915dfc84d6d07a6b2accf8402d9ffc708
1// Copyright 2011 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(UnicodeCache* unicode_cache, 113 Iterator* current, 114 EndMark end) { 115 while (*current != end) { 116 if (!unicode_cache->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(UnicodeCache* unicode_cache, 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(unicode_cache, ¤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(unicode_cache, ¤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(UnicodeCache* unicode_cache, 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(unicode_cache, ¤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 (current == end) { 258 return JUNK_STRING_VALUE; 259 } 260 } else if (*current == '-') { 261 ++current; 262 if (current == 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 unicode_cache, current, end, negative, allow_trailing_junk); 316 case 4: 317 return InternalStringToIntDouble<2>( 318 unicode_cache, current, end, negative, allow_trailing_junk); 319 case 8: 320 return InternalStringToIntDouble<3>( 321 unicode_cache, current, end, negative, allow_trailing_junk); 322 323 case 16: 324 return InternalStringToIntDouble<4>( 325 unicode_cache, current, end, negative, allow_trailing_junk); 326 327 case 32: 328 return InternalStringToIntDouble<5>( 329 unicode_cache, 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(unicode_cache, ¤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(unicode_cache, ¤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(UnicodeCache* unicode_cache, 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(unicode_cache, ¤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(unicode_cache, ¤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>(unicode_cache, 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(unicode_cache, ¤t, end)) { 647 return JUNK_STRING_VALUE; 648 } 649 650 parsing_done: 651 exponent += insignificant_digits; 652 653 if (octal) { 654 return InternalStringToIntDouble<3>(unicode_cache, 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(UnicodeCache* unicode_cache, 675 String* str, int flags, double empty_string_val) { 676 StringShape shape(str); 677 if (shape.IsSequentialAscii()) { 678 const char* begin = SeqAsciiString::cast(str)->GetChars(); 679 const char* end = begin + str->length(); 680 return InternalStringToDouble(unicode_cache, begin, end, flags, 681 empty_string_val); 682 } else if (shape.IsSequentialTwoByte()) { 683 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); 684 const uc16* end = begin + str->length(); 685 return InternalStringToDouble(unicode_cache, begin, end, flags, 686 empty_string_val); 687 } else { 688 StringInputBuffer buffer(str); 689 return InternalStringToDouble(unicode_cache, 690 StringInputBufferIterator(&buffer), 691 StringInputBufferIterator::EndMarker(), 692 flags, 693 empty_string_val); 694 } 695} 696 697 698double StringToInt(UnicodeCache* unicode_cache, 699 String* str, 700 int radix) { 701 StringShape shape(str); 702 if (shape.IsSequentialAscii()) { 703 const char* begin = SeqAsciiString::cast(str)->GetChars(); 704 const char* end = begin + str->length(); 705 return InternalStringToInt(unicode_cache, begin, end, radix); 706 } else if (shape.IsSequentialTwoByte()) { 707 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); 708 const uc16* end = begin + str->length(); 709 return InternalStringToInt(unicode_cache, begin, end, radix); 710 } else { 711 StringInputBuffer buffer(str); 712 return InternalStringToInt(unicode_cache, 713 StringInputBufferIterator(&buffer), 714 StringInputBufferIterator::EndMarker(), 715 radix); 716 } 717} 718 719 720double StringToDouble(UnicodeCache* unicode_cache, 721 const char* str, int flags, double empty_string_val) { 722 const char* end = str + StrLength(str); 723 return InternalStringToDouble(unicode_cache, str, end, flags, 724 empty_string_val); 725} 726 727 728double StringToDouble(UnicodeCache* unicode_cache, 729 Vector<const char> str, 730 int flags, 731 double empty_string_val) { 732 const char* end = str.start() + str.length(); 733 return InternalStringToDouble(unicode_cache, str.start(), end, flags, 734 empty_string_val); 735} 736 737double StringToDouble(UnicodeCache* unicode_cache, 738 Vector<const uc16> str, 739 int flags, 740 double empty_string_val) { 741 const uc16* end = str.start() + str.length(); 742 return InternalStringToDouble(unicode_cache, str.start(), end, flags, 743 empty_string_val); 744} 745 746 747const char* DoubleToCString(double v, Vector<char> buffer) { 748 switch (fpclassify(v)) { 749 case FP_NAN: return "NaN"; 750 case FP_INFINITE: return (v < 0.0 ? "-Infinity" : "Infinity"); 751 case FP_ZERO: return "0"; 752 default: { 753 StringBuilder builder(buffer.start(), buffer.length()); 754 int decimal_point; 755 int sign; 756 const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1; 757 char decimal_rep[kV8DtoaBufferCapacity]; 758 int length; 759 760 DoubleToAscii(v, DTOA_SHORTEST, 0, 761 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 762 &sign, &length, &decimal_point); 763 764 if (sign) builder.AddCharacter('-'); 765 766 if (length <= decimal_point && decimal_point <= 21) { 767 // ECMA-262 section 9.8.1 step 6. 768 builder.AddString(decimal_rep); 769 builder.AddPadding('0', decimal_point - length); 770 771 } else if (0 < decimal_point && decimal_point <= 21) { 772 // ECMA-262 section 9.8.1 step 7. 773 builder.AddSubstring(decimal_rep, decimal_point); 774 builder.AddCharacter('.'); 775 builder.AddString(decimal_rep + decimal_point); 776 777 } else if (decimal_point <= 0 && decimal_point > -6) { 778 // ECMA-262 section 9.8.1 step 8. 779 builder.AddString("0."); 780 builder.AddPadding('0', -decimal_point); 781 builder.AddString(decimal_rep); 782 783 } else { 784 // ECMA-262 section 9.8.1 step 9 and 10 combined. 785 builder.AddCharacter(decimal_rep[0]); 786 if (length != 1) { 787 builder.AddCharacter('.'); 788 builder.AddString(decimal_rep + 1); 789 } 790 builder.AddCharacter('e'); 791 builder.AddCharacter((decimal_point >= 0) ? '+' : '-'); 792 int exponent = decimal_point - 1; 793 if (exponent < 0) exponent = -exponent; 794 builder.AddFormatted("%d", exponent); 795 } 796 return builder.Finalize(); 797 } 798 } 799} 800 801 802const char* IntToCString(int n, Vector<char> buffer) { 803 bool negative = false; 804 if (n < 0) { 805 // We must not negate the most negative int. 806 if (n == kMinInt) return DoubleToCString(n, buffer); 807 negative = true; 808 n = -n; 809 } 810 // Build the string backwards from the least significant digit. 811 int i = buffer.length(); 812 buffer[--i] = '\0'; 813 do { 814 buffer[--i] = '0' + (n % 10); 815 n /= 10; 816 } while (n); 817 if (negative) buffer[--i] = '-'; 818 return buffer.start() + i; 819} 820 821 822char* DoubleToFixedCString(double value, int f) { 823 const int kMaxDigitsBeforePoint = 21; 824 const double kFirstNonFixed = 1e21; 825 const int kMaxDigitsAfterPoint = 20; 826 ASSERT(f >= 0); 827 ASSERT(f <= kMaxDigitsAfterPoint); 828 829 bool negative = false; 830 double abs_value = value; 831 if (value < 0) { 832 abs_value = -value; 833 negative = true; 834 } 835 836 // If abs_value has more than kMaxDigitsBeforePoint digits before the point 837 // use the non-fixed conversion routine. 838 if (abs_value >= kFirstNonFixed) { 839 char arr[100]; 840 Vector<char> buffer(arr, ARRAY_SIZE(arr)); 841 return StrDup(DoubleToCString(value, buffer)); 842 } 843 844 // Find a sufficiently precise decimal representation of n. 845 int decimal_point; 846 int sign; 847 // Add space for the '\0' byte. 848 const int kDecimalRepCapacity = 849 kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 1; 850 char decimal_rep[kDecimalRepCapacity]; 851 int decimal_rep_length; 852 DoubleToAscii(value, DTOA_FIXED, f, 853 Vector<char>(decimal_rep, kDecimalRepCapacity), 854 &sign, &decimal_rep_length, &decimal_point); 855 856 // Create a representation that is padded with zeros if needed. 857 int zero_prefix_length = 0; 858 int zero_postfix_length = 0; 859 860 if (decimal_point <= 0) { 861 zero_prefix_length = -decimal_point + 1; 862 decimal_point = 1; 863 } 864 865 if (zero_prefix_length + decimal_rep_length < decimal_point + f) { 866 zero_postfix_length = decimal_point + f - decimal_rep_length - 867 zero_prefix_length; 868 } 869 870 unsigned rep_length = 871 zero_prefix_length + decimal_rep_length + zero_postfix_length; 872 StringBuilder rep_builder(rep_length + 1); 873 rep_builder.AddPadding('0', zero_prefix_length); 874 rep_builder.AddString(decimal_rep); 875 rep_builder.AddPadding('0', zero_postfix_length); 876 char* rep = rep_builder.Finalize(); 877 878 // Create the result string by appending a minus and putting in a 879 // decimal point if needed. 880 unsigned result_size = decimal_point + f + 2; 881 StringBuilder builder(result_size + 1); 882 if (negative) builder.AddCharacter('-'); 883 builder.AddSubstring(rep, decimal_point); 884 if (f > 0) { 885 builder.AddCharacter('.'); 886 builder.AddSubstring(rep + decimal_point, f); 887 } 888 DeleteArray(rep); 889 return builder.Finalize(); 890} 891 892 893static char* CreateExponentialRepresentation(char* decimal_rep, 894 int exponent, 895 bool negative, 896 int significant_digits) { 897 bool negative_exponent = false; 898 if (exponent < 0) { 899 negative_exponent = true; 900 exponent = -exponent; 901 } 902 903 // Leave room in the result for appending a minus, for a period, the 904 // letter 'e', a minus or a plus depending on the exponent, and a 905 // three digit exponent. 906 unsigned result_size = significant_digits + 7; 907 StringBuilder builder(result_size + 1); 908 909 if (negative) builder.AddCharacter('-'); 910 builder.AddCharacter(decimal_rep[0]); 911 if (significant_digits != 1) { 912 builder.AddCharacter('.'); 913 builder.AddString(decimal_rep + 1); 914 int rep_length = StrLength(decimal_rep); 915 builder.AddPadding('0', significant_digits - rep_length); 916 } 917 918 builder.AddCharacter('e'); 919 builder.AddCharacter(negative_exponent ? '-' : '+'); 920 builder.AddFormatted("%d", exponent); 921 return builder.Finalize(); 922} 923 924 925 926char* DoubleToExponentialCString(double value, int f) { 927 const int kMaxDigitsAfterPoint = 20; 928 // f might be -1 to signal that f was undefined in JavaScript. 929 ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint); 930 931 bool negative = false; 932 if (value < 0) { 933 value = -value; 934 negative = true; 935 } 936 937 // Find a sufficiently precise decimal representation of n. 938 int decimal_point; 939 int sign; 940 // f corresponds to the digits after the point. There is always one digit 941 // before the point. The number of requested_digits equals hence f + 1. 942 // And we have to add one character for the null-terminator. 943 const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1; 944 // Make sure that the buffer is big enough, even if we fall back to the 945 // shortest representation (which happens when f equals -1). 946 ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1); 947 char decimal_rep[kV8DtoaBufferCapacity]; 948 int decimal_rep_length; 949 950 if (f == -1) { 951 DoubleToAscii(value, DTOA_SHORTEST, 0, 952 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 953 &sign, &decimal_rep_length, &decimal_point); 954 f = decimal_rep_length - 1; 955 } else { 956 DoubleToAscii(value, DTOA_PRECISION, f + 1, 957 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 958 &sign, &decimal_rep_length, &decimal_point); 959 } 960 ASSERT(decimal_rep_length > 0); 961 ASSERT(decimal_rep_length <= f + 1); 962 963 int exponent = decimal_point - 1; 964 char* result = 965 CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1); 966 967 return result; 968} 969 970 971char* DoubleToPrecisionCString(double value, int p) { 972 const int kMinimalDigits = 1; 973 const int kMaximalDigits = 21; 974 ASSERT(p >= kMinimalDigits && p <= kMaximalDigits); 975 USE(kMinimalDigits); 976 977 bool negative = false; 978 if (value < 0) { 979 value = -value; 980 negative = true; 981 } 982 983 // Find a sufficiently precise decimal representation of n. 984 int decimal_point; 985 int sign; 986 // Add one for the terminating null character. 987 const int kV8DtoaBufferCapacity = kMaximalDigits + 1; 988 char decimal_rep[kV8DtoaBufferCapacity]; 989 int decimal_rep_length; 990 991 DoubleToAscii(value, DTOA_PRECISION, p, 992 Vector<char>(decimal_rep, kV8DtoaBufferCapacity), 993 &sign, &decimal_rep_length, &decimal_point); 994 ASSERT(decimal_rep_length <= p); 995 996 int exponent = decimal_point - 1; 997 998 char* result = NULL; 999 1000 if (exponent < -6 || exponent >= p) { 1001 result = 1002 CreateExponentialRepresentation(decimal_rep, exponent, negative, p); 1003 } else { 1004 // Use fixed notation. 1005 // 1006 // Leave room in the result for appending a minus, a period and in 1007 // the case where decimal_point is not positive for a zero in 1008 // front of the period. 1009 unsigned result_size = (decimal_point <= 0) 1010 ? -decimal_point + p + 3 1011 : p + 2; 1012 StringBuilder builder(result_size + 1); 1013 if (negative) builder.AddCharacter('-'); 1014 if (decimal_point <= 0) { 1015 builder.AddString("0."); 1016 builder.AddPadding('0', -decimal_point); 1017 builder.AddString(decimal_rep); 1018 builder.AddPadding('0', p - decimal_rep_length); 1019 } else { 1020 const int m = Min(decimal_rep_length, decimal_point); 1021 builder.AddSubstring(decimal_rep, m); 1022 builder.AddPadding('0', decimal_point - decimal_rep_length); 1023 if (decimal_point < p) { 1024 builder.AddCharacter('.'); 1025 const int extra = negative ? 2 : 1; 1026 if (decimal_rep_length > decimal_point) { 1027 const int len = StrLength(decimal_rep + decimal_point); 1028 const int n = Min(len, p - (builder.position() - extra)); 1029 builder.AddSubstring(decimal_rep + decimal_point, n); 1030 } 1031 builder.AddPadding('0', extra + (p - builder.position())); 1032 } 1033 } 1034 result = builder.Finalize(); 1035 } 1036 1037 return result; 1038} 1039 1040 1041char* DoubleToRadixCString(double value, int radix) { 1042 ASSERT(radix >= 2 && radix <= 36); 1043 1044 // Character array used for conversion. 1045 static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 1046 1047 // Buffer for the integer part of the result. 1024 chars is enough 1048 // for max integer value in radix 2. We need room for a sign too. 1049 static const int kBufferSize = 1100; 1050 char integer_buffer[kBufferSize]; 1051 integer_buffer[kBufferSize - 1] = '\0'; 1052 1053 // Buffer for the decimal part of the result. We only generate up 1054 // to kBufferSize - 1 chars for the decimal part. 1055 char decimal_buffer[kBufferSize]; 1056 decimal_buffer[kBufferSize - 1] = '\0'; 1057 1058 // Make sure the value is positive. 1059 bool is_negative = value < 0.0; 1060 if (is_negative) value = -value; 1061 1062 // Get the integer part and the decimal part. 1063 double integer_part = floor(value); 1064 double decimal_part = value - integer_part; 1065 1066 // Convert the integer part starting from the back. Always generate 1067 // at least one digit. 1068 int integer_pos = kBufferSize - 2; 1069 do { 1070 integer_buffer[integer_pos--] = 1071 chars[static_cast<int>(modulo(integer_part, radix))]; 1072 integer_part /= radix; 1073 } while (integer_part >= 1.0); 1074 // Sanity check. 1075 ASSERT(integer_pos > 0); 1076 // Add sign if needed. 1077 if (is_negative) integer_buffer[integer_pos--] = '-'; 1078 1079 // Convert the decimal part. Repeatedly multiply by the radix to 1080 // generate the next char. Never generate more than kBufferSize - 1 1081 // chars. 1082 // 1083 // TODO(1093998): We will often generate a full decimal_buffer of 1084 // chars because hitting zero will often not happen. The right 1085 // solution would be to continue until the string representation can 1086 // be read back and yield the original value. To implement this 1087 // efficiently, we probably have to modify dtoa. 1088 int decimal_pos = 0; 1089 while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) { 1090 decimal_part *= radix; 1091 decimal_buffer[decimal_pos++] = 1092 chars[static_cast<int>(floor(decimal_part))]; 1093 decimal_part -= floor(decimal_part); 1094 } 1095 decimal_buffer[decimal_pos] = '\0'; 1096 1097 // Compute the result size. 1098 int integer_part_size = kBufferSize - 2 - integer_pos; 1099 // Make room for zero termination. 1100 unsigned result_size = integer_part_size + decimal_pos; 1101 // If the number has a decimal part, leave room for the period. 1102 if (decimal_pos > 0) result_size++; 1103 // Allocate result and fill in the parts. 1104 StringBuilder builder(result_size + 1); 1105 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); 1106 if (decimal_pos > 0) builder.AddCharacter('.'); 1107 builder.AddSubstring(decimal_buffer, decimal_pos); 1108 return builder.Finalize(); 1109} 1110 1111 1112static Mutex* dtoa_lock_one = OS::CreateMutex(); 1113static Mutex* dtoa_lock_zero = OS::CreateMutex(); 1114 1115 1116} } // namespace v8::internal 1117 1118 1119extern "C" { 1120void ACQUIRE_DTOA_LOCK(int n) { 1121 ASSERT(n == 0 || n == 1); 1122 (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)->Lock(); 1123} 1124 1125 1126void FREE_DTOA_LOCK(int n) { 1127 ASSERT(n == 0 || n == 1); 1128 (n == 0 ? v8::internal::dtoa_lock_zero : v8::internal::dtoa_lock_one)-> 1129 Unlock(); 1130} 1131} 1132