summaryrefslogtreecommitdiff
path: root/src/cairo-misc.c
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2017-09-17 14:15:25 +0930
committerAdrian Johnson <ajohnson@redneon.com>2017-09-22 18:17:25 +0930
commite773dd744e88dc871fdc549132f07760f1be94c7 (patch)
tree40198db1160b1efa877101b86605a6b6b7b0e9fb /src/cairo-misc.c
parent871c518121452116ee799fe4262421d4c935972e (diff)
downloadcairo-e773dd744e88dc871fdc549132f07760f1be94c7.tar.gz
factor out ascii to double code in cff-subset into _cairo_strtod
Diffstat (limited to 'src/cairo-misc.c')
-rw-r--r--src/cairo-misc.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index e9b0ab6be..19629feca 100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -771,7 +771,7 @@ _cairo_half_from_float (float f)
# include <locale.h>
const char *
-cairo_get_locale_decimal_point (void)
+_cairo_get_locale_decimal_point (void)
{
struct lconv *locale_data = localeconv ();
return locale_data->decimal_point;
@@ -780,12 +780,68 @@ cairo_get_locale_decimal_point (void)
#else
/* Android's Bionic libc doesn't provide decimal_point */
const char *
-cairo_get_locale_decimal_point (void)
+_cairo_get_locale_decimal_point (void)
{
return ".";
}
#endif
+/* strtod replacement that ignores locale and only accepts decimal points */
+double
+_cairo_strtod (const char *nptr, char **endptr)
+{
+ const char *decimal_point;
+ int decimal_point_len;
+ const char *p;
+ char buf[100];
+ char *bufptr;
+ char *bufend = buf + sizeof(buf) - 1;
+ double value;
+ char *end;
+ int delta;
+ cairo_bool_t have_dp;
+
+ decimal_point = _cairo_get_locale_decimal_point ();
+ decimal_point_len = strlen (decimal_point);
+ assert (decimal_point_len != 0);
+
+ p = nptr;
+ bufptr = buf;
+ delta = 0;
+ have_dp = FALSE;
+ while (*p && _cairo_isspace (*p)) {
+ p++;
+ delta++;
+ }
+
+ while (*p && (bufptr + decimal_point_len < bufend)) {
+ if (_cairo_isdigit (*p)) {
+ *bufptr++ = *p;
+ } else if (*p == '.') {
+ if (have_dp)
+ break;
+ strncpy (bufptr, decimal_point, decimal_point_len);
+ bufptr += decimal_point_len;
+ delta -= decimal_point_len - 1;
+ have_dp = TRUE;
+ } else {
+ break;
+ }
+ p++;
+ }
+ *bufptr = 0;
+
+ value = strtod (buf, &end);
+ if (endptr) {
+ if (end == buf)
+ *endptr = (char*)(nptr);
+ else
+ *endptr = (char*)(nptr + (end - buf) + delta);
+ }
+
+ return value;
+}
+
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN