diff --git a/backend-shared/exportfuncs.cpp b/backend-shared/exportfuncs.cpp index 29a9452bf..ec459292a 100644 --- a/backend-shared/exportfuncs.cpp +++ b/backend-shared/exportfuncs.cpp @@ -276,7 +276,6 @@ void export_depths(const char *filename, bool selected_only) { FILE *f; struct dive *dive; - depth_t depth; int i; const char *unit = NULL; @@ -287,12 +286,11 @@ void export_depths(const char *filename, bool selected_only) continue; FOR_EACH_PICTURE (dive) { - int n = dive->dc.samples; - struct sample *s = dive->dc.sample; - depth.mm = 0; - while (--n >= 0 && (int32_t)s->time.seconds <= picture->offset.seconds) { - depth.mm = s->depth.mm; - s++; + depth_t depth; + for (auto &s: dive->dc.samples) { + if ((int32_t)s.time.seconds > picture->offset.seconds) + break; + depth = s.depth; } put_format(&buf, "%s\t%.1f", picture->filename, get_depth_units(depth.mm, NULL, &unit)); put_format(&buf, "%s\n", unit); diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index a4076f1f5..d7312b514 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -308,7 +308,7 @@ void EditDuration::set(struct dive *d, int value) const d->dc.duration.seconds = value; d->duration = d->dc.duration; d->dc.meandepth.mm = 0; - d->dc.samples = 0; + d->dc.samples.clear(); fake_dc(&d->dc); } @@ -328,7 +328,7 @@ void EditDepth::set(struct dive *d, int value) const d->dc.maxdepth.mm = value; d->maxdepth = d->dc.maxdepth; d->dc.meandepth.mm = 0; - d->dc.samples = 0; + d->dc.samples.clear(); fake_dc(&d->dc); } @@ -897,7 +897,7 @@ EditProfile::EditProfile(const dive *source, int dcNr, EditProfileType type, int meandepth = source->meandepth; duration = source->duration; - copy_samples(sdc, &dc); + dc.samples = sdc->samples; copy_events(sdc, &dc); setText(editProfileTypeToString(type, count) + " " + diveNumberOrDate(d)); @@ -919,8 +919,6 @@ void EditProfile::undo() if (!sdc) return; std::swap(sdc->samples, dc.samples); - std::swap(sdc->alloc_samples, dc.alloc_samples); - std::swap(sdc->sample, dc.sample); std::swap(sdc->events, dc.events); std::swap(sdc->maxdepth, dc.maxdepth); std::swap(d->maxdepth, maxdepth); @@ -1339,13 +1337,13 @@ EditSensors::EditSensors(int toCylinderIn, int fromCylinderIn, int dcNr) void EditSensors::mapSensors(int toCyl, int fromCyl) { - for (int i = 0; i < dc->samples; ++i) { + for (auto &sample: dc->samples) { for (int s = 0; s < MAX_SENSORS; ++s) { - if (dc->sample[i].pressure[s].mbar && dc->sample[i].sensor[s] == fromCyl) - dc->sample[i].sensor[s] = toCyl; + if (sample.pressure[s].mbar && sample.sensor[s] == fromCyl) + sample.sensor[s] = toCyl; // In case the cylinder we are moving to has a sensor attached, move it to the other cylinder - else if (dc->sample[i].pressure[s].mbar && dc->sample[i].sensor[s] == toCyl) - dc->sample[i].sensor[s] = fromCyl; + else if (sample.pressure[s].mbar && sample.sensor[s] == toCyl) + sample.sensor[s] = fromCyl; } } emit diveListNotifier.diveComputerEdited(dc); diff --git a/core/cochran.cpp b/core/cochran.cpp index 5af62a8dd..1fbcc92d6 100644 --- a/core/cochran.cpp +++ b/core/cochran.cpp @@ -494,10 +494,6 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log, while (offset + config.sample_size < size) { s = samples + offset; - // Start with an empty sample - sample = prepare_sample(dc); - sample->time.seconds = sample_cnt * profile_period; - // Check for event if (s[0] & 0x80) { cochran_dive_event(dc, s, sample_cnt * profile_period, &in_deco, &deco_ceiling, &deco_time); @@ -505,6 +501,10 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log, continue; } + // Start with an empty sample + sample = prepare_sample(dc); + sample->time.seconds = sample_cnt * profile_period; + // Depth is in every sample depth_sample = (double)(s[0] & 0x3F) / 4 * (s[0] & 0x40 ? -1 : 1); depth += depth_sample; @@ -591,8 +591,6 @@ static void cochran_parse_samples(struct dive *dive, const unsigned char *log, sample->sensor[0] = 0; sample->pressure[0].mbar = lrint(psi * PSI / 100); - finish_sample(dc); - offset += config.sample_size; sample_cnt++; } diff --git a/core/dive.cpp b/core/dive.cpp index 10e98ae6b..f920f5790 100644 --- a/core/dive.cpp +++ b/core/dive.cpp @@ -52,6 +52,9 @@ dive::~dive() free_dive_structures(this); } +dive::dive(dive &&) = default; +dive &dive::operator=(const dive &) = default; + /* * The legacy format for sample pressures has a single pressure * for each sample that can have any sensor, plus a possible @@ -65,16 +68,15 @@ dive::~dive() */ int legacy_format_o2pressures(const struct dive *dive, const struct divecomputer *dc) { - int i, o2sensor; + int o2sensor; o2sensor = (dc->divemode == CCR) ? get_cylinder_idx_by_use(dive, OXYGEN) : -1; - for (i = 0; i < dc->samples; i++) { - const struct sample *s = dc->sample + i; + for (const auto &s: dc->samples) { int seen_pressure = 0, idx; for (idx = 0; idx < MAX_SENSORS; idx++) { - int sensor = s->sensor[idx]; - pressure_t p = s->pressure[idx]; + int sensor = s.sensor[idx]; + pressure_t p = s.pressure[idx]; if (!p.mbar) continue; @@ -180,7 +182,6 @@ int dive_getUniqID() static void copy_dc(const struct divecomputer *sdc, struct divecomputer *ddc) { *ddc = *sdc; - copy_samples(sdc, ddc); copy_events(sdc, ddc); } @@ -515,14 +516,13 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i return; } - if (!dc->samples) + if (dc->samples.empty()) fake_dc(dc); const struct event *ev = get_next_event(dc->events, "gaschange"); std::vector depthtime(dive->cylinders.nr, 0); - for (i = 0; i < dc->samples; i++) { - struct sample *sample = dc->sample + i; - int32_t time = sample->time.seconds; - int depth = sample->depth.mm; + for (auto it = dc->samples.begin(); it != dc->samples.end(); ++it) { + int32_t time = it->time.seconds; + int depth = it->depth.mm; /* Make sure to move the event past 'lasttime' */ while (ev && lasttime >= ev->time.seconds) { @@ -531,13 +531,13 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i } /* Do we need to fake a midway sample at an event? */ - if (ev && time > ev->time.seconds) { + if (ev && it != dc->samples.begin() && time > ev->time.seconds) { int newtime = ev->time.seconds; int newdepth = interpolate(lastdepth, depth, newtime - lasttime, time - lasttime); time = newtime; depth = newdepth; - i--; + --it; } /* We ignore segments at the surface */ if (depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) { @@ -586,7 +586,7 @@ int explicit_first_cylinder(const struct dive *dive, const struct divecomputer * return -1; if (dc) { const struct event *ev = get_next_event(dc->events, "gaschange"); - if (ev && ((dc->sample && ev->time.seconds == dc->sample[0].time.seconds) || ev->time.seconds <= 1)) + if (ev && ((!dc->samples.empty() && ev->time.seconds == dc->samples[0].time.seconds) || ev->time.seconds <= 1)) res = get_cylinder_index(dive, ev); else if (dc->divemode == CCR) res = std::max(get_cylinder_idx_by_use(dive, DILUENT), res); @@ -618,15 +618,15 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc) struct gasmix gasmix = get_gasmix_from_event(dive, ev); const struct event *next = get_next_event(ev, "gaschange"); - for (int i = 0; i < dc->samples; i++) { - if (next && dc->sample[i].time.seconds >= next->time.seconds) { + for (auto &sample: dc->samples) { + if (next && sample.time.seconds >= next->time.seconds) { ev = next; gasmix = get_gasmix_from_event(dive, ev); next = get_next_event(ev, "gaschange"); } - gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(dc->sample[i].depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode); - if (abs(dc->sample[i].setpoint.mbar - (int)(1000 * pressures.o2)) <= 50) - dc->sample[i].setpoint.mbar = 0; + gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(sample.depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode); + if (abs(sample.setpoint.mbar - (int)(1000 * pressures.o2)) <= 50) + sample.setpoint.mbar = 0; } } @@ -906,16 +906,14 @@ static void fixup_dc_events(struct divecomputer *dc) static int interpolate_depth(struct divecomputer *dc, int idx, int lastdepth, int lasttime, int now) { - int i; int nextdepth = lastdepth; int nexttime = now; - for (i = idx+1; i < dc->samples; i++) { - struct sample *sample = dc->sample + i; - if (sample->depth.mm < 0) + for (auto it = dc->samples.begin() + idx; it != dc->samples.end(); ++it) { + if (it->depth.mm < 0) continue; - nextdepth = sample->depth.mm; - nexttime = sample->time.seconds; + nextdepth = it->depth.mm; + nexttime = it->time.seconds; break; } return interpolate(lastdepth, nextdepth, now-lasttime, nexttime-lasttime); @@ -923,18 +921,16 @@ static int interpolate_depth(struct divecomputer *dc, int idx, int lastdepth, in static void fixup_dc_depths(struct dive *dive, struct divecomputer *dc) { - int i; int maxdepth = dc->maxdepth.mm; int lasttime = 0, lastdepth = 0; - for (i = 0; i < dc->samples; i++) { - struct sample *sample = dc->sample + i; - int time = sample->time.seconds; - int depth = sample->depth.mm; + for (const auto [idx, sample]: enumerated_range(dc->samples)) { + int time = sample.time.seconds; + int depth = sample.depth.mm; - if (depth < 0) { - depth = interpolate_depth(dc, i, lastdepth, lasttime, time); - sample->depth.mm = depth; + if (depth < 0 && idx + 2 < static_cast(dc->samples.size())) { + depth = interpolate_depth(dc, idx, lastdepth, lasttime, time); + sample.depth.mm = depth; } if (depth > SURFACE_THRESHOLD) { @@ -944,8 +940,8 @@ static void fixup_dc_depths(struct dive *dive, struct divecomputer *dc) lastdepth = depth; lasttime = time; - if (sample->cns > dive->maxcns) - dive->maxcns = sample->cns; + if (sample.cns > dive->maxcns) + dive->maxcns = sample.cns; } update_depth(&dc->maxdepth, maxdepth); @@ -956,25 +952,20 @@ static void fixup_dc_depths(struct dive *dive, struct divecomputer *dc) static void fixup_dc_ndl(struct divecomputer *dc) { - int i; - - for (i = 0; i < dc->samples; i++) { - struct sample *sample = dc->sample + i; - if (sample->ndl.seconds != 0) + for (auto &sample: dc->samples) { + if (sample.ndl.seconds != 0) break; - if (sample->ndl.seconds == 0) - sample->ndl.seconds = -1; + if (sample.ndl.seconds == 0) + sample.ndl.seconds = -1; } } static void fixup_dc_temp(struct dive *dive, struct divecomputer *dc) { - int i; int mintemp = 0, lasttemp = 0; - for (i = 0; i < dc->samples; i++) { - struct sample *sample = dc->sample + i; - int temp = sample->temperature.mkelvin; + for (auto &sample: dc->samples) { + int temp = sample.temperature.mkelvin; if (temp) { /* @@ -983,7 +974,7 @@ static void fixup_dc_temp(struct dive *dive, struct divecomputer *dc) * the redundant ones. */ if (lasttemp == temp) - sample->temperature.mkelvin = 0; + sample.temperature.mkelvin = 0; else lasttemp = temp; @@ -991,7 +982,7 @@ static void fixup_dc_temp(struct dive *dive, struct divecomputer *dc) mintemp = temp; } - update_min_max_temperatures(dive, sample->temperature); + update_min_max_temperatures(dive, sample.temperature); } update_temperature(&dc->watertemp, mintemp); update_min_max_temperatures(dive, dc->watertemp); @@ -1000,22 +991,20 @@ static void fixup_dc_temp(struct dive *dive, struct divecomputer *dc) /* Remove redundant pressure information */ static void simplify_dc_pressures(struct divecomputer *dc) { - int i; int lastindex[2] = { -1, -1 }; int lastpressure[2] = { 0 }; - for (i = 0; i < dc->samples; i++) { + for (auto &sample: dc->samples) { int j; - struct sample *sample = dc->sample + i; for (j = 0; j < MAX_SENSORS; j++) { - int pressure = sample->pressure[j].mbar; - int index = sample->sensor[j]; + int pressure = sample.pressure[j].mbar; + int index = sample.sensor[j]; if (index == lastindex[j]) { /* Remove duplicate redundant pressure information */ if (pressure == lastpressure[j]) - sample->pressure[j].mbar = 0; + sample.pressure[j].mbar = 0; } lastindex[j] = index; lastpressure[j] = pressure; @@ -1057,30 +1046,22 @@ static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p) */ static void fixup_dive_pressures(struct dive *dive, struct divecomputer *dc) { - int i; - /* Walk the samples from the beginning to find starting pressures.. */ - for (i = 0; i < dc->samples; i++) { - int idx; - struct sample *sample = dc->sample + i; - - if (sample->depth.mm < SURFACE_THRESHOLD) + for (auto &sample: dc->samples) { + if (sample.depth.mm < SURFACE_THRESHOLD) continue; - for (idx = 0; idx < MAX_SENSORS; idx++) - fixup_start_pressure(dive, sample->sensor[idx], sample->pressure[idx]); + for (int idx = 0; idx < MAX_SENSORS; idx++) + fixup_start_pressure(dive, sample.sensor[idx], sample.pressure[idx]); } /* ..and from the end for ending pressures */ - for (i = dc->samples; --i >= 0; ) { - int idx; - struct sample *sample = dc->sample + i; - - if (sample->depth.mm < SURFACE_THRESHOLD) + for (auto it = dc->samples.rbegin(); it != dc->samples.rend(); ++it) { + if (it->depth.mm < SURFACE_THRESHOLD) continue; - for (idx = 0; idx < MAX_SENSORS; idx++) - fixup_end_pressure(dive, sample->sensor[idx], sample->pressure[idx]); + for (int idx = 0; idx < MAX_SENSORS; idx++) + fixup_end_pressure(dive, it->sensor[idx], it->pressure[idx]); } simplify_dc_pressures(dc); @@ -1155,13 +1136,12 @@ static void fixup_no_o2sensors(struct divecomputer *dc) if (dc->no_o2sensors != 0 || !(dc->divemode == CCR || dc->divemode == PSCR)) return; - for (int i = 0; i < dc->samples; i++) { - int nsensor = 0, j; - struct sample *s = dc->sample + i; + for (const auto &sample: dc->samples) { + int nsensor = 0; // How many o2 sensors can we find in this sample? - for (j = 0; j < MAX_O2_SENSORS; j++) - if (s->o2sensor[j].mbar) + for (int j = 0; j < MAX_O2_SENSORS; j++) + if (sample.o2sensor[j].mbar) nsensor++; // If we fond more than the previous found max, record it. @@ -1178,21 +1158,20 @@ static void fixup_dc_sample_sensors(struct dive *dive, struct divecomputer *dc) { unsigned long sensor_mask = 0; - for (int i = 0; i < dc->samples; i++) { - struct sample *s = dc->sample + i; + for (auto &sample: dc->samples) { for (int j = 0; j < MAX_SENSORS; j++) { - int sensor = s->sensor[j]; + int sensor = sample.sensor[j]; // No invalid sensor ID's, please if (sensor < 0 || sensor > MAX_SENSORS) { - s->sensor[j] = NO_SENSOR; - s->pressure[j].mbar = 0; + sample.sensor[j] = NO_SENSOR; + sample.pressure[j].mbar = 0; continue; } // Don't bother tracking sensors with no data - if (!s->pressure[j].mbar) { - s->sensor[j] = NO_SENSOR; + if (!sample.pressure[j].mbar) { + sample.sensor[j] = NO_SENSOR; continue; } @@ -1240,7 +1219,7 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc) fixup_no_o2sensors(dc); /* If there are no samples, generate a fake profile based on depth and time */ - if (!dc->samples) + if (dc->samples.empty()) fake_dc(dc); } @@ -1304,13 +1283,12 @@ struct dive *fixup_dive(struct dive *dive) * 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(const 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) { - struct sample *prev = dc->sample + last; - int last_time = prev->time.seconds; - int last_depth = prev->depth.mm; + if (!dc->samples.empty()) { + const struct sample &prev = dc->samples.back(); + int last_time = prev.time.seconds; + int last_depth = prev.depth.mm; /* * Only do surface events if the samples are more than @@ -1320,18 +1298,18 @@ static void merge_one_sample(const struct sample *sample, int time, struct divec struct sample surface; /* Init a few values from prev sample to avoid useless info in XML */ - surface.bearing.degrees = prev->bearing.degrees; - surface.ndl.seconds = prev->ndl.seconds; + surface.bearing.degrees = prev.bearing.degrees; + surface.ndl.seconds = prev.ndl.seconds; add_sample(&surface, last_time + 20, dc); add_sample(&surface, time - 20, dc); } } - add_sample(sample, time, dc); + 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[]); +static void sample_renumber(struct sample &s, const struct sample *next, const int mapping[]); /* * Merge samples. Dive 'a' is "offset" seconds before Dive 'b' @@ -1341,10 +1319,10 @@ static void merge_samples(struct divecomputer *res, const int *cylinders_map_a, const int *cylinders_map_b, int offset) { - int asamples = a->samples; - int bsamples = b->samples; - struct sample *as = a->sample; - struct sample *bs = b->sample; + auto as = a->samples.begin(); + auto bs = b->samples.begin(); + auto a_end = a->samples.end(); + auto b_end = b->samples.end(); /* * We want a positive sample offset, so that sample @@ -1354,27 +1332,18 @@ static void merge_samples(struct divecomputer *res, * 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; + std::swap(as, bs); + std::swap(a_end, b_end); + std::swap(cylinders_map_a, cylinders_map_b); } for (;;) { - int j; - int at, bt; - struct sample sample; - if (!res) return; - at = asamples ? as->time.seconds : -1; - bt = bsamples ? bs->time.seconds + offset : -1; + int at = as != a_end ? as->time.seconds : -1; + int bt = bs != b_end ? bs->time.seconds + offset : -1; /* No samples? All done! */ if (at < 0 && bt < 0) @@ -1383,20 +1352,18 @@ static void merge_samples(struct divecomputer *res, /* Only samples from a? */ if (bt < 0) { add_sample_a: - merge_one_sample(as, at, res); + merge_one_sample(*as, at, res); renumber_last_sample(res, cylinders_map_a); as++; - asamples--; continue; } /* Only samples from b? */ if (at < 0) { add_sample_b: - merge_one_sample(bs, bt, res); + merge_one_sample(*bs, bt, res); renumber_last_sample(res, cylinders_map_b); bs++; - bsamples--; continue; } @@ -1406,13 +1373,13 @@ static void merge_samples(struct divecomputer *res, goto add_sample_b; /* same-time sample: add a merged sample. Take the non-zero ones */ - sample = *bs; - sample_renumber(&sample, 0, cylinders_map_b); + struct sample sample = *bs; + sample_renumber(sample, nullptr, cylinders_map_b); if (as->depth.mm) sample.depth = as->depth; if (as->temperature.mkelvin) sample.temperature = as->temperature; - for (j = 0; j < MAX_SENSORS; ++j) { + for (int j = 0; j < MAX_SENSORS; ++j) { int sensor_id; sensor_id = cylinders_map_a[as->sensor[j]]; @@ -1437,12 +1404,10 @@ static void merge_samples(struct divecomputer *res, if (as->in_deco) sample.in_deco = true; - merge_one_sample(&sample, at, res); + merge_one_sample(sample, at, res); as++; bs++; - asamples--; - bsamples--; } } @@ -1636,38 +1601,34 @@ static void add_initial_gaschange(struct dive *dive, struct divecomputer *dc, in add_gas_switch_event(dive, dc, offset, idx); } -static void sample_renumber(struct sample *s, int i, const int mapping[]) +static void sample_renumber(struct sample &s, const struct sample *prev, const int mapping[]) { - int j; - - for (j = 0; j < MAX_SENSORS; j++) { + for (int j = 0; j < MAX_SENSORS; j++) { int sensor = -1; - if (s->sensor[j] != NO_SENSOR) - sensor = mapping[s->sensor[j]]; + if (s.sensor[j] != NO_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; + if (!prev) { + 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; + s.sensor[j] = prev->sensor[j]; + s.pressure[j].mbar = prev->pressure[j].mbar; } } else { - s->sensor[j] = sensor; + s.sensor[j] = sensor; } } } static void renumber_last_sample(struct divecomputer *dc, const int mapping[]) { - int idx; - - if (dc->samples <= 0) + if (dc->samples.empty()) return; - idx = dc->samples - 1; - sample_renumber(dc->sample + idx, idx, mapping); + sample *prev = dc->samples.size() > 1 ? &dc->samples[dc->samples.size() - 2] : nullptr; + sample_renumber(dc->samples.back(), prev, mapping); } static void event_renumber(struct event *ev, const int mapping[]) @@ -1681,12 +1642,11 @@ static void event_renumber(struct event *ev, const int mapping[]) static void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, const int mapping[]) { - int i; struct event *ev; /* Remap or delete the sensor indices */ - for (i = 0; i < dc->samples; i++) - sample_renumber(dc->sample + i, i, mapping); + for (auto [i, sample]: enumerated_range(dc->samples)) + sample_renumber(sample, i > 0 ? &dc->samples[i-1] : nullptr, mapping); /* Remap the gas change indices */ for (ev = dc->events; ev; ev = ev->next) @@ -2008,17 +1968,17 @@ static struct dive_trip *get_preferred_trip(const struct dive *a, const struct d /* * Sample 's' is between samples 'a' and 'b'. It is 'offset' seconds before 'b'. * - * If 's' and 'a' are at the same time, offset is 0, and b is NULL. + * If 's' and 'a' are at the same time, offset is 0. */ -static int compare_sample(struct sample *s, struct sample *a, struct sample *b, int offset) +static int compare_sample(const struct sample &s, const struct sample &a, const struct sample &b, int offset) { - unsigned int depth = a->depth.mm; + unsigned int depth = a.depth.mm; int diff; if (offset) { - unsigned int interval = b->time.seconds - a->time.seconds; - unsigned int depth_a = a->depth.mm; - unsigned int depth_b = b->depth.mm; + unsigned int interval = b.time.seconds - a.time.seconds; + unsigned int depth_a = a.depth.mm; + unsigned int depth_b = b.depth.mm; if (offset > interval) return -1; @@ -2027,7 +1987,7 @@ static int compare_sample(struct sample *s, struct sample *a, struct sample *b, depth = (depth_a * offset) + (depth_b * (interval - offset)); depth /= interval; } - diff = s->depth.mm - depth; + diff = s.depth.mm - depth; if (diff < 0) diff = -diff; /* cut off at one meter difference */ @@ -2043,10 +2003,9 @@ static int compare_sample(struct sample *s, struct sample *a, struct sample *b, */ static unsigned long sample_difference(struct divecomputer *a, struct divecomputer *b, int offset) { - int asamples = a->samples; - int bsamples = b->samples; - struct sample *as = a->sample; - struct sample *bs = b->sample; + if (a->samples.empty() || b->samples.empty()) + return; + unsigned long error = 0; int start = -1; @@ -2057,45 +2016,36 @@ static unsigned long sample_difference(struct divecomputer *a, struct divecomput * skip the first sample - this way we know can always look at * as/bs[-1] to look at the samples around it in the loop. */ - as++; - bs++; - asamples--; - bsamples--; + auto as = a->samples.begin() + 1; + auto bs = a->samples.begin() + 1; for (;;) { - int at, bt, diff; - - /* If we run out of samples, punt */ - if (!asamples) + if (as == a->samples.end()) return INT_MAX; - if (!bsamples) + if (bs == b->samples.end()) return INT_MAX; - at = as->time.seconds; - bt = bs->time.seconds + offset; + int at = as->time.seconds; + int bt = bs->time.seconds + offset; /* b hasn't started yet? Ignore it */ if (bt < 0) { - bs++; - bsamples--; + ++bs; continue; } + int diff; if (at < bt) { - diff = compare_sample(as, bs - 1, bs, bt - at); - as++; - asamples--; + diff = compare_sample(*as, *std::prev(bs), *bs, bt - at); + ++as; } else if (at > bt) { - diff = compare_sample(bs, as - 1, as, at - bt); - bs++; - bsamples--; + diff = compare_sample(*bs, *std::prev(as), *as, at - bt); + ++bs; } else { - diff = compare_sample(as, bs, NULL, 0); - as++; - bs++; - asamples--; - bsamples--; + diff = compare_sample(*as, *bs, *bs, 0); + ++as; + ++bs; } /* Invalid comparison point? */ @@ -2130,13 +2080,10 @@ static unsigned long sample_difference(struct divecomputer *a, struct divecomput */ static int find_sample_offset(struct divecomputer *a, struct divecomputer *b) { - int offset, best; - unsigned long max; - /* No samples? Merge at any time (0 offset) */ - if (!a->samples) + if (a->samples.empty()) return 0; - if (!b->samples) + if (b->samples.empty()) return 0; /* @@ -2145,8 +2092,8 @@ static int find_sample_offset(struct divecomputer *a, struct divecomputer *b) * Check this first, without wasting time trying to find * some minimal offset case. */ - best = 0; - max = sample_difference(a, b, 0); + int best = 0; + unsigned long max = sample_difference(a, b, 0); if (!max) return 0; @@ -2154,10 +2101,10 @@ static int find_sample_offset(struct divecomputer *a, struct divecomputer *b) * Otherwise, look if we can find anything better within * a thirty second window.. */ - for (offset = -30; offset <= 30; offset++) { + for (int offset = -30; offset <= 30; offset++) { unsigned long diff; - diff = sample_difference(a, b, offset); + int diff = sample_difference(a, b, offset); if (diff > max) continue; best = offset; @@ -2320,17 +2267,17 @@ struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded return res; } -static int same_sample(struct sample *a, struct sample *b) +static bool operator==(const sample &a, const sample &b) { - if (a->time.seconds != b->time.seconds) - return 0; - if (a->depth.mm != b->depth.mm) - return 0; - if (a->temperature.mkelvin != b->temperature.mkelvin) - return 0; - if (a->pressure[0].mbar != b->pressure[0].mbar) - return 0; - return a->sensor[0] == b->sensor[0]; + if (a.time.seconds != b.time.seconds) + return false; + if (a.depth.mm != b.depth.mm) + return false; + if (a.temperature.mkelvin != b.temperature.mkelvin) + return false; + if (a.pressure[0].mbar != b.pressure[0].mbar) + return false; + return a.sensor[0] == b.sensor[0]; } static int same_dc(struct divecomputer *a, struct divecomputer *b) @@ -2346,9 +2293,6 @@ static int same_dc(struct divecomputer *a, struct divecomputer *b) return 0; if (a->samples != b->samples) return 0; - for (i = 0; i < a->samples; i++) - if (!same_sample(a->sample + i, b->sample + i)) - return 0; eva = a->events; evb = b->events; while (eva && evb) { @@ -2416,8 +2360,7 @@ static const struct divecomputer *find_matching_computer(const struct divecomput static void copy_dive_computer(struct divecomputer *res, const struct divecomputer *a) { *res = *a; - res->samples = res->alloc_samples = 0; - res->sample = NULL; + res->samples.clear(); res->events = NULL; res->next = NULL; } @@ -2694,7 +2637,7 @@ static void force_fixup_dive(struct dive *d) */ static int split_dive_at(const struct dive *dive, int a, int b, struct dive **out1, struct dive **out2) { - int i, nr; + int nr; int32_t t; struct dive *d1, *d2; struct divecomputer *dc1, *dc2; @@ -2705,7 +2648,7 @@ static int split_dive_at(const struct dive *dive, int a, int b, struct dive **ou return -1; /* Splitting should leave at least 3 samples per dive */ - if (a < 3 || b > dive->dc.samples - 4) + if (a < 3 || static_cast(b + 4) > dive->dc.samples.size()) return -1; /* We're not trying to be efficient here.. */ @@ -2724,26 +2667,22 @@ static int split_dive_at(const struct dive *dive, int a, int b, struct dive **ou * Cut off the samples of d1 at the beginning * of the interval. */ - dc1->samples = a; + dc1->samples.resize(a); /* And get rid of the 'b' first samples of d2 */ - dc2->samples -= b; - memmove(dc2->sample, dc2->sample+b, dc2->samples * sizeof(struct sample)); + dc2->samples.erase(dc2->samples.begin(), dc2->samples.begin() + b); /* Now the secondary dive computers */ - t = dc2->sample[0].time.seconds; - while ((dc1 = dc1->next)) { - i = 0; - while (dc1->samples < i && dc1->sample[i].time.seconds <= t) - ++i; - dc1->samples = i; + t = dc2->samples[0].time.seconds; + while ((dc1 = dc1->next)) { + auto it = std::find_if(dc1->samples.begin(), dc1->samples.end(), + [t](auto &sample) { return sample.time.seconds >= t; }); + dc1->samples.erase(it, dc1->samples.end()); } while ((dc2 = dc2->next)) { - i = 0; - while (dc2->samples < i && dc2->sample[i].time.seconds < t) - ++i; - dc2->samples -= i; - memmove(dc2->sample, dc2->sample + i, dc2->samples * sizeof(struct sample)); + auto it = std::find_if(dc2->samples.begin(), dc2->samples.end(), + [t](auto &sample) { return sample.time.seconds >= t; }); + dc2->samples.erase(dc2->samples.begin(), it); } dc1 = &d1->dc; dc2 = &d2->dc; @@ -2754,8 +2693,8 @@ static int split_dive_at(const struct dive *dive, int a, int b, struct dive **ou d2->when += t; while (dc1 && dc2) { dc2->when += t; - for (i = 0; i < dc2->samples; i++) - dc2->sample[i].time.seconds -= t; + for (auto &sample: dc2->samples) + sample.time.seconds -= t; /* Remove the events past 't' from d1 */ evp = &dc1->events; @@ -2823,20 +2762,17 @@ static bool should_split(const struct divecomputer *dc, int t1, int t2) */ int split_dive(const struct dive *dive, struct dive **new1, struct dive **new2) { - int i; - int at_surface, surface_start; - const struct divecomputer *dc; - *new1 = *new2 = NULL; if (!dive) return -1; - dc = &dive->dc; - surface_start = 0; - at_surface = 1; - for (i = 1; i < dc->samples; i++) { - struct sample *sample = dc->sample+i; - int surface_sample = sample->depth.mm < SURFACE_THRESHOLD; + const struct divecomputer *dc = &dive->dc; + bool at_surface = true; + if (dc->samples.empty()) + return -1; + auto surface_start = dc->samples.begin(); + for (auto it = dc->samples.begin() + 1; it != dc->samples.end(); ++it) { + bool surface_sample = it->depth.mm < SURFACE_THRESHOLD; /* * We care about the transition from and to depth 0, @@ -2848,38 +2784,35 @@ int split_dive(const struct dive *dive, struct dive **new1, struct dive **new2) // Did it become surface after having been non-surface? We found the start if (at_surface) { - surface_start = i; + surface_start = it; continue; } // Going down again? We want at least a minute from // the surface start. - if (!surface_start) + if (surface_start == dc->samples.begin()) continue; - if (!should_split(dc, dc->sample[surface_start].time.seconds, sample[-1].time.seconds)) + if (!should_split(dc, surface_start->time.seconds, std::prev(it)->time.seconds)) continue; - return split_dive_at(dive, surface_start, i-1, new1, new2); + return split_dive_at(dive, surface_start - dc->samples.begin(), it - dc->samples.begin() - 1, new1, new2); } return -1; } int split_dive_at_time(const struct dive *dive, duration_t time, struct dive **new1, struct dive **new2) { - int i = 0; - if (!dive) return -1; - struct sample *sample = dive->dc.sample; - *new1 = *new2 = NULL; - while(sample->time.seconds < time.seconds) { - ++sample; - ++i; - if (dive->dc.samples == i) - return -1; - } - return split_dive_at(dive, i, i - 1, new1, new2); + auto it = std::find_if(dive->dc.samples.begin(), dive->dc.samples.end(), + [time](auto &sample) { return sample.time.seconds >= time.seconds; }); + if (it == dive->dc.samples.end()) + return -1; + size_t idx = it - dive->dc.samples.begin(); + if (idx < 1) + return -1; + return split_dive_at(dive, static_cast(idx), static_cast(idx - 1), new1, new2); } /* @@ -2893,12 +2826,10 @@ int split_dive_at_time(const struct dive *dive, duration_t time, struct dive **n static inline int dc_totaltime(const struct divecomputer *dc) { int time = dc->duration.seconds; - int nr = dc->samples; - while (nr--) { - struct sample *s = dc->sample + nr; - time = s->time.seconds; - if (s->depth.mm >= SURFACE_THRESHOLD) + for (auto it = dc->samples.rbegin(); it != dc->samples.rend(); ++it) { + time = it->time.seconds; + if (it->depth.mm >= SURFACE_THRESHOLD) break; } return time; @@ -3464,12 +3395,11 @@ struct gasmix get_gasmix_at_time(const struct dive *d, const struct divecomputer bool cylinder_with_sensor_sample(const struct dive *dive, int cylinder_id) { for (const struct divecomputer *dc = &dive->dc; dc; dc = dc->next) { - for (int i = 0; i < dc->samples; ++i) { - struct sample *sample = dc->sample + i; + for (const auto &sample: dc->samples) { for (int j = 0; j < MAX_SENSORS; ++j) { - if (!sample->pressure[j].mbar) + if (!sample.pressure[j].mbar) continue; - if (sample->sensor[j] == cylinder_id) + if (sample.sensor[j] == cylinder_id) return true; } } diff --git a/core/dive.h b/core/dive.h index 2a54526b8..9f81005d3 100644 --- a/core/dive.h +++ b/core/dive.h @@ -59,6 +59,8 @@ struct dive { dive(); ~dive(); + dive(dive &&); + dive &operator=(const dive &); }; /* For the top-level list: an entry is either a dive or a trip */ diff --git a/core/divecomputer.cpp b/core/divecomputer.cpp index 131758226..f64878e4d 100644 --- a/core/divecomputer.cpp +++ b/core/divecomputer.cpp @@ -21,6 +21,7 @@ divecomputer::~divecomputer() } divecomputer::divecomputer(divecomputer &&) = default; +divecomputer &divecomputer::operator=(const divecomputer &) = default; /* * Good fake dive profiles are hard. @@ -81,7 +82,7 @@ divecomputer::divecomputer(divecomputer &&) = default; * In general, we have more free variables than we have constraints, * but we can aim for certain basics, like a good ascent slope. */ -static int fill_samples(struct sample *s, int max_d, int avg_d, int max_t, double slope, double d_frac) +static int fill_samples(std::vector &s, int max_d, int avg_d, int max_t, double slope, double d_frac) { double t_frac = max_t * (1 - avg_d / (double)max_d); int t1 = lrint(max_d / slope); @@ -108,7 +109,7 @@ static int fill_samples(struct sample *s, int max_d, int avg_d, int max_t, doubl * we should assume either a PADI rectangular profile (for short and/or * shallow dives) or more reasonably a six point profile with a 3 minute * safety stop at 5m */ -static void fill_samples_no_avg(struct sample *s, int max_d, int max_t, double slope) +static void fill_samples_no_avg(std::vector &s, int max_d, int max_t, double slope) { // shallow or short dives are just trapecoids based on the given slope if (max_d < 10000 || max_t < 600) { @@ -130,27 +131,24 @@ static void fill_samples_no_avg(struct sample *s, int max_d, int max_t, double s void fake_dc(struct divecomputer *dc) { - alloc_samples(dc, 6); - struct sample *fake = dc->sample; - int i; - - dc->samples = 6; - /* The dive has no samples, so create a few fake ones */ int max_t = dc->duration.seconds; int max_d = dc->maxdepth.mm; int avg_d = dc->meandepth.mm; - memset(fake, 0, 6 * sizeof(struct sample)); + if (!max_t || !max_d) { + dc->samples.clear(); + return; + } + + std::vector &fake = dc->samples; + fake.resize(6); + fake[5].time.seconds = max_t; - for (i = 0; i < 6; i++) { + for (int i = 0; i < 6; i++) { fake[i].bearing.degrees = -1; fake[i].ndl.seconds = -1; } - if (!max_t || !max_d) { - dc->samples = 0; - return; - } /* Set last manually entered time to the total dive length */ dc->last_manual_time = dc->duration; @@ -167,7 +165,7 @@ void fake_dc(struct divecomputer *dc) * the user supplied data */ fill_samples_no_avg(fake, max_d, max_t, std::max(2.0 * max_d / max_t, (double)prefs.ascratelast6m)); if (fake[3].time.seconds == 0) { // just a 4 point profile - dc->samples = 4; + dc->samples.resize(4); fake[3].time.seconds = max_t; } return; @@ -235,16 +233,16 @@ enum divemode_t get_current_divemode(const struct divecomputer *dc, int time, co int get_depth_at_time(const struct divecomputer *dc, unsigned int time) { int depth = 0; - if (dc && dc->sample) - for (int i = 0; i < dc->samples; i++) { - if (dc->sample[i].time.seconds > (int)time) + if (dc) { + for (const auto &sample: dc->samples) { + if (sample.time.seconds > (int)time) break; - depth = dc->sample[i].depth.mm; + depth = sample.depth.mm; } + } return depth; } - static void free_dc(struct divecomputer *dc) { delete dc; @@ -257,60 +255,28 @@ void free_dive_dcs(struct divecomputer *dc) STRUCTURED_LIST_FREE(struct divecomputer, dc->next, free_dc); } -/* make room for num samples; if not enough space is available, the sample - * array is reallocated and the existing samples are copied. */ -void alloc_samples(struct divecomputer *dc, int num) -{ - if (num > dc->alloc_samples) { - dc->alloc_samples = (num * 3) / 2 + 10; - dc->sample = (struct sample *)realloc(dc->sample, dc->alloc_samples * sizeof(struct sample)); - if (!dc->sample) - dc->samples = dc->alloc_samples = 0; - } -} - -void free_samples(struct divecomputer *dc) -{ - if (dc) { - free(dc->sample); - dc->sample = 0; - dc->samples = 0; - dc->alloc_samples = 0; - } -} - struct sample *prepare_sample(struct divecomputer *dc) { if (dc) { - int nr = dc->samples; - struct sample *sample; - alloc_samples(dc, nr + 1); - if (!dc->sample) - return NULL; - sample = dc->sample + nr; - memset(sample, 0, sizeof(*sample)); + dc->samples.emplace_back(); + auto &sample = dc->samples.back(); // Copy the sensor numbers - but not the pressure values // from the previous sample if any. - if (nr) { + if (dc->samples.size() >= 2) { + auto &prev = dc->samples[dc->samples.size() - 2]; for (int idx = 0; idx < MAX_SENSORS; idx++) - sample->sensor[idx] = sample[-1].sensor[idx]; + sample.sensor[idx] = prev.sensor[idx]; } // Init some values with -1 - sample->bearing.degrees = -1; - sample->ndl.seconds = -1; + sample.bearing.degrees = -1; + sample.ndl.seconds = -1; - return sample; + return &sample; } return NULL; } - -void finish_sample(struct divecomputer *dc) -{ - dc->samples++; -} - struct sample *add_sample(const struct sample *sample, int time, struct divecomputer *dc) { struct sample *p = prepare_sample(dc); @@ -318,7 +284,6 @@ struct sample *add_sample(const struct sample *sample, int time, struct divecomp if (p) { *p = *sample; p->time.seconds = time; - finish_sample(dc); } return p; } @@ -331,17 +296,12 @@ struct sample *add_sample(const struct sample *sample, int time, struct divecomp */ void fixup_dc_duration(struct divecomputer *dc) { - int duration, i; - int lasttime, lastdepth, depthtime; + int duration = 0; + int lasttime = 0, lastdepth = 0, depthtime = 0; - duration = 0; - lasttime = 0; - lastdepth = 0; - depthtime = 0; - for (i = 0; i < dc->samples; i++) { - struct sample *sample = dc->sample + i; - int time = sample->time.seconds; - int depth = sample->depth.mm; + for (const auto &sample: dc->samples) { + int time = sample.time.seconds; + int depth = sample.depth.mm; /* We ignore segments at the surface */ if (depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) { @@ -357,7 +317,6 @@ void fixup_dc_duration(struct divecomputer *dc) } } - /* * What do the dive computers say the water temperature is? * (not in the samples, but as dc property for dcs that support that) @@ -413,28 +372,6 @@ void copy_events(const struct divecomputer *s, struct divecomputer *d) *pev = NULL; } -void copy_samples(const struct divecomputer *s, struct divecomputer *d) -{ - /* instead of carefully copying them one by one and calling add_sample - * over and over again, let's just copy the whole blob */ - if (!s || !d) - return; - int nr = s->samples; - d->samples = nr; - d->alloc_samples = nr; - // We expect to be able to read the memory in the other end of the pointer - // if its a valid pointer, so don't expect malloc() to return NULL for - // zero-sized malloc, do it ourselves. - d->sample = NULL; - - if(!nr) - return; - - d->sample = (struct sample *)malloc(nr * sizeof(struct sample)); - if (d->sample) - memcpy(d->sample, s->sample, nr * sizeof(struct sample)); -} - void add_event_to_dc(struct divecomputer *dc, struct event *ev) { struct event **p; @@ -528,7 +465,6 @@ int match_one_dc(const struct divecomputer *a, const struct divecomputer *b) void free_dc_contents(struct divecomputer *dc) { - free(dc->sample); free_events(dc->events); } diff --git a/core/divecomputer.h b/core/divecomputer.h index 1e7240809..1111ab500 100644 --- a/core/divecomputer.h +++ b/core/divecomputer.h @@ -37,8 +37,7 @@ struct divecomputer { int salinity = 0; // kg per 10000 l std::string model, serial, fw_version; uint32_t deviceid = 0, diveid = 0; - int samples = 0, alloc_samples = 0; - struct sample *sample = nullptr; + std::vector samples; struct event *events = nullptr; std::vector extra_data; struct divecomputer *next = nullptr; @@ -46,6 +45,7 @@ struct divecomputer { divecomputer(); ~divecomputer(); divecomputer(divecomputer &&); + divecomputer &operator=(const divecomputer &); }; extern void fake_dc(struct divecomputer *dc); @@ -53,17 +53,13 @@ extern void free_dc_contents(struct divecomputer *dc); extern enum divemode_t get_current_divemode(const struct divecomputer *dc, int time, const struct event **evp, enum divemode_t *divemode); extern int get_depth_at_time(const struct divecomputer *dc, unsigned int time); extern void free_dive_dcs(struct divecomputer *dc); -extern void alloc_samples(struct divecomputer *dc, int num); -extern void free_samples(struct divecomputer *dc); extern struct sample *prepare_sample(struct divecomputer *dc); -extern void finish_sample(struct divecomputer *dc); extern struct sample *add_sample(const struct sample *sample, int time, struct divecomputer *dc); extern void fixup_dc_duration(struct divecomputer *dc); extern unsigned int dc_airtemp(const struct divecomputer *dc); extern unsigned int dc_watertemp(const struct divecomputer *dc); extern void copy_events(const struct divecomputer *s, struct divecomputer *d); extern void swap_event(struct divecomputer *dc, struct event *from, struct event *to); -extern void copy_samples(const struct divecomputer *s, struct divecomputer *d); extern void add_event_to_dc(struct divecomputer *dc, struct event *ev); extern struct event *add_event(struct divecomputer *dc, unsigned int time, int type, int flags, int value, const std::string &name); extern void remove_event_from_dc(struct divecomputer *dc, struct event *event); diff --git a/core/divelist.cpp b/core/divelist.cpp index 21795f499..b56006d9b 100644 --- a/core/divelist.cpp +++ b/core/divelist.cpp @@ -15,6 +15,7 @@ #include "interpolate.h" #include "planner.h" #include "qthelper.h" +#include "range.h" #include "gettext.h" #include "git-access.h" #include "selection.h" @@ -80,26 +81,25 @@ static int active_o2(const struct dive *dive, const struct divecomputer *dc, dur } // Do not call on first sample as it acccesses the previous sample -static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc, const struct sample *sample) +static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc, const struct sample &sample, const struct sample &psample) { int po2i, po2f, po2; - const struct sample *psample = sample - 1; // Use sensor[0] if available - if ((dc->divemode == CCR || dc->divemode == PSCR) && sample->o2sensor[0].mbar) { - po2i = psample->o2sensor[0].mbar; - po2f = sample->o2sensor[0].mbar; // then use data from the first o2 sensor + if ((dc->divemode == CCR || dc->divemode == PSCR) && sample.o2sensor[0].mbar) { + po2i = psample.o2sensor[0].mbar; + po2f = sample.o2sensor[0].mbar; // then use data from the first o2 sensor po2 = (po2f + po2i) / 2; - } else if (sample->setpoint.mbar > 0) { - po2 = std::min((int) sample->setpoint.mbar, - depth_to_mbar(sample->depth.mm, dive)); + } else if (sample.setpoint.mbar > 0) { + po2 = std::min((int) sample.setpoint.mbar, + depth_to_mbar(sample.depth.mm, dive)); } else { - double amb_presure = depth_to_bar(sample->depth.mm, dive); - double pamb_pressure = depth_to_bar(psample->depth.mm , dive); + double amb_presure = depth_to_bar(sample.depth.mm, dive); + double pamb_pressure = depth_to_bar(psample.depth.mm , dive); if (dc->divemode == PSCR) { - po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, dc, psample->time)); - po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, dc, sample->time)); + po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, dc, psample.time)); + po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, dc, sample.time)); } else { - int o2 = active_o2(dive, dc, psample->time); // ... calculate po2 from depth and FiO2. + int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2. po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment po2f = lrint(o2 * amb_presure); // (final) po2 at end of segment } @@ -117,37 +117,34 @@ static int get_sample_o2(const struct dive *dive, const struct divecomputer *dc, oxygen tolerance curves. Inst. env. Med. Report 1-70, University of Pennsylvania, Philadelphia, USA. */ static int calculate_otu(const struct dive *dive) { - int i; double otu = 0.0; const struct divecomputer *dc = &dive->dc; - for (i = 1; i < dc->samples; i++) { + for (auto [psample, sample]: pairwise_range(dc->samples)) { int t; int po2i, po2f; double pm; - struct sample *sample = dc->sample + i; - struct sample *psample = sample - 1; - t = sample->time.seconds - psample->time.seconds; + t = sample.time.seconds - psample.time.seconds; // if there is sensor data use sensor[0] - if ((dc->divemode == CCR || dc->divemode == PSCR) && sample->o2sensor[0].mbar) { - po2i = psample->o2sensor[0].mbar; - po2f = sample->o2sensor[0].mbar; // ... use data from the first o2 sensor + if ((dc->divemode == CCR || dc->divemode == PSCR) && sample.o2sensor[0].mbar) { + po2i = psample.o2sensor[0].mbar; + po2f = sample.o2sensor[0].mbar; // ... use data from the first o2 sensor } else { - if (sample->setpoint.mbar > 0) { - po2f = std::min((int) sample->setpoint.mbar, - depth_to_mbar(sample->depth.mm, dive)); - if (psample->setpoint.mbar > 0) - po2i = std::min((int) psample->setpoint.mbar, - depth_to_mbar(psample->depth.mm, dive)); + if (sample.setpoint.mbar > 0) { + po2f = std::min((int) sample.setpoint.mbar, + depth_to_mbar(sample.depth.mm, dive)); + if (psample.setpoint.mbar > 0) + po2i = std::min((int) psample.setpoint.mbar, + depth_to_mbar(psample.depth.mm, dive)); else po2i = po2f; } else { // For OC and rebreather without o2 sensor/setpoint - double amb_presure = depth_to_bar(sample->depth.mm, dive); - double pamb_pressure = depth_to_bar(psample->depth.mm , dive); + double amb_presure = depth_to_bar(sample.depth.mm, dive); + double pamb_pressure = depth_to_bar(psample.depth.mm , dive); if (dc->divemode == PSCR) { - po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, dc, psample->time)); - po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, dc, sample->time)); + po2i = pscr_o2(pamb_pressure, get_gasmix_at_time(dive, dc, psample.time)); + po2f = pscr_o2(amb_presure, get_gasmix_at_time(dive, dc, sample.time)); } else { - int o2 = active_o2(dive, dc, psample->time); // ... calculate po2 from depth and FiO2. + int o2 = active_o2(dive, dc, psample.time); // ... calculate po2 from depth and FiO2. po2i = lrint(o2 * pamb_pressure); // (initial) po2 at start of segment po2f = lrint(o2 * amb_presure); // (final) po2 at end of segment } @@ -182,18 +179,13 @@ static int calculate_otu(const struct dive *dive) to the end of the segment, assuming a constant rate of change in po2 (i.e. depth) with time. */ static double calculate_cns_dive(const struct dive *dive) { - int n; const struct divecomputer *dc = &dive->dc; double cns = 0.0; double rate; /* Calculate the CNS for each sample in this dive and sum them */ - for (n = 1; n < dc->samples; n++) { - int t; - int po2; - struct sample *sample = dc->sample + n; - struct sample *psample = sample - 1; - t = sample->time.seconds - psample->time.seconds; - po2 = get_sample_o2(dive, dc, sample); + for (auto [psample, sample]: pairwise_range(dc->samples)) { + int t = sample.time.seconds - psample.time.seconds; + int po2 = get_sample_o2(dive, dc, sample, psample); /* Don't increase CNS when po2 below 500 matm */ if (po2 <= 500) continue; @@ -340,13 +332,12 @@ static int calculate_cns(struct dive *dive) static double calculate_airuse(const struct dive *dive) { int airuse = 0; - int i; // SAC for a CCR dive does not make sense. if (dive->dc.divemode == CCR) return 0.0; - for (i = 0; i < dive->cylinders.nr; i++) { + for (int i = 0; i < dive->cylinders.nr; i++) { pressure_t start, end; const cylinder_t *cyl = get_cylinder(dive, i); @@ -400,24 +391,21 @@ static void add_dive_to_deco(struct deco_state *ds, struct dive *dive, bool in_p { struct divecomputer *dc = &dive->dc; struct gasmix gasmix = gasmix_air; - int i; const struct event *ev = NULL, *evd = NULL; enum divemode_t current_divemode = UNDEF_COMP_TYPE; if (!dc) return; - for (i = 1; i < dc->samples; i++) { - struct sample *psample = dc->sample + i - 1; - struct sample *sample = dc->sample + i; - int t0 = psample->time.seconds; - int t1 = sample->time.seconds; + for (auto [psample, sample]: pairwise_range(dc->samples)) { + int t0 = psample.time.seconds; + int t1 = sample.time.seconds; int j; for (j = t0; j < t1; j++) { - int depth = interpolate(psample->depth.mm, sample->depth.mm, j - t0, t1 - t0); + int depth = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0); gasmix = get_gasmix(dive, dc, j, &ev, gasmix); - add_segment(ds, depth_to_bar(depth, dive), gasmix, 1, sample->setpoint.mbar, + add_segment(ds, depth_to_bar(depth, dive), gasmix, 1, sample.setpoint.mbar, get_current_divemode(&dive->dc, j, &evd, ¤t_divemode), dive->sac, in_planner); } @@ -645,10 +633,10 @@ static int comp_dc(const struct divecomputer *dc1, const struct divecomputer *dc * trip-time is defined such that dives that do not belong to * a trip are sorted *after* dives that do. Thus, in the default * chronologically-descending sort order, they are shown *before*. - * "id" is a stable, strictly increasing unique number, that - * is handed out when a dive is added to the system. + * "id" is a stable, strictly increasing unique number, which + * is generated when a dive is added to the system. * We might also consider sorting by end-time and other criteria, - * but see the caveat above (editing means rearrangement of the dives). + * but see the caveat above (editing means reordering of the dives). */ int comp_dives(const struct dive *a, const struct dive *b) { diff --git a/core/import-csv.cpp b/core/import-csv.cpp index 2d148ed34..b577777a0 100644 --- a/core/import-csv.cpp +++ b/core/import-csv.cpp @@ -436,7 +436,6 @@ int try_to_open_csv(std::string &mem, enum csv_format type, struct divelog *log) sample = prepare_sample(dc); sample->time.seconds = time; add_sample_data(sample, type, val); - finish_sample(dc); time++; dc->duration.seconds = time; @@ -741,7 +740,6 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log) add_sample_data(sample, POSEIDON_SETPOINT, prev_setpoint); if (!has_ndl && prev_ndl >= 0) add_sample_data(sample, POSEIDON_NDL, prev_ndl); - finish_sample(dc); if (!lineptr || !*lineptr) break; diff --git a/core/libdivecomputer.cpp b/core/libdivecomputer.cpp index 2bf09147e..48294c5de 100644 --- a/core/libdivecomputer.cpp +++ b/core/libdivecomputer.cpp @@ -309,7 +309,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_ return DC_STATUS_SUCCESS; } -static void handle_event(struct divecomputer *dc, struct sample *sample, dc_sample_value_t value) +static void handle_event(struct divecomputer *dc, const struct sample &sample, dc_sample_value_t value) { int type, time; struct event *ev; @@ -360,20 +360,19 @@ static void handle_event(struct divecomputer *dc, struct sample *sample, dc_samp #endif time = value.event.time; - if (sample) - time += sample->time.seconds; + time += sample.time.seconds; ev = add_event(dc, time, type, value.event.flags, value.event.value, name); if (event_is_gaschange(ev) && ev->gas.index >= 0) current_gas_index = ev->gas.index; } -static void handle_gasmix(struct divecomputer *dc, struct sample *sample, int idx) +static void handle_gasmix(struct divecomputer *dc, const struct sample &sample, int idx) { /* TODO: Verify that index is not higher than the number of cylinders */ if (idx < 0) return; - add_event(dc, sample->time.seconds, SAMPLE_EVENT_GASCHANGE2, idx+1, 0, "gaschange"); + add_event(dc, sample.time.seconds, SAMPLE_EVENT_GASCHANGE2, idx+1, 0, "gaschange"); current_gas_index = idx; } @@ -381,30 +380,19 @@ void sample_cb(dc_sample_type_t type, const dc_sample_value_t *pvalue, void *userdata) { static unsigned int nsensor = 0; - dc_sample_value_t value = *pvalue; struct divecomputer *dc = (divecomputer *)userdata; - struct sample *sample; + dc_sample_value_t value = *pvalue; /* - * We fill in the "previous" sample - except for DC_SAMPLE_TIME, - * which creates a new one. + * DC_SAMPLE_TIME is special: it creates a new sample. + * Other types fill in an existing sample. */ - sample = dc->samples ? dc->sample + dc->samples - 1 : NULL; - - /* - * Ok, sanity check. - * If first sample is not a DC_SAMPLE_TIME, Allocate a sample for us - */ - if (sample == NULL && type != DC_SAMPLE_TIME) - sample = prepare_sample(dc); - - switch (type) { - case DC_SAMPLE_TIME: + if (type == DC_SAMPLE_TIME) { nsensor = 0; // Create a new sample. // Mark depth as negative - sample = prepare_sample(dc); + struct sample *sample = prepare_sample(dc); sample->time.seconds = value.time / 1000; sample->depth.mm = -1; // The current sample gets some sticky values @@ -418,40 +406,46 @@ sample_cb(dc_sample_type_t type, const dc_sample_value_t *pvalue, void *userdata sample->cns = cns; sample->heartbeat = heartbeat; sample->bearing.degrees = bearing; - finish_sample(dc); - break; + return; + } + + if (dc->samples.empty()) + prepare_sample(dc); + struct sample &sample = dc->samples.back(); + + switch (type) { case DC_SAMPLE_DEPTH: - sample->depth.mm = lrint(value.depth * 1000); + sample.depth.mm = lrint(value.depth * 1000); break; case DC_SAMPLE_PRESSURE: - add_sample_pressure(sample, value.pressure.tank, lrint(value.pressure.value * 1000)); + add_sample_pressure(&sample, value.pressure.tank, lrint(value.pressure.value * 1000)); break; case DC_SAMPLE_GASMIX: handle_gasmix(dc, sample, value.gasmix); break; case DC_SAMPLE_TEMPERATURE: - sample->temperature.mkelvin = C_to_mkelvin(value.temperature); + sample.temperature.mkelvin = C_to_mkelvin(value.temperature); break; case DC_SAMPLE_EVENT: handle_event(dc, sample, value); break; case DC_SAMPLE_RBT: - sample->rbt.seconds = (!strncasecmp(dc->model.c_str(), "suunto", 6)) ? value.rbt : value.rbt * 60; + sample.rbt.seconds = (!strncasecmp(dc->model.c_str(), "suunto", 6)) ? value.rbt : value.rbt * 60; break; #ifdef DC_SAMPLE_TTS case DC_SAMPLE_TTS: - sample->tts.seconds = value.time; + sample.tts.seconds = value.time; break; #endif case DC_SAMPLE_HEARTBEAT: - sample->heartbeat = heartbeat = value.heartbeat; + sample.heartbeat = heartbeat = value.heartbeat; break; case DC_SAMPLE_BEARING: - sample->bearing.degrees = bearing = value.bearing; + sample.bearing.degrees = bearing = value.bearing; break; #ifdef DEBUG_DC_VENDOR case DC_SAMPLE_VENDOR: - printf(" ", FRACTION_TUPLE(sample->time.seconds, 60), + printf(" ", FRACTION_TUPLE(sample.time.seconds, 60), value.vendor.type, value.vendor.size); for (int i = 0; i < value.vendor.size; ++i) printf("%02X", ((unsigned char *)value.vendor.data)[i]); @@ -460,11 +454,11 @@ sample_cb(dc_sample_type_t type, const dc_sample_value_t *pvalue, void *userdata #endif case DC_SAMPLE_SETPOINT: /* for us a setpoint means constant pO2 from here */ - sample->setpoint.mbar = po2 = lrint(value.setpoint * 1000); + sample.setpoint.mbar = po2 = lrint(value.setpoint * 1000); break; case DC_SAMPLE_PPO2: if (nsensor < MAX_O2_SENSORS) - sample->o2sensor[nsensor].mbar = lrint(value.ppo2.value * 1000); + sample.o2sensor[nsensor].mbar = lrint(value.ppo2.value * 1000); else report_error("%d is more o2 sensors than we can handle", nsensor); nsensor++; @@ -473,25 +467,25 @@ sample_cb(dc_sample_type_t type, const dc_sample_value_t *pvalue, void *userdata dc->no_o2sensors = nsensor; break; case DC_SAMPLE_CNS: - sample->cns = cns = lrint(value.cns * 100); + sample.cns = cns = lrint(value.cns * 100); break; case DC_SAMPLE_DECO: if (value.deco.type == DC_DECO_NDL) { - sample->ndl.seconds = ndl = value.deco.time; - sample->stopdepth.mm = stopdepth = lrint(value.deco.depth * 1000.0); - sample->in_deco = in_deco = false; + sample.ndl.seconds = ndl = value.deco.time; + sample.stopdepth.mm = stopdepth = lrint(value.deco.depth * 1000.0); + sample.in_deco = in_deco = false; } else if (value.deco.type == DC_DECO_DECOSTOP || value.deco.type == DC_DECO_DEEPSTOP) { - sample->stopdepth.mm = stopdepth = lrint(value.deco.depth * 1000.0); - sample->stoptime.seconds = stoptime = value.deco.time; - sample->in_deco = in_deco = stopdepth > 0; + sample.stopdepth.mm = stopdepth = lrint(value.deco.depth * 1000.0); + sample.stoptime.seconds = stoptime = value.deco.time; + sample.in_deco = in_deco = stopdepth > 0; ndl = 0; } else if (value.deco.type == DC_DECO_SAFETYSTOP) { - sample->in_deco = in_deco = false; - sample->stopdepth.mm = stopdepth = lrint(value.deco.depth * 1000.0); - sample->stoptime.seconds = stoptime = value.deco.time; + sample.in_deco = in_deco = false; + sample.stopdepth.mm = stopdepth = lrint(value.deco.depth * 1000.0); + sample.stoptime.seconds = stoptime = value.deco.time; } - sample->tts.seconds = value.deco.tts; + sample.tts.seconds = value.deco.tts; default: break; } @@ -870,18 +864,18 @@ static int dive_cb(const unsigned char *data, unsigned int size, } /* Various libdivecomputer interface fixups */ - if (dive->dc.airtemp.mkelvin == 0 && first_temp_is_air && dive->dc.samples) { - dive->dc.airtemp = dive->dc.sample[0].temperature; - dive->dc.sample[0].temperature.mkelvin = 0; + if (dive->dc.airtemp.mkelvin == 0 && first_temp_is_air && !dive->dc.samples.empty()) { + dive->dc.airtemp = dive->dc.samples[0].temperature; + dive->dc.samples[0].temperature.mkelvin = 0; } /* special case for bug in Tecdiving DiveComputer.eu * often the first sample has a water temperature of 0C, followed by the correct * temperature in the next sample */ - if (dive->dc.model == "Tecdiving DiveComputer.eu" && - dive->dc.sample[0].temperature.mkelvin == ZERO_C_IN_MKELVIN && - dive->dc.sample[1].temperature.mkelvin > dive->dc.sample[0].temperature.mkelvin) - dive->dc.sample[0].temperature.mkelvin = dive->dc.sample[1].temperature.mkelvin; + if (dive->dc.model == "Tecdiving DiveComputer.eu" && !dive->dc.samples.empty() && + dive->dc.samples[0].temperature.mkelvin == ZERO_C_IN_MKELVIN && + dive->dc.samples[1].temperature.mkelvin > dive->dc.samples[0].temperature.mkelvin) + dive->dc.samples[0].temperature.mkelvin = dive->dc.samples[1].temperature.mkelvin; record_dive_to_table(dive.release(), devdata->log->dives.get()); return true; diff --git a/core/liquivision.cpp b/core/liquivision.cpp index a8d482548..d09245c7a 100644 --- a/core/liquivision.cpp +++ b/core/liquivision.cpp @@ -334,7 +334,6 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int sample->depth.mm = array_uint16_le(ds + (d - 1) * 2) * 10; // cm->mm sample->temperature.mkelvin = C_to_mkelvin((float) array_uint16_le(ts + (d - 1) * 2) / 10); // dC->mK add_sample_pressure(sample, event.pressure.sensor, event.pressure.mbar); - finish_sample(dc); break; } else if (event.time > sample_time) { @@ -342,7 +341,6 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int sample->time.seconds = sample_time; sample->depth.mm = depth_mm; sample->temperature.mkelvin = temp_mk; - finish_sample(dc); d++; continue; @@ -351,7 +349,6 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int sample->depth.mm = depth_mm; sample->temperature.mkelvin = temp_mk; add_sample_pressure(sample, event.pressure.sensor, event.pressure.mbar); - finish_sample(dc); d++; break; @@ -370,7 +367,6 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int sample->temperature.mkelvin = last_temp + (temp_mk - last_temp) * ((int)event.time - (int)last_time) / sample_interval; } - finish_sample(dc); break; } @@ -385,7 +381,6 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int sample->depth.mm = array_uint16_le(ds + d * 2) * 10; // cm->mm sample->temperature.mkelvin = C_to_mkelvin((float)array_uint16_le(ts + d * 2) / 10); - finish_sample(dc); } if (log_version == 3 && model == 4) { diff --git a/core/load-git.cpp b/core/load-git.cpp index 3f892522c..bf52146ec 100644 --- a/core/load-git.cpp +++ b/core/load-git.cpp @@ -675,8 +675,9 @@ static int sanitize_sensor_id(const struct dive *d, int nr) static struct sample *new_sample(struct git_parser_state *state) { struct sample *sample = prepare_sample(state->active_dc); - if (sample != state->active_dc->sample) { - memcpy(sample, sample - 1, sizeof(struct sample)); + size_t num_samples = state->active_dc->samples.size(); + if (num_samples >= 2) { + *sample = state->active_dc->samples[num_samples - 2]; sample->pressure[0].mbar = 0; sample->pressure[1].mbar = 0; } else { @@ -717,7 +718,6 @@ static void sample_parser(char *line, struct git_parser_state *state) line = parse_sample_unit(sample, val, line); } } - finish_sample(state->active_dc); } static void parse_dc_airtemp(char *line, struct git_parser_state *state) @@ -1645,7 +1645,7 @@ static struct divecomputer *create_new_dc(struct dive *dive) while (dc->next) dc = dc->next; /* Did we already fill that in? */ - if (dc->samples || !dc->model.empty() || dc->when) { + if (!dc->samples.empty() || !dc->model.empty() || dc->when) { struct divecomputer *newdc = new divecomputer; dc->next = newdc; dc = newdc; diff --git a/core/parse.cpp b/core/parse.cpp index d3cc16e50..e759f10ee 100644 --- a/core/parse.cpp +++ b/core/parse.cpp @@ -118,7 +118,7 @@ void event_end(struct parser_state *state) bool is_dive(struct parser_state *state) { return state->cur_dive && - (state->cur_dive->dive_site || state->cur_dive->when || state->cur_dive->dc.samples); + (state->cur_dive->dive_site || state->cur_dive->when || !state->cur_dive->dc.samples.empty()); } void reset_dc_info(struct divecomputer *, struct parser_state *state) @@ -361,8 +361,8 @@ void sample_start(struct parser_state *state) struct divecomputer *dc = get_dc(state); struct sample *sample = prepare_sample(dc); - if (sample != dc->sample) { - memcpy(sample, sample-1, sizeof(struct sample)); + if (dc->samples.size() > 1) { + *sample = dc->samples[dc->samples.size() - 2]; sample->pressure[0].mbar = 0; sample->pressure[1].mbar = 0; } else { @@ -378,7 +378,6 @@ void sample_end(struct parser_state *state) if (!state->cur_dive) return; - finish_sample(get_dc(state)); state->cur_sample = NULL; } @@ -392,7 +391,7 @@ void divecomputer_start(struct parser_state *state) dc = dc->next; /* Did we already fill that in? */ - if (dc->samples || !dc->model.empty() || dc->when) { + if (!dc->samples.empty() || !dc->model.empty() || dc->when) { struct divecomputer *newdc = new divecomputer; if (newdc) { dc->next = newdc; diff --git a/core/planner.cpp b/core/planner.cpp index d78eb52d1..dc251a97f 100644 --- a/core/planner.cpp +++ b/core/planner.cpp @@ -112,11 +112,8 @@ static void interpolate_transition(struct deco_state *ds, struct dive *dive, dur /* returns the tissue tolerance at the end of this (partial) dive */ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct divecomputer *dc, deco_state_cache &cache) { - struct sample *sample, *psample; - int i; - depth_t lastdepth = {}; - duration_t t0 = {}, t1 = {}; - struct gasmix gas; + depth_t lastdepth; + duration_t t0; int surface_interval = 0; if (!dive) @@ -127,24 +124,20 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct surface_interval = init_decompression(ds, dive, true); cache.cache(ds); } - if (!dc->samples) + if (dc->samples.empty()) return 0; - psample = sample = dc->sample; const struct event *evdm = NULL; enum divemode_t divemode = UNDEF_COMP_TYPE; - for (i = 0; i < dc->samples; i++, sample++) { - o2pressure_t setpoint; + const struct sample *psample = nullptr; + for (auto &sample: dc->samples) { + o2pressure_t setpoint = psample ? psample->setpoint + : sample.setpoint; - if (i) - setpoint = sample[-1].setpoint; - else - setpoint = sample[0].setpoint; - - t1 = sample->time; - gas = get_gasmix_at_time(dive, dc, t0); - if (i > 0) + duration_t t1 = sample.time; + struct gasmix gas = get_gasmix_at_time(dive, dc, t0); + if (psample) lastdepth = psample->depth; /* The ceiling in the deeper portion of a multilevel dive is sometimes critical for the VPM-B @@ -156,7 +149,7 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct * portion of the dive. * Remember the value for later. */ - if ((decoMode(true) == VPMB) && (lastdepth.mm > sample->depth.mm)) { + if ((decoMode(true) == VPMB) && (lastdepth.mm > sample.depth.mm)) { pressure_t ceiling_pressure; nuclear_regeneration(ds, t0.seconds); vpmb_start_gradient(ds); @@ -171,8 +164,8 @@ static int tissue_at_end(struct deco_state *ds, struct dive *dive, const struct } divemode = get_current_divemode(&dive->dc, t0.seconds + 1, &evdm, &divemode); - interpolate_transition(ds, dive, t0, t1, lastdepth, sample->depth, gas, setpoint, divemode); - psample = sample; + interpolate_transition(ds, dive, t0, t1, lastdepth, sample.depth, gas, setpoint, divemode); + psample = &sample; t0 = t1; } return surface_interval; @@ -208,7 +201,6 @@ static void update_cylinder_pressure(struct dive *d, int old_depth, int new_dept static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, struct divecomputer *dc, bool track_gas) { struct divedatapoint *dp; - struct sample *sample; struct event *ev; cylinder_t *cyl; int oldpo2 = 0; @@ -230,7 +222,7 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, dc->when = dive->when = diveplan->when; dc->surface_pressure.mbar = diveplan->surface_pressure; dc->salinity = diveplan->salinity; - free_samples(dc); + dc->samples.clear(); while ((ev = dc->events)) { dc->events = dc->events->next; delete ev; @@ -240,12 +232,11 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, * there is no real dp for time = 0, set first cylinder to 0 * O2 setpoint for this sample will be filled later from next dp */ cyl = get_or_create_cylinder(dive, 0); - sample = prepare_sample(dc); + struct sample *sample = prepare_sample(dc); sample->sac.mliter = prefs.bottomsac; if (track_gas && cyl->type.workingpressure.mbar) sample->pressure[0].mbar = cyl->end.mbar; sample->manually_entered = true; - finish_sample(dc); lastcylid = 0; while (dp) { int po2 = dp->setpoint; @@ -286,7 +277,6 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, sample->depth = lastdepth; sample->manually_entered = dp->entered; sample->sac.mliter = dp->entered ? prefs.bottomsac : prefs.decosac; - finish_sample(dc); lastcylid = dp->cylinderid; } if (dp->divemode != type) { @@ -311,7 +301,6 @@ static void create_dive_from_plan(struct diveplan *diveplan, struct dive *dive, if (cyl->type.workingpressure.mbar) sample->pressure[0].mbar = cyl->end.mbar; } - finish_sample(dc); dp = dp->next; } dc->last_manual_time.seconds = last_manual_point; @@ -660,7 +649,6 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i int bottom_time; int previous_deco_time; deco_state_cache bottom_cache; - struct sample *sample; int po2; int transitiontime, gi; int current_cylinder, stop_cylinder; @@ -727,20 +715,20 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i *(decostoplevels + 1) = M_OR_FT(3,10); /* Let's start at the last 'sample', i.e. the last manually entered waypoint. */ - sample = &dc->sample[dc->samples - 1]; + const struct sample &sample = dc->samples.back(); /* Keep time during the ascend */ - bottom_time = clock = previous_point_time = dc->sample[dc->samples - 1].time.seconds; + bottom_time = clock = previous_point_time = sample.time.seconds; - current_cylinder = get_cylinderid_at_time(dive, dc, sample->time); + current_cylinder = get_cylinderid_at_time(dive, dc, sample.time); // Find the divemode at the end of the dive const struct event *ev = NULL; divemode = UNDEF_COMP_TYPE; divemode = get_current_divemode(dc, bottom_time, &ev, &divemode); gas = get_cylinder(dive, current_cylinder)->gasmix; - po2 = sample->setpoint.mbar; - depth = dc->sample[dc->samples - 1].depth.mm; + po2 = sample.setpoint.mbar; + depth = sample.depth.mm; average_max_depth(diveplan, &avg_depth, &max_depth); last_ascend_rate = ascent_velocity(depth, avg_depth, bottom_time); diff --git a/core/profile.cpp b/core/profile.cpp index db09c71a0..ec7aa8c1c 100644 --- a/core/profile.cpp +++ b/core/profile.cpp @@ -305,9 +305,7 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec do { if (dc == given_dc) seen = true; - int i = dc->samples; int lastdepth = 0; - struct sample *s = dc->sample; struct event *ev; /* Make sure we can fit all events */ @@ -318,13 +316,13 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec ev = ev->next; } - while (--i >= 0) { - int depth = s->depth.mm; - int temperature = s->temperature.mkelvin; - int heartbeat = s->heartbeat; + for (auto &s: dc->samples) { + int depth = s.depth.mm; + int temperature = s.temperature.mkelvin; + int heartbeat = s.heartbeat; for (int sensor = 0; sensor < MAX_SENSORS; ++sensor) { - int pressure = s->pressure[sensor].mbar; + int pressure = s.pressure[sensor].mbar; if (pressure && pressure < minpressure) minpressure = pressure; if (pressure > maxpressure) @@ -342,17 +340,16 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec minhr = heartbeat; if (depth > maxdepth) - maxdepth = s->depth.mm; + maxdepth = s.depth.mm; /* Make sure that we get the first sample beyond the last event. * If maxtime is somewhere in the middle of the last segment, * populate_plot_entries() gets confused leading to display artifacts. */ if ((depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD || in_planner || !found_sample_beyond_last_event) && - s->time.seconds > maxtime) { + s.time.seconds > maxtime) { found_sample_beyond_last_event = true; - maxtime = s->time.seconds; + maxtime = s.time.seconds; } lastdepth = depth; - s++; } dc = dc->next; @@ -416,7 +413,7 @@ static void populate_plot_entries(const struct dive *dive, const struct divecomp * that has time > maxtime (because there can be surface samples * past "maxtime" in the original sample data) */ - size_t nr = dc->samples + 6 + pi.maxtime / 10 + count_events(dc); + size_t nr = dc->samples.size() + 6 + pi.maxtime / 10 + count_events(dc); pi.entry.reserve(nr); pi.pressures.reserve(nr * pi.nr_cylinders); @@ -430,8 +427,7 @@ static void populate_plot_entries(const struct dive *dive, const struct divecomp /* skip events at time = 0 */ while (ev && ev->time.seconds == 0) ev = ev->next; - for (int i = 0; i < dc->samples; i++) { - const struct sample &sample = dc->sample[i]; + for (const auto &sample: dc->samples) { int time = sample.time.seconds; int offset, delta; int depth = sample.depth.mm; @@ -708,8 +704,9 @@ static void populate_secondary_sensor_data(const struct divecomputer *dc, struct ++seen[c]; // Count instances so we can differentiate a real sensor from just start and end pressure int idx = 0; /* We should try to see if it has interesting pressure data here */ - for (int i = 0; i < dc->samples && idx < pi.nr; i++) { - const struct sample &sample = dc->sample[i]; + for (const auto &sample: dc->samples) { + if (idx >= pi.nr) + break; for (; idx < pi.nr; ++idx) { if (idx == pi.nr - 1 || pi.entry[idx].sec >= sample.time.seconds) // We've either found the entry at or just after the sample's time, diff --git a/core/range.h b/core/range.h index 7c7050105..76c3ac3e7 100644 --- a/core/range.h +++ b/core/range.h @@ -32,7 +32,79 @@ void move_in_range(Range &v, int rangeBegin, int rangeEnd, int destination) std::rotate(it + destination, it + rangeBegin, it + rangeEnd); } -// A rudimentary adaptor for looping over ranges with an index: +// Small helper base class for iterator adapters. +template +class iterator_adapter { +protected: + Base it; +public: + iterator_adapter(Base it) : it(it) + { + } + bool operator==(const iterator_adapter &it2) const { + return it == it2.it; + } + bool operator!=(const iterator_adapter &it2) const + { + return it != it2.it; + } +}; + +// A rudimentary adapter for looping over pairs of elements in ranges: +// for (auto [it1, it2]: pairwise_range(v)) ... +// The pairs are overlapping, i.e. there is one less pair than elements: +// { 1, 2, 3, 4 } -> (1,2), (2,3), (3,4) +template +class pairwise_range +{ + Range &base; +public: + using base_iterator = decltype(std::begin(std::declval())); + using item_type = decltype(*std::begin(base)); + class iterator : public iterator_adapter { + public: + using iterator_adapter::iterator_adapter; + std::pair operator*() const + { + return { *this->it, *std::next(this->it) }; + } + iterator &operator++() + { + ++this->it; + return *this; + } + iterator &operator--() + { + --this->it; + return *this; + } + iterator operator++(int) + { + return iterator(this->it++); + } + iterator operator--(int) + { + return iterator(this->it--); + } + }; + + iterator begin() + { + return iterator(std::begin(base)); + } + iterator end() + { + return std::begin(base) == std::end(base) ? + iterator(std::begin(base)) : + iterator(std::prev(std::end(base))); + } + + pairwise_range(Range &base): base(base) + { + } +}; + +// A rudimentary adapter for looping over ranges with an index: // for (auto [idx, item]: enumerated_range(v)) ... // The index is a signed integer, since this is what we use more often. template @@ -41,30 +113,31 @@ class enumerated_range Range &base; public: using base_iterator = decltype(std::begin(std::declval())); - class iterator { + class iterator : public iterator_adapter{ int idx; - base_iterator it; public: - std::pair operator*() const + using iterator_adapter::iterator_adapter; + using item_type = decltype(*std::begin(base)); + std::pair operator*() const { - return { idx, *it }; + return { idx, *this->it }; } iterator &operator++() { ++idx; - ++it; + ++this->it; return *this; } - iterator(int idx, base_iterator it) : idx(idx), it(it) + iterator &operator--() { + --idx; + --this->it; + return *this; } - bool operator==(const iterator &it2) const + iterator &operator++(int) = delete; // Postfix increment/decrement not supported for now + iterator &operator--(int) = delete; // Postfix increment/decrement not supported for now + iterator(int idx, base_iterator it) : iterator_adapter(it), idx(idx) { - return it == it2.it; - } - bool operator!=(const iterator &it2) const - { - return it != it2.it; } }; @@ -82,6 +155,7 @@ public: } }; + // Find the index of an element in a range. Return -1 if not found // Range must have a random access iterator. template diff --git a/core/save-git.cpp b/core/save-git.cpp index 0e4de1867..d6937ada8 100644 --- a/core/save-git.cpp +++ b/core/save-git.cpp @@ -245,17 +245,17 @@ static void show_index(struct membuffer *b, int value, const char *pre, const ch * * For parsing, look at the units to figure out what the numbers are. */ -static void save_sample(struct membuffer *b, struct sample *sample, struct sample *old, int o2sensor) +static void save_sample(struct membuffer *b, const struct sample &sample, struct sample &old, int o2sensor) { int idx; - put_format(b, "%3u:%02u", FRACTION_TUPLE(sample->time.seconds, 60)); - put_milli(b, " ", sample->depth.mm, "m"); - put_temperature(b, sample->temperature, " ", "°C"); + put_format(b, "%3u:%02u", FRACTION_TUPLE(sample.time.seconds, 60)); + put_milli(b, " ", sample.depth.mm, "m"); + put_temperature(b, sample.temperature, " ", "°C"); for (idx = 0; idx < MAX_SENSORS; idx++) { - pressure_t p = sample->pressure[idx]; - int sensor = sample->sensor[idx]; + pressure_t p = sample.pressure[idx]; + int sensor = sample.sensor[idx]; if (sensor == NO_SENSOR) continue; @@ -266,7 +266,7 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl /* Old-style "o2sensor" syntax for CCR dives? */ if (o2sensor >= 0) { if (sensor == o2sensor) { - put_pressure(b, sample->pressure[1]," o2pressure=","bar"); + put_pressure(b, sample.pressure[1]," o2pressure=","bar"); continue; } @@ -275,11 +275,11 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl /* * Note: regardless of which index we used for the non-O2 * sensor, we know there is only one non-O2 sensor in legacy - * mode, and "old->sensor[0]" contains that index. + * mode, and "old.sensor[0]" contains that index. */ - if (sensor != old->sensor[0]) { + if (sensor != old.sensor[0]) { put_format(b, " sensor=%d", sensor); - old->sensor[0] = sensor; + old.sensor[0] = sensor; } continue; } @@ -290,88 +290,86 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl } /* the deco/ndl values are stored whenever they change */ - if (sample->ndl.seconds != old->ndl.seconds) { - put_format(b, " ndl=%u:%02u", FRACTION_TUPLE(sample->ndl.seconds, 60)); - old->ndl = sample->ndl; + if (sample.ndl.seconds != old.ndl.seconds) { + put_format(b, " ndl=%u:%02u", FRACTION_TUPLE(sample.ndl.seconds, 60)); + old.ndl = sample.ndl; } - if (sample->tts.seconds != old->tts.seconds) { - put_format(b, " tts=%u:%02u", FRACTION_TUPLE(sample->tts.seconds, 60)); - old->tts = sample->tts; + if (sample.tts.seconds != old.tts.seconds) { + put_format(b, " tts=%u:%02u", FRACTION_TUPLE(sample.tts.seconds, 60)); + old.tts = sample.tts; } - if (sample->in_deco != old->in_deco) { - put_format(b, " in_deco=%d", sample->in_deco ? 1 : 0); - old->in_deco = sample->in_deco; + if (sample.in_deco != old.in_deco) { + put_format(b, " in_deco=%d", sample.in_deco ? 1 : 0); + old.in_deco = sample.in_deco; } - if (sample->stoptime.seconds != old->stoptime.seconds) { - put_format(b, " stoptime=%u:%02u", FRACTION_TUPLE(sample->stoptime.seconds, 60)); - old->stoptime = sample->stoptime; + if (sample.stoptime.seconds != old.stoptime.seconds) { + put_format(b, " stoptime=%u:%02u", FRACTION_TUPLE(sample.stoptime.seconds, 60)); + old.stoptime = sample.stoptime; } - if (sample->stopdepth.mm != old->stopdepth.mm) { - put_milli(b, " stopdepth=", sample->stopdepth.mm, "m"); - old->stopdepth = sample->stopdepth; + if (sample.stopdepth.mm != old.stopdepth.mm) { + put_milli(b, " stopdepth=", sample.stopdepth.mm, "m"); + old.stopdepth = sample.stopdepth; } - if (sample->cns != old->cns) { - put_format(b, " cns=%u%%", sample->cns); - old->cns = sample->cns; + if (sample.cns != old.cns) { + put_format(b, " cns=%u%%", sample.cns); + old.cns = sample.cns; } - if (sample->rbt.seconds != old->rbt.seconds) { - put_format(b, " rbt=%u:%02u", FRACTION_TUPLE(sample->rbt.seconds, 60)); - old->rbt.seconds = sample->rbt.seconds; + if (sample.rbt.seconds != old.rbt.seconds) { + put_format(b, " rbt=%u:%02u", FRACTION_TUPLE(sample.rbt.seconds, 60)); + old.rbt.seconds = sample.rbt.seconds; } - if (sample->o2sensor[0].mbar != old->o2sensor[0].mbar) { - put_milli(b, " sensor1=", sample->o2sensor[0].mbar, "bar"); - old->o2sensor[0] = sample->o2sensor[0]; + if (sample.o2sensor[0].mbar != old.o2sensor[0].mbar) { + put_milli(b, " sensor1=", sample.o2sensor[0].mbar, "bar"); + old.o2sensor[0] = sample.o2sensor[0]; } - if ((sample->o2sensor[1].mbar) && (sample->o2sensor[1].mbar != old->o2sensor[1].mbar)) { - put_milli(b, " sensor2=", sample->o2sensor[1].mbar, "bar"); - old->o2sensor[1] = sample->o2sensor[1]; + if ((sample.o2sensor[1].mbar) && (sample.o2sensor[1].mbar != old.o2sensor[1].mbar)) { + put_milli(b, " sensor2=", sample.o2sensor[1].mbar, "bar"); + old.o2sensor[1] = sample.o2sensor[1]; } - if ((sample->o2sensor[2].mbar) && (sample->o2sensor[2].mbar != old->o2sensor[2].mbar)) { - put_milli(b, " sensor3=", sample->o2sensor[2].mbar, "bar"); - old->o2sensor[2] = sample->o2sensor[2]; + if ((sample.o2sensor[2].mbar) && (sample.o2sensor[2].mbar != old.o2sensor[2].mbar)) { + put_milli(b, " sensor3=", sample.o2sensor[2].mbar, "bar"); + old.o2sensor[2] = sample.o2sensor[2]; } - if ((sample->o2sensor[3].mbar) && (sample->o2sensor[3].mbar != old->o2sensor[3].mbar)) { - put_milli(b, " sensor4=", sample->o2sensor[3].mbar, "bar"); - old->o2sensor[3] = sample->o2sensor[3]; + if ((sample.o2sensor[3].mbar) && (sample.o2sensor[3].mbar != old.o2sensor[3].mbar)) { + put_milli(b, " sensor4=", sample.o2sensor[3].mbar, "bar"); + old.o2sensor[3] = sample.o2sensor[3]; } - if ((sample->o2sensor[4].mbar) && (sample->o2sensor[4].mbar != old->o2sensor[4].mbar)) { - put_milli(b, " sensor5=", sample->o2sensor[4].mbar, "bar"); - old->o2sensor[4] = sample->o2sensor[4]; + if ((sample.o2sensor[4].mbar) && (sample.o2sensor[4].mbar != old.o2sensor[4].mbar)) { + put_milli(b, " sensor5=", sample.o2sensor[4].mbar, "bar"); + old.o2sensor[4] = sample.o2sensor[4]; } - if ((sample->o2sensor[5].mbar) && (sample->o2sensor[5].mbar != old->o2sensor[5].mbar)) { - put_milli(b, " sensor6=", sample->o2sensor[5].mbar, "bar"); - old->o2sensor[5] = sample->o2sensor[5]; + if ((sample.o2sensor[5].mbar) && (sample.o2sensor[5].mbar != old.o2sensor[5].mbar)) { + put_milli(b, " sensor6=", sample.o2sensor[5].mbar, "bar"); + old.o2sensor[5] = sample.o2sensor[5]; } - if (sample->setpoint.mbar != old->setpoint.mbar) { - put_milli(b, " po2=", sample->setpoint.mbar, "bar"); - old->setpoint = sample->setpoint; + if (sample.setpoint.mbar != old.setpoint.mbar) { + put_milli(b, " po2=", sample.setpoint.mbar, "bar"); + old.setpoint = sample.setpoint; } - if (sample->heartbeat != old->heartbeat) { - show_index(b, sample->heartbeat, "heartbeat=", ""); - old->heartbeat = sample->heartbeat; + if (sample.heartbeat != old.heartbeat) { + show_index(b, sample.heartbeat, "heartbeat=", ""); + old.heartbeat = sample.heartbeat; } - if (sample->bearing.degrees != old->bearing.degrees) { - show_index(b, sample->bearing.degrees, "bearing=", "°"); - old->bearing.degrees = sample->bearing.degrees; + if (sample.bearing.degrees != old.bearing.degrees) { + show_index(b, sample.bearing.degrees, "bearing=", "°"); + old.bearing.degrees = sample.bearing.degrees; } put_format(b, "\n"); } static void save_samples(struct membuffer *b, struct dive *dive, struct divecomputer *dc) { - int nr; int o2sensor; - struct sample *s; struct sample dummy; /* Is this a CCR dive with the old-style "o2pressure" sensor? */ @@ -381,12 +379,8 @@ static void save_samples(struct membuffer *b, struct dive *dive, struct divecomp dummy.sensor[1] = o2sensor; } - s = dc->sample; - nr = dc->samples; - while (--nr >= 0) { - save_sample(b, s, &dummy, o2sensor); - s++; - } + for (const auto &s: dc->samples) + save_sample(b, s, dummy, o2sensor); } static void save_one_event(struct membuffer *b, struct dive *dive, struct event *ev) diff --git a/core/save-html.cpp b/core/save-html.cpp index 36d91dde1..aaef0e5bc 100644 --- a/core/save-html.cpp +++ b/core/save-html.cpp @@ -178,19 +178,16 @@ static void put_cylinder_HTML(struct membuffer *b, struct dive *dive) static void put_HTML_samples(struct membuffer *b, struct dive *dive) { - int i; put_format(b, "\"maxdepth\":%d,", dive->dc.maxdepth.mm); put_format(b, "\"duration\":%d,", dive->dc.duration.seconds); - struct sample *s = dive->dc.sample; - if (!dive->dc.samples) + if (dive->dc.samples.empty()) return; const char *separator = "\"samples\":["; - for (i = 0; i < dive->dc.samples; i++) { - put_format(b, "%s[%d,%d,%d,%d]", separator, s->time.seconds, s->depth.mm, s->pressure[0].mbar, s->temperature.mkelvin); + for (auto &s: dive->dc.samples) { + put_format(b, "%s[%d,%d,%d,%d]", separator, s.time.seconds, s.depth.mm, s.pressure[0].mbar, s.temperature.mkelvin); separator = ", "; - s++; } put_string(b, "],"); } diff --git a/core/save-xml.cpp b/core/save-xml.cpp index b4748649d..9089295cb 100644 --- a/core/save-xml.cpp +++ b/core/save-xml.cpp @@ -232,15 +232,15 @@ static void show_index(struct membuffer *b, int value, const char *pre, const ch show_integer(b, value, pre, post); } -static void save_sample(struct membuffer *b, struct sample *sample, struct sample *old, int o2sensor) +static void save_sample(struct membuffer *b, const struct sample &sample, struct sample &old, int o2sensor) { int idx; - put_format(b, " time.seconds, 60)); - put_milli(b, " depth='", sample->depth.mm, " m'"); - if (sample->temperature.mkelvin && sample->temperature.mkelvin != old->temperature.mkelvin) { - put_temperature(b, sample->temperature, " temp='", " C'"); - old->temperature = sample->temperature; + put_format(b, " pressure[idx]; - int sensor = sample->sensor[idx]; + pressure_t p = sample.pressure[idx]; + int sensor = sample.sensor[idx]; if (sensor == NO_SENSOR) continue; @@ -264,9 +264,9 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl continue; } put_pressure(b, p, " pressure='", " bar'"); - if (sensor != old->sensor[0]) { + if (sensor != old.sensor[0]) { put_format(b, " sensor='%d'", sensor); - old->sensor[0] = sensor; + old.sensor[0] = sensor; } continue; } @@ -277,78 +277,78 @@ static void save_sample(struct membuffer *b, struct sample *sample, struct sampl } /* the deco/ndl values are stored whenever they change */ - if (sample->ndl.seconds != old->ndl.seconds) { - put_format(b, " ndl='%u:%02u min'", FRACTION_TUPLE(sample->ndl.seconds, 60)); - old->ndl = sample->ndl; + if (sample.ndl.seconds != old.ndl.seconds) { + put_format(b, " ndl='%u:%02u min'", FRACTION_TUPLE(sample.ndl.seconds, 60)); + old.ndl = sample.ndl; } - if (sample->tts.seconds != old->tts.seconds) { - put_format(b, " tts='%u:%02u min'", FRACTION_TUPLE(sample->tts.seconds, 60)); - old->tts = sample->tts; + if (sample.tts.seconds != old.tts.seconds) { + put_format(b, " tts='%u:%02u min'", FRACTION_TUPLE(sample.tts.seconds, 60)); + old.tts = sample.tts; } - if (sample->rbt.seconds != old->rbt.seconds) { - put_format(b, " rbt='%u:%02u min'", FRACTION_TUPLE(sample->rbt.seconds, 60)); - old->rbt = sample->rbt; + if (sample.rbt.seconds != old.rbt.seconds) { + put_format(b, " rbt='%u:%02u min'", FRACTION_TUPLE(sample.rbt.seconds, 60)); + old.rbt = sample.rbt; } - if (sample->in_deco != old->in_deco) { - put_format(b, " in_deco='%d'", sample->in_deco ? 1 : 0); - old->in_deco = sample->in_deco; + if (sample.in_deco != old.in_deco) { + put_format(b, " in_deco='%d'", sample.in_deco ? 1 : 0); + old.in_deco = sample.in_deco; } - if (sample->stoptime.seconds != old->stoptime.seconds) { - put_format(b, " stoptime='%u:%02u min'", FRACTION_TUPLE(sample->stoptime.seconds, 60)); - old->stoptime = sample->stoptime; + if (sample.stoptime.seconds != old.stoptime.seconds) { + put_format(b, " stoptime='%u:%02u min'", FRACTION_TUPLE(sample.stoptime.seconds, 60)); + old.stoptime = sample.stoptime; } - if (sample->stopdepth.mm != old->stopdepth.mm) { - put_milli(b, " stopdepth='", sample->stopdepth.mm, " m'"); - old->stopdepth = sample->stopdepth; + if (sample.stopdepth.mm != old.stopdepth.mm) { + put_milli(b, " stopdepth='", sample.stopdepth.mm, " m'"); + old.stopdepth = sample.stopdepth; } - if (sample->cns != old->cns) { - put_format(b, " cns='%u%%'", sample->cns); - old->cns = sample->cns; + if (sample.cns != old.cns) { + put_format(b, " cns='%u%%'", sample.cns); + old.cns = sample.cns; } - if ((sample->o2sensor[0].mbar) && (sample->o2sensor[0].mbar != old->o2sensor[0].mbar)) { - put_milli(b, " sensor1='", sample->o2sensor[0].mbar, " bar'"); - old->o2sensor[0] = sample->o2sensor[0]; + if ((sample.o2sensor[0].mbar) && (sample.o2sensor[0].mbar != old.o2sensor[0].mbar)) { + put_milli(b, " sensor1='", sample.o2sensor[0].mbar, " bar'"); + old.o2sensor[0] = sample.o2sensor[0]; } - if ((sample->o2sensor[1].mbar) && (sample->o2sensor[1].mbar != old->o2sensor[1].mbar)) { - put_milli(b, " sensor2='", sample->o2sensor[1].mbar, " bar'"); - old->o2sensor[1] = sample->o2sensor[1]; + if ((sample.o2sensor[1].mbar) && (sample.o2sensor[1].mbar != old.o2sensor[1].mbar)) { + put_milli(b, " sensor2='", sample.o2sensor[1].mbar, " bar'"); + old.o2sensor[1] = sample.o2sensor[1]; } - if ((sample->o2sensor[2].mbar) && (sample->o2sensor[2].mbar != old->o2sensor[2].mbar)) { - put_milli(b, " sensor3='", sample->o2sensor[2].mbar, " bar'"); - old->o2sensor[2] = sample->o2sensor[2]; + if ((sample.o2sensor[2].mbar) && (sample.o2sensor[2].mbar != old.o2sensor[2].mbar)) { + put_milli(b, " sensor3='", sample.o2sensor[2].mbar, " bar'"); + old.o2sensor[2] = sample.o2sensor[2]; } - if ((sample->o2sensor[3].mbar) && (sample->o2sensor[3].mbar != old->o2sensor[3].mbar)) { - put_milli(b, " sensor4='", sample->o2sensor[3].mbar, " bar'"); - old->o2sensor[3] = sample->o2sensor[3]; + if ((sample.o2sensor[3].mbar) && (sample.o2sensor[3].mbar != old.o2sensor[3].mbar)) { + put_milli(b, " sensor4='", sample.o2sensor[3].mbar, " bar'"); + old.o2sensor[3] = sample.o2sensor[3]; } - if ((sample->o2sensor[4].mbar) && (sample->o2sensor[4].mbar != old->o2sensor[4].mbar)) { - put_milli(b, " sensor5='", sample->o2sensor[4].mbar, " bar'"); - old->o2sensor[4] = sample->o2sensor[4]; + if ((sample.o2sensor[4].mbar) && (sample.o2sensor[4].mbar != old.o2sensor[4].mbar)) { + put_milli(b, " sensor5='", sample.o2sensor[4].mbar, " bar'"); + old.o2sensor[4] = sample.o2sensor[4]; } - if ((sample->o2sensor[5].mbar) && (sample->o2sensor[5].mbar != old->o2sensor[5].mbar)) { - put_milli(b, " sensor6='", sample->o2sensor[5].mbar, " bar'"); - old->o2sensor[5] = sample->o2sensor[5]; + if ((sample.o2sensor[5].mbar) && (sample.o2sensor[5].mbar != old.o2sensor[5].mbar)) { + put_milli(b, " sensor6='", sample.o2sensor[5].mbar, " bar'"); + old.o2sensor[5] = sample.o2sensor[5]; } - if (sample->setpoint.mbar != old->setpoint.mbar) { - put_milli(b, " po2='", sample->setpoint.mbar, " bar'"); - old->setpoint = sample->setpoint; + if (sample.setpoint.mbar != old.setpoint.mbar) { + put_milli(b, " po2='", sample.setpoint.mbar, " bar'"); + old.setpoint = sample.setpoint; } - if (sample->heartbeat != old->heartbeat) { - show_index(b, sample->heartbeat, "heartbeat='", "'"); - old->heartbeat = sample->heartbeat; + if (sample.heartbeat != old.heartbeat) { + show_index(b, sample.heartbeat, "heartbeat='", "'"); + old.heartbeat = sample.heartbeat; } - if (sample->bearing.degrees != old->bearing.degrees) { - show_index(b, sample->bearing.degrees, "bearing='", "'"); - old->bearing.degrees = sample->bearing.degrees; + if (sample.bearing.degrees != old.bearing.degrees) { + show_index(b, sample.bearing.degrees, "bearing='", "'"); + old.bearing.degrees = sample.bearing.degrees; } put_format(b, " />\n"); } @@ -423,9 +423,7 @@ static void show_date(struct membuffer *b, timestamp_t when) static void save_samples(struct membuffer *b, struct dive *dive, struct divecomputer *dc) { - int nr; int o2sensor; - struct sample *s; struct sample dummy; /* Set up default pressure sensor indices */ @@ -435,12 +433,8 @@ static void save_samples(struct membuffer *b, struct dive *dive, struct divecomp dummy.sensor[1] = o2sensor; } - s = dc->sample; - nr = dc->samples; - while (--nr >= 0) { - save_sample(b, s, &dummy, o2sensor); - s++; - } + for (const auto &s: dc->samples) + save_sample(b, s, dummy, o2sensor); } static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer *dc) diff --git a/core/statistics.cpp b/core/statistics.cpp index fce4a5690..40843ba43 100644 --- a/core/statistics.cpp +++ b/core/statistics.cpp @@ -262,8 +262,8 @@ bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc, bool first_gas_explicit = false; const struct event *event = get_next_event(dc->events, "gaschange"); while (event) { - if (dc->sample && (event->time.seconds == 0 || - (dc->samples && dc->sample[0].time.seconds == event->time.seconds))) + if (!dc->samples.empty() && (event->time.seconds == 0 || + (dc->samples[0].time.seconds == event->time.seconds))) first_gas_explicit = true; if (get_cylinder_index(dive, event) == idx) return true; diff --git a/core/uemis.cpp b/core/uemis.cpp index 7ff20ea3e..1e7f1413b 100644 --- a/core/uemis.cpp +++ b/core/uemis.cpp @@ -349,7 +349,6 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive) add_sample_pressure(sample, active, (u_sample->tank_pressure_high * 256 + u_sample->tank_pressure_low) * 10); sample->cns = u_sample->cns; event(dive, dc, sample, u_sample); - finish_sample(dc); i += 0x25; u_sample++; } diff --git a/desktop-widgets/modeldelegates.cpp b/desktop-widgets/modeldelegates.cpp index 0346a9a3e..49fe3e74d 100644 --- a/desktop-widgets/modeldelegates.cpp +++ b/desktop-widgets/modeldelegates.cpp @@ -298,8 +298,7 @@ QWidget *SensorDelegate::createEditor(QWidget *parent, const QStyleOptionViewIte return comboBox; std::vector sensors; - for (int i = 0; i < currentdc->samples; ++i) { - auto &sample = currentdc->sample[i]; + for (const auto &sample: currentdc->samples) { for (int s = 0; s < MAX_SENSORS; ++s) { if (sample.pressure[s].mbar) { if (std::find(sensors.begin(), sensors.end(), sample.sensor[s]) == sensors.end()) diff --git a/desktop-widgets/profilewidget.cpp b/desktop-widgets/profilewidget.cpp index ad9e35fd7..3d44b4cf6 100644 --- a/desktop-widgets/profilewidget.cpp +++ b/desktop-widgets/profilewidget.cpp @@ -218,7 +218,7 @@ void ProfileWidget::plotDive(dive *dIn, int dcIn) if (d && !editedDive && DivePlannerPointsModel::instance()->currentMode() == DivePlannerPointsModel::NOTHING) { struct divecomputer *comp = get_dive_dc(d, dc); - if (comp && is_dc_manually_added_dive(comp) && comp->samples && comp->samples <= 50) + if (comp && is_dc_manually_added_dive(comp) && !comp->samples.empty() && comp->samples.size() <= 50) editDive(); } diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index a9951ee16..cb8fe5ae7 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -38,6 +38,7 @@ #include "core/subsurface-string.h" #include "core/string-format.h" #include "core/pref.h" +#include "core/sample.h" #include "core/selection.h" #include "core/save-profiledata.h" #include "core/settings/qPrefLog.h" @@ -1135,7 +1136,7 @@ bool QMLManager::checkDuration(struct dive *d, QString duration) } d->dc.duration.seconds = d->duration.seconds = h * 3600 + m * 60 + s; if (is_dc_manually_added_dive(&d->dc)) - free_samples(&d->dc); + d->dc.samples.clear(); else appendTextToLog("Cannot change the duration on a dive that wasn't manually added"); return true; @@ -1154,7 +1155,7 @@ bool QMLManager::checkDepth(dive *d, QString depth) d->maxdepth.mm = depthValue; if (is_dc_manually_added_dive(&d->dc)) { d->dc.maxdepth.mm = d->maxdepth.mm; - free_samples(&d->dc); + d->dc.samples.clear(); } return true; } @@ -1358,7 +1359,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt if (d->maxdepth.mm == d->dc.maxdepth.mm && d->maxdepth.mm > 0 && is_dc_manually_added_dive(&d->dc) && - d->dc.samples == 0) { + d->dc.samples.empty()) { // so we have depth > 0, a manually added dive and no samples // let's create an actual profile so the desktop version can work it // first clear out the mean depth (or the fake_dc() function tries diff --git a/profile-widget/diveeventitem.cpp b/profile-widget/diveeventitem.cpp index dac9a649f..aa12bf021 100644 --- a/profile-widget/diveeventitem.cpp +++ b/profile-widget/diveeventitem.cpp @@ -201,10 +201,9 @@ bool DiveEventItem::isInteresting(const struct dive *d, const struct divecompute * Some gas change events are special. Some dive computers just tell us the initial gas this way. * Don't bother showing those */ - const struct sample *first_sample = &dc->sample[0]; if (ev->name == "gaschange" && (ev->time.seconds == 0 || - (first_sample && ev->time.seconds == first_sample->time.seconds) || + (!dc->samples.empty() && ev->time.seconds == dc->samples[0].time.seconds) || depthAtTime(pi, ev->time) < SURFACE_THRESHOLD)) return false; diff --git a/profile-widget/profilescene.cpp b/profile-widget/profilescene.cpp index 4ae91c378..d847229b3 100644 --- a/profile-widget/profilescene.cpp +++ b/profile-widget/profilescene.cpp @@ -428,7 +428,7 @@ void ProfileScene::plotDive(const struct dive *dIn, int dcIn, DivePlannerPointsM } const struct divecomputer *currentdc = get_dive_dc_const(d, dc); - if (!currentdc || !currentdc->samples) { + if (!currentdc || currentdc->samples.empty()) { clear(); return; } diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index 42829df38..26a5df057 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -242,8 +242,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const case SENSORS: { std::vector sensors; const struct divecomputer *currentdc = get_dive_dc(d, dcNr); - for (int i = 0; i < currentdc->samples; ++i) { - auto &sample = currentdc->sample[i]; + for (const auto &sample: currentdc->samples) { for (int s = 0; s < MAX_SENSORS; ++s) { if (sample.pressure[s].mbar) { if (sample.sensor[s] == index.row()) diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index a3370c26d..6a976d5f6 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -138,14 +138,14 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn) bool hasMarkedSamples = false; - if (dc->samples) - hasMarkedSamples = dc->sample[0].manually_entered; + if (!dc->samples.empty()) + hasMarkedSamples = dc->samples[0].manually_entered; else fake_dc(dc); // if this dive has more than 100 samples (so it is probably a logged dive), // average samples so we end up with a total of 100 samples. - int plansamples = dc->samples <= 100 ? dc->samples : 100; + int plansamples = std::min(static_cast(dc->samples.size()), 100); int j = 0; int cylinderid = 0; @@ -153,12 +153,12 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn) for (int i = 0; i < plansamples - 1; i++) { if (dc->last_manual_time.seconds && dc->last_manual_time.seconds > 120 && lasttime.seconds >= dc->last_manual_time.seconds) break; - while (j * plansamples <= i * dc->samples) { - const sample &s = dc->sample[j]; + while (j * plansamples <= i * static_cast(dc->samples.size())) { + const sample &s = dc->samples[j]; if (s.time.seconds != 0 && (!hasMarkedSamples || s.manually_entered)) { depthsum += s.depth.mm; if (j > 0) - last_sp = dc->sample[j-1].setpoint; + last_sp = dc->samples[j-1].setpoint; ++samplecount; newtime = s.time; }