summaryrefslogtreecommitdiff
path: root/src/cairo-misc.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2017-09-17 11:17:13 -0400
committerBehdad Esfahbod <behdad@behdad.org>2017-12-19 15:17:01 -0500
commita8ae2eafc85fda76fde79defa40fe06000d907db (patch)
treef05c686541ad60f5b26b5d0218a5af28d5e8bdef /src/cairo-misc.c
parentac5acc45383f7ada422dec3e7c8a71bdb041fc8a (diff)
downloadcairo-a8ae2eafc85fda76fde79defa40fe06000d907db.tar.gz
Use strtod_l when available
Using strtod_l and newlocale is a nicer way to have provide a C-locale-only strtod. Since these APIs are not available everywhere, keep the old code as a fallback.
Diffstat (limited to 'src/cairo-misc.c')
-rw-r--r--src/cairo-misc.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index 1ecbabf33..cf0d6d160 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -43,6 +43,10 @@
#include <stdio.h>
#include <errno.h>
+#include <locale.h>
+#ifdef HAVE_XLOCALE_H
+#include <xlocale.h>
+#endif
COMPILE_TIME_ASSERT ((int)CAIRO_STATUS_LAST_STATUS < (int)CAIRO_INT_STATUS_UNSUPPORTED);
COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127);
@@ -789,6 +793,38 @@ _cairo_get_locale_decimal_point (void)
}
#endif
+#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L)
+
+static locale_t C_locale;
+
+static locale_t
+get_C_locale (void)
+{
+ locale_t C;
+
+retry:
+ C = (locale_t) _cairo_atomic_ptr_get (&C_locale);
+
+ if (unlikely (!C)) {
+ C = newlocale (LC_ALL_MASK, "C", NULL);
+
+ if (!_cairo_atomic_ptr_cmpxchg (&C_locale, NULL, C)) {
+ freelocale (C_locale);
+ goto retry;
+ }
+ }
+
+ return C;
+}
+
+double
+_cairo_strtod (const char *nptr, char **endptr)
+{
+ return strtod_l (nptr, endptr, get_C_locale ());
+}
+
+#else
+
/* strtod replacement that ignores locale and only accepts decimal points */
double
_cairo_strtod (const char *nptr, char **endptr)
@@ -844,6 +880,7 @@ _cairo_strtod (const char *nptr, char **endptr)
return value;
}
+#endif
/**
* _cairo_fopen: