summaryrefslogtreecommitdiffstats
path: root/Python/fileutils.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2018-01-15 22:23:47 (GMT)
committerGitHub <noreply@github.com>2018-01-15 22:23:47 (GMT)
commit5f959c4f9eca404b8bc4bc6348fed27c4b907b89 (patch)
tree29b215542b7705687eb5644a0640896e587646b7 /Python/fileutils.c
parentfb8569e36f2629654d5bc9c7ba05978edce408f4 (diff)
downloadcpython-5f959c4f9eca404b8bc4bc6348fed27c4b907b89.zip
cpython-5f959c4f9eca404b8bc4bc6348fed27c4b907b89.tar.gz
cpython-5f959c4f9eca404b8bc4bc6348fed27c4b907b89.tar.bz2
[3.6] bpo-31900: Fix localeconv() encoding for LC_NUMERIC (#4174) (#5192)
* Add _Py_GetLocaleconvNumeric() function: decode decimal_point and thousands_sep fields of localeconv() from the LC_NUMERIC encoding, rather than decoding from the LC_CTYPE encoding. * Modify locale.localeconv() and "n" formatter of str.format() (for int, float and complex to use _Py_GetLocaleconvNumeric() internally. (cherry picked from commit cb064fc2321ce8673fe365e9ef60445a27657f54)
Diffstat (limited to 'Python/fileutils.c')
-rw-r--r--Python/fileutils.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 97505e5..14dd81b 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -1597,3 +1597,80 @@ error:
return -1;
}
#endif
+
+
+int
+_Py_GetLocaleconvNumeric(PyObject **decimal_point, PyObject **thousands_sep,
+ const char **grouping)
+{
+ int res = -1;
+
+ struct lconv *lc = localeconv();
+
+ int change_locale = 0;
+ if (decimal_point != NULL &&
+ (strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127))
+ {
+ change_locale = 1;
+ }
+ if (thousands_sep != NULL &&
+ (strlen(lc->thousands_sep) > 1 || ((unsigned char)lc->thousands_sep[0]) > 127))
+ {
+ change_locale = 1;
+ }
+
+ /* Keep a copy of the LC_CTYPE locale */
+ char *oldloc = NULL, *loc = NULL;
+ if (change_locale) {
+ oldloc = setlocale(LC_CTYPE, NULL);
+ if (!oldloc) {
+ PyErr_SetString(PyExc_RuntimeWarning, "faild to get LC_CTYPE locale");
+ return -1;
+ }
+
+ oldloc = _PyMem_Strdup(oldloc);
+ if (!oldloc) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ loc = setlocale(LC_NUMERIC, NULL);
+ if (loc != NULL && strcmp(loc, oldloc) == 0) {
+ loc = NULL;
+ }
+
+ if (loc != NULL) {
+ /* Only set the locale temporarilty the LC_CTYPE locale
+ if LC_NUMERIC locale is different than LC_CTYPE locale and
+ decimal_point and/or thousands_sep are non-ASCII or longer than
+ 1 byte */
+ setlocale(LC_CTYPE, loc);
+ }
+ }
+
+ if (decimal_point != NULL) {
+ *decimal_point = PyUnicode_DecodeLocale(lc->decimal_point, NULL);
+ if (*decimal_point == NULL) {
+ goto error;
+ }
+ }
+ if (thousands_sep != NULL) {
+ *thousands_sep = PyUnicode_DecodeLocale(lc->thousands_sep, NULL);
+ if (*thousands_sep == NULL) {
+ goto error;
+ }
+ }
+
+ if (grouping != NULL) {
+ *grouping = lc->grouping;
+ }
+
+ res = 0;
+
+error:
+ if (loc != NULL) {
+ setlocale(LC_CTYPE, oldloc);
+ }
+ PyMem_Free(oldloc);
+ return res;
+}