5 #ifndef V8_CONVERSIONS_INL_H_
6 #define V8_CONVERSIONS_INL_H_
48 const double k2Pow52 = 4503599627370496.0;
56 #ifndef V8_TARGET_BIG_ENDIAN
62 memcpy(&result, mantissa_ptr,
sizeof(result));
63 return negative ? ~result + 1 : result;
73 volatile float f =
static_cast<float>(x);
79 if (std::isnan(x))
return 0;
80 if (!std::isfinite(x) || x == 0)
return x;
81 return (x >= 0) ? std::floor(x) : std::ceil(x);
94 if (exponent > 31)
return 0;
100 template <
class Iterator,
class EndMark>
103 const char* substring) {
104 DCHECK(**current == *substring);
105 for (substring++; *substring !=
'\0'; substring++) {
107 if (*current == end || **current != *substring)
return false;
116 template <
class Iterator,
class EndMark>
120 while (*current != end) {
129 template <
int radix_log_2,
class Iterator,
class EndMark>
134 bool allow_trailing_junk) {
138 while (*current ==
'0') {
145 const int radix = (1 << radix_log_2);
149 if (*current >=
'0' && *current <=
'9' && *current <
'0' + radix) {
150 digit =
static_cast<char>(*current) -
'0';
151 }
else if (radix > 10 && *current >=
'a' && *current <
'a' + radix - 10) {
152 digit =
static_cast<char>(*current) -
'a' + 10;
153 }
else if (radix > 10 && *current >=
'A' && *current <
'A' + radix - 10) {
154 digit =
static_cast<char>(*current) -
'A' + 10;
156 if (allow_trailing_junk ||
164 number = number * radix + digit;
165 int overflow =
static_cast<int>(number >> 53);
169 int overflow_bits_count = 1;
171 overflow_bits_count++;
175 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
176 int dropped_bits =
static_cast<int>(number) & dropped_bits_mask;
177 number >>= overflow_bits_count;
178 exponent = overflow_bits_count;
180 bool zero_tail =
true;
183 if (current == end || !
isDigit(*current, radix))
break;
184 zero_tail = zero_tail && *current ==
'0';
185 exponent += radix_log_2;
188 if (!allow_trailing_junk &&
193 int middle_value = (1 << (overflow_bits_count - 1));
194 if (dropped_bits > middle_value) {
196 }
else if (dropped_bits == middle_value) {
199 if ((number & 1) != 0 || !zero_tail) {
205 if ((number & (
static_cast<int64_t
>(1) << 53)) != 0) {
212 }
while (current != end);
214 DCHECK(number < ((int64_t)1 << 53));
215 DCHECK(
static_cast<int64_t
>(
static_cast<double>(number)) == number);
219 if (number == 0)
return -0.0;
222 return static_cast<double>(number);
226 return std::ldexp(
static_cast<double>(
negative ? -number : number), exponent);
230 template <
class Iterator,
class EndMark>
235 const bool allow_trailing_junk =
true;
239 return empty_string_val;
243 bool leading_zero =
false;
245 if (*current ==
'+') {
248 if (current == end) {
251 }
else if (*current ==
'-') {
253 if (current == end) {
262 if (*current ==
'0') {
265 if (*current ==
'x' || *current ==
'X') {
273 }
else if (radix == 16) {
274 if (*current ==
'0') {
278 if (*current ==
'x' || *current ==
'X') {
290 while (*current ==
'0') {
296 if (!leading_zero && !
isDigit(*current, radix)) {
303 return InternalStringToIntDouble<1>(
304 unicode_cache, current, end,
negative, allow_trailing_junk);
306 return InternalStringToIntDouble<2>(
307 unicode_cache, current, end,
negative, allow_trailing_junk);
309 return InternalStringToIntDouble<3>(
310 unicode_cache, current, end,
negative, allow_trailing_junk);
313 return InternalStringToIntDouble<4>(
314 unicode_cache, current, end,
negative, allow_trailing_junk);
317 return InternalStringToIntDouble<5>(
318 unicode_cache, current, end,
negative, allow_trailing_junk);
332 while (*current >=
'0' && *current <=
'9') {
337 buffer[buffer_pos++] =
static_cast<char>(*current);
340 if (current == end)
break;
343 if (!allow_trailing_junk &&
349 buffer[buffer_pos] =
'\0';
359 int lim_0 =
'0' + (radix < 10 ? radix : 10);
360 int lim_a =
'a' + (radix - 10);
361 int lim_A =
'A' + (radix - 10);
373 unsigned int part = 0, multiplier = 1;
376 if (*current >=
'0' && *current < lim_0) {
378 }
else if (*current >=
'a' && *current < lim_a) {
379 d = *current -
'a' + 10;
380 }
else if (*current >=
'A' && *current < lim_A) {
381 d = *current -
'A' + 10;
391 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
393 if (m > kMaximumMultiplier)
break;
394 part = part * radix + d;
396 DCHECK(multiplier > part);
399 if (current == end) {
406 v = v * multiplier + part;
409 if (!allow_trailing_junk &&
423 template <
class Iterator,
class EndMark>
428 double empty_string_val) {
438 return empty_string_val;
451 int significant_digits = 0;
452 int insignificant_digits = 0;
453 bool nonzero_digit_dropped =
false;
463 if (*current ==
'+') {
468 }
else if (*current ==
'-') {
474 static const char kInfinityString[] =
"Infinity";
475 if (*current == kInfinityString[0]) {
480 if (!allow_trailing_junk &&
489 bool leading_zero =
false;
490 if (*current ==
'0') {
497 if ((
flags &
ALLOW_HEX) && (*current ==
'x' || *current ==
'X')) {
503 return InternalStringToIntDouble<4>(unicode_cache,
507 allow_trailing_junk);
516 return InternalStringToIntDouble<3>(unicode_cache,
520 allow_trailing_junk);
529 return InternalStringToIntDouble<1>(unicode_cache,
533 allow_trailing_junk);
537 while (*current ==
'0') {
546 while (*current >=
'0' && *current <=
'9') {
549 buffer[buffer_pos++] =
static_cast<char>(*current);
550 significant_digits++;
553 insignificant_digits++;
554 nonzero_digit_dropped = nonzero_digit_dropped || *current !=
'0';
556 octal = octal && *current <
'8';
558 if (current == end)
goto parsing_done;
561 if (significant_digits == 0) {
565 if (*current ==
'.') {
567 if (octal)
goto parsing_done;
570 if (current == end) {
571 if (significant_digits == 0 && !leading_zero) {
578 if (significant_digits == 0) {
582 while (*current ==
'0') {
591 while (*current >=
'0' && *current <=
'9') {
594 buffer[buffer_pos++] =
static_cast<char>(*current);
595 significant_digits++;
599 nonzero_digit_dropped = nonzero_digit_dropped || *current !=
'0';
602 if (current == end)
goto parsing_done;
606 if (!leading_zero && exponent == 0 && significant_digits == 0) {
615 if (*current ==
'e' || *current ==
'E') {
618 if (current == end) {
619 if (allow_trailing_junk) {
626 if (*current ==
'+' || *current ==
'-') {
627 sign =
static_cast<char>(*current);
629 if (current == end) {
630 if (allow_trailing_junk) {
638 if (current == end || *current < '0' || *current >
'9') {
639 if (allow_trailing_junk) {
646 const int max_exponent = INT_MAX / 2;
647 DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
651 int digit = *current -
'0';
652 if (num >= max_exponent / 10
653 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
656 num = num * 10 + digit;
659 }
while (current != end && *current >=
'0' && *current <=
'9');
661 exponent += (
sign ==
'-' ? -num : num);
664 if (!allow_trailing_junk &&
670 exponent += insignificant_digits;
673 return InternalStringToIntDouble<3>(unicode_cache,
677 allow_trailing_junk);
680 if (nonzero_digit_dropped) {
681 buffer[buffer_pos++] =
'1';
686 buffer[buffer_pos] =
'\0';
689 return (
sign == NEGATIVE) ? -converted : converted;
#define SLOW_DCHECK(condition)
static const uint64_t kSignMask
static const int kSignificandSize
uint64_t Significand() const
bool IsWhiteSpaceOrLineTerminator(unibrow::uchar c)
#define DCHECK(condition)
static const size_t kBufferSize
bool IsPowerOfTwo32(uint32_t value)
bool isDigit(int x, int radix)
double InternalStringToIntDouble(UnicodeCache *unicode_cache, Iterator current, EndMark end, bool negative, bool allow_trailing_junk)
double InternalStringToDouble(UnicodeCache *unicode_cache, Iterator current, EndMark end, int flags, double empty_string_val)
unsigned int FastD2UI(double x)
double Strtod(Vector< const char > buffer, int exponent)
double DoubleToInteger(double x)
bool AdvanceToNonspace(UnicodeCache *unicode_cache, Iterator *current, EndMark end)
double SignedZero(bool negative)
const int kMaxSignificantDigits
int32_t DoubleToInt32(double x)
double InternalStringToInt(UnicodeCache *unicode_cache, Iterator current, EndMark end, int radix)
const uint64_t kQuietNaNMask
float DoubleToFloat32(double x)
double uint64_to_double(uint64_t d64)
bool isBinaryDigit(int x)
bool SubStringEquals(Iterator *current, EndMark end, const char *substring)
Debugger support for the V8 JavaScript engine.