From 3ca69c8c32b8408dd9f8e6e866cd07e58c0d79b7 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 14 Sep 2017 20:50:35 -0400 Subject: [PATCH] Use strtod_l() to correctly parse decimal numbers in French & other locales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test with, eg.: $ LC_ALL=fr_FR.utf-8 ./hb-view NotoSansArabic-VF.ttf بهداد --variations wght=1.2 --- configure.ac | 4 ++-- src/hb-common.cc | 53 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 9151abc05..d65cae8cd 100644 --- a/configure.ac +++ b/configure.ac @@ -69,8 +69,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) ]) # Functions and headers -AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty) -AC_CHECK_HEADERS(unistd.h sys/mman.h) +AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l) +AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h) # Compiler flags AC_CANONICAL_HOST diff --git a/src/hb-common.cc b/src/hb-common.cc index 0483816d3..8e8e55653 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -32,6 +32,9 @@ #include "hb-object-private.hh" #include +#ifdef HAVE_XLOCALE_H +#include +#endif /* hb_options_t */ @@ -246,8 +249,8 @@ struct hb_language_item_t { static hb_language_item_t *langs; #ifdef HB_USE_ATEXIT -static -void free_langs (void) +static void +free_langs (void) { while (langs) { hb_language_item_t *next = langs->next; @@ -694,6 +697,48 @@ parse_uint32 (const char **pp, const char *end, uint32_t *pv) return true; } +#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L) +#define USE_XLOCALE 1 +#endif + +#ifdef USE_XLOCALE + +static locale_t C_locale; + +#ifdef HB_USE_ATEXIT +static void +free_C_locale (void) +{ + if (C_locale) + freelocale (C_locale); +} +#endif + +static locale_t +get_C_locale (void) +{ +retry: + locale_t C = (locale_t) hb_atomic_ptr_get (&C_locale); + + if (unlikely (!C)) + { + C = newlocale (LC_ALL_MASK, "C", NULL); + + if (!hb_atomic_ptr_cmpexch (&C_locale, NULL, C)) + { + freelocale (C_locale); + goto retry; + } + +#ifdef HB_USE_ATEXIT + atexit (free_C_locale); /* First person registers atexit() callback. */ +#endif + } + + return C; +} +#endif + static bool parse_float (const char **pp, const char *end, float *pv) { @@ -707,7 +752,11 @@ parse_float (const char **pp, const char *end, float *pv) float v; errno = 0; +#ifdef USE_XLOCALE + v = strtod_l (p, &pend, get_C_locale ()); +#else v = strtod (p, &pend); +#endif if (errno || p == pend) return false;