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