blob: f9a8831b11ef92785ad86f02aedf086eea99c730 [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
6/* ascii character tests (as opposed to locale tests) */
7#define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
8 (c) == '\r' || (c) == '\t' || (c) == '\v')
9#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
Martin v. Löwis737ea822004-06-08 18:52:54 +000010
11
12/**
13 * PyOS_ascii_strtod:
14 * @nptr: the string to convert to a numeric value.
15 * @endptr: if non-%NULL, it returns the character after
16 * the last character used in the conversion.
17 *
18 * Converts a string to a #gdouble value.
19 * This function behaves like the standard strtod() function
20 * does in the C locale. It does this without actually
21 * changing the current locale, since that would not be
22 * thread-safe.
23 *
24 * This function is typically used when reading configuration
25 * files or other non-user input that should be locale independent.
26 * To handle input from the user you should normally use the
27 * locale-sensitive system strtod() function.
28 *
29 * If the correct value would cause overflow, plus or minus %HUGE_VAL
30 * is returned (according to the sign of the value), and %ERANGE is
31 * stored in %errno. If the correct value would cause underflow,
32 * zero is returned and %ERANGE is stored in %errno.
Georg Brandlb569ee42006-05-29 14:28:05 +000033 * If memory allocation fails, %ENOMEM is stored in %errno.
Martin v. Löwis737ea822004-06-08 18:52:54 +000034 *
35 * This function resets %errno before calling strtod() so that
36 * you can reliably detect overflow and underflow.
37 *
38 * Return value: the #gdouble value.
39 **/
Eric Smithaca19e62009-04-22 13:29:05 +000040
41/*
42 Use system strtod; since strtod is locale aware, we may
43 have to first fix the decimal separator.
44
45 Note that unlike _Py_dg_strtod, the system strtod may not always give
46 correctly rounded results.
47*/
48
Martin v. Löwis737ea822004-06-08 18:52:54 +000049double
Neal Norwitze7214a12005-12-18 05:03:17 +000050PyOS_ascii_strtod(const char *nptr, char **endptr)
Martin v. Löwis737ea822004-06-08 18:52:54 +000051{
52 char *fail_pos;
Neal Norwitz0e7a0ed2005-12-18 05:37:36 +000053 double val = -1.0;
Martin v. Löwis737ea822004-06-08 18:52:54 +000054 struct lconv *locale_data;
55 const char *decimal_point;
Neal Norwitzd39d8612006-01-08 01:03:36 +000056 size_t decimal_point_len;
Martin v. Löwis737ea822004-06-08 18:52:54 +000057 const char *p, *decimal_point_pos;
58 const char *end = NULL; /* Silence gcc */
Guido van Rossum3b835492008-01-05 00:59:59 +000059 const char *digits_pos = NULL;
60 int negate = 0;
Martin v. Löwis737ea822004-06-08 18:52:54 +000061
Martin v. Löwis737ea822004-06-08 18:52:54 +000062 assert(nptr != NULL);
63
64 fail_pos = NULL;
65
66 locale_data = localeconv();
67 decimal_point = locale_data->decimal_point;
68 decimal_point_len = strlen(decimal_point);
69
70 assert(decimal_point_len != 0);
71
72 decimal_point_pos = NULL;
Guido van Rossum3b835492008-01-05 00:59:59 +000073
74 /* We process any leading whitespace and the optional sign manually,
75 then pass the remainder to the system strtod. This ensures that
76 the result of an underflow has the correct sign. (bug #1725) */
77
78 p = nptr;
79 /* Skip leading space */
80 while (ISSPACE(*p))
81 p++;
82
83 /* Process leading sign, if present */
84 if (*p == '-') {
85 negate = 1;
86 p++;
87 } else if (*p == '+') {
88 p++;
89 }
90
91 /* What's left should begin with a digit, a decimal point, or one of
92 the letters i, I, n, N. It should not begin with 0x or 0X */
93 if ((!ISDIGIT(*p) &&
94 *p != '.' && *p != 'i' && *p != 'I' && *p != 'n' && *p != 'N')
95 ||
96 (*p == '0' && (p[1] == 'x' || p[1] == 'X')))
97 {
98 if (endptr)
99 *endptr = (char*)nptr;
100 errno = EINVAL;
101 return val;
102 }
103 digits_pos = p;
104
Martin v. Löwis737ea822004-06-08 18:52:54 +0000105 if (decimal_point[0] != '.' ||
106 decimal_point[1] != 0)
107 {
Neal Norwitze7214a12005-12-18 05:03:17 +0000108 while (ISDIGIT(*p))
109 p++;
110
111 if (*p == '.')
Martin v. Löwis737ea822004-06-08 18:52:54 +0000112 {
Neal Norwitze7214a12005-12-18 05:03:17 +0000113 decimal_point_pos = p++;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000114
Martin v. Löwis737ea822004-06-08 18:52:54 +0000115 while (ISDIGIT(*p))
116 p++;
117
Neal Norwitze7214a12005-12-18 05:03:17 +0000118 if (*p == 'e' || *p == 'E')
119 p++;
120 if (*p == '+' || *p == '-')
121 p++;
122 while (ISDIGIT(*p))
123 p++;
124 end = p;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000125 }
Martin v. Löwisfcfff0a2006-07-03 12:19:50 +0000126 else if (strncmp(p, decimal_point, decimal_point_len) == 0)
127 {
128 /* Python bug #1417699 */
Guido van Rossum3b835492008-01-05 00:59:59 +0000129 if (endptr)
130 *endptr = (char*)nptr;
Martin v. Löwisfcfff0a2006-07-03 12:19:50 +0000131 errno = EINVAL;
132 return val;
133 }
Eric Smith5c35a9d2008-03-17 12:14:29 +0000134 /* For the other cases, we need not convert the decimal
135 point */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000136 }
137
Neal Norwitze7214a12005-12-18 05:03:17 +0000138 /* Set errno to zero, so that we can distinguish zero results
139 and underflows */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000140 errno = 0;
141
142 if (decimal_point_pos)
143 {
144 char *copy, *c;
145
Eric Smith5c35a9d2008-03-17 12:14:29 +0000146 /* We need to convert the '.' to the locale specific decimal
147 point */
Guido van Rossum3b835492008-01-05 00:59:59 +0000148 copy = (char *)PyMem_MALLOC(end - digits_pos +
149 1 + decimal_point_len);
Georg Brandlb569ee42006-05-29 14:28:05 +0000150 if (copy == NULL) {
151 if (endptr)
Georg Brandl80181e22006-05-29 14:33:55 +0000152 *endptr = (char *)nptr;
Georg Brandlb569ee42006-05-29 14:28:05 +0000153 errno = ENOMEM;
154 return val;
155 }
Martin v. Löwis737ea822004-06-08 18:52:54 +0000156
157 c = copy;
Guido van Rossum3b835492008-01-05 00:59:59 +0000158 memcpy(c, digits_pos, decimal_point_pos - digits_pos);
159 c += decimal_point_pos - digits_pos;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000160 memcpy(c, decimal_point, decimal_point_len);
161 c += decimal_point_len;
Eric Smith5c35a9d2008-03-17 12:14:29 +0000162 memcpy(c, decimal_point_pos + 1,
163 end - (decimal_point_pos + 1));
Martin v. Löwis737ea822004-06-08 18:52:54 +0000164 c += end - (decimal_point_pos + 1);
165 *c = 0;
166
167 val = strtod(copy, &fail_pos);
168
169 if (fail_pos)
170 {
171 if (fail_pos > decimal_point_pos)
Guido van Rossum3b835492008-01-05 00:59:59 +0000172 fail_pos = (char *)digits_pos +
173 (fail_pos - copy) -
174 (decimal_point_len - 1);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000175 else
Guido van Rossum3b835492008-01-05 00:59:59 +0000176 fail_pos = (char *)digits_pos +
177 (fail_pos - copy);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000178 }
179
Brett Cannon0ed05872006-05-25 20:44:08 +0000180 PyMem_FREE(copy);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000181
182 }
Neal Norwitze7214a12005-12-18 05:03:17 +0000183 else {
Guido van Rossum3b835492008-01-05 00:59:59 +0000184 val = strtod(digits_pos, &fail_pos);
Neal Norwitze7214a12005-12-18 05:03:17 +0000185 }
Martin v. Löwis737ea822004-06-08 18:52:54 +0000186
Guido van Rossum3b835492008-01-05 00:59:59 +0000187 if (fail_pos == digits_pos)
188 fail_pos = (char *)nptr;
189
190 if (negate && fail_pos != nptr)
191 val = -val;
192
Martin v. Löwis737ea822004-06-08 18:52:54 +0000193 if (endptr)
194 *endptr = fail_pos;
195
196 return val;
197}
198
Eric Smithaca19e62009-04-22 13:29:05 +0000199double
200PyOS_ascii_atof(const char *nptr)
201{
202 return PyOS_ascii_strtod(nptr, NULL);
203}
204
205
Eric Smith0a950632008-04-30 01:09:30 +0000206/* Given a string that may have a decimal point in the current
207 locale, change it back to a dot. Since the string cannot get
208 longer, no need for a maximum buffer size parameter. */
209Py_LOCAL_INLINE(void)
210change_decimal_from_locale_to_dot(char* buffer)
211{
212 struct lconv *locale_data = localeconv();
213 const char *decimal_point = locale_data->decimal_point;
214
215 if (decimal_point[0] != '.' || decimal_point[1] != 0) {
216 size_t decimal_point_len = strlen(decimal_point);
217
218 if (*buffer == '+' || *buffer == '-')
219 buffer++;
220 while (isdigit(Py_CHARMASK(*buffer)))
221 buffer++;
222 if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
223 *buffer = '.';
224 buffer++;
225 if (decimal_point_len > 1) {
226 /* buffer needs to get smaller */
227 size_t rest_len = strlen(buffer +
228 (decimal_point_len - 1));
229 memmove(buffer,
230 buffer + (decimal_point_len - 1),
231 rest_len);
232 buffer[rest_len] = 0;
233 }
234 }
235 }
236}
237
Martin v. Löwis737ea822004-06-08 18:52:54 +0000238
Eric Smith068f0652009-04-25 21:40:15 +0000239Py_LOCAL_INLINE(void)
240ensure_sign(char* buffer, size_t buf_size)
241{
242 Py_ssize_t len;
243
244 if (buffer[0] == '-')
245 /* Already have a sign. */
246 return;
247
248 /* Include the trailing 0 byte. */
249 len = strlen(buffer)+1;
250 if (len >= buf_size+1)
251 /* No room for the sign, don't do anything. */
252 return;
253
254 memmove(buffer+1, buffer, len);
255 buffer[0] = '+';
256}
257
Eric Smith7ef40bf2008-02-20 23:34:22 +0000258/* From the C99 standard, section 7.19.6:
259The exponent always contains at least two digits, and only as many more digits
260as necessary to represent the exponent.
261*/
262#define MIN_EXPONENT_DIGITS 2
263
Eric Smith0a950632008-04-30 01:09:30 +0000264/* Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS
265 in length. */
266Py_LOCAL_INLINE(void)
267ensure_minumim_exponent_length(char* buffer, size_t buf_size)
268{
269 char *p = strpbrk(buffer, "eE");
270 if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
271 char *start = p + 2;
272 int exponent_digit_cnt = 0;
273 int leading_zero_cnt = 0;
274 int in_leading_zeros = 1;
275 int significant_digit_cnt;
276
277 /* Skip over the exponent and the sign. */
278 p += 2;
279
280 /* Find the end of the exponent, keeping track of leading
281 zeros. */
282 while (*p && isdigit(Py_CHARMASK(*p))) {
283 if (in_leading_zeros && *p == '0')
284 ++leading_zero_cnt;
285 if (*p != '0')
286 in_leading_zeros = 0;
287 ++p;
288 ++exponent_digit_cnt;
289 }
290
291 significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
292 if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
293 /* If there are 2 exactly digits, we're done,
294 regardless of what they contain */
295 }
296 else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
297 int extra_zeros_cnt;
298
299 /* There are more than 2 digits in the exponent. See
300 if we can delete some of the leading zeros */
301 if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
302 significant_digit_cnt = MIN_EXPONENT_DIGITS;
303 extra_zeros_cnt = exponent_digit_cnt -
304 significant_digit_cnt;
305
306 /* Delete extra_zeros_cnt worth of characters from the
307 front of the exponent */
308 assert(extra_zeros_cnt >= 0);
309
310 /* Add one to significant_digit_cnt to copy the
311 trailing 0 byte, thus setting the length */
312 memmove(start,
313 start + extra_zeros_cnt,
314 significant_digit_cnt + 1);
315 }
316 else {
317 /* If there are fewer than 2 digits, add zeros
318 until there are 2, if there's enough room */
319 int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
320 if (start + zeros + exponent_digit_cnt + 1
321 < buffer + buf_size) {
322 memmove(start + zeros, start,
323 exponent_digit_cnt + 1);
324 memset(start, '0', zeros);
325 }
326 }
327 }
328}
329
Eric Smithaca19e62009-04-22 13:29:05 +0000330/* Ensure that buffer has a decimal point in it. The decimal point will not
331 be in the current locale, it will always be '.'. Don't add a decimal if an
332 exponent is present. */
Eric Smith0a950632008-04-30 01:09:30 +0000333Py_LOCAL_INLINE(void)
334ensure_decimal_point(char* buffer, size_t buf_size)
335{
336 int insert_count = 0;
337 char* chars_to_insert;
338
339 /* search for the first non-digit character */
340 char *p = buffer;
Eric Smithf032a002008-07-19 00:24:05 +0000341 if (*p == '-' || *p == '+')
342 /* Skip leading sign, if present. I think this could only
343 ever be '-', but it can't hurt to check for both. */
344 ++p;
Eric Smith0a950632008-04-30 01:09:30 +0000345 while (*p && isdigit(Py_CHARMASK(*p)))
346 ++p;
347
348 if (*p == '.') {
349 if (isdigit(Py_CHARMASK(*(p+1)))) {
350 /* Nothing to do, we already have a decimal
351 point and a digit after it */
352 }
353 else {
354 /* We have a decimal point, but no following
355 digit. Insert a zero after the decimal. */
356 ++p;
357 chars_to_insert = "0";
358 insert_count = 1;
359 }
360 }
Eric Smithaca19e62009-04-22 13:29:05 +0000361 else if (!(*p == 'e' || *p == 'E')) {
362 /* Don't add ".0" if we have an exponent. */
Eric Smith0a950632008-04-30 01:09:30 +0000363 chars_to_insert = ".0";
364 insert_count = 2;
365 }
366 if (insert_count) {
367 size_t buf_len = strlen(buffer);
368 if (buf_len + insert_count + 1 >= buf_size) {
369 /* If there is not enough room in the buffer
370 for the additional text, just skip it. It's
371 not worth generating an error over. */
372 }
373 else {
374 memmove(p + insert_count, p,
375 buffer + strlen(buffer) - p + 1);
376 memcpy(p, chars_to_insert, insert_count);
377 }
378 }
379}
380
Eric Smith7ef40bf2008-02-20 23:34:22 +0000381/* see FORMATBUFLEN in unicodeobject.c */
382#define FLOAT_FORMATBUFLEN 120
383
Martin v. Löwis737ea822004-06-08 18:52:54 +0000384/**
Eric Smith068f0652009-04-25 21:40:15 +0000385 * _PyOS_ascii_formatd:
Martin v. Löwis737ea822004-06-08 18:52:54 +0000386 * @buffer: A buffer to place the resulting string in
Eric Smith8113ca62008-03-17 11:01:01 +0000387 * @buf_size: The length of the buffer.
Martin v. Löwis737ea822004-06-08 18:52:54 +0000388 * @format: The printf()-style format to use for the
389 * code to use for converting.
390 * @d: The #gdouble to convert
391 *
392 * Converts a #gdouble to a string, using the '.' as
393 * decimal point. To format the number you pass in
394 * a printf()-style format string. Allowed conversion
Eric Smithaca19e62009-04-22 13:29:05 +0000395 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'.
Martin v. Löwis737ea822004-06-08 18:52:54 +0000396 *
Eric Smith8113ca62008-03-17 11:01:01 +0000397 * 'Z' is the same as 'g', except it always has a decimal and
398 * at least one digit after the decimal.
Eric Smith7ef40bf2008-02-20 23:34:22 +0000399 *
Martin v. Löwis737ea822004-06-08 18:52:54 +0000400 * Return value: The pointer to the buffer with the converted string.
401 **/
Eric Smith068f0652009-04-25 21:40:15 +0000402/* DEPRECATED, will be deleted in 2.8 and 3.2 */
403PyAPI_FUNC(char *)
Martin v. Löwis737ea822004-06-08 18:52:54 +0000404PyOS_ascii_formatd(char *buffer,
Eric Smith8113ca62008-03-17 11:01:01 +0000405 size_t buf_size,
Martin v. Löwis737ea822004-06-08 18:52:54 +0000406 const char *format,
407 double d)
408{
Martin v. Löwis737ea822004-06-08 18:52:54 +0000409 char format_char;
Eric Smith7ef40bf2008-02-20 23:34:22 +0000410 size_t format_len = strlen(format);
411
Eric Smith8113ca62008-03-17 11:01:01 +0000412 /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but
413 also with at least one character past the decimal. */
Eric Smith7ef40bf2008-02-20 23:34:22 +0000414 char tmp_format[FLOAT_FORMATBUFLEN];
Martin v. Löwis737ea822004-06-08 18:52:54 +0000415
Eric Smith068f0652009-04-25 21:40:15 +0000416 if (PyErr_WarnEx(PyExc_DeprecationWarning,
417 "PyOS_ascii_formatd is deprecated, "
418 "use PyOS_double_to_string instead", 1) < 0)
419 return NULL;
420
Eric Smith7ef40bf2008-02-20 23:34:22 +0000421 /* The last character in the format string must be the format char */
422 format_char = format[format_len - 1];
Martin v. Löwis737ea822004-06-08 18:52:54 +0000423
Martin v. Löwis737ea822004-06-08 18:52:54 +0000424 if (format[0] != '%')
425 return NULL;
426
Eric Smith7ef40bf2008-02-20 23:34:22 +0000427 /* I'm not sure why this test is here. It's ensuring that the format
428 string after the first character doesn't have a single quote, a
429 lowercase l, or a percent. This is the reverse of the commented-out
430 test about 10 lines ago. */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000431 if (strpbrk(format + 1, "'l%"))
432 return NULL;
433
Eric Smith8113ca62008-03-17 11:01:01 +0000434 /* Also curious about this function is that it accepts format strings
435 like "%xg", which are invalid for floats. In general, the
436 interface to this function is not very good, but changing it is
437 difficult because it's a public API. */
438
Martin v. Löwis737ea822004-06-08 18:52:54 +0000439 if (!(format_char == 'e' || format_char == 'E' ||
440 format_char == 'f' || format_char == 'F' ||
Eric Smith7ef40bf2008-02-20 23:34:22 +0000441 format_char == 'g' || format_char == 'G' ||
Eric Smithaca19e62009-04-22 13:29:05 +0000442 format_char == 'Z'))
Martin v. Löwis737ea822004-06-08 18:52:54 +0000443 return NULL;
444
Eric Smithaca19e62009-04-22 13:29:05 +0000445 /* Map 'Z' format_char to 'g', by copying the format string and
Eric Smith8113ca62008-03-17 11:01:01 +0000446 replacing the final char with a 'g' */
Eric Smithaca19e62009-04-22 13:29:05 +0000447 if (format_char == 'Z') {
Eric Smith7ef40bf2008-02-20 23:34:22 +0000448 if (format_len + 1 >= sizeof(tmp_format)) {
449 /* The format won't fit in our copy. Error out. In
Eric Smith5c35a9d2008-03-17 12:14:29 +0000450 practice, this will never happen and will be
451 detected by returning NULL */
Eric Smith7ef40bf2008-02-20 23:34:22 +0000452 return NULL;
453 }
454 strcpy(tmp_format, format);
455 tmp_format[format_len - 1] = 'g';
456 format = tmp_format;
457 }
Martin v. Löwis737ea822004-06-08 18:52:54 +0000458
Eric Smith8113ca62008-03-17 11:01:01 +0000459
Eric Smith7ef40bf2008-02-20 23:34:22 +0000460 /* Have PyOS_snprintf do the hard work */
Eric Smith8113ca62008-03-17 11:01:01 +0000461 PyOS_snprintf(buffer, buf_size, format, d);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000462
Eric Smith0a950632008-04-30 01:09:30 +0000463 /* Do various fixups on the return string */
Martin v. Löwis737ea822004-06-08 18:52:54 +0000464
Eric Smith0a950632008-04-30 01:09:30 +0000465 /* Get the current locale, and find the decimal point string.
Eric Smithaca19e62009-04-22 13:29:05 +0000466 Convert that string back to a dot. */
467 change_decimal_from_locale_to_dot(buffer);
Eric Smith7ef40bf2008-02-20 23:34:22 +0000468
469 /* If an exponent exists, ensure that the exponent is at least
470 MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
471 for the extra zeros. Also, if there are more than
472 MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
473 back to MIN_EXPONENT_DIGITS */
Eric Smith0a950632008-04-30 01:09:30 +0000474 ensure_minumim_exponent_length(buffer, buf_size);
Martin v. Löwis737ea822004-06-08 18:52:54 +0000475
Eric Smith8113ca62008-03-17 11:01:01 +0000476 /* If format_char is 'Z', make sure we have at least one character
477 after the decimal point (and make sure we have a decimal point). */
Eric Smith0a950632008-04-30 01:09:30 +0000478 if (format_char == 'Z')
479 ensure_decimal_point(buffer, buf_size);
Eric Smith8113ca62008-03-17 11:01:01 +0000480
Martin v. Löwis737ea822004-06-08 18:52:54 +0000481 return buffer;
482}
483
Eric Smith068f0652009-04-25 21:40:15 +0000484PyAPI_FUNC(void)
485_PyOS_double_to_string(char *buf, size_t buf_len, double val,
486 char format_code, int precision,
487 int flags, int *ptype)
Martin v. Löwis737ea822004-06-08 18:52:54 +0000488{
Eric Smithaca19e62009-04-22 13:29:05 +0000489 char format[32];
Eric Smithaca19e62009-04-22 13:29:05 +0000490 int t;
491 int upper = 0;
492
Eric Smith068f0652009-04-25 21:40:15 +0000493 if (buf_len < 1) {
494 assert(0);
495 /* There's no way to signal this error. Just return. */
496 return;
497 }
498 buf[0] = 0;
499
Eric Smithaca19e62009-04-22 13:29:05 +0000500 /* Validate format_code, and map upper and lower case */
501 switch (format_code) {
502 case 'e': /* exponent */
503 case 'f': /* fixed */
504 case 'g': /* general */
505 break;
506 case 'E':
507 upper = 1;
508 format_code = 'e';
509 break;
510 case 'F':
511 upper = 1;
512 format_code = 'f';
513 break;
514 case 'G':
515 upper = 1;
516 format_code = 'g';
517 break;
518 case 'r': /* repr format */
519 /* Supplied precision is unused, must be 0. */
Eric Smith068f0652009-04-25 21:40:15 +0000520 if (precision != 0)
521 return;
Eric Smithaca19e62009-04-22 13:29:05 +0000522 precision = 17;
523 format_code = 'g';
524 break;
525 case 's': /* str format */
526 /* Supplied precision is unused, must be 0. */
Eric Smith068f0652009-04-25 21:40:15 +0000527 if (precision != 0)
528 return;
Eric Smithaca19e62009-04-22 13:29:05 +0000529 precision = 12;
530 format_code = 'g';
531 break;
532 default:
Eric Smith068f0652009-04-25 21:40:15 +0000533 assert(0);
534 return;
535 }
536
537 /* Check for buf too small to fit "-inf". Other buffer too small
538 conditions are dealt with when converting or formatting finite
539 numbers. */
540 if (buf_len < 5) {
541 assert(0);
542 return;
Eric Smithaca19e62009-04-22 13:29:05 +0000543 }
544
545 /* Handle nan and inf. */
546 if (Py_IS_NAN(val)) {
547 strcpy(buf, "nan");
548 t = Py_DTST_NAN;
549 } else if (Py_IS_INFINITY(val)) {
550 if (copysign(1., val) == 1.)
551 strcpy(buf, "inf");
552 else
553 strcpy(buf, "-inf");
554 t = Py_DTST_INFINITE;
555 } else {
556 t = Py_DTST_FINITE;
557
Eric Smith068f0652009-04-25 21:40:15 +0000558 /* Build the format string. */
559 PyOS_snprintf(format, sizeof(format), "%%%s.%i%c",
560 (flags & Py_DTSF_ALT ? "#" : ""), precision,
561 format_code);
Eric Smithaca19e62009-04-22 13:29:05 +0000562
Eric Smith068f0652009-04-25 21:40:15 +0000563 /* Have PyOS_snprintf do the hard work. */
564 PyOS_snprintf(buf, buf_len, format, val);
565
566 /* Do various fixups on the return string */
567
568 /* Get the current locale, and find the decimal point string.
569 Convert that string back to a dot. */
570 change_decimal_from_locale_to_dot(buf);
571
572 /* If an exponent exists, ensure that the exponent is at least
573 MIN_EXPONENT_DIGITS digits, providing the buffer is large
574 enough for the extra zeros. Also, if there are more than
575 MIN_EXPONENT_DIGITS, remove as many zeros as possible until
576 we get back to MIN_EXPONENT_DIGITS */
577 ensure_minumim_exponent_length(buf, buf_len);
578
579 /* Possibly make sure we have at least one character after the
580 decimal point (and make sure we have a decimal point). */
Eric Smithaca19e62009-04-22 13:29:05 +0000581 if (flags & Py_DTSF_ADD_DOT_0)
Eric Smith068f0652009-04-25 21:40:15 +0000582 ensure_decimal_point(buf, buf_len);
Eric Smithaca19e62009-04-22 13:29:05 +0000583 }
584
Eric Smith068f0652009-04-25 21:40:15 +0000585 /* Add the sign if asked and the result isn't negative. */
586 if (flags & Py_DTSF_SIGN && buf[0] != '-')
587 ensure_sign(buf, buf_len);
Eric Smithaca19e62009-04-22 13:29:05 +0000588
Eric Smith068f0652009-04-25 21:40:15 +0000589 if (upper) {
590 /* Convert to upper case. */
591 char *p;
592 for (p = buf; *p; p++)
593 *p = toupper(*p);
594 }
595
596 if (ptype)
597 *ptype = t;
598}
599
600
601PyAPI_FUNC(char *) PyOS_double_to_string(double val,
602 char format_code,
603 int precision,
604 int flags,
605 int *ptype)
606{
607 char buf[128];
608 Py_ssize_t len;
609 char *result;
610
611 _PyOS_double_to_string(buf, sizeof(buf), val, format_code, precision,
612 flags, ptype);
613 len = strlen(buf);
614 if (len == 0) {
615 PyErr_BadInternalCall();
616 return NULL;
617 }
618
619 /* Add 1 for the trailing 0 byte. */
620 result = PyMem_Malloc(len + 1);
Eric Smithaca19e62009-04-22 13:29:05 +0000621 if (result == NULL) {
622 PyErr_NoMemory();
623 return NULL;
624 }
Eric Smith068f0652009-04-25 21:40:15 +0000625 strcpy(result, buf);
Eric Smithaca19e62009-04-22 13:29:05 +0000626
Eric Smithaca19e62009-04-22 13:29:05 +0000627 return result;
Martin v. Löwis737ea822004-06-08 18:52:54 +0000628}