From 28520da65574866cdd7cf0d0ed8f0c062970cdb6 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Tue, 28 May 2024 21:31:11 +0200 Subject: [PATCH] core: convert cylinder_t and cylinder_table to C++ This had to be done simultaneously, because the table macros do not work properly with C++ objects. Signed-off-by: Berthold Stoeger --- backend-shared/exportfuncs.cpp | 8 +- commands/command_divelist.cpp | 2 +- commands/command_edit.cpp | 52 ++-- core/cochran.cpp | 15 +- core/datatrak.cpp | 13 +- core/dive.cpp | 255 ++++++++---------- core/dive.h | 5 +- core/divelist.cpp | 21 +- core/equipment.cpp | 200 +++++++------- core/equipment.h | 37 +-- core/filterconstraint.cpp | 21 +- core/fulltext.cpp | 6 +- core/gas.cpp | 12 +- core/gas.h | 2 +- core/gaspressures.cpp | 4 +- core/import-csv.cpp | 45 ++-- core/import-divinglog.cpp | 2 +- core/import-shearwater.cpp | 21 +- core/libdivecomputer.cpp | 10 +- core/liquivision.cpp | 3 +- core/load-git.cpp | 8 +- core/parse-xml.cpp | 25 +- core/parse.cpp | 2 +- core/planner.cpp | 18 +- core/plannernotes.cpp | 44 +-- core/profile.cpp | 35 ++- core/profile.h | 2 +- core/qthelper.cpp | 13 +- core/save-git.cpp | 25 +- core/save-html.cpp | 33 ++- core/save-xml.cpp | 26 +- core/statistics.cpp | 27 +- core/string-format.cpp | 78 +++--- core/uemis.cpp | 2 +- desktop-widgets/profilewidget.cpp | 2 +- desktop-widgets/simplewidgets.cpp | 8 +- .../tab-widgets/TabDiveInformation.cpp | 8 +- desktop-widgets/templatelayout.cpp | 8 +- mobile-widgets/qmlmanager.cpp | 2 +- profile-widget/diveprofileitem.cpp | 7 +- profile-widget/profilewidget2.cpp | 28 +- profile-widget/tankitem.cpp | 2 +- qt-models/cylindermodel.cpp | 73 +++-- qt-models/diveplannermodel.cpp | 22 +- qt-models/divesummarymodel.cpp | 9 +- qt-models/divetripmodel.cpp | 19 +- smtk-import/smartrak.cpp | 15 +- stats/statsvariables.cpp | 28 +- 48 files changed, 593 insertions(+), 710 deletions(-) diff --git a/backend-shared/exportfuncs.cpp b/backend-shared/exportfuncs.cpp index 65bf89155..6a3bf1c96 100644 --- a/backend-shared/exportfuncs.cpp +++ b/backend-shared/exportfuncs.cpp @@ -205,10 +205,10 @@ void export_TeX(const char *filename, bool selected_only, bool plain, ExportCall // Print cylinder data put_format(&buf, "\n%% Gas use information:\n"); qty_cyl = 0; - for (i = 0; i < dive->cylinders.nr; i++){ - const cylinder_t &cyl = *get_cylinder(dive, i); - if (is_cylinder_used(dive, i) || (prefs.include_unused_tanks && cyl.type.description)){ - put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description); + for (int i = 0; i < static_cast(dive->cylinders.size()); i++){ + const cylinder_t &cyl = dive->cylinders[i]; + if (is_cylinder_used(dive, i) || (prefs.include_unused_tanks && !cyl.type.description.empty())){ + put_format(&buf, "\\def\\%scyl%cdescription{%s}\n", ssrf, 'a' + i, cyl.type.description.c_str()); put_format(&buf, "\\def\\%scyl%cgasname{%s}\n", ssrf, 'a' + i, gasname(cyl.gasmix)); put_format(&buf, "\\def\\%scyl%cmixO2{%.1f\\%%}\n", ssrf, 'a' + i, get_o2(cyl.gasmix)/10.0); put_format(&buf, "\\def\\%scyl%cmixHe{%.1f\\%%}\n", ssrf, 'a' + i, get_he(cyl.gasmix)/10.0); diff --git a/commands/command_divelist.cpp b/commands/command_divelist.cpp index 49f16b8bd..f745f2955 100644 --- a/commands/command_divelist.cpp +++ b/commands/command_divelist.cpp @@ -962,7 +962,7 @@ MergeDives::MergeDives(const QVector &dives) { setText(Command::Base::tr("merge dive")); - // Just a safety check - if there's not two or more dives - do nothing + // Just a safety check - if there's not two or more dives - do nothing. // The caller should have made sure that this doesn't happen. if (dives.count() < 2) { qWarning("Merging less than two dives"); diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index 5d5976068..1864588ed 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -629,7 +629,6 @@ static void swapCandQString(QString &q, char *&c) PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dIn), tags(nullptr) { - memset(&cylinders, 0, sizeof(cylinders)); memset(&weightsystems, 0, sizeof(weightsystems)); if (what.notes) notes = data->notes; @@ -656,14 +655,14 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI if (what.tags) tags = taglist_copy(data->tag_list); if (what.cylinders) { - copy_cylinders(&data->cylinders, &cylinders); + cylinders = data->cylinders; // Paste cylinders is "special": // 1) For cylinders that exist in the destination dive we keep the gas-mix and pressures. // 2) For cylinders that do not yet exist in the destination dive, we set the pressures to 0, i.e. unset. // Moreover, for these we set the manually_added flag, because they weren't downloaded from a DC. - for (int i = 0; i < d->cylinders.nr && i < cylinders.nr; ++i) { - const cylinder_t &src = *get_cylinder(d, i); - cylinder_t &dst = cylinders.cylinders[i]; + for (size_t i = 0; i < d->cylinders.size() && i < cylinders.size(); ++i) { + const cylinder_t &src = d->cylinders[i]; + cylinder_t &dst = cylinders[i]; dst.gasmix = src.gasmix; dst.start = src.start; dst.end = src.end; @@ -677,8 +676,8 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI dst.bestmix_o2 = src.bestmix_o2; dst.bestmix_he = src.bestmix_he; } - for (int i = d->cylinders.nr; i < cylinders.nr; ++i) { - cylinder_t &cyl = cylinders.cylinders[i]; + for (size_t i = d->cylinders.size(); i < cylinders.size(); ++i) { + cylinder_t &cyl = cylinders[i]; cyl.start.mbar = 0; cyl.end.mbar = 0; cyl.sample_start.mbar = 0; @@ -697,7 +696,6 @@ PasteState::PasteState(dive *dIn, const dive *data, dive_components what) : d(dI PasteState::~PasteState() { taglist_free(tags); - clear_cylinder_table(&cylinders); clear_weightsystem_table(&weightsystems); free(weightsystems.weightsystems); } @@ -803,7 +801,6 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive), duration({0}), salinity(0) { - memset(&cylinders, 0, sizeof(cylinders)); if (!d) return; @@ -828,7 +825,6 @@ ReplanDive::ReplanDive(dive *source) : d(current_dive), ReplanDive::~ReplanDive() { - clear_cylinder_table(&cylinders); free(notes); } @@ -1124,7 +1120,6 @@ AddCylinder::AddCylinder(bool currentDiveOnly) : AddCylinder::~AddCylinder() { - free_cylinder(cyl); } bool AddCylinder::workToBeDone() @@ -1148,7 +1143,7 @@ void AddCylinder::redo() for (dive *d: dives) { int index = first_hidden_cylinder(d); indexes.push_back(index); - add_cylinder(&d->cylinders, index, clone_cylinder(cyl)); + add_cylinder(&d->cylinders, index, cyl); update_cylinder_related_info(d); emit diveListNotifier.cylinderAdded(d, index); invalidate_dive_cache(d); // Ensure that dive is written in git_save() @@ -1157,14 +1152,14 @@ void AddCylinder::redo() static bool same_cylinder_type(const cylinder_t &cyl1, const cylinder_t &cyl2) { - return same_string(cyl1.type.description, cyl2.type.description) && - cyl1.cylinder_use == cyl2.cylinder_use; + return std::tie(cyl1.cylinder_use, cyl1.type.description) == + std::tie(cyl2.cylinder_use, cyl2.type.description); } static bool same_cylinder_size(const cylinder_t &cyl1, const cylinder_t &cyl2) { - return cyl1.type.size.mliter == cyl2.type.size.mliter && - cyl1.type.workingpressure.mbar == cyl2.type.workingpressure.mbar; + return std::tie(cyl1.type.size.mliter, cyl1.type.workingpressure.mbar) == + std::tie(cyl2.type.size.mliter, cyl2.type.workingpressure.mbar); } // Flags for comparing cylinders @@ -1177,7 +1172,7 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt EditDivesBase(currentDiveOnly) { // Get the old cylinder, bail if index is invalid - if (!current || index < 0 || index >= current->cylinders.nr) { + if (!current || index < 0 || index >= static_cast(current->cylinders.size())) { dives.clear(); return; } @@ -1189,12 +1184,12 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt cyl.reserve(dives.size()); for (dive *d: dives) { - if (index >= d->cylinders.nr) + if (index >= static_cast(d->cylinders.size())) continue; if (nonProtectedOnly && is_cylinder_prot(d, index)) continue; // We checked that the cylinder exists above. - const cylinder_t &cylinder = *get_cylinder(d, index); + const cylinder_t &cylinder = d->cylinders[index]; if (d != current && (!same_cylinder_size(orig, cylinder) || !same_cylinder_type(orig, cylinder))) { // when editing cylinders, we assume that the user wanted to edit the 'n-th' cylinder @@ -1206,15 +1201,13 @@ EditCylinderBase::EditCylinderBase(int index, bool currentDiveOnly, bool nonProt // that's silly as it's always the same value - but we need this vector of indices in the case where we add // a cylinder to several dives as the spot will potentially be different in different dives indexes.push_back(index); - cyl.push_back(clone_cylinder(cylinder)); + cyl.push_back(cylinder); } dives = std::move(divesNew); } EditCylinderBase::~EditCylinderBase() { - for (cylinder_t c: cyl) - free_cylinder(c); } bool EditCylinderBase::workToBeDone() @@ -1235,8 +1228,8 @@ RemoveCylinder::RemoveCylinder(int index, bool currentDiveOnly) : void RemoveCylinder::undo() { for (size_t i = 0; i < dives.size(); ++i) { - std::vector mapping = get_cylinder_map_for_add(dives[i]->cylinders.nr, indexes[i]); - add_cylinder(&dives[i]->cylinders, indexes[i], clone_cylinder(cyl[i])); + std::vector mapping = get_cylinder_map_for_add(dives[i]->cylinders.size(), indexes[i]); + add_cylinder(&dives[i]->cylinders, indexes[i], cyl[i]); cylinder_renumber(dives[i], &mapping[0]); update_cylinder_related_info(dives[i]); emit diveListNotifier.cylinderAdded(dives[i], indexes[i]); @@ -1247,7 +1240,7 @@ void RemoveCylinder::undo() void RemoveCylinder::redo() { for (size_t i = 0; i < dives.size(); ++i) { - std::vector mapping = get_cylinder_map_for_remove(dives[i]->cylinders.nr, indexes[i]); + std::vector mapping = get_cylinder_map_for_remove(dives[i]->cylinders.size(), indexes[i]); remove_cylinder(dives[i], indexes[i]); cylinder_renumber(dives[i], &mapping[0]); update_cylinder_related_info(dives[i]); @@ -1282,15 +1275,12 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn, else setText(Command::Base::tr("Edit cylinder (%n dive(s))", "", dives.size())); - QString description = cylIn.type.description; - // The base class copied the cylinders for us, let's edit them for (int i = 0; i < (int)indexes.size(); ++i) { switch (type) { case EditCylinderType::TYPE: - free((void *)cyl[i].type.description); cyl[i].type = cylIn.type; - cyl[i].type.description = copy_qstring(description); + cyl[i].type.description = cylIn.type.description; cyl[i].cylinder_use = cylIn.cylinder_use; break; case EditCylinderType::PRESSURE: @@ -1301,7 +1291,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn, cyl[i].gasmix = cylIn.gasmix; cyl[i].bestmix_o2 = cylIn.bestmix_o2; cyl[i].bestmix_he = cylIn.bestmix_he; - sanitize_gasmix(&cyl[i].gasmix); + sanitize_gasmix(cyl[i].gasmix); break; } } @@ -1310,7 +1300,7 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn, void EditCylinder::redo() { for (size_t i = 0; i < dives.size(); ++i) { - std::string name = cyl[i].type.description; + const std::string &name = cyl[i].type.description; set_tank_info_data(tank_info_table, name, cyl[i].type.size, cyl[i].type.workingpressure); std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]); update_cylinder_related_info(dives[i]); diff --git a/core/cochran.cpp b/core/cochran.cpp index d39d73ef7..5cad4cd0b 100644 --- a/core/cochran.cpp +++ b/core/cochran.cpp @@ -672,24 +672,22 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod, case TYPE_GEMINI: case TYPE_COMMANDER: if (config.type == TYPE_GEMINI) { - cylinder_t cyl; dc->model = "Gemini"; dc->deviceid = buf[0x18c] * 256 + buf[0x18d]; // serial no - fill_default_cylinder(dive.get(), &cyl); + cylinder_t cyl = default_cylinder(dive.get()); cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT] / 256 + log[CMD_O2_PERCENT + 1]) * 10; cyl.gasmix.he.permille = 0; - add_cylinder(&dive->cylinders, 0, cyl); + add_cylinder(&dive->cylinders, 0, std::move(cyl)); } else { dc->model = "Commander"; dc->deviceid = array_uint32_le(buf + 0x31e); // serial no for (g = 0; g < 2; g++) { - cylinder_t cyl; - fill_default_cylinder(dive.get(), &cyl); + cylinder_t cyl = default_cylinder(dive.get()); cyl.gasmix.o2.permille = (log[CMD_O2_PERCENT + g * 2] / 256 + log[CMD_O2_PERCENT + g * 2 + 1]) * 10; cyl.gasmix.he.permille = 0; - add_cylinder(&dive->cylinders, g, cyl); + add_cylinder(&dive->cylinders, g, std::move(cyl)); } } @@ -727,15 +725,14 @@ static void cochran_parse_dive(const unsigned char *decode, unsigned mod, dc->model = "EMC"; dc->deviceid = array_uint32_le(buf + 0x31e); // serial no for (g = 0; g < 4; g++) { - cylinder_t cyl; - fill_default_cylinder(dive.get(), &cyl); + cylinder_t cyl = default_cylinder(dive.get()); cyl.gasmix.o2.permille = (log[EMC_O2_PERCENT + g * 2] / 256 + log[EMC_O2_PERCENT + g * 2 + 1]) * 10; cyl.gasmix.he.permille = (log[EMC_HE_PERCENT + g * 2] / 256 + log[EMC_HE_PERCENT + g * 2 + 1]) * 10; - add_cylinder(&dive->cylinders, g, cyl); + add_cylinder(&dive->cylinders, g, std::move(cyl)); } tm.tm_year = log[EMC_YEAR]; diff --git a/core/datatrak.cpp b/core/datatrak.cpp index 2e4b59b8b..43da325a1 100644 --- a/core/datatrak.cpp +++ b/core/datatrak.cpp @@ -334,14 +334,13 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct read_bytes(2); if (tmp_2bytes != 0x7FFF) { cylinder_t cyl; - std::string desc = cyl_type_by_size(tmp_2bytes * 10); cyl.type.size.mliter = tmp_2bytes * 10; - cyl.type.description = desc.c_str(); + cyl.type.description = cyl_type_by_size(tmp_2bytes * 10); cyl.start.mbar = 200000; cyl.gasmix.he.permille = 0; cyl.gasmix.o2.permille = 210; cyl.manually_added = true; - add_cloned_cylinder(&dt_dive->cylinders, cyl); + dt_dive->cylinders.push_back(std::move(cyl)); } /* @@ -372,7 +371,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct * Air used in bar*100. */ read_bytes(2); - if (tmp_2bytes != 0x7FFF && dt_dive->cylinders.nr > 0) + if (tmp_2bytes != 0x7FFF && dt_dive->cylinders.size() > 0) get_cylinder(dt_dive, 0)->gas_used.mliter = lrint(get_cylinder(dt_dive, 0)->type.size.mliter * (tmp_2bytes / 100.0)); /* @@ -548,10 +547,10 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct free(compl_buffer); goto bail; } - if (is_nitrox && dt_dive->cylinders.nr > 0) + if (is_nitrox && dt_dive->cylinders.size() > 0) get_cylinder(dt_dive, 0)->gasmix.o2.permille = lrint(membuf[23] & 0x0F ? 20.0 + 2 * (membuf[23] & 0x0F) : 21.0) * 10; - if (is_O2 && dt_dive->cylinders.nr > 0) + if (is_O2 && dt_dive->cylinders.size() > 0) get_cylinder(dt_dive, 0)->gasmix.o2.permille = membuf[23] * 10; free(compl_buffer); } @@ -564,7 +563,7 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct dt_dive->dcs[0].deviceid = 0; else dt_dive->dcs[0].deviceid = 0xffffffff; - if (!is_SCR && dt_dive->cylinders.nr > 0) { + if (!is_SCR && dt_dive->cylinders.size() > 0) { get_cylinder(dt_dive, 0)->end.mbar = get_cylinder(dt_dive, 0)->start.mbar - ((get_cylinder(dt_dive, 0)->gas_used.mliter / get_cylinder(dt_dive, 0)->type.size.mliter) * 1000); } diff --git a/core/dive.cpp b/core/dive.cpp index a60657951..20687e392 100644 --- a/core/dive.cpp +++ b/core/dive.cpp @@ -17,6 +17,7 @@ #include "errorhelper.h" #include "event.h" #include "extradata.h" +#include "format.h" #include "interpolate.h" #include "qthelper.h" #include "membuffer.h" @@ -121,8 +122,8 @@ void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int second /* sanity check so we don't crash */ /* FIXME: The planner uses a dummy cylinder one past the official number of cylinders * in the table to mark no-cylinder surface interavals. This is horrendous. Fix ASAP. */ - //if (idx < 0 || idx >= dive->cylinders.nr) { - if (idx < 0 || idx >= dive->cylinders.nr + 1 || idx >= dive->cylinders.allocated) { + //if (idx < 0 || idx >= dive->cylinders.size()) { + if (idx < 0 || static_cast(idx) >= dive->cylinders.size() + 1) { report_error("Unknown cylinder index: %d", idx); return; } @@ -135,9 +136,7 @@ struct gasmix get_gasmix_from_event(const struct dive *dive, const struct event if (ev.is_gaschange()) { int index = ev.gas.index; // FIXME: The planner uses one past cylinder-count to signify "surface air". Remove in due course. - if (index == dive->cylinders.nr) - return gasmix_air; - if (index >= 0 && index < dive->cylinders.nr) + if (index >= 0 && static_cast(index) < dive->cylinders.size() + 1) return get_cylinder(dive, index)->gasmix; return ev.gas.mix; } @@ -176,8 +175,7 @@ static void free_dive_structures(struct dive *d) free(d->suit); /* free tags, additional dive computers, and pictures */ taglist_free(d->tag_list); - clear_cylinder_table(&d->cylinders); - free(d->cylinders.cylinders); + d->cylinders.clear(); clear_weightsystem_table(&d->weightsystems); free(d->weightsystems.weightsystems); clear_picture_table(&d->pictures); @@ -185,7 +183,7 @@ static void free_dive_structures(struct dive *d) } /* copy_dive makes duplicates of many components of a dive; - * in order not to leak memory, we need to free those . + * in order not to leak memory, we need to free those. * copy_dive doesn't play with the divetrip and forward/backward pointers * so we can ignore those */ void clear_dive(struct dive *d) @@ -206,7 +204,6 @@ void copy_dive(const struct dive *s, struct dive *d) * relevant components that are referenced through pointers, * so all the strings and the structured lists */ *d = *s; - memset(&d->cylinders, 0, sizeof(d->cylinders)); memset(&d->weightsystems, 0, sizeof(d->weightsystems)); memset(&d->pictures, 0, sizeof(d->pictures)); d->full_text = NULL; @@ -215,7 +212,6 @@ void copy_dive(const struct dive *s, struct dive *d) d->diveguide = copy_string(s->diveguide); d->notes = copy_string(s->notes); d->suit = copy_string(s->suit); - copy_cylinders(&s->cylinders, &d->cylinders); copy_weights(&s->weightsystems, &d->weightsystems); copy_pictures(&s->pictures, &d->pictures); d->tag_list = taglist_copy(s->tag_list); @@ -293,11 +289,6 @@ void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int tim } } -int nr_cylinders(const struct dive *dive) -{ - return dive->cylinders.nr; -} - int nr_weightsystems(const struct dive *dive) { return dive->weightsystems.nr; @@ -305,14 +296,13 @@ int nr_weightsystems(const struct dive *dive) void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only) { - int i; if (!s || !d) return; - clear_cylinder_table(&d->cylinders); - for (i = 0; i < s->cylinders.nr; i++) { + d->cylinders.clear(); + for (auto [i, cyl]: enumerated_range(s->cylinders)) { if (!used_only || is_cylinder_used(s, i) || get_cylinder(s, i)->cylinder_use == NOT_USED) - add_cloned_cylinder(&d->cylinders, *get_cylinder(s, i)); + d->cylinders.push_back(cyl); } } @@ -354,12 +344,12 @@ static void update_temperature(temperature_t *temperature, int new_temp) /* Which cylinders had gas used? */ #define SOME_GAS 5000 -static bool cylinder_used(const cylinder_t *cyl) +static bool cylinder_used(const cylinder_t &cyl) { int start_mbar, end_mbar; - start_mbar = cyl->start.mbar ?: cyl->sample_start.mbar; - end_mbar = cyl->end.mbar ?: cyl->sample_end.mbar; + start_mbar = cyl.start.mbar ?: cyl.sample_start.mbar; + end_mbar = cyl.end.mbar ?: cyl.sample_end.mbar; // More than 5 bar used? This matches statistics.cpp // heuristics @@ -369,10 +359,10 @@ static bool cylinder_used(const cylinder_t *cyl) /* Get list of used cylinders. Returns the number of used cylinders. */ static int get_cylinder_used(const struct dive *dive, bool used[]) { - int i, num = 0; + int num = 0; - for (i = 0; i < dive->cylinders.nr; i++) { - used[i] = cylinder_used(get_cylinder(dive, i)); + for (auto [i, cyl]: enumerated_range(dive->cylinders)) { + used[i] = cylinder_used(cyl); if (used[i]) num++; } @@ -384,8 +374,8 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div const bool used_cylinders[], int num) { int idx; - auto used_and_unknown = std::make_unique(dive->cylinders.nr); - std::copy(used_cylinders, used_cylinders + dive->cylinders.nr, used_and_unknown.get()); + auto used_and_unknown = std::make_unique(dive->cylinders.size()); + std::copy(used_cylinders, used_cylinders + dive->cylinders.size(), used_and_unknown.get()); /* We know about using the O2 cylinder in a CCR dive */ if (dc->divemode == CCR) { @@ -419,16 +409,15 @@ static bool has_unknown_used_cylinders(const struct dive *dive, const struct div void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration) { - int i; int32_t lasttime = 0; int lastdepth = 0; int idx = 0; int num_used_cylinders; - if (dive->cylinders.nr <= 0) + if (dive->cylinders.empty()) return; - for (i = 0; i < dive->cylinders.nr; i++) + for (size_t i = 0; i < dive->cylinders.size(); i++) mean[i] = duration[i] = 0; if (!dc) return; @@ -438,7 +427,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i * if we don't actually know about the usage of all the * used cylinders. */ - auto used_cylinders = std::make_unique(dive->cylinders.nr); + auto used_cylinders = std::make_unique(dive->cylinders.size()); num_used_cylinders = get_cylinder_used(dive, used_cylinders.get()); if (has_unknown_used_cylinders(dive, dc, used_cylinders.get(), num_used_cylinders)) { /* @@ -453,7 +442,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i * For a single cylinder, use the overall mean * and duration */ - for (i = 0; i < dive->cylinders.nr; i++) { + for (size_t i = 0; i < dive->cylinders.size(); i++) { if (used_cylinders[i]) { mean[i] = dc->meandepth.mm; duration[i] = dc->duration.seconds; @@ -466,7 +455,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i fake_dc(dc); event_loop loop("gaschange"); const struct event *ev = loop.next(*dc); - std::vector depthtime(dive->cylinders.nr, 0); + std::vector depthtime(dive->cylinders.size(), 0); for (auto it = dc->samples.begin(); it != dc->samples.end(); ++it) { int32_t time = it->time.seconds; int depth = it->depth.mm; @@ -494,7 +483,7 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i lastdepth = depth; lasttime = time; } - for (i = 0; i < dive->cylinders.nr; i++) { + for (size_t i = 0; i < dive->cylinders.size(); i++) { if (duration[i]) mean[i] = (depthtime[i] + duration[i] / 2) / duration[i]; } @@ -529,7 +518,7 @@ static int same_rounded_pressure(pressure_t a, pressure_t b) int explicit_first_cylinder(const struct dive *dive, const struct divecomputer *dc) { int res = 0; - if (!dive->cylinders.nr) + if (dive->cylinders.empty()) return -1; if (dc) { const struct event *ev = get_first_event(*dc, "gaschange"); @@ -538,7 +527,7 @@ int explicit_first_cylinder(const struct dive *dive, const struct divecomputer * else if (dc->divemode == CCR) res = std::max(get_cylinder_idx_by_use(dive, DILUENT), res); } - return res < dive->cylinders.nr ? res : 0; + return static_cast(res) < dive->cylinders.size() ? res : 0; } /* this gets called when the dive mode has changed (so OC vs. CC) @@ -598,22 +587,18 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc) * cylinder name is independent from the gasmix, and different * gasmixes have different compressibility. */ -static void match_standard_cylinder(cylinder_type_t *type) +static void match_standard_cylinder(cylinder_type_t &type) { - double cuft, bar; - int psi, len; - const char *fmt; - char buffer[40], *p; - /* Do we already have a cylinder description? */ - if (type->description) + if (!type.description.empty()) return; - bar = type->workingpressure.mbar / 1000.0; - cuft = ml_to_cuft(type->size.mliter); + double bar = type.workingpressure.mbar / 1000.0; + double cuft = ml_to_cuft(type.size.mliter); cuft *= bar_to_atm(bar); - psi = lrint(to_PSI(type->workingpressure)); + int psi = lrint(to_PSI(type.workingpressure)); + const char *fmt; switch (psi) { case 2300 ... 2500: /* 2400 psi: LP tank */ fmt = "LP%d"; @@ -633,12 +618,7 @@ static void match_standard_cylinder(cylinder_type_t *type) default: return; } - len = snprintf(buffer, sizeof(buffer), fmt, (int)lrint(cuft)); - p = (char *)malloc(len + 1); - if (!p) - return; - memcpy(p, buffer, len + 1); - type->description = p; + type.description = format_string_std(fmt, (int)lrint(cuft)); } /* @@ -651,14 +631,14 @@ static void match_standard_cylinder(cylinder_type_t *type) * We internally use physical size only. But we save the workingpressure * so that we can do the conversion if required. */ -static void sanitize_cylinder_type(cylinder_type_t *type) +static void sanitize_cylinder_type(cylinder_type_t &type) { /* If we have no working pressure, it had *better* be just a physical size! */ - if (!type->workingpressure.mbar) + if (!type.workingpressure.mbar) return; /* No size either? Nothing to go on */ - if (!type->size.mliter) + if (!type.size.mliter) return; /* Ok, we have both size and pressure: try to match a description */ @@ -667,11 +647,9 @@ static void sanitize_cylinder_type(cylinder_type_t *type) static void sanitize_cylinder_info(struct dive *dive) { - int i; - - for (i = 0; i < dive->cylinders.nr; i++) { - sanitize_gasmix(&get_cylinder(dive, i)->gasmix); - sanitize_cylinder_type(&get_cylinder(dive, i)->type); + for (auto &cyl :dive->cylinders) { + sanitize_gasmix(cyl.gasmix); + sanitize_cylinder_type(cyl.type); } } @@ -935,19 +913,19 @@ static void simplify_dc_pressures(struct divecomputer &dc) /* Do we need a sensor -> cylinder mapping? */ static void fixup_start_pressure(struct dive *dive, int idx, pressure_t p) { - if (idx >= 0 && idx < dive->cylinders.nr) { - cylinder_t *cyl = get_cylinder(dive, idx); - if (p.mbar && !cyl->sample_start.mbar) - cyl->sample_start = p; + if (idx >= 0 && static_cast(idx) < dive->cylinders.size()) { + cylinder_t &cyl = dive->cylinders[idx]; + if (p.mbar && !cyl.sample_start.mbar) + cyl.sample_start = p; } } static void fixup_end_pressure(struct dive *dive, int idx, pressure_t p) { - if (idx >= 0 && idx < dive->cylinders.nr) { - cylinder_t *cyl = get_cylinder(dive, idx); - if (p.mbar && !cyl->sample_end.mbar) - cyl->sample_end = p; + if (idx >= 0 && static_cast(idx) < dive->cylinders.size()) { + cylinder_t &cyl = dive->cylinders[idx]; + if (p.mbar && !cyl.sample_end.mbar) + cyl.sample_end = p; } } @@ -1003,13 +981,13 @@ static bool validate_gaschange(struct dive *dive, struct event &event) if (event.gas.index >= 0) return true; - index = find_best_gasmix_match(event.gas.mix, &dive->cylinders); - if (index < 0 || index >= dive->cylinders.nr) + index = find_best_gasmix_match(event.gas.mix, dive->cylinders); + if (index < 0 || static_cast(index) >= dive->cylinders.size()) return false; /* Fix up the event to have the right information */ event.gas.index = index; - event.gas.mix = get_cylinder(dive, index)->gasmix; + event.gas.mix = dive->cylinders[index].gasmix; /* Convert to odd libdivecomputer format */ o2 = get_o2(event.gas.mix); @@ -1094,7 +1072,7 @@ static void fixup_dc_sample_sensors(struct dive *dive, struct divecomputer &dc) } // Ignore the sensors we have cylinders for - sensor_mask >>= dive->cylinders.nr; + sensor_mask >>= dive->cylinders.size(); // Do we need to add empty cylinders? while (sensor_mask) { @@ -1160,13 +1138,12 @@ struct dive *fixup_dive(struct dive *dive) fixup_duration(dive); fixup_watertemp(dive); fixup_airtemp(dive); - for (i = 0; i < dive->cylinders.nr; i++) { - cylinder_t *cyl = get_cylinder(dive, i); - add_cylinder_description(cyl->type); - if (same_rounded_pressure(cyl->sample_start, cyl->start)) - cyl->start.mbar = 0; - if (same_rounded_pressure(cyl->sample_end, cyl->end)) - cyl->end.mbar = 0; + for (auto &cyl: dive->cylinders) { + add_cylinder_description(cyl.type); + if (same_rounded_pressure(cyl.sample_start, cyl.start)) + cyl.start.mbar = 0; + if (same_rounded_pressure(cyl.sample_end, cyl.end)) + cyl.end.mbar = 0; } update_cylinder_related_info(dive); for (i = 0; i < dive->weightsystems.nr; i++) { @@ -1487,12 +1464,9 @@ pick_b: * cylinder_use_type = an enum, one of {oxygen, diluent, bailout} */ int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cylinder_use_type) { - int cylinder_index; - for (cylinder_index = 0; cylinder_index < dive->cylinders.nr; cylinder_index++) { - if (get_cylinder(dive, cylinder_index)->cylinder_use == cylinder_use_type) - return cylinder_index; // return the index of the cylinder with that cylinder use type - } - return -1; // negative number means cylinder_use_type not found in list of cylinders + auto it = std::find_if(dive->cylinders.begin(), dive->cylinders.end(), [cylinder_use_type] + (auto &cyl) { return cyl.cylinder_use == cylinder_use_type; }); + return it != dive->cylinders.end() ? it - dive->cylinders.begin() : -1; } /* Force an initial gaschange event to the (old) gas #0 */ @@ -1580,13 +1554,13 @@ void cylinder_renumber(struct dive *dive, int mapping[]) dc_cylinder_renumber(dive, dc, mapping); } -int same_gasmix_cylinder(const cylinder_t *cyl, int cylid, const struct dive *dive, bool check_unused) +int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused) { - struct gasmix mygas = cyl->gasmix; - for (int i = 0; i < dive->cylinders.nr; i++) { + struct gasmix mygas = cyl.gasmix; + for (auto [i, cyl]: enumerated_range(dive->cylinders)) { if (i == cylid) continue; - struct gasmix gas2 = get_cylinder(dive, i)->gasmix; + struct gasmix gas2 = cyl.gasmix; if (gasmix_distance(mygas, gas2) == 0 && (is_cylinder_used(dive, i) || check_unused)) return i; } @@ -1614,20 +1588,15 @@ static int different_manual_pressures(const cylinder_t *a, const cylinder_t *b) */ static int match_cylinder(const cylinder_t *cyl, const struct dive *dive, const bool try_match[]) { - int i; - - for (i = 0; i < dive->cylinders.nr; i++) { - const cylinder_t *target; - + for (auto [i, target]: enumerated_range(dive->cylinders)) { if (!try_match[i]) continue; - target = get_cylinder(dive, i); - if (!same_gasmix(cyl->gasmix, target->gasmix)) + if (!same_gasmix(cyl->gasmix, target.gasmix)) continue; - if (cyl->cylinder_use != target->cylinder_use) + if (cyl->cylinder_use != target.cylinder_use) continue; - if (different_manual_pressures(cyl, target)) + if (different_manual_pressures(cyl, &target)) continue; /* open question: Should we check sizes too? */ @@ -1679,8 +1648,8 @@ static void merge_one_cylinder(cylinder_t *a, const cylinder_t *b) a->type.size.mliter = b->type.size.mliter; if (!a->type.workingpressure.mbar) a->type.workingpressure.mbar = b->type.workingpressure.mbar; - if (empty_string(a->type.description)) - a->type.description = copy_string(b->type.description); + if (a->type.description.empty()) + a->type.description = b->type.description; /* If either cylinder has manually entered pressures, try to merge them. * Use pressures from divecomputer samples if only one cylinder has such a value. @@ -1697,24 +1666,24 @@ static void merge_one_cylinder(cylinder_t *a, const cylinder_t *b) a->bestmix_he = a->bestmix_he && b->bestmix_he; } -static bool cylinder_has_data(const cylinder_t *cyl) +static bool cylinder_has_data(const cylinder_t &cyl) { - return !cyl->type.size.mliter && - !cyl->type.workingpressure.mbar && - !cyl->type.description && - !cyl->gasmix.o2.permille && - !cyl->gasmix.he.permille && - !cyl->start.mbar && - !cyl->end.mbar && - !cyl->sample_start.mbar && - !cyl->sample_end.mbar && - !cyl->gas_used.mliter && - !cyl->deco_gas_used.mliter; + return !cyl.type.size.mliter && + !cyl.type.workingpressure.mbar && + cyl.type.description.empty() && + !cyl.gasmix.o2.permille && + !cyl.gasmix.he.permille && + !cyl.start.mbar && + !cyl.end.mbar && + !cyl.sample_start.mbar && + !cyl.sample_end.mbar && + !cyl.gas_used.mliter && + !cyl.deco_gas_used.mliter; } static bool cylinder_in_use(const struct dive *dive, int idx) { - if (idx < 0 || idx >= dive->cylinders.nr) + if (idx < 0 || static_cast(idx) >= dive->cylinders.size()) return false; /* This tests for gaschange events or pressure changes */ @@ -1722,7 +1691,7 @@ static bool cylinder_in_use(const struct dive *dive, int idx) return true; /* This tests for typenames or gas contents */ - return cylinder_has_data(get_cylinder(dive, idx)); + return cylinder_has_data(dive->cylinders[idx]); } /* @@ -1738,22 +1707,21 @@ static bool cylinder_in_use(const struct dive *dive, int idx) static void merge_cylinders(struct dive *res, const struct dive *a, const struct dive *b, int mapping_a[], int mapping_b[]) { - int i; - int max_cylinders = a->cylinders.nr + b->cylinders.nr; + size_t max_cylinders = a->cylinders.size() + b->cylinders.size(); auto used_in_a = std::make_unique(max_cylinders); auto used_in_b = std::make_unique(max_cylinders); auto try_to_match = std::make_unique(max_cylinders); std::fill(try_to_match.get(), try_to_match.get() + max_cylinders, false); /* First, clear all cylinders in destination */ - clear_cylinder_table(&res->cylinders); + res->cylinders.clear(); /* Clear all cylinder mappings */ - std::fill(mapping_a, mapping_a + a->cylinders.nr, -1); - std::fill(mapping_b, mapping_b + b->cylinders.nr, -1); + std::fill(mapping_a, mapping_a + a->cylinders.size(), -1); + std::fill(mapping_b, mapping_b + b->cylinders.size(), -1); /* Calculate usage map of cylinders, clear matching map */ - for (i = 0; i < max_cylinders; i++) { + for (size_t i = 0; i < max_cylinders; i++) { used_in_a[i] = cylinder_in_use(a, i); used_in_b[i] = cylinder_in_use(b, i); } @@ -1762,20 +1730,20 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct * For each cylinder in 'a' that is used, copy it to 'res'. * These are also potential matches for 'b' to use. */ - for (i = 0; i < max_cylinders; i++) { - int res_nr = res->cylinders.nr; + for (size_t i = 0; i < max_cylinders; i++) { + size_t res_nr = res->cylinders.size(); if (!used_in_a[i]) continue; - mapping_a[i] = res_nr; + mapping_a[i] = static_cast(res_nr); try_to_match[res_nr] = true; - add_cloned_cylinder(&res->cylinders, *get_cylinder(a, i)); + res->cylinders.push_back(a->cylinders[i]); } /* * For each cylinder in 'b' that is used, try to match it * with an existing cylinder in 'res' from 'a' */ - for (i = 0; i < b->cylinders.nr; i++) { + for (size_t i = 0; i < b->cylinders.size(); i++) { int j; if (!used_in_b[i]) @@ -1785,9 +1753,9 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct /* No match? Add it to the result */ if (j < 0) { - int res_nr = res->cylinders.nr; - mapping_b[i] = res_nr; - add_cloned_cylinder(&res->cylinders, *get_cylinder(b, i)); + size_t res_nr = res->cylinders.size(); + mapping_b[i] = static_cast(res_nr); + res->cylinders.push_back(b->cylinders[i]); continue; } @@ -2402,8 +2370,8 @@ struct dive *merge_dives(const struct dive *a, const struct dive *b, int offset, taglist_merge(&res->tag_list, a->tag_list, b->tag_list); /* if we get dives without any gas / cylinder information in an import, make sure * that there is at leatst one entry in the cylinder map for that dive */ - auto cylinders_map_a = std::make_unique(std::max(1, a->cylinders.nr)); - auto cylinders_map_b = std::make_unique(std::max(1, b->cylinders.nr)); + auto cylinders_map_a = std::make_unique(std::max(size_t(1), a->cylinders.size())); + auto cylinders_map_b = std::make_unique(std::max(size_t(1), b->cylinders.size())); merge_cylinders(res, a, b, cylinders_map_a.get(), cylinders_map_b.get()); merge_equipment(res, a, b); merge_temperatures(res, a, b); @@ -2456,7 +2424,7 @@ static void force_fixup_dive(struct dive *d) int old_mintemp = d->mintemp.mkelvin; int old_maxtemp = d->maxtemp.mkelvin; duration_t old_duration = d->duration; - std::vector old_pressures(d->cylinders.nr); + std::vector old_pressures(d->cylinders.size()); d->maxdepth.mm = 0; dc->maxdepth.mm = 0; @@ -2465,12 +2433,11 @@ static void force_fixup_dive(struct dive *d) d->duration.seconds = 0; d->maxtemp.mkelvin = 0; d->mintemp.mkelvin = 0; - for (int i = 0; i < d->cylinders.nr; i++) { - cylinder_t *cyl = get_cylinder(d, i); - old_pressures[i].start = cyl->start; - old_pressures[i].end = cyl->end; - cyl->start.mbar = 0; - cyl->end.mbar = 0; + for (auto [i, cyl]: enumerated_range(d->cylinders)) { + old_pressures[i].start = cyl.start; + old_pressures[i].end = cyl.end; + cyl.start.mbar = 0; + cyl.end.mbar = 0; } fixup_dive(d); @@ -2489,11 +2456,11 @@ static void force_fixup_dive(struct dive *d) if (!d->duration.seconds) d->duration = old_duration; - for (int i = 0; i < d->cylinders.nr; i++) { - if (!get_cylinder(d, i)->start.mbar) - get_cylinder(d, i)->start = old_pressures[i].start; - if (!get_cylinder(d, i)->end.mbar) - get_cylinder(d, i)->end = old_pressures[i].end; + for (auto [i, cyl]: enumerated_range(d->cylinders)) { + if (!cyl.start.mbar) + cyl.start = old_pressures[i].start; + if (!cyl.end.mbar) + cyl.end = old_pressures[i].end; } } @@ -3171,7 +3138,7 @@ gasmix_loop::gasmix_loop(const struct dive &d, const struct divecomputer &dc) : dive(d), dc(dc), last(gasmix_air), loop("gaschange") { /* if there is no cylinder, return air */ - if (dive.cylinders.nr <= 0) + if (dive.cylinders.empty()) return; /* on first invocation, get initial gas mix and first event (if any) */ @@ -3183,7 +3150,7 @@ gasmix_loop::gasmix_loop(const struct dive &d, const struct divecomputer &dc) : gasmix gasmix_loop::next(int time) { /* if there is no cylinder, return air */ - if (dive.cylinders.nr <= 0) + if (dive.cylinders.empty()) return last; while (ev && ev->time.seconds <= time) { diff --git a/core/dive.h b/core/dive.h index 2e3747856..811b25ff6 100644 --- a/core/dive.h +++ b/core/dive.h @@ -30,7 +30,7 @@ struct dive { struct dive_site *dive_site = nullptr; char *notes = nullptr; char *diveguide = nullptr, *buddy = nullptr; - struct cylinder_table cylinders = { }; + struct cylinder_table cylinders; struct weightsystem_table weightsystems = { }; char *suit = nullptr; int number = 0; @@ -74,7 +74,7 @@ extern bool dive_cache_is_valid(const struct dive *dive); extern int get_cylinder_idx_by_use(const struct dive *dive, enum cylinderuse cylinder_use_type); extern void cylinder_renumber(struct dive *dive, int mapping[]); -extern int same_gasmix_cylinder(const cylinder_t *cyl, int cylid, const struct dive *dive, bool check_unused); +extern int same_gasmix_cylinder(const cylinder_t &cyl, int cylid, const struct dive *dive, bool check_unused); /* when selectively copying dive information, which parts should be copied? */ struct dive_components { @@ -190,7 +190,6 @@ extern struct event create_gas_switch_event(struct dive *dive, struct divecomput extern void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration); extern int get_cylinder_index(const struct dive *dive, const struct event &ev); extern struct gasmix get_gasmix_from_event(const struct dive *, const struct event &ev); -extern int nr_cylinders(const struct dive *dive); extern int nr_weightsystems(const struct dive *dive); extern bool cylinder_with_sensor_sample(const struct dive *dive, int cylinder_id); diff --git a/core/divelist.cpp b/core/divelist.cpp index 53dcf2d46..348cb091d 100644 --- a/core/divelist.cpp +++ b/core/divelist.cpp @@ -32,19 +32,17 @@ */ void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2max_p) { - int i; int maxo2 = -1, maxhe = -1, mino2 = 1000; - for (i = 0; i < dive->cylinders.nr; i++) { - const cylinder_t *cyl = get_cylinder(dive, i); - int o2 = get_o2(cyl->gasmix); - int he = get_he(cyl->gasmix); + for (auto [i, cyl]: enumerated_range(dive->cylinders)) { + int o2 = get_o2(cyl.gasmix); + int he = get_he(cyl.gasmix); if (!is_cylinder_used(dive, i)) continue; - if (cyl->cylinder_use == OXYGEN) + if (cyl.cylinder_use == OXYGEN) continue; - if (cyl->cylinder_use == NOT_USED) + if (cyl.cylinder_use == NOT_USED) continue; if (o2 > maxo2) maxo2 = o2; @@ -337,12 +335,11 @@ static double calculate_airuse(const struct dive *dive) if (dive->dcs[0].divemode == CCR) return 0.0; - for (int i = 0; i < dive->cylinders.nr; i++) { + for (auto [i, cyl]: enumerated_range(dive->cylinders)) { pressure_t start, end; - const cylinder_t *cyl = get_cylinder(dive, i); - start = cyl->start.mbar ? cyl->start : cyl->sample_start; - end = cyl->end.mbar ? cyl->end : cyl->sample_end; + start = cyl.start.mbar ? cyl.start : cyl.sample_start; + end = cyl.end.mbar ? cyl.end : cyl.sample_end; if (!end.mbar || start.mbar <= end.mbar) { // If a cylinder is used but we do not have info on amout of gas used // better not pretend we know the total gas use. @@ -354,7 +351,7 @@ static double calculate_airuse(const struct dive *dive) continue; } - airuse += gas_volume(cyl, start) - gas_volume(cyl, end); + airuse += gas_volume(&cyl, start) - gas_volume(&cyl, end); } return airuse / 1000.0; } diff --git a/core/equipment.cpp b/core/equipment.cpp index bce1c4eed..81c919640 100644 --- a/core/equipment.cpp +++ b/core/equipment.cpp @@ -18,9 +18,43 @@ #include "divelog.h" #include "errorhelper.h" #include "pref.h" +#include "range.h" #include "subsurface-string.h" #include "table.h" +cylinder_t::cylinder_t() = default; +cylinder_t::~cylinder_t() = default; + +static cylinder_t make_surface_air_cylinder() +{ + cylinder_t res; + res.cylinder_use = NOT_USED; + return res; +} +static const cylinder_t surface_air_cylinder = make_surface_air_cylinder(); + +static void warn_index(size_t i, size_t max) +{ + if (i >= max + 1) { + report_info("Warning: accessing invalid cylinder %lu (%lu existing)", + static_cast(i), static_cast(max)); + } +} + +cylinder_t &cylinder_table::operator[](size_t i) +{ + warn_index(i, size()); + return i < size() ? std::vector::operator[](i) + : const_cast(surface_air_cylinder); +} + +const cylinder_t &cylinder_table::operator[](size_t i) const +{ + warn_index(i, size()); + return i < size() ? std::vector::operator[](i) + : surface_air_cylinder; +} + /* Warning: this has strange semantics for C-code! Not the weightsystem object * is freed, but the data it references. The object itself is passed in by value. * This is due to the fact how the table macros work. @@ -31,12 +65,6 @@ void free_weightsystem(weightsystem_t ws) ws.description = NULL; } -void free_cylinder(cylinder_t c) -{ - free((void *)c.type.description); - c.type.description = NULL; -} - void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d) { clear_weightsystem_table(d); @@ -44,14 +72,6 @@ void copy_weights(const struct weightsystem_table *s, struct weightsystem_table add_cloned_weightsystem(d, s->weightsystems[i]); } -void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d) -{ - int i; - clear_cylinder_table(d); - for (i = 0; i < s->nr; i++) - add_cloned_cylinder(d, s->cylinders[i]); -} - /* weightsystem table functions */ //static MAKE_GET_IDX(weightsystem_table, weightsystem_t, weightsystems) static MAKE_GROW_TABLE(weightsystem_table, weightsystem_t, weightsystems) @@ -62,16 +82,6 @@ static MAKE_REMOVE_FROM(weightsystem_table, weightsystems) //MAKE_REMOVE(weightsystem_table, weightsystem_t, weightsystem) MAKE_CLEAR_TABLE(weightsystem_table, weightsystems, weightsystem) -/* cylinder table functions */ -//static MAKE_GET_IDX(cylinder_table, cylinder_t, cylinders) -static MAKE_GROW_TABLE(cylinder_table, cylinder_t, cylinders) -//static MAKE_GET_INSERTION_INDEX(cylinder_table, cylinder_t, cylinders, cylinder_less_than) -static MAKE_ADD_TO(cylinder_table, cylinder_t, cylinders) -static MAKE_REMOVE_FROM(cylinder_table, cylinders) -//MAKE_SORT(cylinder_table, cylinder_t, cylinders, comp_cylinders) -//MAKE_REMOVE(cylinder_table, cylinder_t, cylinder) -MAKE_CLEAR_TABLE(cylinder_table, cylinders, cylinder) - const char *cylinderuse_text[NUM_GAS_USE] = { QT_TRANSLATE_NOOP("gettextFromC", "OC-gas"), QT_TRANSLATE_NOOP("gettextFromC", "diluent"), QT_TRANSLATE_NOOP("gettextFromC", "oxygen"), QT_TRANSLATE_NOOP("gettextFromC", "not used") }; @@ -144,11 +154,11 @@ std::pair get_tank_info_data(const std::vector void add_cylinder_description(const cylinder_type_t &type) { - std::string desc = type.description ? type.description : std::string(); + const std::string &desc = type.description; if (desc.empty()) return; if (std::any_of(tank_info_table.begin(), tank_info_table.end(), - [&type](const tank_info &info) { return info.name == type.description; })) + [&desc](const tank_info &info) { return info.name == desc; })) return; add_tank_info_metric(tank_info_table, desc, type.size.mliter, type.workingpressure.mbar / 1000); @@ -191,30 +201,16 @@ void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws) add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws)); } -cylinder_t clone_cylinder(cylinder_t cyl) +/* Add a clone of a weightsystem to the end of a weightsystem table. + * Cloned means that the description-string is copied. */ +void add_cloned_weightsystem_at(struct weightsystem_table *t, weightsystem_t ws) { - cylinder_t res = cyl; - res.type.description = copy_string(res.type.description); - return res; + add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws)); } void add_cylinder(struct cylinder_table *t, int idx, cylinder_t cyl) { - add_to_cylinder_table(t, idx, cyl); - /* FIXME: This is a horrible hack: we make sure that at the end of - * every single cylinder table there is an empty cylinder that can - * be used by the planner as "surface air" cylinder. Fix this. - */ - add_to_cylinder_table(t, t->nr, cylinder_t()); - t->nr--; - t->cylinders[t->nr].cylinder_use = NOT_USED; -} - -/* Add a clone of a cylinder to the end of a cylinder table. - * Cloned means that the description-string is copied. */ -void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl) -{ - add_cylinder(t, t->nr, clone_cylinder(cyl)); + t->insert(t->begin() + idx, std::move(cyl)); } bool same_weightsystem(weightsystem_t w1, weightsystem_t w2) @@ -250,17 +246,12 @@ int gas_volume(const cylinder_t *cyl, pressure_t p) return lrint(cyl->type.size.mliter * bar_to_atm(bar) / z_factor); } -int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders) +int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table &cylinders) { - int i; int best = -1, score = INT_MAX; - for (i = 0; i < cylinders->nr; i++) { - const cylinder_t *match; - int distance; - - match = cylinders->cylinders + i; - distance = gasmix_distance(mix, match->gasmix); + for (auto [i, match]: enumerated_range(cylinders)) { + int distance = gasmix_distance(mix, match.gasmix); if (distance >= score) continue; best = i; @@ -336,10 +327,8 @@ void reset_tank_info_table(std::vector &table) /* Add cylinders from dive list */ for (int i = 0; i < divelog.dives->nr; ++i) { const struct dive *dive = divelog.dives->dives[i]; - for (int j = 0; j < dive->cylinders.nr; j++) { - const cylinder_t *cyl = get_cylinder(dive, j); - add_cylinder_description(cyl->type); - } + for (auto &cyl: dive->cylinders) + add_cylinder_description(cyl.type); } } @@ -357,7 +346,7 @@ struct std::vector ws_info_table = { void remove_cylinder(struct dive *dive, int idx) { - remove_from_cylinder_table(&dive->cylinders, idx); + dive->cylinders.erase(dive->cylinders.begin() + idx); } void remove_weightsystem(struct dive *dive, int idx) @@ -380,68 +369,61 @@ void reset_cylinders(struct dive *dive, bool track_gas) { pressure_t decopo2 = {.mbar = prefs.decopo2}; - for (int i = 0; i < dive->cylinders.nr; i++) { - cylinder_t *cyl = get_cylinder(dive, i); - if (cyl->depth.mm == 0) /* if the gas doesn't give a mod, calculate based on prefs */ - cyl->depth = gas_mod(cyl->gasmix, decopo2, dive, M_OR_FT(3,10)); + for (cylinder_t &cyl: dive->cylinders) { + if (cyl.depth.mm == 0) /* if the gas doesn't give a mod, calculate based on prefs */ + cyl.depth = gas_mod(cyl.gasmix, decopo2, dive, M_OR_FT(3,10)); if (track_gas) - cyl->start.mbar = cyl->end.mbar = cyl->type.workingpressure.mbar; - cyl->gas_used.mliter = 0; - cyl->deco_gas_used.mliter = 0; + cyl.start.mbar = cyl.end.mbar = cyl.type.workingpressure.mbar; + cyl.gas_used.mliter = 0; + cyl.deco_gas_used.mliter = 0; } } -static void copy_cylinder_type(const cylinder_t *s, cylinder_t *d) +static void copy_cylinder_type(const cylinder_t &s, cylinder_t &d) { - free_cylinder(*d); - d->type = s->type; - d->type.description = s->type.description ? strdup(s->type.description) : NULL; - d->gasmix = s->gasmix; - d->depth = s->depth; - d->cylinder_use = s->cylinder_use; - d->manually_added = true; + d.type = s.type; + d.gasmix = s.gasmix; + d.depth = s.depth; + d.cylinder_use = s.cylinder_use; + d.manually_added = true; } /* copy the equipment data part of the cylinders but keep pressures */ void copy_cylinder_types(const struct dive *s, struct dive *d) { - int i; if (!s || !d) return; - for (i = 0; i < s->cylinders.nr && i < d->cylinders.nr; i++) - copy_cylinder_type(get_cylinder(s, i), get_cylinder(d, i)); + for (size_t i = 0; i < s->cylinders.size() && i < d->cylinders.size(); i++) + copy_cylinder_type(s->cylinders[i], d->cylinders[i]); - for ( ; i < s->cylinders.nr; i++) - add_cloned_cylinder(&d->cylinders, *get_cylinder(s, i)); + for (size_t i = d->cylinders.size(); i < s->cylinders.size(); i++) + d->cylinders.push_back(s->cylinders[i]); } cylinder_t *add_empty_cylinder(struct cylinder_table *t) { - cylinder_t cyl; - cyl.type.description = strdup(""); - add_cylinder(t, t->nr, cyl); - return &t->cylinders[t->nr - 1]; + t->emplace_back(); + return &t->back(); } /* access to cylinders is controlled by two functions: * - get_cylinder() returns the cylinder of a dive and supposes that * the cylinder with the given index exists. If it doesn't, an error - * message is printed and NULL returned. + * message is printed and the "surface air" cylinder returned. + * (NOTE: this MUST not be written into!). * - get_or_create_cylinder() creates an empty cylinder if it doesn't exist. * Multiple cylinders might be created if the index is bigger than the * number of existing cylinders */ -cylinder_t *get_cylinder(const struct dive *d, int idx) +cylinder_t *get_cylinder(struct dive *d, int idx) { - /* FIXME: The planner uses a dummy cylinder one past the official number of cylinders - * in the table to mark no-cylinder surface interavals. This is horrendous. Fix ASAP. */ - // if (idx < 0 || idx >= d->cylinders.nr) { - if (idx < 0 || idx >= d->cylinders.nr + 1 || idx >= d->cylinders.allocated) { - report_info("Warning: accessing invalid cylinder %d (%d existing)", idx, d->cylinders.nr); - return NULL; - } - return &d->cylinders.cylinders[idx]; + return &d->cylinders[idx]; +} + +const cylinder_t *get_cylinder(const struct dive *d, int idx) +{ + return &d->cylinders[idx]; } cylinder_t *get_or_create_cylinder(struct dive *d, int idx) @@ -450,9 +432,9 @@ cylinder_t *get_or_create_cylinder(struct dive *d, int idx) report_info("Warning: accessing invalid cylinder %d", idx); return NULL; } - while (idx >= d->cylinders.nr) + while (static_cast(idx) >= d->cylinders.size()) add_empty_cylinder(&d->cylinders); - return &d->cylinders.cylinders[idx]; + return &d->cylinders[idx]; } /* if a default cylinder is set, use that */ @@ -465,7 +447,7 @@ void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) return; for (auto &ti: tank_info_table) { if (ti.name == cyl_name) { - cyl->type.description = strdup(ti.name.c_str()); + cyl->type.description = ti.name; if (ti.ml) { cyl->type.size.mliter = ti.ml; cyl->type.workingpressure.mbar = ti.bar * 1000; @@ -481,10 +463,16 @@ void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) } } +cylinder_t default_cylinder(const struct dive *d) +{ + cylinder_t res; + fill_default_cylinder(d, &res); + return res; +} + cylinder_t create_new_cylinder(const struct dive *d) { - cylinder_t cyl; - fill_default_cylinder(d, &cyl); + cylinder_t cyl = default_cylinder(d); cyl.start = cyl.type.workingpressure; cyl.cylinder_use = OC_GAS; return cyl; @@ -500,7 +488,7 @@ cylinder_t create_new_manual_cylinder(const struct dive *d) void add_default_cylinder(struct dive *d) { // Only add if there are no cylinders yet - if (d->cylinders.nr > 0) + if (!d->cylinders.empty()) return; cylinder_t cyl; @@ -508,7 +496,7 @@ void add_default_cylinder(struct dive *d) cyl = create_new_cylinder(d); } else { // roughly an AL80 - cyl.type.description = strdup(translate("gettextFromC", "unknown")); + cyl.type.description = translate("gettextFromC", "unknown"); cyl.type.size.mliter = 11100; cyl.type.workingpressure.mbar = 207000; } @@ -521,11 +509,11 @@ static bool show_cylinder(const struct dive *d, int i) if (is_cylinder_used(d, i)) return true; - const cylinder_t *cyl = &d->cylinders.cylinders[i]; - if (cyl->start.mbar || cyl->sample_start.mbar || - cyl->end.mbar || cyl->sample_end.mbar) + const cylinder_t &cyl = d->cylinders[i]; + if (cyl.start.mbar || cyl.sample_start.mbar || + cyl.end.mbar || cyl.sample_end.mbar) return true; - if (cyl->manually_added) + if (cyl.manually_added) return true; /* @@ -538,10 +526,10 @@ static bool show_cylinder(const struct dive *d, int i) /* The unused cylinders at the end of the cylinder list are hidden. */ int first_hidden_cylinder(const struct dive *d) { - int res = d->cylinders.nr; + size_t res = d->cylinders.size(); while (res > 0 && !show_cylinder(d, res - 1)) --res; - return res; + return static_cast(res); } #ifdef DEBUG_CYL @@ -551,7 +539,7 @@ void dump_cylinders(struct dive *dive, bool verbose) for (int i = 0; i < dive->cylinders; i++) { cylinder_t *cyl = get_cylinder(dive, i); - printf("%02d: Type %s, %3.1fl, %3.0fbar\n", i, cyl->type.description, cyl->type.size.mliter / 1000.0, cyl->type.workingpressure.mbar / 1000.0); + printf("%02d: Type %s, %3.1fl, %3.0fbar\n", i, cyl->type.description.c_str(), cyl->type.size.mliter / 1000.0, cyl->type.workingpressure.mbar / 1000.0); printf(" Gasmix O2 %2.0f%% He %2.0f%%\n", cyl->gasmix.o2.permille / 10.0, cyl->gasmix.he.permille / 10.0); printf(" Pressure Start %3.0fbar End %3.0fbar Sample start %3.0fbar Sample end %3.0fbar\n", cyl->start.mbar / 1000.0, cyl->end.mbar / 1000.0, cyl->sample_start.mbar / 1000.0, cyl->sample_end.mbar / 1000.0); if (verbose) { diff --git a/core/equipment.h b/core/equipment.h index 09ed5e4cd..ba2e5b278 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -17,7 +17,7 @@ struct cylinder_type_t { volume_t size; pressure_t workingpressure; - const char *description = nullptr; /* "LP85", "AL72", "AL80", "HP100+" or whatever */ + std::string description; /* "LP85", "AL72", "AL80", "HP100+" or whatever */ }; struct cylinder_t @@ -32,17 +32,23 @@ struct cylinder_t enum cylinderuse cylinder_use = OC_GAS; bool bestmix_o2 = false; bool bestmix_he = false; + + cylinder_t(); + ~cylinder_t(); }; -/* Table of cylinders. Attention: this stores cylinders, - * *not* pointers to cylinders. This has two crucial consequences: - * 1) Pointers to cylinders are not stable. They may be - * invalidated if the table is reallocated. - * 2) add_cylinder(), etc. take ownership of the - * cylinder. Notably of the description string. */ -struct cylinder_table { - int nr, allocated; - cylinder_t *cylinders; +/* Table of cylinders. + * This is a crazy class: it is basically a std::vector<>, but overrides + * the [] accessor functions and allows out-of-bound accesses. + * This is used in the planner, which uses "max_index + 1" for the + * surface air cylinder. + * Note: an out-of-bound access returns a reference to an object with + * static linkage that MUST NOT be written into. + * Yes, this is all very mad, but it grew historically. + */ +struct cylinder_table : public std::vector { + cylinder_t &operator[](size_t i); + const cylinder_t &operator[](size_t i) const; }; struct weightsystem_t @@ -68,16 +74,13 @@ struct weightsystem_table { extern enum cylinderuse cylinderuse_from_text(const char *text); extern void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d); -extern void copy_cylinders(const struct cylinder_table *s, struct cylinder_table *d); extern weightsystem_t clone_weightsystem(weightsystem_t ws); extern void free_weightsystem(weightsystem_t ws); extern void copy_cylinder_types(const struct dive *s, struct dive *d); extern void add_cloned_weightsystem(struct weightsystem_table *t, weightsystem_t ws); -extern cylinder_t clone_cylinder(cylinder_t cyl); -extern void free_cylinder(cylinder_t cyl); extern cylinder_t *add_empty_cylinder(struct cylinder_table *t); -extern void add_cloned_cylinder(struct cylinder_table *t, cylinder_t cyl); -extern cylinder_t *get_cylinder(const struct dive *d, int idx); +extern cylinder_t *get_cylinder(struct dive *d, int idx); +extern const cylinder_t *get_cylinder(const struct dive *d, int idx); extern cylinder_t *get_or_create_cylinder(struct dive *d, int idx); extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2); extern void remove_cylinder(struct dive *dive, int idx); @@ -85,8 +88,9 @@ extern void remove_weightsystem(struct dive *dive, int idx); extern void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws); extern void reset_cylinders(struct dive *dive, bool track_gas); extern int gas_volume(const cylinder_t *cyl, pressure_t p); /* Volume in mliter of a cylinder at pressure 'p' */ -extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table *cylinders); +extern int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table &cylinders); extern void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl); /* dive is needed to fill out MOD, which depends on salinity. */ +extern cylinder_t default_cylinder(const struct dive *d); extern cylinder_t create_new_manual_cylinder(const struct dive *dive); /* dive is needed to fill out MOD, which depends on salinity. */ extern void add_default_cylinder(struct dive *dive); extern int first_hidden_cylinder(const struct dive *d); @@ -99,7 +103,6 @@ extern void clear_weightsystem_table(struct weightsystem_table *); extern void add_to_weightsystem_table(struct weightsystem_table *, int idx, weightsystem_t ws); /* Cylinder table functions */ -extern void clear_cylinder_table(struct cylinder_table *); extern void add_cylinder(struct cylinder_table *, int idx, cylinder_t cyl); void get_gas_string(struct gasmix gasmix, char *text, int len); diff --git a/core/filterconstraint.cpp b/core/filterconstraint.cpp index 2a2ffe448..8dbc066ae 100644 --- a/core/filterconstraint.cpp +++ b/core/filterconstraint.cpp @@ -857,8 +857,8 @@ static bool has_weight_type(const filter_constraint &c, const struct dive *d) static bool has_cylinder_type(const filter_constraint &c, const struct dive *d) { QStringList cylinderTypes; - for (int i = 0; i < d->cylinders.nr; ++i) - cylinderTypes.push_back(d->cylinders.cylinders[i].type.description); + for (const cylinder_t &cyl: d->cylinders) + cylinderTypes.push_back(QString::fromStdString(cyl.type.description)); return check(c, cylinderTypes); } @@ -904,22 +904,15 @@ static bool check_numerical_range_non_zero(const filter_constraint &c, int v) static bool check_cylinder_size(const filter_constraint &c, const struct dive *d) { - for (int i = 0; i < d->cylinders.nr; ++i) { - const cylinder_t &cyl = d->cylinders.cylinders[i]; - if (cyl.type.size.mliter && check_numerical_range(c, cyl.type.size.mliter)) - return true; - } - return false; + return std::any_of(d->cylinders.begin(), d->cylinders.end(), [&c](auto &cyl) + { return cyl.type.size.mliter && + check_numerical_range(c, cyl.type.size.mliter); }); } static bool check_gas_range(const filter_constraint &c, const struct dive *d, gas_component component) { - for (int i = 0; i < d->cylinders.nr; ++i) { - const cylinder_t &cyl = d->cylinders.cylinders[i]; - if (check_numerical_range(c, get_gas_component_fraction(cyl.gasmix, component).permille)) - return true; - } - return false; + return std::any_of(d->cylinders.begin(), d->cylinders.end(), [&c, &component](auto &cyl) + { return check_numerical_range(c, get_gas_component_fraction(cyl.gasmix, component).permille); }); } static long days_since_epoch(timestamp_t timestamp) diff --git a/core/fulltext.cpp b/core/fulltext.cpp index 563d6967c..b010f25ab 100644 --- a/core/fulltext.cpp +++ b/core/fulltext.cpp @@ -125,10 +125,8 @@ static std::vector getWords(const dive *d) tokenize(QString(d->suit), res); for (const tag_entry *tag = d->tag_list; tag; tag = tag->next) tokenize(QString::fromStdString(tag->tag->name), res); - for (int i = 0; i < d->cylinders.nr; ++i) { - const cylinder_t &cyl = *get_cylinder(d, i); - tokenize(QString(cyl.type.description), res); - } + for (auto &cyl: d->cylinders) + tokenize(QString::fromStdString(cyl.type.description), res); for (int i = 0; i < d->weightsystems.nr; ++i) { const weightsystem_t &ws = d->weightsystems.weightsystems[i]; tokenize(QString(ws.description), res); diff --git a/core/gas.cpp b/core/gas.cpp index 823bb9803..398a2127c 100644 --- a/core/gas.cpp +++ b/core/gas.cpp @@ -40,20 +40,20 @@ int same_gasmix(struct gasmix a, struct gasmix b) return get_o2(a) == get_o2(b) && get_he(a) == get_he(b); } -void sanitize_gasmix(struct gasmix *mix) +void sanitize_gasmix(struct gasmix &mix) { unsigned int o2, he; - o2 = get_o2(*mix); - he = get_he(*mix); + o2 = get_o2(mix); + he = get_he(mix); /* Regular air: leave empty */ if (!he) { if (!o2) return; /* 20.8% to 21% O2 is just air */ - if (gasmix_is_air(*mix)) { - mix->o2.permille = 0; + if (gasmix_is_air(mix)) { + mix.o2.permille = 0; return; } } @@ -62,7 +62,7 @@ void sanitize_gasmix(struct gasmix *mix) if (o2 <= 1000 && he <= 1000 && o2 + he <= 1000) return; report_info("Odd gasmix: %u O2 %u He", o2, he); - *mix = gasmix_air; + mix = gasmix_air; } int gasmix_distance(struct gasmix a, struct gasmix b) diff --git a/core/gas.h b/core/gas.h index 8a8352be0..4e6bcf193 100644 --- a/core/gas.h +++ b/core/gas.h @@ -58,7 +58,7 @@ struct gas_pressures { double o2 = 0.0, n2 = 0.0, he = 0.0; }; -extern void sanitize_gasmix(struct gasmix *mix); +extern void sanitize_gasmix(struct gasmix &mix); extern int gasmix_distance(struct gasmix a, struct gasmix b); extern fraction_t get_gas_component_fraction(struct gasmix mix, enum gas_component component); extern gas_pressures fill_pressures(double amb_pressure, struct gasmix mix, double po2, enum divemode_t dctype); diff --git a/core/gaspressures.cpp b/core/gaspressures.cpp index 0179f18ff..0f241f4b1 100644 --- a/core/gaspressures.cpp +++ b/core/gaspressures.cpp @@ -310,13 +310,13 @@ static void debug_print_pressures(struct plot_info &pi) void populate_pressure_information(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi, int sensor) { int first, last, cyl; - cylinder_t *cylinder = get_cylinder(dive, sensor); + const cylinder_t *cylinder = get_cylinder(dive, sensor); std::vector track; size_t current = std::string::npos; int missing_pr = 0, dense = 1; const double gasfactor[5] = {1.0, 0.0, prefs.pscr_ratio/1000.0, 1.0, 1.0 }; - if (sensor < 0 || sensor >= dive->cylinders.nr) + if (sensor < 0 || static_cast(sensor) >= dive->cylinders.size()) return; /* if we have no pressure data whatsoever, this is pointless, so let's just return */ diff --git a/core/import-csv.cpp b/core/import-csv.cpp index 56d6849b5..347b52ab4 100644 --- a/core/import-csv.cpp +++ b/core/import-csv.cpp @@ -494,7 +494,6 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log) bool has_depth = false, has_setpoint = false, has_ndl = false; char *lineptr; int prev_time = 0; - cylinder_t cyl; struct divecomputer *dc; struct tm cur_tm; @@ -517,26 +516,32 @@ int parse_txt_file(const char *filename, const char *csv, struct divelog *log) dive->dcs[0].divemode = CCR; dive->dcs[0].no_o2sensors = 2; - cyl.cylinder_use = OXYGEN; - cyl.type.size.mliter = 3000; - cyl.type.workingpressure.mbar = 200000; - cyl.type.description = "3l Mk6"; - cyl.gasmix.o2.permille = 1000; - cyl.manually_added = true; - cyl.bestmix_o2 = 0; - cyl.bestmix_he = 0; - add_cloned_cylinder(&dive->cylinders, cyl); + { + cylinder_t cyl; + cyl.cylinder_use = OXYGEN; + cyl.type.size.mliter = 3000; + cyl.type.workingpressure.mbar = 200000; + cyl.type.description = "3l Mk6"; + cyl.gasmix.o2.permille = 1000; + cyl.manually_added = true; + cyl.bestmix_o2 = 0; + cyl.bestmix_he = 0; + dive->cylinders.push_back(std::move(cyl)); + } - cyl.cylinder_use = DILUENT; - cyl.type.size.mliter = 3000; - cyl.type.workingpressure.mbar = 200000; - cyl.type.description = "3l Mk6"; - value = parse_mkvi_value(memtxt.data(), "Helium percentage"); - he = atoi(value.c_str()); - value = parse_mkvi_value(memtxt.data(), "Nitrogen percentage"); - cyl.gasmix.o2.permille = (100 - atoi(value.c_str()) - he) * 10; - cyl.gasmix.he.permille = he * 10; - add_cloned_cylinder(&dive->cylinders, cyl); + { + cylinder_t cyl; + cyl.cylinder_use = DILUENT; + cyl.type.size.mliter = 3000; + cyl.type.workingpressure.mbar = 200000; + cyl.type.description = "3l Mk6"; + value = parse_mkvi_value(memtxt.data(), "Helium percentage"); + he = atoi(value.c_str()); + value = parse_mkvi_value(memtxt.data(), "Nitrogen percentage"); + cyl.gasmix.o2.permille = (100 - atoi(value.c_str()) - he) * 10; + cyl.gasmix.he.permille = he * 10; + dive->cylinders.push_back(std::move(cyl)); + } lineptr = strstr(memtxt.data(), "Dive started at"); while (!empty_string(lineptr) && (lineptr = strchr(lineptr, '\n'))) { diff --git a/core/import-divinglog.cpp b/core/import-divinglog.cpp index 6907caeb7..2ff967cdd 100644 --- a/core/import-divinglog.cpp +++ b/core/import-divinglog.cpp @@ -130,7 +130,7 @@ static int divinglog_profile(void *param, int, char **data, char **) state->cur_sample->temperature.mkelvin = C_to_mkelvin(temp / 10.0f); state->cur_sample->pressure[0].mbar = pressure * 100; state->cur_sample->rbt.seconds = rbt; - if (oldcyl != tank && tank >= 0 && tank < state->cur_dive->cylinders.nr) { + if (oldcyl != tank && tank >= 0 && static_cast(tank) < state->cur_dive->cylinders.size()) { struct gasmix mix = get_cylinder(state->cur_dive.get(), tank)->gasmix; int o2 = get_o2(mix); int he = get_he(mix); diff --git a/core/import-shearwater.cpp b/core/import-shearwater.cpp index 5ce5bbc3d..077feec09 100644 --- a/core/import-shearwater.cpp +++ b/core/import-shearwater.cpp @@ -58,24 +58,20 @@ static int shearwater_changes(void *param, int columns, char **data, char **) o2 = 1000; // Find the cylinder index - int index; - bool found = false; - for (index = 0; index < state->cur_dive->cylinders.nr; ++index) { - const cylinder_t *cyl = get_cylinder(state->cur_dive.get(), index); - if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he) { - found = true; - break; - } - } - if (!found) { + auto it = std::find_if(state->cur_dive->cylinders.begin(), state->cur_dive->cylinders.end(), + [o2, he](auto &cyl) + { return cyl.gasmix.o2.permille == o2 && cyl.gasmix.he.permille == he; }); + if (it == state->cur_dive->cylinders.end()) { // Cylinder not found, creating a new one cyl = cylinder_start(state); cyl->gasmix.o2.permille = o2; cyl->gasmix.he.permille = he; cylinder_end(state); + it = std::prev(state->cur_dive->cylinders.end()); } - add_gas_switch_event(state->cur_dive.get(), get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), index); + add_gas_switch_event(state->cur_dive.get(), get_dc(state), state->sample_rate ? atoi(data[0]) / state->sample_rate * 10 : atoi(data[0]), + it - state->cur_dive->cylinders.begin()); return 0; } @@ -103,9 +99,8 @@ static int shearwater_profile_sample(void *param, int, char **data, char **) state->cur_sample->depth.mm = state->metric ? lrint(permissive_strtod(data[1], NULL) * 1000) : feet_to_mm(permissive_strtod(data[1], NULL)); if (data[2]) state->cur_sample->temperature.mkelvin = state->metric ? C_to_mkelvin(permissive_strtod(data[2], NULL)) : F_to_mkelvin(permissive_strtod(data[2], NULL)); - if (data[3]) { + if (data[3]) state->cur_sample->setpoint.mbar = lrint(permissive_strtod(data[3], NULL) * 1000); - } if (data[4]) state->cur_sample->ndl.seconds = atoi(data[4]) * 60; if (data[5]) diff --git a/core/libdivecomputer.cpp b/core/libdivecomputer.cpp index 2bf817a45..0efed9f32 100644 --- a/core/libdivecomputer.cpp +++ b/core/libdivecomputer.cpp @@ -165,7 +165,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_ bottom_gas = gasmix_air; } - clear_cylinder_table(&dive->cylinders); + dive->cylinders.clear(); for (i = 0; i < std::max(ngases, ntanks); i++) { cylinder_t cyl; cyl.cylinder_use = NOT_USED; @@ -266,7 +266,7 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_ snprintf(name_buffer, sizeof(name_buffer), "%d cuft", rounded_size); break; } - cyl.type.description = copy_string(name_buffer); + cyl.type.description = name_buffer; cyl.type.size.mliter = lrint(cuft_to_l(rounded_size) * 1000 / mbar_to_atm(cyl.type.workingpressure.mbar)); } @@ -301,10 +301,10 @@ static dc_status_t parse_gasmixes(device_data_t *devdata, struct dive *dive, dc_ fill_default_cylinder(dive, &cyl); } /* whatever happens, make sure there is a name for the cylinder */ - if (empty_string(cyl.type.description)) - cyl.type.description = strdup(translate("gettextFromC", "unknown")); + if (cyl.type.description.empty()) + cyl.type.description = translate("gettextFromC", "unknown"); - add_cylinder(&dive->cylinders, dive->cylinders.nr, cyl); + dive->cylinders.push_back(std::move(cyl)); } return DC_STATUS_SUCCESS; } diff --git a/core/liquivision.cpp b/core/liquivision.cpp index ef2203596..0147b9468 100644 --- a/core/liquivision.cpp +++ b/core/liquivision.cpp @@ -147,8 +147,7 @@ static void parse_dives(int log_version, const unsigned char *buf, unsigned int /* Just the main cylinder until we can handle the buddy cylinder porperly */ for (i = 0; i < 1; i++) { - cylinder_t cyl; - fill_default_cylinder(dive.get(), &cyl); + cylinder_t cyl = default_cylinder(dive.get()); add_cylinder(&dive->cylinders, i, cyl); } diff --git a/core/load-git.cpp b/core/load-git.cpp index 8e47da3eb..4fa832644 100644 --- a/core/load-git.cpp +++ b/core/load-git.cpp @@ -389,7 +389,7 @@ static void parse_cylinder_keyvalue(void *_cylinder, const char *key, const std: return; } if (!strcmp(key, "description")) { - cylinder->type.description = strdup(value.c_str()); + cylinder->type.description = value; return; } if (!strcmp(key, "o2")) { @@ -444,9 +444,9 @@ static void parse_dive_cylinder(char *line, struct git_parser_state *state) line = parse_keyvalue_entry(parse_cylinder_keyvalue, &cylinder, line, state); } if (cylinder.cylinder_use == OXYGEN) - state->o2pressure_sensor = state->active_dive->cylinders.nr; + state->o2pressure_sensor = static_cast(state->active_dive->cylinders.size()); - add_cylinder(&state->active_dive->cylinders, state->active_dive->cylinders.nr, cylinder); + state->active_dive->cylinders.push_back(std::move(cylinder)); } static void parse_weightsystem_keyvalue(void *_ws, const char *key, const std::string &value) @@ -655,7 +655,7 @@ static char *parse_sample_unit(struct sample *sample, double val, char *unit) */ static int sanitize_sensor_id(const struct dive *d, int nr) { - return d && nr >= 0 && nr < d->cylinders.nr ? nr : NO_SENSOR; + return d && nr >= 0 && static_cast(nr) < d->cylinders.size() ? nr : NO_SENSOR; } /* diff --git a/core/parse-xml.cpp b/core/parse-xml.cpp index b67827586..ce1dfa263 100644 --- a/core/parse-xml.cpp +++ b/core/parse-xml.cpp @@ -32,6 +32,7 @@ #include "membuffer.h" #include "picture.h" #include "qthelper.h" +#include "range.h" #include "sample.h" #include "tag.h" #include "xmlparams.h" @@ -233,7 +234,7 @@ static void cylinder_use(const char *buffer, enum cylinderuse *cyl_use, struct p enum cylinderuse use = cylinderuse_from_text(trimmed.c_str()); *cyl_use = use; if (use == OXYGEN) - state->o2pressure_sensor = state->cur_dive->cylinders.nr - 1; + state->o2pressure_sensor = static_cast(state->cur_dive->cylinders.size()) - 1; } } @@ -990,10 +991,8 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf, { /* For cylinder related fields, we might have to create a cylinder first. */ cylinder_t cyl; - if (MATCH("tanktype", utf8_string, (char **)&cyl.type.description)) { - cylinder_t *cyl0 = get_or_create_cylinder(dive, 0); - free((void *)cyl0->type.description); - cyl0->type.description = cyl.type.description; + if (MATCH("tanktype", utf8_string_std, &cyl.type.description)) { + get_or_create_cylinder(dive, 0)->type.description = std::move(cyl.type.description); return 1; } if (MATCH("tanksize", cylindersize, &cyl.type.size)) { @@ -1230,7 +1229,7 @@ static void gps_picture_location(const char *buffer, struct picture *pic) /* We're in the top-level dive xml. Try to convert whatever value to a dive value */ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, struct parser_state *state) { - cylinder_t *cyl = dive->cylinders.nr > 0 ? get_cylinder(dive, dive->cylinders.nr - 1) : NULL; + cylinder_t *cyl = !dive->cylinders.empty() ? &dive->cylinders.back() : NULL; weightsystem_t *ws = dive->weightsystems.nr > 0 ? &dive->weightsystems.weightsystems[dive->weightsystems.nr - 1] : NULL; pressure_t p; @@ -1356,7 +1355,7 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str return; if (MATCH_STATE("workpressure.cylinder", pressure, &cyl->type.workingpressure)) return; - if (MATCH("description.cylinder", utf8_string, (char **)&cyl->type.description)) + if (MATCH("description.cylinder", utf8_string_std, &cyl->type.description)) return; if (MATCH_STATE("start.cylinder", pressure, &cyl->start)) return; @@ -1798,7 +1797,6 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log) unsigned char event; bool found; unsigned int time = 0; - int i; char serial[6]; struct battery_status { uint16_t volt1; @@ -1971,11 +1969,10 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log) state.cur_event.type = SAMPLE_EVENT_GASCHANGE2; state.cur_event.value = ptr[7] << 8 ^ ptr[6]; - found = false; - for (i = 0; i < state.cur_dive->cylinders.nr; ++i) { - const cylinder_t *cyl = get_cylinder(state.cur_dive.get(), i); - if (cyl->gasmix.o2.permille == ptr[6] * 10 && cyl->gasmix.he.permille == ptr[7] * 10) { + for (const auto [i, cyl]: enumerated_range(state.cur_dive->cylinders)) { + if (cyl.gasmix.o2.permille == ptr[6] * 10 && cyl.gasmix.he.permille == ptr[7] * 10) { found = true; + state.cur_event.gas.index = i; break; } } @@ -1984,9 +1981,7 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct divelog *log) cyl->gasmix.o2.permille = ptr[6] * 10; cyl->gasmix.he.permille = ptr[7] * 10; cylinder_end(&state); - state.cur_event.gas.index = state.cur_dive->cylinders.nr - 1; - } else { - state.cur_event.gas.index = i; + state.cur_event.gas.index = static_cast(state.cur_dive->cylinders.size()) - 1; } break; case 6: diff --git a/core/parse.cpp b/core/parse.cpp index 6859d1299..9b8e100bd 100644 --- a/core/parse.cpp +++ b/core/parse.cpp @@ -335,7 +335,7 @@ void ws_end(struct parser_state *state) */ static int sanitize_sensor_id(const struct dive *d, int nr) { - return d && nr >= 0 && nr < d->cylinders.nr ? nr : NO_SENSOR; + return d && nr >= 0 && static_cast(nr) < d->cylinders.size() ? nr : NO_SENSOR; } /* diff --git a/core/planner.cpp b/core/planner.cpp index f6f856a43..3bf63227a 100644 --- a/core/planner.cpp +++ b/core/planner.cpp @@ -19,6 +19,7 @@ #include "event.h" #include "interpolate.h" #include "planner.h" +#include "range.h" #include "subsurface-time.h" #include "gettext.h" #include "libdivecomputer/parser.h" @@ -94,7 +95,7 @@ int get_cylinderid_at_time(struct dive *dive, struct divecomputer *dc, duration_ static int get_gasidx(struct dive *dive, struct gasmix mix) { - return find_best_gasmix_match(mix, &dive->cylinders); + return find_best_gasmix_match(mix, dive->cylinders); } static void interpolate_transition(struct deco_state *ds, struct dive *dive, duration_t t0, duration_t t1, depth_t d0, depth_t d1, struct gasmix gasmix, o2pressure_t po2, enum divemode_t divemode) @@ -368,12 +369,12 @@ struct gaschanges { static int setpoint_change(struct dive *dive, int cylinderid) { cylinder_t *cylinder = get_cylinder(dive, cylinderid); - if (!cylinder->type.description) + if (cylinder->type.description.empty()) return 0; - if (!strncmp(cylinder->type.description, "SP ", 3)) { + if (starts_with(cylinder->type.description, "SP ")) { float sp; - sscanf(cylinder->type.description + 3, "%f", &sp); - return (int) (sp * 1000); + sscanf(cylinder->type.description.c_str() + 3, "%f", &sp); + return (int) (sp * 1000.0); } else { return 0; } @@ -572,10 +573,9 @@ static bool trial_ascent(struct deco_state *ds, int wait_time, int trial_depth, */ static bool enough_gas(const struct dive *dive, int current_cylinder) { - cylinder_t *cyl; - if (current_cylinder < 0 || current_cylinder >= dive->cylinders.nr) + if (current_cylinder < 0 || static_cast(current_cylinder) >= dive->cylinders.size()) return false; - cyl = get_cylinder(dive, current_cylinder); + const cylinder_t *cyl = get_cylinder(dive, current_cylinder); if (!cyl->start.mbar) return true; @@ -1086,7 +1086,7 @@ bool plan(struct deco_state *ds, struct diveplan *diveplan, struct dive *dive, i // we had a fixed cylinder table: It uses an extra fake cylinder // past the regular cylinder table, which is not visible to the UI. // Fix this as soon as possible! - current_cylinder = dive->cylinders.nr; + current_cylinder = static_cast(dive->cylinders.size()); plan_add_segment(diveplan, prefs.surface_segment, 0, current_cylinder, 0, false, OC); } create_dive_from_plan(diveplan, dive, dc, is_planner); diff --git a/core/plannernotes.cpp b/core/plannernotes.cpp index b47b8101f..71f1577c8 100644 --- a/core/plannernotes.cpp +++ b/core/plannernotes.cpp @@ -16,6 +16,7 @@ #include "units.h" #include "divelist.h" #include "planner.h" +#include "range.h" #include "gettext.h" #include "libdivecomputer/parser.h" #include "qthelper.h" @@ -461,34 +462,33 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d } /* Print gas consumption: This loop covers all cylinders */ - for (int gasidx = 0; gasidx < dive->cylinders.nr; gasidx++) { + for (auto [gasidx, cyl]: enumerated_range(dive->cylinders)) { double volume, pressure, deco_volume, deco_pressure, mingas_volume, mingas_pressure, mingas_d_pressure, mingas_depth; const char *unit, *pressure_unit, *depth_unit; std::string temp; std::string warning; std::string mingas; - cylinder_t *cyl = get_cylinder(dive, gasidx); - if (cyl->cylinder_use == NOT_USED) + if (cyl.cylinder_use == NOT_USED) continue; - volume = get_volume_units(cyl->gas_used.mliter, NULL, &unit); - deco_volume = get_volume_units(cyl->deco_gas_used.mliter, NULL, &unit); - if (cyl->type.size.mliter) { - int remaining_gas = lrint((double)cyl->end.mbar * cyl->type.size.mliter / 1000.0 / gas_compressibility_factor(cyl->gasmix, cyl->end.mbar / 1000.0)); - double deco_pressure_mbar = isothermal_pressure(cyl->gasmix, 1.0, remaining_gas + cyl->deco_gas_used.mliter, - cyl->type.size.mliter) * 1000 - cyl->end.mbar; + volume = get_volume_units(cyl.gas_used.mliter, NULL, &unit); + deco_volume = get_volume_units(cyl.deco_gas_used.mliter, NULL, &unit); + if (cyl.type.size.mliter) { + int remaining_gas = lrint((double)cyl.end.mbar * cyl.type.size.mliter / 1000.0 / gas_compressibility_factor(cyl.gasmix, cyl.end.mbar / 1000.0)); + double deco_pressure_mbar = isothermal_pressure(cyl.gasmix, 1.0, remaining_gas + cyl.deco_gas_used.mliter, + cyl.type.size.mliter) * 1000 - cyl.end.mbar; deco_pressure = get_pressure_units(lrint(deco_pressure_mbar), &pressure_unit); - pressure = get_pressure_units(cyl->start.mbar - cyl->end.mbar, &pressure_unit); + pressure = get_pressure_units(cyl.start.mbar - cyl.end.mbar, &pressure_unit); /* Warn if the plan uses more gas than is available in a cylinder * This only works if we have working pressure for the cylinder * 10bar is a made up number - but it seemed silly to pretend you could breathe cylinder down to 0 */ - if (cyl->end.mbar < 10000) + if (cyl.end.mbar < 10000) warning = format_string_std("
\n — %s %s", translate("gettextFromC", "Warning:"), translate("gettextFromC", "this is more gas than available in the specified cylinder!")); else - if (cyl->end.mbar / 1000.0 * cyl->type.size.mliter / gas_compressibility_factor(cyl->gasmix, cyl->end.mbar / 1000.0) - < cyl->deco_gas_used.mliter) + if (cyl.end.mbar / 1000.0 * cyl.type.size.mliter / gas_compressibility_factor(cyl.gasmix, cyl.end.mbar / 1000.0) + < cyl.deco_gas_used.mliter) warning = format_string_std("
\n — %s %s", translate("gettextFromC", "Warning:"), translate("gettextFromC", "not enough reserve for gas sharing on ascent!")); @@ -502,17 +502,17 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d volume_t mingasv; mingasv.mliter = lrint(prefs.sacfactor / 100.0 * prefs.problemsolvingtime * prefs.bottomsac * depth_to_bar(lastbottomdp->depth.mm, dive) - + prefs.sacfactor / 100.0 * cyl->deco_gas_used.mliter); + + prefs.sacfactor / 100.0 * cyl.deco_gas_used.mliter); /* Calculate minimum gas pressure for cyclinder. */ - lastbottomdp->minimum_gas.mbar = lrint(isothermal_pressure(cyl->gasmix, 1.0, - mingasv.mliter, cyl->type.size.mliter) * 1000); + lastbottomdp->minimum_gas.mbar = lrint(isothermal_pressure(cyl.gasmix, 1.0, + mingasv.mliter, cyl.type.size.mliter) * 1000); /* Translate all results into correct units */ mingas_volume = get_volume_units(mingasv.mliter, NULL, &unit); mingas_pressure = get_pressure_units(lastbottomdp->minimum_gas.mbar, &pressure_unit); - mingas_d_pressure = get_pressure_units(lrint((double)cyl->end.mbar + deco_pressure_mbar - lastbottomdp->minimum_gas.mbar), &pressure_unit); + mingas_d_pressure = get_pressure_units(lrint((double)cyl.end.mbar + deco_pressure_mbar - lastbottomdp->minimum_gas.mbar), &pressure_unit); mingas_depth = get_depth_units(lastbottomdp->depth.mm, NULL, &depth_unit); /* Print it to results */ - if (cyl->start.mbar > lastbottomdp->minimum_gas.mbar) { + if (cyl.start.mbar > lastbottomdp->minimum_gas.mbar) { mingas = casprintf_loc("
\n — %s (%s %.1fx%s/+%d%s@%.0f%s): " "%.0f%s/%.0f%s/Δ:%+.0f%s", mingas_d_pressure > 0 ? "green" :"red", @@ -536,18 +536,18 @@ void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive, bool show_d /* Print the gas consumption for every cylinder here to temp buffer. */ if (lrint(volume) > 0) { temp = casprintf_loc(translate("gettextFromC", "%.0f%s/%.0f%s of %s (%.0f%s/%.0f%s in planned ascent)"), - volume, unit, pressure, pressure_unit, gasname(cyl->gasmix), deco_volume, unit, deco_pressure, pressure_unit); + volume, unit, pressure, pressure_unit, gasname(cyl.gasmix), deco_volume, unit, deco_pressure, pressure_unit); } else { temp = casprintf_loc(translate("gettextFromC", "%.0f%s/%.0f%s of %s"), - volume, unit, pressure, pressure_unit, gasname(cyl->gasmix)); + volume, unit, pressure, pressure_unit, gasname(cyl.gasmix)); } } else { if (lrint(volume) > 0) { temp = casprintf_loc(translate("gettextFromC", "%.0f%s of %s (%.0f%s during planned ascent)"), - volume, unit, gasname(cyl->gasmix), deco_volume, unit); + volume, unit, gasname(cyl.gasmix), deco_volume, unit); } else { temp = casprintf_loc(translate("gettextFromC", "%.0f%s of %s"), - volume, unit, gasname(cyl->gasmix)); + volume, unit, gasname(cyl.gasmix)); } } /* Gas consumption: Now finally print all strings to output */ diff --git a/core/profile.cpp b/core/profile.cpp index fffb6108a..b59f19930 100644 --- a/core/profile.cpp +++ b/core/profile.cpp @@ -24,6 +24,7 @@ #include "libdivecomputer/version.h" #include "membuffer.h" #include "qthelper.h" +#include "range.h" #include "format.h" //#define DEBUG_GAS 1 @@ -216,7 +217,7 @@ int get_cylinder_index(const struct dive *dive, const struct event &ev) report_info("Still looking up cylinder based on gas mix in get_cylinder_index()!"); mix = get_gasmix_from_event(dive, ev); - best = find_best_gasmix_match(mix, &dive->cylinders); + best = find_best_gasmix_match(mix, dive->cylinders); return best < 0 ? 0 : best; } @@ -259,12 +260,11 @@ static void calculate_max_limits_new(const struct dive *dive, const struct divec int maxhr = 0, minhr = INT_MAX; int mintemp = dive->mintemp.mkelvin; int maxtemp = dive->maxtemp.mkelvin; - int cyl; /* Get the per-cylinder maximum pressure if they are manual */ - for (cyl = 0; cyl < dive->cylinders.nr; cyl++) { - int mbar_start = get_cylinder(dive, cyl)->start.mbar; - int mbar_end = get_cylinder(dive, cyl)->end.mbar; + for (auto &cyl: dive->cylinders) { + int mbar_start = cyl.start.mbar; + int mbar_end = cyl.end.mbar; if (mbar_start > maxpressure) maxpressure = mbar_start; if (mbar_end && mbar_end < minpressure) @@ -364,7 +364,7 @@ static void insert_entry(struct plot_info &pi, int time, int depth, int sac) static void populate_plot_entries(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi) { - pi.nr_cylinders = dive->cylinders.nr; + pi.nr_cylinders = static_cast(dive->cylinders.size()); /* * To avoid continuous reallocation, allocate the expected number of entries. @@ -494,26 +494,21 @@ static void populate_plot_entries(const struct dive *dive, const struct divecomp */ static int sac_between(const struct dive *dive, const struct plot_info &pi, int first, int last, const char gases[]) { - int i, airuse; - double pressuretime; - if (first == last) return 0; /* Get airuse for the set of cylinders over the range */ - airuse = 0; - for (i = 0; i < pi.nr_cylinders; i++) { + int airuse = 0; + for (int i = 0; i < pi.nr_cylinders; i++) { pressure_t a, b; - cylinder_t *cyl; - int cyluse; if (!gases[i]) continue; a.mbar = get_plot_pressure(pi, first, i); b.mbar = get_plot_pressure(pi, last, i); - cyl = get_cylinder(dive, i); - cyluse = gas_volume(cyl, a) - gas_volume(cyl, b); + const cylinder_t *cyl = get_cylinder(dive, i); + int cyluse = gas_volume(cyl, a) - gas_volume(cyl, b); if (cyluse > 0) airuse += cyluse; } @@ -521,7 +516,7 @@ static int sac_between(const struct dive *dive, const struct plot_info &pi, int return 0; /* Calculate depthpressure integrated over time */ - pressuretime = 0.0; + double pressuretime = 0.0; do { const struct plot_data &entry = pi.entry[first]; const struct plot_data &next = pi.entry[first + 1]; @@ -632,8 +627,8 @@ static void fill_sac(const struct dive *dive, struct plot_info &pi, int idx, con */ static void matching_gases(const struct dive *dive, struct gasmix gasmix, char gases[]) { - for (int i = 0; i < dive->cylinders.nr; i++) - gases[i] = same_gasmix(gasmix, get_cylinder(dive, i)->gasmix); + for (auto [i, cyl]: enumerated_range(dive->cylinders)) + gases[i] = same_gasmix(gasmix, cyl.gasmix); } static void calculate_sac(const struct dive *dive, const struct divecomputer *dc, struct plot_info &pi) @@ -1536,7 +1531,7 @@ std::vector compare_samples(const struct dive *d, const struct plot if (last_pressures[cylinder_index]) { bar_used[cylinder_index] += last_pressures[cylinder_index] - next_pressure; - cylinder_t *cyl = get_cylinder(d, cylinder_index); + const cylinder_t *cyl = get_cylinder(d, cylinder_index); volumes_used[cylinder_index] += gas_volume(cyl, (pressure_t){ last_pressures[cylinder_index] }) - gas_volume(cyl, (pressure_t){ next_pressure }); } @@ -1589,7 +1584,7 @@ std::vector compare_samples(const struct dive *d, const struct plot total_bar_used += bar_used[cylinder_index]; total_volume_used += volumes_used[cylinder_index]; - cylinder_t *cyl = get_cylinder(d, cylinder_index); + const cylinder_t *cyl = get_cylinder(d, cylinder_index); if (cyl->type.size.mliter) { if (cylinder_volume.mliter && cylinder_volume.mliter != cyl->type.size.mliter) { cylindersizes_are_identical = false; diff --git a/core/profile.h b/core/profile.h index e8a03a8fb..405bbc1a7 100644 --- a/core/profile.h +++ b/core/profile.h @@ -95,7 +95,7 @@ struct plot_info { double maxpp = 0.0; bool waypoint_above_ceiling = false; std::vector entry; - std::vector pressures; /* cylinders.nr blocks of nr entries. */ + std::vector pressures; /* cylinders.size() blocks of nr entries. */ plot_info(); ~plot_info(); diff --git a/core/qthelper.cpp b/core/qthelper.cpp index 87563bc0f..f0582d01a 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -12,6 +12,7 @@ #include "version.h" #include "errorhelper.h" #include "planner.h" +#include "range.h" #include "subsurface-time.h" #include "gettextfromc.h" #include "metadata.h" @@ -357,11 +358,10 @@ static bool lessThan(const QPair &a, const QPair &b) QVector> selectedDivesGasUsed() { - int j; QMap gasUsed; for (dive *d: getDiveSelection()) { std::vector diveGases = get_gas_used(d); - for (j = 0; j < d->cylinders.nr; j++) { + for (size_t j = 0; j < d->cylinders.size(); j++) { if (diveGases[j].mliter) { QString gasName = gasname(get_cylinder(d, j)->gasmix); gasUsed[gasName] += diveGases[j].mliter; @@ -1189,16 +1189,15 @@ QString get_gas_string(struct gasmix gas) QStringList get_dive_gas_list(const struct dive *d) { QStringList list; - for (int i = 0; i < d->cylinders.nr; i++) { - const cylinder_t *cyl = get_cylinder(d, i); + for (auto [i, cyl]: enumerated_range(d->cylinders)) { /* Check if we have the same gasmix two or more times * If yes return more verbose string */ int same_gas = same_gasmix_cylinder(cyl, i, d, true); if (same_gas == -1) - list.push_back(get_gas_string(cyl->gasmix)); + list.push_back(get_gas_string(cyl.gasmix)); else - list.push_back(get_gas_string(cyl->gasmix) + QString(" (%1 %2 ").arg(gettextFromC::tr("cyl.")).arg(i + 1) + - cyl->type.description + ")"); + list.push_back(get_gas_string(cyl.gasmix) + QStringLiteral(" (%1 %2 ").arg(gettextFromC::tr("cyl.")).arg(i + 1) + + QString::fromStdString(cyl.type.description) + ")"); } return list; } diff --git a/core/save-git.cpp b/core/save-git.cpp index 5c27b0a77..ff8d489a9 100644 --- a/core/save-git.cpp +++ b/core/save-git.cpp @@ -141,28 +141,23 @@ static void put_gasmix(struct membuffer *b, struct gasmix mix) static void save_cylinder_info(struct membuffer *b, struct dive *dive) { - int i, nr; - - nr = nr_cylinders(dive); - for (i = 0; i < nr; i++) { - cylinder_t *cylinder = get_cylinder(dive, i); - int volume = cylinder->type.size.mliter; - const char *description = cylinder->type.description; - int use = cylinder->cylinder_use; + for (auto &cyl: dive->cylinders) { + int volume = cyl.type.size.mliter; + int use = cyl.cylinder_use; put_string(b, "cylinder"); if (volume) put_milli(b, " vol=", volume, "l"); - put_pressure(b, cylinder->type.workingpressure, " workpressure=", "bar"); - show_utf8(b, " description=", description, ""); + put_pressure(b, cyl.type.workingpressure, " workpressure=", "bar"); + show_utf8(b, " description=", cyl.type.description.c_str(), ""); strip_mb(b); - put_gasmix(b, cylinder->gasmix); - put_pressure(b, cylinder->start, " start=", "bar"); - put_pressure(b, cylinder->end, " end=", "bar"); + put_gasmix(b, cyl.gasmix); + put_pressure(b, cyl.start, " start=", "bar"); + put_pressure(b, cyl.end, " end=", "bar"); if (use > OC_GAS && use < NUM_GAS_USE) show_utf8(b, " use=", cylinderuse_text[use], ""); - if (cylinder->depth.mm != 0) - put_milli(b, " depth=", cylinder->depth.mm, "m"); + if (cyl.depth.mm != 0) + put_milli(b, " depth=", cyl.depth.mm, "m"); put_string(b, "\n"); } } diff --git a/core/save-html.cpp b/core/save-html.cpp index 28ab7e579..9971d41fe 100644 --- a/core/save-html.cpp +++ b/core/save-html.cpp @@ -121,43 +121,40 @@ static void put_weightsystem_HTML(struct membuffer *b, const struct dive *dive) static void put_cylinder_HTML(struct membuffer *b, const struct dive *dive) { - int i, nr; const char *separator = "\"Cylinders\":["; - nr = nr_cylinders(dive); - if (!nr) + if (dive->cylinders.empty()) put_string(b, separator); - for (i = 0; i < nr; i++) { - cylinder_t *cylinder = get_cylinder(dive, i); + for (auto &cyl: dive->cylinders) { put_format(b, "%s{", separator); separator = ", "; - write_attribute(b, "Type", cylinder->type.description, ", "); - if (cylinder->type.size.mliter) { - int volume = cylinder->type.size.mliter; - if (prefs.units.volume == units::CUFT && cylinder->type.workingpressure.mbar) - volume = lrint(volume * bar_to_atm(cylinder->type.workingpressure.mbar / 1000.0)); + write_attribute(b, "Type", cyl.type.description.c_str(), ", "); + if (cyl.type.size.mliter) { + int volume = cyl.type.size.mliter; + if (prefs.units.volume == units::CUFT && cyl.type.workingpressure.mbar) + volume = lrint(volume * bar_to_atm(cyl.type.workingpressure.mbar / 1000.0)); put_HTML_volume_units(b, volume, "\"Size\":\"", " \", "); } else { write_attribute(b, "Size", "--", ", "); } - put_HTML_pressure_units(b, cylinder->type.workingpressure, "\"WPressure\":\"", " \", "); + put_HTML_pressure_units(b, cyl.type.workingpressure, "\"WPressure\":\"", " \", "); - if (cylinder->start.mbar) { - put_HTML_pressure_units(b, cylinder->start, "\"SPressure\":\"", " \", "); + if (cyl.start.mbar) { + put_HTML_pressure_units(b, cyl.start, "\"SPressure\":\"", " \", "); } else { write_attribute(b, "SPressure", "--", ", "); } - if (cylinder->end.mbar) { - put_HTML_pressure_units(b, cylinder->end, "\"EPressure\":\"", " \", "); + if (cyl.end.mbar) { + put_HTML_pressure_units(b, cyl.end, "\"EPressure\":\"", " \", "); } else { write_attribute(b, "EPressure", "--", ", "); } - if (cylinder->gasmix.o2.permille) { - put_format(b, "\"O2\":\"%u.%u%%\",", FRACTION_TUPLE(cylinder->gasmix.o2.permille, 10)); - put_format(b, "\"He\":\"%u.%u%%\"", FRACTION_TUPLE(cylinder->gasmix.he.permille, 10)); + if (cyl.gasmix.o2.permille) { + put_format(b, "\"O2\":\"%u.%u%%\",", FRACTION_TUPLE(cyl.gasmix.o2.permille, 10)); + put_format(b, "\"He\":\"%u.%u%%\"", FRACTION_TUPLE(cyl.gasmix.he.permille, 10)); } else { write_attribute(b, "O2", "Air", ""); } diff --git a/core/save-xml.cpp b/core/save-xml.cpp index db8ec819b..7ba8880be 100644 --- a/core/save-xml.cpp +++ b/core/save-xml.cpp @@ -177,28 +177,22 @@ static void put_gasmix(struct membuffer *b, struct gasmix mix) static void save_cylinder_info(struct membuffer *b, struct dive *dive) { - int i, nr; - - nr = nr_cylinders(dive); - - for (i = 0; i < nr; i++) { - cylinder_t *cylinder = get_cylinder(dive, i); - int volume = cylinder->type.size.mliter; - const char *description = cylinder->type.description; - int use = cylinder->cylinder_use; + for (auto &cyl: dive->cylinders) { + int volume = cyl.type.size.mliter; + int use = cyl.cylinder_use; put_format(b, " type.workingpressure, " workpressure='", " bar'"); - show_utf8(b, description, " description='", "'", 1); - put_gasmix(b, cylinder->gasmix); - put_pressure(b, cylinder->start, " start='", " bar'"); - put_pressure(b, cylinder->end, " end='", " bar'"); + put_pressure(b, cyl.type.workingpressure, " workpressure='", " bar'"); + show_utf8(b, cyl.type.description.c_str(), " description='", "'", 1); + put_gasmix(b, cyl.gasmix); + put_pressure(b, cyl.start, " start='", " bar'"); + put_pressure(b, cyl.end, " end='", " bar'"); if (use > OC_GAS && use < NUM_GAS_USE) show_utf8(b, cylinderuse_text[use], " use='", "'", 1); - if (cylinder->depth.mm != 0) - put_milli(b, " depth='", cylinder->depth.mm, " m'"); + if (cyl.depth.mm != 0) + put_milli(b, " depth='", cyl.depth.mm, " m'"); put_format(b, " />\n"); } } diff --git a/core/statistics.cpp b/core/statistics.cpp index 6b36209aa..501aad223 100644 --- a/core/statistics.cpp +++ b/core/statistics.cpp @@ -9,6 +9,7 @@ #include "divelog.h" #include "event.h" #include "gettext.h" +#include "range.h" #include "sample.h" #include "subsurface-time.h" #include "trip.h" @@ -273,15 +274,14 @@ bool has_gaschange_event(const struct dive *dive, const struct divecomputer *dc, bool is_cylinder_used(const struct dive *dive, int idx) { - cylinder_t *cyl; - if (idx < 0 || idx >= dive->cylinders.nr) + if (idx < 0 || static_cast(idx) >= dive->cylinders.size()) return false; - cyl = get_cylinder(dive, idx); - if ((cyl->start.mbar - cyl->end.mbar) > SOME_GAS) + const cylinder_t &cyl = dive->cylinders[idx]; + if ((cyl.start.mbar - cyl.end.mbar) > SOME_GAS) return true; - if ((cyl->sample_start.mbar - cyl->sample_end.mbar) > SOME_GAS) + if ((cyl.sample_start.mbar - cyl.sample_end.mbar) > SOME_GAS) return true; for (auto &dc: dive->dcs) { @@ -295,7 +295,7 @@ bool is_cylinder_used(const struct dive *dive, int idx) bool is_cylinder_prot(const struct dive *dive, int idx) { - if (idx < 0 || idx >= dive->cylinders.nr) + if (idx < 0 || static_cast(idx) >= dive->cylinders.size()) return false; return std::any_of(dive->dcs.begin(), dive->dcs.end(), @@ -303,18 +303,17 @@ bool is_cylinder_prot(const struct dive *dive, int idx) { return has_gaschange_event(dive, &dc, idx); }); } -/* Returns a vector with dive->cylinders.nr entries */ +/* Returns a vector with dive->cylinders.size() entries */ std::vector get_gas_used(struct dive *dive) { - std::vector gases(dive->cylinders.nr); - for (int idx = 0; idx < dive->cylinders.nr; idx++) { - cylinder_t *cyl = get_cylinder(dive, idx); + std::vector gases(dive->cylinders.size()); + for (auto [idx, cyl]: enumerated_range(dive->cylinders)) { pressure_t start, end; - start = cyl->start.mbar ? cyl->start : cyl->sample_start; - end = cyl->end.mbar ? cyl->end : cyl->sample_end; + start = cyl.start.mbar ? cyl.start : cyl.sample_start; + end = cyl.end.mbar ? cyl.end : cyl.sample_end; if (end.mbar && start.mbar > end.mbar) - gases[idx].mliter = gas_volume(cyl, start) - gas_volume(cyl, end); + gases[idx].mliter = gas_volume(&cyl, start) - gas_volume(&cyl, end); else gases[idx].mliter = 0; } @@ -327,7 +326,7 @@ std::vector get_gas_used(struct dive *dive) static std::pair get_gas_parts(struct gasmix mix, volume_t vol, int o2_in_topup) { if (gasmix_is_air(mix)) - return { {0}, {0} }; + return { volume_t() , volume_t() }; volume_t air = { (int)lrint(((double)vol.mliter * get_n2(mix)) / (1000 - o2_in_topup)) }; volume_t he = { (int)lrint(((double)vol.mliter * get_he(mix)) / 1000.0) }; diff --git a/core/string-format.cpp b/core/string-format.cpp index 718865fa8..39f54de84 100644 --- a/core/string-format.cpp +++ b/core/string-format.cpp @@ -4,6 +4,7 @@ #include "event.h" #include "format.h" #include "qthelper.h" +#include "range.h" #include "subsurface-string.h" #include "trip.h" #include @@ -13,23 +14,21 @@ enum returnPressureSelector { START_PRESSURE, END_PRESSURE }; static QLocale loc; -static QString getPressures(const struct dive *dive, int i, enum returnPressureSelector ret) +static QString getPressures(const cylinder_t &cyl, enum returnPressureSelector ret) { - const cylinder_t *cyl = get_cylinder(dive, i); - QString fmt; if (ret == START_PRESSURE) { - if (cyl->start.mbar) - fmt = get_pressure_string(cyl->start, true); - else if (cyl->sample_start.mbar) - fmt = get_pressure_string(cyl->sample_start, true); + if (cyl.start.mbar) + return get_pressure_string(cyl.start, true); + else if (cyl.sample_start.mbar) + return get_pressure_string(cyl.sample_start, true); } if (ret == END_PRESSURE) { - if (cyl->end.mbar) - fmt = get_pressure_string(cyl->end, true); - else if(cyl->sample_end.mbar) - fmt = get_pressure_string(cyl->sample_end, true); + if (cyl.end.mbar) + return get_pressure_string(cyl.end, true); + else if (cyl.sample_end.mbar) + return get_pressure_string(cyl.sample_end, true); } - return fmt; + return QString(); } QString formatSac(const dive *d) @@ -77,9 +76,9 @@ QString format_gps_decimal(const dive *d) QStringList formatGetCylinder(const dive *d) { QStringList getCylinder; - for (int i = 0; i < d->cylinders.nr; i++) { + for (auto [i, cyl]: enumerated_range(d->cylinders)) { if (is_cylinder_used(d, i)) - getCylinder << get_cylinder(d, i)->type.description; + getCylinder << QString::fromStdString(cyl.type.description); } return getCylinder; } @@ -87,9 +86,9 @@ QStringList formatGetCylinder(const dive *d) QStringList formatStartPressure(const dive *d) { QStringList startPressure; - for (int i = 0; i < d->cylinders.nr; i++) { + for (auto [i, cyl]: enumerated_range(d->cylinders)) { if (is_cylinder_used(d, i)) - startPressure << getPressures(d, i, START_PRESSURE); + startPressure << getPressures(cyl, START_PRESSURE); } return startPressure; } @@ -97,9 +96,9 @@ QStringList formatStartPressure(const dive *d) QStringList formatEndPressure(const dive *d) { QStringList endPressure; - for (int i = 0; i < d->cylinders.nr; i++) { + for (auto [i, cyl]: enumerated_range(d->cylinders)) { if (is_cylinder_used(d, i)) - endPressure << getPressures(d, i, END_PRESSURE); + endPressure << getPressures(cyl, END_PRESSURE); } return endPressure; } @@ -107,9 +106,9 @@ QStringList formatEndPressure(const dive *d) QStringList formatFirstGas(const dive *d) { QStringList gas; - for (int i = 0; i < d->cylinders.nr; i++) { + for (auto [i, cyl]: enumerated_range(d->cylinders)) { if (is_cylinder_used(d, i)) - gas << get_gas_string(get_cylinder(d, i)->gasmix); + gas << get_gas_string(cyl.gasmix); } return gas; } @@ -133,20 +132,14 @@ static void addStringToSortedList(QStringList &l, const std::string &s) l.insert(it, qs); } -// Safely treat null-strings. Remove once everyhting is converted to std::string -static std::string c_to_std(const char *s) -{ - return s ? std::string(s) : std::string(); -} - QStringList formatFullCylinderList() { QStringList cylinders; struct dive *d; int i = 0; for_each_dive (i, d) { - for (int j = 0; j < d->cylinders.nr; j++) - addStringToSortedList(cylinders, c_to_std(get_cylinder(d, j)->type.description)); + for (const cylinder_t &cyl: d->cylinders) + addStringToSortedList(cylinders, cyl.type.description); } for (const auto &ti: tank_info_table) @@ -155,25 +148,22 @@ QStringList formatFullCylinderList() return cylinders; } -static QString formattedCylinder(const struct dive *dive, int idx) +static QString formattedCylinder(const cylinder_t &cyl) { - const cylinder_t *cyl = get_cylinder(dive, idx); - const char *desc = cyl->type.description; - QString fmt = desc ? QString(desc) : gettextFromC::tr("unknown"); - fmt += ", " + get_volume_string(cyl->type.size, true); - fmt += ", " + get_pressure_string(cyl->type.workingpressure, true); - fmt += ", " + get_pressure_string(cyl->start, false) + " - " + get_pressure_string(cyl->end, true); - fmt += ", " + get_gas_string(cyl->gasmix); + const std::string &desc = cyl.type.description; + QString fmt = !desc.empty() ? QString::fromStdString(desc) : gettextFromC::tr("unknown"); + fmt += ", " + get_volume_string(cyl.type.size, true); + fmt += ", " + get_pressure_string(cyl.type.workingpressure, true); + fmt += ", " + get_pressure_string(cyl.start, false) + " - " + get_pressure_string(cyl.end, true); + fmt += ", " + get_gas_string(cyl.gasmix); return fmt; } QStringList formatCylinders(const dive *d) { QStringList cylinders; - for (int i = 0; i < d->cylinders.nr; i++) { - QString cyl = formattedCylinder(d, i); - cylinders << cyl; - } + for (const cylinder_t &cyl: d->cylinders) + cylinders << formattedCylinder(cyl); return cylinders; } @@ -182,14 +172,14 @@ QString formatGas(const dive *d) /*WARNING: here should be the gastlist, returned * from the get_gas_string function or this is correct? */ - QString gas, gases; - for (int i = 0; i < d->cylinders.nr; i++) { + QString gases; + for (auto [i, cyl]: enumerated_range(d->cylinders)) { if (!is_cylinder_used(d, i)) continue; - gas = get_cylinder(d, i)->type.description; + QString gas = QString::fromStdString(cyl.type.description); if (!gas.isEmpty()) gas += QChar(' '); - gas += gasname(get_cylinder(d, i)->gasmix); + gas += gasname(cyl.gasmix); // if has a description and if such gas is not already present if (!gas.isEmpty() && gases.indexOf(gas) == -1) { if (!gases.isEmpty()) diff --git a/core/uemis.cpp b/core/uemis.cpp index 33ec3539f..0f65d71f6 100644 --- a/core/uemis.cpp +++ b/core/uemis.cpp @@ -335,7 +335,7 @@ void uemis::parse_divelog_binary(std::string_view base64, struct dive *dive) u_sample = (uemis_sample *)(data.data() + i); while ((i <= data.size()) && (data[i] != 0 || data[i + 1] != 0)) { if (u_sample->active_tank != active) { - if (u_sample->active_tank >= dive->cylinders.nr) { + if (u_sample->active_tank >= static_cast(dive->cylinders.size())) { report_info("got invalid sensor #%d was #%d", u_sample->active_tank, active); } else { active = u_sample->active_tank; diff --git a/desktop-widgets/profilewidget.cpp b/desktop-widgets/profilewidget.cpp index 8fcb8f66d..81439ad96 100644 --- a/desktop-widgets/profilewidget.cpp +++ b/desktop-widgets/profilewidget.cpp @@ -298,7 +298,7 @@ void ProfileWidget::cylindersChanged(struct dive *changed, int pos) // If we're editing the current dive we have to update the // cylinders of the edited dive. if (editedDive) { - copy_cylinders(&d->cylinders, &editedDive.get()->cylinders); + editedDive.get()->cylinders = d->cylinders; // TODO: Holy moly that function sends too many signals. Fix it! DivePlannerPointsModel::instance()->loadFromDive(editedDive.get(), dc); } diff --git a/desktop-widgets/simplewidgets.cpp b/desktop-widgets/simplewidgets.cpp index 748820d31..00cd24a8d 100644 --- a/desktop-widgets/simplewidgets.cpp +++ b/desktop-widgets/simplewidgets.cpp @@ -23,6 +23,7 @@ #include "profile-widget/profilewidget2.h" #include "commands/command.h" #include "core/metadata.h" +#include "core/range.h" #include "core/tag.h" void RenumberDialog::buttonClicked(QAbstractButton *button) @@ -348,11 +349,10 @@ void DiveComponentSelection::buttonClicked(QAbstractButton *button) text << "\n"; } if (what->cylinders) { - int cyl; text << tr("Cylinders:\n"); - for (cyl = 0; cyl < current_dive->cylinders.nr; cyl++) { - if (is_cylinder_used(current_dive, cyl)) - text << get_cylinder(current_dive, cyl)->type.description << " " << gasname(get_cylinder(current_dive, cyl)->gasmix) << "\n"; + for (auto [idx, cyl]: enumerated_range(current_dive->cylinders)) { + if (is_cylinder_used(current_dive, idx)) + text << QString::fromStdString(cyl.type.description) << " " << gasname(cyl.gasmix) << "\n"; } } if (what->weights) { diff --git a/desktop-widgets/tab-widgets/TabDiveInformation.cpp b/desktop-widgets/tab-widgets/TabDiveInformation.cpp index 73394a4aa..f08594fe0 100644 --- a/desktop-widgets/tab-widgets/TabDiveInformation.cpp +++ b/desktop-widgets/tab-widgets/TabDiveInformation.cpp @@ -126,14 +126,14 @@ void TabDiveInformation::updateProfile() std::vector gases = get_gas_used(currentDive); QString volumes; - std::vector mean(currentDive->cylinders.nr), duration(currentDive->cylinders.nr); + std::vector mean(currentDive->cylinders.size()), duration(currentDive->cylinders.size()); struct divecomputer *currentdc = parent.getCurrentDC(); - if (currentdc && currentDive->cylinders.nr >= 0) + if (currentdc && !currentDive->cylinders.empty()) per_cylinder_mean_depth(currentDive, currentdc, mean.data(), duration.data()); volume_t sac; QString gaslist, SACs, separator; - for (int i = 0; i < currentDive->cylinders.nr; i++) { + for (size_t i = 0; i < currentDive->cylinders.size(); i++) { if (!is_cylinder_used(currentDive, i)) continue; gaslist.append(separator); volumes.append(separator); SACs.append(separator); @@ -154,7 +154,7 @@ void TabDiveInformation::updateProfile() ui->diveTimeText->setText(get_dive_duration_string(currentDive->duration.seconds, tr("h"), tr("min"), tr("sec"), " ", currentDive->dcs[0].divemode == FREEDIVE)); - ui->sacText->setText(currentDive->cylinders.nr > 0 && mean[0] && currentDive->dcs[0].divemode != CCR ? std::move(SACs) : QString()); + ui->sacText->setText(!currentDive->cylinders.empty() && mean[0] && currentDive->dcs[0].divemode != CCR ? std::move(SACs) : QString()); if (currentDive->surface_pressure.mbar == 0) { ui->atmPressVal->clear(); // If no atm pressure for dive then clear text box diff --git a/desktop-widgets/templatelayout.cpp b/desktop-widgets/templatelayout.cpp index fb58f0629..47ebfa8e2 100644 --- a/desktop-widgets/templatelayout.cpp +++ b/desktop-widgets/templatelayout.cpp @@ -303,9 +303,9 @@ static int findEnd(const QList &tokenList, int from, int to, token_t star static std::vector cylinderList(const dive *d) { std::vector res; - res.reserve(d->cylinders.nr); - for (int i = 0; i < d->cylinders.nr; ++i) - res.push_back(&d->cylinders.cylinders[i]); + res.reserve(d->cylinders.size()); + for (auto &cyl: d->cylinders) + res.push_back(&cyl); return res; } @@ -481,7 +481,7 @@ QVariant TemplateLayout::getValue(QString list, QString property, const State &s return QVariant(); const cylinder_t *cylinder = *state.currentCylinderObject; if (property == "description") { - return cylinder->type.description; + return QString::fromStdString(cylinder->type.description); } else if (property == "size") { return get_volume_string(cylinder->type.size, true); } else if (property == "workingPressure") { diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index 40c5417de..9cf600738 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -1295,7 +1295,7 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt break; } } - get_or_create_cylinder(d, j)->type.description = copy_qstring(usedCylinder[k]); + get_or_create_cylinder(d, j)->type.description = usedCylinder[k].toStdString(); get_cylinder(d, j)->type.size.mliter = size; get_cylinder(d, j)->type.workingpressure.mbar = wp; k++; diff --git a/profile-widget/diveprofileitem.cpp b/profile-widget/diveprofileitem.cpp index 4b75bda82..a4573c8b1 100644 --- a/profile-widget/diveprofileitem.cpp +++ b/profile-widget/diveprofileitem.cpp @@ -602,7 +602,10 @@ void DiveGasPressureItem::replot(const dive *d, int fromIn, int toIn, bool in_pl bool showDescriptions = false; for (int cyl = 0; cyl < pInfo.nr_cylinders; cyl++) { - showDescriptions = showDescriptions || same_gasmix_cylinder(get_cylinder(d, cyl), cyl, d, true) != -1; + const cylinder_t *c = get_cylinder(d, cyl); + if (!c) + continue; + showDescriptions = showDescriptions || (c && same_gasmix_cylinder(*c, cyl, d, true) != -1); if (act_segments[cyl].polygon.empty()) continue; act_segments[cyl].cyl = cyl; @@ -655,7 +658,7 @@ void DiveGasPressureItem::plotGasValue(double mbar, double sec, const cylinder_t QString gas = get_gas_string(cylinder->gasmix); QString label; if (showDescription) - label = QStringLiteral("(%1) %2").arg(cylinder->type.description, gas); + label = QStringLiteral("(%1) %2").arg(QString::fromStdString(cylinder->type.description), gas); else label = gas; auto text = std::make_unique(dpr, 1.0, align, this); diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp index 0ff940d84..ce235a27b 100644 --- a/profile-widget/profilewidget2.cpp +++ b/profile-widget/profilewidget2.cpp @@ -502,13 +502,11 @@ struct int ProfileWidget2::getEntryFromPos(QPointF pos) #ifndef SUBSURFACE_MOBILE /// Prints cylinder information for display. /// eg : "Cyl 1 (AL80 EAN32)" -static QString printCylinderDescription(int i, const cylinder_t *cylinder) +static QString printCylinderDescription(int i, const cylinder_t &cylinder) { QString label = gettextFromC::tr("Cyl") + QString(" %1").arg(i+1); - if( cylinder != NULL ) { - QString mix = get_gas_string(cylinder->gasmix); - label += QString(" (%2 %3)").arg(cylinder->type.description).arg(mix); - } + QString mix = get_gas_string(cylinder.gasmix); + label += QString(" (%2 %3)").arg(QString::fromStdString(cylinder.type.description)).arg(mix); return label; } @@ -562,18 +560,16 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) if (d && item && item->ev.is_gaschange()) { int eventTime = item->ev.time.seconds; QMenu *gasChange = m.addMenu(tr("Edit Gas Change")); - for (int i = 0; i < d->cylinders.nr; i++) { - const cylinder_t *cylinder = get_cylinder(d, i); - QString label = printCylinderDescription(i, cylinder); - gasChange->addAction(label, [this, i, eventTime] { addGasSwitch(i, eventTime); }); + for (auto [i, cyl]: enumerated_range(d->cylinders)) { + QString label = printCylinderDescription(i, cyl); + gasChange->addAction(label, [this, idx = i, eventTime] { addGasSwitch(idx, eventTime); }); } - } else if (d && d->cylinders.nr > 1) { + } else if (d && d->cylinders.size() > 1) { // if we have more than one gas, offer to switch to another one QMenu *gasChange = m.addMenu(tr("Add gas change")); - for (int i = 0; i < d->cylinders.nr; i++) { - const cylinder_t *cylinder = get_cylinder(d, i); - QString label = printCylinderDescription(i, cylinder); - gasChange->addAction(label, [this, i, seconds] { addGasSwitch(i, seconds); }); + for (auto [i, cyl]: enumerated_range(d->cylinders)) { + QString label = printCylinderDescription(i, cyl); + gasChange->addAction(label, [this, idx = i, seconds] { addGasSwitch(idx, seconds); }); } } m.addAction(tr("Add setpoint change"), [this, seconds]() { ProfileWidget2::addSetpointChange(seconds); }); @@ -763,7 +759,7 @@ void ProfileWidget2::splitDive(int seconds) void ProfileWidget2::addGasSwitch(int tank, int seconds) { - if (!d || tank < 0 || tank >= d->cylinders.nr) + if (!d || tank < 0 || static_cast(tank) >= d->cylinders.size()) return; Command::addGasSwitch(mutable_dive(), dc, seconds, tank); @@ -923,7 +919,7 @@ void ProfileWidget2::repositionDiveHandlers() QLineF line(p1, p2); QPointF pos = line.pointAt(0.5); gases[i]->setPos(pos); - if (datapoint.cylinderid >= 0 && datapoint.cylinderid < d->cylinders.nr) + if (datapoint.cylinderid >= 0 && datapoint.cylinderid < static_cast(d->cylinders.size())) gases[i]->setText(get_gas_string(get_cylinder(d, datapoint.cylinderid)->gasmix)); else gases[i]->setText(QString()); diff --git a/profile-widget/tankitem.cpp b/profile-widget/tankitem.cpp index 5df474e83..e92a5b0d1 100644 --- a/profile-widget/tankitem.cpp +++ b/profile-widget/tankitem.cpp @@ -76,7 +76,7 @@ void TankItem::setData(const struct dive *d, const struct divecomputer *dc, int return; // Bail if there are no cylinders - if (d->cylinders.nr <= 0) + if (d->cylinders.empty()) return; // start with the first gasmix and at the start of the plotted range diff --git a/qt-models/cylindermodel.cpp b/qt-models/cylindermodel.cpp index 203d48ae7..4e87feef0 100644 --- a/qt-models/cylindermodel.cpp +++ b/qt-models/cylindermodel.cpp @@ -6,6 +6,7 @@ #include "core/color.h" #include "qt-models/diveplannermodel.h" #include "core/gettextfromc.h" +#include "core/range.h" #include "core/sample.h" #include "core/selection.h" #include "core/subsurface-qt/divelistnotifier.h" @@ -140,7 +141,7 @@ int CylindersModel::calcNumRows() const if (!d) return 0; if (inPlanner || prefs.include_unused_tanks) - return d->cylinders.nr; + return static_cast(d->cylinders.size()); return first_hidden_cylinder(d); } @@ -192,7 +193,7 @@ QVariant CylindersModel::data(const QModelIndex &index, int role) const case Qt::EditRole: switch (index.column()) { case TYPE: - return QString(cyl->type.description); + return QString::fromStdString(cyl->type.description); case SIZE: if (cyl->type.size.mliter) return get_cylinder_string(cyl); @@ -326,10 +327,9 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in switch (index.column()) { case TYPE: { - QString type = value.toString(); - if (!same_string(qPrintable(type), tempCyl.type.description)) { - free((void *)tempCyl.type.description); - tempCyl.type.description = strdup(qPrintable(type)); + std::string type = value.toString().toStdString(); + if (type != tempCyl.type.description) { + tempCyl.type.description = type; dataChanged(index, index); } return true; @@ -361,8 +361,6 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in QString vString = value.toString(); bool changed = vString != data(index, role).toString(); - std::string newType; // If we allocate a new type string, this makes sure that it is freed at the end of the function - // First, we make a shallow copy of the old cylinder. Then we modify the fields inside that copy. // At the end, we either place an EditCylinder undo command (EquipmentTab) or copy the cylinder back (planner). // Yes, this is not ideal, but the pragmatic thing to do for now. @@ -374,8 +372,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in Command::EditCylinderType type = Command::EditCylinderType::TYPE; switch (index.column()) { case TYPE: - newType = qPrintable(vString); - cyl.type.description = newType.c_str(); + cyl.type.description = vString.toStdString(); type = Command::EditCylinderType::TYPE; break; case SIZE: @@ -473,10 +470,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in if (inPlanner) { // In the planner - simply overwrite the cylinder in the dive with the modified cylinder. - // We have only made a shallow copy, therefore copy the new cylinder first. - cylinder_t copy = clone_cylinder(cyl); - std::swap(copy, *get_cylinder(d, row)); - free_cylinder(copy); + *get_cylinder(d, row) = cyl; dataChanged(index, index); } else { // On the EquipmentTab - place an editCylinder command. @@ -496,10 +490,10 @@ void CylindersModel::add() { if (!d) return; - int row = d->cylinders.nr; + int row = static_cast(d->cylinders.size()); cylinder_t cyl = create_new_manual_cylinder(d); beginInsertRows(QModelIndex(), row, row); - add_cylinder(&d->cylinders, row, cyl); + add_cylinder(&d->cylinders, row, std::move(cyl)); ++numRows; endInsertRows(); emit dataChanged(createIndex(row, 0), createIndex(row, COLUMNS - 1)); @@ -552,7 +546,7 @@ void CylindersModel::remove(QModelIndex index) --numRows; endRemoveRows(); - std::vector mapping = get_cylinder_map_for_remove(d->cylinders.nr + 1, index.row()); + std::vector mapping = get_cylinder_map_for_remove(static_cast(d->cylinders.size() + 1), index.row()); cylinder_renumber(d, mapping.data()); DivePlannerPointsModel::instance()->cylinderRenumber(mapping.data()); } @@ -612,21 +606,18 @@ void CylindersModel::updateNumRows() // Only invoked from planner. void CylindersModel::moveAtFirst(int cylid) { - if (!d || cylid <= 0 || cylid >= d->cylinders.nr) + if (!d || cylid <= 0 || cylid >= static_cast(d->cylinders.size())) return; cylinder_t temp_cyl; beginMoveRows(QModelIndex(), cylid, cylid, QModelIndex(), 0); - memmove(&temp_cyl, get_cylinder(d, cylid), sizeof(temp_cyl)); - for (int i = cylid - 1; i >= 0; i--) - memmove(get_cylinder(d, i + 1), get_cylinder(d, i), sizeof(temp_cyl)); - memmove(get_cylinder(d, 0), &temp_cyl, sizeof(temp_cyl)); + move_in_range(d->cylinders, cylid, cylid + 1, 0); // Create a mapping of cylinder indices: // 1) Fill mapping[0]..mapping[cyl] with 0..index // 2) Set mapping[cyl] to 0 // 3) Fill mapping[cyl+1]..mapping[end] with cyl.. - std::vector mapping(d->cylinders.nr); + std::vector mapping(d->cylinders.size()); std::iota(mapping.begin(), mapping.begin() + cylid, 1); mapping[cylid] = 0; std::iota(mapping.begin() + (cylid + 1), mapping.end(), cylid); @@ -644,12 +635,11 @@ void CylindersModel::updateDecoDepths(pressure_t olddecopo2) pressure_t decopo2; decopo2.mbar = prefs.decopo2; - for (int i = 0; i < d->cylinders.nr; i++) { - cylinder_t *cyl = get_cylinder(d, i); + for (auto &cyl: d->cylinders) { /* If the gas's deco MOD matches the old pO2, it will have been automatically calculated and should be updated. * If they don't match, we should leave the user entered depth as it is */ - if (cyl->depth.mm == gas_mod(cyl->gasmix, olddecopo2, d, M_OR_FT(3, 10)).mm) { - cyl->depth = gas_mod(cyl->gasmix, decopo2, d, M_OR_FT(3, 10)); + if (cyl.depth.mm == gas_mod(cyl.gasmix, olddecopo2, d, M_OR_FT(3, 10)).mm) { + cyl.depth = gas_mod(cyl.gasmix, decopo2, d, M_OR_FT(3, 10)); } } emit dataChanged(createIndex(0, 0), createIndex(numRows - 1, COLUMNS - 1)); @@ -671,23 +661,22 @@ bool CylindersModel::updateBestMixes() // Check if any of the cylinders are best mixes, update if needed bool gasUpdated = false; - for (int i = 0; i < d->cylinders.nr; i++) { - cylinder_t *cyl = get_cylinder(d, i); - if (cyl->bestmix_o2) { - cyl->gasmix.o2 = best_o2(d->maxdepth, d, inPlanner); + for (auto &cyl: d->cylinders) { + if (cyl.bestmix_o2) { + cyl.gasmix.o2 = best_o2(d->maxdepth, d, inPlanner); // fO2 + fHe must not be greater than 1 - if (get_o2(cyl->gasmix) + get_he(cyl->gasmix) > 1000) - cyl->gasmix.he.permille = 1000 - get_o2(cyl->gasmix); + if (get_o2(cyl.gasmix) + get_he(cyl.gasmix) > 1000) + cyl.gasmix.he.permille = 1000 - get_o2(cyl.gasmix); pressure_t modpO2; modpO2.mbar = prefs.decopo2; - cyl->depth = gas_mod(cyl->gasmix, modpO2, d, M_OR_FT(3, 10)); + cyl.depth = gas_mod(cyl.gasmix, modpO2, d, M_OR_FT(3, 10)); gasUpdated = true; } - if (cyl->bestmix_he) { - cyl->gasmix.he = best_he(d->maxdepth, d, prefs.o2narcotic, cyl->gasmix.o2); + if (cyl.bestmix_he) { + cyl.gasmix.he = best_he(d->maxdepth, d, prefs.o2narcotic, cyl.gasmix.o2); // fO2 + fHe must not be greater than 1 - if (get_o2(cyl->gasmix) + get_he(cyl->gasmix) > 1000) - cyl->gasmix.o2.permille = 1000 - get_he(cyl->gasmix); + if (get_o2(cyl.gasmix) + get_he(cyl.gasmix) > 1000) + cyl.gasmix.o2.permille = 1000 - get_he(cyl.gasmix); gasUpdated = true; } } @@ -727,7 +716,7 @@ void CylindersModel::initTempCyl(int row) return; tempRow = row; - tempCyl = clone_cylinder(*cyl); + tempCyl = *cyl; dataChanged(index(row, TYPE), index(row, USE)); } @@ -738,7 +727,7 @@ void CylindersModel::clearTempCyl() return; int oldRow = tempRow; tempRow = -1; - free_cylinder(tempCyl); + tempCyl = cylinder_t(); dataChanged(index(oldRow, TYPE), index(oldRow, USE)); } @@ -752,7 +741,7 @@ void CylindersModel::commitTempCyl(int row) if (!cyl) return; // Only submit a command if the type changed - if (!same_string(cyl->type.description, tempCyl.type.description) || gettextFromC::tr(cyl->type.description) != QString(tempCyl.type.description)) { + if (cyl->type.description != tempCyl.type.description || gettextFromC::tr(cyl->type.description.c_str()) != QString::fromStdString(tempCyl.type.description)) { if (inPlanner) { std::swap(*cyl, tempCyl); } else { @@ -760,6 +749,6 @@ void CylindersModel::commitTempCyl(int row) emit divesEdited(count); } } - free_cylinder(tempCyl); + tempCyl = cylinder_t(); tempRow = -1; } diff --git a/qt-models/diveplannermodel.cpp b/qt-models/diveplannermodel.cpp index 234b09fc3..69996cc4f 100644 --- a/qt-models/diveplannermodel.cpp +++ b/qt-models/diveplannermodel.cpp @@ -195,13 +195,13 @@ void DivePlannerPointsModel::loadFromDive(dive *dIn, int dcNrIn) // setup the cylinder widget accordingly void DivePlannerPointsModel::setupCylinders() { - clear_cylinder_table(&d->cylinders); + d->cylinders.clear(); if (mode == PLAN && current_dive) { // take the displayed cylinders from the selected dive as starting point copy_used_cylinders(current_dive, d, !prefs.include_unused_tanks); reset_cylinders(d, true); - if (d->cylinders.nr > 0) { + if (!d->cylinders.empty()) { cylinders.updateDive(d, dcNr); return; // We have at least one cylinder } @@ -281,13 +281,14 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const case GAS: /* Check if we have the same gasmix two or more times * If yes return more verbose string */ - int same_gas = same_gasmix_cylinder(get_cylinder(d, p.cylinderid), p.cylinderid, d, true); + const cylinder_t &cyl = d->cylinders[p.cylinderid]; + int same_gas = same_gasmix_cylinder(cyl, p.cylinderid, d, true); if (same_gas == -1) - return get_gas_string(get_cylinder(d, p.cylinderid)->gasmix); + return get_gas_string(cyl.gasmix); else - return get_gas_string(get_cylinder(d, p.cylinderid)->gasmix) + + return get_gas_string(cyl.gasmix) + QString(" (%1 %2 ").arg(tr("cyl.")).arg(p.cylinderid + 1) + - get_cylinder(d, p.cylinderid)->type.description + ")"; + QString::fromStdString(cyl.type.description) + ")"; } } else if (role == Qt::DecorationRole) { switch (index.column()) { @@ -602,6 +603,7 @@ void DivePlannerPointsModel::setAscratestopsDisplay(int rate) qPrefDivePlanner::set_ascratestops(lrint(rate * unit_factor())); emitDataChanged(); } + int DivePlannerPointsModel::ascratestopsDisplay() const { return lrint((float)prefs.ascratestops / unit_factor()); @@ -1028,11 +1030,9 @@ void DivePlannerPointsModel::createTemporaryPlan() // Get the user-input and calculate the dive info free_dps(&diveplan); - for (int i = 0; i < d->cylinders.nr; i++) { - cylinder_t *cyl = get_cylinder(d, i); - if (cyl->depth.mm && cyl->cylinder_use == OC_GAS) { - plan_add_segment(&diveplan, 0, cyl->depth.mm, i, 0, false, OC); - } + for (auto [i, cyl]: enumerated_range(d->cylinders)) { + if (cyl.depth.mm && cyl.cylinder_use == OC_GAS) + plan_add_segment(&diveplan, 0, cyl.depth.mm, i, 0, false, OC); } int lastIndex = -1; diff --git a/qt-models/divesummarymodel.cpp b/qt-models/divesummarymodel.cpp index a3345a396..43cb8d6ce 100644 --- a/qt-models/divesummarymodel.cpp +++ b/qt-models/divesummarymodel.cpp @@ -151,12 +151,9 @@ static void calculateDive(struct dive *dive, Stats &stats) } // EAN dive ? - for (int j = 0; j < dive->cylinders.nr; ++j) { - if (get_cylinder(dive, j)->gasmix.o2.permille > 210) { - stats.divesEAN++; - break; - } - } + if (std::any_of(dive->cylinders.begin(), dive->cylinders.end(), [] (auto &cyl) + { return cyl.gasmix.o2.permille > 210; })) + stats.divesEAN++; } // Returns a (first_dive, last_dive) pair diff --git a/qt-models/divetripmodel.cpp b/qt-models/divetripmodel.cpp index d2d858ca1..80b298458 100644 --- a/qt-models/divetripmodel.cpp +++ b/qt-models/divetripmodel.cpp @@ -336,7 +336,7 @@ QVariant DiveTripModelBase::diveData(const struct dive *d, int column, int role) case SUIT: return QString(d->suit); case CYLINDER: - return d->cylinders.nr > 0 ? QString(get_cylinder(d, 0)->type.description) : QString(); + return !d->cylinders.empty() ? QString::fromStdString(d->cylinders[0].type.description) : QString(); case SAC: return displaySac(d, prefs.units.show_units_table); case OTU: @@ -1721,6 +1721,11 @@ static int strCmp(const char *s1, const char *s2) return QString::localeAwareCompare(QString(s1), QString(s2)); // TODO: avoid copy } +static int strCmp(const std::string &s1, const std::string &s2) +{ + return QString::localeAwareCompare(QString::fromStdString(s1), QString::fromStdString(s2)); // TODO: avoid copy +} + bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) const { // We assume that i1.column() == i2.column(). @@ -1750,9 +1755,9 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c case SUIT: return lessThanHelper(strCmp(d1->suit, d2->suit), row_diff); case CYLINDER: - if (d1->cylinders.nr > 0 && d2->cylinders.nr > 0) - return lessThanHelper(strCmp(get_cylinder(d1, 0)->type.description, get_cylinder(d2, 0)->type.description), row_diff); - return d1->cylinders.nr - d2->cylinders.nr < 0; + if (!d1->cylinders.empty() && !d2->cylinders.empty()) + return lessThanHelper(strCmp(d1->cylinders[0].type.description, d2->cylinders[0].type.description), row_diff); + return d1->cylinders.size() < d2->cylinders.size(); case GAS: return lessThanHelper(nitrox_sort_value(d1) - nitrox_sort_value(d2), row_diff); case SAC: @@ -1764,19 +1769,19 @@ bool DiveTripModelList::lessThan(const QModelIndex &i1, const QModelIndex &i2) c case TAGS: { std::string s1 = taglist_get_tagstring(d1->tag_list); std::string s2 = taglist_get_tagstring(d2->tag_list); - int diff = strCmp(s1.c_str(), s2.c_str()); + int diff = strCmp(s1, s2); return lessThanHelper(diff, row_diff); } case PHOTOS: return lessThanHelper(countPhotos(d1) - countPhotos(d2), row_diff); case COUNTRY: - return lessThanHelper(strCmp(get_dive_country(d1).c_str(), get_dive_country(d2).c_str()), row_diff); + return lessThanHelper(strCmp(get_dive_country(d1), get_dive_country(d2)), row_diff); case BUDDIES: return lessThanHelper(strCmp(d1->buddy, d2->buddy), row_diff); case DIVEGUIDE: return lessThanHelper(strCmp(d1->diveguide, d2->diveguide), row_diff); case LOCATION: - return lessThanHelper(strCmp(get_dive_location(d1).c_str(), get_dive_location(d2).c_str()), row_diff); + return lessThanHelper(strCmp(get_dive_location(d1), get_dive_location(d2)), row_diff); case NOTES: return lessThanHelper(strCmp(d1->notes, d2->notes), row_diff); case DIVEMODE: diff --git a/smtk-import/smartrak.cpp b/smtk-import/smartrak.cpp index 5aeafee25..391001573 100644 --- a/smtk-import/smartrak.cpp +++ b/smtk-import/smartrak.cpp @@ -449,7 +449,7 @@ static void smtk_build_tank_info(MdbHandle *mdb, cylinder_t *tank, char *idx) for (i = 1; i <= atoi(idx); i++) table.fetch_row(); - tank->type.description = copy_string(table.get_data(1)); + tank->type.description = table.get_data(1); tank->type.size.mliter = lrint(strtod(table.get_data(2), NULL) * 1000); tank->type.workingpressure.mbar = lrint(strtod(table.get_data(4), NULL) * 1000); } @@ -472,9 +472,9 @@ static bool is_same_cylinder(cylinder_t *cyl_a, cylinder_t *cyl_b) if (!(abs(cyl_a->end.mbar - cyl_b->end.mbar) <= 100)) return false; // different names (none of them null) - if (!same_string(cyl_a->type.description, "---") && - !same_string(cyl_b->type.description, "---") && - !same_string(cyl_a->type.description, cyl_b->type.description)) + if (cyl_a->type.description != "---" && + cyl_b->type.description != "---" && + cyl_a->type.description != cyl_b->type.description) return false; // Cylinders are most probably the same return true; @@ -495,9 +495,8 @@ static void merge_cylinder_type(cylinder_type_t *src, cylinder_type_t *dst) dst->size.mliter = src->size.mliter; if (!dst->workingpressure.mbar) dst->workingpressure.mbar = src->workingpressure.mbar; - if (!dst->description || same_string(dst->description, "---")) { - dst->description = src->description; - src->description = NULL; + if (dst->description.empty() || dst->description == "---") { + dst->description = std::move(src->description); } } @@ -532,7 +531,7 @@ static void smtk_clean_cylinders(struct dive *d) cyl = base + tanks - 1; while (cyl != base) { - if (same_string(cyl->type.description, "---") && cyl->start.mbar == 0 && cyl->end.mbar == 0) + if (cyl->type.description == "---" && cyl->start.mbar == 0 && cyl->end.mbar == 0) remove_cylinder(d, i); else if (is_same_cylinder(cyl, cyl - 1)) { diff --git a/stats/statsvariables.cpp b/stats/statsvariables.cpp index c7a770838..33caf3f44 100644 --- a/stats/statsvariables.cpp +++ b/stats/statsvariables.cpp @@ -1553,9 +1553,9 @@ struct GasTypeBinner : public MultiBinner { } std::vector to_bin_values(const dive *d) const { std::vector res; - res.reserve(d->cylinders.nr); - for (int i = 0; i < d->cylinders.nr; ++i) { - struct gasmix mix = d->cylinders.cylinders[i].gasmix; + res.reserve(d->cylinders.size()); + for (auto &cyl: d->cylinders) { + struct gasmix mix = cyl.gasmix; if (gasmix_is_invalid(mix)) continue; // Add dive to each bin only once. @@ -1591,9 +1591,9 @@ struct GasTypeGeneralBinner : public MultiBinner { } std::vector to_bin_values(const dive *d) const { std::vector res; - res.reserve(d->cylinders.nr); - for (int i = 0; i < d->cylinders.nr; ++i) { - struct gasmix mix = d->cylinders.cylinders[i].gasmix; + res.reserve(d->cylinders.size()); + for (auto &cyl: d->cylinders) { + struct gasmix mix = cyl.gasmix; if (gasmix_is_invalid(mix)) continue; res.push_back(gasmix_to_type(mix)); @@ -1619,9 +1619,9 @@ struct GasTypeVariable : public StatsVariableTemplate mixes; // List multiple cylinders only once - mixes.reserve(d->cylinders.nr); - for (int i = 0; i < d->cylinders.nr; ++i) { - struct gasmix mix = d->cylinders.cylinders[i].gasmix; + mixes.reserve(d->cylinders.size()); + for (auto &cyl: d->cylinders) { + struct gasmix mix = cyl.gasmix; if (gasmix_is_invalid(mix)) continue; if (std::find_if(mixes.begin(), mixes.end(), @@ -1648,7 +1648,7 @@ struct GasTypeVariable : public StatsVariableTemplatecylinders.nr <= 0) + if (d->cylinders.empty()) return invalid_value(); // If sorting be He, the second sort criterion is O2 descending, because // we are interested in the "bottom gas": highest He and lowest O2. @@ -1657,7 +1657,7 @@ static int get_gas_content(const struct dive *d, bool he, bool max_he) std::make_tuple(get_he(c2.gasmix), -get_o2(c2.gasmix)); } : [] (const cylinder_t &c1, const cylinder_t &c2) { return get_o2(c1.gasmix) < get_o2(c2.gasmix); }; - auto it = std::max_element(d->cylinders.cylinders, d->cylinders.cylinders + d->cylinders.nr, comp); + auto it = std::max_element(d->cylinders.begin(), d->cylinders.end(), comp); return he ? get_he(it->gasmix) : get_o2(it->gasmix); } @@ -1798,9 +1798,9 @@ struct WeightsystemVariable : public StatsVariableTemplate cylinder_types(const dive *d) { std::vector res; - res.reserve(d->cylinders.nr); - for (int i = 0; i < d->cylinders.nr; ++i) - add_to_vector_unique(res, QString(d->cylinders.cylinders[i].type.description).trimmed()); + res.reserve(d->cylinders.size()); + for (auto &cyl: d->cylinders) + add_to_vector_unique(res, QString::fromStdString(cyl.type.description).trimmed()); return res; }