Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: src/conversions.cc

Issue 1216005: StringToDouble rewritten not using String::Get and memory allocations.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/cctest/test-conversions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdarg.h> 28 #include <stdarg.h>
29 #include <limits.h>
29 30
30 #include "v8.h" 31 #include "v8.h"
31 32
32 #include "conversions-inl.h" 33 #include "conversions-inl.h"
33 #include "factory.h" 34 #include "factory.h"
34 #include "fast-dtoa.h" 35 #include "fast-dtoa.h"
35 #include "scanner.h" 36 #include "scanner.h"
36 37
37 namespace v8 { 38 namespace v8 {
38 namespace internal { 39 namespace internal {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 result[i - index] = static_cast<char>(c); 86 result[i - index] = static_cast<char>(c);
86 } else { 87 } else {
87 result[i - index] = 127; // Force number parsing to fail. 88 result[i - index] = 127; // Force number parsing to fail.
88 } 89 }
89 } 90 }
90 result[length - index] = '\0'; 91 result[length - index] = '\0';
91 return result; 92 return result;
92 } 93 }
93 94
94 95
96 namespace {
97
98 // C++-style iterator adaptor for StringInputBuffer
99 // (unlike C++ iterators the end-marker has different type).
100 class StringInputBufferIterator {
101 public:
102 class EndMarker {};
103
104 explicit StringInputBufferIterator(StringInputBuffer* buffer);
105
106 int operator*() const;
107 void operator++();
108 bool operator==(EndMarker const&) const { return end_; }
109 bool operator!=(EndMarker const& m) const { return !end_; }
110
111 private:
112 StringInputBuffer* const buffer_;
113 int current_;
114 bool end_;
115 };
116
117
118 StringInputBufferIterator::StringInputBufferIterator(
119 StringInputBuffer* buffer) : buffer_(buffer) {
120 ++(*this);
121 }
122
123 int StringInputBufferIterator::operator*() const {
124 return current_;
125 }
126
127
128 void StringInputBufferIterator::operator++() {
129 end_ = !buffer_->has_more();
130 if (!end_) {
131 current_ = buffer_->GetNext();
132 }
133 }
134 }
135
136
95 static inline void ReleaseCString(const char* original, const char* str) { 137 static inline void ReleaseCString(const char* original, const char* str) {
96 } 138 }
97 139
98 140
99 static inline void ReleaseCString(String* original, const char* str) { 141 static inline void ReleaseCString(String* original, const char* str) {
100 DeleteArray(const_cast<char *>(str)); 142 DeleteArray(const_cast<char *>(str));
101 } 143 }
102 144
103 145
104 static inline bool IsSpace(const char* str, int index) { 146 template <class Iterator, class EndMark>
105 ASSERT(index >= 0 && index < StrLength(str)); 147 static bool SubStringEquals(Iterator* current,
106 return Scanner::kIsWhiteSpace.get(str[index]); 148 EndMark end,
107 } 149 const char* substring) {
108 150 ASSERT(**current == *substring);
109 151 for (substring++; *substring != '\0'; substring++) {
110 static inline bool IsSpace(String* str, int index) { 152 ++*current;
111 return Scanner::kIsWhiteSpace.get(str->Get(index)); 153 if (*current == end || **current != *substring) return false;
112 }
113
114
115 static inline bool SubStringEquals(const char* str,
116 int index,
117 const char* other) {
118 return strncmp(str + index, other, strlen(other)) != 0;
119 }
120
121
122 static inline bool SubStringEquals(String* str, int index, const char* other) {
123 HandleScope scope;
124 int str_length = str->length();
125 int other_length = StrLength(other);
126 int end = index + other_length < str_length ?
127 index + other_length :
128 str_length;
129 Handle<String> substring =
130 Factory::NewSubString(Handle<String>(str), index, end);
131 return substring->IsEqualTo(Vector<const char>(other, other_length));
132 }
133
134
135 // Check if a string should be parsed as an octal number. The string
136 // can be either a char* or a String*.
137 template<class S>
138 static bool ShouldParseOctal(S* s, int i) {
139 int index = i;
140 int len = GetLength(s);
141 if (index < len && GetChar(s, index) != '0') return false;
142
143 // If the first real character (following '0') is not an octal
144 // digit, bail out early. This also takes care of numbers of the
145 // forms 0.xxx and 0exxx by not allowing the first 0 to be
146 // interpreted as an octal.
147 index++;
148 if (index < len) {
149 int d = GetChar(s, index) - '0';
150 if (d < 0 || d > 7) return false;
151 } else {
152 return false;
153 } 154 }
154 155 ++*current;
155 // Traverse all digits (including the first). If there is an octal
156 // prefix which is not a part of a longer decimal prefix, we return
157 // true. Otherwise, false is returned.
158 while (index < len) {
159 int d = GetChar(s, index++) - '0';
160 if (d == 8 || d == 9) return false;
161 if (d < 0 || d > 7) return true;
162 }
163 return true; 156 return true;
164 } 157 }
165 158
166 159
167 extern "C" double gay_strtod(const char* s00, const char** se); 160 extern "C" double gay_strtod(const char* s00, const char** se);
168 161
162 // Maximum number of significant digits in decimal representation.
163 // The longest possible double in decimal representation is
164 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
165 // (768 digits). If we parse a number whose first digits are equal to a
166 // mean of 2 adjacent doubles (that could have up to 769 digits) the result
167 // must be rounded to the bigger one unless the tail consists of zeros, so
168 // we don't need to preserve all the digits.
169 const int kMaxSignificantDigits = 772;
169 170
170 // Parse an int from a string starting a given index and in a given 171 // Parse an int from a string starting a given index and in a given
171 // radix. The string can be either a char* or a String*. 172 // radix. The string can be either a char* or a String*.
172 template <class S> 173 template <class S>
173 static int InternalStringToInt(S* s, int i, int radix, double* value) { 174 static int InternalStringToInt(S* s, int i, int radix, double* value) {
174 int len = GetLength(s); 175 int len = GetLength(s);
175 176
176 // Setup limits for computing the value. 177 // Setup limits for computing the value.
177 ASSERT(2 <= radix && radix <= 36); 178 ASSERT(2 <= radix && radix <= 36);
178 int lim_0 = '0' + (radix < 10 ? radix : 10); 179 int lim_0 = '0' + (radix < 10 ? radix : 10);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 256
256 257
257 int StringToInt(const char* str, int index, int radix, double* value) { 258 int StringToInt(const char* str, int index, int radix, double* value) {
258 return InternalStringToInt(const_cast<char*>(str), index, radix, value); 259 return InternalStringToInt(const_cast<char*>(str), index, radix, value);
259 } 260 }
260 261
261 262
262 static const double JUNK_STRING_VALUE = OS::nan_value(); 263 static const double JUNK_STRING_VALUE = OS::nan_value();
263 264
264 265
265 // Convert a string to a double value. The string can be either a 266 // Returns true if a nonspace found and false if the end has reached.
266 // char* or a String*. 267 template <class Iterator, class EndMark>
267 template<class S> 268 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) {
268 static double InternalStringToDouble(S* str, 269 while (*current != end) {
270 if (!Scanner::kIsWhiteSpace.get(**current)) return true;
271 ++*current;
272 }
273 return false;
274 }
275
276
277 template <class Iterator, class EndMark>
278 static double InternalHexadecimalStringToDouble(Iterator current,
279 EndMark end,
280 char* buffer,
281 bool allow_trailing_junk) {
282 ASSERT(current != end);
283
284 const int max_hex_significant_digits = 52 / 4 + 2;
285 // We reuse the buffer of InternalStringToDouble. Since hexadecimal
286 // numbers may have much less digits than decimal the buffer won't overflow.
287 ASSERT(max_hex_significant_digits < kMaxSignificantDigits);
288
289 int significant_digits = 0;
290 int insignificant_digits = 0;
291 bool leading_zero = false;
292 // A double has a 53bit significand (once the hidden bit has been added).
293 // Halfway cases thus have at most 54bits. Therefore 54/4 + 1 digits are
294 // sufficient to represent halfway cases. By adding another digit we can keep
295 // track of dropped digits.
296 int buffer_pos = 0;
297 bool nonzero_digit_dropped = false;
298
299 // Skip leading 0s.
300 while (*current == '0') {
301 leading_zero = true;
302 ++current;
303 if (current == end) return 0;
304 }
305
306 int begin_pos = buffer_pos;
307 while ((*current >= '0' && *current <= '9')
308 || (*current >= 'a' && *current <= 'f')
309 || (*current >= 'A' && *current <= 'F')) {
310 if (significant_digits <= max_hex_significant_digits) {
311 buffer[buffer_pos++] = static_cast<char>(*current);
312 significant_digits++;
313 } else {
314 insignificant_digits++;
315 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
316 }
317 ++current;
318 if (current == end) break;
319 }
320
321 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
322 return JUNK_STRING_VALUE;
323 }
324
325 if (significant_digits == 0) {
326 return leading_zero ? 0 : JUNK_STRING_VALUE;
327 }
328
329 if (nonzero_digit_dropped) {
330 ASSERT(insignificant_digits > 0);
331 insignificant_digits--;
332 buffer[buffer_pos++] = '1';
333 }
334
335 buffer[buffer_pos] = '\0';
336
337 double result;
338 StringToInt(buffer, begin_pos, 16, &result);
339 if (insignificant_digits > 0) {
340 // Multiplying by a power of 2 doesn't cause a loss of precision.
341 result *= pow(16.0, insignificant_digits);
342 }
343 return result;
344 }
345
346
347 // Converts a string to a double value. Assumes the Iterator supports
348 // the following operations:
349 // 1. current == end (other ops are not allowed), current != end.
350 // 2. *current - gets the current character in the sequence.
351 // 3. ++current (advances the position).
352 template <class Iterator, class EndMark>
353 static double InternalStringToDouble(Iterator current,
354 EndMark end,
269 int flags, 355 int flags,
270 double empty_string_val) { 356 double empty_string_val) {
271 double result = 0.0; 357 // To make sure that iterator dereferencing is valid the following
272 int index = 0; 358 // convention is used:
273 359 // 1. Each '++current' statement is followed by check for equality to 'end'.
274 int len = GetLength(str); 360 // 2. If AdvanceToNonspace returned false then current == end.
275 361 // 3. If 'current' becomes be equal to 'end' the function returns or goes to
276 // Skip leading spaces. 362 // 'parsing_done'.
277 while ((index < len) && IsSpace(str, index)) index++; 363 // 4. 'current' is not dereferenced after the 'parsing_done' label.
278 364 // 5. Code before 'parsing_done' may rely on 'current != end'.
279 // Is the string empty? 365 if (!AdvanceToNonspace(&current, end)) return empty_string_val;
280 if (index >= len) return empty_string_val; 366
281 367 const bool allow_trailing_junk = (flags & ALLOW_TRAILING_JUNK) != 0;
282 // Get the first character. 368
283 uint16_t first = GetChar(str, index); 369 // The longest form of simplified number is: "-<significant digits>'.1eXXX\0".
284 370 const int kBufferSize = kMaxSignificantDigits + 10;
285 // Numbers can only start with '-', '+', '.', 'I' (Infinity), or a digit. 371 char buffer[kBufferSize]; // NOLINT: size is known at compile time.
286 if (first != '-' && first != '+' && first != '.' && first != 'I' && 372 int buffer_pos = 0;
287 (first > '9' || first < '0')) { 373
374 // Exponent will be adjusted if insignificant digits of the integer part
375 // or insignificant leading zeros of the fractional part are dropped.
376 int exponent = 0;
377 int significant_digits = 0;
378 int insignificant_digits = 0;
379 bool nonzero_digit_dropped = false;
380
381 double signed_zero = 0.0;
382
383 if (*current == '+') {
384 // Ignore leading sign; skip following spaces.
385 ++current;
386 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
387 } else if (*current == '-') {
388 buffer[buffer_pos++] = '-';
389 ++current;
390 if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
391 signed_zero = -0.0;
392 }
393
394 static const char kInfinitySymbol[] = "Infinity";
395 if (*current == kInfinitySymbol[0]) {
396 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
397 return JUNK_STRING_VALUE;
398 }
399
400 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
401 return JUNK_STRING_VALUE;
402 }
403
404 ASSERT(buffer_pos == 0 || buffer[0] == '-');
405 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY;
406 }
407
408 bool leading_zero = false;
409 if (*current == '0') {
410 ++current;
411 if (current == end) return signed_zero;
412
413 leading_zero = true;
414
415 // It could be hexadecimal value.
416 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
417 ++current;
418 if (current == end) return JUNK_STRING_VALUE; // "0x".
419
420 double result = InternalHexadecimalStringToDouble(current,
421 end,
422 buffer + buffer_pos,
423 allow_trailing_junk);
424 return (buffer_pos > 0 && buffer[0] == '-') ? -result : result;
425 }
426
427 // Ignore leading zeros in the integer part.
428 while (*current == '0') {
429 ++current;
430 if (current == end) return signed_zero;
431 }
432 }
433
434 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
435
436 // Copy significant digits of the integer part (if any) to the buffer.
437 while (*current >= '0' && *current <= '9') {
438 if (significant_digits < kMaxSignificantDigits) {
439 ASSERT(buffer_pos < kBufferSize);
440 buffer[buffer_pos++] = static_cast<char>(*current);
441 significant_digits++;
442 // Will later check if it's an octal in the buffer.
443 } else {
444 insignificant_digits++; // Move the digit into the exponential part.
445 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
446 }
447 octal = octal && *current < '8';
448 ++current;
449 if (current == end) goto parsing_done;
450 }
451
452 if (significant_digits == 0) {
453 octal = false;
454 }
455
456 if (*current == '.') {
457 ASSERT(buffer_pos < kBufferSize);
458 buffer[buffer_pos++] = '.';
459 ++current;
460 if (current == end) {
461 if (significant_digits == 0 && !leading_zero) {
462 return JUNK_STRING_VALUE;
463 } else {
464 goto parsing_done;
465 }
466 }
467
468 if (significant_digits == 0) {
469 // octal = false;
470 // Integer part consists of 0 or is absent. Significant digits start after
471 // leading zeros (if any).
472 while (*current == '0') {
473 ++current;
474 if (current == end) return signed_zero;
475 exponent--; // Move this 0 into the exponent.
476 }
477 }
478
479 // There is the fractional part.
480 while (*current >= '0' && *current <= '9') {
481 if (significant_digits < kMaxSignificantDigits) {
482 ASSERT(buffer_pos < kBufferSize);
483 buffer[buffer_pos++] = static_cast<char>(*current);
484 significant_digits++;
485 } else {
486 // Ignore insignificant digits in the fractional part.
487 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
488 }
489 ++current;
490 if (current == end) goto parsing_done;
491 }
492 }
493
494 if (!leading_zero && exponent == 0 && significant_digits == 0) {
495 // If leading_zeros is true then the string contains zeros.
496 // If exponent < 0 then string was [+-]\.0*...
497 // If significant_digits != 0 the string is not equal to 0.
498 // Otherwise there are no digits in the string.
288 return JUNK_STRING_VALUE; 499 return JUNK_STRING_VALUE;
289 } 500 }
290 501
291 // Compute sign of result based on first character. 502 // Parse exponential part.
292 int sign = 1; 503 if (*current == 'e' || *current == 'E') {
293 if (first == '-') { 504 if (octal) return JUNK_STRING_VALUE;
294 sign = -1; 505 ++current;
295 index++; 506 if (current == end) {
296 // String only containing a '-' are junk chars. 507 if (allow_trailing_junk) {
297 if (index == len) return JUNK_STRING_VALUE; 508 goto parsing_done;
298 } 509 } else {
299 510 return JUNK_STRING_VALUE;
300 // do we have a hex number? 511 }
301 // (since the string is 0-terminated, it's ok to look one char beyond the end) 512 }
302 if ((flags & ALLOW_HEX) != 0 && 513 char sign = '+';
303 (index + 1) < len && 514 if (*current == '+' || *current == '-') {
304 GetChar(str, index) == '0' && 515 sign = static_cast<char>(*current);
305 (GetChar(str, index + 1) == 'x' || GetChar(str, index + 1) == 'X')) { 516 ++current;
306 index += 2; 517 if (current == end) {
307 index = StringToInt(str, index, 16, &result); 518 if (allow_trailing_junk) {
308 } else if ((flags & ALLOW_OCTALS) != 0 && ShouldParseOctal(str, index)) { 519 goto parsing_done;
309 // NOTE: We optimistically try to parse the number as an octal (if 520 } else {
310 // we're allowed to), even though this is not as dictated by 521 return JUNK_STRING_VALUE;
311 // ECMA-262. The reason for doing this is compatibility with IE and 522 }
312 // Firefox. 523 }
313 index = StringToInt(str, index, 8, &result); 524 }
525
526 if (current == end || *current < '0' || *current > '9') {
527 if (allow_trailing_junk) {
528 goto parsing_done;
529 } else {
530 return JUNK_STRING_VALUE;
531 }
532 }
533
534 const int max_exponent = INT_MAX / 2;
535 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
536 int num = 0;
537 do {
538 // Check overflow.
539 int digit = *current - '0';
540 if (num >= max_exponent / 10
541 && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
542 num = max_exponent;
543 } else {
544 num = num * 10 + digit;
545 }
546 ++current;
547 } while (current != end && *current >= '0' && *current <= '9');
548
549 exponent += (sign == '-' ? -num : num);
550 }
551
552 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
553 return JUNK_STRING_VALUE;
554 }
555
556 parsing_done:
557 exponent += insignificant_digits;
558
559 if (octal) {
560 buffer[buffer_pos] = '\0';
561 // ALLOW_OCTALS is set and there is no '8' or '9' in insignificant
562 // digits. Check significant digits now.
563 char sign = '+';
564 const char* s = buffer;
565 if (*s == '-' || *s == '+') sign = *s++;
566
567 double result;
568 s += StringToInt(s, 0, 8, &result);
569 if (!allow_trailing_junk && *s != '\0') return JUNK_STRING_VALUE;
570
571 if (sign == '-') result = -result;
572 if (insignificant_digits > 0) {
573 result *= pow(8.0, insignificant_digits);
574 }
575 return result;
576 }
577
578 if (nonzero_digit_dropped) {
579 if (insignificant_digits) buffer[buffer_pos++] = '.';
580 buffer[buffer_pos++] = '1';
581 }
582
583 if (exponent != 0) {
584 ASSERT(buffer_pos < kBufferSize);
585 buffer[buffer_pos++] = 'e';
586 if (exponent < 0) {
587 ASSERT(buffer_pos < kBufferSize);
588 buffer[buffer_pos++] = '-';
589 exponent = -exponent;
590 }
591 if (exponent > 999) exponent = 999; // Result will be Infinity or 0 or -0.
592
593 const int exp_digits = 3;
594 for (int i = 0; i < exp_digits; i++) {
595 buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10;
596 exponent /= 10;
597 }
598 ASSERT(exponent == 0);
599 buffer_pos += exp_digits;
600 }
601
602 ASSERT(buffer_pos < kBufferSize);
603 buffer[buffer_pos] = '\0';
604
605 return gay_strtod(buffer, NULL);
606 }
607
608 double StringToDouble(String* str, int flags, double empty_string_val) {
609 StringShape shape(str);
610 if (shape.IsSequentialAscii()) {
611 const char* begin = SeqAsciiString::cast(str)->GetChars();
612 const char* end = begin + str->length();
613 return InternalStringToDouble(begin, end, flags, empty_string_val);
614 } else if (shape.IsSequentialTwoByte()) {
615 const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
616 const uc16* end = begin + str->length();
617 return InternalStringToDouble(begin, end, flags, empty_string_val);
314 } else { 618 } else {
315 const char* cstr = GetCString(str, index); 619 StringInputBuffer buffer(str);
316 const char* end; 620 return InternalStringToDouble(StringInputBufferIterator(&buffer),
317 // Optimistically parse the number and then, if that fails, 621 StringInputBufferIterator::EndMarker(),
318 // check if it might have been {+,-,}Infinity. 622 flags,
319 result = gay_strtod(cstr, &end); 623 empty_string_val);
320 ReleaseCString(str, cstr); 624 }
321 if (result != 0.0 || end != cstr) {
322 // It appears that strtod worked
323 index += static_cast<int>(end - cstr);
324 } else {
325 // Check for {+,-,}Infinity
326 bool is_negative = (GetChar(str, index) == '-');
327 if (GetChar(str, index) == '+' || GetChar(str, index) == '-')
328 index++;
329 if (!SubStringEquals(str, index, "Infinity"))
330 return JUNK_STRING_VALUE;
331 result = is_negative ? -V8_INFINITY : V8_INFINITY;
332 index += 8;
333 }
334 }
335
336 if ((flags & ALLOW_TRAILING_JUNK) == 0) {
337 // skip trailing spaces
338 while ((index < len) && IsSpace(str, index)) index++;
339 // string ending with junk?
340 if (index < len) return JUNK_STRING_VALUE;
341 }
342
343 return sign * result;
344 }
345
346
347 double StringToDouble(String* str, int flags, double empty_string_val) {
348 return InternalStringToDouble(str, flags, empty_string_val);
349 } 625 }
350 626
351 627
352 double StringToDouble(const char* str, int flags, double empty_string_val) { 628 double StringToDouble(const char* str, int flags, double empty_string_val) {
353 return InternalStringToDouble(str, flags, empty_string_val); 629 const char* end = str + StrLength(str);
354 } 630
355 631 return InternalStringToDouble(str, end, flags, empty_string_val);
356 632 }
633
634
357 extern "C" char* dtoa(double d, int mode, int ndigits, 635 extern "C" char* dtoa(double d, int mode, int ndigits,
358 int* decpt, int* sign, char** rve); 636 int* decpt, int* sign, char** rve);
359 637
360 extern "C" void freedtoa(char* s); 638 extern "C" void freedtoa(char* s);
361 639
362 const char* DoubleToCString(double v, Vector<char> buffer) { 640 const char* DoubleToCString(double v, Vector<char> buffer) {
363 StringBuilder builder(buffer.start(), buffer.length()); 641 StringBuilder builder(buffer.start(), buffer.length());
364 642
365 switch (fpclassify(v)) { 643 switch (fpclassify(v)) {
366 case FP_NAN: 644 case FP_NAN:
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 // Allocate result and fill in the parts. 988 // Allocate result and fill in the parts.
711 StringBuilder builder(result_size + 1); 989 StringBuilder builder(result_size + 1);
712 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); 990 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size);
713 if (decimal_pos > 0) builder.AddCharacter('.'); 991 if (decimal_pos > 0) builder.AddCharacter('.');
714 builder.AddSubstring(decimal_buffer, decimal_pos); 992 builder.AddSubstring(decimal_buffer, decimal_pos);
715 return builder.Finalize(); 993 return builder.Finalize();
716 } 994 }
717 995
718 996
719 } } // namespace v8::internal 997 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/cctest/test-conversions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698