From 5f36c8ccdedc1ca34f06bb51995ae91b250c8877 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Fri, 3 May 2024 23:18:45 +0200 Subject: [PATCH] core: use C++ structures for tanksystem info Signed-off-by: Berthold Stoeger --- commands/command_edit.cpp | 5 +- core/datatrak.cpp | 14 ++-- core/dive.cpp | 2 +- core/divelist.cpp | 2 +- core/equipment.cpp | 82 ++++++++----------- core/equipment.h | 32 +++----- core/string-format.cpp | 14 ++-- desktop-widgets/modeldelegates.cpp | 2 +- .../preferences/preferences_equipment.cpp | 11 +-- mobile-widgets/qmlmanager.cpp | 5 +- qt-models/tankinfomodel.cpp | 8 +- subsurface-desktop-main.cpp | 3 +- subsurface-mobile-main.cpp | 3 +- 13 files changed, 77 insertions(+), 106 deletions(-) diff --git a/commands/command_edit.cpp b/commands/command_edit.cpp index c42fb76d7..b76329303 100644 --- a/commands/command_edit.cpp +++ b/commands/command_edit.cpp @@ -1319,8 +1319,9 @@ EditCylinder::EditCylinder(int index, cylinder_t cylIn, EditCylinderType typeIn, void EditCylinder::redo() { for (size_t i = 0; i < dives.size(); ++i) { - set_tank_info_size(&tank_info_table, cyl[i].type.description, cyl[i].type.size); - set_tank_info_workingpressure(&tank_info_table, cyl[i].type.description, cyl[i].type.workingpressure); + std::string name = cyl[i].type.description; + set_tank_info_size(tank_info_table, name, cyl[i].type.size); + set_tank_info_workingpressure(tank_info_table, name, cyl[i].type.workingpressure); std::swap(*get_cylinder(dives[i], indexes[i]), cyl[i]); update_cylinder_related_info(dives[i]); emit diveListNotifier.cylinderEdited(dives[i], indexes[i]); diff --git a/core/datatrak.cpp b/core/datatrak.cpp index 30bd8a5aa..f77fa3c57 100644 --- a/core/datatrak.cpp +++ b/core/datatrak.cpp @@ -131,14 +131,11 @@ static int dtrak_prepare_data(int model, device_data_t &dev_data) * Just get the first in the user's list for given size. * Reaching the end of the list means there is no tank of this size. */ -static const char *cyl_type_by_size(int size) +static std::string cyl_type_by_size(int size) { - for (int i = 0; i < tank_info_table.nr; ++i) { - const struct tank_info *ti = &tank_info_table.infos[i]; - if (ti->ml == size) - return ti->name; - } - return ""; + auto it = std::find_if(tank_info_table.begin(), tank_info_table.end(), + [size] (const tank_info &info) { return info.ml == size; }); + return it != tank_info_table.end() ? it->name : std::string(); } /* @@ -338,8 +335,9 @@ static char *dt_dive_parser(unsigned char *runner, struct dive *dt_dive, struct read_bytes(2); if (tmp_2bytes != 0x7FFF) { cylinder_t cyl = empty_cylinder; + std::string desc = cyl_type_by_size(tmp_2bytes * 10); cyl.type.size.mliter = tmp_2bytes * 10; - cyl.type.description = cyl_type_by_size(tmp_2bytes * 10); + cyl.type.description = desc.c_str(); cyl.start.mbar = 200000; cyl.gasmix.he.permille = 0; cyl.gasmix.o2.permille = 210; diff --git a/core/dive.cpp b/core/dive.cpp index 45ab40156..05dd1e4f1 100644 --- a/core/dive.cpp +++ b/core/dive.cpp @@ -1290,7 +1290,7 @@ extern "C" struct dive *fixup_dive(struct dive *dive) fixup_airtemp(dive); for (i = 0; i < dive->cylinders.nr; i++) { cylinder_t *cyl = get_cylinder(dive, i); - add_cylinder_description(&cyl->type); + 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)) diff --git a/core/divelist.cpp b/core/divelist.cpp index e841242e8..a7a98fb98 100644 --- a/core/divelist.cpp +++ b/core/divelist.cpp @@ -1311,7 +1311,7 @@ extern "C" void clear_dive_file_data() min_datafile_version = 0; clear_git_id(); - reset_tank_info_table(&tank_info_table); + reset_tank_info_table(tank_info_table); /* Inform frontend of reset data. This should reset all the models. */ emit_reset_signal(); diff --git a/core/equipment.cpp b/core/equipment.cpp index 675b077b0..fd661591b 100644 --- a/core/equipment.cpp +++ b/core/equipment.cpp @@ -52,11 +52,6 @@ extern "C" void copy_cylinders(const struct cylinder_table *s, struct cylinder_t add_cloned_cylinder(d, s->cylinders[i]); } -static void free_tank_info(struct tank_info info) -{ - free((void *)info.name); -} - /* weightsystem table functions */ //static MAKE_GET_IDX(weightsystem_table, weightsystem_t, weightsystems) static MAKE_GROW_TABLE(weightsystem_table, weightsystem_t, weightsystems) @@ -77,12 +72,6 @@ static MAKE_REMOVE_FROM(cylinder_table, cylinders) //MAKE_REMOVE(cylinder_table, cylinder_t, cylinder) MAKE_CLEAR_TABLE(cylinder_table, cylinders, cylinder) -/* tank_info table functions */ -static MAKE_GROW_TABLE(tank_info_table, tank_info_t, infos) -static MAKE_ADD_TO(tank_info_table, tank_info_t, infos) -//static MAKE_REMOVE_FROM(tank_info_table, infos) -MAKE_CLEAR_TABLE(tank_info_table, infos, tank_info) - 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") }; @@ -97,28 +86,24 @@ extern "C" enum cylinderuse cylinderuse_from_text(const char *text) } /* Add a metric or an imperial tank info structure. Copies the passed-in string. */ -extern "C" void add_tank_info_metric(struct tank_info_table *table, const char *name, int ml, int bar) +static void add_tank_info_metric(std::vector &table, const std::string &name, int ml, int bar) { - struct tank_info info = { strdup(name), .ml = ml, .bar = bar }; - add_to_tank_info_table(table, table->nr, info); + tank_info_table.push_back(tank_info{ name, .ml = ml, .bar = bar }); } -extern "C" void add_tank_info_imperial(struct tank_info_table *table, const char *name, int cuft, int psi) +static void add_tank_info_imperial(std::vector &table, const std::string &name, int cuft, int psi) { - struct tank_info info = { strdup(name), .cuft = cuft, .psi = psi }; - add_to_tank_info_table(table, table->nr, info); + tank_info_table.push_back(tank_info{ name, .cuft = cuft, .psi = psi }); } -extern "C" struct tank_info *get_tank_info(struct tank_info_table *table, const char *name) +struct tank_info *get_tank_info(std::vector &table, const std::string &name) { - for (int i = 0; i < table->nr; ++i) { - if (same_string(table->infos[i].name, name)) - return &table->infos[i]; - } - return NULL; + auto it = std::find_if(table.begin(), table.end(), [&name](const tank_info &info) + { return info.name == name; }); + return it != table.end() ? &*it : nullptr; } -extern "C" void set_tank_info_size(struct tank_info_table *table, const char *name, volume_t size) +void set_tank_info_size(std::vector &table, const std::string &name, volume_t size) { struct tank_info *info = get_tank_info(table, name); if (info) { @@ -133,7 +118,7 @@ extern "C" void set_tank_info_size(struct tank_info_table *table, const char *na } } -extern "C" void set_tank_info_workingpressure(struct tank_info_table *table, const char *name, pressure_t working_pressure) +void set_tank_info_workingpressure(std::vector &table, const std::string &name, pressure_t working_pressure) { struct tank_info *info = get_tank_info(table, name); if (info) { @@ -148,18 +133,16 @@ extern "C" void set_tank_info_workingpressure(struct tank_info_table *table, con } } -/* placeholders for a few functions that we need to redesign for the Qt UI */ -extern "C" void add_cylinder_description(const cylinder_type_t *type) +void add_cylinder_description(const cylinder_type_t &type) { - const char *desc = type->description; - if (empty_string(desc)) + std::string desc = type.description ? type.description : std::string(); + if (desc.empty()) return; - for (int i = 0; i < tank_info_table.nr; i++) { - if (strcmp(tank_info_table.infos[i].name, desc) == 0) - return; - } - add_tank_info_metric(&tank_info_table, desc, type->size.mliter, - type->workingpressure.mbar / 1000); + if (std::any_of(tank_info_table.begin(), tank_info_table.end(), + [&type](const tank_info &info) { return info.name == type.description; })) + return; + add_tank_info_metric(tank_info_table, desc, type.size.mliter, + type.workingpressure.mbar / 1000); } void add_weightsystem_description(const weightsystem_t &weightsystem) @@ -282,7 +265,7 @@ extern "C" int find_best_gasmix_match(struct gasmix mix, const struct cylinder_t * we should pick up any other names from the dive * logs directly. */ -static void add_default_tank_infos(struct tank_info_table *table) +static void add_default_tank_infos(std::vector &table) { /* Size-only metric cylinders */ add_tank_info_metric(table, "10.0ℓ", 10000, 0); @@ -334,10 +317,10 @@ static void add_default_tank_infos(struct tank_info_table *table) add_tank_info_metric(table, "D20 232 bar", 40000, 232); } -struct tank_info_table tank_info_table; -extern "C" void reset_tank_info_table(struct tank_info_table *table) +std::vector tank_info_table; +void reset_tank_info_table(std::vector &table) { - clear_tank_info_table(table); + table.clear(); if (prefs.display_default_tank_infos) add_default_tank_infos(table); @@ -346,7 +329,7 @@ extern "C" void reset_tank_info_table(struct tank_info_table *table) 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); + add_cylinder_description(cyl->type); } } } @@ -471,17 +454,16 @@ extern "C" void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl) if (!cyl_name) return; - for (int i = 0; i < tank_info_table.nr; ++i) { - struct tank_info *ti = &tank_info_table.infos[i]; - if (strcmp(ti->name, cyl_name) == 0) { - cyl->type.description = strdup(ti->name); - if (ti->ml) { - cyl->type.size.mliter = ti->ml; - cyl->type.workingpressure.mbar = ti->bar * 1000; + for (auto &ti: tank_info_table) { + if (ti.name == cyl_name) { + cyl->type.description = strdup(ti.name.c_str()); + if (ti.ml) { + cyl->type.size.mliter = ti.ml; + cyl->type.workingpressure.mbar = ti.bar * 1000; } else { - cyl->type.workingpressure.mbar = psi_to_mbar(ti->psi); - if (ti->psi) - cyl->type.size.mliter = lrint(cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi))); + cyl->type.workingpressure.mbar = psi_to_mbar(ti.psi); + if (ti.psi) + cyl->type.size.mliter = lrint(cuft_to_l(ti.cuft) * 1000 / bar_to_atm(psi_to_bar(ti.psi))); } // MOD of air cyl->depth = gas_mod(cyl->gasmix, pO2, dive, 1); diff --git a/core/equipment.h b/core/equipment.h index 3c7d18312..c28e2a00d 100644 --- a/core/equipment.h +++ b/core/equipment.h @@ -81,7 +81,6 @@ 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_or_create_cylinder(struct dive *d, int idx); -extern void add_cylinder_description(const cylinder_type_t *); extern bool same_weightsystem(weightsystem_t w1, weightsystem_t w2); extern void remove_cylinder(struct dive *dive, int idx); extern void remove_weightsystem(struct dive *dive, int idx); @@ -108,25 +107,6 @@ extern void add_cylinder(struct cylinder_table *, int idx, cylinder_t cyl); void get_gas_string(struct gasmix gasmix, char *text, int len); const char *gasname(struct gasmix gasmix); -typedef struct tank_info { - const char *name; - int cuft, ml, psi, bar; -} tank_info_t; - -struct tank_info_table { - int nr, allocated; - struct tank_info *infos; -}; - -extern struct tank_info_table tank_info_table; -extern void reset_tank_info_table(struct tank_info_table *table); -extern void clear_tank_info_table(struct tank_info_table *table); -extern void add_tank_info_metric(struct tank_info_table *table, const char *name, int ml, int bar); -extern void add_tank_info_imperial(struct tank_info_table *table, const char *name, int cuft, int psi); -extern void set_tank_info_size(struct tank_info_table *table, const char *name, volume_t size); -extern void set_tank_info_workingpressure(struct tank_info_table *table, const char *name, pressure_t working_pressure); -extern struct tank_info *get_tank_info(struct tank_info_table *table, const char *name); - #ifdef __cplusplus } @@ -142,6 +122,18 @@ extern std::vector ws_info_table; extern weight_t get_weightsystem_weight(const std::string &name); // returns 0 if not found extern void add_weightsystem_description(const weightsystem_t &); +struct tank_info { + std::string name; + int cuft, ml, psi, bar; +}; + +extern std::vector tank_info_table; +extern struct tank_info *get_tank_info(std::vector &table, const std::string &name); +extern void set_tank_info_size(std::vector &table, const std::string &name, volume_t size); +extern void set_tank_info_workingpressure(std::vector &table, const std::string &name, pressure_t working_pressure); +extern void add_cylinder_description(const cylinder_type_t &); +extern void reset_tank_info_table(std::vector &table); + #endif #endif // EQUIPMENT_H diff --git a/core/string-format.cpp b/core/string-format.cpp index 4e10c38bf..1dd9dd3e4 100644 --- a/core/string-format.cpp +++ b/core/string-format.cpp @@ -116,21 +116,21 @@ QStringList formatFirstGas(const dive *d) // Add string to sorted QStringList, if it doesn't already exist and // it isn't the empty string. -static void addStringToSortedList(QStringList &l, const char *s) +static void addStringToSortedList(QStringList &l, const std::string &s) { - if (empty_string(s)) + if (s.empty()) return; // Do a binary search for the string. lower_bound() returns an iterator // to either the searched-for element or the next higher element if it // doesn't exist. - QString qs(s); + QString qs = QString::fromStdString(s); auto it = std::lower_bound(l.begin(), l.end(), qs); // TODO: use locale-aware sorting - if (it != l.end() && *it == s) + if (it != l.end() && *it == qs) return; // Add new string at sorted position - l.insert(it, s); + l.insert(it, qs); } QStringList formatFullCylinderList() @@ -143,8 +143,8 @@ QStringList formatFullCylinderList() addStringToSortedList(cylinders, get_cylinder(d, j)->type.description); } - for (int ti = 0; ti < tank_info_table.nr; ti++) - addStringToSortedList(cylinders, tank_info_table.infos[ti].name); + for (const auto &ti: tank_info_table) + addStringToSortedList(cylinders, ti.name); return cylinders; } diff --git a/desktop-widgets/modeldelegates.cpp b/desktop-widgets/modeldelegates.cpp index dbd229f8a..9d65865c9 100644 --- a/desktop-widgets/modeldelegates.cpp +++ b/desktop-widgets/modeldelegates.cpp @@ -220,7 +220,7 @@ void TankInfoDelegate::setModelData(QWidget *, QAbstractItemModel *model, const } int tankSize = 0; int tankPressure = 0; - tank_info *info = get_tank_info(&tank_info_table, qPrintable(cylinderName)); + tank_info *info = get_tank_info(tank_info_table, cylinderName.toStdString()); if (info) { // OMG, the units here are a mess. tankSize = info->ml != 0 ? info->ml : lrint(cuft_to_l(info->cuft) * 1000.0); diff --git a/desktop-widgets/preferences/preferences_equipment.cpp b/desktop-widgets/preferences/preferences_equipment.cpp index 1e8c1e1e8..957c2b143 100644 --- a/desktop-widgets/preferences/preferences_equipment.cpp +++ b/desktop-widgets/preferences/preferences_equipment.cpp @@ -26,11 +26,12 @@ void PreferencesEquipment::refreshSettings() ui->include_unused_tanks->setChecked(prefs.include_unused_tanks); ui->display_default_tank_infos->setChecked(prefs.display_default_tank_infos); ui->default_cylinder->clear(); - for (int i = 0; i < tank_info_table.nr; i++) { - const tank_info &ti = tank_info_table.infos[i]; - ui->default_cylinder->addItem(ti.name); - if (qPrefEquipment::default_cylinder() == ti.name) + int i = 0; + for (const tank_info &ti: tank_info_table) { + ui->default_cylinder->addItem(QString::fromStdString(ti.name)); + if (qPrefEquipment::default_cylinder() == QString::fromStdString(ti.name)) ui->default_cylinder->setCurrentIndex(i); + ++i; } } @@ -45,5 +46,5 @@ void PreferencesEquipment::syncSettings() // reset the tank_info_table. It is somewhat questionable // to do this here. Moreover, it is a bit crude, as this // will be called for *any* preferences change. - reset_tank_info_table(&tank_info_table); + reset_tank_info_table(tank_info_table); } diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index 1476b6b75..7d75a55c3 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -1283,9 +1283,8 @@ void QMLManager::commitChanges(QString diveId, QString number, QString date, QSt if (state != "add" && !is_cylinder_used(d, j)) continue; - for (int i = 0; i < tank_info_table.nr; i++) { - const tank_info &ti = tank_info_table.infos[i]; - if (ti.name == usedCylinder[k] ) { + for (const tank_info &ti: tank_info_table) { + if (ti.name == usedCylinder[k].toStdString()) { if (ti.ml > 0){ size = ti.ml; wp = ti.bar * 1000; diff --git a/qt-models/tankinfomodel.cpp b/qt-models/tankinfomodel.cpp index 6dca11cef..3288cbd16 100644 --- a/qt-models/tankinfomodel.cpp +++ b/qt-models/tankinfomodel.cpp @@ -7,12 +7,12 @@ QVariant TankInfoModel::data(const QModelIndex &index, int role) const { - if (index.row() < 0 || index.row() >= tank_info_table.nr) + if (index.row() < 0 || index.row() >= (int)tank_info_table.size()) return QVariant(); if (role == Qt::FontRole) return defaultModelFont(); if (role == Qt::DisplayRole || role == Qt::EditRole) { - const struct tank_info &info = tank_info_table.infos[index.row()]; + const struct tank_info &info = tank_info_table[index.row()]; int ml = info.ml; double bar = (info.psi) ? psi_to_bar(info.psi) : info.bar; @@ -25,7 +25,7 @@ QVariant TankInfoModel::data(const QModelIndex &index, int role) const case ML: return ml; case DESCRIPTION: - return info.name; + return QString::fromStdString(info.name); } } return QVariant(); @@ -33,7 +33,7 @@ QVariant TankInfoModel::data(const QModelIndex &index, int role) const int TankInfoModel::rowCount(const QModelIndex&) const { - return tank_info_table.nr; + return (int)tank_info_table.size(); } TankInfoModel::TankInfoModel(QObject *parent) : CleanerTableModel(parent) diff --git a/subsurface-desktop-main.cpp b/subsurface-desktop-main.cpp index d17ffb90c..924667c41 100644 --- a/subsurface-desktop-main.cpp +++ b/subsurface-desktop-main.cpp @@ -79,7 +79,7 @@ int main(int argc, char **argv) CheckCloudConnection ccc; ccc.pickServer(); fill_computer_list(); - reset_tank_info_table(&tank_info_table); + reset_tank_info_table(tank_info_table); parse_xml_init(); taglist_init_global(); init_ui(); @@ -114,7 +114,6 @@ int main(int argc, char **argv) qPref::sync(); free_prefs(); - clear_tank_info_table(&tank_info_table); return 0; } diff --git a/subsurface-mobile-main.cpp b/subsurface-mobile-main.cpp index 813d448cc..399db7159 100644 --- a/subsurface-mobile-main.cpp +++ b/subsurface-mobile-main.cpp @@ -61,7 +61,7 @@ int main(int argc, char **argv) CheckCloudConnection ccc; ccc.pickServer(); fill_computer_list(); - reset_tank_info_table(&tank_info_table); + reset_tank_info_table(tank_info_table); parse_xml_init(); taglist_init_global(); @@ -101,7 +101,6 @@ int main(int argc, char **argv) qPref::sync(); free_prefs(); - clear_tank_info_table(&tank_info_table); return 0; }