141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm/** @file
241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    stringlib: locale related helpers implementation.
341b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
441b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
541b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    This program and the accompanying materials are licensed and made available under
641b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    the terms and conditions of the BSD License that accompanies this distribution.
741b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    The full text of the license may be found at
841b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    http://opensource.org/licenses/bsd-license.
941b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm
1041b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1141b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1241b152c5f6ec3a5a6e51b4f8f0f90291a5895edcdarylm**/
136c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
146c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#ifndef STRINGLIB_LOCALEUTIL_H
156c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#define STRINGLIB_LOCALEUTIL_H
166c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
176c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#include <locale.h>
186c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
196c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm// Prevent conflicts with EFI
206c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#undef  MAX
216c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#undef  MIN
226c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
236c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#define MAX(x, y) ((x) < (y) ? (y) : (x))
246c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#define MIN(x, y) ((x) < (y) ? (x) : (y))
256c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
266c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmtypedef struct {
276c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    const char *grouping;
286c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    char previous;
296c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t i; /* Where we're currently pointing in grouping. */
306c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm} GroupGenerator;
316c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
326c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmstatic void
336c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm_GroupGenerator_init(GroupGenerator *self, const char *grouping)
346c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm{
356c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    self->grouping = grouping;
366c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    self->i = 0;
376c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    self->previous = 0;
386c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm}
396c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
406c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm/* Returns the next grouping, or 0 to signify end. */
416c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmstatic Py_ssize_t
426c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm_GroupGenerator_next(GroupGenerator *self)
436c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm{
446c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    /* Note that we don't really do much error checking here. If a
456c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm       grouping string contains just CHAR_MAX, for example, then just
466c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm       terminate the generator. That shouldn't happen, but at least we
476c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm       fail gracefully. */
486c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    switch (self->grouping[self->i]) {
496c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    case 0:
506c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        return self->previous;
516c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    case CHAR_MAX:
526c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Stop the generator. */
536c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        return 0;
546c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    default: {
556c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        char ch = self->grouping[self->i];
566c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        self->previous = ch;
576c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        self->i++;
586c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        return (Py_ssize_t)ch;
596c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    }
606c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    }
616c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm}
626c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
636c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm/* Fill in some digits, leading zeros, and thousands separator. All
646c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm   are optional, depending on when we're called. */
656c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmstatic void
666c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmfill(STRINGLIB_CHAR **digits_end, STRINGLIB_CHAR **buffer_end,
676c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm     Py_ssize_t n_chars, Py_ssize_t n_zeros, const char* thousands_sep,
686c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm     Py_ssize_t thousands_sep_len)
696c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm{
706c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#if STRINGLIB_IS_UNICODE
716c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t i;
726c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#endif
736c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
746c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    if (thousands_sep) {
756c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        *buffer_end -= thousands_sep_len;
766c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
776c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Copy the thousands_sep chars into the buffer. */
786c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#if STRINGLIB_IS_UNICODE
796c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Convert from the char's of the thousands_sep from
806c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm           the locale into unicode. */
816c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        for (i = 0; i < thousands_sep_len; ++i)
826c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            (*buffer_end)[i] = thousands_sep[i];
836c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#else
846c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* No conversion, just memcpy the thousands_sep. */
856c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        memcpy(*buffer_end, thousands_sep, thousands_sep_len);
866c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#endif
876c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    }
886c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
896c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    *buffer_end -= n_chars;
906c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    *digits_end -= n_chars;
916c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    memcpy(*buffer_end, *digits_end, n_chars * sizeof(STRINGLIB_CHAR));
926c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
936c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    *buffer_end -= n_zeros;
946c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    STRINGLIB_FILL(*buffer_end, '0', n_zeros);
956c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm}
966c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
976c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm/**
986c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * _Py_InsertThousandsGrouping:
996c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @buffer: A pointer to the start of a string.
1006c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @n_buffer: Number of characters in @buffer.
1016c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @digits: A pointer to the digits we're reading from. If count
1026c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *          is non-NULL, this is unused.
1036c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @n_digits: The number of digits in the string, in which we want
1046c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *            to put the grouping chars.
1056c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @min_width: The minimum width of the digits in the output string.
1066c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *             Output will be zero-padded on the left to fill.
1076c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @grouping: see definition in localeconv().
1086c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @thousands_sep: see definition in localeconv().
1096c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *
1106c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * There are 2 modes: counting and filling. If @buffer is NULL,
1116c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *  we are in counting mode, else filling mode.
1126c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * If counting, the required buffer size is returned.
1136c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * If filling, we know the buffer will be large enough, so we don't
1146c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *  need to pass in the buffer size.
1156c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * Inserts thousand grouping characters (as defined by grouping and
1166c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *  thousands_sep) into the string between buffer and buffer+n_digits.
1176c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *
1186c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * Return value: 0 on error, else 1.  Note that no error can occur if
1196c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *  count is non-NULL.
1206c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *
1216c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * This name won't be used, the includer of this file should define
1226c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *  it to be the actual function name, based on unicode or string.
1236c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *
1246c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * As closely as possible, this code mimics the logic in decimal.py's
1256c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    _insert_thousands_sep().
1266c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm **/
1276c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmPy_ssize_t
1286c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm_Py_InsertThousandsGrouping(STRINGLIB_CHAR *buffer,
1296c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                            Py_ssize_t n_buffer,
1306c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                            STRINGLIB_CHAR *digits,
1316c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                            Py_ssize_t n_digits,
1326c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                            Py_ssize_t min_width,
1336c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                            const char *grouping,
1346c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                            const char *thousands_sep)
1356c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm{
1366c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t count = 0;
1376c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t n_zeros;
1386c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    int loop_broken = 0;
1396c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    int use_separator = 0; /* First time through, don't append the
1406c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                              separator. They only go between
1416c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                              groups. */
1426c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    STRINGLIB_CHAR *buffer_end = NULL;
1436c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    STRINGLIB_CHAR *digits_end = NULL;
1446c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t l;
1456c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t n_chars;
1466c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t thousands_sep_len = strlen(thousands_sep);
1476c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    Py_ssize_t remaining = n_digits; /* Number of chars remaining to
1486c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                                        be looked at */
1496c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    /* A generator that returns all of the grouping widths, until it
1506c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm       returns 0. */
1516c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    GroupGenerator groupgen;
1526c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    _GroupGenerator_init(&groupgen, grouping);
1536c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1546c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    if (buffer) {
1556c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        buffer_end = buffer + n_buffer;
1566c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        digits_end = digits + n_digits;
1576c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    }
1586c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1596c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    while ((l = _GroupGenerator_next(&groupgen)) > 0) {
1606c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        l = MIN(l, MAX(MAX(remaining, min_width), 1));
1616c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        n_zeros = MAX(0, l - remaining);
1626c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        n_chars = MAX(0, MIN(remaining, l));
1636c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1646c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Use n_zero zero's and n_chars chars */
1656c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1666c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Count only, don't do anything. */
1676c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars;
1686c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1696c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        if (buffer) {
1706c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            /* Copy into the output buffer. */
1716c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            fill(&digits_end, &buffer_end, n_chars, n_zeros,
1726c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                 use_separator ? thousands_sep : NULL, thousands_sep_len);
1736c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        }
1746c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1756c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Use a separator next time. */
1766c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        use_separator = 1;
1776c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1786c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        remaining -= n_chars;
1796c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        min_width -= l;
1806c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1816c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        if (remaining <= 0 && min_width <= 0) {
1826c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            loop_broken = 1;
1836c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            break;
1846c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        }
1856c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        min_width -= thousands_sep_len;
1866c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    }
1876c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    if (!loop_broken) {
1886c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* We left the loop without using a break statement. */
1896c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1906c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        l = MAX(MAX(remaining, min_width), 1);
1916c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        n_zeros = MAX(0, l - remaining);
1926c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        n_chars = MAX(0, MIN(remaining, l));
1936c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
1946c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        /* Use n_zero zero's and n_chars chars */
1956c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        count += (use_separator ? thousands_sep_len : 0) + n_zeros + n_chars;
1966c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        if (buffer) {
1976c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            /* Copy into the output buffer. */
1986c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm            fill(&digits_end, &buffer_end, n_chars, n_zeros,
1996c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                 use_separator ? thousands_sep : NULL, thousands_sep_len);
2006c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        }
2016c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    }
2026c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm    return count;
2036c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm}
2046c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
2056c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm/**
2066c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * _Py_InsertThousandsGroupingLocale:
2076c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @buffer: A pointer to the start of a string.
2086c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * @n_digits: The number of digits in the string, in which we want
2096c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *            to put the grouping chars.
2106c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm *
2116c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm * Reads thee current locale and calls _Py_InsertThousandsGrouping().
2126c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm **/
2136c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylmPy_ssize_t
2146c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm_Py_InsertThousandsGroupingLocale(STRINGLIB_CHAR *buffer,
2156c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                                  Py_ssize_t n_buffer,
2166c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                                  STRINGLIB_CHAR *digits,
2176c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                                  Py_ssize_t n_digits,
2186c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                                  Py_ssize_t min_width)
2196c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm{
2206c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        struct lconv *locale_data = localeconv();
2216c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        const char *grouping = locale_data->grouping;
2226c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        const char *thousands_sep = locale_data->thousands_sep;
2236c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm
2246c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm        return _Py_InsertThousandsGrouping(buffer, n_buffer, digits, n_digits,
2256c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm                                           min_width, grouping, thousands_sep);
2266c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm}
2276c0ebd5f2f53d5c4d6a91fd0b9148ba23e730c39darylm#endif /* STRINGLIB_LOCALEUTIL_H */
228