blob: 90cdc773eabba36ecd47b113854d908ac1c4f8a3 [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"
37
38namespace v8 {
39namespace internal {
40
41int HexValue(uc32 c) {
42 if ('0' <= c && c <= '9')
43 return c - '0';
44 if ('a' <= c && c <= 'f')
45 return c - 'a' + 10;
46 if ('A' <= c && c <= 'F')
47 return c - 'A' + 10;
48 return -1;
49}
50
Steve Block6ded16b2010-05-10 14:33:55 +010051namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +000052
Steve Block6ded16b2010-05-10 14:33:55 +010053// C++-style iterator adaptor for StringInputBuffer
54// (unlike C++ iterators the end-marker has different type).
55class StringInputBufferIterator {
56 public:
57 class EndMarker {};
58
59 explicit StringInputBufferIterator(StringInputBuffer* buffer);
60
61 int operator*() const;
62 void operator++();
63 bool operator==(EndMarker const&) const { return end_; }
64 bool operator!=(EndMarker const& m) const { return !end_; }
65
66 private:
67 StringInputBuffer* const buffer_;
68 int current_;
69 bool end_;
70};
71
72
73StringInputBufferIterator::StringInputBufferIterator(
74 StringInputBuffer* buffer) : buffer_(buffer) {
75 ++(*this);
76}
77
78int StringInputBufferIterator::operator*() const {
79 return current_;
Steve Blocka7e24c12009-10-30 11:49:00 +000080}
81
82
Steve Block6ded16b2010-05-10 14:33:55 +010083void StringInputBufferIterator::operator++() {
84 end_ = !buffer_->has_more();
85 if (!end_) {
86 current_ = buffer_->GetNext();
Steve Blocka7e24c12009-10-30 11:49:00 +000087 }
Steve Block6ded16b2010-05-10 14:33:55 +010088}
Steve Blocka7e24c12009-10-30 11:49:00 +000089}
90
91
Steve Block6ded16b2010-05-10 14:33:55 +010092template <class Iterator, class EndMark>
93static bool SubStringEquals(Iterator* current,
94 EndMark end,
95 const char* substring) {
96 ASSERT(**current == *substring);
97 for (substring++; *substring != '\0'; substring++) {
98 ++*current;
99 if (*current == end || **current != *substring) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000100 }
Steve Block6ded16b2010-05-10 14:33:55 +0100101 ++*current;
Steve Blocka7e24c12009-10-30 11:49:00 +0000102 return true;
103}
104
105
106extern "C" double gay_strtod(const char* s00, const char** se);
107
Steve Block6ded16b2010-05-10 14:33:55 +0100108// Maximum number of significant digits in decimal representation.
109// The longest possible double in decimal representation is
110// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
111// (768 digits). If we parse a number whose first digits are equal to a
112// mean of 2 adjacent doubles (that could have up to 769 digits) the result
113// must be rounded to the bigger one unless the tail consists of zeros, so
114// we don't need to preserve all the digits.
115const int kMaxSignificantDigits = 772;
Steve Blocka7e24c12009-10-30 11:49:00 +0000116
Steve Blocka7e24c12009-10-30 11:49:00 +0000117
Steve Block6ded16b2010-05-10 14:33:55 +0100118static const double JUNK_STRING_VALUE = OS::nan_value();
119
120
121// Returns true if a nonspace found and false if the end has reached.
122template <class Iterator, class EndMark>
123static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
124 while (*current != end) {
125 if (!Scanner::kIsWhiteSpace.get(**current)) return true;
126 ++*current;
127 }
128 return false;
129}
130
131
132static bool isDigit(int x, int radix) {
133 return (x >= '0' && x <= '9' && x < '0' + radix)
134 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
135 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
136}
137
138
139static double SignedZero(bool sign) {
140 return sign ? -0.0 : 0.0;
141}
142
143
144// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
145template <int radix_log_2, class Iterator, class EndMark>
146static double InternalStringToIntDouble(Iterator current,
147 EndMark end,
148 bool sign,
149 bool allow_trailing_junk) {
150 ASSERT(current != end);
151
152 // Skip leading 0s.
153 while (*current == '0') {
154 ++current;
155 if (current == end) return SignedZero(sign);
156 }
157
158 int64_t number = 0;
159 int exponent = 0;
160 const int radix = (1 << radix_log_2);
161
162 do {
163 int digit;
164 if (*current >= '0' && *current <= '9' && *current < '0' + radix) {
165 digit = static_cast<char>(*current) - '0';
166 } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) {
167 digit = static_cast<char>(*current) - 'a' + 10;
168 } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) {
169 digit = static_cast<char>(*current) - 'A' + 10;
170 } else {
171 if (allow_trailing_junk || !AdvanceToNonspace(&current, end)) {
172 break;
173 } else {
174 return JUNK_STRING_VALUE;
175 }
176 }
177
178 number = number * radix + digit;
179 int overflow = static_cast<int>(number >> 53);
180 if (overflow != 0) {
181 // Overflow occurred. Need to determine which direction to round the
182 // result.
183 int overflow_bits_count = 1;
184 while (overflow > 1) {
185 overflow_bits_count++;
186 overflow >>= 1;
187 }
188
189 int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
190 int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
191 number >>= overflow_bits_count;
192 exponent = overflow_bits_count;
193
194 bool zero_tail = true;
195 while (true) {
196 ++current;
197 if (current == end || !isDigit(*current, radix)) break;
198 zero_tail = zero_tail && *current == '0';
199 exponent += radix_log_2;
200 }
201
202 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
203 return JUNK_STRING_VALUE;
204 }
205
206 int middle_value = (1 << (overflow_bits_count - 1));
207 if (dropped_bits > middle_value) {
208 number++; // Rounding up.
209 } else if (dropped_bits == middle_value) {
210 // Rounding to even to consistency with decimals: half-way case rounds
211 // up if significant part is odd and down otherwise.
212 if ((number & 1) != 0 || !zero_tail) {
213 number++; // Rounding up.
214 }
215 }
216
217 // Rounding up may cause overflow.
218 if ((number & ((int64_t)1 << 53)) != 0) {
219 exponent++;
220 number >>= 1;
221 }
222 break;
223 }
224 ++current;
225 } while (current != end);
226
227 ASSERT(number < ((int64_t)1 << 53));
228 ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
229
230 if (exponent == 0) {
231 if (sign) {
232 if (number == 0) return -0.0;
233 number = -number;
234 }
235 return static_cast<double>(number);
236 }
237
238 ASSERT(number != 0);
239 // The double could be constructed faster from number (mantissa), exponent
240 // and sign. Assuming it's a rare case more simple code is used.
241 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent);
242}
243
244
245template <class Iterator, class EndMark>
246static double InternalStringToInt(Iterator current, EndMark end, int radix) {
247 const bool allow_trailing_junk = true;
248 const double empty_string_val = JUNK_STRING_VALUE;
249
250 if (!AdvanceToNonspace(&current, end)) return empty_string_val;
251
252 bool sign = false;
253 bool leading_zero = false;
254
255 if (*current == '+') {
256 // Ignore leading sign; skip following spaces.
257 ++current;
258 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
259 } else if (*current == '-') {
260 ++current;
261 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
262 sign = true;
263 }
264
265 if (radix == 0) {
266 // Radix detection.
267 if (*current == '0') {
268 ++current;
269 if (current == end) return SignedZero(sign);
270 if (*current == 'x' || *current == 'X') {
271 radix = 16;
272 ++current;
273 if (current == end) return JUNK_STRING_VALUE;
274 } else {
275 radix = 8;
276 leading_zero = true;
277 }
278 } else {
279 radix = 10;
280 }
281 } else if (radix == 16) {
282 if (*current == '0') {
283 // Allow "0x" prefix.
284 ++current;
285 if (current == end) return SignedZero(sign);
286 if (*current == 'x' || *current == 'X') {
287 ++current;
288 if (current == end) return JUNK_STRING_VALUE;
289 } else {
290 leading_zero = true;
291 }
292 }
293 }
294
295 if (radix < 2 || radix > 36) return JUNK_STRING_VALUE;
296
297 // Skip leading zeros.
298 while (*current == '0') {
299 leading_zero = true;
300 ++current;
301 if (current == end) return SignedZero(sign);
302 }
303
304 if (!leading_zero && !isDigit(*current, radix)) {
305 return JUNK_STRING_VALUE;
306 }
307
308 if (IsPowerOf2(radix)) {
309 switch (radix) {
310 case 2:
311 return InternalStringToIntDouble<1>(
312 current, end, sign, allow_trailing_junk);
313 case 4:
314 return InternalStringToIntDouble<2>(
315 current, end, sign, allow_trailing_junk);
316 case 8:
317 return InternalStringToIntDouble<3>(
318 current, end, sign, allow_trailing_junk);
319
320 case 16:
321 return InternalStringToIntDouble<4>(
322 current, end, sign, allow_trailing_junk);
323
324 case 32:
325 return InternalStringToIntDouble<5>(
326 current, end, sign, allow_trailing_junk);
327 default:
328 UNREACHABLE();
329 }
330 }
331
332 if (radix == 10) {
333 // Parsing with strtod.
334 const int kMaxSignificantDigits = 309; // Doubles are less than 1.8e308.
335 // The buffer may contain up to kMaxSignificantDigits + 1 digits and a zero
336 // end.
337 const int kBufferSize = kMaxSignificantDigits + 2;
338 char buffer[kBufferSize];
339 int buffer_pos = 0;
340 while (*current >= '0' && *current <= '9') {
341 if (buffer_pos <= kMaxSignificantDigits) {
342 // If the number has more than kMaxSignificantDigits it will be parsed
343 // as infinity.
344 ASSERT(buffer_pos < kBufferSize);
345 buffer[buffer_pos++] = static_cast<char>(*current);
346 }
347 ++current;
348 if (current == end) break;
349 }
350
351 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
352 return JUNK_STRING_VALUE;
353 }
354
355 ASSERT(buffer_pos < kBufferSize);
356 buffer[buffer_pos++] = '\0';
357 return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL);
358 }
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 == '-') {
465 buffer[buffer_pos++] = '-';
466 ++current;
467 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
468 sign = true;
469 }
470
471 static const char kInfinitySymbol[] = "Infinity";
472 if (*current == kInfinitySymbol[0]) {
473 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
474 return JUNK_STRING_VALUE;
475 }
476
477 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
478 return JUNK_STRING_VALUE;
479 }
480
481 ASSERT(buffer_pos == 0 || buffer[0] == '-');
482 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY;
483 }
484
485 bool leading_zero = false;
486 if (*current == '0') {
487 ++current;
488 if (current == end) return SignedZero(sign);
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)) {
496 return JUNK_STRING_VALUE; // "0x".
497 }
498
499 bool sign = (buffer_pos > 0 && buffer[0] == '-');
500 return InternalStringToIntDouble<4>(current,
501 end,
502 sign,
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(sign);
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 == '.') {
536 ++current;
537 if (current == end) {
538 if (significant_digits == 0 && !leading_zero) {
539 return JUNK_STRING_VALUE;
540 } else {
541 goto parsing_done;
542 }
543 }
544
545 if (significant_digits == 0) {
546 // octal = false;
547 // Integer part consists of 0 or is absent. Significant digits start after
548 // leading zeros (if any).
549 while (*current == '0') {
550 ++current;
551 if (current == end) return SignedZero(sign);
552 exponent--; // Move this 0 into the exponent.
553 }
554 }
555
556 ASSERT(buffer_pos < kBufferSize);
557 buffer[buffer_pos++] = '.';
558 fractional_part = true;
559
560 // There is the fractional part.
561 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 } else {
567 // Ignore insignificant digits in the fractional part.
568 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
569 }
570 ++current;
571 if (current == end) goto parsing_done;
572 }
573 }
574
575 if (!leading_zero && exponent == 0 && significant_digits == 0) {
576 // If leading_zeros is true then the string contains zeros.
577 // If exponent < 0 then string was [+-]\.0*...
578 // If significant_digits != 0 the string is not equal to 0.
579 // Otherwise there are no digits in the string.
580 return JUNK_STRING_VALUE;
581 }
582
583 // Parse exponential part.
584 if (*current == 'e' || *current == 'E') {
585 if (octal) return JUNK_STRING_VALUE;
586 ++current;
587 if (current == end) {
588 if (allow_trailing_junk) {
589 goto parsing_done;
590 } else {
591 return JUNK_STRING_VALUE;
592 }
593 }
594 char sign = '+';
595 if (*current == '+' || *current == '-') {
596 sign = static_cast<char>(*current);
597 ++current;
598 if (current == end) {
599 if (allow_trailing_junk) {
600 goto parsing_done;
601 } else {
602 return JUNK_STRING_VALUE;
603 }
604 }
605 }
606
607 if (current == end || *current < '0' || *current > '9') {
608 if (allow_trailing_junk) {
609 goto parsing_done;
610 } else {
611 return JUNK_STRING_VALUE;
612 }
613 }
614
615 const int max_exponent = INT_MAX / 2;
616 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
617 int num = 0;
618 do {
619 // Check overflow.
620 int digit = *current - '0';
621 if (num >= max_exponent / 10
622 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
623 num = max_exponent;
624 } else {
625 num = num * 10 + digit;
626 }
627 ++current;
628 } while (current != end && *current >= '0' && *current <= '9');
629
630 exponent += (sign == '-' ? -num : num);
631 }
632
633 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
634 return JUNK_STRING_VALUE;
635 }
636
637 parsing_done:
638 exponent += insignificant_digits;
639
640 if (octal) {
641 bool sign = buffer[0] == '-';
642 int start_pos = (sign ? 1 : 0);
643
644 return InternalStringToIntDouble<3>(buffer + start_pos,
645 buffer + buffer_pos,
646 sign,
647 allow_trailing_junk);
648 }
649
650 if (nonzero_digit_dropped) {
651 if (insignificant_digits) buffer[buffer_pos++] = '.';
652 buffer[buffer_pos++] = '1';
653 }
654
655 // If the number has no more than kMaxDigitsInInt digits and doesn't have
656 // fractional part it could be parsed faster (without checks for
657 // spaces, overflow, etc.).
658 const int kMaxDigitsInInt = 9 * sizeof(int) / 4; // NOLINT
659
660 if (exponent != 0) {
661 ASSERT(buffer_pos < kBufferSize);
662 buffer[buffer_pos++] = 'e';
663 if (exponent < 0) {
664 ASSERT(buffer_pos < kBufferSize);
665 buffer[buffer_pos++] = '-';
666 exponent = -exponent;
667 }
668 if (exponent > 999) exponent = 999; // Result will be Infinity or 0 or -0.
669
670 const int exp_digits = 3;
671 for (int i = 0; i < exp_digits; i++) {
672 buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10;
673 exponent /= 10;
674 }
675 ASSERT(exponent == 0);
676 buffer_pos += exp_digits;
677 } else if (!fractional_part && significant_digits <= kMaxDigitsInInt) {
678 if (significant_digits == 0) return SignedZero(sign);
679 ASSERT(buffer_pos > 0);
680 int num = 0;
681 int start_pos = (buffer[0] == '-' ? 1 : 0);
682 for (int i = start_pos; i < buffer_pos; i++) {
683 ASSERT(buffer[i] >= '0' && buffer[i] <= '9');
684 num = 10 * num + (buffer[i] - '0');
685 }
686 return static_cast<double>(start_pos == 0 ? num : -num);
687 }
688
689 ASSERT(buffer_pos < kBufferSize);
690 buffer[buffer_pos] = '\0';
691
692 return gay_strtod(buffer, NULL);
693}
694
Steve Blocka7e24c12009-10-30 11:49:00 +0000695double StringToDouble(String* str, int flags, double empty_string_val) {
Steve Block6ded16b2010-05-10 14:33:55 +0100696 StringShape shape(str);
697 if (shape.IsSequentialAscii()) {
698 const char* begin = SeqAsciiString::cast(str)->GetChars();
699 const char* end = begin + str->length();
700 return InternalStringToDouble(begin, end, flags, empty_string_val);
701 } else if (shape.IsSequentialTwoByte()) {
702 const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
703 const uc16* end = begin + str->length();
704 return InternalStringToDouble(begin, end, flags, empty_string_val);
705 } else {
706 StringInputBuffer buffer(str);
707 return InternalStringToDouble(StringInputBufferIterator(&buffer),
708 StringInputBufferIterator::EndMarker(),
709 flags,
710 empty_string_val);
711 }
712}
713
714
715double StringToInt(String* str, int radix) {
716 StringShape shape(str);
717 if (shape.IsSequentialAscii()) {
718 const char* begin = SeqAsciiString::cast(str)->GetChars();
719 const char* end = begin + str->length();
720 return InternalStringToInt(begin, end, radix);
721 } else if (shape.IsSequentialTwoByte()) {
722 const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
723 const uc16* end = begin + str->length();
724 return InternalStringToInt(begin, end, radix);
725 } else {
726 StringInputBuffer buffer(str);
727 return InternalStringToInt(StringInputBufferIterator(&buffer),
728 StringInputBufferIterator::EndMarker(),
729 radix);
730 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000731}
732
733
734double StringToDouble(const char* str, int flags, double empty_string_val) {
Steve Block6ded16b2010-05-10 14:33:55 +0100735 const char* end = str + StrLength(str);
Steve Block6ded16b2010-05-10 14:33:55 +0100736 return InternalStringToDouble(str, end, flags, empty_string_val);
Steve Blocka7e24c12009-10-30 11:49:00 +0000737}
738
739
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100740double StringToDouble(Vector<const char> str,
741 int flags,
742 double empty_string_val) {
743 const char* end = str.start() + str.length();
744 return InternalStringToDouble(str.start(), end, flags, empty_string_val);
745}
746
747
Steve Blocka7e24c12009-10-30 11:49:00 +0000748extern "C" char* dtoa(double d, int mode, int ndigits,
749 int* decpt, int* sign, char** rve);
750
751extern "C" void freedtoa(char* s);
752
753const char* DoubleToCString(double v, Vector<char> buffer) {
754 StringBuilder builder(buffer.start(), buffer.length());
755
756 switch (fpclassify(v)) {
757 case FP_NAN:
758 builder.AddString("NaN");
759 break;
760
761 case FP_INFINITE:
762 if (v < 0.0) {
763 builder.AddString("-Infinity");
764 } else {
765 builder.AddString("Infinity");
766 }
767 break;
768
769 case FP_ZERO:
770 builder.AddCharacter('0');
771 break;
772
773 default: {
774 int decimal_point;
775 int sign;
Steve Block6ded16b2010-05-10 14:33:55 +0100776 char* decimal_rep;
777 bool used_gay_dtoa = false;
Kristian Monsen25f61362010-05-21 11:50:48 +0100778 const int kV8DtoaBufferCapacity = kBase10MaximalLength + 1;
779 char v8_dtoa_buffer[kV8DtoaBufferCapacity];
Steve Block6ded16b2010-05-10 14:33:55 +0100780 int length;
Kristian Monsen25f61362010-05-21 11:50:48 +0100781
782 if (DoubleToAscii(v, DTOA_SHORTEST, 0,
783 Vector<char>(v8_dtoa_buffer, kV8DtoaBufferCapacity),
784 &sign, &length, &decimal_point)) {
785 decimal_rep = v8_dtoa_buffer;
Steve Block6ded16b2010-05-10 14:33:55 +0100786 } else {
787 decimal_rep = dtoa(v, 0, 0, &decimal_point, &sign, NULL);
788 used_gay_dtoa = true;
789 length = StrLength(decimal_rep);
790 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000791
792 if (sign) builder.AddCharacter('-');
793
794 if (length <= decimal_point && decimal_point <= 21) {
795 // ECMA-262 section 9.8.1 step 6.
796 builder.AddString(decimal_rep);
797 builder.AddPadding('0', decimal_point - length);
798
799 } else if (0 < decimal_point && decimal_point <= 21) {
800 // ECMA-262 section 9.8.1 step 7.
801 builder.AddSubstring(decimal_rep, decimal_point);
802 builder.AddCharacter('.');
803 builder.AddString(decimal_rep + decimal_point);
804
805 } else if (decimal_point <= 0 && decimal_point > -6) {
806 // ECMA-262 section 9.8.1 step 8.
807 builder.AddString("0.");
808 builder.AddPadding('0', -decimal_point);
809 builder.AddString(decimal_rep);
810
811 } else {
812 // ECMA-262 section 9.8.1 step 9 and 10 combined.
813 builder.AddCharacter(decimal_rep[0]);
814 if (length != 1) {
815 builder.AddCharacter('.');
816 builder.AddString(decimal_rep + 1);
817 }
818 builder.AddCharacter('e');
819 builder.AddCharacter((decimal_point >= 0) ? '+' : '-');
820 int exponent = decimal_point - 1;
821 if (exponent < 0) exponent = -exponent;
822 builder.AddFormatted("%d", exponent);
823 }
824
Steve Block6ded16b2010-05-10 14:33:55 +0100825 if (used_gay_dtoa) freedtoa(decimal_rep);
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 }
827 }
828 return builder.Finalize();
829}
830
831
832const char* IntToCString(int n, Vector<char> buffer) {
833 bool negative = false;
834 if (n < 0) {
835 // We must not negate the most negative int.
836 if (n == kMinInt) return DoubleToCString(n, buffer);
837 negative = true;
838 n = -n;
839 }
840 // Build the string backwards from the least significant digit.
841 int i = buffer.length();
842 buffer[--i] = '\0';
843 do {
844 buffer[--i] = '0' + (n % 10);
845 n /= 10;
846 } while (n);
847 if (negative) buffer[--i] = '-';
848 return buffer.start() + i;
849}
850
851
852char* DoubleToFixedCString(double value, int f) {
Kristian Monsen25f61362010-05-21 11:50:48 +0100853 const int kMaxDigitsBeforePoint = 20;
854 const double kFirstNonFixed = 1e21;
855 const int kMaxDigitsAfterPoint = 20;
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 ASSERT(f >= 0);
Kristian Monsen25f61362010-05-21 11:50:48 +0100857 ASSERT(f <= kMaxDigitsAfterPoint);
Steve Blocka7e24c12009-10-30 11:49:00 +0000858
859 bool negative = false;
860 double abs_value = value;
861 if (value < 0) {
862 abs_value = -value;
863 negative = true;
864 }
865
Kristian Monsen25f61362010-05-21 11:50:48 +0100866 // If abs_value has more than kMaxDigitsBeforePoint digits before the point
867 // use the non-fixed conversion routine.
868 if (abs_value >= kFirstNonFixed) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000869 char arr[100];
870 Vector<char> buffer(arr, ARRAY_SIZE(arr));
871 return StrDup(DoubleToCString(value, buffer));
872 }
873
874 // Find a sufficiently precise decimal representation of n.
875 int decimal_point;
876 int sign;
Kristian Monsen25f61362010-05-21 11:50:48 +0100877 // Add space for the '.' and the '\0' byte.
878 const int kDecimalRepCapacity =
879 kMaxDigitsBeforePoint + kMaxDigitsAfterPoint + 2;
880 char decimal_rep[kDecimalRepCapacity];
881 int decimal_rep_length;
882 bool status = DoubleToAscii(value, DTOA_FIXED, f,
883 Vector<char>(decimal_rep, kDecimalRepCapacity),
884 &sign, &decimal_rep_length, &decimal_point);
885 USE(status);
886 ASSERT(status);
Steve Blocka7e24c12009-10-30 11:49:00 +0000887
888 // Create a representation that is padded with zeros if needed.
889 int zero_prefix_length = 0;
890 int zero_postfix_length = 0;
891
892 if (decimal_point <= 0) {
893 zero_prefix_length = -decimal_point + 1;
894 decimal_point = 1;
895 }
896
897 if (zero_prefix_length + decimal_rep_length < decimal_point + f) {
898 zero_postfix_length = decimal_point + f - decimal_rep_length -
899 zero_prefix_length;
900 }
901
902 unsigned rep_length =
903 zero_prefix_length + decimal_rep_length + zero_postfix_length;
904 StringBuilder rep_builder(rep_length + 1);
905 rep_builder.AddPadding('0', zero_prefix_length);
906 rep_builder.AddString(decimal_rep);
907 rep_builder.AddPadding('0', zero_postfix_length);
908 char* rep = rep_builder.Finalize();
Steve Blocka7e24c12009-10-30 11:49:00 +0000909
910 // Create the result string by appending a minus and putting in a
911 // decimal point if needed.
912 unsigned result_size = decimal_point + f + 2;
913 StringBuilder builder(result_size + 1);
914 if (negative) builder.AddCharacter('-');
915 builder.AddSubstring(rep, decimal_point);
916 if (f > 0) {
917 builder.AddCharacter('.');
918 builder.AddSubstring(rep + decimal_point, f);
919 }
920 DeleteArray(rep);
921 return builder.Finalize();
922}
923
924
925static char* CreateExponentialRepresentation(char* decimal_rep,
926 int exponent,
927 bool negative,
928 int significant_digits) {
929 bool negative_exponent = false;
930 if (exponent < 0) {
931 negative_exponent = true;
932 exponent = -exponent;
933 }
934
935 // Leave room in the result for appending a minus, for a period, the
936 // letter 'e', a minus or a plus depending on the exponent, and a
937 // three digit exponent.
938 unsigned result_size = significant_digits + 7;
939 StringBuilder builder(result_size + 1);
940
941 if (negative) builder.AddCharacter('-');
942 builder.AddCharacter(decimal_rep[0]);
943 if (significant_digits != 1) {
944 builder.AddCharacter('.');
945 builder.AddString(decimal_rep + 1);
Steve Blockd0582a62009-12-15 09:54:21 +0000946 int rep_length = StrLength(decimal_rep);
947 builder.AddPadding('0', significant_digits - rep_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000948 }
949
950 builder.AddCharacter('e');
951 builder.AddCharacter(negative_exponent ? '-' : '+');
952 builder.AddFormatted("%d", exponent);
953 return builder.Finalize();
954}
955
956
957
958char* DoubleToExponentialCString(double value, int f) {
959 // f might be -1 to signal that f was undefined in JavaScript.
960 ASSERT(f >= -1 && f <= 20);
961
962 bool negative = false;
963 if (value < 0) {
964 value = -value;
965 negative = true;
966 }
967
968 // Find a sufficiently precise decimal representation of n.
969 int decimal_point;
970 int sign;
971 char* decimal_rep = NULL;
972 if (f == -1) {
973 decimal_rep = dtoa(value, 0, 0, &decimal_point, &sign, NULL);
Steve Blockd0582a62009-12-15 09:54:21 +0000974 f = StrLength(decimal_rep) - 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 } else {
976 decimal_rep = dtoa(value, 2, f + 1, &decimal_point, &sign, NULL);
977 }
Steve Blockd0582a62009-12-15 09:54:21 +0000978 int decimal_rep_length = StrLength(decimal_rep);
Steve Blocka7e24c12009-10-30 11:49:00 +0000979 ASSERT(decimal_rep_length > 0);
980 ASSERT(decimal_rep_length <= f + 1);
981 USE(decimal_rep_length);
982
983 int exponent = decimal_point - 1;
984 char* result =
985 CreateExponentialRepresentation(decimal_rep, exponent, negative, f+1);
986
987 freedtoa(decimal_rep);
988
989 return result;
990}
991
992
993char* DoubleToPrecisionCString(double value, int p) {
994 ASSERT(p >= 1 && p <= 21);
995
996 bool negative = false;
997 if (value < 0) {
998 value = -value;
999 negative = true;
1000 }
1001
1002 // Find a sufficiently precise decimal representation of n.
1003 int decimal_point;
1004 int sign;
1005 char* decimal_rep = dtoa(value, 2, p, &decimal_point, &sign, NULL);
Steve Blockd0582a62009-12-15 09:54:21 +00001006 int decimal_rep_length = StrLength(decimal_rep);
Steve Blocka7e24c12009-10-30 11:49:00 +00001007 ASSERT(decimal_rep_length <= p);
1008
1009 int exponent = decimal_point - 1;
1010
1011 char* result = NULL;
1012
1013 if (exponent < -6 || exponent >= p) {
1014 result =
1015 CreateExponentialRepresentation(decimal_rep, exponent, negative, p);
1016 } else {
1017 // Use fixed notation.
1018 //
1019 // Leave room in the result for appending a minus, a period and in
1020 // the case where decimal_point is not positive for a zero in
1021 // front of the period.
1022 unsigned result_size = (decimal_point <= 0)
1023 ? -decimal_point + p + 3
1024 : p + 2;
1025 StringBuilder builder(result_size + 1);
1026 if (negative) builder.AddCharacter('-');
1027 if (decimal_point <= 0) {
1028 builder.AddString("0.");
1029 builder.AddPadding('0', -decimal_point);
1030 builder.AddString(decimal_rep);
1031 builder.AddPadding('0', p - decimal_rep_length);
1032 } else {
1033 const int m = Min(decimal_rep_length, decimal_point);
1034 builder.AddSubstring(decimal_rep, m);
1035 builder.AddPadding('0', decimal_point - decimal_rep_length);
1036 if (decimal_point < p) {
1037 builder.AddCharacter('.');
1038 const int extra = negative ? 2 : 1;
1039 if (decimal_rep_length > decimal_point) {
Steve Blockd0582a62009-12-15 09:54:21 +00001040 const int len = StrLength(decimal_rep + decimal_point);
Steve Blocka7e24c12009-10-30 11:49:00 +00001041 const int n = Min(len, p - (builder.position() - extra));
1042 builder.AddSubstring(decimal_rep + decimal_point, n);
1043 }
1044 builder.AddPadding('0', extra + (p - builder.position()));
1045 }
1046 }
1047 result = builder.Finalize();
1048 }
1049
1050 freedtoa(decimal_rep);
1051 return result;
1052}
1053
1054
1055char* DoubleToRadixCString(double value, int radix) {
1056 ASSERT(radix >= 2 && radix <= 36);
1057
1058 // Character array used for conversion.
1059 static const char chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
1060
1061 // Buffer for the integer part of the result. 1024 chars is enough
1062 // for max integer value in radix 2. We need room for a sign too.
1063 static const int kBufferSize = 1100;
1064 char integer_buffer[kBufferSize];
1065 integer_buffer[kBufferSize - 1] = '\0';
1066
1067 // Buffer for the decimal part of the result. We only generate up
1068 // to kBufferSize - 1 chars for the decimal part.
1069 char decimal_buffer[kBufferSize];
1070 decimal_buffer[kBufferSize - 1] = '\0';
1071
1072 // Make sure the value is positive.
1073 bool is_negative = value < 0.0;
1074 if (is_negative) value = -value;
1075
1076 // Get the integer part and the decimal part.
1077 double integer_part = floor(value);
1078 double decimal_part = value - integer_part;
1079
1080 // Convert the integer part starting from the back. Always generate
1081 // at least one digit.
1082 int integer_pos = kBufferSize - 2;
1083 do {
1084 integer_buffer[integer_pos--] =
Steve Block3ce2e202009-11-05 08:53:23 +00001085 chars[static_cast<int>(modulo(integer_part, radix))];
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 integer_part /= radix;
1087 } while (integer_part >= 1.0);
1088 // Sanity check.
1089 ASSERT(integer_pos > 0);
1090 // Add sign if needed.
1091 if (is_negative) integer_buffer[integer_pos--] = '-';
1092
1093 // Convert the decimal part. Repeatedly multiply by the radix to
1094 // generate the next char. Never generate more than kBufferSize - 1
1095 // chars.
1096 //
1097 // TODO(1093998): We will often generate a full decimal_buffer of
1098 // chars because hitting zero will often not happen. The right
1099 // solution would be to continue until the string representation can
1100 // be read back and yield the original value. To implement this
1101 // efficiently, we probably have to modify dtoa.
1102 int decimal_pos = 0;
1103 while ((decimal_part > 0.0) && (decimal_pos < kBufferSize - 1)) {
1104 decimal_part *= radix;
1105 decimal_buffer[decimal_pos++] =
1106 chars[static_cast<int>(floor(decimal_part))];
1107 decimal_part -= floor(decimal_part);
1108 }
1109 decimal_buffer[decimal_pos] = '\0';
1110
1111 // Compute the result size.
1112 int integer_part_size = kBufferSize - 2 - integer_pos;
1113 // Make room for zero termination.
1114 unsigned result_size = integer_part_size + decimal_pos;
1115 // If the number has a decimal part, leave room for the period.
1116 if (decimal_pos > 0) result_size++;
1117 // Allocate result and fill in the parts.
1118 StringBuilder builder(result_size + 1);
1119 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
1120 if (decimal_pos > 0) builder.AddCharacter('.');
1121 builder.AddSubstring(decimal_buffer, decimal_pos);
1122 return builder.Finalize();
1123}
1124
1125
1126} } // namespace v8::internal