diff options
-rw-r--r-- | dive.c | 4 | ||||
-rw-r--r-- | dive.h | 6 | ||||
-rw-r--r-- | parse-xml.c | 52 | ||||
-rw-r--r-- | save-xml.c | 13 | ||||
-rw-r--r-- | uemis-downloader.c | 2 | ||||
-rw-r--r-- | uemis.c | 11 | ||||
-rw-r--r-- | uemis.h | 3 |
7 files changed, 72 insertions, 19 deletions
@@ -1366,8 +1366,8 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, gboolean pr res->when = dl ? dl->when : a->when; res->selected = a->selected || b->selected; merge_trip(res, a, b); - MERGE_NONZERO(res, a, b, latitude); - MERGE_NONZERO(res, a, b, longitude); + MERGE_NONZERO(res, a, b, latitude.udeg); + MERGE_NONZERO(res, a, b, longitude.udeg); MERGE_TXT(res, a, b, location); MERGE_TXT(res, a, b, notes); MERGE_TXT(res, a, b, buddy); @@ -75,6 +75,10 @@ typedef struct { int grams; } weight_t; +typedef struct { + int udeg; +} degrees_t; + struct gasmix { fraction_t o2; fraction_t he; @@ -300,7 +304,7 @@ struct dive { char *notes; char *divemaster, *buddy; int rating; - double latitude, longitude; + degrees_t latitude, longitude; depth_t maxdepth, meandepth; int salinity; // kg per 10000 l duration_t duration, surfacetime; 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); } diff --git a/save-xml.c b/save-xml.c index 948f2ed08..5dc47795f 100644 --- a/save-xml.c +++ b/save-xml.c @@ -4,7 +4,6 @@ #include <stdlib.h> #include <errno.h> #include <time.h> -#include <math.h> #include "dive.h" @@ -183,9 +182,9 @@ static void save_salinity(FILE *f, struct dive *dive) * on a great circle (ie longitude at equator). And micro-degrees * is also enough to fit in a fixed-point 32-bit integer. */ -static int format_degrees(char *buffer, double value) +static int format_degrees(char *buffer, degrees_t value) { - int udeg = round(value * 1000000.0); + int udeg = value.udeg; const char *sign = ""; if (udeg < 0) { @@ -196,7 +195,7 @@ static int format_degrees(char *buffer, double value) sign, udeg / 1000000, udeg % 1000000); } -static int format_location(char *buffer, double latitude, double longitude) +static int format_location(char *buffer, degrees_t latitude, degrees_t longitude) { int len = sprintf(buffer, "gps='"); @@ -212,8 +211,8 @@ static void show_location(FILE *f, struct dive *dive) { char buffer[80]; const char *prefix = " <location>"; - double latitude = dive->latitude; - double longitude = dive->longitude; + degrees_t latitude = dive->latitude; + degrees_t longitude = dive->longitude; /* * Ok, theoretically I guess you could dive at @@ -221,7 +220,7 @@ static void show_location(FILE *f, struct dive *dive) * if you do, just fudge it a bit, and say that * you dove a few meters away. */ - if (latitude || longitude) { + if (latitude.udeg || longitude.udeg) { int len = sprintf(buffer, " <location "); len += format_location(buffer+len, latitude, longitude); diff --git a/uemis-downloader.c b/uemis-downloader.c index 449ae55ee..8f4ceaf2e 100644 --- a/uemis-downloader.c +++ b/uemis-downloader.c @@ -553,7 +553,7 @@ static void parse_divespot(char *buf) uemis_set_divelocation(divespot, strdup(locationstring), latitude, longitude); } -static void track_divespot(char *val, int diveid, char **location, double *latitude, double *longitude) +static void track_divespot(char *val, int diveid, char **location, degrees_t *latitude, degrees_t *longitude) { int id = atoi(val); if (id >= 0 && id > nr_divespots) @@ -15,6 +15,7 @@ #include <glib/gi18n.h> #define __USE_XOPEN #include <time.h> +#include <math.h> #include "dive.h" #include "uemis.h" @@ -107,8 +108,8 @@ struct uemis_helper { int lbs; int divespot; char **location; - double *latitude; - double *longitude; + degrees_t *latitude; + degrees_t *longitude; struct uemis_helper *next; }; static struct uemis_helper *uemis_helper = NULL; @@ -153,7 +154,7 @@ int uemis_get_weight_unit(int diveid) return 0; } -void uemis_mark_divelocation(int diveid, int divespot, char **location, double *longitude, double *latitude) +void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *longitude, degrees_t *latitude) { struct uemis_helper *hp = uemis_get_helper(diveid); hp->divespot = divespot; @@ -168,8 +169,8 @@ void uemis_set_divelocation(int divespot, char *text, double longitude, double l while (hp) { if (hp->divespot == divespot && hp->location) { *hp->location = text; - *hp->longitude = longitude; - *hp->latitude = latitude; + hp->longitude->udeg = round(longitude * 1000000); + hp->latitude->udeg = round(latitude * 1000000); } hp = hp->next; } @@ -6,10 +6,11 @@ #define UEMIS_H #include <stdint.h> +#include "dive.h" void uemis_parse_divelog_binary(char *base64, void *divep); int uemis_get_weight_unit(int diveid); -void uemis_mark_divelocation(int diveid, int divespot, char **location, double *longitude, double *latitude); +void uemis_mark_divelocation(int diveid, int divespot, char **location, degrees_t *longitude, degrees_t *latitude); void uemis_set_divelocation(int divespot, char *text, double longitude, double latitude); typedef struct { |