summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.c4
-rw-r--r--dive.h6
-rw-r--r--parse-xml.c52
-rw-r--r--save-xml.c13
-rw-r--r--uemis-downloader.c2
-rw-r--r--uemis.c11
-rw-r--r--uemis.h3
7 files changed, 72 insertions, 19 deletions
diff --git a/dive.c b/dive.c
index d18a3d458..f527fae37 100644
--- a/dive.c
+++ b/dive.c
@@ -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);
diff --git a/dive.h b/dive.h
index 746d2a9fc..4cfa6fa38 100644
--- a/dive.h
+++ b/dive.h
@@ -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)
diff --git a/uemis.c b/uemis.c
index af344a5f1..4306a1b55 100644
--- a/uemis.c
+++ b/uemis.c
@@ -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;
}
diff --git a/uemis.h b/uemis.h
index ac47b0978..f8489f5c3 100644
--- a/uemis.h
+++ b/uemis.h
@@ -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 {