/src/icu/source/i18n/double-conversion-double-to-string.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  |  | #include <algorithm>  | 
38  |  | #include <climits>  | 
39  |  | #include <cmath>  | 
40  |  |  | 
41  |  | // ICU PATCH: Customize header file paths for ICU.  | 
42  |  | // The file fixed-dtoa.h is not needed.  | 
43  |  |  | 
44  |  | #include "double-conversion-double-to-string.h"  | 
45  |  |  | 
46  |  | #include "double-conversion-bignum-dtoa.h"  | 
47  |  | #include "double-conversion-fast-dtoa.h"  | 
48  |  | #include "double-conversion-ieee.h"  | 
49  |  | #include "double-conversion-utils.h"  | 
50  |  |  | 
51  |  | // ICU PATCH: Wrap in ICU namespace  | 
52  |  | U_NAMESPACE_BEGIN  | 
53  |  |  | 
54  |  | namespace double_conversion { | 
55  |  |  | 
56  |  | #if 0  // not needed for ICU  | 
57  |  | const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() { | 
58  |  |   int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;  | 
59  |  |   static DoubleToStringConverter converter(flags,  | 
60  |  |                                            "Infinity",  | 
61  |  |                                            "NaN",  | 
62  |  |                                            'e',  | 
63  |  |                                            -6, 21,  | 
64  |  |                                            6, 0);  | 
65  |  |   return converter;  | 
66  |  | }  | 
67  |  |  | 
68  |  |  | 
69  |  | bool DoubleToStringConverter::HandleSpecialValues(  | 
70  |  |     double value,  | 
71  |  |     StringBuilder* result_builder) const { | 
72  |  |   Double double_inspect(value);  | 
73  |  |   if (double_inspect.IsInfinite()) { | 
74  |  |     if (infinity_symbol_ == NULL) return false;  | 
75  |  |     if (value < 0) { | 
76  |  |       result_builder->AddCharacter('-'); | 
77  |  |     }  | 
78  |  |     result_builder->AddString(infinity_symbol_);  | 
79  |  |     return true;  | 
80  |  |   }  | 
81  |  |   if (double_inspect.IsNan()) { | 
82  |  |     if (nan_symbol_ == NULL) return false;  | 
83  |  |     result_builder->AddString(nan_symbol_);  | 
84  |  |     return true;  | 
85  |  |   }  | 
86  |  |   return false;  | 
87  |  | }  | 
88  |  |  | 
89  |  |  | 
90  |  | void DoubleToStringConverter::CreateExponentialRepresentation(  | 
91  |  |     const char* decimal_digits,  | 
92  |  |     int length,  | 
93  |  |     int exponent,  | 
94  |  |     StringBuilder* result_builder) const { | 
95  |  |   DOUBLE_CONVERSION_ASSERT(length != 0);  | 
96  |  |   result_builder->AddCharacter(decimal_digits[0]);  | 
97  |  |   if (length != 1) { | 
98  |  |     result_builder->AddCharacter('.'); | 
99  |  |     result_builder->AddSubstring(&decimal_digits[1], length-1);  | 
100  |  |   }  | 
101  |  |   result_builder->AddCharacter(exponent_character_);  | 
102  |  |   if (exponent < 0) { | 
103  |  |     result_builder->AddCharacter('-'); | 
104  |  |     exponent = -exponent;  | 
105  |  |   } else { | 
106  |  |     if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) { | 
107  |  |       result_builder->AddCharacter('+'); | 
108  |  |     }  | 
109  |  |   }  | 
110  |  |   DOUBLE_CONVERSION_ASSERT(exponent < 1e4);  | 
111  |  |   // Changing this constant requires updating the comment of DoubleToStringConverter constructor  | 
112  |  |   const int kMaxExponentLength = 5;  | 
113  |  |   char buffer[kMaxExponentLength + 1];  | 
114  |  |   buffer[kMaxExponentLength] = '\0';  | 
115  |  |   int first_char_pos = kMaxExponentLength;  | 
116  |  |   if (exponent == 0) { | 
117  |  |     buffer[--first_char_pos] = '0';  | 
118  |  |   } else { | 
119  |  |     while (exponent > 0) { | 
120  |  |       buffer[--first_char_pos] = '0' + (exponent % 10);  | 
121  |  |       exponent /= 10;  | 
122  |  |     }  | 
123  |  |   }  | 
124  |  |   // Add prefix '0' to make exponent width >= min(min_exponent_with_, kMaxExponentLength)  | 
125  |  |   // For example: convert 1e+9 -> 1e+09, if min_exponent_with_ is set to 2  | 
126  |  |   while(kMaxExponentLength - first_char_pos < std::min(min_exponent_width_, kMaxExponentLength)) { | 
127  |  |     buffer[--first_char_pos] = '0';  | 
128  |  |   }  | 
129  |  |   result_builder->AddSubstring(&buffer[first_char_pos],  | 
130  |  |                                kMaxExponentLength - first_char_pos);  | 
131  |  | }  | 
132  |  |  | 
133  |  |  | 
134  |  | void DoubleToStringConverter::CreateDecimalRepresentation(  | 
135  |  |     const char* decimal_digits,  | 
136  |  |     int length,  | 
137  |  |     int decimal_point,  | 
138  |  |     int digits_after_point,  | 
139  |  |     StringBuilder* result_builder) const { | 
140  |  |   // Create a representation that is padded with zeros if needed.  | 
141  |  |   if (decimal_point <= 0) { | 
142  |  |       // "0.00000decimal_rep" or "0.000decimal_rep00".  | 
143  |  |     result_builder->AddCharacter('0'); | 
144  |  |     if (digits_after_point > 0) { | 
145  |  |       result_builder->AddCharacter('.'); | 
146  |  |       result_builder->AddPadding('0', -decimal_point); | 
147  |  |       DOUBLE_CONVERSION_ASSERT(length <= digits_after_point - (-decimal_point));  | 
148  |  |       result_builder->AddSubstring(decimal_digits, length);  | 
149  |  |       int remaining_digits = digits_after_point - (-decimal_point) - length;  | 
150  |  |       result_builder->AddPadding('0', remaining_digits); | 
151  |  |     }  | 
152  |  |   } else if (decimal_point >= length) { | 
153  |  |     // "decimal_rep0000.00000" or "decimal_rep.0000".  | 
154  |  |     result_builder->AddSubstring(decimal_digits, length);  | 
155  |  |     result_builder->AddPadding('0', decimal_point - length); | 
156  |  |     if (digits_after_point > 0) { | 
157  |  |       result_builder->AddCharacter('.'); | 
158  |  |       result_builder->AddPadding('0', digits_after_point); | 
159  |  |     }  | 
160  |  |   } else { | 
161  |  |     // "decima.l_rep000".  | 
162  |  |     DOUBLE_CONVERSION_ASSERT(digits_after_point > 0);  | 
163  |  |     result_builder->AddSubstring(decimal_digits, decimal_point);  | 
164  |  |     result_builder->AddCharacter('.'); | 
165  |  |     DOUBLE_CONVERSION_ASSERT(length - decimal_point <= digits_after_point);  | 
166  |  |     result_builder->AddSubstring(&decimal_digits[decimal_point],  | 
167  |  |                                  length - decimal_point);  | 
168  |  |     int remaining_digits = digits_after_point - (length - decimal_point);  | 
169  |  |     result_builder->AddPadding('0', remaining_digits); | 
170  |  |   }  | 
171  |  |   if (digits_after_point == 0) { | 
172  |  |     if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { | 
173  |  |       result_builder->AddCharacter('.'); | 
174  |  |     }  | 
175  |  |     if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { | 
176  |  |       result_builder->AddCharacter('0'); | 
177  |  |     }  | 
178  |  |   }  | 
179  |  | }  | 
180  |  |  | 
181  |  |  | 
182  |  | bool DoubleToStringConverter::ToShortestIeeeNumber(  | 
183  |  |     double value,  | 
184  |  |     StringBuilder* result_builder,  | 
185  |  |     DoubleToStringConverter::DtoaMode mode) const { | 
186  |  |   DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);  | 
187  |  |   if (Double(value).IsSpecial()) { | 
188  |  |     return HandleSpecialValues(value, result_builder);  | 
189  |  |   }  | 
190  |  |  | 
191  |  |   int decimal_point;  | 
192  |  |   bool sign;  | 
193  |  |   const int kDecimalRepCapacity = kBase10MaximalLength + 1;  | 
194  |  |   char decimal_rep[kDecimalRepCapacity];  | 
195  |  |   int decimal_rep_length;  | 
196  |  |  | 
197  |  |   DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,  | 
198  |  |                 &sign, &decimal_rep_length, &decimal_point);  | 
199  |  |  | 
200  |  |   bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;  | 
201  |  |   if (sign && (value != 0.0 || !unique_zero)) { | 
202  |  |     result_builder->AddCharacter('-'); | 
203  |  |   }  | 
204  |  |  | 
205  |  |   int exponent = decimal_point - 1;  | 
206  |  |   if ((decimal_in_shortest_low_ <= exponent) &&  | 
207  |  |       (exponent < decimal_in_shortest_high_)) { | 
208  |  |     CreateDecimalRepresentation(decimal_rep, decimal_rep_length,  | 
209  |  |                                 decimal_point,  | 
210  |  |                                 (std::max)(0, decimal_rep_length - decimal_point),  | 
211  |  |                                 result_builder);  | 
212  |  |   } else { | 
213  |  |     CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,  | 
214  |  |                                     result_builder);  | 
215  |  |   }  | 
216  |  |   return true;  | 
217  |  | }  | 
218  |  |  | 
219  |  |  | 
220  |  | bool DoubleToStringConverter::ToFixed(double value,  | 
221  |  |                                       int requested_digits,  | 
222  |  |                                       StringBuilder* result_builder) const { | 
223  |  |   DOUBLE_CONVERSION_ASSERT(kMaxFixedDigitsBeforePoint == 60);  | 
224  |  |   const double kFirstNonFixed = 1e60;  | 
225  |  |  | 
226  |  |   if (Double(value).IsSpecial()) { | 
227  |  |     return HandleSpecialValues(value, result_builder);  | 
228  |  |   }  | 
229  |  |  | 
230  |  |   if (requested_digits > kMaxFixedDigitsAfterPoint) return false;  | 
231  |  |   if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;  | 
232  |  |  | 
233  |  |   // Find a sufficiently precise decimal representation of n.  | 
234  |  |   int decimal_point;  | 
235  |  |   bool sign;  | 
236  |  |   // Add space for the '\0' byte.  | 
237  |  |   const int kDecimalRepCapacity =  | 
238  |  |       kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;  | 
239  |  |   char decimal_rep[kDecimalRepCapacity];  | 
240  |  |   int decimal_rep_length;  | 
241  |  |   DoubleToAscii(value, FIXED, requested_digits,  | 
242  |  |                 decimal_rep, kDecimalRepCapacity,  | 
243  |  |                 &sign, &decimal_rep_length, &decimal_point);  | 
244  |  |  | 
245  |  |   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);  | 
246  |  |   if (sign && (value != 0.0 || !unique_zero)) { | 
247  |  |     result_builder->AddCharacter('-'); | 
248  |  |   }  | 
249  |  |  | 
250  |  |   CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,  | 
251  |  |                               requested_digits, result_builder);  | 
252  |  |   return true;  | 
253  |  | }  | 
254  |  |  | 
255  |  |  | 
256  |  | bool DoubleToStringConverter::ToExponential(  | 
257  |  |     double value,  | 
258  |  |     int requested_digits,  | 
259  |  |     StringBuilder* result_builder) const { | 
260  |  |   if (Double(value).IsSpecial()) { | 
261  |  |     return HandleSpecialValues(value, result_builder);  | 
262  |  |   }  | 
263  |  |  | 
264  |  |   if (requested_digits < -1) return false;  | 
265  |  |   if (requested_digits > kMaxExponentialDigits) return false;  | 
266  |  |  | 
267  |  |   int decimal_point;  | 
268  |  |   bool sign;  | 
269  |  |   // Add space for digit before the decimal point and the '\0' character.  | 
270  |  |   const int kDecimalRepCapacity = kMaxExponentialDigits + 2;  | 
271  |  |   DOUBLE_CONVERSION_ASSERT(kDecimalRepCapacity > kBase10MaximalLength);  | 
272  |  |   char decimal_rep[kDecimalRepCapacity];  | 
273  |  | #ifndef NDEBUG  | 
274  |  |   // Problem: there is an assert in StringBuilder::AddSubstring() that  | 
275  |  |   // will pass this buffer to strlen(), and this buffer is not generally  | 
276  |  |   // null-terminated.  | 
277  |  |   memset(decimal_rep, 0, sizeof(decimal_rep));  | 
278  |  | #endif  | 
279  |  |   int decimal_rep_length;  | 
280  |  |  | 
281  |  |   if (requested_digits == -1) { | 
282  |  |     DoubleToAscii(value, SHORTEST, 0,  | 
283  |  |                   decimal_rep, kDecimalRepCapacity,  | 
284  |  |                   &sign, &decimal_rep_length, &decimal_point);  | 
285  |  |   } else { | 
286  |  |     DoubleToAscii(value, PRECISION, requested_digits + 1,  | 
287  |  |                   decimal_rep, kDecimalRepCapacity,  | 
288  |  |                   &sign, &decimal_rep_length, &decimal_point);  | 
289  |  |     DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= requested_digits + 1);  | 
290  |  |  | 
291  |  |     for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { | 
292  |  |       decimal_rep[i] = '0';  | 
293  |  |     }  | 
294  |  |     decimal_rep_length = requested_digits + 1;  | 
295  |  |   }  | 
296  |  |  | 
297  |  |   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);  | 
298  |  |   if (sign && (value != 0.0 || !unique_zero)) { | 
299  |  |     result_builder->AddCharacter('-'); | 
300  |  |   }  | 
301  |  |  | 
302  |  |   int exponent = decimal_point - 1;  | 
303  |  |   CreateExponentialRepresentation(decimal_rep,  | 
304  |  |                                   decimal_rep_length,  | 
305  |  |                                   exponent,  | 
306  |  |                                   result_builder);  | 
307  |  |   return true;  | 
308  |  | }  | 
309  |  |  | 
310  |  |  | 
311  |  | bool DoubleToStringConverter::ToPrecision(double value,  | 
312  |  |                                           int precision,  | 
313  |  |                                           StringBuilder* result_builder) const { | 
314  |  |   if (Double(value).IsSpecial()) { | 
315  |  |     return HandleSpecialValues(value, result_builder);  | 
316  |  |   }  | 
317  |  |  | 
318  |  |   if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) { | 
319  |  |     return false;  | 
320  |  |   }  | 
321  |  |  | 
322  |  |   // Find a sufficiently precise decimal representation of n.  | 
323  |  |   int decimal_point;  | 
324  |  |   bool sign;  | 
325  |  |   // Add one for the terminating null character.  | 
326  |  |   const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;  | 
327  |  |   char decimal_rep[kDecimalRepCapacity];  | 
328  |  |   int decimal_rep_length;  | 
329  |  |  | 
330  |  |   DoubleToAscii(value, PRECISION, precision,  | 
331  |  |                 decimal_rep, kDecimalRepCapacity,  | 
332  |  |                 &sign, &decimal_rep_length, &decimal_point);  | 
333  |  |   DOUBLE_CONVERSION_ASSERT(decimal_rep_length <= precision);  | 
334  |  |  | 
335  |  |   bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);  | 
336  |  |   if (sign && (value != 0.0 || !unique_zero)) { | 
337  |  |     result_builder->AddCharacter('-'); | 
338  |  |   }  | 
339  |  |  | 
340  |  |   // The exponent if we print the number as x.xxeyyy. That is with the  | 
341  |  |   // decimal point after the first digit.  | 
342  |  |   int exponent = decimal_point - 1;  | 
343  |  |  | 
344  |  |   int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;  | 
345  |  |   bool as_exponential =  | 
346  |  |       (-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||  | 
347  |  |       (decimal_point - precision + extra_zero >  | 
348  |  |        max_trailing_padding_zeroes_in_precision_mode_);  | 
349  |  |   if ((flags_ & NO_TRAILING_ZERO) != 0) { | 
350  |  |     // Truncate trailing zeros that occur after the decimal point (if exponential,  | 
351  |  |     // that is everything after the first digit).  | 
352  |  |     int stop = as_exponential ? 1 : std::max(1, decimal_point);  | 
353  |  |     while (decimal_rep_length > stop && decimal_rep[decimal_rep_length - 1] == '0') { | 
354  |  |       --decimal_rep_length;  | 
355  |  |     }  | 
356  |  |     // Clamp precision to avoid the code below re-adding the zeros.  | 
357  |  |     precision = std::min(precision, decimal_rep_length);  | 
358  |  |   }  | 
359  |  |   if (as_exponential) { | 
360  |  |     // Fill buffer to contain 'precision' digits.  | 
361  |  |     // Usually the buffer is already at the correct length, but 'DoubleToAscii'  | 
362  |  |     // is allowed to return less characters.  | 
363  |  |     for (int i = decimal_rep_length; i < precision; ++i) { | 
364  |  |       decimal_rep[i] = '0';  | 
365  |  |     }  | 
366  |  |  | 
367  |  |     CreateExponentialRepresentation(decimal_rep,  | 
368  |  |                                     precision,  | 
369  |  |                                     exponent,  | 
370  |  |                                     result_builder);  | 
371  |  |   } else { | 
372  |  |     CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,  | 
373  |  |                                 (std::max)(0, precision - decimal_point),  | 
374  |  |                                 result_builder);  | 
375  |  |   }  | 
376  |  |   return true;  | 
377  |  | }  | 
378  |  | #endif // not needed for ICU  | 
379  |  |  | 
380  |  |  | 
381  |  | static BignumDtoaMode DtoaToBignumDtoaMode(  | 
382  | 0  |     DoubleToStringConverter::DtoaMode dtoa_mode) { | 
383  | 0  |   switch (dtoa_mode) { | 
384  | 0  |     case DoubleToStringConverter::SHORTEST:  return BIGNUM_DTOA_SHORTEST;  | 
385  | 0  |     case DoubleToStringConverter::SHORTEST_SINGLE:  | 
386  | 0  |         return BIGNUM_DTOA_SHORTEST_SINGLE;  | 
387  | 0  |     case DoubleToStringConverter::FIXED:     return BIGNUM_DTOA_FIXED;  | 
388  | 0  |     case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;  | 
389  | 0  |     default:  | 
390  | 0  |       DOUBLE_CONVERSION_UNREACHABLE();  | 
391  | 0  |   }  | 
392  | 0  | }  | 
393  |  |  | 
394  |  |  | 
395  |  | void DoubleToStringConverter::DoubleToAscii(double v,  | 
396  |  |                                             DtoaMode mode,  | 
397  |  |                                             int requested_digits,  | 
398  |  |                                             char* buffer,  | 
399  |  |                                             int buffer_length,  | 
400  |  |                                             bool* sign,  | 
401  |  |                                             int* length,  | 
402  | 0  |                                             int* point) { | 
403  | 0  |   Vector<char> vector(buffer, buffer_length);  | 
404  | 0  |   DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());  | 
405  | 0  |   DOUBLE_CONVERSION_ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);  | 
406  |  | 
  | 
407  | 0  |   if (Double(v).Sign() < 0) { | 
408  | 0  |     *sign = true;  | 
409  | 0  |     v = -v;  | 
410  | 0  |   } else { | 
411  | 0  |     *sign = false;  | 
412  | 0  |   }  | 
413  |  | 
  | 
414  | 0  |   if (mode == PRECISION && requested_digits == 0) { | 
415  | 0  |     vector[0] = '\0';  | 
416  | 0  |     *length = 0;  | 
417  | 0  |     return;  | 
418  | 0  |   }  | 
419  |  |  | 
420  | 0  |   if (v == 0) { | 
421  | 0  |     vector[0] = '0';  | 
422  | 0  |     vector[1] = '\0';  | 
423  | 0  |     *length = 1;  | 
424  | 0  |     *point = 1;  | 
425  | 0  |     return;  | 
426  | 0  |   }  | 
427  |  |  | 
428  | 0  |   bool fast_worked;  | 
429  | 0  |   switch (mode) { | 
430  | 0  |     case SHORTEST:  | 
431  | 0  |       fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);  | 
432  | 0  |       break;  | 
433  |  | #if 0 // not needed for ICU  | 
434  |  |     case SHORTEST_SINGLE:  | 
435  |  |       fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,  | 
436  |  |                              vector, length, point);  | 
437  |  |       break;  | 
438  |  |     case FIXED:  | 
439  |  |       fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);  | 
440  |  |       break;  | 
441  |  |     case PRECISION:  | 
442  |  |       fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,  | 
443  |  |                              vector, length, point);  | 
444  |  |       break;  | 
445  |  | #endif // not needed for ICU  | 
446  | 0  |     default:  | 
447  | 0  |       fast_worked = false;  | 
448  | 0  |       DOUBLE_CONVERSION_UNREACHABLE();  | 
449  | 0  |   }  | 
450  | 0  |   if (fast_worked) return;  | 
451  |  |  | 
452  |  |   // If the fast dtoa didn't succeed use the slower bignum version.  | 
453  | 0  |   BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);  | 
454  | 0  |   BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);  | 
455  | 0  |   vector[*length] = '\0';  | 
456  | 0  | }  | 
457  |  |  | 
458  |  | }  // namespace double_conversion  | 
459  |  |  | 
460  |  | // ICU PATCH: Close ICU namespace  | 
461  |  | U_NAMESPACE_END  | 
462  |  | #endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING  |