diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-29 16:21:41 -0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2017-04-30 12:38:09 -0700 |
commit | 9084bbae578b3996d8e8c7adb74ef9bb25da6720 (patch) | |
tree | e3772b6d00c8afdf2127d6165f2e7deeeb393087 | |
parent | 95bff0daaf0160fa39e55ce3d9258f43c397865c (diff) | |
download | subsurface-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.c | 45 |
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; } } |