Modified interface to _Py_[String|Unicode]InsertThousandsGrouping, in anticipation of fixing issue 3140.

This commit is contained in:
Eric Smith 2008-06-24 00:42:10 +00:00
parent 57acc8f5ab
commit 65fe47b931
4 changed files with 30 additions and 23 deletions

View File

@ -182,8 +182,8 @@ PyAPI_FUNC(int) PyString_AsStringAndSize(
see Objects/stringlib/localeutil.h */ see Objects/stringlib/localeutil.h */
PyAPI_FUNC(int) _PyString_InsertThousandsGrouping(char *buffer, PyAPI_FUNC(int) _PyString_InsertThousandsGrouping(char *buffer,
Py_ssize_t len, Py_ssize_t n_buffer,
char *plast, Py_ssize_t n_digits,
Py_ssize_t buf_size, Py_ssize_t buf_size,
Py_ssize_t *count, Py_ssize_t *count,
int append_zero_char); int append_zero_char);

View File

@ -563,8 +563,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
if (format->type == 'n') if (format->type == 'n')
/* Compute how many additional chars we need to allocate /* Compute how many additional chars we need to allocate
to hold the thousands grouping. */ to hold the thousands grouping. */
STRINGLIB_GROUPING(pnumeric_chars, n_digits, STRINGLIB_GROUPING(NULL, n_digits, n_digits,
pnumeric_chars+n_digits,
0, &n_grouping_chars, 0); 0, &n_grouping_chars, 0);
/* Allocate a new string to hold the result */ /* Allocate a new string to hold the result */
@ -592,8 +591,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format,
/* We know this can't fail, since we've already /* We know this can't fail, since we've already
reserved enough space. */ reserved enough space. */
STRINGLIB_CHAR *pstart = p + n_leading_chars; STRINGLIB_CHAR *pstart = p + n_leading_chars;
int r = STRINGLIB_GROUPING(pstart, n_digits, int r = STRINGLIB_GROUPING(pstart, n_digits, n_digits,
pstart + n_digits,
spec.n_total+n_grouping_chars-n_leading_chars, spec.n_total+n_grouping_chars-n_leading_chars,
NULL, 0); NULL, 0);
assert(r); assert(r);

View File

@ -8,10 +8,9 @@
/** /**
* _Py_InsertThousandsGrouping: * _Py_InsertThousandsGrouping:
* @buffer: A pointer to the start of a string. * @buffer: A pointer to the start of a string.
* @len: The length of the string. * @n_buffer: The length of the string.
* @plast: A pointer to the end of of the digits in the string. This * @n_digits: The number of digits in the string, in which we want
* may be before the end of the string (if the string contains * to put the grouping chars.
* decimals, for example).
* @buf_size: The maximum size of the buffer pointed to by buffer. * @buf_size: The maximum size of the buffer pointed to by buffer.
* @count: If non-NULL, points to a variable that will receive the * @count: If non-NULL, points to a variable that will receive the
* number of characters we need to insert (and no formatting * number of characters we need to insert (and no formatting
@ -21,10 +20,11 @@
* string. * string.
* *
* Inserts thousand grouping characters (as defined in the current * Inserts thousand grouping characters (as defined in the current
* locale) into the string between buffer and plast. If count is * locale) into the string between buffer and buffer+n_digits. If
* non-NULL, don't do any formatting, just count the number of * count is non-NULL, don't do any formatting, just count the number
* characters to insert. This is used by the caller to appropriately * of characters to insert. This is used by the caller to
* resize the buffer, if needed. * appropriately resize the buffer, if needed. If count is non-NULL,
* buffer can be NULL (it is not dereferenced at all in that case).
* *
* Return value: 0 on error, else 1. Note that no error can occur if * Return value: 0 on error, else 1. Note that no error can occur if
* count is non-NULL. * count is non-NULL.
@ -34,8 +34,8 @@
**/ **/
int int
_Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer, _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
Py_ssize_t len, Py_ssize_t n_buffer,
STRINGLIB_CHAR *plast, Py_ssize_t n_digits,
Py_ssize_t buf_size, Py_ssize_t buf_size,
Py_ssize_t *count, Py_ssize_t *count,
int append_zero_char) int append_zero_char)
@ -44,15 +44,22 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
const char *grouping = locale_data->grouping; const char *grouping = locale_data->grouping;
const char *thousands_sep = locale_data->thousands_sep; const char *thousands_sep = locale_data->thousands_sep;
Py_ssize_t thousands_sep_len = strlen(thousands_sep); Py_ssize_t thousands_sep_len = strlen(thousands_sep);
STRINGLIB_CHAR *pend = buffer + len; /* current end of buffer */ STRINGLIB_CHAR *pend = NULL; /* current end of buffer */
STRINGLIB_CHAR *pmax = buffer + buf_size; /* max of buffer */ STRINGLIB_CHAR *pmax = NULL; /* max of buffer */
char current_grouping; char current_grouping;
Py_ssize_t remaining = n_digits; /* Number of chars remaining to
be looked at */
/* Initialize the character count, if we're just counting. */ /* Initialize the character count, if we're just counting. */
if (count) if (count)
*count = 0; *count = 0;
else {
/* We're not just counting, we're modifying buffer */
pend = buffer + n_buffer;
pmax = buffer + buf_size;
}
/* Starting at plast and working right-to-left, keep track of /* Starting at the end and working right-to-left, keep track of
what grouping needs to be added and insert that. */ what grouping needs to be added and insert that. */
current_grouping = *grouping++; current_grouping = *grouping++;
@ -60,11 +67,11 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
if (current_grouping == 0) if (current_grouping == 0)
return 1; return 1;
while (plast - buffer > current_grouping) { while (remaining > current_grouping) {
/* Always leave buffer and pend valid at the end of this /* Always leave buffer and pend valid at the end of this
loop, since we might leave with a return statement. */ loop, since we might leave with a return statement. */
plast -= current_grouping; remaining -= current_grouping;
if (count) { if (count) {
/* We're only counting, not touching the memory. */ /* We're only counting, not touching the memory. */
*count += thousands_sep_len; *count += thousands_sep_len;
@ -72,6 +79,8 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
else { else {
/* Do the formatting. */ /* Do the formatting. */
STRINGLIB_CHAR *plast = buffer + remaining;
/* Is there room to insert thousands_sep_len chars? */ /* Is there room to insert thousands_sep_len chars? */
if (pmax - pend < thousands_sep_len) if (pmax - pend < thousands_sep_len)
/* No room. */ /* No room. */
@ -111,7 +120,7 @@ _Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
if (append_zero_char) { if (append_zero_char) {
/* Append a zero character to mark the end of the string, /* Append a zero character to mark the end of the string,
if there's room. */ if there's room. */
if (pend - plast < 1) if (pend - (buffer + remaining) < 1)
/* No room, error. */ /* No room, error. */
return 0; return 0;
*pend = 0; *pend = 0;

View File

@ -364,7 +364,7 @@ add_thousands_grouping(char* buffer, size_t buf_size)
/* At this point, p points just past the right-most character we /* At this point, p points just past the right-most character we
want to format. We need to add the grouping string for the want to format. We need to add the grouping string for the
characters between buffer and p. */ characters between buffer and p. */
return _PyString_InsertThousandsGrouping(buffer, len, p, return _PyString_InsertThousandsGrouping(buffer, len, p-buffer,
buf_size, NULL, 1); buf_size, NULL, 1);
} }