Mercurial > cpython-lru_cache-weakref
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 |
| 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 | 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 | 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 } |
