From 81687a7388bf16d84d85987c97d029dc5e0c61a0 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Tue, 27 May 2014 22:45:50 +0100 Subject: [PATCH] SF Bugs#106: Fix incorrect location on opening .vik file saved in different locale. Enable reading in of decimal values that may contain either '.' or ',' as the separator. Need to use modified version of strtod() since the standard C library does not support reading in values from a different locale. Ideally Viking shouldn't have saved these values into the file in a locale dependent manner, but for a few values this is the case (ever since the first public release of Viking). Thus to maintain backwards compatibility need to handle standard variations of the decimal separator. Selected strtod() from the Sanos project for it's simplicity (compared to 'David M. Gay' version: http://www.netlib.org/fp/dtoa.c - which may handle extremes of precision better - but such values aren't encountered in Viking) --- .gitignore | 5 +++++ src/Makefile.am | 3 ++- src/file.c | 11 ++++++----- src/misc/strtod.c | 19 +++++++++++-------- src/misc/strtod.h | 22 ++++++++++++++++++++++ 5 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 src/misc/strtod.h diff --git a/.gitignore b/.gitignore index f9bac588..601cb82c 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,11 @@ help/C/*html /src/icons/icons.o /src/icons/libicons.a +# src/misc/ +src/misc/.deps +src/misc/.dirstamp +src/misc/*.o + # /test/ /test/.deps /test/Makefile.in diff --git a/src/Makefile.am b/src/Makefile.am index 14d2a075..6ad2915c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -144,7 +144,8 @@ libviking_a_SOURCES = \ print.c print.h \ viklayer_defaults.c viklayer_defaults.h \ settings.c settings.h \ - preferences.c preferences.h + preferences.c preferences.h \ + misc/strtod.c misc/strtod.h if BING libviking_a_SOURCES += \ diff --git a/src/file.c b/src/file.c index 835f2ece..d2692a35 100644 --- a/src/file.c +++ b/src/file.c @@ -45,6 +45,7 @@ #include #include "file.h" +#include "misc/strtod.h" #define TEST_BOOLEAN(str) (! ((str)[0] == '\0' || (str)[0] == '0' || (str)[0] == 'n' || (str)[0] == 'N' || (str)[0] == 'f' || (str)[0] == 'F') ) #define VIK_MAGIC "#VIK" @@ -433,13 +434,13 @@ static gboolean file_read ( VikAggregateLayer *top, FILE *f, const gchar *dirpat // However we'll still carry and attempt to read whatever we can } else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "xmpp", eq_pos ) == 0) /* "hard coded" params: global & for all layer-types */ - vik_viewport_set_xmpp ( VIK_VIEWPORT(vp), strtod ( line+5, NULL ) ); + vik_viewport_set_xmpp ( VIK_VIEWPORT(vp), strtod_i8n ( line+5, NULL ) ); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "ympp", eq_pos ) == 0) - vik_viewport_set_ympp ( VIK_VIEWPORT(vp), strtod ( line+5, NULL ) ); + vik_viewport_set_ympp ( VIK_VIEWPORT(vp), strtod_i8n ( line+5, NULL ) ); else if ( stack->under == NULL && eq_pos == 3 && strncasecmp ( line, "lat", eq_pos ) == 0 ) - ll.lat = strtod ( line+4, NULL ); + ll.lat = strtod_i8n ( line+4, NULL ); else if ( stack->under == NULL && eq_pos == 3 && strncasecmp ( line, "lon", eq_pos ) == 0 ) - ll.lon = strtod ( line+4, NULL ); + ll.lon = strtod_i8n ( line+4, NULL ); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "utm" ) == 0) vik_viewport_set_drawmode ( VIK_VIEWPORT(vp), VIK_VIEWPORT_DRAWMODE_UTM); else if ( stack->under == NULL && eq_pos == 4 && strncasecmp ( line, "mode", eq_pos ) == 0 && strcasecmp ( line+5, "expedia" ) == 0) @@ -500,7 +501,7 @@ static gboolean file_read ( VikAggregateLayer *top, FILE *f, const gchar *dirpat } else { switch ( params[i].type ) { - case VIK_LAYER_PARAM_DOUBLE: x.d = strtod(line, NULL); break; + case VIK_LAYER_PARAM_DOUBLE: x.d = strtod_i8n(line, NULL); break; case VIK_LAYER_PARAM_UINT: x.u = strtoul(line, NULL, 10); break; case VIK_LAYER_PARAM_INT: x.i = strtol(line, NULL, 10); break; case VIK_LAYER_PARAM_BOOLEAN: x.b = TEST_BOOLEAN(line); break; diff --git a/src/misc/strtod.c b/src/misc/strtod.c index 17936dac..1492a104 100644 --- a/src/misc/strtod.c +++ b/src/misc/strtod.c @@ -31,13 +31,16 @@ // SUCH DAMAGE. // +// Tweaked version for Viking project to read in values containing ',' or '.' as the decimal separator +// Modified functions to prevent clashing with the system ones + #include #include #include #include #include -double strtod(const char *str, char **endptr) { +double strtod_i8n(const char *str, char **endptr) { double number; int exponent; int negative; @@ -70,7 +73,7 @@ double strtod(const char *str, char **endptr) { } // Process decimal part - if (*p == '.') { + if (*p == '.' || *p == ',') { p++; while (isdigit(*p)) { @@ -141,15 +144,15 @@ double strtod(const char *str, char **endptr) { return number; } -float strtof(const char *str, char **endptr) { - return (float) strtod(str, endptr); +float strtof_i8n(const char *str, char **endptr) { + return (float) strtod_i8n(str, endptr); } -long double strtold(const char *str, char **endptr) { - return strtod(str, endptr); +long double strtold_i8n(const char *str, char **endptr) { + return strtod_i8n(str, endptr); } -double atof(const char *str) { - return strtod(str, NULL); +double atof_i8n(const char *str) { + return strtod_i8n(str, NULL); } diff --git a/src/misc/strtod.h b/src/misc/strtod.h new file mode 100644 index 00000000..d138a474 --- /dev/null +++ b/src/misc/strtod.h @@ -0,0 +1,22 @@ +// License: CC0 +// Basic interface to strtod.c from the Sanos Operating System Kernel (http://www.jbox.dk/sanos/) +// Function names modified to prevent clashing with whatever OS this code is being built with + + +#ifndef __STRTOD_H +#define __STRTOD_H + +#ifdef __cplusplus +extern "C" { +#endif + +double strtod_i8n(const char *str, char **endptr); +float strtof_i8n(const char *str, char **endptr); +long double strtold_i8n(const char *str, char **endptr); +double atof_i8n(const char *str); + +#ifdef __cplusplus +} +#endif + +#endif -- 2.39.5