diff options
-rw-r--r-- | dive.h | 16 | ||||
-rw-r--r-- | parse-xml.c | 166 | ||||
-rw-r--r-- | save-xml.c | 54 |
3 files changed, 167 insertions, 69 deletions
@@ -8,6 +8,7 @@ #include <zip.h> #include <sqlite3.h> #include <string.h> +#include "divesite.h" /* Windows has no MIN/MAX macros - so let's just roll our own */ #define MIN(x, y) ({ \ @@ -387,11 +388,6 @@ extern void dive_set_geodata_from_picture(struct dive *d, struct picture *pic); extern int explicit_first_cylinder(struct dive *dive, struct divecomputer *dc); -static inline int dive_has_gps_location(struct dive *dive) -{ - return dive->latitude.udeg || dive->longitude.udeg; -} - static inline void copy_gps_location(struct dive *from, struct dive *to) { if (from && to) { @@ -607,6 +603,16 @@ static inline int get_idx_by_uniq_id(int id) return i; } +static inline bool dive_site_has_gps_location(struct dive_site *ds) +{ + return ds && (ds->latitude.udeg || ds->longitude.udeg); +} + +static inline int dive_has_gps_location(struct dive *dive) +{ + return dive_site_has_gps_location(get_dive_site_by_uuid(dive->dive_site_uuid)); +} + #ifdef __cplusplus extern "C" { #endif diff --git a/parse-xml.c b/parse-xml.c index 5baa40394..4377a32cb 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -128,6 +128,7 @@ const struct units IMPERIAL_units = IMPERIAL_UNITS; #define MAX_EVENT_NAME 128 static struct divecomputer *cur_dc; static struct dive *cur_dive; +static struct dive_site *cur_dive_site; static dive_trip_t *cur_trip = NULL; static struct sample *cur_sample; static struct picture *cur_picture; @@ -968,22 +969,21 @@ void try_to_fill_userid(const char *name, char *buf) static const char *country, *city; -static void divinglog_place(char *place, char **location) +static void divinglog_place(char *place, uint32_t *uuid) { char buffer[1024], *p; int len; - len = snprintf(buffer, sizeof(buffer), - "%s%s%s%s%s", - place, - city ? ", " : "", - city ? city : "", - country ? ", " : "", - country ? country : ""); - - p = malloc(len + 1); - memcpy(p, buffer, len + 1); - *location = p; + snprintf(buffer, sizeof(buffer), + "%s%s%s%s%s", + place, + city ? ", " : "", + city ? city : "", + country ? ", " : "", + country ? country : ""); + *uuid = get_dive_site_uuid_by_name(buffer); + if (*uuid == 0) + *uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); city = NULL; country = NULL; @@ -1005,7 +1005,7 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf) MATCH("names.buddy", utf8_string, &dive->buddy) || MATCH("name.country", utf8_string, &country) || MATCH("name.city", utf8_string, &city) || - MATCH("name.place", divinglog_place, &dive->location) || + MATCH("name.place", divinglog_place, &dive->dive_site_uuid) || 0; } @@ -1138,12 +1138,64 @@ static void gps_long(char *buffer, struct dive *dive) dive->longitude = parse_degrees(buffer, &end); } -static void gps_location(char *buffer, struct dive *dive) +static void gps_location(char *buffer, struct dive_site *ds) { char *end; - dive->latitude = parse_degrees(buffer, &end); - dive->longitude = parse_degrees(end, &end); + ds->latitude = parse_degrees(buffer, &end); + ds->longitude = parse_degrees(end, &end); +} + +static void gps_in_dive(char *buffer, struct dive *dive) +{ + char *end; + fprintf(stderr, "called gps_in_dive with buffer |%s|\n", buffer); + degrees_t latitude = parse_degrees(buffer, &end); + degrees_t longitude = parse_degrees(end, &end); + fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + uint32_t uuid = dive->dive_site_uuid; + if (uuid == 0) { + fprintf(stderr, "found no uuid in dive, creating a divesite without name and above GPS\n"); + dive->dive_site_uuid = create_dive_site("", latitude, longitude); + } else { + fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n"); + struct dive_site *ds = get_dive_site_by_uuid(uuid); + if (dive_site_has_gps_location(ds) && + (latitude.udeg != 0 || longitude.udeg != 0) && + (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { + // Houston, we have a problem + fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n", + ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0, + latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); + } else { + fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)"); + ds->latitude = latitude; + ds->longitude = longitude; + } + } +} + +static void add_dive_site(char *buffer, struct dive *dive) +{ + fprintf(stderr, "add_dive_site with name %s\n", buffer); + int size; + size = trimspace(buffer); + if(size) { + if (dive->dive_site_uuid) { + // we have a uuid, let's hope there's no name + struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); + if (!ds) { + fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid); + exit(1); + } + if (!same_string(ds->name, buffer)) { + fprintf(stderr, "dive links to dive site of different name %s / %s\n", ds->name, buffer); + exit(1); + } + } else { + dive->dive_site_uuid = create_dive_site(buffer, (degrees_t){0}, (degrees_t){0}); + } + } } static void gps_picture_location(char *buffer, struct picture *pic) @@ -1173,7 +1225,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) default: break; } - + if (MATCH("divesiteid", hex_value, &dive->dive_site_uuid)) + return; if (MATCH("number", get_index, &dive->number)) return; if (MATCH("tags", divetags, &dive->tag_list)) @@ -1203,9 +1256,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) return; if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end)) return; - if (MATCH("gps", gps_location, dive)) + if (MATCH("gps", gps_in_dive, dive)) return; - if (MATCH("Place", gps_location, dive)) + if (MATCH("Place", gps_in_dive, dive)) return; if (MATCH("latitude", gps_lat, dive)) return; @@ -1219,9 +1272,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf) return; if (MATCH("lon", gps_long, dive)) return; - if (MATCH("location", utf8_string, &dive->location)) + if (MATCH("location", add_dive_site, dive)) return; - if (MATCH("name.dive", utf8_string, &dive->location)) + if (MATCH("name.dive", add_dive_site, dive)) return; if (MATCH("suit", utf8_string, &dive->suit)) return; @@ -1290,6 +1343,27 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char * nonmatch("trip", name, buf); } +/* We're processing a divesite entry - try to fill the components */ +static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, char *buf) +{ + start_match("divesite", name, buf); + + struct dive_site *ds = *ds_p; + + if (MATCH("uuid", hex_value, &ds->uuid)) + return; + if (MATCH("name", utf8_string, &ds->name)) + return; + if (MATCH("description", utf8_string, &ds->description)) + return; + if (MATCH("notes", utf8_string, &ds->notes)) + return; + if (MATCH("gps", gps_location, ds)) + return; + + nonmatch("divesite", name, buf); +} + /* * While in some formats file boundaries are dive boundaries, in many * others (as for example in our native format) there are @@ -1305,7 +1379,7 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char * static bool is_dive(void) { return (cur_dive && - (cur_dive->location || cur_dive->when || cur_dive->dc.samples)); + (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples)); } static void reset_dc_info(struct divecomputer *dc) @@ -1349,6 +1423,32 @@ static void dc_settings_end(void) reset_dc_settings(); } +static void dive_site_start(void) +{ + if (cur_dive_site) + return; + cur_dive_site = calloc(1, sizeof(struct dive_site)); + fprintf(stderr, "allocated cur_dive_site\n"); +} + +static void dive_site_end(void) +{ + fprintf(stderr, "done with dive_site\n"); + if (!cur_dive_site) + return; + if (cur_dive_site->uuid) { + uint32_t tmp = create_dive_site(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude); + struct dive_site *ds = get_dive_site_by_uuid(tmp); + ds->uuid = cur_dive_site->uuid; + ds->notes = cur_dive_site->notes; + ds->description = cur_dive_site->description; + } + free(cur_dive_site); + cur_dive_site = NULL; +} + +// now we need to add the code to parse the parts of the divesite enry + static void dive_start(void) { if (cur_dive) @@ -1538,6 +1638,10 @@ static void entry(const char *name, char *buf) try_to_match_autogroup(name, buf); return; } + if (cur_dive_site) { + try_to_fill_dive_site(&cur_dive_site, name, buf); + return; + } if (!cur_event.deleted) { try_to_fill_event(name, buf); return; @@ -1666,6 +1770,7 @@ static struct nesting { } nesting[] = { { "divecomputerid", dc_settings_start, dc_settings_end }, { "settings", settings_start, settings_end }, + { "site", dive_site_start, dive_site_end }, { "dive", dive_start, dive_end }, { "Dive", dive_start, dive_end }, { "trip", trip_start, trip_end }, @@ -2291,7 +2396,7 @@ extern int shearwater_dive(void *param, int columns, char **data, char **column) cur_dive->when = (time_t)(atol(data[1])); if (data[2]) - utf8_string(data[2], &cur_dive->location); + add_dive_site(data[2], cur_dive); if (data[3]) utf8_string(data[3], &cur_dive->buddy); if (data[4]) @@ -2388,19 +2493,20 @@ extern int cobalt_visibility(void *handle, int columns, char **data, char **colu extern int cobalt_location(void *handle, int columns, char **data, char **column) { + static char *location = NULL; if (data[0]) { - if (cur_dive->location) { - char *tmp = malloc(strlen(cur_dive->location) + strlen(data[0]) + 4); + if (location) { + char *tmp = malloc(strlen(location) + strlen(data[0]) + 4); if (!tmp) return -1; - sprintf(tmp, "%s / %s", cur_dive->location, data[0]); - free(cur_dive->location); - cur_dive->location = tmp; + sprintf(tmp, "%s / %s", location, data[0]); + free(location); + location = NULL; + cur_dive->dive_site_uuid = create_dive_site(tmp, (degrees_t){0}, (degrees_t){0}); } else { - utf8_string(data[0], &cur_dive->location); + location = strdup(data[0]); } } - return 0; } diff --git a/save-xml.c b/save-xml.c index 053b8fc96..dad57dc9b 100644 --- a/save-xml.c +++ b/save-xml.c @@ -110,38 +110,8 @@ static void save_salinity(struct membuffer *b, struct divecomputer *dc) put_string(b, " />\n"); } -static void show_location(struct membuffer *b, struct dive *dive) -{ - degrees_t latitude = dive->latitude; - degrees_t longitude = dive->longitude; - - /* Should we write a location tag at all? */ - if (!(latitude.udeg || longitude.udeg) && !dive->location) - return; - - put_string(b, " <location"); - - /* - * Ok, theoretically I guess you could dive at - * exactly 0,0. But we don't support that. So - * if you do, just fudge it a bit, and say that - * you dove a few meters away. - */ - if (latitude.udeg || longitude.udeg) { - put_degrees(b, latitude, " gps='", " "); - put_degrees(b, longitude, "", "'"); - } - - /* Do we have a location name or should we write a empty tag? */ - if (dive->location && dive->location[0] != '\0') - show_utf8(b, dive->location, ">", "</location>\n", 0); - else - put_string(b, "/>\n"); -} - static void save_overview(struct membuffer *b, struct dive *dive) { - show_location(b, dive); show_utf8(b, dive->divemaster, " <divemaster>", "</divemaster>\n", 0); show_utf8(b, dive->buddy, " <buddy>", "</buddy>\n", 0); show_utf8(b, dive->notes, " <notes>", "</notes>\n", 0); @@ -424,7 +394,8 @@ void save_one_dive(struct membuffer *b, struct dive *dive) if (dive->visibility) put_format(b, " visibility='%d'", dive->visibility); save_tags(b, dive->tag_list); - + if (dive->dive_site_uuid) + put_format(b, " divesiteid='%8x'", dive->dive_site_uuid); show_date(b, dive->when); put_format(b, " duration='%u:%02u min'>\n", FRACTION(dive->dc.duration.seconds, 60)); @@ -507,7 +478,7 @@ static void save_one_device(void *_f, const char *model, uint32_t deviceid, put_format(b, "/>\n"); } -#define VERSION 2 +#define VERSION 3 int save_dives(const char *filename) { @@ -529,8 +500,23 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) call_for_each_dc(b, save_one_device); if (autogroup) put_format(b, " <autogroup state='1' />\n"); - put_format(b, "</settings>\n<dives>\n"); - + put_format(b, "</settings>\n"); + + /* save the dive sites */ + put_format(b, "<divesites>\n"); + for (i = 0; i < dive_site_table.nr; i++) { + struct dive_site *ds = get_dive_site(i); + put_format(b, "<site uuid='%8x' ", ds->uuid); + show_utf8(b, ds->name, " name='", "'", 1); + if (ds->latitude.udeg || ds->longitude.udeg) { + put_degrees(b, ds->latitude, " gps='", " "); + put_degrees(b, ds->longitude, "", "'"); + } + show_utf8(b, ds->description, " description='", "'", 1); + show_utf8(b, ds->notes, " notes='", "'", 1); + put_format(b, "/>\n"); + } + put_format(b, "</divesites>\n<dives>\n"); for (trip = dive_trip_list; trip != NULL; trip = trip->next) trip->index = 0; |