OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 24 matching lines...) Expand all Loading... |
35 #include "bignum-dtoa.h" | 35 #include "bignum-dtoa.h" |
36 #include "double.h" | 36 #include "double.h" |
37 #include "fast-dtoa.h" | 37 #include "fast-dtoa.h" |
38 #include "fixed-dtoa.h" | 38 #include "fixed-dtoa.h" |
39 #include "strtod.h" | 39 #include "strtod.h" |
40 #include "utils.h" | 40 #include "utils.h" |
41 | 41 |
42 namespace WTF { | 42 namespace WTF { |
43 | 43 |
44 namespace double_conversion { | 44 namespace double_conversion { |
45 | 45 |
46 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter(
) { | 46 const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter(
) { |
47 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; | 47 int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; |
48 static DoubleToStringConverter converter(flags, | 48 static DoubleToStringConverter converter(flags, |
49 "Infinity", | 49 "Infinity", |
50 "NaN", | 50 "NaN", |
51 'e', | 51 'e', |
52 -6, 21, | 52 -6, 21, |
53 6, 0); | 53 6, 0); |
54 return converter; | 54 return converter; |
55 } | 55 } |
56 | 56 |
57 | 57 |
58 bool DoubleToStringConverter::HandleSpecialValues( | 58 bool DoubleToStringConverter::HandleSpecialValues( |
59 double value, | 59 double value, |
60 StringBuilder* result_buil
der) const { | 60 StringBuilder* result_buil
der) const { |
61 Double double_inspect(value); | 61 Double double_inspect(value); |
62 if (double_inspect.IsInfinite()) { | 62 if (double_inspect.IsInfinite()) { |
63 if (infinity_symbol_ == NULL) return false; | 63 if (infinity_symbol_ == NULL) return false; |
64 if (value < 0) { | 64 if (value < 0) { |
65 result_builder->AddCharacter('-'); | 65 result_builder->AddCharacter('-'); |
66 } | 66 } |
67 result_builder->AddString(infinity_symbol_); | 67 result_builder->AddString(infinity_symbol_); |
68 return true; | 68 return true; |
69 } | 69 } |
70 if (double_inspect.IsNan()) { | 70 if (double_inspect.IsNan()) { |
71 if (nan_symbol_ == NULL) return false; | 71 if (nan_symbol_ == NULL) return false; |
72 result_builder->AddString(nan_symbol_); | 72 result_builder->AddString(nan_symbol_); |
73 return true; | 73 return true; |
74 } | 74 } |
75 return false; | 75 return false; |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 void DoubleToStringConverter::CreateExponentialRepresentation( | 79 void DoubleToStringConverter::CreateExponentialRepresentation( |
80 const char* de
cimal_digits, | 80 const char* de
cimal_digits, |
81 int length, | 81 int length, |
82 int exponent, | 82 int exponent, |
83 StringBuilder*
result_builder) const { | 83 StringBuilder*
result_builder) const { |
84 ASSERT(length != 0); | 84 ASSERT(length != 0); |
85 result_builder->AddCharacter(decimal_digits[0]); | 85 result_builder->AddCharacter(decimal_digits[0]); |
86 if (length != 1) { | 86 if (length != 1) { |
87 result_builder->AddCharacter('.'); | 87 result_builder->AddCharacter('.'); |
88 result_builder->AddSubstring(&decimal_digits[1], length-1); | 88 result_builder->AddSubstring(&decimal_digits[1], length-1); |
(...skipping 16 matching lines...) Expand all Loading... |
105 char buffer[kMaxExponentLength + 1]; | 105 char buffer[kMaxExponentLength + 1]; |
106 int first_char_pos = kMaxExponentLength; | 106 int first_char_pos = kMaxExponentLength; |
107 buffer[first_char_pos] = '\0'; | 107 buffer[first_char_pos] = '\0'; |
108 while (exponent > 0) { | 108 while (exponent > 0) { |
109 buffer[--first_char_pos] = '0' + (exponent % 10); | 109 buffer[--first_char_pos] = '0' + (exponent % 10); |
110 exponent /= 10; | 110 exponent /= 10; |
111 } | 111 } |
112 result_builder->AddSubstring(&buffer[first_char_pos], | 112 result_builder->AddSubstring(&buffer[first_char_pos], |
113 kMaxExponentLength - first_char_pos); | 113 kMaxExponentLength - first_char_pos); |
114 } | 114 } |
115 | 115 |
116 | 116 |
117 void DoubleToStringConverter::CreateDecimalRepresentation( | 117 void DoubleToStringConverter::CreateDecimalRepresentation( |
118 const char* decima
l_digits, | 118 const char* decima
l_digits, |
119 int length, | 119 int length, |
120 int decimal_point, | 120 int decimal_point, |
121 int digits_after_p
oint, | 121 int digits_after_p
oint, |
122 StringBuilder* res
ult_builder) const { | 122 StringBuilder* res
ult_builder) const { |
123 // Create a representation that is padded with zeros if needed. | 123 // Create a representation that is padded with zeros if needed. |
124 if (decimal_point <= 0) { | 124 if (decimal_point <= 0) { |
125 // "0.00000decimal_rep". | 125 // "0.00000decimal_rep". |
126 result_builder->AddCharacter('0'); | 126 result_builder->AddCharacter('0'); |
(...skipping 26 matching lines...) Expand all Loading... |
153 } | 153 } |
154 if (digits_after_point == 0) { | 154 if (digits_after_point == 0) { |
155 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { | 155 if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { |
156 result_builder->AddCharacter('.'); | 156 result_builder->AddCharacter('.'); |
157 } | 157 } |
158 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { | 158 if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { |
159 result_builder->AddCharacter('0'); | 159 result_builder->AddCharacter('0'); |
160 } | 160 } |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 | 164 |
165 bool DoubleToStringConverter::ToShortest(double value, | 165 bool DoubleToStringConverter::ToShortest(double value, |
166 StringBuilder* result_builder) cons
t { | 166 StringBuilder* result_builder) cons
t { |
167 if (Double(value).IsSpecial()) { | 167 if (Double(value).IsSpecial()) { |
168 return HandleSpecialValues(value, result_builder); | 168 return HandleSpecialValues(value, result_builder); |
169 } | 169 } |
170 | 170 |
171 int decimal_point; | 171 int decimal_point; |
172 bool sign; | 172 bool sign; |
173 const int kDecimalRepCapacity = kBase10MaximalLength + 1; | 173 const int kDecimalRepCapacity = kBase10MaximalLength + 1; |
174 char decimal_rep[kDecimalRepCapacity]; | 174 char decimal_rep[kDecimalRepCapacity]; |
175 int decimal_rep_length; | 175 int decimal_rep_length; |
176 | 176 |
177 DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, | 177 DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, |
178 &sign, &decimal_rep_length, &decimal_point); | 178 &sign, &decimal_rep_length, &decimal_point); |
179 | 179 |
180 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; | 180 bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; |
181 if (sign && (value != 0.0 || !unique_zero)) { | 181 if (sign && (value != 0.0 || !unique_zero)) { |
182 result_builder->AddCharacter('-'); | 182 result_builder->AddCharacter('-'); |
183 } | 183 } |
184 | 184 |
185 int exponent = decimal_point - 1; | 185 int exponent = decimal_point - 1; |
186 if ((decimal_in_shortest_low_ <= exponent) && | 186 if ((decimal_in_shortest_low_ <= exponent) && |
187 (exponent < decimal_in_shortest_high_)) { | 187 (exponent < decimal_in_shortest_high_)) { |
188 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, | 188 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, |
189 decimal_point, | 189 decimal_point, |
190 Max(0, decimal_rep_length - decimal_poin
t), | 190 Max(0, decimal_rep_length - decimal_poin
t), |
191 result_builder); | 191 result_builder); |
192 } else { | 192 } else { |
193 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exp
onent, | 193 CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exp
onent, |
194 result_builder); | 194 result_builder); |
195 } | 195 } |
196 return true; | 196 return true; |
197 } | 197 } |
198 | 198 |
199 | 199 |
200 bool DoubleToStringConverter::ToFixed(double value, | 200 bool DoubleToStringConverter::ToFixed(double value, |
201 int requested_digits, | 201 int requested_digits, |
202 StringBuilder* result_builder) const { | 202 StringBuilder* result_builder) const { |
203 ASSERT(kMaxFixedDigitsBeforePoint == 60); | 203 ASSERT(kMaxFixedDigitsBeforePoint == 60); |
204 const double kFirstNonFixed = 1e60; | 204 const double kFirstNonFixed = 1e60; |
205 | 205 |
206 if (Double(value).IsSpecial()) { | 206 if (Double(value).IsSpecial()) { |
207 return HandleSpecialValues(value, result_builder); | 207 return HandleSpecialValues(value, result_builder); |
208 } | 208 } |
209 | 209 |
210 if (requested_digits > kMaxFixedDigitsAfterPoint) return false; | 210 if (requested_digits > kMaxFixedDigitsAfterPoint) return false; |
211 if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; | 211 if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; |
212 | 212 |
213 // Find a sufficiently precise decimal representation of n. | 213 // Find a sufficiently precise decimal representation of n. |
214 int decimal_point; | 214 int decimal_point; |
215 bool sign; | 215 bool sign; |
216 // Add space for the '\0' byte. | 216 // Add space for the '\0' byte. |
217 const int kDecimalRepCapacity = | 217 const int kDecimalRepCapacity = |
218 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; | 218 kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; |
219 char decimal_rep[kDecimalRepCapacity]; | 219 char decimal_rep[kDecimalRepCapacity]; |
220 int decimal_rep_length; | 220 int decimal_rep_length; |
221 DoubleToAscii(value, FIXED, requested_digits, | 221 DoubleToAscii(value, FIXED, requested_digits, |
222 decimal_rep, kDecimalRepCapacity, | 222 decimal_rep, kDecimalRepCapacity, |
223 &sign, &decimal_rep_length, &decimal_point); | 223 &sign, &decimal_rep_length, &decimal_point); |
224 | 224 |
225 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); | 225 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
226 if (sign && (value != 0.0 || !unique_zero)) { | 226 if (sign && (value != 0.0 || !unique_zero)) { |
227 result_builder->AddCharacter('-'); | 227 result_builder->AddCharacter('-'); |
228 } | 228 } |
229 | 229 |
230 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_poi
nt, | 230 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_poi
nt, |
231 requested_digits, result_builder); | 231 requested_digits, result_builder); |
232 return true; | 232 return true; |
233 } | 233 } |
234 | 234 |
235 | 235 |
236 bool DoubleToStringConverter::ToExponential( | 236 bool DoubleToStringConverter::ToExponential( |
237 double value, | 237 double value, |
238 int requested_digits, | 238 int requested_digits, |
239 StringBuilder* result_builder) c
onst { | 239 StringBuilder* result_builder) c
onst { |
240 if (Double(value).IsSpecial()) { | 240 if (Double(value).IsSpecial()) { |
241 return HandleSpecialValues(value, result_builder); | 241 return HandleSpecialValues(value, result_builder); |
242 } | 242 } |
243 | 243 |
244 if (requested_digits < -1) return false; | 244 if (requested_digits < -1) return false; |
245 if (requested_digits > kMaxExponentialDigits) return false; | 245 if (requested_digits > kMaxExponentialDigits) return false; |
246 | 246 |
247 int decimal_point; | 247 int decimal_point; |
248 bool sign; | 248 bool sign; |
249 // Add space for digit before the decimal point and the '\0' character. | 249 // Add space for digit before the decimal point and the '\0' character. |
250 const int kDecimalRepCapacity = kMaxExponentialDigits + 2; | 250 const int kDecimalRepCapacity = kMaxExponentialDigits + 2; |
251 ASSERT(kDecimalRepCapacity > kBase10MaximalLength); | 251 ASSERT(kDecimalRepCapacity > kBase10MaximalLength); |
252 char decimal_rep[kDecimalRepCapacity]; | 252 char decimal_rep[kDecimalRepCapacity]; |
253 int decimal_rep_length; | 253 int decimal_rep_length; |
254 | 254 |
255 if (requested_digits == -1) { | 255 if (requested_digits == -1) { |
256 DoubleToAscii(value, SHORTEST, 0, | 256 DoubleToAscii(value, SHORTEST, 0, |
257 decimal_rep, kDecimalRepCapacity, | 257 decimal_rep, kDecimalRepCapacity, |
258 &sign, &decimal_rep_length, &decimal_point); | 258 &sign, &decimal_rep_length, &decimal_point); |
259 } else { | 259 } else { |
260 DoubleToAscii(value, PRECISION, requested_digits + 1, | 260 DoubleToAscii(value, PRECISION, requested_digits + 1, |
261 decimal_rep, kDecimalRepCapacity, | 261 decimal_rep, kDecimalRepCapacity, |
262 &sign, &decimal_rep_length, &decimal_point); | 262 &sign, &decimal_rep_length, &decimal_point); |
263 ASSERT(decimal_rep_length <= requested_digits + 1); | 263 ASSERT(decimal_rep_length <= requested_digits + 1); |
264 | 264 |
265 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { | 265 for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { |
266 decimal_rep[i] = '0'; | 266 decimal_rep[i] = '0'; |
267 } | 267 } |
268 decimal_rep_length = requested_digits + 1; | 268 decimal_rep_length = requested_digits + 1; |
269 } | 269 } |
270 | 270 |
271 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); | 271 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
272 if (sign && (value != 0.0 || !unique_zero)) { | 272 if (sign && (value != 0.0 || !unique_zero)) { |
273 result_builder->AddCharacter('-'); | 273 result_builder->AddCharacter('-'); |
274 } | 274 } |
275 | 275 |
276 int exponent = decimal_point - 1; | 276 int exponent = decimal_point - 1; |
277 CreateExponentialRepresentation(decimal_rep, | 277 CreateExponentialRepresentation(decimal_rep, |
278 decimal_rep_length, | 278 decimal_rep_length, |
279 exponent, | 279 exponent, |
280 result_builder); | 280 result_builder); |
281 return true; | 281 return true; |
282 } | 282 } |
283 | 283 |
284 | 284 |
285 bool DoubleToStringConverter::ToPrecision(double value, | 285 bool DoubleToStringConverter::ToPrecision(double value, |
286 int precision, | 286 int precision, |
287 StringBuilder* result_builder) con
st { | 287 StringBuilder* result_builder) con
st { |
288 if (Double(value).IsSpecial()) { | 288 if (Double(value).IsSpecial()) { |
289 return HandleSpecialValues(value, result_builder); | 289 return HandleSpecialValues(value, result_builder); |
290 } | 290 } |
291 | 291 |
292 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits)
{ | 292 if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits)
{ |
293 return false; | 293 return false; |
294 } | 294 } |
295 | 295 |
296 // Find a sufficiently precise decimal representation of n. | 296 // Find a sufficiently precise decimal representation of n. |
297 int decimal_point; | 297 int decimal_point; |
298 bool sign; | 298 bool sign; |
299 // Add one for the terminating null character. | 299 // Add one for the terminating null character. |
300 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; | 300 const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; |
301 char decimal_rep[kDecimalRepCapacity]; | 301 char decimal_rep[kDecimalRepCapacity]; |
302 int decimal_rep_length; | 302 int decimal_rep_length; |
303 | 303 |
304 DoubleToAscii(value, PRECISION, precision, | 304 DoubleToAscii(value, PRECISION, precision, |
305 decimal_rep, kDecimalRepCapacity, | 305 decimal_rep, kDecimalRepCapacity, |
306 &sign, &decimal_rep_length, &decimal_point); | 306 &sign, &decimal_rep_length, &decimal_point); |
307 ASSERT(decimal_rep_length <= precision); | 307 ASSERT(decimal_rep_length <= precision); |
308 | 308 |
309 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); | 309 bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
310 if (sign && (value != 0.0 || !unique_zero)) { | 310 if (sign && (value != 0.0 || !unique_zero)) { |
311 result_builder->AddCharacter('-'); | 311 result_builder->AddCharacter('-'); |
312 } | 312 } |
313 | 313 |
314 // The exponent if we print the number as x.xxeyyy. That is with the | 314 // The exponent if we print the number as x.xxeyyy. That is with the |
315 // decimal point after the first digit. | 315 // decimal point after the first digit. |
316 int exponent = decimal_point - 1; | 316 int exponent = decimal_point - 1; |
317 | 317 |
318 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 :
0; | 318 int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 :
0; |
319 if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_)
|| | 319 if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_)
|| |
320 (decimal_point - precision + extra_zero > | 320 (decimal_point - precision + extra_zero > |
321 max_trailing_padding_zeroes_in_precision_mode_)) { | 321 max_trailing_padding_zeroes_in_precision_mode_)) { |
322 // Fill buffer to contain 'precision' digits. | 322 // Fill buffer to contain 'precision' digits. |
323 // Usually the buffer is already at the correct length, but 'Dou
bleToAscii' | 323 // Usually the buffer is already at the correct length, but 'Dou
bleToAscii' |
324 // is allowed to return less characters. | 324 // is allowed to return less characters. |
325 for (int i = decimal_rep_length; i < precision; ++i) { | 325 for (int i = decimal_rep_length; i < precision; ++i) { |
326 decimal_rep[i] = '0'; | 326 decimal_rep[i] = '0'; |
327 } | 327 } |
328 | 328 |
329 CreateExponentialRepresentation(decimal_rep, | 329 CreateExponentialRepresentation(decimal_rep, |
330 precision, | 330 precision, |
331 exponent, | 331 exponent, |
332 result_builder); | 332 result_builder); |
333 } else { | 333 } else { |
334 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, dec
imal_point, | 334 CreateDecimalRepresentation(decimal_rep, decimal_rep_length, dec
imal_point, |
335 Max(0, precision - decimal_point), | 335 Max(0, precision - decimal_point), |
336 result_builder); | 336 result_builder); |
337 } | 337 } |
338 return true; | 338 return true; |
339 } | 339 } |
340 | 340 |
341 | 341 |
342 static BignumDtoaMode DtoaToBignumDtoaMode( | 342 static BignumDtoaMode DtoaToBignumDtoaMode( |
343 DoubleToStringConverter::DtoaMode
dtoa_mode) { | 343 DoubleToStringConverter::DtoaMode
dtoa_mode) { |
344 switch (dtoa_mode) { | 344 switch (dtoa_mode) { |
345 case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST
; | 345 case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST
; |
346 case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; | 346 case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; |
347 case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISIO
N; | 347 case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISIO
N; |
348 default: | 348 default: |
349 UNREACHABLE(); | 349 UNREACHABLE(); |
350 return BIGNUM_DTOA_SHORTEST; // To silence compiler. | 350 return BIGNUM_DTOA_SHORTEST; // To silence compiler. |
351 } | 351 } |
352 } | 352 } |
353 | 353 |
354 | 354 |
355 void DoubleToStringConverter::DoubleToAscii(double v, | 355 void DoubleToStringConverter::DoubleToAscii(double v, |
356 DtoaMode mode, | 356 DtoaMode mode, |
357 int requested_digits, | 357 int requested_digits, |
358 char* buffer, | 358 char* buffer, |
359 int buffer_length, | 359 int buffer_length, |
360 bool* sign, | 360 bool* sign, |
361 int* length, | 361 int* length, |
362 int* point) { | 362 int* point) { |
363 Vector<char> vector(buffer, buffer_length); | 363 Vector<char> vector(buffer, buffer_length); |
364 ASSERT(!Double(v).IsSpecial()); | 364 ASSERT(!Double(v).IsSpecial()); |
365 ASSERT(mode == SHORTEST || requested_digits >= 0); | 365 ASSERT(mode == SHORTEST || requested_digits >= 0); |
366 | 366 |
367 if (Double(v).Sign() < 0) { | 367 if (Double(v).Sign() < 0) { |
368 *sign = true; | 368 *sign = true; |
369 v = -v; | 369 v = -v; |
370 } else { | 370 } else { |
371 *sign = false; | 371 *sign = false; |
372 } | 372 } |
373 | 373 |
374 if (mode == PRECISION && requested_digits == 0) { | 374 if (mode == PRECISION && requested_digits == 0) { |
375 vector[0] = '\0'; | 375 vector[0] = '\0'; |
376 *length = 0; | 376 *length = 0; |
377 return; | 377 return; |
378 } | 378 } |
379 | 379 |
380 if (v == 0) { | 380 if (v == 0) { |
381 vector[0] = '0'; | 381 vector[0] = '0'; |
382 vector[1] = '\0'; | 382 vector[1] = '\0'; |
383 *length = 1; | 383 *length = 1; |
384 *point = 1; | 384 *point = 1; |
385 return; | 385 return; |
386 } | 386 } |
387 | 387 |
388 bool fast_worked; | 388 bool fast_worked; |
389 switch (mode) { | 389 switch (mode) { |
390 case SHORTEST: | 390 case SHORTEST: |
391 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length,
point); | 391 fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length,
point); |
392 break; | 392 break; |
393 case FIXED: | 393 case FIXED: |
394 fast_worked = FastFixedDtoa(v, requested_digits, vector, length,
point); | 394 fast_worked = FastFixedDtoa(v, requested_digits, vector, length,
point); |
395 break; | 395 break; |
396 case PRECISION: | 396 case PRECISION: |
397 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, | 397 fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, |
398 vector, length, point); | 398 vector, length, point); |
399 break; | 399 break; |
400 default: | 400 default: |
401 UNREACHABLE(); | 401 UNREACHABLE(); |
402 fast_worked = false; | 402 fast_worked = false; |
403 } | 403 } |
404 if (fast_worked) return; | 404 if (fast_worked) return; |
405 | 405 |
406 // If the fast dtoa didn't succeed use the slower bignum version. | 406 // If the fast dtoa didn't succeed use the slower bignum version. |
407 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode); | 407 BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode); |
408 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point); | 408 BignumDtoa(v, bignum_mode, requested_digits, vector, length, point); |
409 vector[*length] = '\0'; | 409 vector[*length] = '\0'; |
410 } | 410 } |
411 | 411 |
412 | 412 |
413 // Maximum number of significant digits in decimal representation. | 413 // Maximum number of significant digits in decimal representation. |
414 // The longest possible double in decimal representation is | 414 // The longest possible double in decimal representation is |
415 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 | 415 // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 |
416 // (768 digits). If we parse a number whose first digits are equal to a | 416 // (768 digits). If we parse a number whose first digits are equal to a |
417 // mean of 2 adjacent doubles (that could have up to 769 digits) the result | 417 // mean of 2 adjacent doubles (that could have up to 769 digits) the result |
418 // must be rounded to the bigger one unless the tail consists of zeros, so | 418 // must be rounded to the bigger one unless the tail consists of zeros, so |
419 // we don't need to preserve all the digits. | 419 // we don't need to preserve all the digits. |
420 const int kMaxSignificantDigits = 772; | 420 const int kMaxSignificantDigits = 772; |
421 | 421 |
422 | 422 |
423 static double SignedZero(bool sign) { | 423 static double SignedZero(bool sign) { |
424 return sign ? -0.0 : 0.0; | 424 return sign ? -0.0 : 0.0; |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 double StringToDoubleConverter::StringToDouble( | 428 double StringToDoubleConverter::StringToDouble( |
429 const char* input, | 429 const char* input, |
430 size_t length, | 430 size_t length, |
431 size_t* processed_characters_
count) { | 431 size_t* processed_characters_
count) { |
432 const char* current = input; | 432 const char* current = input; |
433 const char* end = input + length; | 433 const char* end = input + length; |
434 | 434 |
435 *processed_characters_count = 0; | 435 *processed_characters_count = 0; |
436 | 436 |
437 // To make sure that iterator dereferencing is valid the following | 437 // To make sure that iterator dereferencing is valid the following |
438 // convention is used: | 438 // convention is used: |
439 // 1. Each '++current' statement is followed by check for equality to 'e
nd'. | 439 // 1. Each '++current' statement is followed by check for equality to 'e
nd'. |
440 // 3. If 'current' becomes equal to 'end' the function returns or goes t
o | 440 // 3. If 'current' becomes equal to 'end' the function returns or goes t
o |
441 // 'parsing_done'. | 441 // 'parsing_done'. |
442 // 4. 'current' is not dereferenced after the 'parsing_done' label. | 442 // 4. 'current' is not dereferenced after the 'parsing_done' label. |
443 // 5. Code before 'parsing_done' may rely on 'current != end'. | 443 // 5. Code before 'parsing_done' may rely on 'current != end'. |
444 if (current == end) return 0.0; | 444 if (current == end) return 0.0; |
445 | 445 |
446 // The longest form of simplified number is: "-<significant digits>.1eXX
X\0". | 446 // The longest form of simplified number is: "-<significant digits>.1eXX
X\0". |
447 const int kBufferSize = kMaxSignificantDigits + 10; | 447 const int kBufferSize = kMaxSignificantDigits + 10; |
448 char buffer[kBufferSize]; // NOLINT: size is known at compile time. | 448 char buffer[kBufferSize]; // NOLINT: size is known at compile time. |
449 int buffer_pos = 0; | 449 int buffer_pos = 0; |
450 | 450 |
451 // Exponent will be adjusted if insignificant digits of the integer part | 451 // Exponent will be adjusted if insignificant digits of the integer part |
452 // or insignificant leading zeros of the fractional part are dropped. | 452 // or insignificant leading zeros of the fractional part are dropped. |
453 int exponent = 0; | 453 int exponent = 0; |
454 int significant_digits = 0; | 454 int significant_digits = 0; |
455 int insignificant_digits = 0; | 455 int insignificant_digits = 0; |
456 bool nonzero_digit_dropped = false; | 456 bool nonzero_digit_dropped = false; |
457 bool sign = false; | 457 bool sign = false; |
458 | 458 |
459 if (*current == '+' || *current == '-') { | 459 if (*current == '+' || *current == '-') { |
460 sign = (*current == '-'); | 460 sign = (*current == '-'); |
461 ++current; | 461 ++current; |
462 if (current == end) return 0.0; | 462 if (current == end) return 0.0; |
463 } | 463 } |
464 | 464 |
465 bool leading_zero = false; | 465 bool leading_zero = false; |
466 if (*current == '0') { | 466 if (*current == '0') { |
467 ++current; | 467 ++current; |
468 if (current == end) { | 468 if (current == end) { |
469 *processed_characters_count = current - input; | 469 *processed_characters_count = current - input; |
470 return SignedZero(sign); | 470 return SignedZero(sign); |
471 } | 471 } |
472 | 472 |
473 leading_zero = true; | 473 leading_zero = true; |
474 | 474 |
475 // Ignore leading zeros in the integer part. | 475 // Ignore leading zeros in the integer part. |
476 while (*current == '0') { | 476 while (*current == '0') { |
477 ++current; | 477 ++current; |
478 if (current == end) { | 478 if (current == end) { |
479 *processed_characters_count = current - input; | 479 *processed_characters_count = current - input; |
480 return SignedZero(sign); | 480 return SignedZero(sign); |
481 } | 481 } |
482 } | 482 } |
483 } | 483 } |
484 | 484 |
485 // Copy significant digits of the integer part (if any) to the buffer. | 485 // Copy significant digits of the integer part (if any) to the buffer. |
486 while (*current >= '0' && *current <= '9') { | 486 while (*current >= '0' && *current <= '9') { |
487 if (significant_digits < kMaxSignificantDigits) { | 487 if (significant_digits < kMaxSignificantDigits) { |
488 ASSERT(buffer_pos < kBufferSize); | 488 ASSERT(buffer_pos < kBufferSize); |
489 buffer[buffer_pos++] = static_cast<char>(*current); | 489 buffer[buffer_pos++] = static_cast<char>(*current); |
490 significant_digits++; | 490 significant_digits++; |
491 } else { | 491 } else { |
492 insignificant_digits++; // Move the digit into the exponential
part. | 492 insignificant_digits++; // Move the digit into the exponential
part. |
493 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'
; | 493 nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'
; |
494 } | 494 } |
495 ++current; | 495 ++current; |
496 if (current == end) goto parsing_done; | 496 if (current == end) goto parsing_done; |
497 } | 497 } |
498 | 498 |
499 if (*current == '.') { | 499 if (*current == '.') { |
500 ++current; | 500 ++current; |
501 if (current == end) { | 501 if (current == end) { |
502 if (significant_digits == 0 && !leading_zero) { | 502 if (significant_digits == 0 && !leading_zero) { |
503 return 0.0; | 503 return 0.0; |
504 } else { | 504 } else { |
505 goto parsing_done; | 505 goto parsing_done; |
506 } | 506 } |
507 } | 507 } |
508 | 508 |
509 if (significant_digits == 0) { | 509 if (significant_digits == 0) { |
510 // Integer part consists of 0 or is absent. Significant digits s
tart after | 510 // Integer part consists of 0 or is absent. Significant digits s
tart after |
511 // leading zeros (if any). | 511 // leading zeros (if any). |
512 while (*current == '0') { | 512 while (*current == '0') { |
513 ++current; | 513 ++current; |
514 if (current == end) { | 514 if (current == end) { |
515 *processed_characters_count = current - input; | 515 *processed_characters_count = current - input; |
516 return SignedZero(sign); | 516 return SignedZero(sign); |
517 } | 517 } |
518 exponent--; // Move this 0 into the exponent. | 518 exponent--; // Move this 0 into the exponent. |
519 } | 519 } |
520 } | 520 } |
521 | 521 |
522 // There is a fractional part. | 522 // There is a fractional part. |
523 while (*current >= '0' && *current <= '9') { | 523 while (*current >= '0' && *current <= '9') { |
524 if (significant_digits < kMaxSignificantDigits) { | 524 if (significant_digits < kMaxSignificantDigits) { |
525 ASSERT(buffer_pos < kBufferSize); | 525 ASSERT(buffer_pos < kBufferSize); |
526 buffer[buffer_pos++] = static_cast<char>(*current); | 526 buffer[buffer_pos++] = static_cast<char>(*current); |
527 significant_digits++; | 527 significant_digits++; |
528 exponent--; | 528 exponent--; |
529 } else { | 529 } else { |
530 // Ignore insignificant digits in the fractional part. | 530 // Ignore insignificant digits in the fractional part. |
531 nonzero_digit_dropped = nonzero_digit_dropped || *current !=
'0'; | 531 nonzero_digit_dropped = nonzero_digit_dropped || *current !=
'0'; |
532 } | 532 } |
533 ++current; | 533 ++current; |
534 if (current == end) goto parsing_done; | 534 if (current == end) goto parsing_done; |
535 } | 535 } |
536 } | 536 } |
537 | 537 |
538 if (!leading_zero && exponent == 0 && significant_digits == 0) { | 538 if (!leading_zero && exponent == 0 && significant_digits == 0) { |
539 // If leading_zeros is true then the string contains zeros. | 539 // If leading_zeros is true then the string contains zeros. |
540 // If exponent < 0 then string was [+-]\.0*... | 540 // If exponent < 0 then string was [+-]\.0*... |
541 // If significant_digits != 0 the string is not equal to 0. | 541 // If significant_digits != 0 the string is not equal to 0. |
542 // Otherwise there are no digits in the string. | 542 // Otherwise there are no digits in the string. |
543 return 0.0; | 543 return 0.0; |
544 } | 544 } |
545 | 545 |
546 // Parse exponential part. | 546 // Parse exponential part. |
547 if (*current == 'e' || *current == 'E') { | 547 if (*current == 'e' || *current == 'E') { |
548 ++current; | 548 ++current; |
549 if (current == end) { | 549 if (current == end) { |
550 --current; | 550 --current; |
551 goto parsing_done; | 551 goto parsing_done; |
552 } | 552 } |
553 char sign = 0; | 553 char sign = 0; |
554 if (*current == '+' || *current == '-') { | 554 if (*current == '+' || *current == '-') { |
555 sign = static_cast<char>(*current); | 555 sign = static_cast<char>(*current); |
556 ++current; | 556 ++current; |
557 if (current == end) { | 557 if (current == end) { |
558 current -= 2; | 558 current -= 2; |
559 goto parsing_done; | 559 goto parsing_done; |
560 } | 560 } |
561 } | 561 } |
562 | 562 |
563 if (*current < '0' || *current > '9') { | 563 if (*current < '0' || *current > '9') { |
564 if (sign) | 564 if (sign) |
565 --current; | 565 --current; |
566 --current; | 566 --current; |
567 goto parsing_done; | 567 goto parsing_done; |
568 } | 568 } |
569 | 569 |
570 const int max_exponent = INT_MAX / 2; | 570 const int max_exponent = INT_MAX / 2; |
571 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2
); | 571 ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2
); |
572 int num = 0; | 572 int num = 0; |
573 do { | 573 do { |
574 // Check overflow. | 574 // Check overflow. |
575 int digit = *current - '0'; | 575 int digit = *current - '0'; |
576 if (num >= max_exponent / 10 | 576 if (num >= max_exponent / 10 |
577 && !(num == max_exponent / 10 && digit <= max_exponent % 10)
) { | 577 && !(num == max_exponent / 10 && digit <= max_exponent % 10)
) { |
578 num = max_exponent; | 578 num = max_exponent; |
579 } else { | 579 } else { |
580 num = num * 10 + digit; | 580 num = num * 10 + digit; |
581 } | 581 } |
582 ++current; | 582 ++current; |
583 } while (current != end && *current >= '0' && *current <= '9'); | 583 } while (current != end && *current >= '0' && *current <= '9'); |
584 | 584 |
585 exponent += (sign == '-' ? -num : num); | 585 exponent += (sign == '-' ? -num : num); |
586 } | 586 } |
587 | 587 |
588 parsing_done: | 588 parsing_done: |
589 exponent += insignificant_digits; | 589 exponent += insignificant_digits; |
590 | 590 |
591 if (nonzero_digit_dropped) { | 591 if (nonzero_digit_dropped) { |
592 buffer[buffer_pos++] = '1'; | 592 buffer[buffer_pos++] = '1'; |
593 exponent--; | 593 exponent--; |
594 } | 594 } |
595 | 595 |
596 ASSERT(buffer_pos < kBufferSize); | 596 ASSERT(buffer_pos < kBufferSize); |
597 buffer[buffer_pos] = '\0'; | 597 buffer[buffer_pos] = '\0'; |
598 | 598 |
599 double converted = Strtod(Vector<const char>(buffer, buffer_pos), expone
nt); | 599 double converted = Strtod(Vector<const char>(buffer, buffer_pos), expone
nt); |
600 *processed_characters_count = current - input; | 600 *processed_characters_count = current - input; |
601 return sign? -converted: converted; | 601 return sign? -converted: converted; |
602 } | 602 } |
603 | 603 |
604 } // namespace double_conversion | 604 } // namespace double_conversion |
605 | 605 |
606 } // namespace WTF | 606 } // namespace WTF |
OLD | NEW |