diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2017-09-17 14:15:25 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2017-09-22 18:17:25 +0930 |
commit | e773dd744e88dc871fdc549132f07760f1be94c7 (patch) | |
tree | 40198db1160b1efa877101b86605a6b6b7b0e9fb /src/cairo-misc.c | |
parent | 871c518121452116ee799fe4262421d4c935972e (diff) | |
download | cairo-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.c | 60 |
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 |