summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dive.h7
-rw-r--r--libdivecomputer.c4
-rw-r--r--parse-xml.c71
-rw-r--r--save-xml.c52
4 files changed, 115 insertions, 19 deletions
diff --git a/dive.h b/dive.h
index 95f977da0..2e7841b45 100644
--- a/dive.h
+++ b/dive.h
@@ -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");
}