summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2017-04-29 16:21:41 -0700
committerGravatar Dirk Hohndel <dirk@hohndel.org>2017-04-30 12:38:09 -0700
commit9084bbae578b3996d8e8c7adb74ef9bb25da6720 (patch)
treee3772b6d00c8afdf2127d6165f2e7deeeb393087
parent95bff0daaf0160fa39e55ce3d9258f43c397865c (diff)
downloadsubsurface-9084bbae578b3996d8e8c7adb74ef9bb25da6720.tar.gz
Fix event merging when interleaving dives
The core to avoid adding redundant gas switch events was completely buggered, and caused the result list to be corrupted if it ever triggered. This should fix it. Fixes: b5de08b7 ("No gas change event on merging dives with same gas") Reported-by: Jan Mulder <jlmulder@xs4all.nl> Cc: Miika Turkia <miika.turkia@gmail.com> Cc: Dirk Hohndel <dirk@hohndel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--core/dive.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/core/dive.c b/core/dive.c
index b4a015c1f..e71249413 100644
--- a/core/dive.c
+++ b/core/dive.c
@@ -1783,6 +1783,7 @@ static void merge_events(struct divecomputer *res, struct divecomputer *src1, st
{
struct event *a, *b;
struct event **p = &res->events;
+ struct event *last_gas = NULL;
/* Always use positive offsets */
if (offset < 0) {
@@ -1804,6 +1805,8 @@ static void merge_events(struct divecomputer *res, struct divecomputer *src1, st
while (a || b) {
int s;
+ struct event *pick;
+
if (!b) {
*p = a;
break;
@@ -1814,32 +1817,34 @@ static void merge_events(struct divecomputer *res, struct divecomputer *src1, st
}
s = sort_event(a, b);
- /* No gas change event when continuing with same gas */
- if (same_gas(a, b)) {
- if (s > 0) {
- p = &b->next;
- b = b->next;
- } else {
- p = &a->next;
- a = a->next;
- }
+ /* Identical events? Just skip one of them (we pick a) */
+ if (!s) {
+ a = a->next;
continue;
}
- /* Pick b */
- if (s > 0) {
- *p = b;
- p = &b->next;
+ /* Otherwise, pick the one that sorts first */
+ if (s < 0) {
+ pick = a;
+ a = a->next;
+ } else {
+ pick = b;
b = b->next;
- continue;
}
- /* Pick 'a' or neither */
- if (s < 0) {
- *p = a;
- p = &a->next;
+
+ /*
+ * If that's a gas-change that matches the previous
+ * gas change, we'll just skip it
+ */
+ if (event_is_gaschange(pick)) {
+ if (last_gas && same_gas(pick, last_gas))
+ continue;
+ last_gas = pick;
}
- a = a->next;
- continue;
+
+ /* Add it to the target list */
+ *p = pick;
+ p = &pick->next;
}
}