diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 6d580f48212..465d87b6f26 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -1936,32 +1936,20 @@ PyAPI_FUNC(PyObject *) _PyUnicode_XStrip( ); #endif -/* Using the current locale, insert the thousands grouping - into the string pointed to by buffer. For the argument descriptions, - see Objects/stringlib/localeutil.h */ - -#ifndef Py_LIMITED_API -PyAPI_FUNC(Py_ssize_t) _PyUnicode_InsertThousandsGroupingLocale(Py_UNICODE *buffer, - Py_ssize_t n_buffer, - Py_UNICODE *digits, - Py_ssize_t n_digits, - Py_ssize_t min_width); -#endif - /* Using explicit passed-in values, insert the thousands grouping into the string pointed to by buffer. For the argument descriptions, see Objects/stringlib/localeutil.h */ #ifndef Py_LIMITED_API PyAPI_FUNC(Py_ssize_t) _PyUnicode_InsertThousandsGrouping( PyObject *unicode, - int kind, - void *buffer, + Py_ssize_t index, Py_ssize_t n_buffer, void *digits, Py_ssize_t n_digits, Py_ssize_t min_width, const char *grouping, - const char *thousands_sep); + PyObject *thousands_sep, + Py_UCS4 *maxchar); #endif /* === Characters Type APIs =============================================== */ diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index 7345b30c054..70e748f2c34 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -1,4 +1,5 @@ from test.support import verbose, TestFailed +import locale import sys import test.support as support import unittest @@ -282,6 +283,20 @@ class FormatTest(unittest.TestCase): self.assertEqual(format(1+2j, "\u2007^8"), "\u2007(1+2j)\u2007") self.assertEqual(format(0j, "\u2007^4"), "\u20070j\u2007") + def test_locale(self): + try: + oldloc = locale.setlocale(locale.LC_ALL, '') + except locale.Error as err: + self.skipTest("Cannot set locale: {}".format(err)) + try: + sep = locale.localeconv()['thousands_sep'] + text = format(123456789, "n") + self.assertIn(sep, text) + self.assertEqual(text.replace(sep, ''), '123456789') + finally: + locale.setlocale(locale.LC_ALL, oldloc) + + def test_main(): support.run_unittest(FormatTest) diff --git a/Objects/stringlib/asciilib.h b/Objects/stringlib/asciilib.h index ae68e3c89f0..fa481c08efb 100644 --- a/Objects/stringlib/asciilib.h +++ b/Objects/stringlib/asciilib.h @@ -21,12 +21,9 @@ #define STRINGLIB_RESIZE not_supported #define STRINGLIB_CHECK PyUnicode_Check #define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact -#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping -#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale #define STRINGLIB_TOSTR PyObject_Str #define STRINGLIB_TOASCII PyObject_ASCII #define _Py_InsertThousandsGrouping _PyUnicode_ascii_InsertThousandsGrouping -#define _Py_InsertThousandsGroupingLocale _PyUnicode_ascii_InsertThousandsGroupingLocale diff --git a/Objects/stringlib/localeutil.h b/Objects/stringlib/localeutil.h index ddce69d4558..28c87c8f832 100644 --- a/Objects/stringlib/localeutil.h +++ b/Objects/stringlib/localeutil.h @@ -2,8 +2,9 @@ #include -#define MAX(x, y) ((x) < (y) ? (y) : (x)) -#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#ifndef STRINGLIB_IS_UNICODE +# error "localeutil is specific to Unicode" +#endif typedef struct { const char *grouping; @@ -46,7 +47,7 @@ STRINGLIB(GroupGenerator_next)(STRINGLIB(GroupGenerator) *self) are optional, depending on when we're called. */ static void STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end, - Py_ssize_t n_chars, Py_ssize_t n_zeros, const char* thousands_sep, + Py_ssize_t n_chars, Py_ssize_t n_zeros, STRINGLIB_CHAR* thousands_sep, Py_ssize_t thousands_sep_len) { Py_ssize_t i; @@ -55,15 +56,8 @@ STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end, *buffer_end -= thousands_sep_len; /* Copy the thousands_sep chars into the buffer. */ -#if STRINGLIB_IS_UNICODE - /* Convert from the char's of the thousands_sep from - the locale into unicode. */ - for (i = 0; i < thousands_sep_len; ++i) - (*buffer_end)[i] = thousands_sep[i]; -#else - /* No conversion, just memcpy the thousands_sep. */ - memcpy(*buffer_end, thousands_sep, thousands_sep_len); -#endif + memcpy(*buffer_end, thousands_sep, + thousands_sep_len * STRINGLIB_SIZEOF_CHAR); } *buffer_end -= n_chars; @@ -76,7 +70,7 @@ STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end, } /** - * _Py_InsertThousandsGrouping: + * InsertThousandsGrouping: * @buffer: A pointer to the start of a string. * @n_buffer: Number of characters in @buffer. * @digits: A pointer to the digits we're reading from. If count @@ -106,13 +100,15 @@ STRINGLIB(fill)(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end, _insert_thousands_sep(). **/ Py_ssize_t -_Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer, - Py_ssize_t n_buffer, - STRINGLIB_CHAR *digits, - Py_ssize_t n_digits, - Py_ssize_t min_width, - const char *grouping, - const char *thousands_sep) +STRINGLIB(InsertThousandsGrouping)( + STRINGLIB_CHAR *buffer, + Py_ssize_t n_buffer, + STRINGLIB_CHAR *digits, + Py_ssize_t n_digits, + Py_ssize_t min_width, + const char *grouping, + STRINGLIB_CHAR *thousands_sep, + Py_ssize_t thousands_sep_len) { Py_ssize_t count = 0; Py_ssize_t n_zeros; @@ -124,7 +120,6 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer, STRINGLIB_CHAR *digits_end = NULL; Py_ssize_t l; Py_ssize_t n_chars; - Py_ssize_t thousands_sep_len = strlen(thousands_sep); Py_ssize_t remaining = n_digits; /* Number of chars remaining to be looked at */ /* A generator that returns all of the grouping widths, until it @@ -138,9 +133,9 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer, } while ((l = STRINGLIB(GroupGenerator_next)(&groupgen)) > 0) { - l = MIN(l, MAX(MAX(remaining, min_width), 1)); - n_zeros = MAX(0, l - remaining); - n_chars = MAX(0, MIN(remaining, l)); + l = Py_MIN(l, Py_MAX(Py_MAX(remaining, min_width), 1)); + n_zeros = Py_MAX(0, l - remaining); + n_chars = Py_MAX(0, Py_MIN(remaining, l)); /* Use n_zero zero's and n_chars chars */ @@ -168,9 +163,9 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer, if (!loop_broken) { /* We left the loop without using a break statement. */ - l = MAX(MAX(remaining, min_width), 1); - n_zeros = MAX(0, l - remaining); - n_chars = MAX(0, MIN(remaining, l)); + l = Py_MAX(Py_MAX(remaining, min_width), 1); + n_zeros = Py_MAX(0, l - remaining); + n_chars = Py_MAX(0, Py_MIN(remaining, l)); /* Use n_zero zero's and n_chars chars */ count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars; @@ -183,25 +178,3 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer, return count; } -/** - * _Py_InsertThousandsGroupingLocale: - * @buffer: A pointer to the start of a string. - * @n_digits: The number of digits in the string, in which we want - * to put the grouping chars. - * - * Reads thee current locale and calls _Py_InsertThousandsGrouping(). - **/ -Py_ssize_t -_Py_InsertThousandsGroupingLocale(STRINGLIB_CHAR *buffer, - Py_ssize_t n_buffer, - STRINGLIB_CHAR *digits, - Py_ssize_t n_digits, - Py_ssize_t min_width) -{ - struct lconv *locale_data = localeconv(); - const char *grouping = locale_data->grouping; - const char *thousands_sep = locale_data->thousands_sep; - - return _Py_InsertThousandsGrouping(buffer, n_buffer, digits, n_digits, - min_width, grouping, thousands_sep); -} diff --git a/Objects/stringlib/stringdefs.h b/Objects/stringlib/stringdefs.h index fec9f189a1f..7bb91a7a5b7 100644 --- a/Objects/stringlib/stringdefs.h +++ b/Objects/stringlib/stringdefs.h @@ -25,7 +25,5 @@ #define STRINGLIB_CHECK PyBytes_Check #define STRINGLIB_CHECK_EXACT PyBytes_CheckExact #define STRINGLIB_TOSTR PyObject_Str -#define STRINGLIB_GROUPING _PyBytes_InsertThousandsGrouping -#define STRINGLIB_GROUPING_LOCALE _PyBytes_InsertThousandsGroupingLocale #define STRINGLIB_TOASCII PyObject_Repr #endif /* !STRINGLIB_STRINGDEFS_H */ diff --git a/Objects/stringlib/ucs1lib.h b/Objects/stringlib/ucs1lib.h index 42b9d91c539..ed2b0a3023f 100644 --- a/Objects/stringlib/ucs1lib.h +++ b/Objects/stringlib/ucs1lib.h @@ -21,13 +21,10 @@ #define STRINGLIB_RESIZE not_supported #define STRINGLIB_CHECK PyUnicode_Check #define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact -#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping -#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale #define STRINGLIB_TOSTR PyObject_Str #define STRINGLIB_TOASCII PyObject_ASCII #define _Py_InsertThousandsGrouping _PyUnicode_ucs1_InsertThousandsGrouping -#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs1_InsertThousandsGroupingLocale diff --git a/Objects/stringlib/ucs2lib.h b/Objects/stringlib/ucs2lib.h index 611e741ca3f..a5089058871 100644 --- a/Objects/stringlib/ucs2lib.h +++ b/Objects/stringlib/ucs2lib.h @@ -21,12 +21,9 @@ #define STRINGLIB_RESIZE not_supported #define STRINGLIB_CHECK PyUnicode_Check #define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact -#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping -#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale #define STRINGLIB_TOSTR PyObject_Str #define STRINGLIB_TOASCII PyObject_ASCII #define _Py_InsertThousandsGrouping _PyUnicode_ucs2_InsertThousandsGrouping -#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs2_InsertThousandsGroupingLocale diff --git a/Objects/stringlib/ucs4lib.h b/Objects/stringlib/ucs4lib.h index 330b29257bc..eda0feb7d42 100644 --- a/Objects/stringlib/ucs4lib.h +++ b/Objects/stringlib/ucs4lib.h @@ -21,12 +21,9 @@ #define STRINGLIB_RESIZE not_supported #define STRINGLIB_CHECK PyUnicode_Check #define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact -#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping -#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale #define STRINGLIB_TOSTR PyObject_Str #define STRINGLIB_TOASCII PyObject_ASCII #define _Py_InsertThousandsGrouping _PyUnicode_ucs4_InsertThousandsGrouping -#define _Py_InsertThousandsGroupingLocale _PyUnicode_ucs4_InsertThousandsGroupingLocale diff --git a/Objects/stringlib/undef.h b/Objects/stringlib/undef.h index fd87e56d360..9310204178e 100644 --- a/Objects/stringlib/undef.h +++ b/Objects/stringlib/undef.h @@ -7,5 +7,5 @@ #undef STRINGLIB_NEW #undef STRINGLIB_RESIZE #undef _Py_InsertThousandsGrouping -#undef _Py_InsertThousandsGroupingLocale +#undef STRINGLIB_IS_UNICODE diff --git a/Objects/stringlib/unicodedefs.h b/Objects/stringlib/unicodedefs.h index 3ccc57ed9b9..f16f21e60c3 100644 --- a/Objects/stringlib/unicodedefs.h +++ b/Objects/stringlib/unicodedefs.h @@ -24,8 +24,6 @@ #define STRINGLIB_RESIZE PyUnicode_Resize #define STRINGLIB_CHECK PyUnicode_Check #define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact -#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping -#define STRINGLIB_GROUPING_LOCALE _PyUnicode_InsertThousandsGroupingLocale #if PY_VERSION_HEX < 0x03000000 #define STRINGLIB_TOSTR PyObject_Unicode diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 01748be3e8f..2841b07e8ae 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9151,34 +9151,75 @@ any_find_slice(int direction, PyObject* s1, PyObject* s2, } Py_ssize_t -_PyUnicode_InsertThousandsGrouping(PyObject *unicode, int kind, void *data, - Py_ssize_t n_buffer, - void *digits, Py_ssize_t n_digits, - Py_ssize_t min_width, - const char *grouping, - const char *thousands_sep) +_PyUnicode_InsertThousandsGrouping( + PyObject *unicode, Py_ssize_t index, + Py_ssize_t n_buffer, + void *digits, Py_ssize_t n_digits, + Py_ssize_t min_width, + const char *grouping, PyObject *thousands_sep, + Py_UCS4 *maxchar) { + unsigned int kind, thousands_sep_kind; + void *data, *thousands_sep_data; + Py_ssize_t thousands_sep_len; + Py_ssize_t len; + + if (unicode != NULL) { + kind = PyUnicode_KIND(unicode); + data = PyUnicode_DATA(unicode) + index * kind; + } + else { + kind = PyUnicode_1BYTE_KIND; + data = NULL; + } + thousands_sep_kind = PyUnicode_KIND(thousands_sep); + thousands_sep_data = PyUnicode_DATA(thousands_sep); + thousands_sep_len = PyUnicode_GET_LENGTH(thousands_sep); + if (unicode != NULL && thousands_sep_kind != kind) { + thousands_sep_data = _PyUnicode_AsKind(thousands_sep, kind); + if (!thousands_sep_data) + return -1; + } + switch (kind) { case PyUnicode_1BYTE_KIND: if (unicode != NULL && PyUnicode_IS_ASCII(unicode)) - return _PyUnicode_ascii_InsertThousandsGrouping( + len = asciilib_InsertThousandsGrouping( (Py_UCS1*)data, n_buffer, (Py_UCS1*)digits, n_digits, - min_width, grouping, thousands_sep); + min_width, grouping, + thousands_sep_data, thousands_sep_len); else - return _PyUnicode_ucs1_InsertThousandsGrouping( + len = ucs1lib_InsertThousandsGrouping( (Py_UCS1*)data, n_buffer, (Py_UCS1*)digits, n_digits, - min_width, grouping, thousands_sep); + min_width, grouping, + thousands_sep_data, thousands_sep_len); + break; case PyUnicode_2BYTE_KIND: - return _PyUnicode_ucs2_InsertThousandsGrouping( + len = ucs2lib_InsertThousandsGrouping( (Py_UCS2*)data, n_buffer, (Py_UCS2*)digits, n_digits, - min_width, grouping, thousands_sep); + min_width, grouping, + thousands_sep_data, thousands_sep_len); + break; case PyUnicode_4BYTE_KIND: - return _PyUnicode_ucs4_InsertThousandsGrouping( + len = ucs4lib_InsertThousandsGrouping( (Py_UCS4*)data, n_buffer, (Py_UCS4*)digits, n_digits, - min_width, grouping, thousands_sep); + min_width, grouping, + thousands_sep_data, thousands_sep_len); + break; + default: + assert(0); + return -1; } - assert(0); - return -1; + if (unicode != NULL && thousands_sep_kind != kind) + PyMem_Free(thousands_sep_data); + if (unicode == NULL) { + *maxchar = 127; + if (len != n_digits) { + *maxchar = Py_MAX(*maxchar, + PyUnicode_MAX_CHAR_VALUE(thousands_sep)); + } + } + return len; } diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index ed716a5b971..94f8047e18c 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -346,11 +346,13 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars, before and including the decimal. Note that locales only support 8-bit chars, not unicode. */ typedef struct { - char *decimal_point; - char *thousands_sep; - char *grouping; + PyObject *decimal_point; + PyObject *thousands_sep; + const char *grouping; } LocaleInfo; +#define STATIC_LOCALE_INFO_INIT {0, 0, 0} + /* describes the layout for an integer, see the comment in calc_number_widths() for details */ typedef struct { @@ -415,7 +417,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, Py_UCS4 sign_char, PyObject *number, Py_ssize_t n_start, Py_ssize_t n_end, Py_ssize_t n_remainder, int has_decimal, const LocaleInfo *locale, - const InternalFormatSpec *format) + const InternalFormatSpec *format, Py_UCS4 *maxchar) { Py_ssize_t n_non_digit_non_padding; Py_ssize_t n_padding; @@ -423,7 +425,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, spec->n_digits = n_end - n_start - n_remainder - (has_decimal?1:0); spec->n_lpadding = 0; spec->n_prefix = n_prefix; - spec->n_decimal = has_decimal ? strlen(locale->decimal_point) : 0; + spec->n_decimal = has_decimal ? PyUnicode_GET_LENGTH(locale->decimal_point) : 0; spec->n_remainder = n_remainder; spec->n_spadding = 0; spec->n_rpadding = 0; @@ -484,11 +486,15 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, to special case it because the grouping code always wants to have at least one character. */ spec->n_grouped_digits = 0; - else + else { + Py_UCS4 grouping_maxchar; spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping( - NULL, PyUnicode_1BYTE_KIND, NULL, 0, NULL, + NULL, 0, + 0, NULL, spec->n_digits, spec->n_min_width, - locale->grouping, locale->thousands_sep); + locale->grouping, locale->thousands_sep, &grouping_maxchar); + *maxchar = Py_MAX(*maxchar, grouping_maxchar); + } /* Given the desired width and the total of digit and non-digit space we consume, see if we need any padding. format->width can @@ -519,6 +525,10 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, break; } } + + if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding) + *maxchar = Py_MAX(*maxchar, format->fill_char); + return spec->n_lpadding + spec->n_sign + spec->n_prefix + spec->n_spadding + spec->n_grouped_digits + spec->n_decimal + spec->n_remainder + spec->n_rpadding; @@ -587,12 +597,11 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, r = #endif _PyUnicode_InsertThousandsGrouping( - out, kind, - (char*)data + kind * pos, + out, pos, spec->n_grouped_digits, pdigits + kind * d_pos, spec->n_digits, spec->n_min_width, - locale->grouping, locale->thousands_sep); + locale->grouping, locale->thousands_sep, NULL); #ifndef NDEBUG assert(r == spec->n_grouped_digits); #endif @@ -615,10 +624,8 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, pos += spec->n_grouped_digits; if (spec->n_decimal) { - Py_ssize_t t; - for (t = 0; t < spec->n_decimal; ++t) - PyUnicode_WRITE(kind, data, pos + t, - locale->decimal_point[t]); + if (PyUnicode_CopyCharacters(out, pos, locale->decimal_point, 0, spec->n_decimal) < 0) + return -1; pos += spec->n_decimal; d_pos += 1; } @@ -643,32 +650,60 @@ static char no_grouping[1] = {CHAR_MAX}; grouping description, either for the current locale if type is LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or none if LT_NO_LOCALE. */ -static void +static int get_locale_info(int type, LocaleInfo *locale_info) { switch (type) { case LT_CURRENT_LOCALE: { struct lconv *locale_data = localeconv(); - locale_info->decimal_point = locale_data->decimal_point; - locale_info->thousands_sep = locale_data->thousands_sep; + locale_info->decimal_point = PyUnicode_DecodeLocale( + locale_data->decimal_point, + NULL); + if (locale_info->decimal_point == NULL) + return -1; + locale_info->thousands_sep = PyUnicode_DecodeLocale( + locale_data->thousands_sep, + NULL); + if (locale_info->thousands_sep == NULL) { + Py_DECREF(locale_info->decimal_point); + return -1; + } locale_info->grouping = locale_data->grouping; break; } case LT_DEFAULT_LOCALE: - locale_info->decimal_point = "."; - locale_info->thousands_sep = ","; + locale_info->decimal_point = PyUnicode_FromOrdinal('.'); + locale_info->thousands_sep = PyUnicode_FromOrdinal(','); + if (!locale_info->decimal_point || !locale_info->thousands_sep) { + Py_XDECREF(locale_info->decimal_point); + Py_XDECREF(locale_info->thousands_sep); + return -1; + } locale_info->grouping = "\3"; /* Group every 3 characters. The (implicit) trailing 0 means repeat infinitely. */ break; case LT_NO_LOCALE: - locale_info->decimal_point = "."; - locale_info->thousands_sep = ""; + locale_info->decimal_point = PyUnicode_FromOrdinal('.'); + locale_info->thousands_sep = PyUnicode_New(0, 0); + if (!locale_info->decimal_point || !locale_info->thousands_sep) { + Py_XDECREF(locale_info->decimal_point); + Py_XDECREF(locale_info->thousands_sep); + return -1; + } locale_info->grouping = no_grouping; break; default: assert(0); } + return 0; +} + +static void +free_locale_info(LocaleInfo *locale_info) +{ + Py_XDECREF(locale_info->decimal_point); + Py_XDECREF(locale_info->thousands_sep); } /************************************************************************/ @@ -769,7 +804,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ - LocaleInfo locale; + LocaleInfo locale = STATIC_LOCALE_INFO_INIT; /* no precision allowed on integers */ if (format->precision != -1) { @@ -868,18 +903,17 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, } /* Determine the grouping, separator, and decimal point, if any. */ - get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : - (format->thousands_separators ? - LT_DEFAULT_LOCALE : - LT_NO_LOCALE), - &locale); + if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale) == -1) + goto done; /* Calculate how much memory we'll need. */ n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars, - inumeric_chars + n_digits, n_remainder, 0, &locale, format); - - if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding) - maxchar = Py_MAX(maxchar, format->fill_char); + inumeric_chars + n_digits, n_remainder, 0, + &locale, format, &maxchar); /* Allocate the memory. */ result = PyUnicode_New(n_total, maxchar); @@ -897,6 +931,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, done: Py_XDECREF(tmp); + free_locale_info(&locale); assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -938,7 +973,7 @@ format_float_internal(PyObject *value, /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ - LocaleInfo locale; + LocaleInfo locale = STATIC_LOCALE_INFO_INIT; if (format->alternate) flags |= Py_DTSF_ALT; @@ -1009,19 +1044,17 @@ format_float_internal(PyObject *value, parse_number(unicode_tmp, index, index + n_digits, &n_remainder, &has_decimal); /* Determine the grouping, separator, and decimal point, if any. */ - get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : - (format->thousands_separators ? - LT_DEFAULT_LOCALE : - LT_NO_LOCALE), - &locale); + if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale) == -1) + goto done; /* Calculate how much memory we'll need. */ n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, index + n_digits, n_remainder, has_decimal, - &locale, format); - - if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding) - maxchar = Py_MAX(maxchar, format->fill_char); + &locale, format, &maxchar); /* Allocate the memory. */ result = PyUnicode_New(n_total, maxchar); @@ -1040,6 +1073,7 @@ format_float_internal(PyObject *value, done: PyMem_Free(buf); Py_DECREF(unicode_tmp); + free_locale_info(&locale); assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -1094,7 +1128,7 @@ format_complex_internal(PyObject *value, /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ - LocaleInfo locale; + LocaleInfo locale = STATIC_LOCALE_INFO_INIT; /* Zero padding is not allowed. */ if (format->fill_char == '0') { @@ -1190,11 +1224,12 @@ format_complex_internal(PyObject *value, &n_im_remainder, &im_has_decimal); /* Determine the grouping, separator, and decimal point, if any. */ - get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : - (format->thousands_separators ? - LT_DEFAULT_LOCALE : - LT_NO_LOCALE), - &locale); + if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale) == -1) + goto done; /* Turn off any padding. We'll do it later after we've composed the numbers without padding. */ @@ -1205,7 +1240,8 @@ format_complex_internal(PyObject *value, /* Calculate how much memory we'll need. */ n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, re_unicode_tmp, i_re, i_re + n_re_digits, n_re_remainder, - re_has_decimal, &locale, &tmp_format); + re_has_decimal, &locale, &tmp_format, + &maxchar); /* Same formatting, but always include a sign, unless the real part is * going to be omitted, in which case we use whatever sign convention was @@ -1214,7 +1250,8 @@ format_complex_internal(PyObject *value, tmp_format.sign = '+'; n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, im_unicode_tmp, i_im, i_im + n_im_digits, n_im_remainder, - im_has_decimal, &locale, &tmp_format); + im_has_decimal, &locale, &tmp_format, + &maxchar); if (skip_re) n_re_total = 0; @@ -1223,9 +1260,7 @@ format_complex_internal(PyObject *value, calc_padding(n_re_total + n_im_total + 1 + add_parens * 2, format->width, format->align, &lpad, &rpad, &total); - if (re_spec.n_lpadding || re_spec.n_spadding || re_spec.n_rpadding - || im_spec.n_lpadding || im_spec.n_spadding || im_spec.n_rpadding - || lpad || rpad) + if (lpad || rpad) maxchar = Py_MAX(maxchar, format->fill_char); result = PyUnicode_New(total, maxchar); @@ -1275,6 +1310,7 @@ done: PyMem_Free(im_buf); Py_XDECREF(re_unicode_tmp); Py_XDECREF(im_unicode_tmp); + free_locale_info(&locale); assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; }