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 |
(...skipping 30 matching lines...) Expand all Loading... | |
41 int HexValue(uc32 c) { | 41 int HexValue(uc32 c) { |
42 if ('0' <= c && c <= '9') | 42 if ('0' <= c && c <= '9') |
43 return c - '0'; | 43 return c - '0'; |
44 if ('a' <= c && c <= 'f') | 44 if ('a' <= c && c <= 'f') |
45 return c - 'a' + 10; | 45 return c - 'a' + 10; |
46 if ('A' <= c && c <= 'F') | 46 if ('A' <= c && c <= 'F') |
47 return c - 'A' + 10; | 47 return c - 'A' + 10; |
48 return -1; | 48 return -1; |
49 } | 49 } |
50 | 50 |
51 | |
52 // Provide a common interface to getting a character at a certain | |
53 // index from a char* or a String object. | |
54 static inline int GetChar(const char* str, int index) { | |
55 ASSERT(index >= 0 && index < StrLength(str)); | |
56 return str[index]; | |
57 } | |
58 | |
59 | |
60 static inline int GetChar(String* str, int index) { | |
61 return str->Get(index); | |
62 } | |
63 | |
64 | |
65 static inline int GetLength(const char* str) { | |
66 return StrLength(str); | |
67 } | |
68 | |
69 | |
70 static inline int GetLength(String* str) { | |
71 return str->length(); | |
72 } | |
73 | |
74 | |
75 static inline const char* GetCString(const char* str, int index) { | |
76 return str + index; | |
77 } | |
78 | |
79 | |
80 static inline const char* GetCString(String* str, int index) { | |
81 int length = str->length(); | |
82 char* result = NewArray<char>(length + 1); | |
83 for (int i = index; i < length; i++) { | |
84 uc16 c = str->Get(i); | |
85 if (c <= 127) { | |
86 result[i - index] = static_cast<char>(c); | |
87 } else { | |
88 result[i - index] = 127; // Force number parsing to fail. | |
89 } | |
90 } | |
91 result[length - index] = '\0'; | |
92 return result; | |
93 } | |
94 | |
95 | |
96 namespace { | 51 namespace { |
97 | 52 |
98 // C++-style iterator adaptor for StringInputBuffer | 53 // C++-style iterator adaptor for StringInputBuffer |
99 // (unlike C++ iterators the end-marker has different type). | 54 // (unlike C++ iterators the end-marker has different type). |
100 class StringInputBufferIterator { | 55 class StringInputBufferIterator { |
101 public: | 56 public: |
102 class EndMarker {}; | 57 class EndMarker {}; |
103 | 58 |
104 explicit StringInputBufferIterator(StringInputBuffer* buffer); | 59 explicit StringInputBufferIterator(StringInputBuffer* buffer); |
105 | 60 |
(...skipping 21 matching lines...) Expand all Loading... | |
127 | 82 |
128 void StringInputBufferIterator::operator++() { | 83 void StringInputBufferIterator::operator++() { |
129 end_ = !buffer_->has_more(); | 84 end_ = !buffer_->has_more(); |
130 if (!end_) { | 85 if (!end_) { |
131 current_ = buffer_->GetNext(); | 86 current_ = buffer_->GetNext(); |
132 } | 87 } |
133 } | 88 } |
134 } | 89 } |
135 | 90 |
136 | 91 |
137 static inline void ReleaseCString(const char* original, const char* str) { | |
138 } | |
139 | |
140 | |
141 static inline void ReleaseCString(String* original, const char* str) { | |
142 DeleteArray(const_cast<char *>(str)); | |
143 } | |
144 | |
145 | |
146 template <class Iterator, class EndMark> | 92 template <class Iterator, class EndMark> |
147 static bool SubStringEquals(Iterator* current, | 93 static bool SubStringEquals(Iterator* current, |
148 EndMark end, | 94 EndMark end, |
149 const char* substring) { | 95 const char* substring) { |
150 ASSERT(**current == *substring); | 96 ASSERT(**current == *substring); |
151 for (substring++; *substring != '\0'; substring++) { | 97 for (substring++; *substring != '\0'; substring++) { |
152 ++*current; | 98 ++*current; |
153 if (*current == end || **current != *substring) return false; | 99 if (*current == end || **current != *substring) return false; |
154 } | 100 } |
155 ++*current; | 101 ++*current; |
156 return true; | 102 return true; |
157 } | 103 } |
158 | 104 |
159 | 105 |
160 extern "C" double gay_strtod(const char* s00, const char** se); | 106 extern "C" double gay_strtod(const char* s00, const char** se); |
161 | 107 |
162 // Maximum number of significant digits in decimal representation. | 108 // Maximum number of significant digits in decimal representation. |
163 // The longest possible double in decimal representation is | 109 // The longest possible double in decimal representation is |
164 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 | 110 // (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 | 111 // (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 | 112 // 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 | 113 // must be rounded to the bigger one unless the tail consists of zeros, so |
168 // we don't need to preserve all the digits. | 114 // we don't need to preserve all the digits. |
169 const int kMaxSignificantDigits = 772; | 115 const int kMaxSignificantDigits = 772; |
170 | 116 |
171 // Parse an int from a string starting a given index and in a given | |
172 // radix. The string can be either a char* or a String*. | |
173 template <class S> | |
174 static int InternalStringToInt(S* s, int i, int radix, double* value) { | |
175 int len = GetLength(s); | |
176 | |
177 // Setup limits for computing the value. | |
178 ASSERT(2 <= radix && radix <= 36); | |
179 int lim_0 = '0' + (radix < 10 ? radix : 10); | |
180 int lim_a = 'a' + (radix - 10); | |
181 int lim_A = 'A' + (radix - 10); | |
182 | |
183 // NOTE: The code for computing the value may seem a bit complex at | |
184 // first glance. It is structured to use 32-bit multiply-and-add | |
185 // loops as long as possible to avoid loosing precision. | |
186 | |
187 double v = 0.0; | |
188 int j; | |
189 for (j = i; j < len;) { | |
190 // Parse the longest part of the string starting at index j | |
191 // possible while keeping the multiplier, and thus the part | |
192 // itself, within 32 bits. | |
193 uint32_t part = 0, multiplier = 1; | |
194 int k; | |
195 for (k = j; k < len; k++) { | |
196 int c = GetChar(s, k); | |
197 if (c >= '0' && c < lim_0) { | |
198 c = c - '0'; | |
199 } else if (c >= 'a' && c < lim_a) { | |
200 c = c - 'a' + 10; | |
201 } else if (c >= 'A' && c < lim_A) { | |
202 c = c - 'A' + 10; | |
203 } else { | |
204 break; | |
205 } | |
206 | |
207 // Update the value of the part as long as the multiplier fits | |
208 // in 32 bits. When we can't guarantee that the next iteration | |
209 // will not overflow the multiplier, we stop parsing the part | |
210 // by leaving the loop. | |
211 static const uint32_t kMaximumMultiplier = 0xffffffffU / 36; | |
212 uint32_t m = multiplier * radix; | |
213 if (m > kMaximumMultiplier) break; | |
214 part = part * radix + c; | |
215 multiplier = m; | |
216 ASSERT(multiplier > part); | |
217 } | |
218 | |
219 // Compute the number of part digits. If no digits were parsed; | |
220 // we're done parsing the entire string. | |
221 int digits = k - j; | |
222 if (digits == 0) break; | |
223 | |
224 // Update the value and skip the part in the string. | |
225 ASSERT(multiplier == | |
226 pow(static_cast<double>(radix), static_cast<double>(digits))); | |
227 v = v * multiplier + part; | |
228 j = k; | |
229 } | |
230 | |
231 // If the resulting value is larger than 2^53 the value does not fit | |
232 // in the mantissa of the double and there is a loss of precision. | |
233 // When the value is larger than 2^53 the rounding depends on the | |
234 // code generation. If the code generator spills the double value | |
235 // it uses 64 bits and if it does not it uses 80 bits. | |
236 // | |
237 // If there is a potential for overflow we resort to strtod for | |
238 // radix 10 numbers to get higher precision. For numbers in another | |
239 // radix we live with the loss of precision. | |
240 static const double kPreciseConversionLimit = 9007199254740992.0; | |
241 if (radix == 10 && v > kPreciseConversionLimit) { | |
242 const char* cstr = GetCString(s, i); | |
243 const char* end; | |
244 v = gay_strtod(cstr, &end); | |
245 ReleaseCString(s, cstr); | |
246 } | |
247 | |
248 *value = v; | |
249 return j; | |
250 } | |
251 | |
252 | |
253 int StringToInt(String* str, int index, int radix, double* value) { | |
254 return InternalStringToInt(str, index, radix, value); | |
255 } | |
256 | |
257 | |
258 int StringToInt(const char* str, int index, int radix, double* value) { | |
259 return InternalStringToInt(const_cast<char*>(str), index, radix, value); | |
260 } | |
261 | |
262 | 117 |
263 static const double JUNK_STRING_VALUE = OS::nan_value(); | 118 static const double JUNK_STRING_VALUE = OS::nan_value(); |
264 | 119 |
265 | 120 |
266 // Returns true if a nonspace found and false if the end has reached. | 121 // Returns true if a nonspace found and false if the end has reached. |
267 template <class Iterator, class EndMark> | 122 template <class Iterator, class EndMark> |
268 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) { | 123 static inline bool AdvanceToNonspace(Iterator* current, EndMark end) { |
269 while (*current != end) { | 124 while (*current != end) { |
270 if (!Scanner::kIsWhiteSpace.get(**current)) return true; | 125 if (!Scanner::kIsWhiteSpace.get(**current)) return true; |
271 ++*current; | 126 ++*current; |
272 } | 127 } |
273 return false; | 128 return false; |
274 } | 129 } |
275 | 130 |
276 | 131 |
277 static bool isDigit(int x, int radix) { | 132 static bool isDigit(int x, int radix) { |
278 return (x >= '0' && x <= '9' && x < '0' + radix) | 133 return (x >= '0' && x <= '9' && x < '0' + radix) |
279 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) | 134 || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) |
280 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); | 135 || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); |
281 } | 136 } |
282 | 137 |
283 | 138 |
139 static double SignedZero(bool sign) { | |
140 return sign ? -0.0 : 0.0; | |
141 } | |
142 | |
143 | |
284 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. | 144 // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
285 template <int radix_log_2, class Iterator, class EndMark> | 145 template <int radix_log_2, class Iterator, class EndMark> |
286 static double InternalStringToIntDouble(Iterator current, | 146 static double InternalStringToIntDouble(Iterator current, |
287 EndMark end, | 147 EndMark end, |
288 bool sign, | 148 bool sign, |
289 bool allow_trailing_junk) { | 149 bool allow_trailing_junk) { |
290 ASSERT(current != end); | 150 ASSERT(current != end); |
291 | 151 |
292 // Skip leading 0s. | 152 // Skip leading 0s. |
293 while (*current == '0') { | 153 while (*current == '0') { |
294 ++current; | 154 ++current; |
295 if (current == end) return sign ? -0.0 : 0.0; | 155 if (current == end) return SignedZero(sign); |
296 } | 156 } |
297 | 157 |
298 int64_t number = 0; | 158 int64_t number = 0; |
299 int exponent = 0; | 159 int exponent = 0; |
300 const int radix = (1 << radix_log_2); | 160 const int radix = (1 << radix_log_2); |
301 | 161 |
302 do { | 162 do { |
303 int digit; | 163 int digit; |
304 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { | 164 if (*current >= '0' && *current <= '9' && *current < '0' + radix) { |
305 digit = static_cast<char>(*current) - '0'; | 165 digit = static_cast<char>(*current) - '0'; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 return static_cast<double>(number); | 235 return static_cast<double>(number); |
376 } | 236 } |
377 | 237 |
378 ASSERT(number != 0); | 238 ASSERT(number != 0); |
379 // The double could be constructed faster from number (mantissa), exponent | 239 // The double could be constructed faster from number (mantissa), exponent |
380 // and sign. Assuming it's a rare case more simple code is used. | 240 // and sign. Assuming it's a rare case more simple code is used. |
381 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent); | 241 return static_cast<double>(sign ? -number : number) * pow(2.0, exponent); |
382 } | 242 } |
383 | 243 |
384 | 244 |
245 template <class Iterator, class EndMark> | |
246 static 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(¤t, 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(¤t, end)) return JUNK_STRING_VALUE; | |
259 } else if (*current == '-') { | |
260 ++current; | |
261 if (!AdvanceToNonspace(¤t, 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 | |
Florian Loitsch
2010/03/31 16:50:00
Maybe add comment:
A number with more than kMaxSig
SeRya
2010/03/31 17:18:08
The comment 7 lines below says the same. I think t
Florian Loitsch
2010/04/03 13:10:59
true. fine with me.
| |
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(¤t, 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 // TODO(serya): The following legacy code causes accumulating rounding | |
361 // error for number greater than ~2^56. It should be rewritten using long | |
362 // arithmetic. | |
363 | |
364 int lim_0 = '0' + (radix < 10 ? radix : 10); | |
365 int lim_a = 'a' + (radix - 10); | |
366 int lim_A = 'A' + (radix - 10); | |
367 | |
368 // NOTE: The code for computing the value may seem a bit complex at | |
369 // first glance. It is structured to use 32-bit multiply-and-add | |
370 // loops as long as possible to avoid loosing precision. | |
371 | |
372 double v = 0.0; | |
373 bool done = false; | |
374 do { | |
375 // Parse the longest part of the string starting at index j | |
376 // possible while keeping the multiplier, and thus the part | |
377 // itself, within 32 bits. | |
378 unsigned int part = 0, multiplier = 1; | |
379 while (true) { | |
380 int d; | |
381 if (*current >= '0' && *current < lim_0) { | |
382 d = *current - '0'; | |
383 } else if (*current >= 'a' && *current < lim_a) { | |
384 d = *current - 'a' + 10; | |
385 } else if (*current >= 'A' && *current < lim_A) { | |
386 d = *current - 'A' + 10; | |
387 } else { | |
388 done = true; | |
389 break; | |
390 } | |
391 | |
392 // Update the value of the part as long as the multiplier fits | |
393 // in 32 bits. When we can't guarantee that the next iteration | |
394 // will not overflow the multiplier, we stop parsing the part | |
395 // by leaving the loop. | |
396 const unsigned int kMaximumMultiplier = 0xffffffffU / 36; | |
397 uint32_t m = multiplier * radix; | |
398 if (m > kMaximumMultiplier) break; | |
399 part = part * radix + d; | |
400 multiplier = m; | |
401 ASSERT(multiplier > part); | |
402 | |
403 ++current; | |
404 if (current == end) { | |
405 done = true; | |
406 break; | |
407 } | |
408 } | |
409 | |
410 // Update the value and skip the part in the string. | |
411 v = v * multiplier + part; | |
412 } while (!done); | |
413 | |
414 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | |
415 return JUNK_STRING_VALUE; | |
416 } | |
417 | |
418 return sign ? -v : v; | |
419 } | |
420 | |
421 | |
385 // Converts a string to a double value. Assumes the Iterator supports | 422 // Converts a string to a double value. Assumes the Iterator supports |
386 // the following operations: | 423 // the following operations: |
387 // 1. current == end (other ops are not allowed), current != end. | 424 // 1. current == end (other ops are not allowed), current != end. |
388 // 2. *current - gets the current character in the sequence. | 425 // 2. *current - gets the current character in the sequence. |
389 // 3. ++current (advances the position). | 426 // 3. ++current (advances the position). |
390 template <class Iterator, class EndMark> | 427 template <class Iterator, class EndMark> |
391 static double InternalStringToDouble(Iterator current, | 428 static double InternalStringToDouble(Iterator current, |
392 EndMark end, | 429 EndMark end, |
393 int flags, | 430 int flags, |
394 double empty_string_val) { | 431 double empty_string_val) { |
(...skipping 15 matching lines...) Expand all Loading... | |
410 int buffer_pos = 0; | 447 int buffer_pos = 0; |
411 | 448 |
412 // Exponent will be adjusted if insignificant digits of the integer part | 449 // Exponent will be adjusted if insignificant digits of the integer part |
413 // or insignificant leading zeros of the fractional part are dropped. | 450 // or insignificant leading zeros of the fractional part are dropped. |
414 int exponent = 0; | 451 int exponent = 0; |
415 int significant_digits = 0; | 452 int significant_digits = 0; |
416 int insignificant_digits = 0; | 453 int insignificant_digits = 0; |
417 bool nonzero_digit_dropped = false; | 454 bool nonzero_digit_dropped = false; |
418 bool fractional_part = false; | 455 bool fractional_part = false; |
419 | 456 |
420 double signed_zero = 0.0; | 457 bool sign = false; |
421 | 458 |
422 if (*current == '+') { | 459 if (*current == '+') { |
423 // Ignore leading sign; skip following spaces. | 460 // Ignore leading sign; skip following spaces. |
424 ++current; | 461 ++current; |
425 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 462 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; |
426 } else if (*current == '-') { | 463 } else if (*current == '-') { |
427 buffer[buffer_pos++] = '-'; | 464 buffer[buffer_pos++] = '-'; |
428 ++current; | 465 ++current; |
429 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; | 466 if (!AdvanceToNonspace(¤t, end)) return JUNK_STRING_VALUE; |
430 signed_zero = -0.0; | 467 sign = true; |
431 } | 468 } |
432 | 469 |
433 static const char kInfinitySymbol[] = "Infinity"; | 470 static const char kInfinitySymbol[] = "Infinity"; |
434 if (*current == kInfinitySymbol[0]) { | 471 if (*current == kInfinitySymbol[0]) { |
435 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { | 472 if (!SubStringEquals(¤t, end, kInfinitySymbol)) { |
436 return JUNK_STRING_VALUE; | 473 return JUNK_STRING_VALUE; |
437 } | 474 } |
438 | 475 |
439 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 476 if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
440 return JUNK_STRING_VALUE; | 477 return JUNK_STRING_VALUE; |
441 } | 478 } |
442 | 479 |
443 ASSERT(buffer_pos == 0 || buffer[0] == '-'); | 480 ASSERT(buffer_pos == 0 || buffer[0] == '-'); |
444 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; | 481 return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; |
445 } | 482 } |
446 | 483 |
447 bool leading_zero = false; | 484 bool leading_zero = false; |
448 if (*current == '0') { | 485 if (*current == '0') { |
449 ++current; | 486 ++current; |
450 if (current == end) return signed_zero; | 487 if (current == end) return SignedZero(sign); |
451 | 488 |
452 leading_zero = true; | 489 leading_zero = true; |
453 | 490 |
454 // It could be hexadecimal value. | 491 // It could be hexadecimal value. |
455 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { | 492 if ((flags & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { |
456 ++current; | 493 ++current; |
457 if (current == end) return JUNK_STRING_VALUE; // "0x". | 494 if (current == end || !isDigit(*current, 16)) { |
495 return JUNK_STRING_VALUE; // "0x". | |
496 } | |
458 | 497 |
459 bool sign = (buffer_pos > 0 && buffer[0] == '-'); | 498 bool sign = (buffer_pos > 0 && buffer[0] == '-'); |
460 return InternalStringToIntDouble<4>(current, | 499 return InternalStringToIntDouble<4>(current, |
461 end, | 500 end, |
462 sign, | 501 sign, |
463 allow_trailing_junk); | 502 allow_trailing_junk); |
464 } | 503 } |
465 | 504 |
466 // Ignore leading zeros in the integer part. | 505 // Ignore leading zeros in the integer part. |
467 while (*current == '0') { | 506 while (*current == '0') { |
468 ++current; | 507 ++current; |
469 if (current == end) return signed_zero; | 508 if (current == end) return SignedZero(sign); |
470 } | 509 } |
471 } | 510 } |
472 | 511 |
473 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0; | 512 bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0; |
474 | 513 |
475 // Copy significant digits of the integer part (if any) to the buffer. | 514 // Copy significant digits of the integer part (if any) to the buffer. |
476 while (*current >= '0' && *current <= '9') { | 515 while (*current >= '0' && *current <= '9') { |
477 if (significant_digits < kMaxSignificantDigits) { | 516 if (significant_digits < kMaxSignificantDigits) { |
478 ASSERT(buffer_pos < kBufferSize); | 517 ASSERT(buffer_pos < kBufferSize); |
479 buffer[buffer_pos++] = static_cast<char>(*current); | 518 buffer[buffer_pos++] = static_cast<char>(*current); |
(...skipping 21 matching lines...) Expand all Loading... | |
501 goto parsing_done; | 540 goto parsing_done; |
502 } | 541 } |
503 } | 542 } |
504 | 543 |
505 if (significant_digits == 0) { | 544 if (significant_digits == 0) { |
506 // octal = false; | 545 // octal = false; |
507 // Integer part consists of 0 or is absent. Significant digits start after | 546 // Integer part consists of 0 or is absent. Significant digits start after |
508 // leading zeros (if any). | 547 // leading zeros (if any). |
509 while (*current == '0') { | 548 while (*current == '0') { |
510 ++current; | 549 ++current; |
511 if (current == end) return signed_zero; | 550 if (current == end) return SignedZero(sign); |
512 exponent--; // Move this 0 into the exponent. | 551 exponent--; // Move this 0 into the exponent. |
513 } | 552 } |
514 } | 553 } |
515 | 554 |
516 ASSERT(buffer_pos < kBufferSize); | 555 ASSERT(buffer_pos < kBufferSize); |
517 buffer[buffer_pos++] = '.'; | 556 buffer[buffer_pos++] = '.'; |
518 fractional_part = true; | 557 fractional_part = true; |
519 | 558 |
520 // There is the fractional part. | 559 // There is the fractional part. |
521 while (*current >= '0' && *current <= '9') { | 560 while (*current >= '0' && *current <= '9') { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
628 if (exponent > 999) exponent = 999; // Result will be Infinity or 0 or -0. | 667 if (exponent > 999) exponent = 999; // Result will be Infinity or 0 or -0. |
629 | 668 |
630 const int exp_digits = 3; | 669 const int exp_digits = 3; |
631 for (int i = 0; i < exp_digits; i++) { | 670 for (int i = 0; i < exp_digits; i++) { |
632 buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10; | 671 buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10; |
633 exponent /= 10; | 672 exponent /= 10; |
634 } | 673 } |
635 ASSERT(exponent == 0); | 674 ASSERT(exponent == 0); |
636 buffer_pos += exp_digits; | 675 buffer_pos += exp_digits; |
637 } else if (!fractional_part && significant_digits <= kMaxDigitsInInt) { | 676 } else if (!fractional_part && significant_digits <= kMaxDigitsInInt) { |
638 if (significant_digits == 0) return signed_zero; | 677 if (significant_digits == 0) return SignedZero(sign); |
639 ASSERT(buffer_pos > 0); | 678 ASSERT(buffer_pos > 0); |
640 int num = 0; | 679 int num = 0; |
641 int start_pos = (buffer[0] == '-' ? 1 : 0); | 680 int start_pos = (buffer[0] == '-' ? 1 : 0); |
642 for (int i = start_pos; i < buffer_pos; i++) { | 681 for (int i = start_pos; i < buffer_pos; i++) { |
643 ASSERT(buffer[i] >= '0' && buffer[i] <= '9'); | 682 ASSERT(buffer[i] >= '0' && buffer[i] <= '9'); |
644 num = 10 * num + (buffer[i] - '0'); | 683 num = 10 * num + (buffer[i] - '0'); |
645 } | 684 } |
646 return static_cast<double>(start_pos == 0 ? num : -num); | 685 return static_cast<double>(start_pos == 0 ? num : -num); |
647 } | 686 } |
648 | 687 |
(...skipping 16 matching lines...) Expand all Loading... | |
665 } else { | 704 } else { |
666 StringInputBuffer buffer(str); | 705 StringInputBuffer buffer(str); |
667 return InternalStringToDouble(StringInputBufferIterator(&buffer), | 706 return InternalStringToDouble(StringInputBufferIterator(&buffer), |
668 StringInputBufferIterator::EndMarker(), | 707 StringInputBufferIterator::EndMarker(), |
669 flags, | 708 flags, |
670 empty_string_val); | 709 empty_string_val); |
671 } | 710 } |
672 } | 711 } |
673 | 712 |
674 | 713 |
714 double StringToInt(String* str, int radix) { | |
715 StringShape shape(str); | |
716 if (shape.IsSequentialAscii()) { | |
717 const char* begin = SeqAsciiString::cast(str)->GetChars(); | |
718 const char* end = begin + str->length(); | |
719 return InternalStringToInt(begin, end, radix); | |
720 } else if (shape.IsSequentialTwoByte()) { | |
721 const uc16* begin = SeqTwoByteString::cast(str)->GetChars(); | |
722 const uc16* end = begin + str->length(); | |
723 return InternalStringToInt(begin, end, radix); | |
724 } else { | |
725 StringInputBuffer buffer(str); | |
726 return InternalStringToInt(StringInputBufferIterator(&buffer), | |
727 StringInputBufferIterator::EndMarker(), | |
728 radix); | |
729 } | |
730 } | |
731 | |
732 | |
675 double StringToDouble(const char* str, int flags, double empty_string_val) { | 733 double StringToDouble(const char* str, int flags, double empty_string_val) { |
676 const char* end = str + StrLength(str); | 734 const char* end = str + StrLength(str); |
677 | 735 |
678 return InternalStringToDouble(str, end, flags, empty_string_val); | 736 return InternalStringToDouble(str, end, flags, empty_string_val); |
679 } | 737 } |
680 | 738 |
681 | 739 |
682 extern "C" char* dtoa(double d, int mode, int ndigits, | 740 extern "C" char* dtoa(double d, int mode, int ndigits, |
683 int* decpt, int* sign, char** rve); | 741 int* decpt, int* sign, char** rve); |
684 | 742 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1035 // Allocate result and fill in the parts. | 1093 // Allocate result and fill in the parts. |
1036 StringBuilder builder(result_size + 1); | 1094 StringBuilder builder(result_size + 1); |
1037 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); | 1095 builder.AddSubstring(integer_buffer + integer_pos + 1, integer_part_size); |
1038 if (decimal_pos > 0) builder.AddCharacter('.'); | 1096 if (decimal_pos > 0) builder.AddCharacter('.'); |
1039 builder.AddSubstring(decimal_buffer, decimal_pos); | 1097 builder.AddSubstring(decimal_buffer, decimal_pos); |
1040 return builder.Finalize(); | 1098 return builder.Finalize(); |
1041 } | 1099 } |
1042 | 1100 |
1043 | 1101 |
1044 } } // namespace v8::internal | 1102 } } // namespace v8::internal |
OLD | NEW |