annotate Python/pystrtod.c @ 53716:4f867f1494d5 legacy-trunk

Don't use PyOS_strnicmp for NaN and Inf detection: it's locale-aware.
author Mark Dickinson <dickinsm@gmail.com>
date Sun, 03 May 2009 22:33:34 +0000
parents 1f00bc1d115a
children 1d8f24d40c2c
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;
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
663 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
664 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
665 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
666 case 's': /* str 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
667 /* Supplied precision is unused, must be 0. */
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
668 if (precision != 0)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
669 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
670 precision = 12;
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 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
672 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
673 default:
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
674 assert(0);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
675 return;
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
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
678 /* 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
679 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
680 numbers. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
681 if (buf_len < 5) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
682 assert(0);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
683 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
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
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 /* 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
687 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
688 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
689 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
690 } 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
691 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
692 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
693 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
694 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
695 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
696 } 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
697 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
698
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
699 /* Build the format string. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
700 PyOS_snprintf(format, sizeof(format), "%%%s.%i%c",
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
701 (flags & Py_DTSF_ALT ? "#" : ""), precision,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
702 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
703
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
704 /* Have PyOS_snprintf do the hard work. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
705 PyOS_snprintf(buf, buf_len, format, val);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
706
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
707 /* Do various fixups on the return string */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
708
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
709 /* 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
710 Convert that string back to a dot. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
711 change_decimal_from_locale_to_dot(buf);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
712
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
713 /* 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
714 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
715 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
716 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
717 we get back to MIN_EXPONENT_DIGITS */
53477
bfb47bc1d051 Fix typo in function name
Mark Dickinson <dickinsm@gmail.com>
parents: 53470
diff changeset
718 ensure_minimum_exponent_length(buf, buf_len);
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
719
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
720 /* 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
721 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
722 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
723 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
724 }
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
725
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
726 /* 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
727 if (flags & Py_DTSF_SIGN && buf[0] != '-')
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
728 ensure_sign(buf, buf_len);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
729
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
730 if (upper) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
731 /* Convert to upper case. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
732 char *p;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
733 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
734 *p = Py_TOUPPER(*p);
53442
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
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
737 if (ptype)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
738 *ptype = t;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
739 }
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
740
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
741
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
742 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
743 char format_code,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
744 int precision,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
745 int flags,
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
746 int *ptype)
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
747 {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
748 char buf[128];
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
749 Py_ssize_t len;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
750 char *result;
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
751
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
752 _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
753 flags, ptype);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
754 len = strlen(buf);
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
755 if (len == 0) {
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
756 PyErr_BadInternalCall();
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
757 return NULL;
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
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
760 /* Add 1 for the trailing 0 byte. */
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
761 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
762 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
763 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
764 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
765 }
53442
6947bc3dd433 Issue #5835, deprecate PyOS_ascii_formatd.
Eric Smith <eric@trueblade.com>
parents: 53338
diff changeset
766 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
767
c5e0d9beebf9 Backport of some of the work in r71665 to trunk. This reworks much of
Eric Smith <eric@trueblade.com>
parents: 48021
diff changeset
768 return result;
32305
13656d58d450 Patch #774665: Make Python LC_NUMERIC agnostic.
Martin v. Löwis <martin@v.loewis.de>
parents:
diff changeset
769 }