annotate Python/pystrtod.c @ 56700:2146bbdf4ed7 legacy-trunk

Issue #7117: Prepare for backport of py3k float repr. Add the Python/dtoa.c file containing the main algorithms; add corresponding include file and include in Python.h; include license information for Python/dtoa.c; add dtoa.c and dtoa.h to Makefile.
author Mark Dickinson <dickinsm@gmail.com>
date Sat, 24 Oct 2009 12:13:30 +0000
parents 1d8f24d40c2c
children 38fda3a42c0b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
1 /* -*- Mode: C; c-file-style: "python" -*- */
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
2
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
3 #include <Python.h>
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
4 #include <locale.h>
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
5
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
6 /**
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
7 * PyOS_ascii_strtod:
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
8 * @nptr: the string to convert to a numeric value.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
9 * @endptr: if non-%NULL, it returns the character after
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
10 * the last character used in the conversion.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
11 *
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
12 * Converts a string to a #gdouble value.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
13 * This function behaves like the standard strtod() function
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
14 * does in the C locale. It does this without actually
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
15 * changing the current locale, since that would not be
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
16 * thread-safe.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
17 *
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
18 * This function is typically used when reading configuration
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
19 * files or other non-user input that should be locale independent.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
20 * To handle input from the user you should normally use the
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
21 * locale-sensitive system strtod() function.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
22 *
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
23 * If the correct value would cause overflow, plus or minus %HUGE_VAL
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
24 * is returned (according to the sign of the value), and %ERANGE is
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
25 * stored in %errno. If the correct value would cause underflow,
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
26 * zero is returned and %ERANGE is stored in %errno.
38480
9b001ebeaa5e Handle PyMem_Malloc failure in pystrtod.c. Closes #1494671.
Georg Brandl <georg@python.org>
parents: 38320
diff changeset
27 * If memory allocation fails, %ENOMEM is stored in %errno.
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
28 *
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
29 * This function resets %errno before calling strtod() so that
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
30 * you can reliably detect overflow and underflow.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
31 *
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
32 * Return value: the #gdouble value.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
33 **/
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
34
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
35 /*
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
36 Use system strtod; since strtod is locale aware, we may
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
37 have to first fix the decimal separator.
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
38
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
39 Note that unlike _Py_dg_strtod, the system strtod may not always give
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
40 correctly rounded results.
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
41 */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
42
53716
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
43 /* Case-insensitive string match used for nan and inf detection; t should be
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
44 lower-case. Returns 1 for a successful match, 0 otherwise. */
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
45
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
46 static int
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
47 case_insensitive_match(const char *s, const char *t)
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
48 {
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
49 while(*t && Py_TOLOWER(*s) == *t) {
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
50 s++;
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
51 t++;
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
52 }
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
53 return *t ? 0 : 1;
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
54 }
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
55
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
56 double
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
57 PyOS_ascii_strtod(const char *nptr, char **endptr)
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
58 {
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
59 char *fail_pos;
36080
10440bcfa061 Fix compiler warnings
Neal Norwitz <nnorwitz@gmail.com>
parents: 36077
diff changeset
60 double val = -1.0;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
61 struct lconv *locale_data;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
62 const char *decimal_point;
36230
ded4a497eb76 Fix icc warnings: strlen() returns size_t
Neal Norwitz <nnorwitz@gmail.com>
parents: 36080
diff changeset
63 size_t decimal_point_len;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
64 const char *p, *decimal_point_pos;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
65 const char *end = NULL; /* Silence gcc */
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
66 const char *digits_pos = NULL;
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
67 int negate = 0;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
68
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
69 assert(nptr != NULL);
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
70
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
71 fail_pos = NULL;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
72
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
73 locale_data = localeconv();
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
74 decimal_point = locale_data->decimal_point;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
75 decimal_point_len = strlen(decimal_point);
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
76
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
77 assert(decimal_point_len != 0);
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
78
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
79 decimal_point_pos = NULL;
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
80
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
81 /* Set errno to zero, so that we can distinguish zero results
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
82 and underflows */
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
83 errno = 0;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
84
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
85 /* We process any leading whitespace and the optional sign manually,
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
86 then pass the remainder to the system strtod. This ensures that
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
87 the result of an underflow has the correct sign. (bug #1725) */
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
88
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
89 p = nptr;
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
90 /* Skip leading space */
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
91 while (Py_ISSPACE(*p))
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
92 p++;
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
93
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
94 /* Process leading sign, if present */
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
95 if (*p == '-') {
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
96 negate = 1;
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
97 p++;
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
98 }
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
99 else if (*p == '+') {
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
100 p++;
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
101 }
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
102
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
103 /* Parse infinities and nans */
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
104 if (*p == 'i' || *p == 'I') {
53716
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
105 if (case_insensitive_match(p+1, "nf")) {
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
106 val = Py_HUGE_VAL;
53716
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
107 if (case_insensitive_match(p+3, "inity"))
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
108 fail_pos = (char *)p+8;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
109 else
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
110 fail_pos = (char *)p+3;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
111 goto got_val;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
112 }
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
113 else
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
114 goto invalid_string;
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
115 }
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
116 #ifdef Py_NAN
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
117 if (*p == 'n' || *p == 'N') {
53716
4f867f1494d5 Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
Mark Dickinson <dickinsm@gmail.com>
parents: 53712
diff changeset
118 if (case_insensitive_match(p+1, "an")) {
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
119 val = Py_NAN;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
120 fail_pos = (char *)p+3;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
121 goto got_val;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
122 }
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
123 else
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
124 goto invalid_string;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
125 }
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
126 #endif
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
127
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
128 /* Some platform strtods accept hex floats; Python shouldn't (at the
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
129 moment), so we check explicitly for strings starting with '0x'. */
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
130 if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X'))
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
131 goto invalid_string;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
132
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
133 /* Check that what's left begins with a digit or decimal point */
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
134 if (!Py_ISDIGIT(*p) && *p != '.')
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
135 goto invalid_string;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
136
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
137 digits_pos = p;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
138 if (decimal_point[0] != '.' ||
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
139 decimal_point[1] != 0)
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
140 {
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
141 /* Look for a '.' in the input; if present, it'll need to be
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
142 swapped for the current locale's decimal point before we
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
143 call strtod. On the other hand, if we find the current
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
144 locale's decimal point then the input is invalid. */
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
145 while (Py_ISDIGIT(*p))
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
146 p++;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
147
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
148 if (*p == '.')
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
149 {
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
150 decimal_point_pos = p++;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
151
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
152 /* locate end of number */
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
153 while (Py_ISDIGIT(*p))
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
154 p++;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
155
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
156 if (*p == 'e' || *p == 'E')
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
157 p++;
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
158 if (*p == '+' || *p == '-')
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
159 p++;
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
160 while (Py_ISDIGIT(*p))
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
161 p++;
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
162 end = p;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
163 }
38989
0e8a94ba2106 Bug #1417699: Reject locale-specific decimal point in float()
Martin v. Löwis <martin@v.loewis.de>
parents: 38481
diff changeset
164 else if (strncmp(p, decimal_point, decimal_point_len) == 0)
0e8a94ba2106 Bug #1417699: Reject locale-specific decimal point in float()
Martin v. Löwis <martin@v.loewis.de>
parents: 38481
diff changeset
165 /* Python bug #1417699 */
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
166 goto invalid_string;
45786
16732db00822 Reformated lines > 79 chars.
Eric Smith <eric@trueblade.com>
parents: 45785
diff changeset
167 /* For the other cases, we need not convert the decimal
16732db00822 Reformated lines > 79 chars.
Eric Smith <eric@trueblade.com>
parents: 45785
diff changeset
168 point */
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
169 }
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
170
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
171 if (decimal_point_pos) {
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
172 char *copy, *c;
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
173 /* Create a copy of the input, with the '.' converted to the
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
174 locale-specific decimal point */
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
175 copy = (char *)PyMem_MALLOC(end - digits_pos +
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
176 1 + decimal_point_len);
38480
9b001ebeaa5e Handle PyMem_Malloc failure in pystrtod.c. Closes #1494671.
Georg Brandl <georg@python.org>
parents: 38320
diff changeset
177 if (copy == NULL) {
9b001ebeaa5e Handle PyMem_Malloc failure in pystrtod.c. Closes #1494671.
Georg Brandl <georg@python.org>
parents: 38320
diff changeset
178 if (endptr)
38481
3d1a99b39fca Fix compiler warning.
Georg Brandl <georg@python.org>
parents: 38480
diff changeset
179 *endptr = (char *)nptr;
38480
9b001ebeaa5e Handle PyMem_Malloc failure in pystrtod.c. Closes #1494671.
Georg Brandl <georg@python.org>
parents: 38320
diff changeset
180 errno = ENOMEM;
9b001ebeaa5e Handle PyMem_Malloc failure in pystrtod.c. Closes #1494671.
Georg Brandl <georg@python.org>
parents: 38320
diff changeset
181 return val;
9b001ebeaa5e Handle PyMem_Malloc failure in pystrtod.c. Closes #1494671.
Georg Brandl <georg@python.org>
parents: 38320
diff changeset
182 }
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
183
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
184 c = copy;
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
185 memcpy(c, digits_pos, decimal_point_pos - digits_pos);
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
186 c += decimal_point_pos - digits_pos;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
187 memcpy(c, decimal_point, decimal_point_len);
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
188 c += decimal_point_len;
45786
16732db00822 Reformated lines > 79 chars.
Eric Smith <eric@trueblade.com>
parents: 45785
diff changeset
189 memcpy(c, decimal_point_pos + 1,
16732db00822 Reformated lines > 79 chars.
Eric Smith <eric@trueblade.com>
parents: 45785
diff changeset
190 end - (decimal_point_pos + 1));
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
191 c += end - (decimal_point_pos + 1);
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
192 *c = 0;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
193
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
194 val = strtod(copy, &fail_pos);
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
195
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
196 if (fail_pos)
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
197 {
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
198 if (fail_pos > decimal_point_pos)
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
199 fail_pos = (char *)digits_pos +
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
200 (fail_pos - copy) -
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
201 (decimal_point_len - 1);
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
202 else
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
203 fail_pos = (char *)digits_pos +
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
204 (fail_pos - copy);
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
205 }
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
206
38320
3d477d158401 Swap out bare malloc()/free() use for PyMem_MALLOC()/PyMem_FREE() .
Brett Cannon <bcannon@gmail.com>
parents: 37607
diff changeset
207 PyMem_FREE(copy);
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
208
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
209 }
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
210 else {
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
211 val = strtod(digits_pos, &fail_pos);
36077
3b90258fec9f Get float() to be more portable across platforms. Disable hex strings.
Neal Norwitz <nnorwitz@gmail.com>
parents: 32305
diff changeset
212 }
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
213
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
214 if (fail_pos == digits_pos)
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
215 goto invalid_string;
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
216
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
217 got_val:
44482
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
218 if (negate && fail_pos != nptr)
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
219 val = -val;
3fcaf6cc306d Patch #1725 by Mark Dickinson, fixes incorrect conversion of -1e1000
Guido van Rossum <guido@python.org>
parents: 38989
diff changeset
220
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
221 if (endptr)
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
222 *endptr = fail_pos;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
223
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
224 return val;
53470
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
225
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
226 invalid_string:
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
227 if (endptr)
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
228 *endptr = (char*)nptr;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
229 errno = EINVAL;
01c3363a357f Backport r71967 changes from py3k to trunk.
Mark Dickinson <dickinsm@gmail.com>
parents: 53442
diff changeset
230 return -1.0;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
231 }
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
232
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
233 double
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
234 PyOS_ascii_atof(const char *nptr)
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
235 {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
236 return PyOS_ascii_strtod(nptr, NULL);
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
237 }
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
238
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
239
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
240 /* Given a string that may have a decimal point in the current
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
241 locale, change it back to a dot. Since the string cannot get
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
242 longer, no need for a maximum buffer size parameter. */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
243 Py_LOCAL_INLINE(void)
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
244 change_decimal_from_locale_to_dot(char* buffer)
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
245 {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
246 struct lconv *locale_data = localeconv();
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
247 const char *decimal_point = locale_data->decimal_point;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
248
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
249 if (decimal_point[0] != '.' || decimal_point[1] != 0) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
250 size_t decimal_point_len = strlen(decimal_point);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
251
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
252 if (*buffer == '+' || *buffer == '-')
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
253 buffer++;
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
254 while (Py_ISDIGIT(*buffer))
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
255 buffer++;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
256 if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
257 *buffer = '.';
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
258 buffer++;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
259 if (decimal_point_len > 1) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
260 /* buffer needs to get smaller */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
261 size_t rest_len = strlen(buffer +
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
262 (decimal_point_len - 1));
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
263 memmove(buffer,
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
264 buffer + (decimal_point_len - 1),
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
265 rest_len);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
266 buffer[rest_len] = 0;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
267 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
268 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
269 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
270 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
271
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
272
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
273 Py_LOCAL_INLINE(void)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
274 ensure_sign(char* buffer, size_t buf_size)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
275 {
53555
d9b9422b409c Silence warning on Windows.
Eric Smith <eric@trueblade.com>
parents: 53539
diff changeset
276 size_t len;
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
277
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
278 if (buffer[0] == '-')
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
279 /* Already have a sign. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
280 return;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
281
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
282 /* Include the trailing 0 byte. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
283 len = strlen(buffer)+1;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
284 if (len >= buf_size+1)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
285 /* No room for the sign, don't do anything. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
286 return;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
287
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
288 memmove(buffer+1, buffer, len);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
289 buffer[0] = '+';
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
290 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
291
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
292 /* From the C99 standard, section 7.19.6:
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
293 The exponent always contains at least two digits, and only as many more digits
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
294 as necessary to represent the exponent.
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
295 */
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
296 #define MIN_EXPONENT_DIGITS 2
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
297
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
298 /* Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
299 in length. */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
300 Py_LOCAL_INLINE(void)
53477
bfb47bc1d051 Fix typo in function name
Mark Dickinson <dickinsm@gmail.com>
parents: 53470
diff changeset
301 ensure_minimum_exponent_length(char* buffer, size_t buf_size)
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
302 {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
303 char *p = strpbrk(buffer, "eE");
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
304 if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
305 char *start = p + 2;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
306 int exponent_digit_cnt = 0;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
307 int leading_zero_cnt = 0;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
308 int in_leading_zeros = 1;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
309 int significant_digit_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
310
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
311 /* Skip over the exponent and the sign. */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
312 p += 2;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
313
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
314 /* Find the end of the exponent, keeping track of leading
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
315 zeros. */
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
316 while (*p && Py_ISDIGIT(*p)) {
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
317 if (in_leading_zeros && *p == '0')
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
318 ++leading_zero_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
319 if (*p != '0')
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
320 in_leading_zeros = 0;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
321 ++p;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
322 ++exponent_digit_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
323 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
324
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
325 significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
326 if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
327 /* If there are 2 exactly digits, we're done,
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
328 regardless of what they contain */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
329 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
330 else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
331 int extra_zeros_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
332
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
333 /* There are more than 2 digits in the exponent. See
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
334 if we can delete some of the leading zeros */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
335 if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
336 significant_digit_cnt = MIN_EXPONENT_DIGITS;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
337 extra_zeros_cnt = exponent_digit_cnt -
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
338 significant_digit_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
339
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
340 /* Delete extra_zeros_cnt worth of characters from the
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
341 front of the exponent */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
342 assert(extra_zeros_cnt >= 0);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
343
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
344 /* Add one to significant_digit_cnt to copy the
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
345 trailing 0 byte, thus setting the length */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
346 memmove(start,
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
347 start + extra_zeros_cnt,
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
348 significant_digit_cnt + 1);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
349 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
350 else {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
351 /* If there are fewer than 2 digits, add zeros
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
352 until there are 2, if there's enough room */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
353 int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
354 if (start + zeros + exponent_digit_cnt + 1
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
355 < buffer + buf_size) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
356 memmove(start + zeros, start,
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
357 exponent_digit_cnt + 1);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
358 memset(start, '0', zeros);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
359 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
360 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
361 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
362 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
363
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
364 /* Remove trailing zeros after the decimal point from a numeric string; also
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
365 remove the decimal point if all digits following it are zero. The numeric
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
366 string must end in '\0', and should not have any leading or trailing
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
367 whitespace. Assumes that the decimal point is '.'. */
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
368 Py_LOCAL_INLINE(void)
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
369 remove_trailing_zeros(char *buffer)
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
370 {
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
371 char *old_fraction_end, *new_fraction_end, *end, *p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
372
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
373 p = buffer;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
374 if (*p == '-' || *p == '+')
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
375 /* Skip leading sign, if present */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
376 ++p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
377 while (Py_ISDIGIT(*p))
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
378 ++p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
379
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
380 /* if there's no decimal point there's nothing to do */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
381 if (*p++ != '.')
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
382 return;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
383
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
384 /* scan any digits after the point */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
385 while (Py_ISDIGIT(*p))
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
386 ++p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
387 old_fraction_end = p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
388
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
389 /* scan up to ending '\0' */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
390 while (*p != '\0')
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
391 p++;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
392 /* +1 to make sure that we move the null byte as well */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
393 end = p+1;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
394
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
395 /* scan back from fraction_end, looking for removable zeros */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
396 p = old_fraction_end;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
397 while (*(p-1) == '0')
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
398 --p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
399 /* and remove point if we've got that far */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
400 if (*(p-1) == '.')
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
401 --p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
402 new_fraction_end = p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
403
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
404 memmove(new_fraction_end, old_fraction_end, end-old_fraction_end);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
405 }
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
406
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
407 /* Ensure that buffer has a decimal point in it. The decimal point will not
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
408 be in the current locale, it will always be '.'. Don't add a decimal point
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
409 if an exponent is present. Also, convert to exponential notation where
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
410 adding a '.0' would produce too many significant digits (see issue 5864).
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
411
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
412 Returns a pointer to the fixed buffer, or NULL on failure.
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
413 */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
414 Py_LOCAL_INLINE(char *)
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
415 ensure_decimal_point(char* buffer, size_t buf_size, int precision)
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
416 {
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
417 int digit_count, insert_count = 0, convert_to_exp = 0;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
418 char* chars_to_insert, *digits_start;
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
419
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
420 /* search for the first non-digit character */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
421 char *p = buffer;
48021
40db45bfc0f2 Fix issue 3411: default float format spec fails on negative numbers.
Eric Smith <eric@trueblade.com>
parents: 47815
diff changeset
422 if (*p == '-' || *p == '+')
40db45bfc0f2 Fix issue 3411: default float format spec fails on negative numbers.
Eric Smith <eric@trueblade.com>
parents: 47815
diff changeset
423 /* Skip leading sign, if present. I think this could only
40db45bfc0f2 Fix issue 3411: default float format spec fails on negative numbers.
Eric Smith <eric@trueblade.com>
parents: 47815
diff changeset
424 ever be '-', but it can't hurt to check for both. */
40db45bfc0f2 Fix issue 3411: default float format spec fails on negative numbers.
Eric Smith <eric@trueblade.com>
parents: 47815
diff changeset
425 ++p;
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
426 digits_start = p;
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
427 while (*p && Py_ISDIGIT(*p))
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
428 ++p;
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
429 digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int);
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
430
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
431 if (*p == '.') {
53539
4bdd847b57c2 Issue #5793: rationalize isdigit / isalpha / tolower, etc. Will port to py3k. Should fix Windows buildbot errors.
Eric Smith <eric@trueblade.com>
parents: 53477
diff changeset
432 if (Py_ISDIGIT(*(p+1))) {
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
433 /* Nothing to do, we already have a decimal
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
434 point and a digit after it */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
435 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
436 else {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
437 /* We have a decimal point, but no following
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
438 digit. Insert a zero after the decimal. */
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
439 /* can't ever get here via PyOS_double_to_string */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
440 assert(precision == -1);
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
441 ++p;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
442 chars_to_insert = "0";
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
443 insert_count = 1;
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
444 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
445 }
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
446 else if (!(*p == 'e' || *p == 'E')) {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
447 /* Don't add ".0" if we have an exponent. */
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
448 if (digit_count == precision) {
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
449 /* issue 5864: don't add a trailing .0 in the case
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
450 where the '%g'-formatted result already has as many
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
451 significant digits as were requested. Switch to
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
452 exponential notation instead. */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
453 convert_to_exp = 1;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
454 /* no exponent, no point, and we shouldn't land here
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
455 for infs and nans, so we must be at the end of the
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
456 string. */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
457 assert(*p == '\0');
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
458 }
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
459 else {
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
460 assert(precision == -1 || digit_count < precision);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
461 chars_to_insert = ".0";
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
462 insert_count = 2;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
463 }
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
464 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
465 if (insert_count) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
466 size_t buf_len = strlen(buffer);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
467 if (buf_len + insert_count + 1 >= buf_size) {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
468 /* If there is not enough room in the buffer
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
469 for the additional text, just skip it. It's
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
470 not worth generating an error over. */
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
471 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
472 else {
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
473 memmove(p + insert_count, p,
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
474 buffer + strlen(buffer) - p + 1);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
475 memcpy(p, chars_to_insert, insert_count);
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
476 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
477 }
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
478 if (convert_to_exp) {
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
479 int written;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
480 size_t buf_avail;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
481 p = digits_start;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
482 /* insert decimal point */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
483 assert(digit_count >= 1);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
484 memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
485 p[1] = '.';
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
486 p += digit_count+1;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
487 assert(p <= buf_size+buffer);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
488 buf_avail = buf_size+buffer-p;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
489 if (buf_avail == 0)
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
490 return NULL;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
491 /* Add exponent. It's okay to use lower case 'e': we only
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
492 arrive here as a result of using the empty format code or
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
493 repr/str builtins and those never want an upper case 'E' */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
494 written = PyOS_snprintf(p, buf_avail, "e%+.02d", digit_count-1);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
495 if (!(0 <= written &&
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
496 written < Py_SAFE_DOWNCAST(buf_avail, size_t, int)))
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
497 /* output truncated, or something else bad happened */
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
498 return NULL;
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
499 remove_trailing_zeros(buffer);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
500 }
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
501 return buffer;
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
502 }
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
503
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
504 /* see FORMATBUFLEN in unicodeobject.c */
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
505 #define FLOAT_FORMATBUFLEN 120
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
506
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
507 /**
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
508 * _PyOS_ascii_formatd:
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
509 * @buffer: A buffer to place the resulting string in
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
510 * @buf_size: The length of the buffer.
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
511 * @format: The printf()-style format to use for the
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
512 * code to use for converting.
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
513 * @d: The #gdouble to convert
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
514 *
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
515 * Converts a #gdouble to a string, using the '.' as
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
516 * decimal point. To format the number you pass in
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
517 * a printf()-style format string. Allowed conversion
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
518 * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'.
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
519 *
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
520 * 'Z' is the same as 'g', except it always has a decimal and
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
521 * at least one digit after the decimal.
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
522 *
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
523 * Return value: The pointer to the buffer with the converted string.
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
524 * On failure returns NULL but does not set any Python exception.
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
525 **/
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
526 /* DEPRECATED, will be deleted in 2.8 and 3.2 */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
527 PyAPI_FUNC(char *)
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
528 PyOS_ascii_formatd(char *buffer,
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
529 size_t buf_size,
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
530 const char *format,
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
531 double d)
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
532 {
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
533 char format_char;
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
534 size_t format_len = strlen(format);
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
535
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
536 /* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
537 also with at least one character past the decimal. */
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
538 char tmp_format[FLOAT_FORMATBUFLEN];
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
539
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
540 if (PyErr_WarnEx(PyExc_DeprecationWarning,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
541 "PyOS_ascii_formatd is deprecated, "
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
542 "use PyOS_double_to_string instead", 1) < 0)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
543 return NULL;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
544
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
545 /* The last character in the format string must be the format char */
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
546 format_char = format[format_len - 1];
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
547
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
548 if (format[0] != '%')
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
549 return NULL;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
550
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
551 /* I'm not sure why this test is here. It's ensuring that the format
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
552 string after the first character doesn't have a single quote, a
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
553 lowercase l, or a percent. This is the reverse of the commented-out
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
554 test about 10 lines ago. */
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
555 if (strpbrk(format + 1, "'l%"))
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
556 return NULL;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
557
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
558 /* Also curious about this function is that it accepts format strings
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
559 like "%xg", which are invalid for floats. In general, the
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
560 interface to this function is not very good, but changing it is
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
561 difficult because it's a public API. */
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
562
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
563 if (!(format_char == 'e' || format_char == 'E' ||
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
564 format_char == 'f' || format_char == 'F' ||
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
565 format_char == 'g' || format_char == 'G' ||
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
566 format_char == 'Z'))
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
567 return NULL;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
568
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
569 /* Map 'Z' format_char to 'g', by copying the format string and
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
570 replacing the final char with a 'g' */
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
571 if (format_char == 'Z') {
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
572 if (format_len + 1 >= sizeof(tmp_format)) {
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
573 /* The format won't fit in our copy. Error out. In
45786
16732db00822 Reformated lines > 79 chars.
Eric Smith <eric@trueblade.com>
parents: 45785
diff changeset
574 practice, this will never happen and will be
16732db00822 Reformated lines > 79 chars.
Eric Smith <eric@trueblade.com>
parents: 45785
diff changeset
575 detected by returning NULL */
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
576 return NULL;
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
577 }
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
578 strcpy(tmp_format, format);
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
579 tmp_format[format_len - 1] = 'g';
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
580 format = tmp_format;
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
581 }
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
582
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
583
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
584 /* Have PyOS_snprintf do the hard work */
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
585 PyOS_snprintf(buffer, buf_size, format, d);
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
586
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
587 /* Do various fixups on the return string */
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
588
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
589 /* Get the current locale, and find the decimal point string.
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
590 Convert that string back to a dot. */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
591 change_decimal_from_locale_to_dot(buffer);
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
592
45403
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
593 /* If an exponent exists, ensure that the exponent is at least
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
594 MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
595 for the extra zeros. Also, if there are more than
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
596 MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
0ea236a71d77 Trim leading zeros from a floating point exponent, per C99. See issue 1600. As far as I know, this only affects Windows. Add float type 'n' to PyOS_ascii_formatd (see PEP 3101 for 'n' description).
Eric Smith <eric@trueblade.com>
parents: 44482
diff changeset
597 back to MIN_EXPONENT_DIGITS */
53477
bfb47bc1d051 Fix typo in function name
Mark Dickinson <dickinsm@gmail.com>
parents: 53470
diff changeset
598 ensure_minimum_exponent_length(buffer, buf_size);
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
599
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
600 /* If format_char is 'Z', make sure we have at least one character
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
601 after the decimal point (and make sure we have a decimal point);
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
602 also switch to exponential notation in some edge cases where the
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
603 extra character would produce more significant digits that we
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
604 really want. */
46600
37d645b01523 Issue 2526, float.__format__ 'n' specifier does not support thousands grouping.
Eric Smith <eric@trueblade.com>
parents: 45786
diff changeset
605 if (format_char == 'Z')
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
606 buffer = ensure_decimal_point(buffer, buf_size, -1);
45785
4d29127f3fa0 Issue 2264: empty float presentation type needs to have at least one digit past the decimal point.
Eric Smith <eric@trueblade.com>
parents: 45403
diff changeset
607
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
608 return buffer;
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
609 }
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
610
53618
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
611 /* Precisions used by repr() and str(), respectively.
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
612
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
613 The repr() precision (17 significant decimal digits) is the minimal number
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
614 that is guaranteed to have enough precision so that if the number is read
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
615 back in the exact same binary value is recreated. This is true for IEEE
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
616 floating point by design, and also happens to work for all other modern
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
617 hardware.
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
618
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
619 The str() precision (12 significant decimal digits) is chosen so that in
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
620 most cases, the rounding noise created by various operations is suppressed,
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
621 while giving plenty of precision for practical use.
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
622
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
623 */
4762394fc26c Remove format_float and use _PyOS_double_to_string instead.
Mark Dickinson <dickinsm@gmail.com>
parents: 53611
diff changeset
624
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
625 PyAPI_FUNC(void)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
626 _PyOS_double_to_string(char *buf, size_t buf_len, double val,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
627 char format_code, int precision,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
628 int flags, int *ptype)
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
629 {
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
630 char format[32];
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
631 int t;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
632 int upper = 0;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
633
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
634 if (buf_len < 1) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
635 assert(0);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
636 /* There's no way to signal this error. Just return. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
637 return;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
638 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
639 buf[0] = 0;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
640
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
641 /* Validate format_code, and map upper and lower case */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
642 switch (format_code) {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
643 case 'e': /* exponent */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
644 case 'f': /* fixed */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
645 case 'g': /* general */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
646 break;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
647 case 'E':
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
648 upper = 1;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
649 format_code = 'e';
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
650 break;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
651 case 'F':
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
652 upper = 1;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
653 format_code = 'f';
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
654 break;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
655 case 'G':
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
656 upper = 1;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
657 format_code = 'g';
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
658 break;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
659 case 'r': /* repr format */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
660 /* Supplied precision is unused, must be 0. */
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
661 if (precision != 0)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
662 return;
53802
1d8f24d40c2c Issue #5920: Changed format.__float__ and complex.__float__ to use a precision of 12 when using the empty presentation type. This more closely matches str()'s behavior and reduces surprises when adding alignment flags to an empty format string. Patch by Mark Dickinson.
Eric Smith <eric@trueblade.com>
parents: 53716
diff changeset
663 /* The repr() precision (17 significant decimal digits) is the
1d8f24d40c2c Issue #5920: Changed format.__float__ and complex.__float__ to use a precision of 12 when using the empty presentation type. This more closely matches str()'s behavior and reduces surprises when adding alignment flags to an empty format string. Patch by Mark Dickinson.
Eric Smith <eric@trueblade.com>
parents: 53716
diff changeset
664 minimal number that is guaranteed to have enough precision
1d8f24d40c2c Issue #5920: Changed format.__float__ and complex.__float__ to use a precision of 12 when using the empty presentation type. This more closely matches str()'s behavior and reduces surprises when adding alignment flags to an empty format string. Patch by Mark Dickinson.
Eric Smith <eric@trueblade.com>
parents: 53716
diff changeset
665 so that if the number is read back in the exact same binary
1d8f24d40c2c Issue #5920: Changed format.__float__ and complex.__float__ to use a precision of 12 when using the empty presentation type. This more closely matches str()'s behavior and reduces surprises when adding alignment flags to an empty format string. Patch by Mark Dickinson.
Eric Smith <eric@trueblade.com>
parents: 53716
diff changeset
666 value is recreated. This is true for IEEE floating point
1d8f24d40c2c Issue #5920: Changed format.__float__ and complex.__float__ to use a precision of 12 when using the empty presentation type. This more closely matches str()'s behavior and reduces surprises when adding alignment flags to an empty format string. Patch by Mark Dickinson.
Eric Smith <eric@trueblade.com>
parents: 53716
diff changeset
667 by design, and also happens to work for all other modern
1d8f24d40c2c Issue #5920: Changed format.__float__ and complex.__float__ to use a precision of 12 when using the empty presentation type. This more closely matches str()'s behavior and reduces surprises when adding alignment flags to an empty format string. Patch by Mark Dickinson.
Eric Smith <eric@trueblade.com>
parents: 53716
diff changeset
668 hardware. */
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
669 precision = 17;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
670 format_code = 'g';
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
671 break;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
672 default:
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
673 assert(0);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
674 return;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
675 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
676
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
677 /* Check for buf too small to fit "-inf". Other buffer too small
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
678 conditions are dealt with when converting or formatting finite
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
679 numbers. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
680 if (buf_len < 5) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
681 assert(0);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
682 return;
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
683 }
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
684
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
685 /* Handle nan and inf. */
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
686 if (Py_IS_NAN(val)) {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
687 strcpy(buf, "nan");
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
688 t = Py_DTST_NAN;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
689 } else if (Py_IS_INFINITY(val)) {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
690 if (copysign(1., val) == 1.)
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
691 strcpy(buf, "inf");
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
692 else
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
693 strcpy(buf, "-inf");
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
694 t = Py_DTST_INFINITE;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
695 } else {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
696 t = Py_DTST_FINITE;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
697
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
698 /* Build the format string. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
699 PyOS_snprintf(format, sizeof(format), "%%%s.%i%c",
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
700 (flags & Py_DTSF_ALT ? "#" : ""), precision,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
701 format_code);
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
702
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
703 /* Have PyOS_snprintf do the hard work. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
704 PyOS_snprintf(buf, buf_len, format, val);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
705
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
706 /* Do various fixups on the return string */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
707
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
708 /* Get the current locale, and find the decimal point string.
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
709 Convert that string back to a dot. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
710 change_decimal_from_locale_to_dot(buf);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
711
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
712 /* If an exponent exists, ensure that the exponent is at least
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
713 MIN_EXPONENT_DIGITS digits, providing the buffer is large
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
714 enough for the extra zeros. Also, if there are more than
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
715 MIN_EXPONENT_DIGITS, remove as many zeros as possible until
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
716 we get back to MIN_EXPONENT_DIGITS */
53477
bfb47bc1d051 Fix typo in function name
Mark Dickinson <dickinsm@gmail.com>
parents: 53470
diff changeset
717 ensure_minimum_exponent_length(buf, buf_len);
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
718
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
719 /* Possibly make sure we have at least one character after the
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
720 decimal point (and make sure we have a decimal point). */
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
721 if (flags & Py_DTSF_ADD_DOT_0)
53611
a3fcccee8957 Issue #5864: format(1234.5, '.4') gives misleading result
Mark Dickinson <dickinsm@gmail.com>
parents: 53555
diff changeset
722 buf = ensure_decimal_point(buf, buf_len, precision);
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
723 }
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
724
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
725 /* Add the sign if asked and the result isn't negative. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
726 if (flags & Py_DTSF_SIGN && buf[0] != '-')
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
727 ensure_sign(buf, buf_len);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
728
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
729 if (upper) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
730 /* Convert to upper case. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
731 char *p;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
732 for (p = buf; *p; p++)
53712
1f00bc1d115a Eliminate some locale-dependent calls to isspace and tolower.
Mark Dickinson <dickinsm@gmail.com>
parents: 53618
diff changeset
733 *p = Py_TOUPPER(*p);
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
734 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
735
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
736 if (ptype)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
737 *ptype = t;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
738 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
739
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
740
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
741 PyAPI_FUNC(char *) PyOS_double_to_string(double val,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
742 char format_code,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
743 int precision,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
744 int flags,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
745 int *ptype)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
746 {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
747 char buf[128];
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
748 Py_ssize_t len;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
749 char *result;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
750
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
751 _PyOS_double_to_string(buf, sizeof(buf), val, format_code, precision,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
752 flags, ptype);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
753 len = strlen(buf);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
754 if (len == 0) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
755 PyErr_BadInternalCall();
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
756 return NULL;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
757 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
758
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
759 /* Add 1 for the trailing 0 byte. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
760 result = PyMem_Malloc(len + 1);
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
761 if (result == NULL) {
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
762 PyErr_NoMemory();
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
763 return NULL;
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
764 }
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
765 strcpy(result, buf);
53312
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
766
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
767 return result;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
768 }