1 | // Copyright 2010 the V8 project authors. All rights reserved. |
2 | // Redistribution and use in source and binary forms, with or without |
3 | // modification, are permitted provided that the following conditions are |
4 | // met: |
5 | // |
6 | // * Redistributions of source code must retain the above copyright |
7 | // notice, this list of conditions and the following disclaimer. |
8 | // * Redistributions in binary form must reproduce the above |
9 | // copyright notice, this list of conditions and the following |
10 | // disclaimer in the documentation and/or other materials provided |
11 | // with the distribution. |
12 | // * Neither the name of Google Inc. nor the names of its |
13 | // contributors may be used to endorse or promote products derived |
14 | // from this software without specific prior written permission. |
15 | // |
16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | |
28 | #include <climits> |
29 | #include <locale> |
30 | #include <cmath> |
31 | |
32 | #include <double-conversion/double-conversion.h> |
33 | |
34 | #include <double-conversion/bignum-dtoa.h> |
35 | #include <double-conversion/fast-dtoa.h> |
36 | #include <double-conversion/fixed-dtoa.h> |
37 | #include <double-conversion/ieee.h> |
38 | #include <double-conversion/strtod.h> |
39 | #include <double-conversion/utils.h> |
40 | |
41 | // Fix warning C4244: 'argument': conversion from 'const uc16' to 'char', possible loss of data |
42 | #ifdef _MSC_VER |
43 | __pragma(warning(disable: 4244)) |
44 | #endif |
45 | |
46 | namespace double_conversion { |
47 | |
48 | const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() { |
49 | int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; |
50 | static DoubleToStringConverter converter(flags, |
51 | "Infinity" , |
52 | "NaN" , |
53 | 'e', |
54 | -6, 21, |
55 | 6, 0); |
56 | return converter; |
57 | } |
58 | |
59 | |
60 | bool DoubleToStringConverter::HandleSpecialValues( |
61 | double value, |
62 | StringBuilder* result_builder) const { |
63 | Double double_inspect(value); |
64 | if (double_inspect.IsInfinite()) { |
65 | if (infinity_symbol_ == NULL) return false; |
66 | if (value < 0) { |
67 | result_builder->AddCharacter(c: '-'); |
68 | } |
69 | result_builder->AddString(s: infinity_symbol_); |
70 | return true; |
71 | } |
72 | if (double_inspect.IsNan()) { |
73 | if (nan_symbol_ == NULL) return false; |
74 | result_builder->AddString(s: nan_symbol_); |
75 | return true; |
76 | } |
77 | return false; |
78 | } |
79 | |
80 | |
81 | void DoubleToStringConverter::CreateExponentialRepresentation( |
82 | const char* decimal_digits, |
83 | int length, |
84 | int exponent, |
85 | StringBuilder* result_builder) const { |
86 | ASSERT(length != 0); |
87 | result_builder->AddCharacter(c: decimal_digits[0]); |
88 | if (length != 1) { |
89 | result_builder->AddCharacter(c: '.'); |
90 | result_builder->AddSubstring(s: &decimal_digits[1], n: length-1); |
91 | } |
92 | result_builder->AddCharacter(c: exponent_character_); |
93 | if (exponent < 0) { |
94 | result_builder->AddCharacter(c: '-'); |
95 | exponent = -exponent; |
96 | } else { |
97 | if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) { |
98 | result_builder->AddCharacter(c: '+'); |
99 | } |
100 | } |
101 | if (exponent == 0) { |
102 | result_builder->AddCharacter(c: '0'); |
103 | return; |
104 | } |
105 | ASSERT(exponent < 1e4); |
106 | const int kMaxExponentLength = 5; |
107 | char buffer[kMaxExponentLength + 1]; |
108 | buffer[kMaxExponentLength] = '\0'; |
109 | int first_char_pos = kMaxExponentLength; |
110 | while (exponent > 0) { |
111 | buffer[--first_char_pos] = '0' + (exponent % 10); |
112 | exponent /= 10; |
113 | } |
114 | result_builder->AddSubstring(s: &buffer[first_char_pos], |
115 | n: kMaxExponentLength - first_char_pos); |
116 | } |
117 | |
118 | |
119 | void DoubleToStringConverter::CreateDecimalRepresentation( |
120 | const char* decimal_digits, |
121 | int length, |
122 | int decimal_point, |
123 | int digits_after_point, |
124 | StringBuilder* result_builder) const { |
125 | // Create a representation that is padded with zeros if needed. |
126 | if (decimal_point <= 0) { |
127 | // "0.00000decimal_rep" or "0.000decimal_rep00". |
128 | result_builder->AddCharacter(c: '0'); |
129 | if (digits_after_point > 0) { |
130 | result_builder->AddCharacter(c: '.'); |
131 | result_builder->AddPadding(c: '0', count: -decimal_point); |
132 | ASSERT(length <= digits_after_point - (-decimal_point)); |
133 | result_builder->AddSubstring(s: decimal_digits, n: length); |
134 | int remaining_digits = digits_after_point - (-decimal_point) - length; |
135 | result_builder->AddPadding(c: '0', count: remaining_digits); |
136 | } |
137 | } else if (decimal_point >= length) { |
138 | // "decimal_rep0000.00000" or "decimal_rep.0000". |
139 | result_builder->AddSubstring(s: decimal_digits, n: length); |
140 | result_builder->AddPadding(c: '0', count: decimal_point - length); |
141 | if (digits_after_point > 0) { |
142 | result_builder->AddCharacter(c: '.'); |
143 | result_builder->AddPadding(c: '0', count: digits_after_point); |
144 | } |
145 | } else { |
146 | // "decima.l_rep000". |
147 | ASSERT(digits_after_point > 0); |
148 | result_builder->AddSubstring(s: decimal_digits, n: decimal_point); |
149 | result_builder->AddCharacter(c: '.'); |
150 | ASSERT(length - decimal_point <= digits_after_point); |
151 | result_builder->AddSubstring(s: &decimal_digits[decimal_point], |
152 | n: length - decimal_point); |
153 | int remaining_digits = digits_after_point - (length - decimal_point); |
154 | result_builder->AddPadding(c: '0', count: remaining_digits); |
155 | } |
156 | if (digits_after_point == 0) { |
157 | if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { |
158 | result_builder->AddCharacter(c: '.'); |
159 | } |
160 | if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { |
161 | result_builder->AddCharacter(c: '0'); |
162 | } |
163 | } |
164 | } |
165 | |
166 | |
167 | bool DoubleToStringConverter::ToShortestIeeeNumber( |
168 | double value, |
169 | StringBuilder* result_builder, |
170 | DoubleToStringConverter::DtoaMode mode) const { |
171 | ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE); |
172 | if (Double(value).IsSpecial()) { |
173 | return HandleSpecialValues(value, result_builder); |
174 | } |
175 | |
176 | int decimal_point; |
177 | bool sign; |
178 | const int kDecimalRepCapacity = kBase10MaximalLength + 1; |
179 | char decimal_rep[kDecimalRepCapacity]; |
180 | int decimal_rep_length; |
181 | |
182 | DoubleToAscii(v: value, mode, requested_digits: 0, buffer: decimal_rep, buffer_length: kDecimalRepCapacity, |
183 | sign: &sign, length: &decimal_rep_length, point: &decimal_point); |
184 | |
185 | bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; |
186 | if (sign && (value != 0.0 || !unique_zero)) { |
187 | result_builder->AddCharacter(c: '-'); |
188 | } |
189 | |
190 | int exponent = decimal_point - 1; |
191 | if ((decimal_in_shortest_low_ <= exponent) && |
192 | (exponent < decimal_in_shortest_high_)) { |
193 | CreateDecimalRepresentation(decimal_digits: decimal_rep, length: decimal_rep_length, |
194 | decimal_point, |
195 | digits_after_point: Max(a: 0, b: decimal_rep_length - decimal_point), |
196 | result_builder); |
197 | } else { |
198 | CreateExponentialRepresentation(decimal_digits: decimal_rep, length: decimal_rep_length, exponent, |
199 | result_builder); |
200 | } |
201 | return true; |
202 | } |
203 | |
204 | |
205 | bool DoubleToStringConverter::ToFixed(double value, |
206 | int requested_digits, |
207 | StringBuilder* result_builder) const { |
208 | ASSERT(kMaxFixedDigitsBeforePoint == 60); |
209 | const double kFirstNonFixed = 1e60; |
210 | |
211 | if (Double(value).IsSpecial()) { |
212 | return HandleSpecialValues(value, result_builder); |
213 | } |
214 | |
215 | if (requested_digits > kMaxFixedDigitsAfterPoint) return false; |
216 | if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; |
217 | |
218 | // Find a sufficiently precise decimal representation of n. |
219 | int decimal_point; |
220 | bool sign; |
221 | // Add space for the '\0' byte. |
222 | const int kDecimalRepCapacity = |
223 | kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; |
224 | char decimal_rep[kDecimalRepCapacity]; |
225 | int decimal_rep_length; |
226 | DoubleToAscii(v: value, mode: FIXED, requested_digits, |
227 | buffer: decimal_rep, buffer_length: kDecimalRepCapacity, |
228 | sign: &sign, length: &decimal_rep_length, point: &decimal_point); |
229 | |
230 | bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
231 | if (sign && (value != 0.0 || !unique_zero)) { |
232 | result_builder->AddCharacter(c: '-'); |
233 | } |
234 | |
235 | CreateDecimalRepresentation(decimal_digits: decimal_rep, length: decimal_rep_length, decimal_point, |
236 | digits_after_point: requested_digits, result_builder); |
237 | return true; |
238 | } |
239 | |
240 | |
241 | bool DoubleToStringConverter::ToExponential( |
242 | double value, |
243 | int requested_digits, |
244 | StringBuilder* result_builder) const { |
245 | if (Double(value).IsSpecial()) { |
246 | return HandleSpecialValues(value, result_builder); |
247 | } |
248 | |
249 | if (requested_digits < -1) return false; |
250 | if (requested_digits > kMaxExponentialDigits) return false; |
251 | |
252 | int decimal_point; |
253 | bool sign; |
254 | // Add space for digit before the decimal point and the '\0' character. |
255 | const int kDecimalRepCapacity = kMaxExponentialDigits + 2; |
256 | ASSERT(kDecimalRepCapacity > kBase10MaximalLength); |
257 | char decimal_rep[kDecimalRepCapacity]; |
258 | #ifndef NDEBUG |
259 | // Problem: there is an assert in StringBuilder::AddSubstring() that |
260 | // will pass this buffer to strlen(), and this buffer is not generally |
261 | // null-terminated. |
262 | memset(s: decimal_rep, c: 0, n: sizeof(decimal_rep)); |
263 | #endif |
264 | int decimal_rep_length; |
265 | |
266 | if (requested_digits == -1) { |
267 | DoubleToAscii(v: value, mode: SHORTEST, requested_digits: 0, |
268 | buffer: decimal_rep, buffer_length: kDecimalRepCapacity, |
269 | sign: &sign, length: &decimal_rep_length, point: &decimal_point); |
270 | } else { |
271 | DoubleToAscii(v: value, mode: PRECISION, requested_digits: requested_digits + 1, |
272 | buffer: decimal_rep, buffer_length: kDecimalRepCapacity, |
273 | sign: &sign, length: &decimal_rep_length, point: &decimal_point); |
274 | ASSERT(decimal_rep_length <= requested_digits + 1); |
275 | |
276 | for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { |
277 | decimal_rep[i] = '0'; |
278 | } |
279 | decimal_rep_length = requested_digits + 1; |
280 | } |
281 | |
282 | bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
283 | if (sign && (value != 0.0 || !unique_zero)) { |
284 | result_builder->AddCharacter(c: '-'); |
285 | } |
286 | |
287 | int exponent = decimal_point - 1; |
288 | CreateExponentialRepresentation(decimal_digits: decimal_rep, |
289 | length: decimal_rep_length, |
290 | exponent, |
291 | result_builder); |
292 | return true; |
293 | } |
294 | |
295 | |
296 | bool DoubleToStringConverter::ToPrecision(double value, |
297 | int precision, |
298 | StringBuilder* result_builder) const { |
299 | if (Double(value).IsSpecial()) { |
300 | return HandleSpecialValues(value, result_builder); |
301 | } |
302 | |
303 | if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) { |
304 | return false; |
305 | } |
306 | |
307 | // Find a sufficiently precise decimal representation of n. |
308 | int decimal_point; |
309 | bool sign; |
310 | // Add one for the terminating null character. |
311 | const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; |
312 | char decimal_rep[kDecimalRepCapacity]; |
313 | int decimal_rep_length; |
314 | |
315 | DoubleToAscii(v: value, mode: PRECISION, requested_digits: precision, |
316 | buffer: decimal_rep, buffer_length: kDecimalRepCapacity, |
317 | sign: &sign, length: &decimal_rep_length, point: &decimal_point); |
318 | ASSERT(decimal_rep_length <= precision); |
319 | |
320 | bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); |
321 | if (sign && (value != 0.0 || !unique_zero)) { |
322 | result_builder->AddCharacter(c: '-'); |
323 | } |
324 | |
325 | // The exponent if we print the number as x.xxeyyy. That is with the |
326 | // decimal point after the first digit. |
327 | int exponent = decimal_point - 1; |
328 | |
329 | int = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0; |
330 | if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) || |
331 | (decimal_point - precision + extra_zero > |
332 | max_trailing_padding_zeroes_in_precision_mode_)) { |
333 | // Fill buffer to contain 'precision' digits. |
334 | // Usually the buffer is already at the correct length, but 'DoubleToAscii' |
335 | // is allowed to return less characters. |
336 | for (int i = decimal_rep_length; i < precision; ++i) { |
337 | decimal_rep[i] = '0'; |
338 | } |
339 | |
340 | CreateExponentialRepresentation(decimal_digits: decimal_rep, |
341 | length: precision, |
342 | exponent, |
343 | result_builder); |
344 | } else { |
345 | CreateDecimalRepresentation(decimal_digits: decimal_rep, length: decimal_rep_length, decimal_point, |
346 | digits_after_point: Max(a: 0, b: precision - decimal_point), |
347 | result_builder); |
348 | } |
349 | return true; |
350 | } |
351 | |
352 | |
353 | static BignumDtoaMode DtoaToBignumDtoaMode( |
354 | DoubleToStringConverter::DtoaMode dtoa_mode) { |
355 | switch (dtoa_mode) { |
356 | case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST; |
357 | case DoubleToStringConverter::SHORTEST_SINGLE: |
358 | return BIGNUM_DTOA_SHORTEST_SINGLE; |
359 | case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; |
360 | case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; |
361 | default: |
362 | UNREACHABLE(); |
363 | } |
364 | } |
365 | |
366 | |
367 | void DoubleToStringConverter::DoubleToAscii(double v, |
368 | DtoaMode mode, |
369 | int requested_digits, |
370 | char* buffer, |
371 | int buffer_length, |
372 | bool* sign, |
373 | int* length, |
374 | int* point) { |
375 | Vector<char> vector(buffer, buffer_length); |
376 | ASSERT(!Double(v).IsSpecial()); |
377 | ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0); |
378 | |
379 | if (Double(v).Sign() < 0) { |
380 | *sign = true; |
381 | v = -v; |
382 | } else { |
383 | *sign = false; |
384 | } |
385 | |
386 | if (mode == PRECISION && requested_digits == 0) { |
387 | vector[0] = '\0'; |
388 | *length = 0; |
389 | return; |
390 | } |
391 | |
392 | if (v == 0) { |
393 | vector[0] = '0'; |
394 | vector[1] = '\0'; |
395 | *length = 1; |
396 | *point = 1; |
397 | return; |
398 | } |
399 | |
400 | bool fast_worked; |
401 | switch (mode) { |
402 | case SHORTEST: |
403 | fast_worked = FastDtoa(d: v, mode: FAST_DTOA_SHORTEST, requested_digits: 0, buffer: vector, length, decimal_point: point); |
404 | break; |
405 | case SHORTEST_SINGLE: |
406 | fast_worked = FastDtoa(d: v, mode: FAST_DTOA_SHORTEST_SINGLE, requested_digits: 0, |
407 | buffer: vector, length, decimal_point: point); |
408 | break; |
409 | case FIXED: |
410 | fast_worked = FastFixedDtoa(v, fractional_count: requested_digits, buffer: vector, length, decimal_point: point); |
411 | break; |
412 | case PRECISION: |
413 | fast_worked = FastDtoa(d: v, mode: FAST_DTOA_PRECISION, requested_digits, |
414 | buffer: vector, length, decimal_point: point); |
415 | break; |
416 | default: |
417 | fast_worked = false; |
418 | UNREACHABLE(); |
419 | } |
420 | if (fast_worked) return; |
421 | |
422 | // If the fast dtoa didn't succeed use the slower bignum version. |
423 | BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(dtoa_mode: mode); |
424 | BignumDtoa(v, mode: bignum_mode, requested_digits, buffer: vector, length, point); |
425 | vector[*length] = '\0'; |
426 | } |
427 | |
428 | |
429 | namespace { |
430 | |
431 | inline char ToLower(char ch) { |
432 | static const std::ctype<char>& cType = |
433 | std::use_facet<std::ctype<char> >(loc: std::locale::classic()); |
434 | return cType.tolower(c: ch); |
435 | } |
436 | |
437 | inline char Pass(char ch) { |
438 | return ch; |
439 | } |
440 | |
441 | template <class Iterator, class Converter> |
442 | static inline bool ConsumeSubStringImpl(Iterator* current, |
443 | Iterator end, |
444 | const char* substring, |
445 | Converter converter) { |
446 | ASSERT(converter(**current) == *substring); |
447 | for (substring++; *substring != '\0'; substring++) { |
448 | ++*current; |
449 | if (*current == end || converter(**current) != *substring) { |
450 | return false; |
451 | } |
452 | } |
453 | ++*current; |
454 | return true; |
455 | } |
456 | |
457 | // Consumes the given substring from the iterator. |
458 | // Returns false, if the substring does not match. |
459 | template <class Iterator> |
460 | static bool ConsumeSubString(Iterator* current, |
461 | Iterator end, |
462 | const char* substring, |
463 | bool allow_case_insensibility) { |
464 | if (allow_case_insensibility) { |
465 | return ConsumeSubStringImpl(current, end, substring, ToLower); |
466 | } else { |
467 | return ConsumeSubStringImpl(current, end, substring, Pass); |
468 | } |
469 | } |
470 | |
471 | // Consumes first character of the str is equal to ch |
472 | inline bool ConsumeFirstCharacter(char ch, |
473 | const char* str, |
474 | bool case_insensibility) { |
475 | return case_insensibility ? ToLower(ch) == str[0] : ch == str[0]; |
476 | } |
477 | } // namespace |
478 | |
479 | // Maximum number of significant digits in decimal representation. |
480 | // The longest possible double in decimal representation is |
481 | // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 |
482 | // (768 digits). If we parse a number whose first digits are equal to a |
483 | // mean of 2 adjacent doubles (that could have up to 769 digits) the result |
484 | // must be rounded to the bigger one unless the tail consists of zeros, so |
485 | // we don't need to preserve all the digits. |
486 | const int kMaxSignificantDigits = 772; |
487 | |
488 | |
489 | static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; |
490 | static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7); |
491 | |
492 | |
493 | static const uc16 kWhitespaceTable16[] = { |
494 | 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195, |
495 | 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279 |
496 | }; |
497 | static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16); |
498 | |
499 | |
500 | static bool isWhitespace(int x) { |
501 | if (x < 128) { |
502 | for (int i = 0; i < kWhitespaceTable7Length; i++) { |
503 | if (kWhitespaceTable7[i] == x) return true; |
504 | } |
505 | } else { |
506 | for (int i = 0; i < kWhitespaceTable16Length; i++) { |
507 | if (kWhitespaceTable16[i] == x) return true; |
508 | } |
509 | } |
510 | return false; |
511 | } |
512 | |
513 | |
514 | // Returns true if a nonspace found and false if the end has reached. |
515 | template <class Iterator> |
516 | static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { |
517 | while (*current != end) { |
518 | if (!isWhitespace(**current)) return true; |
519 | ++*current; |
520 | } |
521 | return false; |
522 | } |
523 | |
524 | |
525 | static bool isDigit(int x, int radix) { |
526 | return (x >= '0' && x <= '9' && x < '0' + radix) |
527 | || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) |
528 | || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); |
529 | } |
530 | |
531 | |
532 | static double SignedZero(bool sign) { |
533 | return sign ? -0.0 : 0.0; |
534 | } |
535 | |
536 | |
537 | // Returns true if 'c' is a decimal digit that is valid for the given radix. |
538 | static bool inline IsDecimalDigitForRadix(int c, int radix) { |
539 | return '0' <= c && c <= '9' && (c - '0') < radix; |
540 | } |
541 | |
542 | // Returns true if 'c' is a character digit that is valid for the given radix. |
543 | // The 'a_character' should be 'a' or 'A'. |
544 | // |
545 | // The function is small and could be inlined, but VS2012 emitted a warning |
546 | // because it constant-propagated the radix and concluded that the first |
547 | // condition was always false. By moving it into a separate function the |
548 | // compiler wouldn't warn anymore. |
549 | static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { |
550 | return radix > 10 && c >= a_character && c < a_character + radix - 10; |
551 | } |
552 | |
553 | // Returns true, when the iterator is equal to end. |
554 | template<class Iterator> |
555 | static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) { |
556 | if (separator == StringToDoubleConverter::kNoSeparator) { |
557 | ++(*it); |
558 | return *it == end; |
559 | } |
560 | if (!isDigit(**it, base)) { |
561 | ++(*it); |
562 | return *it == end; |
563 | } |
564 | ++(*it); |
565 | if (*it == end) return true; |
566 | if (*it + 1 == end) return false; |
567 | if (**it == separator && isDigit(*(*it + 1), base)) { |
568 | ++(*it); |
569 | } |
570 | return *it == end; |
571 | } |
572 | |
573 | // Checks whether the string in the range start-end is a hex-float string. |
574 | // This function assumes that the leading '0x'/'0X' is already consumed. |
575 | // |
576 | // Hex float strings are of one of the following forms: |
577 | // - hex_digits+ 'p' ('+'|'-')? exponent_digits+ |
578 | // - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+ |
579 | // - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+ |
580 | template<class Iterator> |
581 | static bool IsHexFloatString(Iterator start, |
582 | Iterator end, |
583 | uc16 separator, |
584 | bool allow_trailing_junk) { |
585 | ASSERT(start != end); |
586 | |
587 | Iterator current = start; |
588 | |
589 | bool saw_digit = false; |
590 | while (isDigit(*current, 16)) { |
591 | saw_digit = true; |
592 | if (Advance(¤t, separator, 16, end)) return false; |
593 | } |
594 | if (*current == '.') { |
595 | if (Advance(¤t, separator, 16, end)) return false; |
596 | while (isDigit(*current, 16)) { |
597 | saw_digit = true; |
598 | if (Advance(¤t, separator, 16, end)) return false; |
599 | } |
600 | } |
601 | if (!saw_digit) return false; |
602 | if (*current != 'p' && *current != 'P') return false; |
603 | if (Advance(¤t, separator, 16, end)) return false; |
604 | if (*current == '+' || *current == '-') { |
605 | if (Advance(¤t, separator, 16, end)) return false; |
606 | } |
607 | if (!isDigit(*current, 10)) return false; |
608 | if (Advance(¤t, separator, 16, end)) return true; |
609 | while (isDigit(*current, 10)) { |
610 | if (Advance(¤t, separator, 16, end)) return true; |
611 | } |
612 | return allow_trailing_junk || !AdvanceToNonspace(¤t, end); |
613 | } |
614 | |
615 | |
616 | // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. |
617 | // |
618 | // If parse_as_hex_float is true, then the string must be a valid |
619 | // hex-float. |
620 | template <int radix_log_2, class Iterator> |
621 | static double RadixStringToIeee(Iterator* current, |
622 | Iterator end, |
623 | bool sign, |
624 | uc16 separator, |
625 | bool parse_as_hex_float, |
626 | bool allow_trailing_junk, |
627 | double junk_string_value, |
628 | bool read_as_double, |
629 | bool* result_is_junk) { |
630 | ASSERT(*current != end); |
631 | ASSERT(!parse_as_hex_float || |
632 | IsHexFloatString(*current, end, separator, allow_trailing_junk)); |
633 | |
634 | const int kDoubleSize = Double::kSignificandSize; |
635 | const int kSingleSize = Single::kSignificandSize; |
636 | const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize; |
637 | |
638 | *result_is_junk = true; |
639 | |
640 | int64_t number = 0; |
641 | int exponent = 0; |
642 | const int radix = (1 << radix_log_2); |
643 | // Whether we have encountered a '.' and are parsing the decimal digits. |
644 | // Only relevant if parse_as_hex_float is true. |
645 | bool post_decimal = false; |
646 | |
647 | // Skip leading 0s. |
648 | while (**current == '0') { |
649 | if (Advance(current, separator, radix, end)) { |
650 | *result_is_junk = false; |
651 | return SignedZero(sign); |
652 | } |
653 | } |
654 | |
655 | while (true) { |
656 | int digit; |
657 | if (IsDecimalDigitForRadix(**current, radix)) { |
658 | digit = static_cast<char>(**current) - '0'; |
659 | if (post_decimal) exponent -= radix_log_2; |
660 | } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { |
661 | digit = static_cast<char>(**current) - 'a' + 10; |
662 | if (post_decimal) exponent -= radix_log_2; |
663 | } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { |
664 | digit = static_cast<char>(**current) - 'A' + 10; |
665 | if (post_decimal) exponent -= radix_log_2; |
666 | } else if (parse_as_hex_float && **current == '.') { |
667 | post_decimal = true; |
668 | Advance(current, separator, radix, end); |
669 | ASSERT(*current != end); |
670 | continue; |
671 | } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { |
672 | break; |
673 | } else { |
674 | if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { |
675 | break; |
676 | } else { |
677 | return junk_string_value; |
678 | } |
679 | } |
680 | |
681 | number = number * radix + digit; |
682 | int overflow = static_cast<int>(number >> kSignificandSize); |
683 | if (overflow != 0) { |
684 | // Overflow occurred. Need to determine which direction to round the |
685 | // result. |
686 | int overflow_bits_count = 1; |
687 | while (overflow > 1) { |
688 | overflow_bits_count++; |
689 | overflow >>= 1; |
690 | } |
691 | |
692 | int dropped_bits_mask = ((1 << overflow_bits_count) - 1); |
693 | int dropped_bits = static_cast<int>(number) & dropped_bits_mask; |
694 | number >>= overflow_bits_count; |
695 | exponent += overflow_bits_count; |
696 | |
697 | bool zero_tail = true; |
698 | for (;;) { |
699 | if (Advance(current, separator, radix, end)) break; |
700 | if (parse_as_hex_float && **current == '.') { |
701 | // Just run over the '.'. We are just trying to see whether there is |
702 | // a non-zero digit somewhere. |
703 | Advance(current, separator, radix, end); |
704 | ASSERT(*current != end); |
705 | post_decimal = true; |
706 | } |
707 | if (!isDigit(**current, radix)) break; |
708 | zero_tail = zero_tail && **current == '0'; |
709 | if (!post_decimal) exponent += radix_log_2; |
710 | } |
711 | |
712 | if (!parse_as_hex_float && |
713 | !allow_trailing_junk && |
714 | AdvanceToNonspace(current, end)) { |
715 | return junk_string_value; |
716 | } |
717 | |
718 | int middle_value = (1 << (overflow_bits_count - 1)); |
719 | if (dropped_bits > middle_value) { |
720 | number++; // Rounding up. |
721 | } else if (dropped_bits == middle_value) { |
722 | // Rounding to even to consistency with decimals: half-way case rounds |
723 | // up if significant part is odd and down otherwise. |
724 | if ((number & 1) != 0 || !zero_tail) { |
725 | number++; // Rounding up. |
726 | } |
727 | } |
728 | |
729 | // Rounding up may cause overflow. |
730 | if ((number & ((int64_t)1 << kSignificandSize)) != 0) { |
731 | exponent++; |
732 | number >>= 1; |
733 | } |
734 | break; |
735 | } |
736 | if (Advance(current, separator, radix, end)) break; |
737 | } |
738 | |
739 | ASSERT(number < ((int64_t)1 << kSignificandSize)); |
740 | ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); |
741 | |
742 | *result_is_junk = false; |
743 | |
744 | if (parse_as_hex_float) { |
745 | ASSERT(**current == 'p' || **current == 'P'); |
746 | Advance(current, separator, radix, end); |
747 | ASSERT(*current != end); |
748 | bool is_negative = false; |
749 | if (**current == '+') { |
750 | Advance(current, separator, radix, end); |
751 | ASSERT(*current != end); |
752 | } else if (**current == '-') { |
753 | is_negative = true; |
754 | Advance(current, separator, radix, end); |
755 | ASSERT(*current != end); |
756 | } |
757 | int written_exponent = 0; |
758 | while (IsDecimalDigitForRadix(**current, 10)) { |
759 | // No need to read exponents if they are too big. That could potentially overflow |
760 | // the `written_exponent` variable. |
761 | if (abs(x: written_exponent) <= 100 * Double::kMaxExponent) { |
762 | written_exponent = 10 * written_exponent + **current - '0'; |
763 | } |
764 | if (Advance(current, separator, radix, end)) break; |
765 | } |
766 | if (is_negative) written_exponent = -written_exponent; |
767 | exponent += written_exponent; |
768 | } |
769 | |
770 | if (exponent == 0 || number == 0) { |
771 | if (sign) { |
772 | if (number == 0) return -0.0; |
773 | number = -number; |
774 | } |
775 | return static_cast<double>(number); |
776 | } |
777 | |
778 | ASSERT(number != 0); |
779 | double result = Double(DiyFp(number, exponent)).value(); |
780 | return sign ? -result : result; |
781 | } |
782 | |
783 | template <class Iterator> |
784 | double StringToDoubleConverter::StringToIeee( |
785 | Iterator input, |
786 | int length, |
787 | bool read_as_double, |
788 | int* processed_characters_count) const { |
789 | Iterator current = input; |
790 | Iterator end = input + length; |
791 | |
792 | *processed_characters_count = 0; |
793 | |
794 | const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; |
795 | const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; |
796 | const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; |
797 | const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; |
798 | const bool allow_case_insensibility = (flags_ & ALLOW_CASE_INSENSIBILITY) != 0; |
799 | |
800 | // To make sure that iterator dereferencing is valid the following |
801 | // convention is used: |
802 | // 1. Each '++current' statement is followed by check for equality to 'end'. |
803 | // 2. If AdvanceToNonspace returned false then current == end. |
804 | // 3. If 'current' becomes equal to 'end' the function returns or goes to |
805 | // 'parsing_done'. |
806 | // 4. 'current' is not dereferenced after the 'parsing_done' label. |
807 | // 5. Code before 'parsing_done' may rely on 'current != end'. |
808 | if (current == end) return empty_string_value_; |
809 | |
810 | if (allow_leading_spaces || allow_trailing_spaces) { |
811 | if (!AdvanceToNonspace(¤t, end)) { |
812 | *processed_characters_count = static_cast<int>(current - input); |
813 | return empty_string_value_; |
814 | } |
815 | if (!allow_leading_spaces && (input != current)) { |
816 | // No leading spaces allowed, but AdvanceToNonspace moved forward. |
817 | return junk_string_value_; |
818 | } |
819 | } |
820 | |
821 | // The longest form of simplified number is: "-<significant digits>.1eXXX\0". |
822 | const int kBufferSize = kMaxSignificantDigits + 10; |
823 | char buffer[kBufferSize]; // NOLINT: size is known at compile time. |
824 | int buffer_pos = 0; |
825 | |
826 | // Exponent will be adjusted if insignificant digits of the integer part |
827 | // or insignificant leading zeros of the fractional part are dropped. |
828 | int exponent = 0; |
829 | int significant_digits = 0; |
830 | int insignificant_digits = 0; |
831 | bool nonzero_digit_dropped = false; |
832 | |
833 | bool sign = false; |
834 | |
835 | if (*current == '+' || *current == '-') { |
836 | sign = (*current == '-'); |
837 | ++current; |
838 | Iterator next_non_space = current; |
839 | // Skip following spaces (if allowed). |
840 | if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; |
841 | if (!allow_spaces_after_sign && (current != next_non_space)) { |
842 | return junk_string_value_; |
843 | } |
844 | current = next_non_space; |
845 | } |
846 | |
847 | if (infinity_symbol_ != NULL) { |
848 | if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensibility)) { |
849 | if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensibility)) { |
850 | return junk_string_value_; |
851 | } |
852 | |
853 | if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { |
854 | return junk_string_value_; |
855 | } |
856 | if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
857 | return junk_string_value_; |
858 | } |
859 | |
860 | ASSERT(buffer_pos == 0); |
861 | *processed_characters_count = static_cast<int>(current - input); |
862 | return sign ? -Double::Infinity() : Double::Infinity(); |
863 | } |
864 | } |
865 | |
866 | if (nan_symbol_ != NULL) { |
867 | if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensibility)) { |
868 | if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensibility)) { |
869 | return junk_string_value_; |
870 | } |
871 | |
872 | if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { |
873 | return junk_string_value_; |
874 | } |
875 | if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
876 | return junk_string_value_; |
877 | } |
878 | |
879 | ASSERT(buffer_pos == 0); |
880 | *processed_characters_count = static_cast<int>(current - input); |
881 | return sign ? -Double::NaN() : Double::NaN(); |
882 | } |
883 | } |
884 | |
885 | bool leading_zero = false; |
886 | if (*current == '0') { |
887 | if (Advance(¤t, separator_, 10, end)) { |
888 | *processed_characters_count = static_cast<int>(current - input); |
889 | return SignedZero(sign); |
890 | } |
891 | |
892 | leading_zero = true; |
893 | |
894 | // It could be hexadecimal value. |
895 | if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) && |
896 | (*current == 'x' || *current == 'X')) { |
897 | ++current; |
898 | |
899 | if (current == end) return junk_string_value_; // "0x" |
900 | |
901 | bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) && |
902 | IsHexFloatString(current, end, separator_, allow_trailing_junk); |
903 | |
904 | if (!parse_as_hex_float && !isDigit(*current, 16)) { |
905 | return junk_string_value_; |
906 | } |
907 | |
908 | bool result_is_junk; |
909 | double result = RadixStringToIeee<4>(¤t, |
910 | end, |
911 | sign, |
912 | separator_, |
913 | parse_as_hex_float, |
914 | allow_trailing_junk, |
915 | junk_string_value_, |
916 | read_as_double, |
917 | &result_is_junk); |
918 | if (!result_is_junk) { |
919 | if (allow_trailing_spaces) AdvanceToNonspace(¤t, end); |
920 | *processed_characters_count = static_cast<int>(current - input); |
921 | } |
922 | return result; |
923 | } |
924 | |
925 | // Ignore leading zeros in the integer part. |
926 | while (*current == '0') { |
927 | if (Advance(¤t, separator_, 10, end)) { |
928 | *processed_characters_count = static_cast<int>(current - input); |
929 | return SignedZero(sign); |
930 | } |
931 | } |
932 | } |
933 | |
934 | bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; |
935 | |
936 | // Copy significant digits of the integer part (if any) to the buffer. |
937 | while (*current >= '0' && *current <= '9') { |
938 | if (significant_digits < kMaxSignificantDigits) { |
939 | ASSERT(buffer_pos < kBufferSize); |
940 | buffer[buffer_pos++] = static_cast<char>(*current); |
941 | significant_digits++; |
942 | // Will later check if it's an octal in the buffer. |
943 | } else { |
944 | insignificant_digits++; // Move the digit into the exponential part. |
945 | nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
946 | } |
947 | octal = octal && *current < '8'; |
948 | if (Advance(¤t, separator_, 10, end)) goto parsing_done; |
949 | } |
950 | |
951 | if (significant_digits == 0) { |
952 | octal = false; |
953 | } |
954 | |
955 | if (*current == '.') { |
956 | if (octal && !allow_trailing_junk) return junk_string_value_; |
957 | if (octal) goto parsing_done; |
958 | |
959 | if (Advance(¤t, separator_, 10, end)) { |
960 | if (significant_digits == 0 && !leading_zero) { |
961 | return junk_string_value_; |
962 | } else { |
963 | goto parsing_done; |
964 | } |
965 | } |
966 | |
967 | if (significant_digits == 0) { |
968 | // octal = false; |
969 | // Integer part consists of 0 or is absent. Significant digits start after |
970 | // leading zeros (if any). |
971 | while (*current == '0') { |
972 | if (Advance(¤t, separator_, 10, end)) { |
973 | *processed_characters_count = static_cast<int>(current - input); |
974 | return SignedZero(sign); |
975 | } |
976 | exponent--; // Move this 0 into the exponent. |
977 | } |
978 | } |
979 | |
980 | // There is a fractional part. |
981 | // We don't emit a '.', but adjust the exponent instead. |
982 | while (*current >= '0' && *current <= '9') { |
983 | if (significant_digits < kMaxSignificantDigits) { |
984 | ASSERT(buffer_pos < kBufferSize); |
985 | buffer[buffer_pos++] = static_cast<char>(*current); |
986 | significant_digits++; |
987 | exponent--; |
988 | } else { |
989 | // Ignore insignificant digits in the fractional part. |
990 | nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; |
991 | } |
992 | if (Advance(¤t, separator_, 10, end)) goto parsing_done; |
993 | } |
994 | } |
995 | |
996 | if (!leading_zero && exponent == 0 && significant_digits == 0) { |
997 | // If leading_zeros is true then the string contains zeros. |
998 | // If exponent < 0 then string was [+-]\.0*... |
999 | // If significant_digits != 0 the string is not equal to 0. |
1000 | // Otherwise there are no digits in the string. |
1001 | return junk_string_value_; |
1002 | } |
1003 | |
1004 | // Parse exponential part. |
1005 | if (*current == 'e' || *current == 'E') { |
1006 | if (octal && !allow_trailing_junk) return junk_string_value_; |
1007 | if (octal) goto parsing_done; |
1008 | Iterator junk_begin = current; |
1009 | ++current; |
1010 | if (current == end) { |
1011 | if (allow_trailing_junk) { |
1012 | current = junk_begin; |
1013 | goto parsing_done; |
1014 | } else { |
1015 | return junk_string_value_; |
1016 | } |
1017 | } |
1018 | char exponen_sign = '+'; |
1019 | if (*current == '+' || *current == '-') { |
1020 | exponen_sign = static_cast<char>(*current); |
1021 | ++current; |
1022 | if (current == end) { |
1023 | if (allow_trailing_junk) { |
1024 | current = junk_begin; |
1025 | goto parsing_done; |
1026 | } else { |
1027 | return junk_string_value_; |
1028 | } |
1029 | } |
1030 | } |
1031 | |
1032 | if (current == end || *current < '0' || *current > '9') { |
1033 | if (allow_trailing_junk) { |
1034 | current = junk_begin; |
1035 | goto parsing_done; |
1036 | } else { |
1037 | return junk_string_value_; |
1038 | } |
1039 | } |
1040 | |
1041 | const int max_exponent = INT_MAX / 2; |
1042 | ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); |
1043 | int num = 0; |
1044 | do { |
1045 | // Check overflow. |
1046 | int digit = *current - '0'; |
1047 | if (num >= max_exponent / 10 |
1048 | && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { |
1049 | num = max_exponent; |
1050 | } else { |
1051 | num = num * 10 + digit; |
1052 | } |
1053 | ++current; |
1054 | } while (current != end && *current >= '0' && *current <= '9'); |
1055 | |
1056 | exponent += (exponen_sign == '-' ? -num : num); |
1057 | } |
1058 | |
1059 | if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { |
1060 | return junk_string_value_; |
1061 | } |
1062 | if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { |
1063 | return junk_string_value_; |
1064 | } |
1065 | if (allow_trailing_spaces) { |
1066 | AdvanceToNonspace(¤t, end); |
1067 | } |
1068 | |
1069 | parsing_done: |
1070 | exponent += insignificant_digits; |
1071 | |
1072 | if (octal) { |
1073 | double result; |
1074 | bool result_is_junk; |
1075 | char* start = buffer; |
1076 | result = RadixStringToIeee<3>(current: &start, |
1077 | end: buffer + buffer_pos, |
1078 | sign, |
1079 | separator: separator_, |
1080 | parse_as_hex_float: false, // Don't parse as hex_float. |
1081 | allow_trailing_junk, |
1082 | junk_string_value: junk_string_value_, |
1083 | read_as_double, |
1084 | result_is_junk: &result_is_junk); |
1085 | ASSERT(!result_is_junk); |
1086 | *processed_characters_count = static_cast<int>(current - input); |
1087 | return result; |
1088 | } |
1089 | |
1090 | if (nonzero_digit_dropped) { |
1091 | buffer[buffer_pos++] = '1'; |
1092 | exponent--; |
1093 | } |
1094 | |
1095 | ASSERT(buffer_pos < kBufferSize); |
1096 | buffer[buffer_pos] = '\0'; |
1097 | |
1098 | double converted; |
1099 | if (read_as_double) { |
1100 | converted = Strtod(buffer: Vector<const char>(buffer, buffer_pos), exponent); |
1101 | } else { |
1102 | converted = Strtof(buffer: Vector<const char>(buffer, buffer_pos), exponent); |
1103 | } |
1104 | *processed_characters_count = static_cast<int>(current - input); |
1105 | return sign? -converted: converted; |
1106 | } |
1107 | |
1108 | |
1109 | double StringToDoubleConverter::StringToDouble( |
1110 | const char* buffer, |
1111 | int length, |
1112 | int* processed_characters_count) const { |
1113 | return StringToIeee(input: buffer, length, read_as_double: true, processed_characters_count); |
1114 | } |
1115 | |
1116 | |
1117 | double StringToDoubleConverter::StringToDouble( |
1118 | const uc16* buffer, |
1119 | int length, |
1120 | int* processed_characters_count) const { |
1121 | return StringToIeee(input: buffer, length, read_as_double: true, processed_characters_count); |
1122 | } |
1123 | |
1124 | |
1125 | float StringToDoubleConverter::StringToFloat( |
1126 | const char* buffer, |
1127 | int length, |
1128 | int* processed_characters_count) const { |
1129 | return static_cast<float>(StringToIeee(input: buffer, length, read_as_double: false, |
1130 | processed_characters_count)); |
1131 | } |
1132 | |
1133 | |
1134 | float StringToDoubleConverter::StringToFloat( |
1135 | const uc16* buffer, |
1136 | int length, |
1137 | int* processed_characters_count) const { |
1138 | return static_cast<float>(StringToIeee(input: buffer, length, read_as_double: false, |
1139 | processed_characters_count)); |
1140 | } |
1141 | |
1142 | } // namespace double_conversion |
1143 | |