core: convert weightsystem_t and weightsystem_table to C++

As for cylinders, this had to be done simultaneously,

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-05-29 07:03:03 +02:00 committed by bstoeger
parent 28520da655
commit 640ecb345b
28 changed files with 137 additions and 247 deletions

View file

@ -631,7 +631,7 @@ static void wlog_compl_parser(std::string &wl_mem, struct dive *dt_dive, int dco
tmp = (int) two_bytes_to_int(runner[pos_weight + 1], runner[pos_weight]);
if (tmp != 0x7fff) {
weightsystem_t ws = { {tmp * 10}, QT_TRANSLATE_NOOP("gettextFromC", "unknown"), false };
add_cloned_weightsystem(&dt_dive->weightsystems, ws);
dt_dive->weightsystems.push_back(std::move(ws));
}
/*

View file

@ -176,8 +176,7 @@ static void free_dive_structures(struct dive *d)
/* free tags, additional dive computers, and pictures */
taglist_free(d->tag_list);
d->cylinders.clear();
clear_weightsystem_table(&d->weightsystems);
free(d->weightsystems.weightsystems);
d->weightsystems.clear();
clear_picture_table(&d->pictures);
free(d->pictures.pictures);
}
@ -204,7 +203,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->weightsystems, 0, sizeof(d->weightsystems));
memset(&d->pictures, 0, sizeof(d->pictures));
d->full_text = NULL;
invalidate_dive_cache(d);
@ -212,7 +210,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_weights(&s->weightsystems, &d->weightsystems);
copy_pictures(&s->pictures, &d->pictures);
d->tag_list = taglist_copy(s->tag_list);
}
@ -260,7 +257,7 @@ void selective_copy_dive(const struct dive *s, struct dive *d, struct dive_compo
if (what.cylinders)
copy_cylinder_types(s, d);
if (what.weights)
copy_weights(&s->weightsystems, &d->weightsystems);
d->weightsystems = s->weightsystems;
if (what.number)
d->number = s->number;
if (what.when)
@ -289,11 +286,6 @@ void copy_events_until(const struct dive *sd, struct dive *dd, int dcNr, int tim
}
}
int nr_weightsystems(const struct dive *dive)
{
return dive->weightsystems.nr;
}
void copy_used_cylinders(const struct dive *s, struct dive *d, bool used_only)
{
if (!s || !d)
@ -1116,8 +1108,6 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer &dc)
struct dive *fixup_dive(struct dive *dive)
{
int i;
sanitize_cylinder_info(dive);
dive->maxcns = dive->cns;
@ -1146,10 +1136,8 @@ struct dive *fixup_dive(struct dive *dive)
cyl.end.mbar = 0;
}
update_cylinder_related_info(dive);
for (i = 0; i < dive->weightsystems.nr; i++) {
const weightsystem_t &ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems)
add_weightsystem_description(ws);
}
/* we should always have a uniq ID as that gets assigned during dive creation,
* but we want to make sure... */
if (!dive->id)
@ -1769,26 +1757,20 @@ static void merge_cylinders(struct dive *res, const struct dive *a, const struct
}
/* Check whether a weightsystem table contains a given weightsystem */
static bool has_weightsystem(const struct weightsystem_table *t, const weightsystem_t w)
static bool has_weightsystem(const weightsystem_table &t, const weightsystem_t &w)
{
int i;
for (i = 0; i < t->nr; i++) {
if (same_weightsystem(w, t->weightsystems[i]))
return true;
}
return false;
return any_of(t.begin(), t.end(), [&w] (auto &w2) { return same_weightsystem(w, w2); });
}
static void merge_equipment(struct dive *res, const struct dive *a, const struct dive *b)
{
int i;
for (i = 0; i < a->weightsystems.nr; i++) {
if (!has_weightsystem(&res->weightsystems, a->weightsystems.weightsystems[i]))
add_cloned_weightsystem(&res->weightsystems, a->weightsystems.weightsystems[i]);
for (auto &ws: a->weightsystems) {
if (!has_weightsystem(res->weightsystems, ws))
res->weightsystems.push_back(ws);
}
for (i = 0; i < b->weightsystems.nr; i++) {
if (!has_weightsystem(&res->weightsystems, b->weightsystems.weightsystems[i]))
add_cloned_weightsystem(&res->weightsystems, b->weightsystems.weightsystems[i]);
for (auto &ws: b->weightsystems) {
if (!has_weightsystem(res->weightsystems, ws))
res->weightsystems.push_back(ws);
}
}

View file

@ -6,7 +6,7 @@
#include "divemode.h"
#include "divecomputer.h"
#include "equipment.h" // TODO: remove
#include "equipment.h"
#include "picture.h" // TODO: remove
#include <string>
@ -30,8 +30,8 @@ struct dive {
struct dive_site *dive_site = nullptr;
char *notes = nullptr;
char *diveguide = nullptr, *buddy = nullptr;
struct cylinder_table cylinders;
struct weightsystem_table weightsystems = { };
cylinder_table cylinders;
weightsystem_table weightsystems;
char *suit = nullptr;
int number = 0;
int rating = 0;
@ -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_weightsystems(const struct dive *dive);
extern bool cylinder_with_sensor_sample(const struct dive *dive, int cylinder_id);
/* UI related protopypes */

View file

@ -64,11 +64,12 @@ void get_dive_gas(const struct dive *dive, int *o2_p, int *he_p, int *o2max_p)
int total_weight(const struct dive *dive)
{
int i, total_grams = 0;
int total_grams = 0;
if (dive)
for (i = 0; i < dive->weightsystems.nr; i++)
total_grams += dive->weightsystems.weightsystems[i].weight.grams;
if (dive) {
for (auto &ws: dive->weightsystems)
total_grams += ws.weight.grams;
}
return total_grams;
}

View file

@ -20,7 +20,6 @@
#include "pref.h"
#include "range.h"
#include "subsurface-string.h"
#include "table.h"
cylinder_t::cylinder_t() = default;
cylinder_t::~cylinder_t() = default;
@ -55,33 +54,13 @@ const cylinder_t &cylinder_table::operator[](size_t i) const
: 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.
*/
void free_weightsystem(weightsystem_t ws)
weightsystem_t::weightsystem_t() = default;
weightsystem_t::~weightsystem_t() = default;
weightsystem_t::weightsystem_t(weight_t w, std::string desc, bool auto_filled)
: weight(w), description(std::move(desc)), auto_filled(auto_filled)
{
free((void *)ws.description);
ws.description = NULL;
}
void copy_weights(const struct weightsystem_table *s, struct weightsystem_table *d)
{
clear_weightsystem_table(d);
for (int i = 0; i < s->nr; i++)
add_cloned_weightsystem(d, s->weightsystems[i]);
}
/* weightsystem table functions */
//static MAKE_GET_IDX(weightsystem_table, weightsystem_t, weightsystems)
static MAKE_GROW_TABLE(weightsystem_table, weightsystem_t, weightsystems)
//static MAKE_GET_INSERTION_INDEX(weightsystem_table, weightsystem_t, weightsystems, weightsystem_less_than)
MAKE_ADD_TO(weightsystem_table, weightsystem_t, weightsystems)
static MAKE_REMOVE_FROM(weightsystem_table, weightsystems)
//MAKE_SORT(weightsystem_table, weightsystem_t, weightsystems, comp_weightsystems)
//MAKE_REMOVE(weightsystem_table, weightsystem_t, weightsystem)
MAKE_CLEAR_TABLE(weightsystem_table, weightsystems, weightsystem)
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")
};
@ -166,7 +145,7 @@ void add_cylinder_description(const cylinder_type_t &type)
void add_weightsystem_description(const weightsystem_t &weightsystem)
{
if (empty_string(weightsystem.description))
if (weightsystem.description.empty())
return;
auto it = std::find_if(ws_info_table.begin(), ws_info_table.end(),
@ -188,26 +167,6 @@ weight_t get_weightsystem_weight(const std::string &name)
return it != ws_info_table.end() ? it->weight : weight_t();
}
weightsystem_t clone_weightsystem(weightsystem_t ws)
{
weightsystem_t res = { ws.weight, copy_string(ws.description), ws.auto_filled };
return res;
}
/* 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(struct weightsystem_table *t, weightsystem_t ws)
{
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
}
/* 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)
{
add_to_weightsystem_table(t, t->nr, clone_weightsystem(ws));
}
void add_cylinder(struct cylinder_table *t, int idx, cylinder_t cyl)
{
t->insert(t->begin() + idx, std::move(cyl));
@ -216,7 +175,7 @@ void add_cylinder(struct cylinder_table *t, int idx, cylinder_t cyl)
bool same_weightsystem(weightsystem_t w1, weightsystem_t w2)
{
return w1.weight.grams == w2.weight.grams &&
same_string(w1.description, w2.description);
w1.description == w2.description;
}
void get_gas_string(struct gasmix gasmix, char *text, int len)
@ -351,16 +310,20 @@ void remove_cylinder(struct dive *dive, int idx)
void remove_weightsystem(struct dive *dive, int idx)
{
remove_from_weightsystem_table(&dive->weightsystems, idx);
dive->weightsystems.erase(dive->weightsystems.begin() + idx);
}
void add_to_weightsystem_table(weightsystem_table *table, int idx, weightsystem_t ws)
{
idx = std::clamp(idx, 0, static_cast<int>(table->size()));
table->insert(table->begin() + idx, std::move(ws));
}
// ws is cloned.
void set_weightsystem(struct dive *dive, int idx, weightsystem_t ws)
{
if (idx < 0 || idx >= dive->weightsystems.nr)
if (idx < 0 || static_cast<size_t>(idx) >= dive->weightsystems.size())
return;
free_weightsystem(dive->weightsystems.weightsystems[idx]);
dive->weightsystems.weightsystems[idx] = clone_weightsystem(ws);
dive->weightsystems[idx] = std::move(ws);
}
/* when planning a dive we need to make sure that all cylinders have a sane depth assigned

View file

@ -54,30 +54,22 @@ struct cylinder_table : public std::vector<cylinder_t> {
struct weightsystem_t
{
weight_t weight;
const char *description; /* "integrated", "belt", "ankle" */
bool auto_filled; /* weight was automatically derived from the type */
};
std::string description; /* "integrated", "belt", "ankle" */
bool auto_filled = false; /* weight was automatically derived from the type */
static const weightsystem_t empty_weightsystem = { { 0 }, 0, false };
weightsystem_t();
weightsystem_t(weight_t w, std::string desc, bool auto_filled);
~weightsystem_t();
};
/* Table of weightsystems. Attention: this stores weightsystems,
* *not* pointers * to weightsystems. This has two crucial
* consequences:
* 1) Pointers to weightsystems are not stable. They may be
* invalidated if the table is reallocated.
* 2) add_to_weightsystem_table(), etc. takes ownership of the
* weightsystem. Notably of the description string */
struct weightsystem_table {
int nr, allocated;
weightsystem_t *weightsystems;
};
* *not* pointers * to weightsystems. Therefore pointers to
* weightsystems are *not* stable.
*/
using weightsystem_table = std::vector<weightsystem_t>;
extern enum cylinderuse cylinderuse_from_text(const char *text);
extern void copy_weights(const struct weightsystem_table *s, struct weightsystem_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 *add_empty_cylinder(struct cylinder_table *t);
extern cylinder_t *get_cylinder(struct dive *d, int idx);
extern const cylinder_t *get_cylinder(const struct dive *d, int idx);
@ -99,8 +91,7 @@ extern void dump_cylinders(struct dive *dive, bool verbose);
#endif
/* Weightsystem table functions */
extern void clear_weightsystem_table(struct weightsystem_table *);
extern void add_to_weightsystem_table(struct weightsystem_table *, int idx, weightsystem_t ws);
extern void add_to_weightsystem_table(weightsystem_table *, int idx, weightsystem_t ws);
/* Cylinder table functions */
extern void add_cylinder(struct cylinder_table *, int idx, cylinder_t cyl);

View file

@ -848,8 +848,8 @@ static bool has_locations(const filter_constraint &c, const struct dive *d)
static bool has_weight_type(const filter_constraint &c, const struct dive *d)
{
QStringList weightsystemTypes;
for (int i = 0; i < d->weightsystems.nr; ++i)
weightsystemTypes.push_back(d->weightsystems.weightsystems[i].description);
for (auto &ws: d->weightsystems)
weightsystemTypes.push_back(QString::fromStdString(ws.description));
return check(c, weightsystemTypes);
}

View file

@ -127,10 +127,8 @@ static std::vector<QString> getWords(const dive *d)
tokenize(QString::fromStdString(tag->tag->name), 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);
}
for (auto &ws: d->weightsystems)
tokenize(QString::fromStdString(ws.description), res);
// TODO: We should tokenize all dive-sites and trips first and then
// take the tokens from a cache.
if (d->dive_site) {

View file

@ -301,7 +301,7 @@ static int divinglog_dive(void *param, int, char **data, char **)
if (data[10]) {
weightsystem_t ws = { { atoi(data[10]) * 1000 }, translate("gettextFromC", "unknown"), false };
add_cloned_weightsystem(&state->cur_dive->weightsystems, ws);
state->cur_dive->weightsystems.push_back(std::move(ws));
}
if (data[11])

View file

@ -457,7 +457,7 @@ static void parse_weightsystem_keyvalue(void *_ws, const char *key, const std::s
return;
}
if (!strcmp(key, "description")) {
ws->description = strdup(value.c_str());
ws->description = value;
return;
}
report_error("Unknown weightsystem key/value pair (%s/%s)", key, value.c_str());
@ -465,7 +465,7 @@ static void parse_weightsystem_keyvalue(void *_ws, const char *key, const std::s
static void parse_dive_weightsystem(char *line, struct git_parser_state *state)
{
weightsystem_t ws = empty_weightsystem;
weightsystem_t ws;
for (;;) {
char c;
@ -476,7 +476,7 @@ static void parse_dive_weightsystem(char *line, struct git_parser_state *state)
line = parse_keyvalue_entry(parse_weightsystem_keyvalue, &ws, line, state);
}
add_to_weightsystem_table(&state->active_dive->weightsystems, state->active_dive->weightsystems.nr, ws);
state->active_dive->weightsystems.push_back(std::move(ws));
}
static int match_action(char *line, void *data,
@ -1688,7 +1688,7 @@ static int parse_dive_entry(struct git_parser_state *state, const git_tree_entry
return report_error("Unable to read dive file");
if (*suffix)
state->active_dive->number = atoi(suffix + 1);
clear_weightsystem_table(&state->active_dive->weightsystems);
state->active_dive->weightsystems.clear();
state->o2pressure_sensor = 1;
for_each_line(blob, dive_parser, state);
git_blob_free(blob);

View file

@ -1230,8 +1230,8 @@ static void gps_picture_location(const char *buffer, struct picture *pic)
static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, struct parser_state *state)
{
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;
weightsystem_t *ws = !dive->weightsystems.empty() > 0 ?
&dive->weightsystems.back() : NULL;
pressure_t p;
weight_t w;
start_match("dive", name, buf);
@ -1339,15 +1339,15 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf, str
if (MATCH_STATE("airpressure.dive", pressure, &dive->surface_pressure))
return;
if (ws) {
if (MATCH("description.weightsystem", utf8_string, (char **)&ws->description))
if (MATCH("description.weightsystem", utf8_string_std, &ws->description))
return;
if (MATCH_STATE("weight.weightsystem", weight, &ws->weight))
return;
}
if (MATCH_STATE("weight", weight, &w)) {
weightsystem_t ws = empty_weightsystem;
weightsystem_t ws;
ws.weight = w;
add_cloned_weightsystem(&dive->weightsystems, ws);
dive->weightsystems.push_back(std::move(ws));
return;
}
if (cyl) {

View file

@ -323,7 +323,7 @@ void cylinder_end(struct parser_state *state)
void ws_start(struct parser_state *state)
{
add_cloned_weightsystem(&state->cur_dive->weightsystems, empty_weightsystem);
state->cur_dive->weightsystems.emplace_back();
}
void ws_end(struct parser_state *state)

View file

@ -162,19 +162,14 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
}
}
static void save_weightsystem_info(struct membuffer *b, struct dive *dive)
static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
{
int i, nr;
nr = nr_weightsystems(dive);
for (i = 0; i < nr; i++) {
weightsystem_t ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems) {
int grams = ws.weight.grams;
const char *description = ws.description;
put_string(b, "weightsystem");
put_milli(b, " weight=", grams, "kg");
show_utf8(b, " description=", description, "");
show_utf8(b, " description=", ws.description.c_str(), "");
put_string(b, "\n");
}
}

View file

@ -96,24 +96,18 @@ static void put_HTML_bookmarks(struct membuffer *b, const struct dive *dive)
static void put_weightsystem_HTML(struct membuffer *b, const struct dive *dive)
{
int i, nr;
nr = nr_weightsystems(dive);
put_string(b, "\"Weights\":[");
const char *separator = "";
for (i = 0; i < nr; i++) {
weightsystem_t ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems) {
int grams = ws.weight.grams;
const char *description = ws.description;
put_string(b, separator);
separator = ", ";
put_string(b, "{");
put_HTML_weight_units(b, grams, "\"weight\":\"", "\",");
write_attribute(b, "description", description, " ");
write_attribute(b, "description", ws.description.c_str(), " ");
put_string(b, "}");
}
put_string(b, "],");

View file

@ -197,20 +197,14 @@ static void save_cylinder_info(struct membuffer *b, struct dive *dive)
}
}
static void save_weightsystem_info(struct membuffer *b, struct dive *dive)
static void save_weightsystem_info(struct membuffer *b, const struct dive *dive)
{
int i, nr;
nr = nr_weightsystems(dive);
for (i = 0; i < nr; i++) {
weightsystem_t ws = dive->weightsystems.weightsystems[i];
for (auto &ws: dive->weightsystems) {
int grams = ws.weight.grams;
const char *description = ws.description;
put_format(b, " <weightsystem");
put_milli(b, " weight='", grams, " kg'");
show_utf8(b, description, " description='", "'", 1);
show_utf8(b, ws.description.c_str(), " description='", "'", 1);
put_format(b, " />\n");
}
}

View file

@ -195,21 +195,19 @@ QString formatSumWeight(const dive *d)
return get_weight_string(weight_t { total_weight(d) }, true);
}
static QString getFormattedWeight(const struct dive *dive, int idx)
static QString getFormattedWeight(const weightsystem_t &weight)
{
const weightsystem_t *weight = &dive->weightsystems.weightsystems[idx];
if (!weight->description)
if (weight.description.empty())
return QString();
QString fmt = QString(weight->description);
fmt += ", " + get_weight_string(weight->weight, true);
return fmt;
return QString::fromStdString(weight.description) +
", " + get_weight_string(weight.weight, true);
}
QString formatWeightList(const dive *d)
{
QString weights;
for (int i = 0; i < d->weightsystems.nr; i++) {
QString w = getFormattedWeight(d, i);
for (auto &ws: d->weightsystems) {
QString w = getFormattedWeight(ws);
if (w.isEmpty())
continue;
weights += w + "; ";
@ -220,8 +218,8 @@ QString formatWeightList(const dive *d)
QStringList formatWeights(const dive *d)
{
QStringList weights;
for (int i = 0; i < d->weightsystems.nr; i++) {
QString w = getFormattedWeight(d, i);
for (auto &ws: d->weightsystems) {
QString w = getFormattedWeight(ws);
if (w.isEmpty())
continue;
weights << w;

View file

@ -745,9 +745,9 @@ static void parse_tag(struct dive *dive, std::string_view tag, std::string_view
} else if (tag == "altitude") {
uemis_get_index(val, dive->dcs[0].surface_pressure.mbar);
} else if (tag == "f32Weight") {
weightsystem_t ws = empty_weightsystem;
weightsystem_t ws;
uemis_get_weight(val, ws, dive->dcs[0].diveid);
add_cloned_weightsystem(&dive->weightsystems, ws);
dive->weightsystems.push_back(std::move(ws));
} else if (tag == "notes") {
uemis_add_string(val, &dive->notes, " ");
} else if (tag == "u8DiveSuit") {