| Index: src/conversions.cc
|
| ===================================================================
|
| --- src/conversions.cc (revision 4329)
|
| +++ src/conversions.cc (working copy)
|
| @@ -48,6 +48,51 @@
|
| return -1;
|
| }
|
|
|
| +
|
| +// Provide a common interface to getting a character at a certain
|
| +// index from a char* or a String object.
|
| +static inline int GetChar(const char* str, int index) {
|
| + ASSERT(index >= 0 && index < StrLength(str));
|
| + return str[index];
|
| +}
|
| +
|
| +
|
| +static inline int GetChar(String* str, int index) {
|
| + return str->Get(index);
|
| +}
|
| +
|
| +
|
| +static inline int GetLength(const char* str) {
|
| + return StrLength(str);
|
| +}
|
| +
|
| +
|
| +static inline int GetLength(String* str) {
|
| + return str->length();
|
| +}
|
| +
|
| +
|
| +static inline const char* GetCString(const char* str, int index) {
|
| + return str + index;
|
| +}
|
| +
|
| +
|
| +static inline const char* GetCString(String* str, int index) {
|
| + int length = str->length();
|
| + char* result = NewArray<char>(length + 1);
|
| + for (int i = index; i < length; i++) {
|
| + uc16 c = str->Get(i);
|
| + if (c <= 127) {
|
| + result[i - index] = static_cast<char>(c);
|
| + } else {
|
| + result[i - index] = 127; // Force number parsing to fail.
|
| + }
|
| + }
|
| + result[length - index] = '\0';
|
| + return result;
|
| +}
|
| +
|
| +
|
| namespace {
|
|
|
| // C++-style iterator adaptor for StringInputBuffer
|
| @@ -89,6 +134,15 @@
|
| }
|
|
|
|
|
| +static inline void ReleaseCString(const char* original, const char* str) {
|
| +}
|
| +
|
| +
|
| +static inline void ReleaseCString(String* original, const char* str) {
|
| + DeleteArray(const_cast<char *>(str));
|
| +}
|
| +
|
| +
|
| template <class Iterator, class EndMark>
|
| static bool SubStringEquals(Iterator* current,
|
| EndMark end,
|
| @@ -114,7 +168,98 @@
|
| // we don't need to preserve all the digits.
|
| const int kMaxSignificantDigits = 772;
|
|
|
| +// Parse an int from a string starting a given index and in a given
|
| +// radix. The string can be either a char* or a String*.
|
| +template <class S>
|
| +static int InternalStringToInt(S* s, int i, int radix, double* value) {
|
| + int len = GetLength(s);
|
|
|
| + // Setup limits for computing the value.
|
| + ASSERT(2 <= radix && radix <= 36);
|
| + int lim_0 = '0' + (radix < 10 ? radix : 10);
|
| + int lim_a = 'a' + (radix - 10);
|
| + int lim_A = 'A' + (radix - 10);
|
| +
|
| + // NOTE: The code for computing the value may seem a bit complex at
|
| + // first glance. It is structured to use 32-bit multiply-and-add
|
| + // loops as long as possible to avoid loosing precision.
|
| +
|
| + double v = 0.0;
|
| + int j;
|
| + for (j = i; j < len;) {
|
| + // Parse the longest part of the string starting at index j
|
| + // possible while keeping the multiplier, and thus the part
|
| + // itself, within 32 bits.
|
| + uint32_t part = 0, multiplier = 1;
|
| + int k;
|
| + for (k = j; k < len; k++) {
|
| + int c = GetChar(s, k);
|
| + if (c >= '0' && c < lim_0) {
|
| + c = c - '0';
|
| + } else if (c >= 'a' && c < lim_a) {
|
| + c = c - 'a' + 10;
|
| + } else if (c >= 'A' && c < lim_A) {
|
| + c = c - 'A' + 10;
|
| + } else {
|
| + break;
|
| + }
|
| +
|
| + // Update the value of the part as long as the multiplier fits
|
| + // in 32 bits. When we can't guarantee that the next iteration
|
| + // will not overflow the multiplier, we stop parsing the part
|
| + // by leaving the loop.
|
| + static const uint32_t kMaximumMultiplier = 0xffffffffU / 36;
|
| + uint32_t m = multiplier * radix;
|
| + if (m > kMaximumMultiplier) break;
|
| + part = part * radix + c;
|
| + multiplier = m;
|
| + ASSERT(multiplier > part);
|
| + }
|
| +
|
| + // Compute the number of part digits. If no digits were parsed;
|
| + // we're done parsing the entire string.
|
| + int digits = k - j;
|
| + if (digits == 0) break;
|
| +
|
| + // Update the value and skip the part in the string.
|
| + ASSERT(multiplier ==
|
| + pow(static_cast<double>(radix), static_cast<double>(digits)));
|
| + v = v * multiplier + part;
|
| + j = k;
|
| + }
|
| +
|
| + // If the resulting value is larger than 2^53 the value does not fit
|
| + // in the mantissa of the double and there is a loss of precision.
|
| + // When the value is larger than 2^53 the rounding depends on the
|
| + // code generation. If the code generator spills the double value
|
| + // it uses 64 bits and if it does not it uses 80 bits.
|
| + //
|
| + // If there is a potential for overflow we resort to strtod for
|
| + // radix 10 numbers to get higher precision. For numbers in another
|
| + // radix we live with the loss of precision.
|
| + static const double kPreciseConversionLimit = 9007199254740992.0;
|
| + if (radix == 10 && v > kPreciseConversionLimit) {
|
| + const char* cstr = GetCString(s, i);
|
| + const char* end;
|
| + v = gay_strtod(cstr, &end);
|
| + ReleaseCString(s, cstr);
|
| + }
|
| +
|
| + *value = v;
|
| + return j;
|
| +}
|
| +
|
| +
|
| +int StringToInt(String* str, int index, int radix, double* value) {
|
| + return InternalStringToInt(str, index, radix, value);
|
| +}
|
| +
|
| +
|
| +int StringToInt(const char* str, int index, int radix, double* value) {
|
| + return InternalStringToInt(const_cast<char*>(str), index, radix, value);
|
| +}
|
| +
|
| +
|
| static const double JUNK_STRING_VALUE = OS::nan_value();
|
|
|
|
|
| @@ -136,23 +281,18 @@
|
| }
|
|
|
|
|
| -static double SignedZero(bool sign) {
|
| - return sign ? -0.0 : 0.0;
|
| -}
|
| -
|
| -
|
| // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
|
| template <int radix_log_2, class Iterator, class EndMark>
|
| -static double InternalStringToIntDouble(Iterator current,
|
| - EndMark end,
|
| - bool sign,
|
| - bool allow_trailing_junk) {
|
| + static double InternalStringToIntDouble(Iterator current,
|
| + EndMark end,
|
| + bool sign,
|
| + bool allow_trailing_junk) {
|
| ASSERT(current != end);
|
|
|
| // Skip leading 0s.
|
| while (*current == '0') {
|
| ++current;
|
| - if (current == end) return SignedZero(sign);
|
| + if (current == end) return sign ? -0.0 : 0.0;
|
| }
|
|
|
| int64_t number = 0;
|
| @@ -242,183 +382,6 @@
|
| }
|
|
|
|
|
| -template <class Iterator, class EndMark>
|
| -static double InternalStringToInt(Iterator current, EndMark end, int radix) {
|
| - const bool allow_trailing_junk = true;
|
| - const double empty_string_val = JUNK_STRING_VALUE;
|
| -
|
| - if (!AdvanceToNonspace(¤t, end)) return empty_string_val;
|
| -
|
| - bool sign = false;
|
| - bool leading_zero = false;
|
| -
|
| - if (*current == '+') {
|
| - // Ignore leading sign; skip following spaces.
|
| - ++current;
|
| - if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE;
|
| - } else if (*current == '-') {
|
| - ++current;
|
| - if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE;
|
| - sign = true;
|
| - }
|
| -
|
| - if (radix == 0) {
|
| - // Radix detection.
|
| - if (*current == '0') {
|
| - ++current;
|
| - if (current == end) return SignedZero(sign);
|
| - if (*current == 'x' || *current == 'X') {
|
| - radix = 16;
|
| - ++current;
|
| - if (current == end) return JUNK_STRING_VALUE;
|
| - } else {
|
| - radix = 8;
|
| - leading_zero = true;
|
| - }
|
| - } else {
|
| - radix = 10;
|
| - }
|
| - } else if (radix == 16) {
|
| - if (*current == '0') {
|
| - // Allow "0x" prefix.
|
| - ++current;
|
| - if (current == end) return SignedZero(sign);
|
| - if (*current == 'x' || *current == 'X') {
|
| - ++current;
|
| - if (current == end) return JUNK_STRING_VALUE;
|
| - } else {
|
| - leading_zero = true;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (radix < 2 || radix > 36) return JUNK_STRING_VALUE;
|
| -
|
| - // Skip leading zeros.
|
| - while (*current == '0') {
|
| - leading_zero = true;
|
| - ++current;
|
| - if (current == end) return SignedZero(sign);
|
| - }
|
| -
|
| - if (!leading_zero && !isDigit(*current, radix)) {
|
| - return JUNK_STRING_VALUE;
|
| - }
|
| -
|
| - if (IsPowerOf2(radix)) {
|
| - switch (radix) {
|
| - case 2:
|
| - return InternalStringToIntDouble<1>(
|
| - current, end, sign, allow_trailing_junk);
|
| - case 4:
|
| - return InternalStringToIntDouble<2>(
|
| - current, end, sign, allow_trailing_junk);
|
| - case 8:
|
| - return InternalStringToIntDouble<3>(
|
| - current, end, sign, allow_trailing_junk);
|
| -
|
| - case 16:
|
| - return InternalStringToIntDouble<4>(
|
| - current, end, sign, allow_trailing_junk);
|
| -
|
| - case 32:
|
| - return InternalStringToIntDouble<5>(
|
| - current, end, sign, allow_trailing_junk);
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| - }
|
| -
|
| - if (radix == 10) {
|
| - // Parsing with strtod.
|
| - const int kMaxSignificantDigits = 308; // Doubles are less than 1.8e308.
|
| - // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
|
| - // end.
|
| - const int kBufferSize = kMaxSignificantDigits + 2;
|
| - char buffer[kBufferSize];
|
| - int buffer_pos = 0;
|
| - while (*current >= '0' && *current <= '9') {
|
| - if (buffer_pos <= kMaxSignificantDigits) {
|
| - // If the number has more than kMaxSignificantDigits it will be parsed
|
| - // as infinity.
|
| - ASSERT(buffer_pos < kBufferSize);
|
| - buffer[buffer_pos++] = static_cast<char>(*current);
|
| - }
|
| - ++current;
|
| - if (current == end) break;
|
| - }
|
| -
|
| - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
| - return JUNK_STRING_VALUE;
|
| - }
|
| -
|
| - ASSERT(buffer_pos < kBufferSize);
|
| - buffer[buffer_pos++] = '\0';
|
| - return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL);
|
| - }
|
| -
|
| - // TODO(serya): The following legacy code causes accumulating rounding
|
| - // error for number greater than ~2^56. It should be rewritten using long
|
| - // arithmetic.
|
| -
|
| - int lim_0 = '0' + (radix < 10 ? radix : 10);
|
| - int lim_a = 'a' + (radix - 10);
|
| - int lim_A = 'A' + (radix - 10);
|
| -
|
| - // NOTE: The code for computing the value may seem a bit complex at
|
| - // first glance. It is structured to use 32-bit multiply-and-add
|
| - // loops as long as possible to avoid loosing precision.
|
| -
|
| - double v = 0.0;
|
| - bool done = false;
|
| - do {
|
| - // Parse the longest part of the string starting at index j
|
| - // possible while keeping the multiplier, and thus the part
|
| - // itself, within 32 bits.
|
| - unsigned int part = 0, multiplier = 1;
|
| - while (true) {
|
| - int d;
|
| - if (*current >= '0' && *current < lim_0) {
|
| - d = *current - '0';
|
| - } else if (*current >= 'a' && *current < lim_a) {
|
| - d = *current - 'a' + 10;
|
| - } else if (*current >= 'A' && *current < lim_A) {
|
| - d = *current - 'A' + 10;
|
| - } else {
|
| - done = true;
|
| - break;
|
| - }
|
| -
|
| - // Update the value of the part as long as the multiplier fits
|
| - // in 32 bits. When we can't guarantee that the next iteration
|
| - // will not overflow the multiplier, we stop parsing the part
|
| - // by leaving the loop.
|
| - const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
|
| - uint32_t m = multiplier * radix;
|
| - if (m > kMaximumMultiplier) break;
|
| - part = part * radix + d;
|
| - multiplier = m;
|
| - ASSERT(multiplier > part);
|
| -
|
| - ++current;
|
| - if (current == end) {
|
| - done = true;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // Update the value and skip the part in the string.
|
| - v = v * multiplier + part;
|
| - } while (!done);
|
| -
|
| - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
| - return JUNK_STRING_VALUE;
|
| - }
|
| -
|
| - return sign ? -v : v;
|
| -}
|
| -
|
| -
|
| // Converts a string to a double value. Assumes the Iterator supports
|
| // the following operations:
|
| // 1. current == end (other ops are not allowed), current != end.
|
| @@ -454,7 +417,7 @@
|
| bool nonzero_digit_dropped = false;
|
| bool fractional_part = false;
|
|
|
| - bool sign = false;
|
| + double signed_zero = 0.0;
|
|
|
| if (*current == '+') {
|
| // Ignore leading sign; skip following spaces.
|
| @@ -464,7 +427,7 @@
|
| buffer[buffer_pos++] = '-';
|
| ++current;
|
| if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE;
|
| - sign = true;
|
| + signed_zero = -0.0;
|
| }
|
|
|
| static const char kInfinitySymbol[] = "Infinity";
|
| @@ -484,11 +447,11 @@
|
| bool leading_zero = false;
|
| if (*current == '0') {
|
| ++current;
|
| - if (current == end) return SignedZero(sign);
|
| + if (current == end) return signed_zero;
|
|
|
| leading_zero = true;
|
|
|
| - // It could be hexadecimal value.
|
| +// It could be hexadecimal value.
|
| if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
|
| ++current;
|
| if (current == end) return JUNK_STRING_VALUE; // "0x".
|
| @@ -503,7 +466,7 @@
|
| // Ignore leading zeros in the integer part.
|
| while (*current == '0') {
|
| ++current;
|
| - if (current == end) return SignedZero(sign);
|
| + if (current == end) return signed_zero;
|
| }
|
| }
|
|
|
| @@ -545,7 +508,7 @@
|
| // leading zeros (if any).
|
| while (*current == '0') {
|
| ++current;
|
| - if (current == end) return SignedZero(sign);
|
| + if (current == end) return signed_zero;
|
| exponent--; // Move this 0 into the exponent.
|
| }
|
| }
|
| @@ -672,7 +635,7 @@
|
| ASSERT(exponent == 0);
|
| buffer_pos += exp_digits;
|
| } else if (!fractional_part && significant_digits <= kMaxDigitsInInt) {
|
| - if (significant_digits == 0) return SignedZero(sign);
|
| + if (significant_digits == 0) return signed_zero;
|
| ASSERT(buffer_pos > 0);
|
| int num = 0;
|
| int start_pos = (buffer[0] == '-' ? 1 : 0);
|
| @@ -709,25 +672,6 @@
|
| }
|
|
|
|
|
| -double StringToInt(String* str, int radix) {
|
| - StringShape shape(str);
|
| - if (shape.IsSequentialAscii()) {
|
| - const char* begin = SeqAsciiString::cast(str)->GetChars();
|
| - const char* end = begin + str->length();
|
| - return InternalStringToInt(begin, end, radix);
|
| - } else if (shape.IsSequentialTwoByte()) {
|
| - const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
|
| - const uc16* end = begin + str->length();
|
| - return InternalStringToInt(begin, end, radix);
|
| - } else {
|
| - StringInputBuffer buffer(str);
|
| - return InternalStringToInt(StringInputBufferIterator(&buffer),
|
| - StringInputBufferIterator::EndMarker(),
|
| - radix);
|
| - }
|
| -}
|
| -
|
| -
|
| double StringToDouble(const char* str, int flags, double empty_string_val) {
|
| const char* end = str + StrLength(str);
|
|
|
|
|