summaryrefslogtreecommitdiffstats
path: root/core/dive.c
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2019-04-06 11:29:42 -1000
committerGravatar bstoeger <32835590+bstoeger@users.noreply.github.com>2019-04-07 20:11:32 +0200
commitbaeb0ba28029d1e9b348ac3933eaedecf3e15e81 (patch)
treeab654369e576d409a8350152f48971eb89c7008e /core/dive.c
parent3184830f513f7928f3d97cfb14b810d80c3bceb4 (diff)
downloadsubsurface-baeb0ba28029d1e9b348ac3933eaedecf3e15e81.tar.gz
Merge extra_data list when merging two dives of the same dive computer
When merging two dives into a longer one, merge the dive computer extra_data list too. We just pick all the extra-data (but avoid entirely duplicate key/value entries). Note that this can cause confusing extra-data, in that both dives migth have things like "battery percentage at beginning/end of dive" keys, and if the values are different, you'll now get *both* of those values, but that's better than randomly just taking one of them. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'core/dive.c')
-rw-r--r--core/dive.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/core/dive.c b/core/dive.c
index 3ee8e5e2c..7e3b30be9 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -2009,6 +2009,58 @@ static void merge_samples(struct divecomputer *res,
}
}
+/*
+ * Does the extradata key/value pair already exist in the
+ * supplied dive computer data?
+ *
+ * This is not hugely efficient (with the whole "do this for
+ * every value you merge" it's O(n**2)) but it's not like we
+ * have very many extra_data entries per dive computer anyway.
+ */
+static bool extra_data_exists(const struct extra_data *ed, const struct divecomputer *dc)
+{
+ const struct extra_data *p;
+
+ for (p = dc->extra_data; p; p = p->next) {
+ if (strcmp(p->key, ed->key))
+ continue;
+ if (strcmp(p->value, ed->value))
+ continue;
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Merge extra_data.
+ *
+ * The extra data from 'a' has already been copied into 'res'. So
+ * we really should just copy over the data from 'b' too.
+ */
+static void merge_extra_data(struct divecomputer *res,
+ const struct divecomputer *a, const struct divecomputer *b)
+{
+ struct extra_data **ed, *src;
+
+ // Find the place to add things in the result
+ ed = &res->extra_data;
+ while (*ed)
+ ed = &(*ed)->next;
+
+ for (src = b->extra_data; src; src = src->next) {
+ if (extra_data_exists(src, a))
+ continue;
+ *ed = malloc(sizeof(struct extra_data));
+ if (!*ed)
+ break;
+ copy_extra_data(src, *ed);
+ ed = &(*ed)->next;
+ }
+
+ // Terminate the result list
+ *ed = NULL;
+}
+
static char *merge_text(const char *a, const char *b, const char *sep)
{
char *res;
@@ -3110,6 +3162,7 @@ static void interleave_dive_computers(struct dive *d, struct divecomputer *res,
if (match) {
merge_events(d, res, a, match, cylinders_map_a, cylinders_map_b, offset);
merge_samples(res, a, match, cylinders_map_a, cylinders_map_b, offset);
+ merge_extra_data(res, a, match);
/* Use the diveid of the later dive! */
if (offset > 0)
res->diveid = match->diveid;