blob: 7edaf224072124437cab688b59bf36302bd066a2 [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>
ricow@chromium.org55ee8072011-09-08 16:33:10 +000035#include "globals.h" // Required for V8_INFINITY
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
37// ----------------------------------------------------------------------------
38// Extra POSIX/ANSI functions for Win32/MSVC.
39
40#include "conversions.h"
ricow@chromium.org55ee8072011-09-08 16:33:10 +000041#include "double.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042#include "platform.h"
ricow@chromium.org55ee8072011-09-08 16:33:10 +000043#include "scanner.h"
44#include "strtod.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
kasperl@chromium.org71affb52009-05-26 05:44:31 +000046namespace v8 {
47namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000048
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000049inline double JunkStringValue() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000050 return BitCast<double, uint64_t>(kQuietNaNMask);
sgjesse@chromium.org6db88712011-07-11 11:41:22 +000051}
52
53
ulan@chromium.orgea52b5f2012-07-30 13:05:33 +000054inline double SignedZero(bool negative) {
55 return negative ? uint64_to_double(Double::kSignMask) : 0.0;
56}
57
58
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000059// The fast double-to-unsigned-int conversion routine does not guarantee
fschneider@chromium.org086aac62010-03-17 13:18:24 +000060// rounding towards zero, or any reasonable value if the argument is larger
61// than what fits in an unsigned 32-bit integer.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000062inline unsigned int FastD2UI(double x) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000063 // There is no unsigned version of lrint, so there is no fast path
64 // in this function as there is in FastD2I. Using lrint doesn't work
65 // for values of 2^31 and above.
66
67 // Convert "small enough" doubles to uint32_t by fixing the 32
68 // least significant non-fractional bits in the low 32 bits of the
69 // double, and reading them from there.
70 const double k2Pow52 = 4503599627370496.0;
71 bool negative = x < 0;
72 if (negative) {
73 x = -x;
74 }
75 if (x < k2Pow52) {
76 x += k2Pow52;
77 uint32_t result;
fschneider@chromium.org086aac62010-03-17 13:18:24 +000078 Address mantissa_ptr = reinterpret_cast<Address>(&x);
fschneider@chromium.org086aac62010-03-17 13:18:24 +000079 // Copy least significant 32 bits of mantissa.
80 memcpy(&result, mantissa_ptr, sizeof(result));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000081 return negative ? ~result + 1 : result;
82 }
83 // Large number (outside uint32 range), Infinity or NaN.
84 return 0x80000000u; // Return integer indefinite.
85}
86
87
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000088inline double DoubleToInteger(double x) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089 if (isnan(x)) return 0;
90 if (!isfinite(x) || x == 0) return x;
91 return (x >= 0) ? floor(x) : ceil(x);
92}
93
94
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095int32_t DoubleToInt32(double x) {
96 int32_t i = FastD2I(x);
97 if (FastI2D(i) == x) return i;
ricow@chromium.org55ee8072011-09-08 16:33:10 +000098 Double d(x);
99 int exponent = d.Exponent();
100 if (exponent < 0) {
101 if (exponent <= -Double::kSignificandSize) return 0;
102 return d.Sign() * static_cast<int32_t>(d.Significand() >> -exponent);
103 } else {
104 if (exponent > 31) return 0;
105 return d.Sign() * static_cast<int32_t>(d.Significand() << exponent);
106 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107}
108
109
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000110template <class Iterator, class EndMark>
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000111bool SubStringEquals(Iterator* current,
112 EndMark end,
113 const char* substring) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000114 ASSERT(**current == *substring);
115 for (substring++; *substring != '\0'; substring++) {
116 ++*current;
117 if (*current == end || **current != *substring) return false;
118 }
119 ++*current;
120 return true;
121}
122
123
124// Returns true if a nonspace character has been found and false if the
125// end was been reached before finding a nonspace character.
126template <class Iterator, class EndMark>
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000127inline bool AdvanceToNonspace(UnicodeCache* unicode_cache,
128 Iterator* current,
129 EndMark end) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000130 while (*current != end) {
131 if (!unicode_cache->IsWhiteSpace(**current)) return true;
132 ++*current;
133 }
134 return false;
135}
136
137
138// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
139template <int radix_log_2, class Iterator, class EndMark>
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000140double InternalStringToIntDouble(UnicodeCache* unicode_cache,
141 Iterator current,
142 EndMark end,
143 bool negative,
144 bool allow_trailing_junk) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000145 ASSERT(current != end);
146
147 // Skip leading 0s.
148 while (*current == '0') {
149 ++current;
150 if (current == end) return SignedZero(negative);
151 }
152
153 int64_t number = 0;
154 int exponent = 0;
155 const int radix = (1 << radix_log_2);
156
157 do {
158 int digit;
159 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
160 digit = static_cast<char>(*current) - '0';
161 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
162 digit = static_cast<char>(*current) - 'a' + 10;
163 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
164 digit = static_cast<char>(*current) - 'A' + 10;
165 } else {
166 if (allow_trailing_junk ||
167 !AdvanceToNonspace(unicode_cache, &current, end)) {
168 break;
169 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000170 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000171 }
172 }
173
174 number = number * radix + digit;
175 int overflow = static_cast<int>(number >> 53);
176 if (overflow != 0) {
177 // Overflow occurred. Need to determine which direction to round the
178 // result.
179 int overflow_bits_count = 1;
180 while (overflow > 1) {
181 overflow_bits_count++;
182 overflow >>= 1;
183 }
184
185 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
186 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
187 number >>= overflow_bits_count;
188 exponent = overflow_bits_count;
189
190 bool zero_tail = true;
191 while (true) {
192 ++current;
193 if (current == end || !isDigit(*current, radix)) break;
194 zero_tail = zero_tail && *current == '0';
195 exponent += radix_log_2;
196 }
197
198 if (!allow_trailing_junk &&
199 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000200 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000201 }
202
203 int middle_value = (1 << (overflow_bits_count - 1));
204 if (dropped_bits > middle_value) {
205 number++; // Rounding up.
206 } else if (dropped_bits == middle_value) {
207 // Rounding to even to consistency with decimals: half-way case rounds
208 // up if significant part is odd and down otherwise.
209 if ((number & 1) != 0 || !zero_tail) {
210 number++; // Rounding up.
211 }
212 }
213
214 // Rounding up may cause overflow.
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000215 if ((number & (static_cast<int64_t>(1) << 53)) != 0) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000216 exponent++;
217 number >>= 1;
218 }
219 break;
220 }
221 ++current;
222 } while (current != end);
223
224 ASSERT(number < ((int64_t)1 << 53));
225 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
226
227 if (exponent == 0) {
228 if (negative) {
229 if (number == 0) return -0.0;
230 number = -number;
231 }
232 return static_cast<double>(number);
233 }
234
235 ASSERT(number != 0);
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +0000236 return ldexp(static_cast<double>(negative ? -number : number), exponent);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000237}
238
239
240template <class Iterator, class EndMark>
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000241double InternalStringToInt(UnicodeCache* unicode_cache,
242 Iterator current,
243 EndMark end,
244 int radix) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000245 const bool allow_trailing_junk = true;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000246 const double empty_string_val = JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000247
248 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
249 return empty_string_val;
250 }
251
252 bool negative = false;
253 bool leading_zero = false;
254
255 if (*current == '+') {
256 // Ignore leading sign; skip following spaces.
257 ++current;
258 if (current == end) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000259 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000260 }
261 } else if (*current == '-') {
262 ++current;
263 if (current == end) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000264 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000265 }
266 negative = true;
267 }
268
269 if (radix == 0) {
270 // Radix detection.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000271 radix = 10;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000272 if (*current == '0') {
273 ++current;
274 if (current == end) return SignedZero(negative);
275 if (*current == 'x' || *current == 'X') {
276 radix = 16;
277 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000278 if (current == end) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000279 } else {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000280 leading_zero = true;
281 }
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000282 }
283 } else if (radix == 16) {
284 if (*current == '0') {
285 // Allow "0x" prefix.
286 ++current;
287 if (current == end) return SignedZero(negative);
288 if (*current == 'x' || *current == 'X') {
289 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000290 if (current == end) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000291 } else {
292 leading_zero = true;
293 }
294 }
295 }
296
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000297 if (radix < 2 || radix > 36) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000298
299 // Skip leading zeros.
300 while (*current == '0') {
301 leading_zero = true;
302 ++current;
303 if (current == end) return SignedZero(negative);
304 }
305
306 if (!leading_zero && !isDigit(*current, radix)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000307 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000308 }
309
310 if (IsPowerOf2(radix)) {
311 switch (radix) {
312 case 2:
313 return InternalStringToIntDouble<1>(
314 unicode_cache, current, end, negative, allow_trailing_junk);
315 case 4:
316 return InternalStringToIntDouble<2>(
317 unicode_cache, current, end, negative, allow_trailing_junk);
318 case 8:
319 return InternalStringToIntDouble<3>(
320 unicode_cache, current, end, negative, allow_trailing_junk);
321
322 case 16:
323 return InternalStringToIntDouble<4>(
324 unicode_cache, current, end, negative, allow_trailing_junk);
325
326 case 32:
327 return InternalStringToIntDouble<5>(
328 unicode_cache, current, end, negative, allow_trailing_junk);
329 default:
330 UNREACHABLE();
331 }
332 }
333
334 if (radix == 10) {
335 // Parsing with strtod.
336 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
337 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
338 // end.
339 const int kBufferSize = kMaxSignificantDigits + 2;
340 char buffer[kBufferSize];
341 int buffer_pos = 0;
342 while (*current >= '0' && *current <= '9') {
343 if (buffer_pos <= kMaxSignificantDigits) {
344 // If the number has more than kMaxSignificantDigits it will be parsed
345 // as infinity.
346 ASSERT(buffer_pos < kBufferSize);
347 buffer[buffer_pos++] = static_cast<char>(*current);
348 }
349 ++current;
350 if (current == end) break;
351 }
352
353 if (!allow_trailing_junk &&
354 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000355 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000356 }
357
358 ASSERT(buffer_pos < kBufferSize);
359 buffer[buffer_pos] = '\0';
360 Vector<const char> buffer_vector(buffer, buffer_pos);
361 return negative ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
362 }
363
364 // The following code causes accumulating rounding error for numbers greater
365 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
366 // 16, or 32, then mathInt may be an implementation-dependent approximation to
367 // the mathematical integer value" (15.1.2.2).
368
369 int lim_0 = '0' + (radix < 10 ? radix : 10);
370 int lim_a = 'a' + (radix - 10);
371 int lim_A = 'A' + (radix - 10);
372
373 // NOTE: The code for computing the value may seem a bit complex at
374 // first glance. It is structured to use 32-bit multiply-and-add
375 // loops as long as possible to avoid loosing precision.
376
377 double v = 0.0;
378 bool done = false;
379 do {
380 // Parse the longest part of the string starting at index j
381 // possible while keeping the multiplier, and thus the part
382 // itself, within 32 bits.
383 unsigned int part = 0, multiplier = 1;
384 while (true) {
385 int d;
386 if (*current >= '0' && *current < lim_0) {
387 d = *current - '0';
388 } else if (*current >= 'a' && *current < lim_a) {
389 d = *current - 'a' + 10;
390 } else if (*current >= 'A' && *current < lim_A) {
391 d = *current - 'A' + 10;
392 } else {
393 done = true;
394 break;
395 }
396
397 // Update the value of the part as long as the multiplier fits
398 // in 32 bits. When we can't guarantee that the next iteration
399 // will not overflow the multiplier, we stop parsing the part
400 // by leaving the loop.
401 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
402 uint32_t m = multiplier * radix;
403 if (m > kMaximumMultiplier) break;
404 part = part * radix + d;
405 multiplier = m;
406 ASSERT(multiplier > part);
407
408 ++current;
409 if (current == end) {
410 done = true;
411 break;
412 }
413 }
414
415 // Update the value and skip the part in the string.
416 v = v * multiplier + part;
417 } while (!done);
418
419 if (!allow_trailing_junk &&
420 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000421 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000422 }
423
424 return negative ? -v : v;
425}
426
427
428// Converts a string to a double value. Assumes the Iterator supports
429// the following operations:
430// 1. current == end (other ops are not allowed), current != end.
431// 2. *current - gets the current character in the sequence.
432// 3. ++current (advances the position).
433template <class Iterator, class EndMark>
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000434double InternalStringToDouble(UnicodeCache* unicode_cache,
435 Iterator current,
436 EndMark end,
437 int flags,
438 double empty_string_val) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000439 // To make sure that iterator dereferencing is valid the following
440 // convention is used:
441 // 1. Each '++current' statement is followed by check for equality to 'end'.
442 // 2. If AdvanceToNonspace returned false then current == end.
443 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
444 // 'parsing_done'.
445 // 4. 'current' is not dereferenced after the 'parsing_done' label.
446 // 5. Code before 'parsing_done' may rely on 'current != end'.
447 if (!AdvanceToNonspace(unicode_cache, &current, end)) {
448 return empty_string_val;
449 }
450
451 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
452
453 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
454 const int kBufferSize = kMaxSignificantDigits + 10;
455 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
456 int buffer_pos = 0;
457
458 // Exponent will be adjusted if insignificant digits of the integer part
459 // or insignificant leading zeros of the fractional part are dropped.
460 int exponent = 0;
461 int significant_digits = 0;
462 int insignificant_digits = 0;
463 bool nonzero_digit_dropped = false;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000464
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000465 enum Sign {
466 NONE,
467 NEGATIVE,
468 POSITIVE
469 };
470
471 Sign sign = NONE;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000472
473 if (*current == '+') {
474 // Ignore leading sign.
475 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000476 if (current == end) return JunkStringValue();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000477 sign = POSITIVE;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000478 } else if (*current == '-') {
479 ++current;
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000480 if (current == end) return JunkStringValue();
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000481 sign = NEGATIVE;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000482 }
483
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000484 static const char kInfinityString[] = "Infinity";
485 if (*current == kInfinityString[0]) {
486 if (!SubStringEquals(&current, end, kInfinityString)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000487 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000488 }
489
490 if (!allow_trailing_junk &&
491 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000492 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000493 }
494
495 ASSERT(buffer_pos == 0);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000496 return (sign == NEGATIVE) ? -V8_INFINITY : V8_INFINITY;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000497 }
498
499 bool leading_zero = false;
500 if (*current == '0') {
501 ++current;
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000502 if (current == end) return SignedZero(sign == NEGATIVE);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000503
504 leading_zero = true;
505
506 // It could be hexadecimal value.
507 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
508 ++current;
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000509 if (current == end || !isDigit(*current, 16) || sign != NONE) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000510 return JunkStringValue(); // "0x".
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000511 }
512
513 return InternalStringToIntDouble<4>(unicode_cache,
514 current,
515 end,
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000516 false,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000517 allow_trailing_junk);
518 }
519
520 // Ignore leading zeros in the integer part.
521 while (*current == '0') {
522 ++current;
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000523 if (current == end) return SignedZero(sign == NEGATIVE);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000524 }
525 }
526
527 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
528
529 // Copy significant digits of the integer part (if any) to the buffer.
530 while (*current >= '0' && *current <= '9') {
531 if (significant_digits < kMaxSignificantDigits) {
532 ASSERT(buffer_pos < kBufferSize);
533 buffer[buffer_pos++] = static_cast<char>(*current);
534 significant_digits++;
535 // Will later check if it's an octal in the buffer.
536 } else {
537 insignificant_digits++; // Move the digit into the exponential part.
538 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
539 }
540 octal = octal && *current < '8';
541 ++current;
542 if (current == end) goto parsing_done;
543 }
544
545 if (significant_digits == 0) {
546 octal = false;
547 }
548
549 if (*current == '.') {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000550 if (octal && !allow_trailing_junk) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000551 if (octal) goto parsing_done;
552
553 ++current;
554 if (current == end) {
555 if (significant_digits == 0 && !leading_zero) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000556 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000557 } else {
558 goto parsing_done;
559 }
560 }
561
562 if (significant_digits == 0) {
563 // octal = false;
564 // Integer part consists of 0 or is absent. Significant digits start after
565 // leading zeros (if any).
566 while (*current == '0') {
567 ++current;
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000568 if (current == end) return SignedZero(sign == NEGATIVE);
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000569 exponent--; // Move this 0 into the exponent.
570 }
571 }
572
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000573 // There is a fractional part. We don't emit a '.', but adjust the exponent
574 // instead.
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000575 while (*current >= '0' && *current <= '9') {
576 if (significant_digits < kMaxSignificantDigits) {
577 ASSERT(buffer_pos < kBufferSize);
578 buffer[buffer_pos++] = static_cast<char>(*current);
579 significant_digits++;
580 exponent--;
581 } else {
582 // Ignore insignificant digits in the fractional part.
583 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
584 }
585 ++current;
586 if (current == end) goto parsing_done;
587 }
588 }
589
590 if (!leading_zero && exponent == 0 && significant_digits == 0) {
591 // If leading_zeros is true then the string contains zeros.
592 // If exponent < 0 then string was [+-]\.0*...
593 // If significant_digits != 0 the string is not equal to 0.
594 // Otherwise there are no digits in the string.
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000595 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000596 }
597
598 // Parse exponential part.
599 if (*current == 'e' || *current == 'E') {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000600 if (octal) return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000601 ++current;
602 if (current == end) {
603 if (allow_trailing_junk) {
604 goto parsing_done;
605 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000606 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000607 }
608 }
609 char sign = '+';
610 if (*current == '+' || *current == '-') {
611 sign = static_cast<char>(*current);
612 ++current;
613 if (current == end) {
614 if (allow_trailing_junk) {
615 goto parsing_done;
616 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000617 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000618 }
619 }
620 }
621
622 if (current == end || *current < '0' || *current > '9') {
623 if (allow_trailing_junk) {
624 goto parsing_done;
625 } else {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000626 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000627 }
628 }
629
630 const int max_exponent = INT_MAX / 2;
631 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
632 int num = 0;
633 do {
634 // Check overflow.
635 int digit = *current - '0';
636 if (num >= max_exponent / 10
637 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
638 num = max_exponent;
639 } else {
640 num = num * 10 + digit;
641 }
642 ++current;
643 } while (current != end && *current >= '0' && *current <= '9');
644
645 exponent += (sign == '-' ? -num : num);
646 }
647
648 if (!allow_trailing_junk &&
649 AdvanceToNonspace(unicode_cache, &current, end)) {
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000650 return JunkStringValue();
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000651 }
652
653 parsing_done:
654 exponent += insignificant_digits;
655
656 if (octal) {
657 return InternalStringToIntDouble<3>(unicode_cache,
658 buffer,
659 buffer + buffer_pos,
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000660 sign == NEGATIVE,
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000661 allow_trailing_junk);
662 }
663
664 if (nonzero_digit_dropped) {
665 buffer[buffer_pos++] = '1';
666 exponent--;
667 }
668
669 ASSERT(buffer_pos < kBufferSize);
670 buffer[buffer_pos] = '\0';
671
672 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000673 return (sign == NEGATIVE) ? -converted : converted;
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000674}
675
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676} } // namespace v8::internal
677
678#endif // V8_CONVERSIONS_INL_H_