Merge branch 'alt-digits-locale-change' into 'main'

gdatetime: Fix incorrect alt-digits being used after changing locale

See merge request GNOME/glib!3655
This commit is contained in:
Michael Catanzaro 2023-10-22 22:32:34 +00:00
commit 7a9f8eec35
3 changed files with 42 additions and 5 deletions

View File

@ -22,12 +22,11 @@ RUN dnf -y update \
glibc-headers \ glibc-headers \
glibc-langpack-de \ glibc-langpack-de \
glibc-langpack-el \ glibc-langpack-el \
glibc-langpack-el \
glibc-langpack-en \ glibc-langpack-en \
glibc-langpack-es \ glibc-langpack-es \
glibc-langpack-es \
glibc-langpack-fa \ glibc-langpack-fa \
glibc-langpack-fr \ glibc-langpack-fr \
glibc-langpack-gu \
glibc-langpack-hr \ glibc-langpack-hr \
glibc-langpack-ja \ glibc-langpack-ja \
glibc-langpack-lt \ glibc-langpack-lt \

View File

@ -54,6 +54,7 @@
#define _GNU_SOURCE 1 #define _GNU_SOURCE 1
#endif #endif
#include <locale.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -2820,6 +2821,9 @@ format_z (GString *outstr,
/* Initializes the array with UTF-8 encoded alternate digits suitable for use /* Initializes the array with UTF-8 encoded alternate digits suitable for use
* in current locale. Returns NULL when current locale does not use alternate * in current locale. Returns NULL when current locale does not use alternate
* digits or there was an error converting them to UTF-8. * digits or there was an error converting them to UTF-8.
*
* This needs external locking, so must only be called from within
* format_number().
*/ */
static const gchar * const * static const gchar * const *
initialize_alt_digits (void) initialize_alt_digits (void)
@ -2874,6 +2878,9 @@ format_number (GString *str,
const gchar * const *digits = ascii_digits; const gchar * const *digits = ascii_digits;
const gchar *tmp[10]; const gchar *tmp[10];
gint i = 0; gint i = 0;
#ifdef HAVE_LANGINFO_OUTDIGIT
static GMutex alt_digits_mutex;
#endif
g_return_if_fail (width <= 10); g_return_if_fail (width <= 10);
@ -2881,16 +2888,21 @@ format_number (GString *str,
if (use_alt_digits) if (use_alt_digits)
{ {
static const gchar * const *alt_digits = NULL; static const gchar * const *alt_digits = NULL;
static gsize initialised; static char *alt_digits_locale = NULL;
const char *current_ctype_locale = setlocale (LC_CTYPE, NULL);
if G_UNLIKELY (g_once_init_enter (&initialised)) /* Lock so we can initialise (or re-initialise, if the locale has changed)
* and hold access to the digits buffer until done formatting. */
g_mutex_lock (&alt_digits_mutex);
if (g_strcmp0 (alt_digits_locale, current_ctype_locale) != 0)
{ {
alt_digits = initialize_alt_digits (); alt_digits = initialize_alt_digits ();
if (alt_digits == NULL) if (alt_digits == NULL)
alt_digits = ascii_digits; alt_digits = ascii_digits;
g_once_init_leave (&initialised, TRUE); alt_digits_locale = g_strdup (current_ctype_locale);
} }
digits = alt_digits; digits = alt_digits;
@ -2907,6 +2919,11 @@ format_number (GString *str,
while (pad && i < width) while (pad && i < width)
tmp[i++] = *pad == '0' ? digits[0] : pad; tmp[i++] = *pad == '0' ? digits[0] : pad;
#ifdef HAVE_LANGINFO_OUTDIGIT
if (use_alt_digits)
g_mutex_unlock (&alt_digits_mutex);
#endif
/* should really be impossible */ /* should really be impossible */
g_assert (i <= 10); g_assert (i <= 10);

View File

@ -1834,6 +1834,7 @@ test_modifiers (void)
TEST_PRINTF_TIME (1, 0, 0, "%#P", "am"); TEST_PRINTF_TIME (1, 0, 0, "%#P", "am");
oldlocale = g_strdup (setlocale (LC_ALL, NULL)); oldlocale = g_strdup (setlocale (LC_ALL, NULL));
setlocale (LC_ALL, "fa_IR.utf-8"); setlocale (LC_ALL, "fa_IR.utf-8");
#ifdef HAVE_LANGINFO_OUTDIGIT #ifdef HAVE_LANGINFO_OUTDIGIT
if (strstr (setlocale (LC_ALL, NULL), "fa_IR") != NULL) if (strstr (setlocale (LC_ALL, NULL), "fa_IR") != NULL)
@ -1852,6 +1853,26 @@ test_modifiers (void)
#else #else
g_test_skip ("langinfo not available, skipping O modifier tests"); g_test_skip ("langinfo not available, skipping O modifier tests");
#endif #endif
setlocale (LC_ALL, "gu_IN.utf-8");
#ifdef HAVE_LANGINFO_OUTDIGIT
if (strstr (setlocale (LC_ALL, NULL), "gu_IN") != NULL)
{
TEST_PRINTF_TIME (23, 0, 0, "%OH", "૨૩"); /* '23' */
TEST_PRINTF_TIME (23, 0, 0, "%OI", "૧૧"); /* '11' */
TEST_PRINTF_TIME (23, 0, 0, "%OM", ""); /* '00' */
TEST_PRINTF_DATE (2011, 7, 1, "%Om", "૦૭"); /* '07' */
TEST_PRINTF_DATE (2011, 7, 1, "%0Om", "૦૭"); /* '07' */
TEST_PRINTF_DATE (2011, 7, 1, "%-Om", ""); /* '7' */
TEST_PRINTF_DATE (2011, 7, 1, "%_Om", ""); /* ' 7' */
}
else
g_test_skip ("locale gu_IN not available, skipping O modifier tests");
#else
g_test_skip ("langinfo not available, skipping O modifier tests");
#endif
setlocale (LC_ALL, oldlocale); setlocale (LC_ALL, oldlocale);
g_free (oldlocale); g_free (oldlocale);
} }