/src/icu/source/i18n/double-conversion-string-to-double.cpp
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | // © 2018 and later: Unicode, Inc. and others.  | 
2  |  | // License & terms of use: http://www.unicode.org/copyright.html  | 
3  |  | //  | 
4  |  | // From the double-conversion library. Original license:  | 
5  |  | //  | 
6  |  | // Copyright 2010 the V8 project authors. All rights reserved.  | 
7  |  | // Redistribution and use in source and binary forms, with or without  | 
8  |  | // modification, are permitted provided that the following conditions are  | 
9  |  | // met:  | 
10  |  | //  | 
11  |  | //     * Redistributions of source code must retain the above copyright  | 
12  |  | //       notice, this list of conditions and the following disclaimer.  | 
13  |  | //     * Redistributions in binary form must reproduce the above  | 
14  |  | //       copyright notice, this list of conditions and the following  | 
15  |  | //       disclaimer in the documentation and/or other materials provided  | 
16  |  | //       with the distribution.  | 
17  |  | //     * Neither the name of Google Inc. nor the names of its  | 
18  |  | //       contributors may be used to endorse or promote products derived  | 
19  |  | //       from this software without specific prior written permission.  | 
20  |  | //  | 
21  |  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  | 
22  |  | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  | 
23  |  | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  | 
24  |  | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | 
25  |  | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  | 
26  |  | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  | 
27  |  | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  | 
28  |  | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  | 
29  |  | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  | 
30  |  | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  | 
31  |  | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  | 
32  |  |  | 
33  |  | // ICU PATCH: ifdef around UCONFIG_NO_FORMATTING  | 
34  |  | #include "unicode/utypes.h"  | 
35  |  | #if !UCONFIG_NO_FORMATTING  | 
36  |  |  | 
37  |  | // ICU PATCH: Do not include std::locale.  | 
38  |  |  | 
39  |  | #include <climits>  | 
40  |  | // #include <locale>  | 
41  |  | #include <cmath>  | 
42  |  |  | 
43  |  | // ICU PATCH: Customize header file paths for ICU.  | 
44  |  |  | 
45  |  | #include "double-conversion-string-to-double.h"  | 
46  |  |  | 
47  |  | #include "double-conversion-ieee.h"  | 
48  |  | #include "double-conversion-strtod.h"  | 
49  |  | #include "double-conversion-utils.h"  | 
50  |  |  | 
51  |  | // ICU PATCH: Wrap in ICU namespace  | 
52  |  | U_NAMESPACE_BEGIN  | 
53  |  |  | 
54  |  | #ifdef _MSC_VER  | 
55  |  | #  if _MSC_VER >= 1900  | 
56  |  | // Fix MSVC >= 2015 (_MSC_VER == 1900) warning  | 
57  |  | // C4244: 'argument': conversion from 'const uc16' to 'char', possible loss of data  | 
58  |  | // against Advance and friends, when instantiated with **it as char, not uc16.  | 
59  |  |  __pragma(warning(disable: 4244))  | 
60  |  | #  endif  | 
61  |  | #  if _MSC_VER <= 1700 // VS2012, see IsDecimalDigitForRadix warning fix, below  | 
62  |  | #    define VS2012_RADIXWARN  | 
63  |  | #  endif  | 
64  |  | #endif  | 
65  |  |  | 
66  |  | namespace double_conversion { | 
67  |  |  | 
68  |  | namespace { | 
69  |  |  | 
70  | 0  | inline char ToLower(char ch) { | 
71  |  | #if 0  // do not include std::locale in ICU  | 
72  |  |   static const std::ctype<char>& cType =  | 
73  |  |       std::use_facet<std::ctype<char> >(std::locale::classic());  | 
74  |  |   return cType.tolower(ch);  | 
75  |  | #else  | 
76  | 0  |   (void)ch;  | 
77  | 0  |   DOUBLE_CONVERSION_UNREACHABLE();  | 
78  | 0  | #endif  | 
79  | 0  | }  | 
80  |  |  | 
81  | 0  | inline char Pass(char ch) { | 
82  | 0  |   return ch;  | 
83  | 0  | }  | 
84  |  |  | 
85  |  | template <class Iterator, class Converter>  | 
86  |  | static inline bool ConsumeSubStringImpl(Iterator* current,  | 
87  |  |                                         Iterator end,  | 
88  |  |                                         const char* substring,  | 
89  | 0  |                                         Converter converter) { | 
90  | 0  |   DOUBLE_CONVERSION_ASSERT(converter(**current) == *substring);  | 
91  | 0  |   for (substring++; *substring != '\0'; substring++) { | 
92  | 0  |     ++*current;  | 
93  | 0  |     if (*current == end || converter(**current) != *substring) { | 
94  | 0  |       return false;  | 
95  | 0  |     }  | 
96  | 0  |   }  | 
97  | 0  |   ++*current;  | 
98  | 0  |   return true;  | 
99  | 0  | } Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::(anonymous namespace)::ConsumeSubStringImpl<char const*, char (*)(char)>(char const**, char const*, char const*, char (*)(char)) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::(anonymous namespace)::ConsumeSubStringImpl<unsigned short const*, char (*)(char)>(unsigned short const**, unsigned short const*, char const*, char (*)(char))  | 
100  |  |  | 
101  |  | // Consumes the given substring from the iterator.  | 
102  |  | // Returns false, if the substring does not match.  | 
103  |  | template <class Iterator>  | 
104  |  | static bool ConsumeSubString(Iterator* current,  | 
105  |  |                              Iterator end,  | 
106  |  |                              const char* substring,  | 
107  | 0  |                              bool allow_case_insensitivity) { | 
108  | 0  |   if (allow_case_insensitivity) { | 
109  | 0  |     return ConsumeSubStringImpl(current, end, substring, ToLower);  | 
110  | 0  |   } else { | 
111  | 0  |     return ConsumeSubStringImpl(current, end, substring, Pass);  | 
112  | 0  |   }  | 
113  | 0  | } Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::(anonymous namespace)::ConsumeSubString<char const*>(char const**, char const*, char const*, bool) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::(anonymous namespace)::ConsumeSubString<unsigned short const*>(unsigned short const**, unsigned short const*, char const*, bool)  | 
114  |  |  | 
115  |  | // Consumes first character of the str is equal to ch  | 
116  |  | inline bool ConsumeFirstCharacter(char ch,  | 
117  |  |                                          const char* str,  | 
118  | 0  |                                          bool case_insensitivity) { | 
119  | 0  |   return case_insensitivity ? ToLower(ch) == str[0] : ch == str[0];  | 
120  | 0  | }  | 
121  |  | }  // namespace  | 
122  |  |  | 
123  |  | // Maximum number of significant digits in decimal representation.  | 
124  |  | // The longest possible double in decimal representation is  | 
125  |  | // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074  | 
126  |  | // (768 digits). If we parse a number whose first digits are equal to a  | 
127  |  | // mean of 2 adjacent doubles (that could have up to 769 digits) the result  | 
128  |  | // must be rounded to the bigger one unless the tail consists of zeros, so  | 
129  |  | // we don't need to preserve all the digits.  | 
130  |  | const int kMaxSignificantDigits = 772;  | 
131  |  |  | 
132  |  |  | 
133  |  | static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 }; | 
134  |  | static const int kWhitespaceTable7Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable7);  | 
135  |  |  | 
136  |  |  | 
137  |  | static const uc16 kWhitespaceTable16[] = { | 
138  |  |   160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,  | 
139  |  |   8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279  | 
140  |  | };  | 
141  |  | static const int kWhitespaceTable16Length = DOUBLE_CONVERSION_ARRAY_SIZE(kWhitespaceTable16);  | 
142  |  |  | 
143  |  |  | 
144  | 0  | static bool isWhitespace(int x) { | 
145  | 0  |   if (x < 128) { | 
146  | 0  |     for (int i = 0; i < kWhitespaceTable7Length; i++) { | 
147  | 0  |       if (kWhitespaceTable7[i] == x) return true;  | 
148  | 0  |     }  | 
149  | 0  |   } else { | 
150  | 0  |     for (int i = 0; i < kWhitespaceTable16Length; i++) { | 
151  | 0  |       if (kWhitespaceTable16[i] == x) return true;  | 
152  | 0  |     }  | 
153  | 0  |   }  | 
154  | 0  |   return false;  | 
155  | 0  | }  | 
156  |  |  | 
157  |  |  | 
158  |  | // Returns true if a nonspace found and false if the end has reached.  | 
159  |  | template <class Iterator>  | 
160  | 0  | static inline bool AdvanceToNonspace(Iterator* current, Iterator end) { | 
161  | 0  |   while (*current != end) { | 
162  | 0  |     if (!isWhitespace(**current)) return true;  | 
163  | 0  |     ++*current;  | 
164  | 0  |   }  | 
165  | 0  |   return false;  | 
166  | 0  | } Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::AdvanceToNonspace<char const*>(char const**, char const*) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::AdvanceToNonspace<char*>(char**, char*) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::AdvanceToNonspace<unsigned short const*>(unsigned short const**, unsigned short const*)  | 
167  |  |  | 
168  |  |  | 
169  | 0  | static bool isDigit(int x, int radix) { | 
170  | 0  |   return (x >= '0' && x <= '9' && x < '0' + radix)  | 
171  | 0  |       || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)  | 
172  | 0  |       || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);  | 
173  | 0  | }  | 
174  |  |  | 
175  |  |  | 
176  | 0  | static double SignedZero(bool sign) { | 
177  | 0  |   return sign ? -0.0 : 0.0;  | 
178  | 0  | }  | 
179  |  |  | 
180  |  |  | 
181  |  | // Returns true if 'c' is a decimal digit that is valid for the given radix.  | 
182  |  | //  | 
183  |  | // The function is small and could be inlined, but VS2012 emitted a warning  | 
184  |  | // because it constant-propagated the radix and concluded that the last  | 
185  |  | // condition was always true. Moving it into a separate function and  | 
186  |  | // suppressing optimisation keeps the compiler from warning.  | 
187  |  | #ifdef VS2012_RADIXWARN  | 
188  |  | #pragma optimize("",off) | 
189  |  | static bool IsDecimalDigitForRadix(int c, int radix) { | 
190  |  |   return '0' <= c && c <= '9' && (c - '0') < radix;  | 
191  |  | }  | 
192  |  | #pragma optimize("",on) | 
193  |  | #else  | 
194  | 0  | static bool inline IsDecimalDigitForRadix(int c, int radix) { | 
195  | 0  |   return '0' <= c && c <= '9' && (c - '0') < radix;  | 
196  | 0  | }  | 
197  |  | #endif  | 
198  |  | // Returns true if 'c' is a character digit that is valid for the given radix.  | 
199  |  | // The 'a_character' should be 'a' or 'A'.  | 
200  |  | //  | 
201  |  | // The function is small and could be inlined, but VS2012 emitted a warning  | 
202  |  | // because it constant-propagated the radix and concluded that the first  | 
203  |  | // condition was always false. By moving it into a separate function the  | 
204  |  | // compiler wouldn't warn anymore.  | 
205  | 0  | static bool IsCharacterDigitForRadix(int c, int radix, char a_character) { | 
206  | 0  |   return radix > 10 && c >= a_character && c < a_character + radix - 10;  | 
207  | 0  | }  | 
208  |  |  | 
209  |  | // Returns true, when the iterator is equal to end.  | 
210  |  | template<class Iterator>  | 
211  | 0  | static bool Advance (Iterator* it, uc16 separator, int base, Iterator& end) { | 
212  | 0  |   if (separator == StringToDoubleConverter::kNoSeparator) { | 
213  | 0  |     ++(*it);  | 
214  | 0  |     return *it == end;  | 
215  | 0  |   }  | 
216  | 0  |   if (!isDigit(**it, base)) { | 
217  | 0  |     ++(*it);  | 
218  | 0  |     return *it == end;  | 
219  | 0  |   }  | 
220  | 0  |   ++(*it);  | 
221  | 0  |   if (*it == end) return true;  | 
222  | 0  |   if (*it + 1 == end) return false;  | 
223  | 0  |   if (**it == separator && isDigit(*(*it + 1), base)) { | 
224  | 0  |     ++(*it);  | 
225  | 0  |   }  | 
226  | 0  |   return *it == end;  | 
227  | 0  | } Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::Advance<char const*>(char const**, unsigned short, int, char const*&) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::Advance<char*>(char**, unsigned short, int, char*&) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::Advance<unsigned short const*>(unsigned short const**, unsigned short, int, unsigned short const*&)  | 
228  |  |  | 
229  |  | // Checks whether the string in the range start-end is a hex-float string.  | 
230  |  | // This function assumes that the leading '0x'/'0X' is already consumed.  | 
231  |  | //  | 
232  |  | // Hex float strings are of one of the following forms:  | 
233  |  | //   - hex_digits+ 'p' ('+'|'-')? exponent_digits+ | 
234  |  | //   - hex_digits* '.' hex_digits+ 'p' ('+'|'-')? exponent_digits+ | 
235  |  | //   - hex_digits+ '.' 'p' ('+'|'-')? exponent_digits+ | 
236  |  | template<class Iterator>  | 
237  |  | static bool IsHexFloatString(Iterator start,  | 
238  |  |                              Iterator end,  | 
239  |  |                              uc16 separator,  | 
240  | 0  |                              bool allow_trailing_junk) { | 
241  | 0  |   DOUBLE_CONVERSION_ASSERT(start != end);  | 
242  |  | 
  | 
243  | 0  |   Iterator current = start;  | 
244  |  | 
  | 
245  | 0  |   bool saw_digit = false;  | 
246  | 0  |   while (isDigit(*current, 16)) { | 
247  | 0  |     saw_digit = true;  | 
248  | 0  |     if (Advance(¤t, separator, 16, end)) return false;  | 
249  | 0  |   }  | 
250  | 0  |   if (*current == '.') { | 
251  | 0  |     if (Advance(¤t, separator, 16, end)) return false;  | 
252  | 0  |     while (isDigit(*current, 16)) { | 
253  | 0  |       saw_digit = true;  | 
254  | 0  |       if (Advance(¤t, separator, 16, end)) return false;  | 
255  | 0  |     }  | 
256  | 0  |   }  | 
257  | 0  |   if (!saw_digit) return false;  | 
258  | 0  |   if (*current != 'p' && *current != 'P') return false;  | 
259  | 0  |   if (Advance(¤t, separator, 16, end)) return false;  | 
260  | 0  |   if (*current == '+' || *current == '-') { | 
261  | 0  |     if (Advance(¤t, separator, 16, end)) return false;  | 
262  | 0  |   }  | 
263  | 0  |   if (!isDigit(*current, 10)) return false;  | 
264  | 0  |   if (Advance(¤t, separator, 16, end)) return true;  | 
265  | 0  |   while (isDigit(*current, 10)) { | 
266  | 0  |     if (Advance(¤t, separator, 16, end)) return true;  | 
267  | 0  |   }  | 
268  | 0  |   return allow_trailing_junk || !AdvanceToNonspace(¤t, end);  | 
269  | 0  | } Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::IsHexFloatString<char const*>(char const*, char const*, unsigned short, bool) Unexecuted instantiation: double-conversion-string-to-double.cpp:bool icu_70::double_conversion::IsHexFloatString<unsigned short const*>(unsigned short const*, unsigned short const*, unsigned short, bool)  | 
270  |  |  | 
271  |  |  | 
272  |  | // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.  | 
273  |  | //  | 
274  |  | // If parse_as_hex_float is true, then the string must be a valid  | 
275  |  | // hex-float.  | 
276  |  | template <int radix_log_2, class Iterator>  | 
277  |  | static double RadixStringToIeee(Iterator* current,  | 
278  |  |                                 Iterator end,  | 
279  |  |                                 bool sign,  | 
280  |  |                                 uc16 separator,  | 
281  |  |                                 bool parse_as_hex_float,  | 
282  |  |                                 bool allow_trailing_junk,  | 
283  |  |                                 double junk_string_value,  | 
284  |  |                                 bool read_as_double,  | 
285  | 0  |                                 bool* result_is_junk) { | 
286  | 0  |   DOUBLE_CONVERSION_ASSERT(*current != end);  | 
287  | 0  |   DOUBLE_CONVERSION_ASSERT(!parse_as_hex_float ||  | 
288  | 0  |       IsHexFloatString(*current, end, separator, allow_trailing_junk));  | 
289  |  | 
  | 
290  | 0  |   const int kDoubleSize = Double::kSignificandSize;  | 
291  | 0  |   const int kSingleSize = Single::kSignificandSize;  | 
292  | 0  |   const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;  | 
293  |  | 
  | 
294  | 0  |   *result_is_junk = true;  | 
295  |  | 
  | 
296  | 0  |   int64_t number = 0;  | 
297  | 0  |   int exponent = 0;  | 
298  | 0  |   const int radix = (1 << radix_log_2);  | 
299  |  |   // Whether we have encountered a '.' and are parsing the decimal digits.  | 
300  |  |   // Only relevant if parse_as_hex_float is true.  | 
301  | 0  |   bool post_decimal = false;  | 
302  |  |  | 
303  |  |   // Skip leading 0s.  | 
304  | 0  |   while (**current == '0') { | 
305  | 0  |     if (Advance(current, separator, radix, end)) { | 
306  | 0  |       *result_is_junk = false;  | 
307  | 0  |       return SignedZero(sign);  | 
308  | 0  |     }  | 
309  | 0  |   }  | 
310  |  |  | 
311  | 0  |   while (true) { | 
312  | 0  |     int digit;  | 
313  | 0  |     if (IsDecimalDigitForRadix(**current, radix)) { | 
314  | 0  |       digit = static_cast<char>(**current) - '0';  | 
315  | 0  |       if (post_decimal) exponent -= radix_log_2;  | 
316  | 0  |     } else if (IsCharacterDigitForRadix(**current, radix, 'a')) { | 
317  | 0  |       digit = static_cast<char>(**current) - 'a' + 10;  | 
318  | 0  |       if (post_decimal) exponent -= radix_log_2;  | 
319  | 0  |     } else if (IsCharacterDigitForRadix(**current, radix, 'A')) { | 
320  | 0  |       digit = static_cast<char>(**current) - 'A' + 10;  | 
321  | 0  |       if (post_decimal) exponent -= radix_log_2;  | 
322  | 0  |     } else if (parse_as_hex_float && **current == '.') { | 
323  | 0  |       post_decimal = true;  | 
324  | 0  |       Advance(current, separator, radix, end);  | 
325  | 0  |       DOUBLE_CONVERSION_ASSERT(*current != end);  | 
326  | 0  |       continue;  | 
327  | 0  |     } else if (parse_as_hex_float && (**current == 'p' || **current == 'P')) { | 
328  | 0  |       break;  | 
329  | 0  |     } else { | 
330  | 0  |       if (allow_trailing_junk || !AdvanceToNonspace(current, end)) { | 
331  | 0  |         break;  | 
332  | 0  |       } else { | 
333  | 0  |         return junk_string_value;  | 
334  | 0  |       }  | 
335  | 0  |     }  | 
336  |  |  | 
337  | 0  |     number = number * radix + digit;  | 
338  | 0  |     int overflow = static_cast<int>(number >> kSignificandSize);  | 
339  | 0  |     if (overflow != 0) { | 
340  |  |       // Overflow occurred. Need to determine which direction to round the  | 
341  |  |       // result.  | 
342  | 0  |       int overflow_bits_count = 1;  | 
343  | 0  |       while (overflow > 1) { | 
344  | 0  |         overflow_bits_count++;  | 
345  | 0  |         overflow >>= 1;  | 
346  | 0  |       }  | 
347  |  | 
  | 
348  | 0  |       int dropped_bits_mask = ((1 << overflow_bits_count) - 1);  | 
349  | 0  |       int dropped_bits = static_cast<int>(number) & dropped_bits_mask;  | 
350  | 0  |       number >>= overflow_bits_count;  | 
351  | 0  |       exponent += overflow_bits_count;  | 
352  |  | 
  | 
353  | 0  |       bool zero_tail = true;  | 
354  | 0  |       for (;;) { | 
355  | 0  |         if (Advance(current, separator, radix, end)) break;  | 
356  | 0  |         if (parse_as_hex_float && **current == '.') { | 
357  |  |           // Just run over the '.'. We are just trying to see whether there is  | 
358  |  |           // a non-zero digit somewhere.  | 
359  | 0  |           Advance(current, separator, radix, end);  | 
360  | 0  |           DOUBLE_CONVERSION_ASSERT(*current != end);  | 
361  | 0  |           post_decimal = true;  | 
362  | 0  |         }  | 
363  | 0  |         if (!isDigit(**current, radix)) break;  | 
364  | 0  |         zero_tail = zero_tail && **current == '0';  | 
365  | 0  |         if (!post_decimal) exponent += radix_log_2;  | 
366  | 0  |       }  | 
367  |  | 
  | 
368  | 0  |       if (!parse_as_hex_float &&  | 
369  | 0  |           !allow_trailing_junk &&  | 
370  | 0  |           AdvanceToNonspace(current, end)) { | 
371  | 0  |         return junk_string_value;  | 
372  | 0  |       }  | 
373  |  |  | 
374  | 0  |       int middle_value = (1 << (overflow_bits_count - 1));  | 
375  | 0  |       if (dropped_bits > middle_value) { | 
376  | 0  |         number++;  // Rounding up.  | 
377  | 0  |       } else if (dropped_bits == middle_value) { | 
378  |  |         // Rounding to even to consistency with decimals: half-way case rounds  | 
379  |  |         // up if significant part is odd and down otherwise.  | 
380  | 0  |         if ((number & 1) != 0 || !zero_tail) { | 
381  | 0  |           number++;  // Rounding up.  | 
382  | 0  |         }  | 
383  | 0  |       }  | 
384  |  |  | 
385  |  |       // Rounding up may cause overflow.  | 
386  | 0  |       if ((number & ((int64_t)1 << kSignificandSize)) != 0) { | 
387  | 0  |         exponent++;  | 
388  | 0  |         number >>= 1;  | 
389  | 0  |       }  | 
390  | 0  |       break;  | 
391  | 0  |     }  | 
392  | 0  |     if (Advance(current, separator, radix, end)) break;  | 
393  | 0  |   }  | 
394  |  |  | 
395  | 0  |   DOUBLE_CONVERSION_ASSERT(number < ((int64_t)1 << kSignificandSize));  | 
396  | 0  |   DOUBLE_CONVERSION_ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);  | 
397  |  | 
  | 
398  | 0  |   *result_is_junk = false;  | 
399  |  | 
  | 
400  | 0  |   if (parse_as_hex_float) { | 
401  | 0  |     DOUBLE_CONVERSION_ASSERT(**current == 'p' || **current == 'P');  | 
402  | 0  |     Advance(current, separator, radix, end);  | 
403  | 0  |     DOUBLE_CONVERSION_ASSERT(*current != end);  | 
404  | 0  |     bool is_negative = false;  | 
405  | 0  |     if (**current == '+') { | 
406  | 0  |       Advance(current, separator, radix, end);  | 
407  | 0  |       DOUBLE_CONVERSION_ASSERT(*current != end);  | 
408  | 0  |     } else if (**current == '-') { | 
409  | 0  |       is_negative = true;  | 
410  | 0  |       Advance(current, separator, radix, end);  | 
411  | 0  |       DOUBLE_CONVERSION_ASSERT(*current != end);  | 
412  | 0  |     }  | 
413  | 0  |     int written_exponent = 0;  | 
414  | 0  |     while (IsDecimalDigitForRadix(**current, 10)) { | 
415  |  |       // No need to read exponents if they are too big. That could potentially overflow  | 
416  |  |       // the `written_exponent` variable.  | 
417  | 0  |       if (abs(written_exponent) <= 100 * Double::kMaxExponent) { | 
418  | 0  |         written_exponent = 10 * written_exponent + **current - '0';  | 
419  | 0  |       }  | 
420  | 0  |       if (Advance(current, separator, radix, end)) break;  | 
421  | 0  |     }  | 
422  | 0  |     if (is_negative) written_exponent = -written_exponent;  | 
423  | 0  |     exponent += written_exponent;  | 
424  | 0  |   }  | 
425  |  | 
  | 
426  | 0  |   if (exponent == 0 || number == 0) { | 
427  | 0  |     if (sign) { | 
428  | 0  |       if (number == 0) return -0.0;  | 
429  | 0  |       number = -number;  | 
430  | 0  |     }  | 
431  | 0  |     return static_cast<double>(number);  | 
432  | 0  |   }  | 
433  |  |  | 
434  | 0  |   DOUBLE_CONVERSION_ASSERT(number != 0);  | 
435  | 0  |   double result = Double(DiyFp(number, exponent)).value();  | 
436  | 0  |   return sign ? -result : result;  | 
437  | 0  | } Unexecuted instantiation: double-conversion-string-to-double.cpp:double icu_70::double_conversion::RadixStringToIeee<4, char const*>(char const**, char const*, bool, unsigned short, bool, bool, double, bool, bool*) Unexecuted instantiation: double-conversion-string-to-double.cpp:double icu_70::double_conversion::RadixStringToIeee<3, char*>(char**, char*, bool, unsigned short, bool, bool, double, bool, bool*) Unexecuted instantiation: double-conversion-string-to-double.cpp:double icu_70::double_conversion::RadixStringToIeee<4, unsigned short const*>(unsigned short const**, unsigned short const*, bool, unsigned short, bool, bool, double, bool, bool*)  | 
438  |  |  | 
439  |  | template <class Iterator>  | 
440  |  | double StringToDoubleConverter::StringToIeee(  | 
441  |  |     Iterator input,  | 
442  |  |     int length,  | 
443  |  |     bool read_as_double,  | 
444  | 0  |     int* processed_characters_count) const { | 
445  | 0  |   Iterator current = input;  | 
446  | 0  |   Iterator end = input + length;  | 
447  |  | 
  | 
448  | 0  |   *processed_characters_count = 0;  | 
449  |  | 
  | 
450  | 0  |   const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;  | 
451  | 0  |   const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;  | 
452  | 0  |   const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;  | 
453  | 0  |   const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;  | 
454  | 0  |   const bool allow_case_insensitivity = (flags_ & ALLOW_CASE_INSENSITIVITY) != 0;  | 
455  |  |  | 
456  |  |   // To make sure that iterator dereferencing is valid the following  | 
457  |  |   // convention is used:  | 
458  |  |   // 1. Each '++current' statement is followed by check for equality to 'end'.  | 
459  |  |   // 2. If AdvanceToNonspace returned false then current == end.  | 
460  |  |   // 3. If 'current' becomes equal to 'end' the function returns or goes to  | 
461  |  |   // 'parsing_done'.  | 
462  |  |   // 4. 'current' is not dereferenced after the 'parsing_done' label.  | 
463  |  |   // 5. Code before 'parsing_done' may rely on 'current != end'.  | 
464  | 0  |   if (current == end) return empty_string_value_;  | 
465  |  |  | 
466  | 0  |   if (allow_leading_spaces || allow_trailing_spaces) { | 
467  | 0  |     if (!AdvanceToNonspace(¤t, end)) { | 
468  | 0  |       *processed_characters_count = static_cast<int>(current - input);  | 
469  | 0  |       return empty_string_value_;  | 
470  | 0  |     }  | 
471  | 0  |     if (!allow_leading_spaces && (input != current)) { | 
472  |  |       // No leading spaces allowed, but AdvanceToNonspace moved forward.  | 
473  | 0  |       return junk_string_value_;  | 
474  | 0  |     }  | 
475  | 0  |   }  | 
476  |  |  | 
477  |  |   // Exponent will be adjusted if insignificant digits of the integer part  | 
478  |  |   // or insignificant leading zeros of the fractional part are dropped.  | 
479  | 0  |   int exponent = 0;  | 
480  | 0  |   int significant_digits = 0;  | 
481  | 0  |   int insignificant_digits = 0;  | 
482  | 0  |   bool nonzero_digit_dropped = false;  | 
483  |  | 
  | 
484  | 0  |   bool sign = false;  | 
485  |  | 
  | 
486  | 0  |   if (*current == '+' || *current == '-') { | 
487  | 0  |     sign = (*current == '-');  | 
488  | 0  |     ++current;  | 
489  | 0  |     Iterator next_non_space = current;  | 
490  |  |     // Skip following spaces (if allowed).  | 
491  | 0  |     if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;  | 
492  | 0  |     if (!allow_spaces_after_sign && (current != next_non_space)) { | 
493  | 0  |       return junk_string_value_;  | 
494  | 0  |     }  | 
495  | 0  |     current = next_non_space;  | 
496  | 0  |   }  | 
497  |  |  | 
498  | 0  |   if (infinity_symbol_ != NULL) { | 
499  | 0  |     if (ConsumeFirstCharacter(*current, infinity_symbol_, allow_case_insensitivity)) { | 
500  | 0  |       if (!ConsumeSubString(¤t, end, infinity_symbol_, allow_case_insensitivity)) { | 
501  | 0  |         return junk_string_value_;  | 
502  | 0  |       }  | 
503  |  |  | 
504  | 0  |       if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { | 
505  | 0  |         return junk_string_value_;  | 
506  | 0  |       }  | 
507  | 0  |       if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 
508  | 0  |         return junk_string_value_;  | 
509  | 0  |       }  | 
510  |  |  | 
511  | 0  |       *processed_characters_count = static_cast<int>(current - input);  | 
512  | 0  |       return sign ? -Double::Infinity() : Double::Infinity();  | 
513  | 0  |     }  | 
514  | 0  |   }  | 
515  |  |  | 
516  | 0  |   if (nan_symbol_ != NULL) { | 
517  | 0  |     if (ConsumeFirstCharacter(*current, nan_symbol_, allow_case_insensitivity)) { | 
518  | 0  |       if (!ConsumeSubString(¤t, end, nan_symbol_, allow_case_insensitivity)) { | 
519  | 0  |         return junk_string_value_;  | 
520  | 0  |       }  | 
521  |  |  | 
522  | 0  |       if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { | 
523  | 0  |         return junk_string_value_;  | 
524  | 0  |       }  | 
525  | 0  |       if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 
526  | 0  |         return junk_string_value_;  | 
527  | 0  |       }  | 
528  |  |  | 
529  | 0  |       *processed_characters_count = static_cast<int>(current - input);  | 
530  | 0  |       return sign ? -Double::NaN() : Double::NaN();  | 
531  | 0  |     }  | 
532  | 0  |   }  | 
533  |  |  | 
534  | 0  |   bool leading_zero = false;  | 
535  | 0  |   if (*current == '0') { | 
536  | 0  |     if (Advance(¤t, separator_, 10, end)) { | 
537  | 0  |       *processed_characters_count = static_cast<int>(current - input);  | 
538  | 0  |       return SignedZero(sign);  | 
539  | 0  |     }  | 
540  |  |  | 
541  | 0  |     leading_zero = true;  | 
542  |  |  | 
543  |  |     // It could be hexadecimal value.  | 
544  | 0  |     if (((flags_ & ALLOW_HEX) || (flags_ & ALLOW_HEX_FLOATS)) &&  | 
545  | 0  |         (*current == 'x' || *current == 'X')) { | 
546  | 0  |       ++current;  | 
547  |  | 
  | 
548  | 0  |       if (current == end) return junk_string_value_;  // "0x"  | 
549  |  |  | 
550  | 0  |       bool parse_as_hex_float = (flags_ & ALLOW_HEX_FLOATS) &&  | 
551  | 0  |                 IsHexFloatString(current, end, separator_, allow_trailing_junk);  | 
552  |  | 
  | 
553  | 0  |       if (!parse_as_hex_float && !isDigit(*current, 16)) { | 
554  | 0  |         return junk_string_value_;  | 
555  | 0  |       }  | 
556  |  |  | 
557  | 0  |       bool result_is_junk;  | 
558  | 0  |       double result = RadixStringToIeee<4>(¤t,  | 
559  | 0  |                                            end,  | 
560  | 0  |                                            sign,  | 
561  | 0  |                                            separator_,  | 
562  | 0  |                                            parse_as_hex_float,  | 
563  | 0  |                                            allow_trailing_junk,  | 
564  | 0  |                                            junk_string_value_,  | 
565  | 0  |                                            read_as_double,  | 
566  | 0  |                                            &result_is_junk);  | 
567  | 0  |       if (!result_is_junk) { | 
568  | 0  |         if (allow_trailing_spaces) AdvanceToNonspace(¤t, end);  | 
569  | 0  |         *processed_characters_count = static_cast<int>(current - input);  | 
570  | 0  |       }  | 
571  | 0  |       return result;  | 
572  | 0  |     }  | 
573  |  |  | 
574  |  |     // Ignore leading zeros in the integer part.  | 
575  | 0  |     while (*current == '0') { | 
576  | 0  |       if (Advance(¤t, separator_, 10, end)) { | 
577  | 0  |         *processed_characters_count = static_cast<int>(current - input);  | 
578  | 0  |         return SignedZero(sign);  | 
579  | 0  |       }  | 
580  | 0  |     }  | 
581  | 0  |   }  | 
582  |  |  | 
583  | 0  |   bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;  | 
584  |  |  | 
585  |  |   // The longest form of simplified number is: "-<significant digits>.1eXXX\0".  | 
586  | 0  |   const int kBufferSize = kMaxSignificantDigits + 10;  | 
587  | 0  |   DOUBLE_CONVERSION_STACK_UNINITIALIZED char  | 
588  | 0  |       buffer[kBufferSize];  // NOLINT: size is known at compile time.  | 
589  | 0  |   int buffer_pos = 0;  | 
590  |  |  | 
591  |  |   // Copy significant digits of the integer part (if any) to the buffer.  | 
592  | 0  |   while (*current >= '0' && *current <= '9') { | 
593  | 0  |     if (significant_digits < kMaxSignificantDigits) { | 
594  | 0  |       DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);  | 
595  | 0  |       buffer[buffer_pos++] = static_cast<char>(*current);  | 
596  | 0  |       significant_digits++;  | 
597  |  |       // Will later check if it's an octal in the buffer.  | 
598  | 0  |     } else { | 
599  | 0  |       insignificant_digits++;  // Move the digit into the exponential part.  | 
600  | 0  |       nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';  | 
601  | 0  |     }  | 
602  | 0  |     octal = octal && *current < '8';  | 
603  | 0  |     if (Advance(¤t, separator_, 10, end)) goto parsing_done;  | 
604  | 0  |   }  | 
605  |  |  | 
606  | 0  |   if (significant_digits == 0) { | 
607  | 0  |     octal = false;  | 
608  | 0  |   }  | 
609  |  | 
  | 
610  | 0  |   if (*current == '.') { | 
611  | 0  |     if (octal && !allow_trailing_junk) return junk_string_value_;  | 
612  | 0  |     if (octal) goto parsing_done;  | 
613  |  |  | 
614  | 0  |     if (Advance(¤t, separator_, 10, end)) { | 
615  | 0  |       if (significant_digits == 0 && !leading_zero) { | 
616  | 0  |         return junk_string_value_;  | 
617  | 0  |       } else { | 
618  | 0  |         goto parsing_done;  | 
619  | 0  |       }  | 
620  | 0  |     }  | 
621  |  |  | 
622  | 0  |     if (significant_digits == 0) { | 
623  |  |       // octal = false;  | 
624  |  |       // Integer part consists of 0 or is absent. Significant digits start after  | 
625  |  |       // leading zeros (if any).  | 
626  | 0  |       while (*current == '0') { | 
627  | 0  |         if (Advance(¤t, separator_, 10, end)) { | 
628  | 0  |           *processed_characters_count = static_cast<int>(current - input);  | 
629  | 0  |           return SignedZero(sign);  | 
630  | 0  |         }  | 
631  | 0  |         exponent--;  // Move this 0 into the exponent.  | 
632  | 0  |       }  | 
633  | 0  |     }  | 
634  |  |  | 
635  |  |     // There is a fractional part.  | 
636  |  |     // We don't emit a '.', but adjust the exponent instead.  | 
637  | 0  |     while (*current >= '0' && *current <= '9') { | 
638  | 0  |       if (significant_digits < kMaxSignificantDigits) { | 
639  | 0  |         DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);  | 
640  | 0  |         buffer[buffer_pos++] = static_cast<char>(*current);  | 
641  | 0  |         significant_digits++;  | 
642  | 0  |         exponent--;  | 
643  | 0  |       } else { | 
644  |  |         // Ignore insignificant digits in the fractional part.  | 
645  | 0  |         nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';  | 
646  | 0  |       }  | 
647  | 0  |       if (Advance(¤t, separator_, 10, end)) goto parsing_done;  | 
648  | 0  |     }  | 
649  | 0  |   }  | 
650  |  |  | 
651  | 0  |   if (!leading_zero && exponent == 0 && significant_digits == 0) { | 
652  |  |     // If leading_zeros is true then the string contains zeros.  | 
653  |  |     // If exponent < 0 then string was [+-]\.0*...  | 
654  |  |     // If significant_digits != 0 the string is not equal to 0.  | 
655  |  |     // Otherwise there are no digits in the string.  | 
656  | 0  |     return junk_string_value_;  | 
657  | 0  |   }  | 
658  |  |  | 
659  |  |   // Parse exponential part.  | 
660  | 0  |   if (*current == 'e' || *current == 'E') { | 
661  | 0  |     if (octal && !allow_trailing_junk) return junk_string_value_;  | 
662  | 0  |     if (octal) goto parsing_done;  | 
663  | 0  |     Iterator junk_begin = current;  | 
664  | 0  |     ++current;  | 
665  | 0  |     if (current == end) { | 
666  | 0  |       if (allow_trailing_junk) { | 
667  | 0  |         current = junk_begin;  | 
668  | 0  |         goto parsing_done;  | 
669  | 0  |       } else { | 
670  | 0  |         return junk_string_value_;  | 
671  | 0  |       }  | 
672  | 0  |     }  | 
673  | 0  |     char exponen_sign = '+';  | 
674  | 0  |     if (*current == '+' || *current == '-') { | 
675  | 0  |       exponen_sign = static_cast<char>(*current);  | 
676  | 0  |       ++current;  | 
677  | 0  |       if (current == end) { | 
678  | 0  |         if (allow_trailing_junk) { | 
679  | 0  |           current = junk_begin;  | 
680  | 0  |           goto parsing_done;  | 
681  | 0  |         } else { | 
682  | 0  |           return junk_string_value_;  | 
683  | 0  |         }  | 
684  | 0  |       }  | 
685  | 0  |     }  | 
686  |  |  | 
687  | 0  |     if (current == end || *current < '0' || *current > '9') { | 
688  | 0  |       if (allow_trailing_junk) { | 
689  | 0  |         current = junk_begin;  | 
690  | 0  |         goto parsing_done;  | 
691  | 0  |       } else { | 
692  | 0  |         return junk_string_value_;  | 
693  | 0  |       }  | 
694  | 0  |     }  | 
695  |  |  | 
696  | 0  |     const int max_exponent = INT_MAX / 2;  | 
697  | 0  |     DOUBLE_CONVERSION_ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);  | 
698  | 0  |     int num = 0;  | 
699  | 0  |     do { | 
700  |  |       // Check overflow.  | 
701  | 0  |       int digit = *current - '0';  | 
702  | 0  |       if (num >= max_exponent / 10  | 
703  | 0  |           && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { | 
704  | 0  |         num = max_exponent;  | 
705  | 0  |       } else { | 
706  | 0  |         num = num * 10 + digit;  | 
707  | 0  |       }  | 
708  | 0  |       ++current;  | 
709  | 0  |     } while (current != end && *current >= '0' && *current <= '9');  | 
710  |  | 
  | 
711  | 0  |     exponent += (exponen_sign == '-' ? -num : num);  | 
712  | 0  |   }  | 
713  |  |  | 
714  | 0  |   if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { | 
715  | 0  |     return junk_string_value_;  | 
716  | 0  |   }  | 
717  | 0  |   if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { | 
718  | 0  |     return junk_string_value_;  | 
719  | 0  |   }  | 
720  | 0  |   if (allow_trailing_spaces) { | 
721  | 0  |     AdvanceToNonspace(¤t, end);  | 
722  | 0  |   }  | 
723  |  | 
  | 
724  | 0  |   parsing_done:  | 
725  | 0  |   exponent += insignificant_digits;  | 
726  |  | 
  | 
727  | 0  |   if (octal) { | 
728  | 0  |     double result;  | 
729  | 0  |     bool result_is_junk;  | 
730  | 0  |     char* start = buffer;  | 
731  | 0  |     result = RadixStringToIeee<3>(&start,  | 
732  | 0  |                                   buffer + buffer_pos,  | 
733  | 0  |                                   sign,  | 
734  | 0  |                                   separator_,  | 
735  | 0  |                                   false, // Don't parse as hex_float.  | 
736  | 0  |                                   allow_trailing_junk,  | 
737  | 0  |                                   junk_string_value_,  | 
738  | 0  |                                   read_as_double,  | 
739  | 0  |                                   &result_is_junk);  | 
740  | 0  |     DOUBLE_CONVERSION_ASSERT(!result_is_junk);  | 
741  | 0  |     *processed_characters_count = static_cast<int>(current - input);  | 
742  | 0  |     return result;  | 
743  | 0  |   }  | 
744  |  |  | 
745  | 0  |   if (nonzero_digit_dropped) { | 
746  | 0  |     buffer[buffer_pos++] = '1';  | 
747  | 0  |     exponent--;  | 
748  | 0  |   }  | 
749  |  | 
  | 
750  | 0  |   DOUBLE_CONVERSION_ASSERT(buffer_pos < kBufferSize);  | 
751  | 0  |   buffer[buffer_pos] = '\0';  | 
752  |  |  | 
753  |  |   // Code above ensures there are no leading zeros and the buffer has fewer than  | 
754  |  |   // kMaxSignificantDecimalDigits characters. Trim trailing zeros.  | 
755  | 0  |   Vector<const char> chars(buffer, buffer_pos);  | 
756  | 0  |   chars = TrimTrailingZeros(chars);  | 
757  | 0  |   exponent += buffer_pos - chars.length();  | 
758  |  | 
  | 
759  | 0  |   double converted;  | 
760  | 0  |   if (read_as_double) { | 
761  | 0  |     converted = StrtodTrimmed(chars, exponent);  | 
762  | 0  |   } else { | 
763  | 0  |     converted = StrtofTrimmed(chars, exponent);  | 
764  | 0  |   }  | 
765  | 0  |   *processed_characters_count = static_cast<int>(current - input);  | 
766  | 0  |   return sign? -converted: converted;  | 
767  | 0  | } Unexecuted instantiation: double icu_70::double_conversion::StringToDoubleConverter::StringToIeee<char const*>(char const*, int, bool, int*) const Unexecuted instantiation: double icu_70::double_conversion::StringToDoubleConverter::StringToIeee<unsigned short const*>(unsigned short const*, int, bool, int*) const  | 
768  |  |  | 
769  |  |  | 
770  |  | double StringToDoubleConverter::StringToDouble(  | 
771  |  |     const char* buffer,  | 
772  |  |     int length,  | 
773  | 0  |     int* processed_characters_count) const { | 
774  | 0  |   return StringToIeee(buffer, length, true, processed_characters_count);  | 
775  | 0  | }  | 
776  |  |  | 
777  |  |  | 
778  |  | double StringToDoubleConverter::StringToDouble(  | 
779  |  |     const uc16* buffer,  | 
780  |  |     int length,  | 
781  | 0  |     int* processed_characters_count) const { | 
782  | 0  |   return StringToIeee(buffer, length, true, processed_characters_count);  | 
783  | 0  | }  | 
784  |  |  | 
785  |  |  | 
786  |  | float StringToDoubleConverter::StringToFloat(  | 
787  |  |     const char* buffer,  | 
788  |  |     int length,  | 
789  | 0  |     int* processed_characters_count) const { | 
790  | 0  |   return static_cast<float>(StringToIeee(buffer, length, false,  | 
791  | 0  |                                          processed_characters_count));  | 
792  | 0  | }  | 
793  |  |  | 
794  |  |  | 
795  |  | float StringToDoubleConverter::StringToFloat(  | 
796  |  |     const uc16* buffer,  | 
797  |  |     int length,  | 
798  | 0  |     int* processed_characters_count) const { | 
799  | 0  |   return static_cast<float>(StringToIeee(buffer, length, false,  | 
800  | 0  |                                          processed_characters_count));  | 
801  | 0  | }  | 
802  |  |  | 
803  |  | }  // namespace double_conversion  | 
804  |  |  | 
805  |  | // ICU PATCH: Close ICU namespace  | 
806  |  | U_NAMESPACE_END  | 
807  |  | #endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING  |