OLD | NEW |
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 Loading... |
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 Loading... |
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(¤t, 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(¤t, 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(¤t, end)) return JUNK_STRING_VALUE; |
| 387 } else if (*current == '-') { |
| 388 buffer[buffer_pos++] = '-'; |
| 389 ++current; |
| 390 if (!AdvanceToNonspace(¤t, 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(¤t, end, kInfinitySymbol)) { |
| 397 return JUNK_STRING_VALUE; |
| 398 } |
| 399 |
| 400 if (!allow_trailing_junk && AdvanceToNonspace(¤t, 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(¤t, 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 Loading... |
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 |
OLD | NEW |