diff options
author | Berthold Stoeger <bstoeger@mail.tuwien.ac.at> | 2018-08-12 22:47:07 -0400 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2018-10-11 16:22:27 -0700 |
commit | 8c2383b4952fa22d41745d29484462ed6a67112b (patch) | |
tree | cca6aa6c81610726770f5a096c887305df62536f | |
parent | 1afd295c413dad73293aac580ee854ea90f8fbd3 (diff) | |
download | subsurface-8c2383b4952fa22d41745d29484462ed6a67112b.tar.gz |
Undo: don't modify source-dives on merge
For undo, it is crucial that commands don't modify existing dives.
Unfortunately, dive merging would write into the data-structures
of the to-be-merged dives. To prevent it from doing so, make the
input dives const-pointers.
This led to a whole cascade of functions that had to take const
and significant churn.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r-- | core/dive.c | 408 | ||||
-rw-r--r-- | core/dive.h | 2 |
2 files changed, 258 insertions, 152 deletions
diff --git a/core/dive.c b/core/dive.c index 48547182c..d643dec22 100644 --- a/core/dive.c +++ b/core/dive.c @@ -488,6 +488,18 @@ static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc) copy_events(sdc, ddc); } +static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, const int mapping[]); + +/* copy dive computer and renumber the cylinders */ +static void copy_dc_renumber(struct dive *d, const struct divecomputer *sdc, struct divecomputer *ddc, const int cylinders_map[]) +{ + *ddc = *sdc; + ddc->model = copy_string(sdc->model); + copy_samples(sdc, ddc); + copy_events(sdc, ddc); + dc_cylinder_renumber(d, ddc, cylinders_map); +} + /* copy an element in a list of pictures */ static void copy_pl(struct picture *sp, struct picture *dp) { @@ -1389,12 +1401,15 @@ static void fixup_airtemp(struct dive *dive) dive->airtemp.mkelvin = dc_airtemp(&dive->dc); } -/* zero out the airtemp in the dive structure if it was just created by - * running fixup on the dive. keep it if it had been edited by hand */ -static void un_fixup_airtemp(struct dive *a) +/* if the air temperature in the dive data is redundant to the one in its + * first divecomputer (i.e., it was added by running fixup on the dive) + * return 0, otherwise return the air temperature given in the dive */ +static temperature_t un_fixup_airtemp(const struct dive *a) { + temperature_t res = a->airtemp; if (a->airtemp.mkelvin && a->airtemp.mkelvin == dc_airtemp(&a->dc)) - a->airtemp.mkelvin = 0; + res.mkelvin = 0; + return res; } /* @@ -1837,7 +1852,7 @@ struct sample *add_sample(const struct sample *sample, int time, struct divecomp * that the time in between the dives is at the surface, not some "last * sample that happened to be at a depth of 1.2m". */ -static void merge_one_sample(struct sample *sample, int time, struct divecomputer *dc) +static void merge_one_sample(const struct sample *sample, int time, struct divecomputer *dc) { int last = dc->samples - 1; if (last >= 0) { @@ -1863,11 +1878,16 @@ static void merge_one_sample(struct sample *sample, int time, struct divecompute add_sample(sample, time, dc); } +static void renumber_last_sample(struct divecomputer *dc, const int mapping[]); +static void sample_renumber(struct sample *s, int i, const int mapping[]); /* * Merge samples. Dive 'a' is "offset" seconds before Dive 'b' */ -static void merge_samples(struct divecomputer *res, struct divecomputer *a, struct divecomputer *b, int offset) +static void merge_samples(struct divecomputer *res, + const struct divecomputer *a, const struct divecomputer *b, + const int *cylinders_map_a, const int *cylinders_map_b, + int offset) { int asamples = a->samples; int bsamples = b->samples; @@ -1882,14 +1902,19 @@ static void merge_samples(struct divecomputer *res, struct divecomputer *a, stru * the reverse offset. */ if (offset < 0) { + const int *cylinders_map_tmp; offset = -offset; asamples = bsamples; bsamples = a->samples; as = bs; bs = a->sample; + cylinders_map_tmp = cylinders_map_a; + cylinders_map_a = cylinders_map_b; + cylinders_map_b = cylinders_map_tmp; } for (;;) { + int j; int at, bt; struct sample sample = { .bearing.degrees = -1, .ndl.seconds = -1 }; @@ -1907,6 +1932,7 @@ static void merge_samples(struct divecomputer *res, struct divecomputer *a, stru if (bt < 0) { add_sample_a: merge_one_sample(as, at, res); + renumber_last_sample(res, cylinders_map_a); as++; asamples--; continue; @@ -1916,6 +1942,7 @@ static void merge_samples(struct divecomputer *res, struct divecomputer *a, stru if (at < 0) { add_sample_b: merge_one_sample(bs, bt, res); + renumber_last_sample(res, cylinders_map_b); bs++; bsamples--; continue; @@ -1928,18 +1955,23 @@ static void merge_samples(struct divecomputer *res, struct divecomputer *a, stru /* same-time sample: add a merged sample. Take the non-zero ones */ sample = *bs; + sample_renumber(&sample, 0, cylinders_map_b); if (as->depth.mm) sample.depth = as->depth; if (as->temperature.mkelvin) sample.temperature = as->temperature; - if (as->pressure[0].mbar) - sample.pressure[0] = as->pressure[0]; - if (as->sensor[0]) - sample.sensor[0] = as->sensor[0]; - if (as->pressure[1].mbar) - sample.pressure[1] = as->pressure[1]; - if (as->sensor[1]) - sample.sensor[1] = as->sensor[1]; + for (j = 0; j < MAX_SENSORS; ++j) { + int sensor_id; + + sensor_id = cylinders_map_a[as->sensor[j]]; + if (sensor_id < 0) + continue; + + if (as->pressure[j].mbar) + sample.pressure[j] = as->pressure[j]; + if (as->sensor[j]) + sample.sensor[j] = sensor_id; + } if (as->cns) sample.cns = as->cns; if (as->setpoint.mbar) @@ -1980,16 +2012,17 @@ static char *merge_text(const char *a, const char *b, const char *sep) return res; } -#define SORT(a, b, field) \ - if (a->field != b->field) \ - return a->field < b->field ? -1 : 1 +#define SORT(a, b) \ + if (a != b) \ + return a < b ? -1 : 1 +#define SORT_FIELD(a, b, field) SORT(a->field, b->field) -static int sort_event(const struct event *a, const struct event *b) +static int sort_event(const struct event *a, const struct event *b, int time_a, int time_b) { - SORT(a, b, time.seconds); - SORT(a, b, type); - SORT(a, b, flags); - SORT(a, b, value); + SORT(time_a, time_b); + SORT_FIELD(a, b, type); + SORT_FIELD(a, b, flags); + SORT_FIELD(a, b, value); return strcmp(a->name, b->name); } @@ -2002,43 +2035,54 @@ static int same_gas(const struct event *a, const struct event *b) return false; } -static void merge_events(struct divecomputer *res, struct divecomputer *src1, struct divecomputer *src2, int offset) +static void event_renumber(struct event *ev, const int mapping[]); +static void add_initial_gaschange(struct dive *dive, struct divecomputer *dc, int offset, int idx); + +static void merge_events(struct dive *d, struct divecomputer *res, + const struct divecomputer *src1, const struct divecomputer *src2, + const int *cylinders_map1, const int *cylinders_map2, + int offset) { - struct event *a, *b; + const struct event *a, *b; struct event **p = &res->events; - struct event *last_gas = NULL; + const struct event *last_gas = NULL; /* Always use positive offsets */ if (offset < 0) { - struct divecomputer *tmp; + const struct divecomputer *tmp; + const int *cylinders_map_tmp; offset = -offset; tmp = src1; src1 = src2; src2 = tmp; + + cylinders_map_tmp = cylinders_map1; + cylinders_map1 = cylinders_map2; + cylinders_map2 = cylinders_map_tmp; } a = src1->events; b = src2->events; - while (b) { - b->time.seconds += offset; - b = b->next; - } - b = src2->events; while (a || b) { int s; - struct event *pick; + const struct event *pick; + const int *cylinders_map; + int event_offset; if (!b) { - *p = a; + *p = clone_event(a); + event_renumber(*p, cylinders_map1); break; } if (!a) { - *p = b; + *p = clone_event(b); + (*p)->time.seconds += offset; + event_renumber(*p, cylinders_map2); break; } - s = sort_event(a, b); + s = sort_event(a, b, a->time.seconds, b->time.seconds + offset); /* Identical events? Just skip one of them (we pick a) */ if (!s) { @@ -2050,9 +2094,13 @@ static void merge_events(struct divecomputer *res, struct divecomputer *src1, st if (s < 0) { pick = a; a = a->next; + event_offset = 0; + cylinders_map = cylinders_map1; } else { pick = b; b = b->next; + event_offset = offset; + cylinders_map = cylinders_map2; } /* @@ -2066,9 +2114,17 @@ static void merge_events(struct divecomputer *res, struct divecomputer *src1, st } /* Add it to the target list */ - *p = pick; - p = &pick->next; + *p = clone_event(pick); + (*p)->time.seconds += event_offset; + event_renumber(*p, cylinders_map); + p = &(*p)->next; } + + /* If the initial cylinder of a divecomputer was remapped, add a gas change event to that cylinder */ + if (cylinders_map1[0] > 0) + add_initial_gaschange(d, res, 0, cylinders_map1[0]); + if (cylinders_map2[0] > 0) + add_initial_gaschange(d, res, offset, cylinders_map2[0]); } static void merge_weightsystem_info(weightsystem_t *res, const weightsystem_t *a, const weightsystem_t *b) @@ -2151,58 +2207,81 @@ extern void fill_pressures(struct gas_pressures *pressures, const double amb_pre } /* Force an initial gaschange event to the (old) gas #0 */ -static void add_initial_gaschange(struct dive *dive, struct divecomputer *dc) +static void add_initial_gaschange(struct dive *dive, struct divecomputer *dc, int offset, int idx) { - const struct event *ev = get_next_event(dc->events, "gaschange"); - - if (ev && ev->time.seconds < 30) - return; + /* if there is a gaschange event up to 30 sec after the initial event, + * refrain from adding the initial event */ + const struct event *ev = dc->events; + while(ev && (ev = get_next_event(ev, "gaschange")) != NULL) { + if (ev->time.seconds > offset + 30) + break; + else if (ev->time.seconds > offset) + return; + ev = ev->next; + } /* Old starting gas mix */ - add_gas_switch_event(dive, dc, 0, 0); + add_gas_switch_event(dive, dc, offset, idx); } -static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, int mapping[]) +static void sample_renumber(struct sample *s, int i, const int mapping[]) { - int i; - struct event *ev; - - /* Did the first gas get remapped? Add gas switch event */ - if (mapping[0] > 0) - add_initial_gaschange(dive, dc); + int j; - /* Remap or delete the sensor indexes */ - for (i = 0; i < dc->samples; i++) { - struct sample *s = dc->sample + i; - int j; + for (j = 0; j < MAX_SENSORS; j++) { + int sensor; - for (j = 0; j < MAX_SENSORS; j++) { - int sensor; - - sensor = mapping[s->sensor[j]]; - if (sensor == -1) { - // Remove sensor and gas pressure info - if (i == 0) { - s->sensor[j] = 0; - s->pressure[j].mbar = 0; - } else { - s->sensor[j] = s[-1].sensor[j]; - s->pressure[j].mbar = s[-1].pressure[j].mbar; - } + sensor = mapping[s->sensor[j]]; + if (sensor == -1) { + // Remove sensor and gas pressure info + if (i == 0) { + s->sensor[j] = 0; + s->pressure[j].mbar = 0; } else { - s->sensor[j] = sensor; + s->sensor[j] = s[-1].sensor[j]; + s->pressure[j].mbar = s[-1].pressure[j].mbar; } + } else { + s->sensor[j] = sensor; } } +} + +static void renumber_last_sample(struct divecomputer *dc, const int mapping[]) +{ + int idx; + + if (dc->samples <= 0) + return; + idx = dc->samples - 1; + sample_renumber(dc->sample + idx, idx, mapping); +} + +static void event_renumber(struct event *ev, const int mapping[]) +{ + if (!event_is_gaschange(ev)) + return; + if (ev->gas.index < 0) + return; + ev->gas.index = mapping[ev->gas.index]; +} + +static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, const int mapping[]) +{ + int i; + struct event *ev; + + /* Remap or delete the sensor indexes */ + for (i = 0; i < dc->samples; i++) + sample_renumber(dc->sample + i, i, mapping); /* Remap the gas change indexes */ - for (ev = dc->events; ev; ev = ev->next) { - if (!event_is_gaschange(ev)) - continue; - if (ev->gas.index < 0) - continue; - ev->gas.index = mapping[ev->gas.index]; - } + for (ev = dc->events; ev; ev = ev->next) + event_renumber(ev, mapping); + + /* If the initial cylinder of a dive was remapped, add a gas change event to that cylinder */ + if (mapping[0] > 0) + add_initial_gaschange(dive, dc, 0, mapping[0]); } /* @@ -2308,27 +2387,60 @@ static int find_unused_cylinder(unsigned int used_map) } /* + * Copy a single cylinder + */ +static void copy_cylinder(const cylinder_t *s, cylinder_t *d) +{ + d->type.size.mliter = s->type.size.mliter; + d->type.workingpressure.mbar = s->type.workingpressure.mbar; + d->type.description = copy_string(s->type.description); + d->gasmix = s->gasmix; + d->start.mbar = s->start.mbar; + d->end.mbar = s->end.mbar; + d->sample_start.mbar = s->sample_start.mbar; + d->sample_end.mbar = s->sample_end.mbar; + d->depth = s->depth; + d->manually_added = s->manually_added; + d->gas_used.mliter = s->gas_used.mliter; + d->deco_gas_used.mliter = s->deco_gas_used.mliter; + d->bestmix_o2 = s->bestmix_o2; + d->bestmix_he = s->bestmix_he; +} + +/* * We matched things up so that they have the same gasmix and * use, but we might want to fill in any missing cylinder details * in 'a' if we had it from 'b'. */ -static void merge_one_cylinder(cylinder_t *a, cylinder_t *b) -{ - if (!a->type.size.mliter) - a->type.size.mliter = b->type.size.mliter; - if (!a->type.workingpressure.mbar) - a->type.workingpressure.mbar = b->type.workingpressure.mbar; - if (!a->type.description && b->type.description) - a->type.description = strdup(b->type.description); - if (!a->start.mbar) - a->start.mbar = b->start.mbar; - if (!a->end.mbar) - a->end.mbar = b->end.mbar; +static void merge_one_cylinder(cylinder_t *res, const cylinder_t *a, const cylinder_t *b) +{ + res->type.size.mliter = a->type.size.mliter ? + a->type.size.mliter : b->type.size.mliter; + res->type.workingpressure.mbar = a->type.workingpressure.mbar ? + a->type.workingpressure.mbar : b->type.workingpressure.mbar; + res->type.description = !empty_string(a->type.description) ? + copy_string(a->type.description) : copy_string(b->type.description); + res->gasmix = a->gasmix; + res->start.mbar = a->start.mbar ? + a->start.mbar : b->start.mbar; + res->end.mbar = a->end.mbar ? + a->end.mbar : b->end.mbar; if (a->sample_start.mbar && b->sample_start.mbar) - a->sample_start.mbar = a->sample_start.mbar > b->sample_start.mbar ? a->sample_start.mbar : b->sample_start.mbar; + res->sample_start.mbar = a->sample_start.mbar > b->sample_start.mbar ? a->sample_start.mbar : b->sample_start.mbar; + else + res->sample_start.mbar = 0; if (a->sample_end.mbar && b->sample_end.mbar) - a->sample_end.mbar = a->sample_end.mbar < b->sample_end.mbar ? a->sample_end.mbar : b->sample_end.mbar; + res->sample_end.mbar = a->sample_end.mbar < b->sample_end.mbar ? a->sample_end.mbar : b->sample_end.mbar; + else + res->sample_end.mbar = 0; + + res->depth = a->depth; + res->manually_added = a->manually_added; + res->gas_used.mliter = a->gas_used.mliter + b->gas_used.mliter; + res->deco_gas_used.mliter = a->deco_gas_used.mliter + b->deco_gas_used.mliter; + res->bestmix_o2 = a->bestmix_o2 && b->bestmix_o2; + res->bestmix_he = a->bestmix_he && b->bestmix_he; } /* @@ -2338,13 +2450,19 @@ static void merge_one_cylinder(cylinder_t *a, cylinder_t *b) * Logic: take all the cylinder information from the preferred dive ('a'), and * then try to match each of the cylinders in the other dive by the gasmix that * is the best match and hasn't been used yet. + * + * For each dive, a cylinder-renumbering table is returned. Currently, only + * cylinders of dive 'b' are renumbered. */ -static void merge_cylinders(struct dive *res, struct dive *a, struct dive *b) +static void merge_cylinders(struct dive *res, const struct dive *a, const struct dive *b, + int mapping_a[], int mapping_b[]) { - int i, renumber = 0; - int mapping[MAX_CYLINDERS]; + int i; unsigned int used_in_a = 0, used_in_b = 0, matched = 0; + /* First, clear all cylinders in destination */ + memset(res->cylinder, 0, sizeof(res->cylinder)); + /* Calculate usage map of cylinders */ for (i = 0; i < MAX_CYLINDERS; i++) { if (!cylinder_none(a->cylinder+i) || is_cylinder_used(a, i)) @@ -2357,7 +2475,8 @@ static void merge_cylinders(struct dive *res, struct dive *a, struct dive *b) for (i = 0; i < MAX_CYLINDERS; i++) { int j; - mapping[i] = -1; + mapping_a[i] = i; + mapping_b[i] = -1; if (!(used_in_b & (1u << i))) continue; @@ -2377,11 +2496,15 @@ static void merge_cylinders(struct dive *res, struct dive *a, struct dive *b) * * - mark 'b' as needing renumbering if the index changed */ - merge_one_cylinder(a->cylinder + j, b->cylinder + i); - mapping[i] = j; + merge_one_cylinder(res->cylinder + j, a->cylinder + j, b->cylinder + i); + mapping_b[i] = j; matched |= 1u << j; - if (j != i) - renumber = 1; + } + + /* Now copy all the used cylinders from 'a' which are used, but have not been matched */ + for (i = 0; i < MAX_CYLINDERS; i++) { + if (used_in_a & (1u << i) && !(matched & (1u << i))) + copy_cylinder(a->cylinder + i, res->cylinder + i); } /* @@ -2390,10 +2513,6 @@ static void merge_cylinders(struct dive *res, struct dive *a, struct dive *b) */ used_in_a |= matched; - /* Now copy all the cylinder info raw from 'a' (whether used/matched or not) */ - memcpy(res->cylinder, a->cylinder, sizeof(res->cylinder)); - memset(a->cylinder, 0, sizeof(a->cylinder)); - /* * Go back to 'b' and remap any remaining cylinders that didn't * match completely. @@ -2402,7 +2521,7 @@ static void merge_cylinders(struct dive *res, struct dive *a, struct dive *b) int j; /* Already remapped, or not interesting? */ - if (mapping[i] >= 0) + if (mapping_b[i] >= 0) continue; if (!(used_in_b & (1u << i))) continue; @@ -2411,32 +2530,24 @@ static void merge_cylinders(struct dive *res, struct dive *a, struct dive *b) if (j < 0) continue; - res->cylinder[j] = b->cylinder[i]; - memset(b->cylinder+i, 0, sizeof(cylinder_t)); - mapping[i] = j; + copy_cylinder(b->cylinder + i, res->cylinder + j); + mapping_b[i] = j; used_in_a |= 1u << j; - if (i != j) - renumber = 1; } - - if (renumber) - cylinder_renumber(b, mapping); } -static void merge_equipment(struct dive *res, struct dive *a, struct dive *b) +static void merge_equipment(struct dive *res, const struct dive *a, const struct dive *b) { int i; - - merge_cylinders(res, a, b); for (i = 0; i < MAX_WEIGHTSYSTEMS; i++) merge_weightsystem_info(res->weightsystem + i, a->weightsystem + i, b->weightsystem + i); } -static void merge_temperatures(struct dive *res, struct dive *a, struct dive *b) +static void merge_temperatures(struct dive *res, const struct dive *a, const struct dive *b) { - un_fixup_airtemp(a); - un_fixup_airtemp(b); - MERGE_NONZERO(res, a, b, airtemp.mkelvin); + temperature_t airtemp_a = un_fixup_airtemp(a); + temperature_t airtemp_b = un_fixup_airtemp(b); + res->airtemp = airtemp_a.mkelvin ? airtemp_a : airtemp_b; MERGE_NONZERO(res, a, b, watertemp.mkelvin); } @@ -2459,7 +2570,7 @@ static void pick_trip(struct dive *res, const struct dive *pick) /* * Pick a trip for a dive */ -static struct dive *get_preferred_trip(struct dive *a, struct dive *b) +static const struct dive *get_preferred_trip(const struct dive *a, const struct dive *b) { dive_trip_t *atrip, *btrip; @@ -2953,14 +3064,9 @@ static void remove_redundant_dc(struct divecomputer *dc, int prefer_downloaded) } while (dc); } -static void clear_dc(struct divecomputer *dc) +static const struct divecomputer *find_matching_computer(const struct divecomputer *match, const struct divecomputer *list) { - memset(dc, 0, sizeof(*dc)); -} - -static struct divecomputer *find_matching_computer(struct divecomputer *match, struct divecomputer *list) -{ - struct divecomputer *p; + const struct divecomputer *p; while ((p = list) != NULL) { list = list->next; @@ -2990,28 +3096,25 @@ static void copy_dive_computer(struct divecomputer *res, const struct divecomput * to match them up. If we find a matching dive computer, we * merge them. If not, we just take the data from 'a'. */ -static void interleave_dive_computers(struct divecomputer *res, - struct divecomputer *a, struct divecomputer *b, int offset) +static void interleave_dive_computers(struct dive *d, struct divecomputer *res, + const struct divecomputer *a, const struct divecomputer *b, + const int cylinders_map_a[], const int cylinders_map_b[], + int offset) { do { - struct divecomputer *match; + const struct divecomputer *match; copy_dive_computer(res, a); match = find_matching_computer(a, b); if (match) { - merge_events(res, a, match, offset); - merge_samples(res, a, match, offset); + 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); /* Use the diveid of the later dive! */ if (offset > 0) res->diveid = match->diveid; } else { - res->sample = a->sample; - res->samples = a->samples; - res->events = a->events; - a->sample = NULL; - a->samples = 0; - a->events = NULL; + copy_dc_renumber(d, a, res, cylinders_map_a); } a = a->next; if (!a) @@ -3035,30 +3138,29 @@ static void interleave_dive_computers(struct divecomputer *res, * try to throw out old information that *might* be from * that one. */ -static void join_dive_computers(struct divecomputer *res, struct divecomputer *a, struct divecomputer *b, int prefer_downloaded) +static void join_dive_computers(struct dive *d, struct divecomputer *res, + const struct divecomputer *a, const struct divecomputer *b, + const int cylinders_map_a[], const int cylinders_map_b[], + int prefer_downloaded) { struct divecomputer *tmp; if (a->model && !b->model) { - *res = *a; - clear_dc(a); + copy_dc_renumber(d, a, res, cylinders_map_a); return; } if (b->model && !a->model) { - *res = *b; - clear_dc(b); + copy_dc_renumber(d, b, res, cylinders_map_b); return; } - *res = *a; - clear_dc(a); + copy_dc_renumber(d, a, res, cylinders_map_a); tmp = res; while (tmp->next) tmp = tmp->next; tmp->next = calloc(1, sizeof(*tmp)); - *tmp->next = *b; - clear_dc(b); + copy_dc_renumber(d, b, tmp->next, cylinders_map_b); remove_redundant_dc(res, prefer_downloaded); } @@ -3335,10 +3437,12 @@ int count_dives_with_suit(const char *suit) * in the "trip" output paramater. If "trip" is NULL, then the dive will * instead be added to this trip. */ -struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip) +struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip) { struct dive *res = alloc_dive(); - struct dive *preferred_trip; + const struct dive *dl = NULL; + const struct dive *preferred_trip; + int cylinders_map_a[MAX_CYLINDERS], cylinders_map_b[MAX_CYLINDERS]; if (offset) { /* @@ -3352,7 +3456,7 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer } if (same_string(a->dc.model, "planned dive")) { - struct dive *tmp = a; + const struct dive *tmp = a; a = b; b = tmp; } @@ -3373,15 +3477,17 @@ struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer MERGE_NONZERO(res, a, b, visibility); MERGE_NONZERO(res, a, b, picture_list); taglist_merge(&res->tag_list, a->tag_list, b->tag_list); + merge_cylinders(res, a, b, cylinders_map_a, cylinders_map_b); merge_equipment(res, a, b); merge_temperatures(res, a, b); if (prefer_downloaded) { /* If we prefer downloaded, do those first, and get rid of "might be same" computers */ - join_dive_computers(&res->dc, &b->dc, &a->dc, 1); + join_dive_computers(res, &res->dc, &dl->dc, &a->dc, cylinders_map_b, cylinders_map_a, 1); } else if (offset && might_be_same_device(&a->dc, &b->dc)) - interleave_dive_computers(&res->dc, &a->dc, &b->dc, offset); + interleave_dive_computers(res, &res->dc, &a->dc, &b->dc, cylinders_map_a, cylinders_map_b, offset); else - join_dive_computers(&res->dc, &a->dc, &b->dc, 0); + join_dive_computers(res, &res->dc, &a->dc, &b->dc, cylinders_map_a, cylinders_map_b, 0); + /* we take the first dive site, unless it's empty */ if (a->dive_site_uuid && !dive_site_is_empty(get_dive_site_by_uuid(a->dive_site_uuid))) res->dive_site_uuid = a->dive_site_uuid; diff --git a/core/dive.h b/core/dive.h index 48cbaa740..cb832a44d 100644 --- a/core/dive.h +++ b/core/dive.h @@ -573,7 +573,7 @@ extern int split_dive_dont_insert(const struct dive *dive, struct dive **new1, s extern void split_dive(struct dive *); extern int split_dive_at_time_dont_insert(const struct dive *dive, duration_t time, struct dive **new1, struct dive **new2); extern void split_dive_at_time(struct dive *dive, duration_t time); -extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip); +extern struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, bool prefer_downloaded, struct dive_trip **trip); extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded); extern struct event *clone_event(const struct event *src_ev); extern void copy_events(const struct divecomputer *s, struct divecomputer *d); |