blob: 730e6477cbee3e0fb781d692ec971d5a32b7ba36 [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_CONVERSIONS_INL_H_
6#define V8_CONVERSIONS_INL_H_
7
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008#include <float.h> // Required for DBL_MAX and on Win32 for finite()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include <limits.h> // Required for INT_MAX etc.
Steve Blocka7e24c12009-10-30 11:49:00 +000010#include <stdarg.h>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include <cmath>
12#include "src/globals.h" // Required for V8_INFINITY
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/unicode-cache-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000014
15// ----------------------------------------------------------------------------
16// Extra POSIX/ANSI functions for Win32/MSVC.
17
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/base/bits.h"
19#include "src/base/platform/platform.h"
20#include "src/conversions.h"
21#include "src/double.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022#include "src/objects-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023#include "src/strtod.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000024
25namespace v8 {
26namespace internal {
27
Ben Murdoch3ef787d2012-04-12 10:51:47 +010028inline double JunkStringValue() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029 return bit_cast<double, uint64_t>(kQuietNaNMask);
30}
31
32
33inline double SignedZero(bool negative) {
34 return negative ? uint64_to_double(Double::kSignMask) : 0.0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000035}
36
37
Steve Block6ded16b2010-05-10 14:33:55 +010038// The fast double-to-unsigned-int conversion routine does not guarantee
39// rounding towards zero, or any reasonable value if the argument is larger
40// than what fits in an unsigned 32-bit integer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010041inline unsigned int FastD2UI(double x) {
Steve Block6ded16b2010-05-10 14:33:55 +010042 // There is no unsigned version of lrint, so there is no fast path
43 // in this function as there is in FastD2I. Using lrint doesn't work
44 // for values of 2^31 and above.
45
46 // Convert "small enough" doubles to uint32_t by fixing the 32
47 // least significant non-fractional bits in the low 32 bits of the
48 // double, and reading them from there.
49 const double k2Pow52 = 4503599627370496.0;
50 bool negative = x < 0;
51 if (negative) {
52 x = -x;
53 }
54 if (x < k2Pow52) {
55 x += k2Pow52;
56 uint32_t result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057#ifndef V8_TARGET_BIG_ENDIAN
Steve Block6ded16b2010-05-10 14:33:55 +010058 Address mantissa_ptr = reinterpret_cast<Address>(&x);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059#else
60 Address mantissa_ptr = reinterpret_cast<Address>(&x) + kIntSize;
61#endif
Steve Block6ded16b2010-05-10 14:33:55 +010062 // Copy least significant 32 bits of mantissa.
63 memcpy(&result, mantissa_ptr, sizeof(result));
64 return negative ? ~result + 1 : result;
65 }
66 // Large number (outside uint32 range), Infinity or NaN.
67 return 0x80000000u; // Return integer indefinite.
Steve Blocka7e24c12009-10-30 11:49:00 +000068}
69
70
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071inline float DoubleToFloat32(double x) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 // TODO(yangguo): This static_cast is implementation-defined behaviour in C++,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 // so we may need to do the conversion manually instead to match the spec.
74 volatile float f = static_cast<float>(x);
75 return f;
76}
77
78
Ben Murdoch3ef787d2012-04-12 10:51:47 +010079inline double DoubleToInteger(double x) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 if (std::isnan(x)) return 0;
81 if (!std::isfinite(x) || x == 0) return x;
82 return (x >= 0) ? std::floor(x) : std::ceil(x);
Steve Blocka7e24c12009-10-30 11:49:00 +000083}
84
85
Steve Blocka7e24c12009-10-30 11:49:00 +000086int32_t DoubleToInt32(double x) {
87 int32_t i = FastD2I(x);
88 if (FastI2D(i) == x) return i;
Ben Murdoch589d6972011-11-30 16:04:58 +000089 Double d(x);
90 int exponent = d.Exponent();
91 if (exponent < 0) {
92 if (exponent <= -Double::kSignificandSize) return 0;
93 return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
94 } else {
95 if (exponent > 31) return 0;
96 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
97 }
Steve Blocka7e24c12009-10-30 11:49:00 +000098}
99
100
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101bool IsSmiDouble(double value) {
102 return !IsMinusZero(value) && value >= Smi::kMinValue &&
103 value <= Smi::kMaxValue && value == FastI2D(FastD2I(value));
104}
105
106
107bool IsInt32Double(double value) {
108 return !IsMinusZero(value) && value >= kMinInt && value <= kMaxInt &&
109 value == FastI2D(FastD2I(value));
110}
111
112
113bool IsUint32Double(double value) {
114 return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
115 value == FastUI2D(FastD2UI(value));
116}
117
118
119int32_t NumberToInt32(Object* number) {
120 if (number->IsSmi()) return Smi::cast(number)->value();
121 return DoubleToInt32(number->Number());
122}
123
124
125uint32_t NumberToUint32(Object* number) {
126 if (number->IsSmi()) return Smi::cast(number)->value();
127 return DoubleToUint32(number->Number());
128}
129
Ben Murdoch097c5b22016-05-18 11:27:45 +0100130int64_t NumberToInt64(Object* number) {
131 if (number->IsSmi()) return Smi::cast(number)->value();
132 return static_cast<int64_t>(number->Number());
133}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134
135bool TryNumberToSize(Isolate* isolate, Object* number, size_t* result) {
136 SealHandleScope shs(isolate);
137 if (number->IsSmi()) {
138 int value = Smi::cast(number)->value();
139 DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
140 std::numeric_limits<size_t>::max());
141 if (value >= 0) {
142 *result = static_cast<size_t>(value);
143 return true;
144 }
145 return false;
146 } else {
147 DCHECK(number->IsHeapNumber());
148 double value = HeapNumber::cast(number)->value();
149 if (value >= 0 && value <= std::numeric_limits<size_t>::max()) {
150 *result = static_cast<size_t>(value);
151 return true;
152 } else {
153 return false;
154 }
155 }
156}
157
158
159size_t NumberToSize(Isolate* isolate, Object* number) {
160 size_t result = 0;
161 bool is_valid = TryNumberToSize(isolate, number, &result);
162 CHECK(is_valid);
163 return result;
164}
165
166
167uint32_t DoubleToUint32(double x) {
168 return static_cast<uint32_t>(DoubleToInt32(x));
169}
170
171
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000172template <class Iterator, class EndMark>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100173bool SubStringEquals(Iterator* current,
174 EndMark end,
175 const char* substring) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 DCHECK(**current == *substring);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000177 for (substring++; *substring != '\0'; substring++) {
178 ++*current;
179 if (*current == end || **current != *substring) return false;
180 }
181 ++*current;
182 return true;
183}
184
185
186// Returns true if a nonspace character has been found and false if the
187// end was been reached before finding a nonspace character.
188template <class Iterator, class EndMark>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100189inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
190 Iterator* current,
191 EndMark end) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000192 while (*current != end) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 if (!unicode_cache->IsWhiteSpaceOrLineTerminator(**current)) return true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000194 ++*current;
195 }
196 return false;
197}
198
199
200// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
201template <int radix_log_2, class Iterator, class EndMark>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100202double InternalStringToIntDouble(UnicodeCache* unicode_cache,
203 Iterator current,
204 EndMark end,
205 bool negative,
206 bool allow_trailing_junk) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 DCHECK(current != end);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000208
209 // Skip leading 0s.
210 while (*current == '0') {
211 ++current;
212 if (current == end) return SignedZero(negative);
213 }
214
215 int64_t number = 0;
216 int exponent = 0;
217 const int radix = (1 << radix_log_2);
218
219 do {
220 int digit;
221 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
222 digit = static_cast<char>(*current) - '0';
223 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
224 digit = static_cast<char>(*current) - 'a' + 10;
225 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
226 digit = static_cast<char>(*current) - 'A' + 10;
227 } else {
228 if (allow_trailing_junk ||
229 !AdvanceToNonspace(unicode_cache, &current, end)) {
230 break;
231 } else {
232 return JunkStringValue();
233 }
234 }
235
236 number = number * radix + digit;
237 int overflow = static_cast<int>(number >> 53);
238 if (overflow != 0) {
239 // Overflow occurred. Need to determine which direction to round the
240 // result.
241 int overflow_bits_count = 1;
242 while (overflow > 1) {
243 overflow_bits_count++;
244 overflow >>= 1;
245 }
246
247 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
248 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
249 number >>= overflow_bits_count;
250 exponent = overflow_bits_count;
251
252 bool zero_tail = true;
253 while (true) {
254 ++current;
255 if (current == end || !isDigit(*current, radix)) break;
256 zero_tail = zero_tail && *current == '0';
257 exponent += radix_log_2;
258 }
259
260 if (!allow_trailing_junk &&
261 AdvanceToNonspace(unicode_cache, &current, end)) {
262 return JunkStringValue();
263 }
264
265 int middle_value = (1 << (overflow_bits_count - 1));
266 if (dropped_bits > middle_value) {
267 number++; // Rounding up.
268 } else if (dropped_bits == middle_value) {
269 // Rounding to even to consistency with decimals: half-way case rounds
270 // up if significant part is odd and down otherwise.
271 if ((number & 1) != 0 || !zero_tail) {
272 number++; // Rounding up.
273 }
274 }
275
276 // Rounding up may cause overflow.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000278 exponent++;
279 number >>= 1;
280 }
281 break;
282 }
283 ++current;
284 } while (current != end);
285
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 DCHECK(number < ((int64_t)1 << 53));
287 DCHECK(static_cast<int64_t>(static_cast<double>(number)) == number);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000288
289 if (exponent == 0) {
290 if (negative) {
291 if (number == 0) return -0.0;
292 number = -number;
293 }
294 return static_cast<double>(number);
295 }
296
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 DCHECK(number != 0);
298 return std::ldexp(static_cast<double>(negative ? -number : number), exponent);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000299}
300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301// ES6 18.2.5 parseInt(string, radix)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000302template <class Iterator, class EndMark>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100303double InternalStringToInt(UnicodeCache* unicode_cache,
304 Iterator current,
305 EndMark end,
306 int radix) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000307 const bool allow_trailing_junk = true;
308 const double empty_string_val = JunkStringValue();
309
310 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
311 return empty_string_val;
312 }
313
314 bool negative = false;
315 bool leading_zero = false;
316
317 if (*current == '+') {
318 // Ignore leading sign; skip following spaces.
319 ++current;
320 if (current == end) {
321 return JunkStringValue();
322 }
323 } else if (*current == '-') {
324 ++current;
325 if (current == end) {
326 return JunkStringValue();
327 }
328 negative = true;
329 }
330
331 if (radix == 0) {
332 // Radix detection.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 radix = 10;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000334 if (*current == '0') {
335 ++current;
336 if (current == end) return SignedZero(negative);
337 if (*current == 'x' || *current == 'X') {
338 radix = 16;
339 ++current;
340 if (current == end) return JunkStringValue();
341 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000342 leading_zero = true;
343 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000344 }
345 } else if (radix == 16) {
346 if (*current == '0') {
347 // Allow "0x" prefix.
348 ++current;
349 if (current == end) return SignedZero(negative);
350 if (*current == 'x' || *current == 'X') {
351 ++current;
352 if (current == end) return JunkStringValue();
353 } else {
354 leading_zero = true;
355 }
356 }
357 }
358
359 if (radix < 2 || radix > 36) return JunkStringValue();
360
361 // Skip leading zeros.
362 while (*current == '0') {
363 leading_zero = true;
364 ++current;
365 if (current == end) return SignedZero(negative);
366 }
367
368 if (!leading_zero && !isDigit(*current, radix)) {
369 return JunkStringValue();
370 }
371
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 if (base::bits::IsPowerOfTwo32(radix)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000373 switch (radix) {
374 case 2:
375 return InternalStringToIntDouble<1>(
376 unicode_cache, current, end, negative, allow_trailing_junk);
377 case 4:
378 return InternalStringToIntDouble<2>(
379 unicode_cache, current, end, negative, allow_trailing_junk);
380 case 8:
381 return InternalStringToIntDouble<3>(
382 unicode_cache, current, end, negative, allow_trailing_junk);
383
384 case 16:
385 return InternalStringToIntDouble<4>(
386 unicode_cache, current, end, negative, allow_trailing_junk);
387
388 case 32:
389 return InternalStringToIntDouble<5>(
390 unicode_cache, current, end, negative, allow_trailing_junk);
391 default:
392 UNREACHABLE();
393 }
394 }
395
396 if (radix == 10) {
397 // Parsing with strtod.
398 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
399 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
400 // end.
401 const int kBufferSize = kMaxSignificantDigits + 2;
402 char buffer[kBufferSize];
403 int buffer_pos = 0;
404 while (*current >= '0' && *current <= '9') {
405 if (buffer_pos <= kMaxSignificantDigits) {
406 // If the number has more than kMaxSignificantDigits it will be parsed
407 // as infinity.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 DCHECK(buffer_pos < kBufferSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000409 buffer[buffer_pos++] = static_cast<char>(*current);
410 }
411 ++current;
412 if (current == end) break;
413 }
414
415 if (!allow_trailing_junk &&
416 AdvanceToNonspace(unicode_cache, &current, end)) {
417 return JunkStringValue();
418 }
419
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 SLOW_DCHECK(buffer_pos < kBufferSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000421 buffer[buffer_pos] = '\0';
422 Vector<const char> buffer_vector(buffer, buffer_pos);
423 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
424 }
425
426 // The following code causes accumulating rounding error for numbers greater
427 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
428 // 16, or 32, then mathInt may be an implementation-dependent approximation to
429 // the mathematical integer value" (15.1.2.2).
430
431 int lim_0 = '0' + (radix < 10 ? radix : 10);
432 int lim_a = 'a' + (radix - 10);
433 int lim_A = 'A' + (radix - 10);
434
435 // NOTE: The code for computing the value may seem a bit complex at
436 // first glance. It is structured to use 32-bit multiply-and-add
437 // loops as long as possible to avoid loosing precision.
438
439 double v = 0.0;
440 bool done = false;
441 do {
442 // Parse the longest part of the string starting at index j
443 // possible while keeping the multiplier, and thus the part
444 // itself, within 32 bits.
445 unsigned int part = 0, multiplier = 1;
446 while (true) {
447 int d;
448 if (*current >= '0' && *current < lim_0) {
449 d = *current - '0';
450 } else if (*current >= 'a' && *current < lim_a) {
451 d = *current - 'a' + 10;
452 } else if (*current >= 'A' && *current < lim_A) {
453 d = *current - 'A' + 10;
454 } else {
455 done = true;
456 break;
457 }
458
459 // Update the value of the part as long as the multiplier fits
460 // in 32 bits. When we can't guarantee that the next iteration
461 // will not overflow the multiplier, we stop parsing the part
462 // by leaving the loop.
463 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
464 uint32_t m = multiplier * radix;
465 if (m > kMaximumMultiplier) break;
466 part = part * radix + d;
467 multiplier = m;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000468 DCHECK(multiplier > part);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000469
470 ++current;
471 if (current == end) {
472 done = true;
473 break;
474 }
475 }
476
477 // Update the value and skip the part in the string.
478 v = v * multiplier + part;
479 } while (!done);
480
481 if (!allow_trailing_junk &&
482 AdvanceToNonspace(unicode_cache, &current, end)) {
483 return JunkStringValue();
484 }
485
486 return negative ? -v : v;
487}
488
489
490// Converts a string to a double value. Assumes the Iterator supports
491// the following operations:
492// 1. current == end (other ops are not allowed), current != end.
493// 2. *current - gets the current character in the sequence.
494// 3. ++current (advances the position).
495template <class Iterator, class EndMark>
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100496double InternalStringToDouble(UnicodeCache* unicode_cache,
497 Iterator current,
498 EndMark end,
499 int flags,
500 double empty_string_val) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000501 // To make sure that iterator dereferencing is valid the following
502 // convention is used:
503 // 1. Each '++current' statement is followed by check for equality to 'end'.
504 // 2. If AdvanceToNonspace returned false then current == end.
505 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
506 // 'parsing_done'.
507 // 4. 'current' is not dereferenced after the 'parsing_done' label.
508 // 5. Code before 'parsing_done' may rely on 'current != end'.
509 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
510 return empty_string_val;
511 }
512
513 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
514
515 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
516 const int kBufferSize = kMaxSignificantDigits + 10;
517 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
518 int buffer_pos = 0;
519
520 // Exponent will be adjusted if insignificant digits of the integer part
521 // or insignificant leading zeros of the fractional part are dropped.
522 int exponent = 0;
523 int significant_digits = 0;
524 int insignificant_digits = 0;
525 bool nonzero_digit_dropped = false;
526
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 enum Sign {
528 NONE,
529 NEGATIVE,
530 POSITIVE
531 };
532
533 Sign sign = NONE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000534
535 if (*current == '+') {
536 // Ignore leading sign.
537 ++current;
538 if (current == end) return JunkStringValue();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 sign = POSITIVE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000540 } else if (*current == '-') {
541 ++current;
542 if (current == end) return JunkStringValue();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 sign = NEGATIVE;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000544 }
545
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 static const char kInfinityString[] = "Infinity";
547 if (*current == kInfinityString[0]) {
548 if (!SubStringEquals(&current, end, kInfinityString)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000549 return JunkStringValue();
550 }
551
552 if (!allow_trailing_junk &&
553 AdvanceToNonspace(unicode_cache, &current, end)) {
554 return JunkStringValue();
555 }
556
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557 DCHECK(buffer_pos == 0);
558 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000559 }
560
561 bool leading_zero = false;
562 if (*current == '0') {
563 ++current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 if (current == end) return SignedZero(sign == NEGATIVE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000565
566 leading_zero = true;
567
568 // It could be hexadecimal value.
569 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
570 ++current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 if (current == end || !isDigit(*current, 16) || sign != NONE) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000572 return JunkStringValue(); // "0x".
573 }
574
575 return InternalStringToIntDouble<4>(unicode_cache,
576 current,
577 end,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 false,
579 allow_trailing_junk);
580
581 // It could be an explicit octal value.
582 } else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
583 ++current;
584 if (current == end || !isDigit(*current, 8) || sign != NONE) {
585 return JunkStringValue(); // "0o".
586 }
587
588 return InternalStringToIntDouble<3>(unicode_cache,
589 current,
590 end,
591 false,
592 allow_trailing_junk);
593
594 // It could be a binary value.
595 } else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
596 ++current;
597 if (current == end || !isBinaryDigit(*current) || sign != NONE) {
598 return JunkStringValue(); // "0b".
599 }
600
601 return InternalStringToIntDouble<1>(unicode_cache,
602 current,
603 end,
604 false,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000605 allow_trailing_junk);
606 }
607
608 // Ignore leading zeros in the integer part.
609 while (*current == '0') {
610 ++current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 if (current == end) return SignedZero(sign == NEGATIVE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000612 }
613 }
614
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000615 bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000616
617 // Copy significant digits of the integer part (if any) to the buffer.
618 while (*current >= '0' && *current <= '9') {
619 if (significant_digits < kMaxSignificantDigits) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 DCHECK(buffer_pos < kBufferSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000621 buffer[buffer_pos++] = static_cast<char>(*current);
622 significant_digits++;
623 // Will later check if it's an octal in the buffer.
624 } else {
625 insignificant_digits++; // Move the digit into the exponential part.
626 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
627 }
628 octal = octal && *current < '8';
629 ++current;
630 if (current == end) goto parsing_done;
631 }
632
633 if (significant_digits == 0) {
634 octal = false;
635 }
636
637 if (*current == '.') {
638 if (octal && !allow_trailing_junk) return JunkStringValue();
639 if (octal) goto parsing_done;
640
641 ++current;
642 if (current == end) {
643 if (significant_digits == 0 && !leading_zero) {
644 return JunkStringValue();
645 } else {
646 goto parsing_done;
647 }
648 }
649
650 if (significant_digits == 0) {
651 // octal = false;
652 // Integer part consists of 0 or is absent. Significant digits start after
653 // leading zeros (if any).
654 while (*current == '0') {
655 ++current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 if (current == end) return SignedZero(sign == NEGATIVE);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000657 exponent--; // Move this 0 into the exponent.
658 }
659 }
660
661 // There is a fractional part. We don't emit a '.', but adjust the exponent
662 // instead.
663 while (*current >= '0' && *current <= '9') {
664 if (significant_digits < kMaxSignificantDigits) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 DCHECK(buffer_pos < kBufferSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000666 buffer[buffer_pos++] = static_cast<char>(*current);
667 significant_digits++;
668 exponent--;
669 } else {
670 // Ignore insignificant digits in the fractional part.
671 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
672 }
673 ++current;
674 if (current == end) goto parsing_done;
675 }
676 }
677
678 if (!leading_zero && exponent == 0 && significant_digits == 0) {
679 // If leading_zeros is true then the string contains zeros.
680 // If exponent < 0 then string was [+-]\.0*...
681 // If significant_digits != 0 the string is not equal to 0.
682 // Otherwise there are no digits in the string.
683 return JunkStringValue();
684 }
685
686 // Parse exponential part.
687 if (*current == 'e' || *current == 'E') {
688 if (octal) return JunkStringValue();
689 ++current;
690 if (current == end) {
691 if (allow_trailing_junk) {
692 goto parsing_done;
693 } else {
694 return JunkStringValue();
695 }
696 }
697 char sign = '+';
698 if (*current == '+' || *current == '-') {
699 sign = static_cast<char>(*current);
700 ++current;
701 if (current == end) {
702 if (allow_trailing_junk) {
703 goto parsing_done;
704 } else {
705 return JunkStringValue();
706 }
707 }
708 }
709
710 if (current == end || *current < '0' || *current > '9') {
711 if (allow_trailing_junk) {
712 goto parsing_done;
713 } else {
714 return JunkStringValue();
715 }
716 }
717
718 const int max_exponent = INT_MAX / 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000719 DCHECK(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000720 int num = 0;
721 do {
722 // Check overflow.
723 int digit = *current - '0';
724 if (num >= max_exponent / 10
725 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
726 num = max_exponent;
727 } else {
728 num = num * 10 + digit;
729 }
730 ++current;
731 } while (current != end && *current >= '0' && *current <= '9');
732
733 exponent += (sign == '-' ? -num : num);
734 }
735
736 if (!allow_trailing_junk &&
737 AdvanceToNonspace(unicode_cache, &current, end)) {
738 return JunkStringValue();
739 }
740
741 parsing_done:
742 exponent += insignificant_digits;
743
744 if (octal) {
745 return InternalStringToIntDouble<3>(unicode_cache,
746 buffer,
747 buffer + buffer_pos,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 sign == NEGATIVE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000749 allow_trailing_junk);
750 }
751
752 if (nonzero_digit_dropped) {
753 buffer[buffer_pos++] = '1';
754 exponent--;
755 }
756
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757 SLOW_DCHECK(buffer_pos < kBufferSize);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000758 buffer[buffer_pos] = '\0';
759
760 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 return (sign == NEGATIVE) ? -converted : converted;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000762}
763
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000764} // namespace internal
765} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +0000766
767#endif // V8_CONVERSIONS_INL_H_