diff options
-rw-r--r-- | dive.h | 7 | ||||
-rw-r--r-- | libdivecomputer.c | 4 | ||||
-rw-r--r-- | parse-xml.c | 71 | ||||
-rw-r--r-- | save-xml.c | 52 |
4 files changed, 115 insertions, 19 deletions
@@ -43,6 +43,8 @@ * We don't actually use these all yet, so maybe they'll change, but * I made a number of types as guidelines. */ +typedef gint64 timestamp_t; + typedef struct { int seconds; } duration_t; @@ -238,10 +240,12 @@ struct event { }; struct divecomputer { + timestamp_t when; + const char *vendor, *product; int samples, alloc_samples; struct sample *sample; - struct event *events; + struct divecomputer *next; }; #define MAX_CYLINDERS (8) @@ -249,7 +253,6 @@ struct divecomputer { #define W_IDX_PRIMARY 0 #define W_IDX_SECONDARY 1 -typedef gint64 timestamp_t; typedef enum { TF_NONE, NO_TRIP, IN_TRIP, AUTOGEN_TRIP, ASSIGNED_TRIP, NUM_TRIPFLAGS } tripflag_t; extern const char *tripflag_names[NUM_TRIPFLAGS]; diff --git a/libdivecomputer.c b/libdivecomputer.c index 27ce8458e..48680c7ce 100644 --- a/libdivecomputer.c +++ b/libdivecomputer.c @@ -242,6 +242,8 @@ static int dive_cb(const unsigned char *data, unsigned int size, dc_parser_destroy(parser); return rc; } + dive->dc.vendor = strdup(devdata->vendor); + dive->dc.product = strdup(devdata->product); tm.tm_year = dt.year; tm.tm_mon = dt.month-1; @@ -249,7 +251,7 @@ static int dive_cb(const unsigned char *data, unsigned int size, tm.tm_hour = dt.hour; tm.tm_min = dt.minute; tm.tm_sec = dt.second; - dive->when = utc_mktime(&tm); + dive->when = dive->dc.when = utc_mktime(&tm); // Parse the divetime. dev_info(devdata, _("Dive %d: %s %d %04d"), import_dive_number, diff --git a/parse-xml.c b/parse-xml.c index 0bf5a4a04..98e7fc9e4 100644 --- a/parse-xml.c +++ b/parse-xml.c @@ -157,6 +157,7 @@ const struct units IMPERIAL_units = { /* * Dive info as it is being built up.. */ +static struct divecomputer *cur_dc; static struct dive *cur_dive; static dive_trip_t *cur_trip = NULL; static struct sample *cur_sample; @@ -703,6 +704,25 @@ static void try_to_fill_event(const char *name, char *buf) nonmatch("event", name, buf); } +/* We're in the top-level dive xml. Try to convert whatever value to a dive value */ +static void try_to_fill_dc(struct divecomputer *dc, const char *name, char *buf) +{ + int len = strlen(name); + + start_match("divecomputer", name, buf); + + if (MATCH(".date", divedate, &dc->when)) + return; + if (MATCH(".time", divetime, &dc->when)) + return; + if (MATCH(".vendor", utf8_string, &dc->vendor)) + return; + if (MATCH(".product", utf8_string, &dc->product)) + return; + + nonmatch("divecomputer", name, buf); +} + /* We're in samples - try to convert the random xml value to something useful */ static void try_to_fill_sample(struct sample *sample, const char *name, char *buf) { @@ -1224,6 +1244,7 @@ static void dive_end(void) else record_dive(cur_dive); cur_dive = NULL; + cur_dc = NULL; cur_cylinder_index = 0; cur_ws_index = 0; } @@ -1251,10 +1272,20 @@ static void event_start(void) cur_event.active = 1; } +/* + * If we don't have an explicit dive computer, + * we use the implicit one that every dive has.. + */ +static struct divecomputer *get_dc(void) +{ + return cur_dc ? : &cur_dive->dc; +} + static void event_end(void) { + struct divecomputer *dc = get_dc(); if (cur_event.name && strcmp(cur_event.name, "surface") != 0) - add_event(&cur_dive->dc, cur_event.time.seconds, + add_event(dc, cur_event.time.seconds, cur_event.type, cur_event.flags, cur_event.value, cur_event.name); cur_event.active = 0; @@ -1280,7 +1311,7 @@ static void ws_end(void) static void sample_start(void) { - cur_sample = prepare_sample(&cur_dive->dc); + cur_sample = prepare_sample(get_dc()); } static void sample_end(void) @@ -1288,10 +1319,39 @@ static void sample_end(void) if (!cur_dive) return; - finish_sample(&cur_dive->dc); + finish_sample(get_dc()); cur_sample = NULL; } +static void divecomputer_start(void) +{ + struct divecomputer *dc; + + /* Start from the previous dive computer */ + dc = &cur_dive->dc; + while (dc->next) + dc = dc->next; + + /* Did we already fill that in? */ + if (dc->samples || dc->vendor || dc->product || dc->when) { + struct divecomputer *newdc = calloc(1, sizeof(*newdc)); + if (newdc) { + dc->next = newdc; + dc = newdc; + } + } + + /* .. this is the one we'll use */ + cur_dc = dc; +} + +static void divecomputer_end(void) +{ + if (!cur_dc->when) + cur_dc->when = cur_dive->when; + cur_dc = NULL; +} + static void entry(const char *name, int size, const char *raw) { char *buf = malloc(size+1); @@ -1308,6 +1368,10 @@ static void entry(const char *name, int size, const char *raw) try_to_fill_sample(cur_sample, name, buf); return; } + if (cur_dc) { + try_to_fill_dc(cur_dc, name, buf); + return; + } if (cur_dive) { try_to_fill_dive(cur_dive, name, buf); return; @@ -1447,6 +1511,7 @@ static struct nesting { { "gasmix", cylinder_start, cylinder_end }, { "cylinder", cylinder_start, cylinder_end }, { "weightsystem", ws_start, ws_end }, + { "divecomputer", divecomputer_start, divecomputer_end }, { "P", sample_start, sample_end }, /* Import type recognition */ diff --git a/save-xml.c b/save-xml.c index db7d321bd..a86cbd23c 100644 --- a/save-xml.c +++ b/save-xml.c @@ -323,17 +323,22 @@ static void save_events(FILE *f, struct event *ev) } } -static void save_trip(FILE *f, dive_trip_t *trip) +static void show_date(FILE *f, timestamp_t when) { struct tm tm; - utc_mkdate(trip->when, &tm); + utc_mkdate(when, &tm); - fprintf(f, "<trip"); fprintf(f, " date='%04u-%02u-%02u'", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday); fprintf(f, " time='%02u:%02u:%02u'", tm.tm_hour, tm.tm_min, tm.tm_sec); +} + +static void save_trip(FILE *f, dive_trip_t *trip) +{ + fprintf(f, "<trip"); + show_date(f, trip->when); if (trip->location) show_utf8(f, trip->location, " location=\'","\'", 1); fprintf(f, ">\n"); @@ -341,12 +346,31 @@ static void save_trip(FILE *f, dive_trip_t *trip) show_utf8(f, trip->notes, "<notes>","</notes>\n", 0); } -static void save_dive(FILE *f, struct dive *dive) +static void save_dc(FILE *f, struct dive *dive, struct divecomputer *dc) { int i; - struct tm tm; + const char *post = ""; + + if (dc->when || dc->vendor || dc->product) { + fprintf(f, "<divecomputer"); + if (dc->vendor) + show_utf8(f, dc->vendor, " vendor='", "'", 1); + if (dc->product) + show_utf8(f, dc->product, " product='", "'", 1); + if (dc->when && dc->when != dive->when) + show_date(f, dc->when); + fprintf(f, ">\n"); + post = "</divecomputer>\n"; + } + save_events(f, dc->events); + for (i = 0; i < dc->samples; i++) + save_sample(f, dc->sample+i); + fprintf(f, post); +} - utc_mkdate(dive->when, &tm); +static void save_dive(FILE *f, struct dive *dive) +{ + struct divecomputer *dc; fputs("<dive", f); if (dive->number) @@ -363,18 +387,20 @@ static void save_dive(FILE *f, struct dive *dive) fprintf(f, " rating='%d'", dive->rating); if (dive->visibility) fprintf(f, " visibility='%d'", dive->visibility); - fprintf(f, " date='%04u-%02u-%02u'", - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday); - fprintf(f, " time='%02u:%02u:%02u'", - tm.tm_hour, tm.tm_min, tm.tm_sec); + show_date(f, dive->when); fprintf(f, " duration='%u:%02u min'>\n", FRACTION(dive->duration.seconds, 60)); save_overview(f, dive); save_cylinder_info(f, dive); save_weightsystem_info(f, dive); - save_events(f, dive->dc.events); - for (i = 0; i < dive->dc.samples; i++) - save_sample(f, dive->dc.sample+i); + + /* Save the dive computer data */ + dc = &dive->dc; + do { + save_dc(f, dive, dc); + dc = dc->next; + } while (dc); + fprintf(f, "</dive>\n"); } |