blob: 104061056e7110bac7f507235fb942a48b881418 [file] [log] [blame]
Martin v. Löwis737ea822004-06-08 18:52:54 +00001/* -*- Mode: C; c-file-style: "python" -*- */
2
3#include <Python.h>
4#include <locale.h>
5
Martin v. Löwis737ea822004-06-08 18:52:54 +00006/**
7 * PyOS_ascii_strtod:
8 * @nptr: the string to convert to a numeric value.
9 * @endptr: if non-%NULL, it returns the character after
10 * the last character used in the conversion.
11 *
12 * Converts a string to a #gdouble value.
13 * This function behaves like the standard strtod() function
14 * does in the C locale. It does this without actually
15 * changing the current locale, since that would not be
16 * thread-safe.
17 *
18 * This function is typically used when reading configuration
19 * files or other non-user input that should be locale independent.
20 * To handle input from the user you should normally use the
21 * locale-sensitive system strtod() function.
22 *
23 * If the correct value would cause overflow, plus or minus %HUGE_VAL
24 * is returned (according to the sign of the value), and %ERANGE is
25 * stored in %errno. If the correct value would cause underflow,
26 * zero is returned and %ERANGE is stored in %errno.
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000027 * If memory allocation fails, %ENOMEM is stored in %errno.
Martin v. Löwis737ea822004-06-08 18:52:54 +000028 *
29 * This function resets %errno before calling strtod() so that
30 * you can reliably detect overflow and underflow.
31 *
32 * Return value: the #gdouble value.
33 **/
Eric Smith0923d1d2009-04-16 20:16:10 +000034
35#ifndef PY_NO_SHORT_FLOAT_REPR
36
37double
38PyOS_ascii_strtod(const char *nptr, char **endptr)
39{
40 double result;
41 _Py_SET_53BIT_PRECISION_HEADER;
42
43 assert(nptr != NULL);
44 /* Set errno to zero, so that we can distinguish zero results
45 and underflows */
46 errno = 0;
47
48 _Py_SET_53BIT_PRECISION_START;
49 result = _Py_dg_strtod(nptr, endptr);
50 _Py_SET_53BIT_PRECISION_END;
51
52 return result;
53
54}
55
56#else
57
58/*
59 Use system strtod; since strtod is locale aware, we may
60 have to first fix the decimal separator.
61
62 Note that unlike _Py_dg_strtod, the system strtod may not always give
63 correctly rounded results.
64*/
65
Martin v. Löwis737ea822004-06-08 18:52:54 +000066double
Neal Norwitze7214a12005-12-18 05:03:17 +000067PyOS_ascii_strtod(const char *nptr, char **endptr)
Martin v. Löwis737ea822004-06-08 18:52:54 +000068{
69 char *fail_pos;
Neal Norwitz0e7a0ed2005-12-18 05:37:36 +000070 double val = -1.0;
Martin v. Löwis737ea822004-06-08 18:52:54 +000071 struct lconv *locale_data;
72 const char *decimal_point;
Neal Norwitzd39d8612006-01-08 01:03:36 +000073 size_t decimal_point_len;
Martin v. Löwis737ea822004-06-08 18:52:54 +000074 const char *p, *decimal_point_pos;
75 const char *end = NULL; /* Silence gcc */
Christian Heimesfaf2f632008-01-06 16:59:19 +000076 const char *digits_pos = NULL;
77 int negate = 0;
Martin v. Löwis737ea822004-06-08 18:52:54 +000078
Martin v. Löwis737ea822004-06-08 18:52:54 +000079 assert(nptr != NULL);
80
81 fail_pos = NULL;
82
83 locale_data = localeconv();
84 decimal_point = locale_data->decimal_point;
85 decimal_point_len = strlen(decimal_point);
86
87 assert(decimal_point_len != 0);
88
89 decimal_point_pos = NULL;
Christian Heimesfaf2f632008-01-06 16:59:19 +000090
Mark Dickinson6d65df12009-04-26 15:30:47 +000091 /* Set errno to zero, so that we can distinguish zero results
92 and underflows */
93 errno = 0;
94
Christian Heimesfaf2f632008-01-06 16:59:19 +000095 /* We process any leading whitespace and the optional sign manually,
96 then pass the remainder to the system strtod. This ensures that
97 the result of an underflow has the correct sign. (bug #1725) */
98
99 p = nptr;
100 /* Skip leading space */
Eric Smith6dc46f52009-04-27 20:39:49 +0000101 while (Py_ISSPACE(*p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000102 p++;
103
104 /* Process leading sign, if present */
105 if (*p == '-') {
106 negate = 1;
107 p++;
Mark Dickinson6d65df12009-04-26 15:30:47 +0000108 }
109 else if (*p == '+') {
Christian Heimesfaf2f632008-01-06 16:59:19 +0000110 p++;
111 }
112
Mark Dickinson6d65df12009-04-26 15:30:47 +0000113 /* Parse infinities and nans */
114 if (*p == 'i' || *p == 'I') {
115 if (PyOS_strnicmp(p, "inf", 3) == 0) {
116 val = Py_HUGE_VAL;
117 if (PyOS_strnicmp(p+3, "inity", 5) == 0)
118 fail_pos = (char *)p+8;
119 else
120 fail_pos = (char *)p+3;
121 goto got_val;
122 }
123 else
124 goto invalid_string;
Christian Heimesfaf2f632008-01-06 16:59:19 +0000125 }
Mark Dickinson6d65df12009-04-26 15:30:47 +0000126#ifdef Py_NAN
127 if (*p == 'n' || *p == 'N') {
128 if (PyOS_strnicmp(p, "nan", 3) == 0) {
129 val = Py_NAN;
130 fail_pos = (char *)p+3;
131 goto got_val;
132 }
133 else
134 goto invalid_string;
135 }
136#endif
Christian Heimesfaf2f632008-01-06 16:59:19 +0000137
Mark Dickinson6d65df12009-04-26 15:30:47 +0000138 /* Some platform strtods accept hex floats; Python shouldn't (at the
139 moment), so we check explicitly for strings starting with '0x'. */
140 if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X'))
141 goto invalid_string;
142
143 /* Check that what's left begins with a digit or decimal point */
Eric Smith6dc46f52009-04-27 20:39:49 +0000144 if (!Py_ISDIGIT(*p) && *p != '.')
Mark Dickinson6d65df12009-04-26 15:30:47 +0000145 goto invalid_string;
146
147 digits_pos = p;
148 if (decimal_point[0] != '.' ||
Martin v. Löwis737ea822004-06-08 18:52:54 +0000149 decimal_point[1] != 0)
150 {
Mark Dickinson6d65df12009-04-26 15:30:47 +0000151 /* Look for a '.' in the input; if present, it'll need to be
152 swapped for the current locale's decimal point before we
153 call strtod. On the other hand, if we find the current
154 locale's decimal point then the input is invalid. */
Eric Smith6dc46f52009-04-27 20:39:49 +0000155 while (Py_ISDIGIT(*p))
Neal Norwitze7214a12005-12-18 05:03:17 +0000156 p++;
157
158 if (*p == '.')
Martin v. Löwis737ea822004-06-08 18:52:54 +0000159 {
Neal Norwitze7214a12005-12-18 05:03:17 +0000160 decimal_point_pos = p++;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000161
Mark Dickinson6d65df12009-04-26 15:30:47 +0000162 /* locate end of number */
Eric Smith6dc46f52009-04-27 20:39:49 +0000163 while (Py_ISDIGIT(*p))
Martin v. Löwis737ea822004-06-08 18:52:54 +0000164 p++;
165
Neal Norwitze7214a12005-12-18 05:03:17 +0000166 if (*p == 'e' || *p == 'E')
167 p++;
168 if (*p == '+' || *p == '-')
169 p++;
Eric Smith6dc46f52009-04-27 20:39:49 +0000170 while (Py_ISDIGIT(*p))
Neal Norwitze7214a12005-12-18 05:03:17 +0000171 p++;
172 end = p;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000173 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000174 else if (strncmp(p, decimal_point, decimal_point_len) == 0)
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000175 /* Python bug #1417699 */
Mark Dickinson6d65df12009-04-26 15:30:47 +0000176 goto invalid_string;
Christian Heimesb186d002008-03-18 15:15:01 +0000177 /* For the other cases, we need not convert the decimal
178 point */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000179 }
180
Mark Dickinson6d65df12009-04-26 15:30:47 +0000181 if (decimal_point_pos) {
Martin v. Löwis737ea822004-06-08 18:52:54 +0000182 char *copy, *c;
Mark Dickinson6d65df12009-04-26 15:30:47 +0000183 /* Create a copy of the input, with the '.' converted to the
184 locale-specific decimal point */
Christian Heimesfaf2f632008-01-06 16:59:19 +0000185 copy = (char *)PyMem_MALLOC(end - digits_pos +
186 1 + decimal_point_len);
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000187 if (copy == NULL) {
188 if (endptr)
189 *endptr = (char *)nptr;
190 errno = ENOMEM;
191 return val;
192 }
Martin v. Löwis737ea822004-06-08 18:52:54 +0000193
194 c = copy;
Christian Heimesfaf2f632008-01-06 16:59:19 +0000195 memcpy(c, digits_pos, decimal_point_pos - digits_pos);
196 c += decimal_point_pos - digits_pos;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000197 memcpy(c, decimal_point, decimal_point_len);
198 c += decimal_point_len;
Christian Heimesb186d002008-03-18 15:15:01 +0000199 memcpy(c, decimal_point_pos + 1,
200 end - (decimal_point_pos + 1));
Martin v. Löwis737ea822004-06-08 18:52:54 +0000201 c += end - (decimal_point_pos + 1);
202 *c = 0;
203
204 val = strtod(copy, &fail_pos);
205
206 if (fail_pos)
207 {
208 if (fail_pos > decimal_point_pos)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000209 fail_pos = (char *)digits_pos +
210 (fail_pos - copy) -
211 (decimal_point_len - 1);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000212 else
Christian Heimesfaf2f632008-01-06 16:59:19 +0000213 fail_pos = (char *)digits_pos +
214 (fail_pos - copy);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000215 }
216
Thomas Wouters477c8d52006-05-27 19:21:47 +0000217 PyMem_FREE(copy);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000218
219 }
Neal Norwitze7214a12005-12-18 05:03:17 +0000220 else {
Christian Heimesfaf2f632008-01-06 16:59:19 +0000221 val = strtod(digits_pos, &fail_pos);
Neal Norwitze7214a12005-12-18 05:03:17 +0000222 }
Martin v. Löwis737ea822004-06-08 18:52:54 +0000223
Christian Heimesfaf2f632008-01-06 16:59:19 +0000224 if (fail_pos == digits_pos)
Mark Dickinson6d65df12009-04-26 15:30:47 +0000225 goto invalid_string;
Christian Heimesfaf2f632008-01-06 16:59:19 +0000226
Mark Dickinson6d65df12009-04-26 15:30:47 +0000227 got_val:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000228 if (negate && fail_pos != nptr)
229 val = -val;
230
Martin v. Löwis737ea822004-06-08 18:52:54 +0000231 if (endptr)
232 *endptr = fail_pos;
233
234 return val;
Mark Dickinson6d65df12009-04-26 15:30:47 +0000235
236 invalid_string:
237 if (endptr)
238 *endptr = (char*)nptr;
239 errno = EINVAL;
240 return -1.0;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000241}
242
Eric Smith0923d1d2009-04-16 20:16:10 +0000243#endif
244
245double
246PyOS_ascii_atof(const char *nptr)
247{
248 return PyOS_ascii_strtod(nptr, NULL);
249}
250
251
Eric Smithb2c7af82008-04-30 02:12:09 +0000252/* Given a string that may have a decimal point in the current
253 locale, change it back to a dot. Since the string cannot get
254 longer, no need for a maximum buffer size parameter. */
255Py_LOCAL_INLINE(void)
256change_decimal_from_locale_to_dot(char* buffer)
257{
258 struct lconv *locale_data = localeconv();
259 const char *decimal_point = locale_data->decimal_point;
260
261 if (decimal_point[0] != '.' || decimal_point[1] != 0) {
262 size_t decimal_point_len = strlen(decimal_point);
263
264 if (*buffer == '+' || *buffer == '-')
265 buffer++;
Eric Smith6dc46f52009-04-27 20:39:49 +0000266 while (Py_ISDIGIT(*buffer))
Eric Smithb2c7af82008-04-30 02:12:09 +0000267 buffer++;
268 if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
269 *buffer = '.';
270 buffer++;
271 if (decimal_point_len > 1) {
272 /* buffer needs to get smaller */
273 size_t rest_len = strlen(buffer +
274 (decimal_point_len - 1));
275 memmove(buffer,
276 buffer + (decimal_point_len - 1),
277 rest_len);
278 buffer[rest_len] = 0;
279 }
280 }
281 }
282}
283
Martin v. Löwis737ea822004-06-08 18:52:54 +0000284
Christian Heimesc3f30c42008-02-22 16:37:40 +0000285/* From the C99 standard, section 7.19.6:
286The exponent always contains at least two digits, and only as many more digits
287as necessary to represent the exponent.
288*/
289#define MIN_EXPONENT_DIGITS 2
290
Eric Smithb2c7af82008-04-30 02:12:09 +0000291/* Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS
292 in length. */
293Py_LOCAL_INLINE(void)
Mark Dickinsonce95e562009-04-26 20:02:24 +0000294ensure_minimum_exponent_length(char* buffer, size_t buf_size)
Eric Smithb2c7af82008-04-30 02:12:09 +0000295{
296 char *p = strpbrk(buffer, "eE");
297 if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
298 char *start = p + 2;
299 int exponent_digit_cnt = 0;
300 int leading_zero_cnt = 0;
301 int in_leading_zeros = 1;
302 int significant_digit_cnt;
303
304 /* Skip over the exponent and the sign. */
305 p += 2;
306
307 /* Find the end of the exponent, keeping track of leading
308 zeros. */
Eric Smith6dc46f52009-04-27 20:39:49 +0000309 while (*p && Py_ISDIGIT(*p)) {
Eric Smithb2c7af82008-04-30 02:12:09 +0000310 if (in_leading_zeros && *p == '0')
311 ++leading_zero_cnt;
312 if (*p != '0')
313 in_leading_zeros = 0;
314 ++p;
315 ++exponent_digit_cnt;
316 }
317
318 significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
319 if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
320 /* If there are 2 exactly digits, we're done,
321 regardless of what they contain */
322 }
323 else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
324 int extra_zeros_cnt;
325
326 /* There are more than 2 digits in the exponent. See
327 if we can delete some of the leading zeros */
328 if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
329 significant_digit_cnt = MIN_EXPONENT_DIGITS;
330 extra_zeros_cnt = exponent_digit_cnt -
331 significant_digit_cnt;
332
333 /* Delete extra_zeros_cnt worth of characters from the
334 front of the exponent */
335 assert(extra_zeros_cnt >= 0);
336
337 /* Add one to significant_digit_cnt to copy the
338 trailing 0 byte, thus setting the length */
339 memmove(start,
340 start + extra_zeros_cnt,
341 significant_digit_cnt + 1);
342 }
343 else {
344 /* If there are fewer than 2 digits, add zeros
345 until there are 2, if there's enough room */
346 int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
347 if (start + zeros + exponent_digit_cnt + 1
348 < buffer + buf_size) {
349 memmove(start + zeros, start,
350 exponent_digit_cnt + 1);
351 memset(start, '0', zeros);
352 }
353 }
354 }
355}
356
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000357/* Remove trailing zeros after the decimal point from a numeric string; also
358 remove the decimal point if all digits following it are zero. The numeric
359 string must end in '\0', and should not have any leading or trailing
360 whitespace. Assumes that the decimal point is '.'. */
Eric Smithb2c7af82008-04-30 02:12:09 +0000361Py_LOCAL_INLINE(void)
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000362remove_trailing_zeros(char *buffer)
Eric Smithb2c7af82008-04-30 02:12:09 +0000363{
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000364 char *old_fraction_end, *new_fraction_end, *end, *p;
365
366 p = buffer;
367 if (*p == '-' || *p == '+')
368 /* Skip leading sign, if present */
369 ++p;
370 while (Py_ISDIGIT(*p))
371 ++p;
372
373 /* if there's no decimal point there's nothing to do */
374 if (*p++ != '.')
375 return;
376
377 /* scan any digits after the point */
378 while (Py_ISDIGIT(*p))
379 ++p;
380 old_fraction_end = p;
381
382 /* scan up to ending '\0' */
383 while (*p != '\0')
384 p++;
385 /* +1 to make sure that we move the null byte as well */
386 end = p+1;
387
388 /* scan back from fraction_end, looking for removable zeros */
389 p = old_fraction_end;
390 while (*(p-1) == '0')
391 --p;
392 /* and remove point if we've got that far */
393 if (*(p-1) == '.')
394 --p;
395 new_fraction_end = p;
396
397 memmove(new_fraction_end, old_fraction_end, end-old_fraction_end);
398}
399
400/* Ensure that buffer has a decimal point in it. The decimal point will not
401 be in the current locale, it will always be '.'. Don't add a decimal point
402 if an exponent is present. Also, convert to exponential notation where
403 adding a '.0' would produce too many significant digits (see issue 5864).
404
405 Returns a pointer to the fixed buffer, or NULL on failure.
406*/
407Py_LOCAL_INLINE(char *)
408ensure_decimal_point(char* buffer, size_t buf_size, int precision)
409{
410 int digit_count, insert_count = 0, convert_to_exp = 0;
411 char *chars_to_insert, *digits_start;
Eric Smithb2c7af82008-04-30 02:12:09 +0000412
413 /* search for the first non-digit character */
414 char *p = buffer;
Eric Smith2ad79e82008-07-19 00:33:23 +0000415 if (*p == '-' || *p == '+')
416 /* Skip leading sign, if present. I think this could only
417 ever be '-', but it can't hurt to check for both. */
418 ++p;
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000419 digits_start = p;
Eric Smith6dc46f52009-04-27 20:39:49 +0000420 while (*p && Py_ISDIGIT(*p))
Eric Smithb2c7af82008-04-30 02:12:09 +0000421 ++p;
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000422 digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int);
Eric Smithb2c7af82008-04-30 02:12:09 +0000423
424 if (*p == '.') {
Eric Smith6dc46f52009-04-27 20:39:49 +0000425 if (Py_ISDIGIT(*(p+1))) {
Eric Smithb2c7af82008-04-30 02:12:09 +0000426 /* Nothing to do, we already have a decimal
427 point and a digit after it */
428 }
429 else {
430 /* We have a decimal point, but no following
431 digit. Insert a zero after the decimal. */
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000432 /* can't ever get here via PyOS_double_to_string */
433 assert(precision == -1);
Eric Smithb2c7af82008-04-30 02:12:09 +0000434 ++p;
435 chars_to_insert = "0";
436 insert_count = 1;
437 }
438 }
Eric Smith0923d1d2009-04-16 20:16:10 +0000439 else if (!(*p == 'e' || *p == 'E')) {
440 /* Don't add ".0" if we have an exponent. */
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000441 if (digit_count == precision) {
442 /* issue 5864: don't add a trailing .0 in the case
443 where the '%g'-formatted result already has as many
444 significant digits as were requested. Switch to
445 exponential notation instead. */
446 convert_to_exp = 1;
447 /* no exponent, no point, and we shouldn't land here
448 for infs and nans, so we must be at the end of the
449 string. */
450 assert(*p == '\0');
451 }
452 else {
453 assert(precision == -1 || digit_count < precision);
454 chars_to_insert = ".0";
455 insert_count = 2;
456 }
Eric Smithb2c7af82008-04-30 02:12:09 +0000457 }
458 if (insert_count) {
459 size_t buf_len = strlen(buffer);
460 if (buf_len + insert_count + 1 >= buf_size) {
461 /* If there is not enough room in the buffer
462 for the additional text, just skip it. It's
463 not worth generating an error over. */
464 }
465 else {
466 memmove(p + insert_count, p,
467 buffer + strlen(buffer) - p + 1);
468 memcpy(p, chars_to_insert, insert_count);
469 }
470 }
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000471 if (convert_to_exp) {
472 int written;
473 size_t buf_avail;
474 p = digits_start;
475 /* insert decimal point */
476 assert(digit_count >= 1);
477 memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */
478 p[1] = '.';
479 p += digit_count+1;
480 assert(p <= buf_size+buffer);
481 buf_avail = buf_size+buffer-p;
482 if (buf_avail == 0)
483 return NULL;
484 /* Add exponent. It's okay to use lower case 'e': we only
485 arrive here as a result of using the empty format code or
486 repr/str builtins and those never want an upper case 'E' */
487 written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1);
488 if (!(0 <= written &&
489 written < Py_SAFE_DOWNCAST(buf_avail, size_t, int)))
490 /* output truncated, or something else bad happened */
491 return NULL;
492 remove_trailing_zeros(buffer);
493 }
494 return buffer;
Eric Smithb2c7af82008-04-30 02:12:09 +0000495}
496
Christian Heimesc3f30c42008-02-22 16:37:40 +0000497/* see FORMATBUFLEN in unicodeobject.c */
498#define FLOAT_FORMATBUFLEN 120
499
Martin v. Löwis737ea822004-06-08 18:52:54 +0000500/**
501 * PyOS_ascii_formatd:
502 * @buffer: A buffer to place the resulting string in
Christian Heimesb186d002008-03-18 15:15:01 +0000503 * @buf_size: The length of the buffer.
Martin v. Löwis737ea822004-06-08 18:52:54 +0000504 * @format: The printf()-style format to use for the
505 * code to use for converting.
506 * @d: The #gdouble to convert
507 *
508 * Converts a #gdouble to a string, using the '.' as
509 * decimal point. To format the number you pass in
510 * a printf()-style format string. Allowed conversion
Eric Smith0923d1d2009-04-16 20:16:10 +0000511 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'.
Martin v. Löwis737ea822004-06-08 18:52:54 +0000512 *
Christian Heimesb186d002008-03-18 15:15:01 +0000513 * 'Z' is the same as 'g', except it always has a decimal and
514 * at least one digit after the decimal.
Christian Heimesc3f30c42008-02-22 16:37:40 +0000515 *
Martin v. Löwis737ea822004-06-08 18:52:54 +0000516 * Return value: The pointer to the buffer with the converted string.
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000517 * On failure returns NULL but does not set any Python exception.
Martin v. Löwis737ea822004-06-08 18:52:54 +0000518 **/
519char *
Eric Smithcc32a112009-04-26 21:35:14 +0000520_PyOS_ascii_formatd(char *buffer,
Christian Heimesb186d002008-03-18 15:15:01 +0000521 size_t buf_size,
Martin v. Löwis737ea822004-06-08 18:52:54 +0000522 const char *format,
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000523 double d,
524 int precision)
Martin v. Löwis737ea822004-06-08 18:52:54 +0000525{
Martin v. Löwis737ea822004-06-08 18:52:54 +0000526 char format_char;
Christian Heimesc3f30c42008-02-22 16:37:40 +0000527 size_t format_len = strlen(format);
528
Christian Heimesb186d002008-03-18 15:15:01 +0000529 /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but
530 also with at least one character past the decimal. */
Christian Heimesc3f30c42008-02-22 16:37:40 +0000531 char tmp_format[FLOAT_FORMATBUFLEN];
Martin v. Löwis737ea822004-06-08 18:52:54 +0000532
Christian Heimesc3f30c42008-02-22 16:37:40 +0000533 /* The last character in the format string must be the format char */
534 format_char = format[format_len - 1];
Martin v. Löwis737ea822004-06-08 18:52:54 +0000535
Martin v. Löwis737ea822004-06-08 18:52:54 +0000536 if (format[0] != '%')
537 return NULL;
538
Christian Heimesc3f30c42008-02-22 16:37:40 +0000539 /* I'm not sure why this test is here. It's ensuring that the format
540 string after the first character doesn't have a single quote, a
541 lowercase l, or a percent. This is the reverse of the commented-out
542 test about 10 lines ago. */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000543 if (strpbrk(format + 1, "'l%"))
544 return NULL;
545
Christian Heimesb186d002008-03-18 15:15:01 +0000546 /* Also curious about this function is that it accepts format strings
547 like "%xg", which are invalid for floats. In general, the
548 interface to this function is not very good, but changing it is
549 difficult because it's a public API. */
550
Martin v. Löwis737ea822004-06-08 18:52:54 +0000551 if (!(format_char == 'e' || format_char == 'E' ||
552 format_char == 'f' || format_char == 'F' ||
Christian Heimesc3f30c42008-02-22 16:37:40 +0000553 format_char == 'g' || format_char == 'G' ||
Eric Smith0923d1d2009-04-16 20:16:10 +0000554 format_char == 'Z'))
Martin v. Löwis737ea822004-06-08 18:52:54 +0000555 return NULL;
556
Eric Smith0923d1d2009-04-16 20:16:10 +0000557 /* Map 'Z' format_char to 'g', by copying the format string and
Christian Heimesb186d002008-03-18 15:15:01 +0000558 replacing the final char with a 'g' */
Eric Smith0923d1d2009-04-16 20:16:10 +0000559 if (format_char == 'Z') {
Christian Heimesc3f30c42008-02-22 16:37:40 +0000560 if (format_len + 1 >= sizeof(tmp_format)) {
561 /* The format won't fit in our copy. Error out. In
Christian Heimesb186d002008-03-18 15:15:01 +0000562 practice, this will never happen and will be
563 detected by returning NULL */
Christian Heimesc3f30c42008-02-22 16:37:40 +0000564 return NULL;
565 }
566 strcpy(tmp_format, format);
567 tmp_format[format_len - 1] = 'g';
568 format = tmp_format;
569 }
Martin v. Löwis737ea822004-06-08 18:52:54 +0000570
Christian Heimesb186d002008-03-18 15:15:01 +0000571
Christian Heimesc3f30c42008-02-22 16:37:40 +0000572 /* Have PyOS_snprintf do the hard work */
Christian Heimesb186d002008-03-18 15:15:01 +0000573 PyOS_snprintf(buffer, buf_size, format, d);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000574
Eric Smithb2c7af82008-04-30 02:12:09 +0000575 /* Do various fixups on the return string */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000576
Eric Smithb2c7af82008-04-30 02:12:09 +0000577 /* Get the current locale, and find the decimal point string.
Eric Smith0923d1d2009-04-16 20:16:10 +0000578 Convert that string back to a dot. */
579 change_decimal_from_locale_to_dot(buffer);
Christian Heimesc3f30c42008-02-22 16:37:40 +0000580
581 /* If an exponent exists, ensure that the exponent is at least
582 MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
583 for the extra zeros. Also, if there are more than
584 MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
585 back to MIN_EXPONENT_DIGITS */
Mark Dickinsonce95e562009-04-26 20:02:24 +0000586 ensure_minimum_exponent_length(buffer, buf_size);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000587
Christian Heimesb186d002008-03-18 15:15:01 +0000588 /* If format_char is 'Z', make sure we have at least one character
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000589 after the decimal point (and make sure we have a decimal point);
590 also switch to exponential notation in some edge cases where the
591 extra character would produce more significant digits that we
592 really want. */
Eric Smithb2c7af82008-04-30 02:12:09 +0000593 if (format_char == 'Z')
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000594 buffer = ensure_decimal_point(buffer, buf_size, precision);
Christian Heimesb186d002008-03-18 15:15:01 +0000595
Martin v. Löwis737ea822004-06-08 18:52:54 +0000596 return buffer;
597}
598
Eric Smithcc32a112009-04-26 21:35:14 +0000599char *
600PyOS_ascii_formatd(char *buffer,
601 size_t buf_size,
602 const char *format,
603 double d)
604{
605 if (PyErr_WarnEx(PyExc_DeprecationWarning,
606 "PyOS_ascii_formatd is deprecated, "
607 "use PyOS_double_to_string instead", 1) < 0)
608 return NULL;
609
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000610 return _PyOS_ascii_formatd(buffer, buf_size, format, d, -1);
Eric Smithcc32a112009-04-26 21:35:14 +0000611}
612
Eric Smith0923d1d2009-04-16 20:16:10 +0000613#ifdef PY_NO_SHORT_FLOAT_REPR
614
615/* The fallback code to use if _Py_dg_dtoa is not available. */
616
617PyAPI_FUNC(char *) PyOS_double_to_string(double val,
618 char format_code,
619 int precision,
620 int flags,
621 int *type)
Martin v. Löwis737ea822004-06-08 18:52:54 +0000622{
Eric Smith0923d1d2009-04-16 20:16:10 +0000623 char format[32];
Mark Dickinsonf489caf2009-05-01 11:42:00 +0000624 Py_ssize_t bufsize;
625 char *buf;
626 int t, exp;
Eric Smith0923d1d2009-04-16 20:16:10 +0000627 int upper = 0;
628
629 /* Validate format_code, and map upper and lower case */
630 switch (format_code) {
631 case 'e': /* exponent */
632 case 'f': /* fixed */
633 case 'g': /* general */
634 break;
635 case 'E':
636 upper = 1;
637 format_code = 'e';
638 break;
639 case 'F':
640 upper = 1;
641 format_code = 'f';
642 break;
643 case 'G':
644 upper = 1;
645 format_code = 'g';
646 break;
647 case 'r': /* repr format */
648 /* Supplied precision is unused, must be 0. */
649 if (precision != 0) {
650 PyErr_BadInternalCall();
651 return NULL;
652 }
653 precision = 17;
654 format_code = 'g';
655 break;
656 case 's': /* str format */
657 /* Supplied precision is unused, must be 0. */
658 if (precision != 0) {
659 PyErr_BadInternalCall();
660 return NULL;
661 }
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000662 precision = 12;
663 format_code = 'g';
Eric Smith0923d1d2009-04-16 20:16:10 +0000664 break;
665 default:
666 PyErr_BadInternalCall();
667 return NULL;
668 }
669
Mark Dickinsonf489caf2009-05-01 11:42:00 +0000670 /* Here's a quick-and-dirty calculation to figure out how big a buffer
671 we need. In general, for a finite float we need:
672
673 1 byte for each digit of the decimal significand, and
674
675 1 for a possible sign
676 1 for a possible decimal point
677 2 for a possible [eE][+-]
678 1 for each digit of the exponent; if we allow 19 digits
679 total then we're safe up to exponents of 2**63.
680 1 for the trailing nul byte
681
682 This gives a total of 24 + the number of digits in the significand,
683 and the number of digits in the significand is:
684
685 for 'g' format: at most precision, except possibly
686 when precision == 0, when it's 1.
687 for 'e' format: precision+1
688 for 'f' format: precision digits after the point, at least 1
689 before. To figure out how many digits appear before the point
690 we have to examine the size of the number. If fabs(val) < 1.0
691 then there will be only one digit before the point. If
692 fabs(val) >= 1.0, then there are at most
693
694 1+floor(log10(ceiling(fabs(val))))
695
696 digits before the point (where the 'ceiling' allows for the
697 possibility that the rounding rounds the integer part of val
698 up). A safe upper bound for the above quantity is
699 1+floor(exp/3), where exp is the unique integer such that 0.5
700 <= fabs(val)/2**exp < 1.0. This exp can be obtained from
701 frexp.
702
703 So we allow room for precision+1 digits for all formats, plus an
704 extra floor(exp/3) digits for 'f' format.
705
706 */
707
708 if (Py_IS_NAN(val) || Py_IS_INFINITY(val))
709 /* 3 for 'inf'/'nan', 1 for sign, 1 for '\0' */
710 bufsize = 5;
711 else {
712 bufsize = 25 + precision;
713 if (format_code == 'f' && fabs(val) >= 1.0) {
714 frexp(val, &exp);
715 bufsize += exp/3;
716 }
717 }
718
719 buf = PyMem_Malloc(bufsize);
720 if (buf == NULL) {
721 PyErr_NoMemory();
722 return NULL;
723 }
724
Eric Smith0923d1d2009-04-16 20:16:10 +0000725 /* Handle nan and inf. */
726 if (Py_IS_NAN(val)) {
727 strcpy(buf, "nan");
728 t = Py_DTST_NAN;
729 } else if (Py_IS_INFINITY(val)) {
730 if (copysign(1., val) == 1.)
731 strcpy(buf, "inf");
732 else
733 strcpy(buf, "-inf");
734 t = Py_DTST_INFINITE;
735 } else {
736 t = Py_DTST_FINITE;
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000737 if (flags & Py_DTSF_ADD_DOT_0)
Eric Smith0923d1d2009-04-16 20:16:10 +0000738 format_code = 'Z';
739
Eric Smithcc32a112009-04-26 21:35:14 +0000740 PyOS_snprintf(format, sizeof(format), "%%%s.%i%c",
741 (flags & Py_DTSF_ALT ? "#" : ""), precision,
742 format_code);
Mark Dickinsonf489caf2009-05-01 11:42:00 +0000743 _PyOS_ascii_formatd(buf, bufsize, format, val, precision);
Eric Smith0923d1d2009-04-16 20:16:10 +0000744 }
745
Mark Dickinsonad476da2009-04-23 19:14:16 +0000746 /* Add sign when requested. It's convenient (esp. when formatting
747 complex numbers) to include a sign even for inf and nan. */
Mark Dickinsonf489caf2009-05-01 11:42:00 +0000748 if (flags & Py_DTSF_SIGN && buf[0] != '-') {
749 size_t len = strlen(buf);
750 /* the bufsize calculations above should ensure that we've got
751 space to add a sign */
752 assert((size_t)bufsize >= len+2);
753 memmove(buf+1, buf, len+1);
754 buf[0] = '+';
755 }
Eric Smith0923d1d2009-04-16 20:16:10 +0000756 if (upper) {
757 /* Convert to upper case. */
758 char *p1;
Mark Dickinsonf489caf2009-05-01 11:42:00 +0000759 for (p1 = buf; *p1; p1++)
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000760 *p1 = Py_TOUPPER(*p1);
Eric Smith0923d1d2009-04-16 20:16:10 +0000761 }
762
763 if (type)
764 *type = t;
Mark Dickinsonf489caf2009-05-01 11:42:00 +0000765 return buf;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000766}
Eric Smith0923d1d2009-04-16 20:16:10 +0000767
768#else
769
770/* _Py_dg_dtoa is available. */
771
772/* I'm using a lookup table here so that I don't have to invent a non-locale
773 specific way to convert to uppercase */
774#define OFS_INF 0
775#define OFS_NAN 1
776#define OFS_E 2
777
778/* The lengths of these are known to the code below, so don't change them */
779static char *lc_float_strings[] = {
780 "inf",
781 "nan",
782 "e",
783};
784static char *uc_float_strings[] = {
785 "INF",
786 "NAN",
787 "E",
788};
789
790
791/* Convert a double d to a string, and return a PyMem_Malloc'd block of
792 memory contain the resulting string.
793
794 Arguments:
795 d is the double to be converted
796 format_code is one of 'e', 'f', 'g', 'r' or 's'. 'e', 'f' and 'g'
797 correspond to '%e', '%f' and '%g'; 'r' and 's' correspond
798 to repr and str.
799 mode is one of '0', '2' or '3', and is completely determined by
800 format_code: 'e', 'g' and 's' use mode 2; 'f' mode 3, 'r' mode 0.
801 precision is the desired precision
802 always_add_sign is nonzero if a '+' sign should be included for positive
803 numbers
804 add_dot_0_if_integer is nonzero if integers in non-exponential form
805 should have ".0" added. Only applies to format codes 'r', 's', and 'g'.
806 use_alt_formatting is nonzero if alternative formatting should be
807 used. Only applies to format codes 'e', 'f' and 'g'.
808 type, if non-NULL, will be set to one of these constants to identify
809 the type of the 'd' argument:
810 Py_DTST_FINITE
811 Py_DTST_INFINITE
812 Py_DTST_NAN
813
814 Returns a PyMem_Malloc'd block of memory containing the resulting string,
815 or NULL on error. If NULL is returned, the Python error has been set.
816 */
817
818static char *
819format_float_short(double d, char format_code,
820 int mode, Py_ssize_t precision,
821 int always_add_sign, int add_dot_0_if_integer,
822 int use_alt_formatting, char **float_strings, int *type)
823{
824 char *buf = NULL;
825 char *p = NULL;
826 Py_ssize_t bufsize = 0;
827 char *digits, *digits_end;
828 int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0;
829 Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end;
830 _Py_SET_53BIT_PRECISION_HEADER;
831
832 /* _Py_dg_dtoa returns a digit string (no decimal point or exponent).
833 Must be matched by a call to _Py_dg_freedtoa. */
834 _Py_SET_53BIT_PRECISION_START;
835 digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign,
836 &digits_end);
837 _Py_SET_53BIT_PRECISION_END;
838
839 decpt = (Py_ssize_t)decpt_as_int;
840 if (digits == NULL) {
841 /* The only failure mode is no memory. */
842 PyErr_NoMemory();
843 goto exit;
844 }
845 assert(digits_end != NULL && digits_end >= digits);
846 digits_len = digits_end - digits;
847
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000848 if (digits_len && !Py_ISDIGIT(digits[0])) {
Eric Smith0923d1d2009-04-16 20:16:10 +0000849 /* Infinities and nans here; adapt Gay's output,
850 so convert Infinity to inf and NaN to nan, and
851 ignore sign of nan. Then return. */
852
Mark Dickinsonad476da2009-04-23 19:14:16 +0000853 /* ignore the actual sign of a nan */
854 if (digits[0] == 'n' || digits[0] == 'N')
855 sign = 0;
856
Eric Smith0923d1d2009-04-16 20:16:10 +0000857 /* We only need 5 bytes to hold the result "+inf\0" . */
858 bufsize = 5; /* Used later in an assert. */
859 buf = (char *)PyMem_Malloc(bufsize);
860 if (buf == NULL) {
861 PyErr_NoMemory();
862 goto exit;
863 }
864 p = buf;
865
Mark Dickinsonad476da2009-04-23 19:14:16 +0000866 if (sign == 1) {
867 *p++ = '-';
868 }
869 else if (always_add_sign) {
870 *p++ = '+';
871 }
Eric Smith0923d1d2009-04-16 20:16:10 +0000872 if (digits[0] == 'i' || digits[0] == 'I') {
Eric Smith0923d1d2009-04-16 20:16:10 +0000873 strncpy(p, float_strings[OFS_INF], 3);
874 p += 3;
875
876 if (type)
877 *type = Py_DTST_INFINITE;
878 }
879 else if (digits[0] == 'n' || digits[0] == 'N') {
Eric Smith0923d1d2009-04-16 20:16:10 +0000880 strncpy(p, float_strings[OFS_NAN], 3);
881 p += 3;
882
883 if (type)
884 *type = Py_DTST_NAN;
885 }
886 else {
887 /* shouldn't get here: Gay's code should always return
888 something starting with a digit, an 'I', or 'N' */
889 strncpy(p, "ERR", 3);
890 p += 3;
891 assert(0);
892 }
893 goto exit;
894 }
895
896 /* The result must be finite (not inf or nan). */
897 if (type)
898 *type = Py_DTST_FINITE;
899
900
901 /* We got digits back, format them. We may need to pad 'digits'
902 either on the left or right (or both) with extra zeros, so in
903 general the resulting string has the form
904
905 [<sign>]<zeros><digits><zeros>[<exponent>]
906
907 where either of the <zeros> pieces could be empty, and there's a
908 decimal point that could appear either in <digits> or in the
909 leading or trailing <zeros>.
910
911 Imagine an infinite 'virtual' string vdigits, consisting of the
912 string 'digits' (starting at index 0) padded on both the left and
913 right with infinite strings of zeros. We want to output a slice
914
915 vdigits[vdigits_start : vdigits_end]
916
917 of this virtual string. Thus if vdigits_start < 0 then we'll end
918 up producing some leading zeros; if vdigits_end > digits_len there
919 will be trailing zeros in the output. The next section of code
920 determines whether to use an exponent or not, figures out the
921 position 'decpt' of the decimal point, and computes 'vdigits_start'
922 and 'vdigits_end'. */
923 vdigits_end = digits_len;
924 switch (format_code) {
925 case 'e':
926 use_exp = 1;
927 vdigits_end = precision;
928 break;
929 case 'f':
930 vdigits_end = decpt + precision;
931 break;
932 case 'g':
Mark Dickinsond3ca5572009-04-29 18:47:07 +0000933 if (decpt <= -4 || decpt >
934 (add_dot_0_if_integer ? precision-1 : precision))
Eric Smith0923d1d2009-04-16 20:16:10 +0000935 use_exp = 1;
936 if (use_alt_formatting)
937 vdigits_end = precision;
938 break;
939 case 'r':
940 /* convert to exponential format at 1e16. We used to convert
941 at 1e17, but that gives odd-looking results for some values
942 when a 16-digit 'shortest' repr is padded with bogus zeros.
943 For example, repr(2e16+8) would give 20000000000000010.0;
944 the true value is 20000000000000008.0. */
945 if (decpt <= -4 || decpt > 16)
946 use_exp = 1;
947 break;
948 case 's':
949 /* if we're forcing a digit after the point, convert to
950 exponential format at 1e11. If not, convert at 1e12. */
951 if (decpt <= -4 || decpt >
952 (add_dot_0_if_integer ? precision-1 : precision))
953 use_exp = 1;
954 break;
955 default:
956 PyErr_BadInternalCall();
957 goto exit;
958 }
959
960 /* if using an exponent, reset decimal point position to 1 and adjust
961 exponent accordingly.*/
962 if (use_exp) {
963 exp = decpt - 1;
964 decpt = 1;
965 }
966 /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start <
967 decpt < vdigits_end if add_dot_0_if_integer and no exponent */
968 vdigits_start = decpt <= 0 ? decpt-1 : 0;
969 if (!use_exp && add_dot_0_if_integer)
970 vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1;
971 else
972 vdigits_end = vdigits_end > decpt ? vdigits_end : decpt;
973
974 /* double check inequalities */
975 assert(vdigits_start <= 0 &&
976 0 <= digits_len &&
977 digits_len <= vdigits_end);
978 /* decimal point should be in (vdigits_start, vdigits_end] */
979 assert(vdigits_start < decpt && decpt <= vdigits_end);
980
981 /* Compute an upper bound how much memory we need. This might be a few
982 chars too long, but no big deal. */
983 bufsize =
984 /* sign, decimal point and trailing 0 byte */
985 3 +
986
987 /* total digit count (including zero padding on both sides) */
988 (vdigits_end - vdigits_start) +
989
990 /* exponent "e+100", max 3 numerical digits */
991 (use_exp ? 5 : 0);
992
993 /* Now allocate the memory and initialize p to point to the start of
994 it. */
995 buf = (char *)PyMem_Malloc(bufsize);
996 if (buf == NULL) {
997 PyErr_NoMemory();
998 goto exit;
999 }
1000 p = buf;
1001
1002 /* Add a negative sign if negative, and a plus sign if non-negative
1003 and always_add_sign is true. */
1004 if (sign == 1)
1005 *p++ = '-';
1006 else if (always_add_sign)
1007 *p++ = '+';
1008
1009 /* note that exactly one of the three 'if' conditions is true,
1010 so we include exactly one decimal point */
1011 /* Zero padding on left of digit string */
1012 if (decpt <= 0) {
1013 memset(p, '0', decpt-vdigits_start);
1014 p += decpt - vdigits_start;
1015 *p++ = '.';
1016 memset(p, '0', 0-decpt);
1017 p += 0-decpt;
1018 }
1019 else {
1020 memset(p, '0', 0-vdigits_start);
1021 p += 0 - vdigits_start;
1022 }
1023
1024 /* Digits, with included decimal point */
1025 if (0 < decpt && decpt <= digits_len) {
1026 strncpy(p, digits, decpt-0);
1027 p += decpt-0;
1028 *p++ = '.';
1029 strncpy(p, digits+decpt, digits_len-decpt);
1030 p += digits_len-decpt;
1031 }
1032 else {
1033 strncpy(p, digits, digits_len);
1034 p += digits_len;
1035 }
1036
1037 /* And zeros on the right */
1038 if (digits_len < decpt) {
1039 memset(p, '0', decpt-digits_len);
1040 p += decpt-digits_len;
1041 *p++ = '.';
1042 memset(p, '0', vdigits_end-decpt);
1043 p += vdigits_end-decpt;
1044 }
1045 else {
1046 memset(p, '0', vdigits_end-digits_len);
1047 p += vdigits_end-digits_len;
1048 }
1049
1050 /* Delete a trailing decimal pt unless using alternative formatting. */
1051 if (p[-1] == '.' && !use_alt_formatting)
1052 p--;
1053
1054 /* Now that we've done zero padding, add an exponent if needed. */
1055 if (use_exp) {
1056 *p++ = float_strings[OFS_E][0];
1057 exp_len = sprintf(p, "%+.02d", exp);
1058 p += exp_len;
1059 }
1060 exit:
1061 if (buf) {
1062 *p = '\0';
1063 /* It's too late if this fails, as we've already stepped on
1064 memory that isn't ours. But it's an okay debugging test. */
1065 assert(p-buf < bufsize);
1066 }
1067 if (digits)
1068 _Py_dg_freedtoa(digits);
1069
1070 return buf;
1071}
1072
1073
1074PyAPI_FUNC(char *) PyOS_double_to_string(double val,
Eric Smith193125a2009-04-16 22:08:31 +00001075 char format_code,
1076 int precision,
1077 int flags,
Eric Smith0923d1d2009-04-16 20:16:10 +00001078 int *type)
1079{
Eric Smith193125a2009-04-16 22:08:31 +00001080 char **float_strings = lc_float_strings;
1081 int mode;
Eric Smith0923d1d2009-04-16 20:16:10 +00001082
Eric Smith193125a2009-04-16 22:08:31 +00001083 /* Validate format_code, and map upper and lower case. Compute the
1084 mode and make any adjustments as needed. */
Eric Smith0923d1d2009-04-16 20:16:10 +00001085 switch (format_code) {
Eric Smith193125a2009-04-16 22:08:31 +00001086 /* exponent */
Eric Smith0923d1d2009-04-16 20:16:10 +00001087 case 'E':
Eric Smith0923d1d2009-04-16 20:16:10 +00001088 float_strings = uc_float_strings;
Eric Smith193125a2009-04-16 22:08:31 +00001089 format_code = 'e';
1090 /* Fall through. */
Eric Smith0923d1d2009-04-16 20:16:10 +00001091 case 'e':
1092 mode = 2;
1093 precision++;
1094 break;
Eric Smith193125a2009-04-16 22:08:31 +00001095
1096 /* fixed */
1097 case 'F':
1098 float_strings = uc_float_strings;
1099 format_code = 'f';
1100 /* Fall through. */
Eric Smith0923d1d2009-04-16 20:16:10 +00001101 case 'f':
1102 mode = 3;
1103 break;
Eric Smith193125a2009-04-16 22:08:31 +00001104
1105 /* general */
1106 case 'G':
1107 float_strings = uc_float_strings;
1108 format_code = 'g';
1109 /* Fall through. */
Eric Smith0923d1d2009-04-16 20:16:10 +00001110 case 'g':
1111 mode = 2;
1112 /* precision 0 makes no sense for 'g' format; interpret as 1 */
1113 if (precision == 0)
1114 precision = 1;
1115 break;
Eric Smith193125a2009-04-16 22:08:31 +00001116
1117 /* repr format */
Eric Smith0923d1d2009-04-16 20:16:10 +00001118 case 'r':
Eric Smith0923d1d2009-04-16 20:16:10 +00001119 mode = 0;
1120 /* Supplied precision is unused, must be 0. */
1121 if (precision != 0) {
1122 PyErr_BadInternalCall();
1123 return NULL;
1124 }
1125 break;
Eric Smith193125a2009-04-16 22:08:31 +00001126
1127 /* str format */
Eric Smith0923d1d2009-04-16 20:16:10 +00001128 case 's':
1129 mode = 2;
1130 /* Supplied precision is unused, must be 0. */
1131 if (precision != 0) {
1132 PyErr_BadInternalCall();
1133 return NULL;
1134 }
1135 precision = 12;
1136 break;
Eric Smith193125a2009-04-16 22:08:31 +00001137
1138 default:
1139 PyErr_BadInternalCall();
1140 return NULL;
Eric Smith0923d1d2009-04-16 20:16:10 +00001141 }
1142
Eric Smith193125a2009-04-16 22:08:31 +00001143 return format_float_short(val, format_code, mode, precision,
Eric Smith0923d1d2009-04-16 20:16:10 +00001144 flags & Py_DTSF_SIGN,
1145 flags & Py_DTSF_ADD_DOT_0,
1146 flags & Py_DTSF_ALT,
1147 float_strings, type);
1148}
1149#endif /* ifdef PY_NO_SHORT_FLOAT_REPR */