blob: 790e807aef4f898413774f6c0c6b6f7ca648e7ea [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// 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#include <stdarg.h>
Steve Block6ded16b2010-05-10 14:33:55 +010029#include <limits.h>
Steve Blocka7e24c12009-10-30 11:49:00 +000030
31#include "v8.h"
32
33#include "conversions-inl.h"
Kristian Monsen25f61362010-05-21 11:50:48 +010034#include "dtoa.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "factory.h"
36#include "scanner.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010037#include "strtod.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038
39namespace v8 {
40namespace internal {
41
42int HexValue(uc32 c) {
43 if ('0' <= c && c <= '9')
44 return c - '0';
45 if ('a' <= c && c <= 'f')
46 return c - 'a' + 10;
47 if ('A' <= c && c <= 'F')
48 return c - 'A' + 10;
49 return -1;
50}
51
Steve Block6ded16b2010-05-10 14:33:55 +010052namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +000053
Steve Block6ded16b2010-05-10 14:33:55 +010054// C++-style iterator adaptor for StringInputBuffer
55// (unlike C++ iterators the end-marker has different type).
56class StringInputBufferIterator {
57 public:
58 class EndMarker {};
59
60 explicit StringInputBufferIterator(StringInputBuffer* buffer);
61
62 int operator*() const;
63 void operator++();
64 bool operator==(EndMarker const&) const { return end_; }
65 bool operator!=(EndMarker const& m) const { return !end_; }
66
67 private:
68 StringInputBuffer* const buffer_;
69 int current_;
70 bool end_;
71};
72
73
74StringInputBufferIterator::StringInputBufferIterator(
75 StringInputBuffer* buffer) : buffer_(buffer) {
76 ++(*this);
77}
78
79int StringInputBufferIterator::operator*() const {
80 return current_;
Steve Blocka7e24c12009-10-30 11:49:00 +000081}
82
83
Steve Block6ded16b2010-05-10 14:33:55 +010084void StringInputBufferIterator::operator++() {
85 end_ = !buffer_->has_more();
86 if (!end_) {
87 current_ = buffer_->GetNext();
Steve Blocka7e24c12009-10-30 11:49:00 +000088 }
Steve Block6ded16b2010-05-10 14:33:55 +010089}
Steve Blocka7e24c12009-10-30 11:49:00 +000090}
91
92
Steve Block6ded16b2010-05-10 14:33:55 +010093template <class Iterator, class EndMark>
94static bool SubStringEquals(Iterator* current,
95 EndMark end,
96 const char* substring) {
97 ASSERT(**current == *substring);
98 for (substring++; *substring != '\0'; substring++) {
99 ++*current;
100 if (*current == end || **current != *substring) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000101 }
Steve Block6ded16b2010-05-10 14:33:55 +0100102 ++*current;
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 return true;
104}
105
106
Steve Block6ded16b2010-05-10 14:33:55 +0100107// Maximum number of significant digits in decimal representation.
108// The longest possible double in decimal representation is
109// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
110// (768 digits). If we parse a number whose first digits are equal to a
111// mean of 2 adjacent doubles (that could have up to 769 digits) the result
112// must be rounded to the bigger one unless the tail consists of zeros, so
113// we don't need to preserve all the digits.
114const int kMaxSignificantDigits = 772;
Steve Blocka7e24c12009-10-30 11:49:00 +0000115
Steve Blocka7e24c12009-10-30 11:49:00 +0000116
Steve Block6ded16b2010-05-10 14:33:55 +0100117static const double JUNK_STRING_VALUE = OS::nan_value();
118
119
120// Returns true if a nonspace found and false if the end has reached.
121template <class Iterator, class EndMark>
122static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
123 while (*current != end) {
124 if (!Scanner::kIsWhiteSpace.get(**current)) return true;
125 ++*current;
126 }
127 return false;
128}
129
130
131static bool isDigit(int x, int radix) {
132 return (x >= '0' && x <= '9' && x < '0' + radix)
133 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
134 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
135}
136
137
138static double SignedZero(bool sign) {
139 return sign ? -0.0 : 0.0;
140}
141
142
143// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
144template <int radix_log_2, class Iterator, class EndMark>
145static double InternalStringToIntDouble(Iterator current,
146 EndMark end,
147 bool sign,
148 bool allow_trailing_junk) {
149 ASSERT(current != end);
150
151 // Skip leading 0s.
152 while (*current == '0') {
153 ++current;
154 if (current == end) return SignedZero(sign);
155 }
156
157 int64_t number = 0;
158 int exponent = 0;
159 const int radix = (1 << radix_log_2);
160
161 do {
162 int digit;
163 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
164 digit = static_cast<char>(*current) - '0';
165 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
166 digit = static_cast<char>(*current) - 'a' + 10;
167 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
168 digit = static_cast<char>(*current) - 'A' + 10;
169 } else {
170 if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
171 break;
172 } else {
173 return JUNK_STRING_VALUE;
174 }
175 }
176
177 number = number * radix + digit;
178 int overflow = static_cast<int>(number >> 53);
179 if (overflow != 0) {
180 // Overflow occurred. Need to determine which direction to round the
181 // result.
182 int overflow_bits_count = 1;
183 while (overflow > 1) {
184 overflow_bits_count++;
185 overflow >>= 1;
186 }
187
188 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
189 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
190 number >>= overflow_bits_count;
191 exponent = overflow_bits_count;
192
193 bool zero_tail = true;
194 while (true) {
195 ++current;
196 if (current == end || !isDigit(*current, radix)) break;
197 zero_tail = zero_tail && *current == '0';
198 exponent += radix_log_2;
199 }
200
201 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
202 return JUNK_STRING_VALUE;
203 }
204
205 int middle_value = (1 << (overflow_bits_count - 1));
206 if (dropped_bits > middle_value) {
207 number++; // Rounding up.
208 } else if (dropped_bits == middle_value) {
209 // Rounding to even to consistency with decimals: half-way case rounds
210 // up if significant part is odd and down otherwise.
211 if ((number & 1) != 0 || !zero_tail) {
212 number++; // Rounding up.
213 }
214 }
215
216 // Rounding up may cause overflow.
217 if ((number & ((int64_t)1 << 53)) != 0) {
218 exponent++;
219 number >>= 1;
220 }
221 break;
222 }
223 ++current;
224 } while (current != end);
225
226 ASSERT(number < ((int64_t)1 << 53));
227 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
228
229 if (exponent == 0) {
230 if (sign) {
231 if (number == 0) return -0.0;
232 number = -number;
233 }
234 return static_cast<double>(number);
235 }
236
237 ASSERT(number != 0);
238 // The double could be constructed faster from number (mantissa), exponent
239 // and sign. Assuming it's a rare case more simple code is used.
240 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent);
241}
242
243
244template <class Iterator, class EndMark>
245static double InternalStringToInt(Iterator current, EndMark end, int radix) {
246 const bool allow_trailing_junk = true;
247 const double empty_string_val = JUNK_STRING_VALUE;
248
249 if (!AdvanceToNonspace(&current, end)) return empty_string_val;
250
251 bool sign = false;
252 bool leading_zero = false;
253
254 if (*current == '+') {
255 // Ignore leading sign; skip following spaces.
256 ++current;
257 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
258 } else if (*current == '-') {
259 ++current;
260 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
261 sign = true;
262 }
263
264 if (radix == 0) {
265 // Radix detection.
266 if (*current == '0') {
267 ++current;
268 if (current == end) return SignedZero(sign);
269 if (*current == 'x' || *current == 'X') {
270 radix = 16;
271 ++current;
272 if (current == end) return JUNK_STRING_VALUE;
273 } else {
274 radix = 8;
275 leading_zero = true;
276 }
277 } else {
278 radix = 10;
279 }
280 } else if (radix == 16) {
281 if (*current == '0') {
282 // Allow "0x" prefix.
283 ++current;
284 if (current == end) return SignedZero(sign);
285 if (*current == 'x' || *current == 'X') {
286 ++current;
287 if (current == end) return JUNK_STRING_VALUE;
288 } else {
289 leading_zero = true;
290 }
291 }
292 }
293
294 if (radix < 2 || radix > 36) return JUNK_STRING_VALUE;
295
296 // Skip leading zeros.
297 while (*current == '0') {
298 leading_zero = true;
299 ++current;
300 if (current == end) return SignedZero(sign);
301 }
302
303 if (!leading_zero && !isDigit(*current, radix)) {
304 return JUNK_STRING_VALUE;
305 }
306
307 if (IsPowerOf2(radix)) {
308 switch (radix) {
309 case 2:
310 return InternalStringToIntDouble<1>(
311 current, end, sign, allow_trailing_junk);
312 case 4:
313 return InternalStringToIntDouble<2>(
314 current, end, sign, allow_trailing_junk);
315 case 8:
316 return InternalStringToIntDouble<3>(
317 current, end, sign, allow_trailing_junk);
318
319 case 16:
320 return InternalStringToIntDouble<4>(
321 current, end, sign, allow_trailing_junk);
322
323 case 32:
324 return InternalStringToIntDouble<5>(
325 current, end, sign, allow_trailing_junk);
326 default:
327 UNREACHABLE();
328 }
329 }
330
331 if (radix == 10) {
332 // Parsing with strtod.
333 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
334 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
335 // end.
336 const int kBufferSize = kMaxSignificantDigits + 2;
337 char buffer[kBufferSize];
338 int buffer_pos = 0;
339 while (*current >= '0' && *current <= '9') {
340 if (buffer_pos <= kMaxSignificantDigits) {
341 // If the number has more than kMaxSignificantDigits it will be parsed
342 // as infinity.
343 ASSERT(buffer_pos < kBufferSize);
344 buffer[buffer_pos++] = static_cast<char>(*current);
345 }
346 ++current;
347 if (current == end) break;
348 }
349
350 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
351 return JUNK_STRING_VALUE;
352 }
353
354 ASSERT(buffer_pos < kBufferSize);
Ben Murdochf87a2032010-10-22 12:50:53 +0100355 buffer[buffer_pos] = '\0';
356 Vector<const char> buffer_vector(buffer, buffer_pos);
357 return sign ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
Steve Block6ded16b2010-05-10 14:33:55 +0100358 }
359
360 // The following code causes accumulating rounding error for numbers greater
361 // than ~2^56. It's explicitly allowed in the spec: "if R is not 2, 4, 8, 10,
362 // 16, or 32, then mathInt may be an implementation-dependent approximation to
363 // the mathematical integer value" (15.1.2.2).
364
Steve Blocka7e24c12009-10-30 11:49:00 +0000365 int lim_0 = '0' + (radix < 10 ? radix : 10);
366 int lim_a = 'a' + (radix - 10);
367 int lim_A = 'A' + (radix - 10);
368
369 // NOTE: The code for computing the value may seem a bit complex at
370 // first glance. It is structured to use 32-bit multiply-and-add
371 // loops as long as possible to avoid loosing precision.
372
373 double v = 0.0;
Steve Block6ded16b2010-05-10 14:33:55 +0100374 bool done = false;
375 do {
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 // Parse the longest part of the string starting at index j
377 // possible while keeping the multiplier, and thus the part
378 // itself, within 32 bits.
Steve Block6ded16b2010-05-10 14:33:55 +0100379 unsigned int part = 0, multiplier = 1;
380 while (true) {
381 int d;
382 if (*current >= '0' && *current < lim_0) {
383 d = *current - '0';
384 } else if (*current >= 'a' && *current < lim_a) {
385 d = *current - 'a' + 10;
386 } else if (*current >= 'A' && *current < lim_A) {
387 d = *current - 'A' + 10;
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 } else {
Steve Block6ded16b2010-05-10 14:33:55 +0100389 done = true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 break;
391 }
392
393 // Update the value of the part as long as the multiplier fits
394 // in 32 bits. When we can't guarantee that the next iteration
395 // will not overflow the multiplier, we stop parsing the part
396 // by leaving the loop.
Steve Block6ded16b2010-05-10 14:33:55 +0100397 const unsigned int kMaximumMultiplier = 0xffffffffU / 36;
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 uint32_t m = multiplier * radix;
399 if (m > kMaximumMultiplier) break;
Steve Block6ded16b2010-05-10 14:33:55 +0100400 part = part * radix + d;
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 multiplier = m;
402 ASSERT(multiplier > part);
Steve Block6ded16b2010-05-10 14:33:55 +0100403
404 ++current;
405 if (current == end) {
406 done = true;
407 break;
408 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 }
410
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 // Update the value and skip the part in the string.
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 v = v * multiplier + part;
Steve Block6ded16b2010-05-10 14:33:55 +0100413 } while (!done);
Steve Blocka7e24c12009-10-30 11:49:00 +0000414
Steve Block6ded16b2010-05-10 14:33:55 +0100415 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 return JUNK_STRING_VALUE;
417 }
418
Steve Block6ded16b2010-05-10 14:33:55 +0100419 return sign ? -v : v;
Steve Blocka7e24c12009-10-30 11:49:00 +0000420}
421
422
Steve Block6ded16b2010-05-10 14:33:55 +0100423// Converts a string to a double value. Assumes the Iterator supports
424// the following operations:
425// 1. current == end (other ops are not allowed), current != end.
426// 2. *current - gets the current character in the sequence.
427// 3. ++current (advances the position).
428template <class Iterator, class EndMark>
429static double InternalStringToDouble(Iterator current,
430 EndMark end,
431 int flags,
432 double empty_string_val) {
433 // To make sure that iterator dereferencing is valid the following
434 // convention is used:
435 // 1. Each '++current' statement is followed by check for equality to 'end'.
436 // 2. If AdvanceToNonspace returned false then current == end.
437 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
438 // 'parsing_done'.
439 // 4. 'current' is not dereferenced after the 'parsing_done' label.
440 // 5. Code before 'parsing_done' may rely on 'current != end'.
441 if (!AdvanceToNonspace(&current, end)) return empty_string_val;
442
443 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
444
445 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
446 const int kBufferSize = kMaxSignificantDigits + 10;
447 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
448 int buffer_pos = 0;
449
450 // Exponent will be adjusted if insignificant digits of the integer part
451 // or insignificant leading zeros of the fractional part are dropped.
452 int exponent = 0;
453 int significant_digits = 0;
454 int insignificant_digits = 0;
455 bool nonzero_digit_dropped = false;
456 bool fractional_part = false;
457
458 bool sign = false;
459
460 if (*current == '+') {
461 // Ignore leading sign; skip following spaces.
462 ++current;
463 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
464 } else if (*current == '-') {
Steve Block6ded16b2010-05-10 14:33:55 +0100465 ++current;
466 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
467 sign = true;
468 }
469
470 static const char kInfinitySymbol[] = "Infinity";
471 if (*current == kInfinitySymbol[0]) {
472 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
473 return JUNK_STRING_VALUE;
474 }
475
476 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
477 return JUNK_STRING_VALUE;
478 }
479
Ben Murdochf87a2032010-10-22 12:50:53 +0100480 ASSERT(buffer_pos == 0);
481 return sign ? -V8_INFINITY : V8_INFINITY;
Steve Block6ded16b2010-05-10 14:33:55 +0100482 }
483
484 bool leading_zero = false;
485 if (*current == '0') {
486 ++current;
487 if (current == end) return SignedZero(sign);
488
489 leading_zero = true;
490
491 // It could be hexadecimal value.
492 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
493 ++current;
494 if (current == end || !isDigit(*current, 16)) {
495 return JUNK_STRING_VALUE; // "0x".
496 }
497
Steve Block6ded16b2010-05-10 14:33:55 +0100498 return InternalStringToIntDouble<4>(current,
499 end,
500 sign,
501 allow_trailing_junk);
502 }
503
504 // Ignore leading zeros in the integer part.
505 while (*current == '0') {
506 ++current;
507 if (current == end) return SignedZero(sign);
508 }
509 }
510
511 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
512
513 // Copy significant digits of the integer part (if any) to the buffer.
514 while (*current >= '0' && *current <= '9') {
515 if (significant_digits < kMaxSignificantDigits) {
516 ASSERT(buffer_pos < kBufferSize);
517 buffer[buffer_pos++] = static_cast<char>(*current);
518 significant_digits++;
519 // Will later check if it's an octal in the buffer.
520 } else {
521 insignificant_digits++; // Move the digit into the exponential part.
522 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
523 }
524 octal = octal && *current < '8';
525 ++current;
526 if (current == end) goto parsing_done;
527 }
528
529 if (significant_digits == 0) {
530 octal = false;
531 }
532
533 if (*current == '.') {
Ben Murdochf87a2032010-10-22 12:50:53 +0100534 if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
535 if (octal) goto parsing_done;
536
Steve Block6ded16b2010-05-10 14:33:55 +0100537 ++current;
538 if (current == end) {
539 if (significant_digits == 0 && !leading_zero) {
540 return JUNK_STRING_VALUE;
541 } else {
542 goto parsing_done;
543 }
544 }
545
546 if (significant_digits == 0) {
547 // octal = false;
548 // Integer part consists of 0 or is absent. Significant digits start after
549 // leading zeros (if any).
550 while (*current == '0') {
551 ++current;
552 if (current == end) return SignedZero(sign);
553 exponent--; // Move this 0 into the exponent.
554 }
555 }
556
Ben Murdochf87a2032010-10-22 12:50:53 +0100557 // We don't emit a '.', but adjust the exponent instead.
Steve Block6ded16b2010-05-10 14:33:55 +0100558 fractional_part = true;
559
Ben Murdochf87a2032010-10-22 12:50:53 +0100560 // There is a fractional part.
Steve Block6ded16b2010-05-10 14:33:55 +0100561 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++;
Ben Murdochf87a2032010-10-22 12:50:53 +0100566 exponent--;
Steve Block6ded16b2010-05-10 14:33:55 +0100567 } 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.
581 return JUNK_STRING_VALUE;
582 }
583
584 // Parse exponential part.
585 if (*current == 'e' || *current == 'E') {
586 if (octal) return JUNK_STRING_VALUE;
587 ++current;
588 if (current == end) {
589 if (allow_trailing_junk) {
590 goto parsing_done;
591 } else {
592 return JUNK_STRING_VALUE;
593 }
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 {
603 return JUNK_STRING_VALUE;
604 }
605 }
606 }
607
608 if (current == end || *current < '0' || *current > '9') {
609 if (allow_trailing_junk) {
610 goto parsing_done;
611 } else {
612 return JUNK_STRING_VALUE;
613 }
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 && AdvanceToNonspace(&current, end)) {
635 return JUNK_STRING_VALUE;
636 }
637
638 parsing_done:
639 exponent += insignificant_digits;
640
641 if (octal) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100642 return InternalStringToIntDouble<3>(buffer,
Steve Block6ded16b2010-05-10 14:33:55 +0100643 buffer + buffer_pos,
644 sign,
645 allow_trailing_junk);
646 }
647
648 if (nonzero_digit_dropped) {
Steve Block6ded16b2010-05-10 14:33:55 +0100649 buffer[buffer_pos++] = '1';
Ben Murdochf87a2032010-10-22 12:50:53 +0100650 exponent--;
Steve Block6ded16b2010-05-10 14:33:55 +0100651 }
652
653 ASSERT(buffer_pos < kBufferSize);
654 buffer[buffer_pos] = '\0';
655
Ben Murdochf87a2032010-10-22 12:50:53 +0100656 double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
657 return sign? -converted: converted;
Steve Block6ded16b2010-05-10 14:33:55 +0100658}
659
Ben Murdochf87a2032010-10-22 12:50:53 +0100660
Steve Blocka7e24c12009-10-30 11:49:00 +0000661double StringToDouble(String* str, int flags, double empty_string_val) {
Steve Block6ded16b2010-05-10 14:33:55 +0100662 StringShape shape(str);
663 if (shape.IsSequentialAscii()) {
664 const char* begin = SeqAsciiString::cast(str)->GetChars();
665 const char* end = begin + str->length();
666 return InternalStringToDouble(begin, end, flags, empty_string_val);
667 } else if (shape.IsSequentialTwoByte()) {
668 const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
669 const uc16* end = begin + str->length();
670 return InternalStringToDouble(begin, end, flags, empty_string_val);
671 } else {
672 StringInputBuffer buffer(str);
673 return InternalStringToDouble(StringInputBufferIterator(&buffer),
674 StringInputBufferIterator::EndMarker(),
675 flags,
676 empty_string_val);
677 }
678}
679
680
681double StringToInt(String* str, int radix) {
682 StringShape shape(str);
683 if (shape.IsSequentialAscii()) {
684 const char* begin = SeqAsciiString::cast(str)->GetChars();
685 const char* end = begin + str->length();
686 return InternalStringToInt(begin, end, radix);
687 } else if (shape.IsSequentialTwoByte()) {
688 const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
689 const uc16* end = begin + str->length();
690 return InternalStringToInt(begin, end, radix);
691 } else {
692 StringInputBuffer buffer(str);
693 return InternalStringToInt(StringInputBufferIterator(&buffer),
694 StringInputBufferIterator::EndMarker(),
695 radix);
696 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000697}
698
699
700double StringToDouble(const char* str, int flags, double empty_string_val) {
Steve Block6ded16b2010-05-10 14:33:55 +0100701 const char* end = str + StrLength(str);
Steve Block6ded16b2010-05-10 14:33:55 +0100702 return InternalStringToDouble(str, end, flags, empty_string_val);
Steve Blocka7e24c12009-10-30 11:49:00 +0000703}
704
705
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100706double StringToDouble(Vector<const char> str,
707 int flags,
708 double empty_string_val) {
709 const char* end = str.start() + str.length();
710 return InternalStringToDouble(str.start(), end, flags, empty_string_val);
711}
712
713
Steve Blocka7e24c12009-10-30 11:49:00 +0000714extern "C" char* dtoa(double d, int mode, int ndigits,
715 int* decpt, int* sign, char** rve);
716
717extern "C" void freedtoa(char* s);
718
719const char* DoubleToCString(double v, Vector<char> buffer) {
720 StringBuilder builder(buffer.start(), buffer.length());
721
722 switch (fpclassify(v)) {
723 case FP_NAN:
724 builder.AddString("NaN");
725 break;
726
727 case FP_INFINITE:
728 if (v < 0.0) {
729 builder.AddString("-Infinity");
730 } else {
731 builder.AddString("Infinity");
732 }
733 break;
734
735 case FP_ZERO:
736 builder.AddCharacter('0');
737 break;
738
739 default: {
740 int decimal_point;
741 int sign;
Steve Block6ded16b2010-05-10 14:33:55 +0100742 char* decimal_rep;
743 bool used_gay_dtoa = false;
Kristian Monsen25f61362010-05-21 11:50:48 +0100744 const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
745 char v8_dtoa_buffer[kV8DtoaBufferCapacity];
Steve Block6ded16b2010-05-10 14:33:55 +0100746 int length;
Kristian Monsen25f61362010-05-21 11:50:48 +0100747
748 if (DoubleToAscii(v, DTOA_SHORTEST, 0,
749 Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
750 &sign, &length, &decimal_point)) {
751 decimal_rep = v8_dtoa_buffer;
Steve Block6ded16b2010-05-10 14:33:55 +0100752 } else {
753 decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
754 used_gay_dtoa = true;
755 length = StrLength(decimal_rep);
756 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000757
758 if (sign) builder.AddCharacter('-');
759
760 if (length <= decimal_point && decimal_point <= 21) {
761 // ECMA-262 section 9.8.1 step 6.
762 builder.AddString(decimal_rep);
763 builder.AddPadding('0', decimal_point - length);
764
765 } else if (0 < decimal_point && decimal_point <= 21) {
766 // ECMA-262 section 9.8.1 step 7.
767 builder.AddSubstring(decimal_rep, decimal_point);
768 builder.AddCharacter('.');
769 builder.AddString(decimal_rep + decimal_point);
770
771 } else if (decimal_point <= 0 && decimal_point > -6) {
772 // ECMA-262 section 9.8.1 step 8.
773 builder.AddString("0.");
774 builder.AddPadding('0', -decimal_point);
775 builder.AddString(decimal_rep);
776
777 } else {
778 // ECMA-262 section 9.8.1 step 9 and 10 combined.
779 builder.AddCharacter(decimal_rep[0]);
780 if (length != 1) {
781 builder.AddCharacter('.');
782 builder.AddString(decimal_rep + 1);
783 }
784 builder.AddCharacter('e');
785 builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
786 int exponent = decimal_point - 1;
787 if (exponent < 0) exponent = -exponent;
788 builder.AddFormatted("%d", exponent);
789 }
790
Steve Block6ded16b2010-05-10 14:33:55 +0100791 if (used_gay_dtoa) freedtoa(decimal_rep);
Steve Blocka7e24c12009-10-30 11:49:00 +0000792 }
793 }
794 return builder.Finalize();
795}
796
797
798const char* IntToCString(int n, Vector<char> buffer) {
799 bool negative = false;
800 if (n < 0) {
801 // We must not negate the most negative int.
802 if (n == kMinInt) return DoubleToCString(n, buffer);
803 negative = true;
804 n = -n;
805 }
806 // Build the string backwards from the least significant digit.
807 int i = buffer.length();
808 buffer[--i] = '\0';
809 do {
810 buffer[--i] = '0' + (n % 10);
811 n /= 10;
812 } while (n);
813 if (negative) buffer[--i] = '-';
814 return buffer.start() + i;
815}
816
817
818char* DoubleToFixedCString(double value, int f) {
Kristian Monsen25f61362010-05-21 11:50:48 +0100819 const int kMaxDigitsBeforePoint = 20;
820 const double kFirstNonFixed = 1e21;
821 const int kMaxDigitsAfterPoint = 20;
Steve Blocka7e24c12009-10-30 11:49:00 +0000822 ASSERT(f >= 0);
Kristian Monsen25f61362010-05-21 11:50:48 +0100823 ASSERT(f <= kMaxDigitsAfterPoint);
Steve Blocka7e24c12009-10-30 11:49:00 +0000824
825 bool negative = false;
826 double abs_value = value;
827 if (value < 0) {
828 abs_value = -value;
829 negative = true;
830 }
831
Kristian Monsen25f61362010-05-21 11:50:48 +0100832 // If abs_value has more than kMaxDigitsBeforePoint digits before the point
833 // use the non-fixed conversion routine.
834 if (abs_value >= kFirstNonFixed) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000835 char arr[100];
836 Vector<char> buffer(arr, ARRAY_SIZE(arr));
837 return StrDup(DoubleToCString(value, buffer));
838 }
839
840 // Find a sufficiently precise decimal representation of n.
841 int decimal_point;
842 int sign;
Kristian Monsen25f61362010-05-21 11:50:48 +0100843 // Add space for the '.' and the '\0' byte.
844 const int kDecimalRepCapacity =
845 kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 2;
846 char decimal_rep[kDecimalRepCapacity];
847 int decimal_rep_length;
848 bool status = DoubleToAscii(value, DTOA_FIXED, f,
849 Vector<char>(decimal_rep, kDecimalRepCapacity),
850 &sign, &decimal_rep_length, &decimal_point);
851 USE(status);
852 ASSERT(status);
Steve Blocka7e24c12009-10-30 11:49:00 +0000853
854 // Create a representation that is padded with zeros if needed.
855 int zero_prefix_length = 0;
856 int zero_postfix_length = 0;
857
858 if (decimal_point <= 0) {
859 zero_prefix_length = -decimal_point + 1;
860 decimal_point = 1;
861 }
862
863 if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
864 zero_postfix_length = decimal_point + f - decimal_rep_length -
865 zero_prefix_length;
866 }
867
868 unsigned rep_length =
869 zero_prefix_length + decimal_rep_length + zero_postfix_length;
870 StringBuilder rep_builder(rep_length + 1);
871 rep_builder.AddPadding('0', zero_prefix_length);
872 rep_builder.AddString(decimal_rep);
873 rep_builder.AddPadding('0', zero_postfix_length);
874 char* rep = rep_builder.Finalize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000875
876 // Create the result string by appending a minus and putting in a
877 // decimal point if needed.
878 unsigned result_size = decimal_point + f + 2;
879 StringBuilder builder(result_size + 1);
880 if (negative) builder.AddCharacter('-');
881 builder.AddSubstring(rep, decimal_point);
882 if (f > 0) {
883 builder.AddCharacter('.');
884 builder.AddSubstring(rep + decimal_point, f);
885 }
886 DeleteArray(rep);
887 return builder.Finalize();
888}
889
890
891static char* CreateExponentialRepresentation(char* decimal_rep,
892 int exponent,
893 bool negative,
894 int significant_digits) {
895 bool negative_exponent = false;
896 if (exponent < 0) {
897 negative_exponent = true;
898 exponent = -exponent;
899 }
900
901 // Leave room in the result for appending a minus, for a period, the
902 // letter 'e', a minus or a plus depending on the exponent, and a
903 // three digit exponent.
904 unsigned result_size = significant_digits + 7;
905 StringBuilder builder(result_size + 1);
906
907 if (negative) builder.AddCharacter('-');
908 builder.AddCharacter(decimal_rep[0]);
909 if (significant_digits != 1) {
910 builder.AddCharacter('.');
911 builder.AddString(decimal_rep + 1);
Steve Blockd0582a62009-12-15 09:54:21 +0000912 int rep_length = StrLength(decimal_rep);
913 builder.AddPadding('0', significant_digits - rep_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000914 }
915
916 builder.AddCharacter('e');
917 builder.AddCharacter(negative_exponent ? '-' : '+');
918 builder.AddFormatted("%d", exponent);
919 return builder.Finalize();
920}
921
922
923
924char* DoubleToExponentialCString(double value, int f) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100925 const int kMaxDigitsAfterPoint = 20;
Steve Blocka7e24c12009-10-30 11:49:00 +0000926 // f might be -1 to signal that f was undefined in JavaScript.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100927 ASSERT(f >= -1 && f <= kMaxDigitsAfterPoint);
Steve Blocka7e24c12009-10-30 11:49:00 +0000928
929 bool negative = false;
930 if (value < 0) {
931 value = -value;
932 negative = true;
933 }
934
935 // Find a sufficiently precise decimal representation of n.
936 int decimal_point;
937 int sign;
938 char* decimal_rep = NULL;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100939 bool used_gay_dtoa = false;
940 // f corresponds to the digits after the point. There is always one digit
941 // before the point. The number of requested_digits equals hence f + 1.
942 // And we have to add one character for the null-terminator.
943 const int kV8DtoaBufferCapacity = kMaxDigitsAfterPoint + 1 + 1;
944 // Make sure that the buffer is big enough, even if we fall back to the
945 // shortest representation (which happens when f equals -1).
946 ASSERT(kBase10MaximalLength <= kMaxDigitsAfterPoint + 1);
947 char v8_dtoa_buffer[kV8DtoaBufferCapacity];
948 int decimal_rep_length;
949
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 if (f == -1) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100951 if (DoubleToAscii(value, DTOA_SHORTEST, 0,
952 Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
953 &sign, &decimal_rep_length, &decimal_point)) {
954 f = decimal_rep_length - 1;
955 decimal_rep = v8_dtoa_buffer;
956 } else {
957 decimal_rep = dtoa(value, 0, 0, &decimal_point, &sign, NULL);
958 decimal_rep_length = StrLength(decimal_rep);
959 f = decimal_rep_length - 1;
960 used_gay_dtoa = true;
961 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000962 } else {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100963 if (DoubleToAscii(value, DTOA_PRECISION, f + 1,
964 Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
965 &sign, &decimal_rep_length, &decimal_point)) {
966 decimal_rep = v8_dtoa_buffer;
967 } else {
968 decimal_rep = dtoa(value, 2, f + 1, &decimal_point, &sign, NULL);
969 decimal_rep_length = StrLength(decimal_rep);
970 used_gay_dtoa = true;
971 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000972 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 ASSERT(decimal_rep_length > 0);
974 ASSERT(decimal_rep_length <= f + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000975
976 int exponent = decimal_point - 1;
977 char* result =
978 CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
979
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100980 if (used_gay_dtoa) {
981 freedtoa(decimal_rep);
982 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000983
984 return result;
985}
986
987
988char* DoubleToPrecisionCString(double value, int p) {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100989 const int kMinimalDigits = 1;
990 const int kMaximalDigits = 21;
991 ASSERT(p >= kMinimalDigits && p <= kMaximalDigits);
992 USE(kMinimalDigits);
Steve Blocka7e24c12009-10-30 11:49:00 +0000993
994 bool negative = false;
995 if (value < 0) {
996 value = -value;
997 negative = true;
998 }
999
1000 // Find a sufficiently precise decimal representation of n.
1001 int decimal_point;
1002 int sign;
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001003 char* decimal_rep = NULL;
1004 bool used_gay_dtoa = false;
1005 // Add one for the terminating null character.
1006 const int kV8DtoaBufferCapacity = kMaximalDigits + 1;
1007 char v8_dtoa_buffer[kV8DtoaBufferCapacity];
1008 int decimal_rep_length;
1009
1010 if (DoubleToAscii(value, DTOA_PRECISION, p,
1011 Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
1012 &sign, &decimal_rep_length, &decimal_point)) {
1013 decimal_rep = v8_dtoa_buffer;
1014 } else {
1015 decimal_rep = dtoa(value, 2, p, &decimal_point, &sign, NULL);
1016 decimal_rep_length = StrLength(decimal_rep);
1017 used_gay_dtoa = true;
1018 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 ASSERT(decimal_rep_length <= p);
1020
1021 int exponent = decimal_point - 1;
1022
1023 char* result = NULL;
1024
1025 if (exponent < -6 || exponent >= p) {
1026 result =
1027 CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
1028 } else {
1029 // Use fixed notation.
1030 //
1031 // Leave room in the result for appending a minus, a period and in
1032 // the case where decimal_point is not positive for a zero in
1033 // front of the period.
1034 unsigned result_size = (decimal_point <= 0)
1035 ? -decimal_point + p + 3
1036 : p + 2;
1037 StringBuilder builder(result_size + 1);
1038 if (negative) builder.AddCharacter('-');
1039 if (decimal_point <= 0) {
1040 builder.AddString("0.");
1041 builder.AddPadding('0', -decimal_point);
1042 builder.AddString(decimal_rep);
1043 builder.AddPadding('0', p - decimal_rep_length);
1044 } else {
1045 const int m = Min(decimal_rep_length, decimal_point);
1046 builder.AddSubstring(decimal_rep, m);
1047 builder.AddPadding('0', decimal_point - decimal_rep_length);
1048 if (decimal_point < p) {
1049 builder.AddCharacter('.');
1050 const int extra = negative ? 2 : 1;
1051 if (decimal_rep_length > decimal_point) {
Steve Blockd0582a62009-12-15 09:54:21 +00001052 const int len = StrLength(decimal_rep + decimal_point);
Steve Blocka7e24c12009-10-30 11:49:00 +00001053 const int n = Min(len, p - (builder.position() - extra));
1054 builder.AddSubstring(decimal_rep + decimal_point, n);
1055 }
1056 builder.AddPadding('0', extra + (p - builder.position()));
1057 }
1058 }
1059 result = builder.Finalize();
1060 }
1061
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001062 if (used_gay_dtoa) {
1063 freedtoa(decimal_rep);
1064 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001065 return result;
1066}
1067
1068
1069char* DoubleToRadixCString(double value, int radix) {
1070 ASSERT(radix >= 2 && radix <= 36);
1071
1072 // Character array used for conversion.
1073 static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
1074
1075 // Buffer for the integer part of the result. 1024 chars is enough
1076 // for max integer value in radix 2. We need room for a sign too.
1077 static const int kBufferSize = 1100;
1078 char integer_buffer[kBufferSize];
1079 integer_buffer[kBufferSize - 1] = '\0';
1080
1081 // Buffer for the decimal part of the result. We only generate up
1082 // to kBufferSize - 1 chars for the decimal part.
1083 char decimal_buffer[kBufferSize];
1084 decimal_buffer[kBufferSize - 1] = '\0';
1085
1086 // Make sure the value is positive.
1087 bool is_negative = value < 0.0;
1088 if (is_negative) value = -value;
1089
1090 // Get the integer part and the decimal part.
1091 double integer_part = floor(value);
1092 double decimal_part = value - integer_part;
1093
1094 // Convert the integer part starting from the back. Always generate
1095 // at least one digit.
1096 int integer_pos = kBufferSize - 2;
1097 do {
1098 integer_buffer[integer_pos--] =
Steve Block3ce2e202009-11-05 08:53:23 +00001099 chars[static_cast<int>(modulo(integer_part, radix))];
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 integer_part /= radix;
1101 } while (integer_part >= 1.0);
1102 // Sanity check.
1103 ASSERT(integer_pos > 0);
1104 // Add sign if needed.
1105 if (is_negative) integer_buffer[integer_pos--] = '-';
1106
1107 // Convert the decimal part. Repeatedly multiply by the radix to
1108 // generate the next char. Never generate more than kBufferSize - 1
1109 // chars.
1110 //
1111 // TODO(1093998): We will often generate a full decimal_buffer of
1112 // chars because hitting zero will often not happen. The right
1113 // solution would be to continue until the string representation can
1114 // be read back and yield the original value. To implement this
1115 // efficiently, we probably have to modify dtoa.
1116 int decimal_pos = 0;
1117 while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
1118 decimal_part *= radix;
1119 decimal_buffer[decimal_pos++] =
1120 chars[static_cast<int>(floor(decimal_part))];
1121 decimal_part -= floor(decimal_part);
1122 }
1123 decimal_buffer[decimal_pos] = '\0';
1124
1125 // Compute the result size.
1126 int integer_part_size = kBufferSize - 2 - integer_pos;
1127 // Make room for zero termination.
1128 unsigned result_size = integer_part_size + decimal_pos;
1129 // If the number has a decimal part, leave room for the period.
1130 if (decimal_pos > 0) result_size++;
1131 // Allocate result and fill in the parts.
1132 StringBuilder builder(result_size + 1);
1133 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
1134 if (decimal_pos > 0) builder.AddCharacter('.');
1135 builder.AddSubstring(decimal_buffer, decimal_pos);
1136 return builder.Finalize();
1137}
1138
1139
1140} } // namespace v8::internal