diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-05 09:59:52 -0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2012-12-05 10:34:02 -0800 |
commit | 5e5e3460acf9d29b03aff71228aff01e31a3bf45 (patch) | |
tree | 07629133d0d9ea1948692690929582ae9029e12e /parse-xml.c | |
parent | 708df33539ef3b6d3cfde435df93fd4475cdde75 (diff) | |
download | subsurface-5e5e3460acf9d29b03aff71228aff01e31a3bf45.tar.gz |
Turn latitude and longitude into integer micro-degree values
This actually makes us internally use 'micro-degrees' for latitude and
longitude, and we never turn them into floating point either at parse
time or save time.
That said, the Uemis downloader internally does still use atof() when
converting things, which is likely a bug (locale issues and all that),
but I'll ask Dirk to check it out.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'parse-xml.c')
-rw-r--r-- | parse-xml.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/parse-xml.c b/parse-xml.c index 2470f8bb4..35299257a 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -788,13 +788,61 @@ static int uddf_dive_match(struct dive *dive, const char *name, int len, char *b 0; } +/* + * This parses "floating point" into micro-degrees. + * We don't do exponentials etc, if somebody does + * gps locations in that format, they are insane. + */ +static degrees_t parse_degrees(char *buf, char **end) +{ + int sign = 1, decimals = 6, value = 0; + degrees_t ret; + + while (isspace(*buf)) + buf++; + switch (*buf) { + case '-': + sign = -1; + /* fallthrough */ + case '+': + buf++; + } + while (isdigit(*buf)) { + value = 10*value + *buf - '0'; + buf++; + } + + /* Get the first six decimals if they exist */ + if (*buf == '.') + buf++; + do { + value *= 10; + if (isdigit(*buf)) { + value += *buf - '0'; + buf++; + } + } while (--decimals); + + /* Rounding */ + switch (*buf) { + case '5' ... '9': + value++; + } + while (isdigit(*buf)) + buf++; + + *end = buf; + ret.udeg = value * sign; + return ret; +} + static void gps_location(char *buffer, void *_dive) { char *end; struct dive *dive = _dive; - dive->latitude = g_ascii_strtod(buffer, &end); - dive->longitude = g_ascii_strtod(end, &end); + dive->latitude = parse_degrees(buffer, &end); + dive->longitude = parse_degrees(end, &end); free(buffer); } |