blob: b828638568aa8e687773c52f51472ac20b7f56e5 [file] [log] [blame]
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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#ifndef V8_CONVERSIONS_INL_H_
29#define V8_CONVERSIONS_INL_H_
30
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000031#include <limits.h> // Required for INT_MAX etc.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include <math.h>
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000033#include <float.h> // Required for DBL_MAX and on Win32 for finite()
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000034#include <stdarg.h>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
36// ----------------------------------------------------------------------------
37// Extra POSIX/ANSI functions for Win32/MSVC.
38
39#include "conversions.h"
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000040#include "strtod.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041#include "platform.h"
42
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000046static inline double JunkStringValue() {
47 return std::numeric_limits<double>::quiet_NaN();
48}
49
50
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000051// The fast double-to-unsigned-int conversion routine does not guarantee
fschneider@chromium.org086aac62010-03-17 13:18:24 +000052// rounding towards zero, or any reasonable value if the argument is larger
53// than what fits in an unsigned 32-bit integer.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000054static inline unsigned int FastD2UI(double x) {
55 // There is no unsigned version of lrint, so there is no fast path
56 // in this function as there is in FastD2I. Using lrint doesn't work
57 // for values of 2^31 and above.
58
59 // Convert "small enough" doubles to uint32_t by fixing the 32
60 // least significant non-fractional bits in the low 32 bits of the
61 // double, and reading them from there.
62 const double k2Pow52 = 4503599627370496.0;
63 bool negative = x < 0;
64 if (negative) {
65 x = -x;
66 }
67 if (x < k2Pow52) {
68 x += k2Pow52;
69 uint32_t result;
fschneider@chromium.org086aac62010-03-17 13:18:24 +000070 Address mantissa_ptr = reinterpret_cast<Address>(&x);
fschneider@chromium.org086aac62010-03-17 13:18:24 +000071 // Copy least significant 32 bits of mantissa.
72 memcpy(&result, mantissa_ptr, sizeof(result));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000073 return negative ? ~result + 1 : result;
74 }
75 // Large number (outside uint32 range), Infinity or NaN.
76 return 0x80000000u; // Return integer indefinite.
77}
78
79
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080static inline double DoubleToInteger(double x) {
81 if (isnan(x)) return 0;
82 if (!isfinite(x) || x == 0) return x;
83 return (x >= 0) ? floor(x) : ceil(x);
84}
85
86
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000087int32_t DoubleToInt32(double x) {
88 int32_t i = FastD2I(x);
89 if (FastI2D(i) == x) return i;
90 static const double two32 = 4294967296.0;
91 static const double two31 = 2147483648.0;
92 if (!isfinite(x) || x == 0) return 0;
ager@chromium.org3811b432009-10-28 14:53:37 +000093 if (x < 0 || x >= two32) x = modulo(x, two32);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094 x = (x >= 0) ? floor(x) : ceil(x) + two32;
95 return (int32_t) ((x >= two31) ? x - two32 : x);
96}
97
98
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000099template <class Iterator, class EndMark>
100static bool SubStringEquals(Iterator* current,
101 EndMark end,
102 const char* substring) {
103 ASSERT(**current == *substring);
104 for (substring++; *substring != '\0'; substring++) {
105 ++*current;
106 if (*current == end || **current != *substring) return false;
107 }
108 ++*current;
109 return true;
110}
111
112
113// Returns true if a nonspace character has been found and false if the
114// end was been reached before finding a nonspace character.
115template <class Iterator, class EndMark>
116static inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
117 Iterator* current,
118 EndMark end) {
119 while (*current != end) {
120 if (!unicode_cache->IsWhiteSpace(**current)) return true;
121 ++*current;
122 }
123 return false;
124}
125
126
127// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
128template <int radix_log_2, class Iterator, class EndMark>
129static double InternalStringToIntDouble(UnicodeCache* unicode_cache,
130 Iterator current,
131 EndMark end,
132 bool negative,
133 bool allow_trailing_junk) {
134 ASSERT(current != end);
135
136 // Skip leading 0s.
137 while (*current == '0') {
138 ++current;
139 if (current == end) return SignedZero(negative);
140 }
141
142 int64_t number = 0;
143 int exponent = 0;
144 const int radix = (1 << radix_log_2);
145
146 do {
147 int digit;
148 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
149 digit = static_cast<char>(*current) - '0';
150 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
151 digit = static_cast<char>(*current) - 'a' + 10;
152 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
153 digit = static_cast<char>(*current) - 'A' + 10;
154 } else {
155 if (allow_trailing_junk ||
156 !AdvanceToNonspace(unicode_cache, &current, end)) {
157 break;
158 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000159 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000160 }
161 }
162
163 number = number * radix + digit;
164 int overflow = static_cast<int>(number >> 53);
165 if (overflow != 0) {
166 // Overflow occurred. Need to determine which direction to round the
167 // result.
168 int overflow_bits_count = 1;
169 while (overflow > 1) {
170 overflow_bits_count++;
171 overflow >>= 1;
172 }
173
174 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
175 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
176 number >>= overflow_bits_count;
177 exponent = overflow_bits_count;
178
179 bool zero_tail = true;
180 while (true) {
181 ++current;
182 if (current == end || !isDigit(*current, radix)) break;
183 zero_tail = zero_tail && *current == '0';
184 exponent += radix_log_2;
185 }
186
187 if (!allow_trailing_junk &&
188 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000189 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000190 }
191
192 int middle_value = (1 << (overflow_bits_count - 1));
193 if (dropped_bits > middle_value) {
194 number++; // Rounding up.
195 } else if (dropped_bits == middle_value) {
196 // Rounding to even to consistency with decimals: half-way case rounds
197 // up if significant part is odd and down otherwise.
198 if ((number & 1) != 0 || !zero_tail) {
199 number++; // Rounding up.
200 }
201 }
202
203 // Rounding up may cause overflow.
204 if ((number & ((int64_t)1 << 53)) != 0) {
205 exponent++;
206 number >>= 1;
207 }
208 break;
209 }
210 ++current;
211 } while (current != end);
212
213 ASSERT(number < ((int64_t)1 << 53));
214 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
215
216 if (exponent == 0) {
217 if (negative) {
218 if (number == 0) return -0.0;
219 number = -number;
220 }
221 return static_cast<double>(number);
222 }
223
224 ASSERT(number != 0);
225 // The double could be constructed faster from number (mantissa), exponent
226 // and sign. Assuming it's a rare case more simple code is used.
227 return static_cast<double>(negative ? -number : number) * pow(2.0, exponent);
228}
229
230
231template <class Iterator, class EndMark>
232static double InternalStringToInt(UnicodeCache* unicode_cache,
233 Iterator current,
234 EndMark end,
235 int radix) {
236 const bool allow_trailing_junk = true;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000237 const double empty_string_val = JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000238
239 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
240 return empty_string_val;
241 }
242
243 bool negative = false;
244 bool leading_zero = false;
245
246 if (*current == '+') {
247 // Ignore leading sign; skip following spaces.
248 ++current;
249 if (current == end) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000250 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000251 }
252 } else if (*current == '-') {
253 ++current;
254 if (current == end) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000255 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000256 }
257 negative = true;
258 }
259
260 if (radix == 0) {
261 // Radix detection.
262 if (*current == '0') {
263 ++current;
264 if (current == end) return SignedZero(negative);
265 if (*current == 'x' || *current == 'X') {
266 radix = 16;
267 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000268 if (current == end) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000269 } else {
270 radix = 8;
271 leading_zero = true;
272 }
273 } else {
274 radix = 10;
275 }
276 } else if (radix == 16) {
277 if (*current == '0') {
278 // Allow "0x" prefix.
279 ++current;
280 if (current == end) return SignedZero(negative);
281 if (*current == 'x' || *current == 'X') {
282 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000283 if (current == end) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000284 } else {
285 leading_zero = true;
286 }
287 }
288 }
289
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000290 if (radix < 2 || radix > 36) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000291
292 // Skip leading zeros.
293 while (*current == '0') {
294 leading_zero = true;
295 ++current;
296 if (current == end) return SignedZero(negative);
297 }
298
299 if (!leading_zero && !isDigit(*current, radix)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000300 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000301 }
302
303 if (IsPowerOf2(radix)) {
304 switch (radix) {
305 case 2:
306 return InternalStringToIntDouble<1>(
307 unicode_cache, current, end, negative, allow_trailing_junk);
308 case 4:
309 return InternalStringToIntDouble<2>(
310 unicode_cache, current, end, negative, allow_trailing_junk);
311 case 8:
312 return InternalStringToIntDouble<3>(
313 unicode_cache, current, end, negative, allow_trailing_junk);
314
315 case 16:
316 return InternalStringToIntDouble<4>(
317 unicode_cache, current, end, negative, allow_trailing_junk);
318
319 case 32:
320 return InternalStringToIntDouble<5>(
321 unicode_cache, current, end, negative, allow_trailing_junk);
322 default:
323 UNREACHABLE();
324 }
325 }
326
327 if (radix == 10) {
328 // Parsing with strtod.
329 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
330 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
331 // end.
332 const int kBufferSize = kMaxSignificantDigits + 2;
333 char buffer[kBufferSize];
334 int buffer_pos = 0;
335 while (*current >= '0' && *current <= '9') {
336 if (buffer_pos <= kMaxSignificantDigits) {
337 // If the number has more than kMaxSignificantDigits it will be parsed
338 // as infinity.
339 ASSERT(buffer_pos < kBufferSize);
340 buffer[buffer_pos++] = static_cast<char>(*current);
341 }
342 ++current;
343 if (current == end) break;
344 }
345
346 if (!allow_trailing_junk &&
347 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000348 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000349 }
350
351 ASSERT(buffer_pos < kBufferSize);
352 buffer[buffer_pos] = '\0';
353 Vector<const char> buffer_vector(buffer, buffer_pos);
354 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
355 }
356
357 // The following code causes accumulating rounding error for numbers greater
358 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
359 // 16, or 32, then mathInt may be an implementation-dependent approximation to
360 // the mathematical integer value" (15.1.2.2).
361
362 int lim_0 = '0' + (radix < 10 ? radix : 10);
363 int lim_a = 'a' + (radix - 10);
364 int lim_A = 'A' + (radix - 10);
365
366 // NOTE: The code for computing the value may seem a bit complex at
367 // first glance. It is structured to use 32-bit multiply-and-add
368 // loops as long as possible to avoid loosing precision.
369
370 double v = 0.0;
371 bool done = false;
372 do {
373 // Parse the longest part of the string starting at index j
374 // possible while keeping the multiplier, and thus the part
375 // itself, within 32 bits.
376 unsigned int part = 0, multiplier = 1;
377 while (true) {
378 int d;
379 if (*current >= '0' && *current < lim_0) {
380 d = *current - '0';
381 } else if (*current >= 'a' && *current < lim_a) {
382 d = *current - 'a' + 10;
383 } else if (*current >= 'A' && *current < lim_A) {
384 d = *current - 'A' + 10;
385 } else {
386 done = true;
387 break;
388 }
389
390 // Update the value of the part as long as the multiplier fits
391 // in 32 bits. When we can't guarantee that the next iteration
392 // will not overflow the multiplier, we stop parsing the part
393 // by leaving the loop.
394 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
395 uint32_t m = multiplier * radix;
396 if (m > kMaximumMultiplier) break;
397 part = part * radix + d;
398 multiplier = m;
399 ASSERT(multiplier > part);
400
401 ++current;
402 if (current == end) {
403 done = true;
404 break;
405 }
406 }
407
408 // Update the value and skip the part in the string.
409 v = v * multiplier + part;
410 } while (!done);
411
412 if (!allow_trailing_junk &&
413 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000414 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000415 }
416
417 return negative ? -v : v;
418}
419
420
421// Converts a string to a double value. Assumes the Iterator supports
422// the following operations:
423// 1. current == end (other ops are not allowed), current != end.
424// 2. *current - gets the current character in the sequence.
425// 3. ++current (advances the position).
426template <class Iterator, class EndMark>
427static double InternalStringToDouble(UnicodeCache* unicode_cache,
428 Iterator current,
429 EndMark end,
430 int flags,
431 double empty_string_val) {
432 // To make sure that iterator dereferencing is valid the following
433 // convention is used:
434 // 1. Each '++current' statement is followed by check for equality to 'end'.
435 // 2. If AdvanceToNonspace returned false then current == end.
436 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
437 // 'parsing_done'.
438 // 4. 'current' is not dereferenced after the 'parsing_done' label.
439 // 5. Code before 'parsing_done' may rely on 'current != end'.
440 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
441 return empty_string_val;
442 }
443
444 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
445
446 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
447 const int kBufferSize = kMaxSignificantDigits + 10;
448 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
449 int buffer_pos = 0;
450
451 // Exponent will be adjusted if insignificant digits of the integer part
452 // or insignificant leading zeros of the fractional part are dropped.
453 int exponent = 0;
454 int significant_digits = 0;
455 int insignificant_digits = 0;
456 bool nonzero_digit_dropped = false;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000457
458 bool negative = false;
459
460 if (*current == '+') {
461 // Ignore leading sign.
462 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000463 if (current == end) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000464 } else if (*current == '-') {
465 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000466 if (current == end) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000467 negative = true;
468 }
469
470 static const char kInfinitySymbol[] = "Infinity";
471 if (*current == kInfinitySymbol[0]) {
472 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000473 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000474 }
475
476 if (!allow_trailing_junk &&
477 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000478 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000479 }
480
481 ASSERT(buffer_pos == 0);
482 return negative ? -V8_INFINITY : V8_INFINITY;
483 }
484
485 bool leading_zero = false;
486 if (*current == '0') {
487 ++current;
488 if (current == end) return SignedZero(negative);
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)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000496 return JunkStringValue(); // "0x".
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000497 }
498
499 return InternalStringToIntDouble<4>(unicode_cache,
500 current,
501 end,
502 negative,
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(negative);
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 == '.') {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000536 if (octal && !allow_trailing_junk) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000537 if (octal) goto parsing_done;
538
539 ++current;
540 if (current == end) {
541 if (significant_digits == 0 && !leading_zero) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000542 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000543 } else {
544 goto parsing_done;
545 }
546 }
547
548 if (significant_digits == 0) {
549 // octal = false;
550 // Integer part consists of 0 or is absent. Significant digits start after
551 // leading zeros (if any).
552 while (*current == '0') {
553 ++current;
554 if (current == end) return SignedZero(negative);
555 exponent--; // Move this 0 into the exponent.
556 }
557 }
558
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000559 // There is a fractional part. We don't emit a '.', but adjust the exponent
560 // instead.
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000561 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 exponent--;
567 } else {
568 // Ignore insignificant digits in the fractional part.
569 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
570 }
571 ++current;
572 if (current == end) goto parsing_done;
573 }
574 }
575
576 if (!leading_zero && exponent == 0 && significant_digits == 0) {
577 // If leading_zeros is true then the string contains zeros.
578 // If exponent < 0 then string was [+-]\.0*...
579 // If significant_digits != 0 the string is not equal to 0.
580 // Otherwise there are no digits in the string.
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000581 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000582 }
583
584 // Parse exponential part.
585 if (*current == 'e' || *current == 'E') {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000586 if (octal) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000587 ++current;
588 if (current == end) {
589 if (allow_trailing_junk) {
590 goto parsing_done;
591 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000592 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000593 }
594 }
595 char sign = '+';
596 if (*current == '+' || *current == '-') {
597 sign = static_cast<char>(*current);
598 ++current;
599 if (current == end) {
600 if (allow_trailing_junk) {
601 goto parsing_done;
602 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000603 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000604 }
605 }
606 }
607
608 if (current == end || *current < '0' || *current > '9') {
609 if (allow_trailing_junk) {
610 goto parsing_done;
611 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000612 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000613 }
614 }
615
616 const int max_exponent = INT_MAX / 2;
617 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
618 int num = 0;
619 do {
620 // Check overflow.
621 int digit = *current - '0';
622 if (num >= max_exponent / 10
623 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
624 num = max_exponent;
625 } else {
626 num = num * 10 + digit;
627 }
628 ++current;
629 } while (current != end && *current >= '0' && *current <= '9');
630
631 exponent += (sign == '-' ? -num : num);
632 }
633
634 if (!allow_trailing_junk &&
635 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000636 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000637 }
638
639 parsing_done:
640 exponent += insignificant_digits;
641
642 if (octal) {
643 return InternalStringToIntDouble<3>(unicode_cache,
644 buffer,
645 buffer + buffer_pos,
646 negative,
647 allow_trailing_junk);
648 }
649
650 if (nonzero_digit_dropped) {
651 buffer[buffer_pos++] = '1';
652 exponent--;
653 }
654
655 ASSERT(buffer_pos < kBufferSize);
656 buffer[buffer_pos] = '\0';
657
658 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
659 return negative ? -converted : converted;
660}
661
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662} } // namespace v8::internal
663
664#endif // V8_CONVERSIONS_INL_H_