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

Side by Side Diff: src/conversions.cc

Issue 1529004: StringToInt rewritten. This version doesn't allocate memory for long decimals... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 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 | « src/conversions.h ('k') | src/runtime.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
(...skipping 30 matching lines...) Expand all
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
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
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(&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
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(&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 // 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(&current, 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
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(&current, end)) return JUNK_STRING_VALUE; 462 if (!AdvanceToNonspace(&current, 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(&current, end)) return JUNK_STRING_VALUE; 466 if (!AdvanceToNonspace(&current, 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(&current, end, kInfinitySymbol)) { 472 if (!SubStringEquals(&current, end, kInfinitySymbol)) {
436 return JUNK_STRING_VALUE; 473 return JUNK_STRING_VALUE;
437 } 474 }
438 475
439 if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) { 476 if (!allow_trailing_junk && AdvanceToNonspace(&current, 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
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
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
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
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
OLDNEW
« no previous file with comments | « src/conversions.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698