summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2012-02-24 00:34:55 (GMT)
committerBrett Cannon <brett@python.org>2012-02-24 00:34:55 (GMT)
commit6858cabb265ed752aeb27cacbacd58817daaacaa (patch)
tree3c21de785e9485916a078b048a6b5414cf9b98a8
parentdfc32706a0422c81a470a38c8197af3be187416d (diff)
parent41a863cb81608c779d60b49e7be8a115816734fc (diff)
downloadcpython-6858cabb265ed752aeb27cacbacd58817daaacaa.zip
cpython-6858cabb265ed752aeb27cacbacd58817daaacaa.tar.gz
cpython-6858cabb265ed752aeb27cacbacd58817daaacaa.tar.bz2
merge
-rw-r--r--Include/unicodeobject.h18
-rw-r--r--Lib/test/test_format.py15
-rw-r--r--Objects/stringlib/asciilib.h3
-rw-r--r--Objects/stringlib/localeutil.h71
-rw-r--r--Objects/stringlib/stringdefs.h2
-rw-r--r--Objects/stringlib/ucs1lib.h3
-rw-r--r--Objects/stringlib/ucs2lib.h3
-rw-r--r--Objects/stringlib/ucs4lib.h3
-rw-r--r--Objects/stringlib/undef.h2
-rw-r--r--Objects/stringlib/unicodedefs.h2
-rw-r--r--Objects/unicodeobject.c75
-rw-r--r--Python/formatter_unicode.c142
12 files changed, 188 insertions, 151 deletions
diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h
index 6d580f4..465d87b 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 7345b30..70e748f 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 ae68e3c..fa481c0 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 ddce69d..28c87c8 100644
--- a/Objects/stringlib/localeutil.h
+++ b/Objects/stringlib/localeutil.h
@@ -2,8 +2,9 @@
#include <locale.h>
-#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 fec9f18..7bb91a7 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 42b9d91..ed2b0a3 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 611e741..a508905 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 330b292..eda0feb 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 fd87e56..9310204 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 3ccc57e..f16f21e 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 01748be..2841b07 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 ed716a5..94f8047 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;
}